OSDN Git Service

Support user event logging for drag and drop
authorHyunyoung Song <hyunyoungs@google.com>
Thu, 1 Sep 2016 19:47:12 +0000 (12:47 -0700)
committerHyunyoung Song <hyunyoungs@google.com>
Sun, 4 Sep 2016 19:48:24 +0000 (19:48 +0000)
b/30039490

Supported in this CL:
- DnD: drag from container [WORKSPACE|HOTSEAT|FOLDER|ALLAPPS|WIDGETS|DEEPSHORTCUTS]
       drag to container [HOTSEAT,WORKSPACE,FOLDER,DROPTARGETS]
- Source and target can be [FOLDER_ICON, ICON, DEEPSHORTCUT, WIDGET]
- $ adb shell setprop log.tag.UserEvent DEBUG will turn on debugging

Change-Id: I0b8b879b80e6dce85bbde6e7794f9e0677832603
(cherry picked from commit 59a238095e82fd02355f4cb53abe01655a50b051)

src/com/android/launcher3/DragSource.java
src/com/android/launcher3/DropTarget.java
src/com/android/launcher3/Workspace.java
src/com/android/launcher3/allapps/AllAppsContainerView.java
src/com/android/launcher3/allapps/AllAppsRecyclerView.java
src/com/android/launcher3/dragndrop/DragController.java
src/com/android/launcher3/folder/Folder.java
src/com/android/launcher3/logging/LoggerUtils.java
src/com/android/launcher3/logging/UserEventDispatcher.java
src/com/android/launcher3/shortcuts/DeepShortcutsContainer.java
src/com/android/launcher3/widget/WidgetsContainerView.java

index da32d82..efbb9d7 100644 (file)
@@ -19,11 +19,12 @@ package com.android.launcher3;
 import android.view.View;
 
 import com.android.launcher3.DropTarget.DragObject;
+import com.android.launcher3.logging.UserEventDispatcher.LaunchSourceProvider;
 
 /**
  * Interface defining an object that can originate a drag.
  */
-public interface DragSource {
+public interface DragSource extends LaunchSourceProvider {
 
     /**
      * @return whether items dragged from this source supports
index 90b8f1c..efdeb1f 100644 (file)
@@ -48,9 +48,12 @@ public interface DropTarget {
         /** The view that moves around while you drag.  */
         public DragView dragView = null;
 
-        /** The data associated with the object being dragged */
+        /** The data associated with the object, after item is dropped. */
         public ItemInfo dragInfo = null;
 
+        /** The data associated with the object  being dragged */
+        public ItemInfo originalDragInfo = null;
+
         /** Where the drag originated */
         public DragSource dragSource = null;
 
index 6f61688..75692a6 100644 (file)
@@ -100,7 +100,7 @@ import java.util.HashSet;
 public class Workspace extends PagedView
         implements DropTarget, DragSource, DragScroller, View.OnTouchListener,
         DragController.DragListener, LauncherTransitionable, ViewGroup.OnHierarchyChangeListener,
-        Insettable, DropTargetSource, AccessibilityDragSource, UserEventDispatcher.LaunchSourceProvider {
+        Insettable, DropTargetSource, AccessibilityDragSource {
     private static final String TAG = "Launcher.Workspace";
 
     private static boolean ENFORCE_DRAG_EVENT_ORDER = false;
@@ -3453,6 +3453,7 @@ public class Workspace extends PagedView
                 if (info.container == NO_ID && info instanceof AppInfo) {
                     // Came from all apps -- make a copy
                     info = ((AppInfo) info).makeShortcut();
+                    d.dragInfo = info;
                 }
                 view = mLauncher.createShortcut(cellLayout, (ShortcutInfo) info);
                 break;
@@ -4322,6 +4323,12 @@ public class Workspace extends PagedView
         target.gridY = info.cellY;
         target.pageIndex = getCurrentPage();
         targetParent.containerType = LauncherLogProto.WORKSPACE;
+        if (info.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
+            target.rank = info.rank;
+            targetParent.containerType = LauncherLogProto.HOTSEAT;
+        } else if (info.container >= 0) {
+            targetParent.containerType = LauncherLogProto.FOLDER;
+        }
     }
 
     /**
index c7bc23b..a8e2140 100644 (file)
@@ -51,6 +51,8 @@ import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.folder.Folder;
 import com.android.launcher3.graphics.TintedDrawableSpan;
 import com.android.launcher3.keyboard.FocusedItemDecorator;
+import com.android.launcher3.userevent.nano.LauncherLogProto;
+import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
 import com.android.launcher3.util.ComponentKey;
 
 import java.nio.charset.Charset;
@@ -700,4 +702,9 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
         mSearchQueryBuilder.clearSpans();
         Selection.setSelection(mSearchQueryBuilder, 0);
     }
+
+    @Override
+    public void fillInLaunchSourceData(View v, ItemInfo info, Target target, Target targetParent) {
+        targetParent.containerType = mAppsRecyclerView.getContainerType(v);
+    }
 }
index 25ed3b8..0173847 100644 (file)
@@ -27,20 +27,16 @@ import android.view.View;
 import com.android.launcher3.BaseRecyclerView;
 import com.android.launcher3.BubbleTextView;
 import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.ItemInfo;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.R;
-import com.android.launcher3.logging.UserEventDispatcher.LaunchSourceProvider;
 import com.android.launcher3.userevent.nano.LauncherLogProto;
-import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
 
 import java.util.List;
 
 /**
  * A RecyclerView with custom fast scroll support for the all apps view.
  */
-public class AllAppsRecyclerView extends BaseRecyclerView
-        implements LaunchSourceProvider {
+public class AllAppsRecyclerView extends BaseRecyclerView {
 
     private AlphabeticalAppsList mApps;
     private AllAppsFastScrollHelper mFastScrollHelper;
@@ -207,10 +203,9 @@ public class AllAppsRecyclerView extends BaseRecyclerView
         updateEmptySearchBackgroundBounds();
     }
 
-    @Override
-    public void fillInLaunchSourceData(View v, ItemInfo info, Target target, Target targetParent) {
+    public int getContainerType(View v) {
         if (mApps.hasFilter()) {
-            targetParent.containerType = LauncherLogProto.SEARCHRESULT;
+            return LauncherLogProto.SEARCHRESULT;
         } else {
             if (v instanceof BubbleTextView) {
                 BubbleTextView icon = (BubbleTextView) v;
@@ -219,12 +214,11 @@ public class AllAppsRecyclerView extends BaseRecyclerView
                     List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems();
                     AlphabeticalAppsList.AdapterItem item = items.get(position);
                     if (item.viewType == AllAppsGridAdapter.VIEW_TYPE_PREDICTION_ICON) {
-                        targetParent.containerType = LauncherLogProto.PREDICTION;
-                        return;
+                        return LauncherLogProto.PREDICTION;
                     }
                 }
             }
-            targetParent.containerType = LauncherLogProto.ALLAPPS;
+            return LauncherLogProto.ALLAPPS;
         }
     }
 
index 9da1cb3..b57f5bf 100644 (file)
@@ -43,7 +43,6 @@ import com.android.launcher3.PagedView;
 import com.android.launcher3.R;
 import com.android.launcher3.ShortcutInfo;
 import com.android.launcher3.Utilities;
-import com.android.launcher3.Workspace;
 import com.android.launcher3.accessibility.DragViewStateAnnouncer;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.util.ItemInfoMatcher;
@@ -51,7 +50,6 @@ import com.android.launcher3.util.Thunk;
 import com.android.launcher3.util.TouchController;
 
 import java.util.ArrayList;
-import java.util.HashSet;
 
 /**
  * Class for initiating a drag within a view or across multiple views.
@@ -271,6 +269,8 @@ public class DragController implements DragDriver.EventListener, TouchController
 
         mDragObject.dragSource = source;
         mDragObject.dragInfo = dragInfo;
+        mDragObject.originalDragInfo = new ItemInfo();
+        mDragObject.originalDragInfo.copyFrom(dragInfo);
 
         if (dragOffset != null) {
             dragView.setDragVisualizeOffset(new Point(dragOffset));
@@ -285,6 +285,7 @@ public class DragController implements DragDriver.EventListener, TouchController
         mLastTouch[0] = mMotionDownX;
         mLastTouch[1] = mMotionDownY;
         handleMoveEvent(mMotionDownX, mMotionDownY);
+        mLauncher.getUserEventDispatcher().resetActionDurationMillis();
         return dragView;
     }
 
@@ -507,7 +508,7 @@ public class DragController implements DragDriver.EventListener, TouchController
      */
     public void setMoveTarget(View view) {
         mMoveTarget = view;
-    }    
+    }
 
     public boolean dispatchUnhandledMove(View focused, int direction) {
         return mMoveTarget != null && mMoveTarget.dispatchUnhandledMove(focused, direction);
@@ -734,6 +735,7 @@ public class DragController implements DragDriver.EventListener, TouchController
         final View dropTargetAsView = dropTarget instanceof View ? (View) dropTarget : null;
         mDragObject.dragSource.onDropCompleted(
                 dropTargetAsView, mDragObject, flingVel != null, accepted);
+        mLauncher.getUserEventDispatcher().logDragNDrop(mDragObject, dropTargetAsView);
     }
 
     private DropTarget findDropTarget(int x, int y, int[] dropCoordinates) {
index 96da181..5450423 100644 (file)
@@ -92,8 +92,7 @@ import java.util.Comparator;
  */
 public class Folder extends LinearLayout implements DragSource, View.OnClickListener,
         View.OnLongClickListener, DropTarget, FolderListener, TextView.OnEditorActionListener,
-        View.OnFocusChangeListener, DragListener, DropTargetSource, AccessibilityDragSource,
-        LaunchSourceProvider {
+        View.OnFocusChangeListener, DragListener, DropTargetSource, AccessibilityDragSource {
     private static final String TAG = "Launcher.Folder";
 
     /**
index dc04597..845dbc2 100644 (file)
@@ -2,8 +2,12 @@ package com.android.launcher3.logging;
 
 import android.view.View;
 
+import com.android.launcher3.ButtonDropTarget;
+import com.android.launcher3.DeleteDropTarget;
+import com.android.launcher3.InfoDropTarget;
 import com.android.launcher3.ItemInfo;
 import com.android.launcher3.LauncherSettings;
+import com.android.launcher3.UninstallDropTarget;
 import com.android.launcher3.userevent.nano.LauncherLogProto;
 import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
 import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
@@ -164,14 +168,35 @@ public class LoggerUtils {
         return event;
     }
 
-    private static Target initTarget(View v) {
+    /**
+     * Used for drag and drop interaction.
+     */
+    public static LauncherLogProto.LauncherEvent initLauncherEvent(
+            int actionType,
+            View v,
+            ItemInfo info,
+            int parentSrcTargetType,
+            View parentDestTargetType){
+        LauncherLogProto.LauncherEvent event = new LauncherLogProto.LauncherEvent();
+
+        event.srcTarget = new LauncherLogProto.Target[2];
+        event.srcTarget[0] = initTarget(v, info);
+        event.srcTarget[1] = new LauncherLogProto.Target();
+        event.srcTarget[1].type = parentSrcTargetType;
+
+        event.destTarget = new LauncherLogProto.Target[2];
+        event.destTarget[0] = initTarget(v, info);
+        event.destTarget[1] = initDropTarget(parentDestTargetType);
+
+        event.action = new LauncherLogProto.Action();
+        event.action.type = actionType;
+        return event;
+    }
+
+    private static Target initTarget(View v, ItemInfo info) {
         Target t = new LauncherLogProto.Target();
         t.type = Target.ITEM;
-        if (!(v.getTag() instanceof ItemInfo)) {
-            return t;
-        }
-        ItemInfo itemInfo = (ItemInfo) v.getTag();
-        switch (itemInfo.itemType) {
+        switch (info.itemType) {
             case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
                 t.itemType = LauncherLogProto.APP_ICON;
                 break;
@@ -190,4 +215,30 @@ public class LoggerUtils {
         }
         return t;
     }
+
+    private static Target initDropTarget(View v) {
+        Target t = new LauncherLogProto.Target();
+        t.type = (v instanceof ButtonDropTarget)? Target.CONTROL : Target.CONTAINER;
+        if (t.type == Target.CONTAINER) {
+            return t;
+        }
+
+        if (v instanceof InfoDropTarget) {
+            t.controlType = LauncherLogProto.APPINFO_TARGET;
+        } else if (v instanceof UninstallDropTarget) {
+            t.controlType = LauncherLogProto.UNINSTALL_TARGET;
+        } else if (v instanceof DeleteDropTarget) {
+            t.controlType = LauncherLogProto.REMOVE_TARGET;
+        }
+        return t;
+    }
+
+    private static Target initTarget(View v) {
+        Target t = new LauncherLogProto.Target();
+        t.type = Target.ITEM;
+        if (!(v.getTag() instanceof ItemInfo)) {
+            return t;
+        }
+        return initTarget(v, (ItemInfo) v.getTag());
+    }
 }
index e4cc182..0356a9c 100644 (file)
@@ -18,12 +18,15 @@ package com.android.launcher3.logging;
 
 import android.content.ComponentName;
 import android.content.Intent;
+import android.os.SystemClock;
 import android.util.Log;
 import android.view.View;
 import android.view.ViewParent;
 
+import com.android.launcher3.DropTarget;
 import com.android.launcher3.ItemInfo;
-import com.android.launcher3.userevent.nano.LauncherLogProto;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.config.ProviderConfig;
 import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
 import com.android.launcher3.userevent.nano.LauncherLogProto.LauncherEvent;
 import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
@@ -37,10 +40,15 @@ import java.util.Locale;
  */
 public class UserEventDispatcher {
 
-    private static final boolean DEBUG_LOGGING = false;
     private final static int MAXIMUM_VIEW_HIERARCHY_LEVEL = 5;
 
+    private final boolean mIsVerbose;
+
     /**
+     * TODO: change the name of this interface to LogContainerProvider
+     * and the method name to fillInLogContainerData. Not changed to minimize CL diff
+     * in this branch.
+     *
      * Implemented by containers to provide a launch source for a given child.
      */
     public interface LaunchSourceProvider {
@@ -61,6 +69,7 @@ public class UserEventDispatcher {
      */
     public static LaunchSourceProvider getLaunchProviderRecursive(View v) {
         ViewParent parent = null;
+
         if (v != null) {
             parent = v.getParent();
         } else {
@@ -88,6 +97,14 @@ public class UserEventDispatcher {
     // Used for filling in predictedRank on {@link Target}s.
     private List<ComponentKey> mPredictedApps;
 
+    public UserEventDispatcher() {
+        if (ProviderConfig.IS_DOGFOOD_BUILD) {
+            mIsVerbose = Utilities.isPropertyEnabled(TAG);
+        } else {
+            mIsVerbose = false;
+        }
+    }
+
     //                      APP_ICON    SHORTCUT    WIDGET
     // --------------------------------------------------------------
     // packageNameHash      required    optional    required
@@ -104,7 +121,7 @@ public class UserEventDispatcher {
         // TODO: make this percolate up the view hierarchy if needed.
         int idx = 0;
         LaunchSourceProvider provider = getLaunchProviderRecursive(v);
-        if (!(v.getTag() instanceof ItemInfo)) {
+        if (v == null || !(v.getTag() instanceof ItemInfo) || provider == null) {
             return null;
         }
         ItemInfo itemInfo = (ItemInfo) v.getTag();
@@ -122,8 +139,8 @@ public class UserEventDispatcher {
         }
 
         // Fill in the duration of time spent navigating in Launcher and the container.
-        event.elapsedContainerMillis = System.currentTimeMillis() - mElapsedContainerMillis;
-        event.elapsedSessionMillis = System.currentTimeMillis() - mElapsedSessionMillis;
+        event.elapsedContainerMillis = SystemClock.uptimeMillis() - mElapsedContainerMillis;
+        event.elapsedSessionMillis = SystemClock.uptimeMillis() - mElapsedSessionMillis;
         return event;
     }
 
@@ -139,8 +156,8 @@ public class UserEventDispatcher {
         LauncherEvent event = LoggerUtils.initLauncherEvent(Action.TOUCH, Target.CONTROL);
         event.action.touch = action;
         event.srcTarget[0].controlType = controlType;
-        event.elapsedContainerMillis = System.currentTimeMillis() - mElapsedContainerMillis;
-        event.elapsedSessionMillis = System.currentTimeMillis() - mElapsedSessionMillis;
+        event.elapsedContainerMillis = SystemClock.uptimeMillis() - mElapsedContainerMillis;
+        event.elapsedSessionMillis = SystemClock.uptimeMillis() - mElapsedSessionMillis;
         dispatchUserEvent(event, null);
     }
 
@@ -149,8 +166,8 @@ public class UserEventDispatcher {
         event.action.touch = action;
         event.action.dir = dir;
         event.srcTarget[0].containerType = containerType;
-        event.elapsedContainerMillis = System.currentTimeMillis() - mElapsedContainerMillis;
-        event.elapsedSessionMillis = System.currentTimeMillis() - mElapsedSessionMillis;
+        event.elapsedContainerMillis = SystemClock.uptimeMillis() - mElapsedContainerMillis;
+        event.elapsedSessionMillis = SystemClock.uptimeMillis() - mElapsedSessionMillis;
         dispatchUserEvent(event, null);
     }
 
@@ -158,14 +175,14 @@ public class UserEventDispatcher {
         LauncherEvent event = LoggerUtils.initLauncherEvent(
                 Action.TOUCH, icon, Target.CONTAINER);
         LaunchSourceProvider provider = getLaunchProviderRecursive(icon);
-        if (!(icon.getTag() instanceof ItemInfo)) {
+        if (icon == null && !(icon.getTag() instanceof ItemInfo)) {
             return;
         }
         ItemInfo info = (ItemInfo) icon.getTag();
         provider.fillInLaunchSourceData(icon, info, event.srcTarget[0], event.srcTarget[1]);
         event.action.touch = Action.LONGPRESS;
-        event.elapsedContainerMillis = System.currentTimeMillis() - mElapsedContainerMillis;
-        event.elapsedSessionMillis = System.currentTimeMillis() - mElapsedSessionMillis;
+        event.elapsedContainerMillis = SystemClock.uptimeMillis() - mElapsedContainerMillis;
+        event.elapsedSessionMillis = SystemClock.uptimeMillis() - mElapsedSessionMillis;
         dispatchUserEvent(event, null);
     }
 
@@ -173,39 +190,66 @@ public class UserEventDispatcher {
         mPredictedApps = predictedApps;
     }
 
+    public void logDragNDrop(DropTarget.DragObject dragObj, View dropTargetAsView) {
+        LauncherEvent event = LoggerUtils.initLauncherEvent(Action.TOUCH,
+                dragObj.dragView,
+                dragObj.originalDragInfo,
+                Target.CONTAINER,
+                dropTargetAsView);
+        event.action.touch = Action.DRAGDROP;
+
+        dragObj.dragSource.fillInLaunchSourceData(null, dragObj.originalDragInfo,
+                event.srcTarget[0], event.srcTarget[1]);
+
+        if (dropTargetAsView instanceof LaunchSourceProvider) {
+            ((LaunchSourceProvider) dropTargetAsView).fillInLaunchSourceData(null,
+                    dragObj.dragInfo, event.destTarget[0], event.destTarget[1]);
+
+        }
+
+        event.elapsedContainerMillis = SystemClock.uptimeMillis() - mElapsedContainerMillis;
+        event.elapsedSessionMillis = SystemClock.uptimeMillis() - mElapsedSessionMillis;
+        event.actionDurationMillis = SystemClock.uptimeMillis() - mActionDurationMillis;
+        dispatchUserEvent(event, null);
+    }
+
     /**
      * Currently logs following containers: workspace, allapps, widget tray.
      */
     public final void resetElapsedContainerMillis() {
-        mElapsedContainerMillis = System.currentTimeMillis();
+        mElapsedContainerMillis = SystemClock.uptimeMillis();
     }
 
     public final void resetElapsedSessionMillis() {
-        mElapsedSessionMillis = System.currentTimeMillis();
-        mElapsedContainerMillis = System.currentTimeMillis();
+        mElapsedSessionMillis = SystemClock.uptimeMillis();
+        mElapsedContainerMillis = SystemClock.uptimeMillis();
     }
 
     public final void resetActionDurationMillis() {
-        mActionDurationMillis = System.currentTimeMillis();
+        mActionDurationMillis = SystemClock.uptimeMillis();
     }
 
     public void dispatchUserEvent(LauncherEvent ev, Intent intent) {
-        if (DEBUG_LOGGING) {
-            Log.d(TAG, String.format(Locale.US,
-                    "\naction:%s\n Source child:%s\tparent:%s",
-                    LoggerUtils.getActionStr(ev.action),
-                    LoggerUtils.getTargetStr(ev.srcTarget != null ? ev.srcTarget[0] : null),
-                    LoggerUtils.getTargetStr(ev.srcTarget.length > 1 ? ev.srcTarget[1] : null)));
-            if (ev.destTarget != null && ev.destTarget.length > 0) {
-                Log.d(TAG, String.format(Locale.US,
-                        " Destination child:%s\tparent:%s",
-                        LoggerUtils.getTargetStr(ev.destTarget != null ? ev.destTarget[0] : null),
-                        LoggerUtils.getTargetStr(ev.destTarget.length > 1 ? ev.destTarget[1] : null)));
-            }
+        if (!mIsVerbose) {
+            return;
+        }
+        Log.d(TAG, String.format(Locale.US,
+                "\naction:%s\n Source child:%s\tparent:%s",
+                LoggerUtils.getActionStr(ev.action),
+                LoggerUtils.getTargetStr(ev.srcTarget != null ? ev.srcTarget[0] : null),
+                LoggerUtils.getTargetStr(ev.srcTarget != null && ev.srcTarget.length > 1 ?
+                        ev.srcTarget[1] : null)));
+        if (ev.destTarget != null && ev.destTarget.length > 0) {
             Log.d(TAG, String.format(Locale.US,
-                    " Elapsed container %d ms session %d ms",
-                    ev.elapsedContainerMillis,
-                    ev.elapsedSessionMillis));
+                    " Destination child:%s\tparent:%s",
+                    LoggerUtils.getTargetStr(ev.destTarget != null ? ev.destTarget[0] : null),
+                    LoggerUtils.getTargetStr(ev.destTarget != null && ev.destTarget.length > 1 ?
+                            ev.destTarget[1] : null)));
         }
+        Log.d(TAG, String.format(Locale.US,
+                " Elapsed container %d ms session %d ms action %d ms",
+                ev.elapsedContainerMillis,
+                ev.elapsedSessionMillis,
+                ev.actionDurationMillis));
     }
 }
index cfeccfc..6bd21cd 100644 (file)
@@ -76,8 +76,7 @@ import java.util.List;
  */
 @TargetApi(Build.VERSION_CODES.N)
 public class DeepShortcutsContainer extends LinearLayout implements View.OnLongClickListener,
-        View.OnTouchListener, DragSource, DragController.DragListener,
-        UserEventDispatcher.LaunchSourceProvider {
+        View.OnTouchListener, DragSource, DragController.DragListener {
     private static final String TAG = "ShortcutsContainer";
 
     private final Point mIconShift = new Point();
index 34bee1b..538d4c9 100644 (file)
@@ -45,6 +45,8 @@ import com.android.launcher3.WidgetPreviewLoader;
 import com.android.launcher3.Workspace;
 import com.android.launcher3.dragndrop.DragController;
 import com.android.launcher3.model.WidgetsModel;
+import com.android.launcher3.userevent.nano.LauncherLogProto;
+import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
 import com.android.launcher3.util.Thunk;
 
 /**
@@ -354,4 +356,9 @@ public class WidgetsContainerView extends BaseContainerView
         }
         return mWidgetPreviewLoader;
     }
+
+    @Override
+    public void fillInLaunchSourceData(View v, ItemInfo info, Target target, Target targetParent) {
+        targetParent.containerType = LauncherLogProto.WIDGETS;
+    }
 }
\ No newline at end of file