Added logging for HOME_INTENT and BACK commands.

Document: go/false-longpress-overview

Change-Id: If6ba4996c861a44f4950b41acb4246e3a483d8f2
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 9a5e186..9160a01 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -1681,9 +1681,27 @@
                 // Can be cases where mWorkspace is null, this prevents a NPE
                 return;
             }
-            // In all these cases, only animate if we're already on home
+
+            // Note: There should be at most one log per method call. This is enforced implicitly
+            // by using if-else statements.
+            UserEventDispatcher ued = getUserEventDispatcher();
+
+            // TODO: Log this case.
             mWorkspace.exitWidgetResizeMode();
 
+            AbstractFloatingView topOpenView = AbstractFloatingView.getTopOpenView(this);
+            if (topOpenView instanceof DeepShortcutsContainer) {
+                ued.logActionCommand(LauncherLogProto.Action.HOME_INTENT,
+                        topOpenView.getExtendedTouchView(), LauncherLogProto.DEEPSHORTCUTS);
+            } else if (topOpenView instanceof Folder) {
+                ued.logActionCommand(LauncherLogProto.Action.HOME_INTENT,
+                            ((Folder) topOpenView).getFolderIcon(), LauncherLogProto.FOLDER);
+            } else if (alreadyOnHome) {
+                ued.logActionCommand(LauncherLogProto.Action.HOME_INTENT,
+                        mWorkspace.getState().containerType, mWorkspace.getCurrentPage());
+            }
+
+            // In all these cases, only animate if we're already on home
             AbstractFloatingView.closeAllOpenViews(this, alreadyOnHome);
             exitSpringLoadedDragMode();
 
@@ -2187,20 +2205,34 @@
             return;
         }
 
+        // Note: There should be at most one log per method call. This is enforced implicitly
+        // by using if-else statements.
+        UserEventDispatcher ued = getUserEventDispatcher();
         AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(this);
         if (topView != null) {
             if (topView.getActiveTextView() != null) {
                 topView.getActiveTextView().dispatchBackKey();
             } else {
+                if (topView instanceof DeepShortcutsContainer) {
+                    ued.logActionCommand(LauncherLogProto.Action.BACK,
+                            topView.getExtendedTouchView(), LauncherLogProto.DEEPSHORTCUTS);
+                } else if (topView instanceof Folder) {
+                    ued.logActionCommand(LauncherLogProto.Action.BACK,
+                            ((Folder) topView).getFolderIcon(), LauncherLogProto.FOLDER);
+                }
                 topView.close(true);
             }
         } else if (isAppsViewVisible()) {
+            ued.logActionCommand(LauncherLogProto.Action.BACK, LauncherLogProto.ALLAPPS);
             showWorkspace(true);
         } else if (isWidgetsViewVisible())  {
+            ued.logActionCommand(LauncherLogProto.Action.BACK, LauncherLogProto.WIDGETS);
             showOverviewMode(true);
         } else if (mWorkspace.isInOverviewMode()) {
+            ued.logActionCommand(LauncherLogProto.Action.BACK, LauncherLogProto.OVERVIEW);
             showWorkspace(true);
         } else {
+            // TODO: Log this case.
             mWorkspace.exitWidgetResizeMode();
 
             // Back button is a no-op here, but give at least some feedback for the button press
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index f6b5072..7758769 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -183,18 +183,20 @@
     // in all apps or customize mode)
 
     public enum State {
-        NORMAL          (false, false),
-        NORMAL_HIDDEN   (false, false),
-        SPRING_LOADED   (false, true),
-        OVERVIEW        (true, true),
-        OVERVIEW_HIDDEN (true, false);
+        NORMAL          (false, false, LauncherLogProto.WORKSPACE),
+        NORMAL_HIDDEN   (false, false, LauncherLogProto.ALLAPPS),
+        SPRING_LOADED   (false, true, LauncherLogProto.WORKSPACE),
+        OVERVIEW        (true, true, LauncherLogProto.OVERVIEW),
+        OVERVIEW_HIDDEN (true, false, LauncherLogProto.WIDGETS);
 
         public final boolean shouldUpdateWidget;
         public final boolean hasMultipleVisiblePages;
+        public final int containerType;
 
-        State(boolean shouldUpdateWidget, boolean hasMultipleVisiblePages) {
+        State(boolean shouldUpdateWidget, boolean hasMultipleVisiblePages, int containerType) {
             this.shouldUpdateWidget = shouldUpdateWidget;
             this.hasMultipleVisiblePages = hasMultipleVisiblePages;
+            this.containerType = containerType;
         }
     }
 
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index 53c12b5..e813bb4 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -79,7 +79,6 @@
 import com.android.launcher3.dragndrop.DragLayer;
 import com.android.launcher3.dragndrop.DragOptions;
 import com.android.launcher3.pageindicators.PageIndicatorDots;
-import com.android.launcher3.shortcuts.DeepShortcutsContainer;
 import com.android.launcher3.userevent.nano.LauncherLogProto;
 import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
 import com.android.launcher3.util.CircleRevealOutlineProvider;
@@ -388,6 +387,10 @@
         return isEditingName() ? mFolderName : null;
     }
 
+    public FolderIcon getFolderIcon() {
+        return mFolderIcon;
+    }
+
     /**
      * We need to handle touch events to prevent them from falling through to the workspace below.
      */
diff --git a/src/com/android/launcher3/logging/LoggerUtils.java b/src/com/android/launcher3/logging/LoggerUtils.java
index c2b97eb..395daa5 100644
--- a/src/com/android/launcher3/logging/LoggerUtils.java
+++ b/src/com/android/launcher3/logging/LoggerUtils.java
@@ -20,8 +20,16 @@
 public class LoggerUtils {
     private static final String TAG = "LoggerUtils";
 
-    public static String getActionStr(LauncherLogProto.Action action) {
-        switch(action.touch) {
+    private static String getCommandStr(Action action) {
+        switch (action.command) {
+            case Action.HOME_INTENT: return "HOME_INTENT";
+            case Action.BACK: return "BACK";
+            default: return "UNKNOWN";
+        }
+    }
+
+    private static String getTouchStr(Action action) {
+        switch (action.touch) {
             case Action.TAP: return "TAP";
             case Action.LONGPRESS: return "LONGPRESS";
             case Action.DRAGDROP: return "DRAGDROP";
@@ -32,6 +40,14 @@
         }
     }
 
+    public static String getActionStr(LauncherLogProto.Action action) {
+        switch (action.type) {
+            case Action.TOUCH: return getTouchStr(action);
+            case Action.COMMAND: return getCommandStr(action);
+            default: return "UNKNOWN";
+        }
+    }
+
     public static String getTargetStr(Target t) {
         String typeStr = "";
         if (t == null){
@@ -61,6 +77,7 @@
             case LauncherLogProto.DEEPSHORTCUT: typeStr = "DEEPSHORTCUT"; break;
             case LauncherLogProto.FOLDER_ICON: typeStr = "FOLDERICON"; break;
             case LauncherLogProto.SEARCHBOX: typeStr = "SEARCHBOX"; break;
+            case LauncherLogProto.EDITTEXT: typeStr = "EDITTEXT"; break;
 
             default: typeStr = "UNKNOWN";
         }
@@ -173,23 +190,41 @@
     }
 
     /**
+     * Used for commands.
+     */
+    public static LauncherLogProto.LauncherEvent initLauncherEvent(int command,
+            boolean createSrcTarget) {
+        LauncherLogProto.LauncherEvent event = new LauncherLogProto.LauncherEvent();
+        event.action = new LauncherLogProto.Action();
+        event.action.type = Action.COMMAND;
+        event.action.command = command;
+        event.srcTarget = null;
+
+        if (createSrcTarget) {
+            event.srcTarget = new LauncherLogProto.Target[1];
+            event.srcTarget[0] = new LauncherLogProto.Target();
+            event.srcTarget[0].type = Target.CONTAINER;
+        }
+        return event;
+    }
+
+    /**
      * 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[0] = initTarget(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[0] = initTarget(info);
         event.destTarget[1] = initDropTarget(parentDestTargetType);
 
         event.action = new LauncherLogProto.Action();
@@ -197,7 +232,7 @@
         return event;
     }
 
-    private static Target initTarget(View v, ItemInfo info) {
+    private static Target initTarget(ItemInfo info) {
         Target t = new LauncherLogProto.Target();
         t.type = Target.ITEM;
         switch (info.itemType) {
@@ -243,6 +278,6 @@
         if (!(v.getTag() instanceof ItemInfo)) {
             return t;
         }
-        return initTarget(v, (ItemInfo) v.getTag());
+        return initTarget((ItemInfo) v.getTag());
     }
 }
diff --git a/src/com/android/launcher3/logging/UserEventDispatcher.java b/src/com/android/launcher3/logging/UserEventDispatcher.java
index abe8f42..2fcdd39 100644
--- a/src/com/android/launcher3/logging/UserEventDispatcher.java
+++ b/src/com/android/launcher3/logging/UserEventDispatcher.java
@@ -117,29 +117,35 @@
                 Action.TOUCH, v, Target.CONTAINER);
         event.action.touch = Action.TAP;
 
-        // Fill in grid(x,y), pageIndex of the child and container type of the parent
-        // TODO: make this percolate up the view hierarchy if needed.
+        // TODO: make idx percolate up the view hierarchy if needed.
         int idx = 0;
-        LogContainerProvider provider = getLaunchProviderRecursive(v);
-        if (v == null || !(v.getTag() instanceof ItemInfo) || provider == null) {
-            return null;
-        }
-        ItemInfo itemInfo = (ItemInfo) v.getTag();
-        provider.fillInLogContainerData(v, itemInfo, event.srcTarget[idx], event.srcTarget[idx + 1]);
-
-        event.srcTarget[idx].intentHash = intent.hashCode();
-        ComponentName cn = intent.getComponent();
-        if (cn != null) {
-            event.srcTarget[idx].packageNameHash = cn.getPackageName().hashCode();
-            event.srcTarget[idx].componentHash = cn.hashCode();
-            if (mPredictedApps != null) {
-                event.srcTarget[idx].predictedRank = mPredictedApps.indexOf(
-                        new ComponentKey(cn, itemInfo.user));
+        if (fillInLogContainerData(event, v)) {
+            ItemInfo itemInfo = (ItemInfo) v.getTag();
+            event.srcTarget[idx].intentHash = intent.hashCode();
+            ComponentName cn = intent.getComponent();
+            if (cn != null) {
+                event.srcTarget[idx].packageNameHash = cn.getPackageName().hashCode();
+                event.srcTarget[idx].componentHash = cn.hashCode();
+                if (mPredictedApps != null) {
+                    event.srcTarget[idx].predictedRank = mPredictedApps.indexOf(
+                            new ComponentKey(cn, itemInfo.user));
+                }
             }
         }
         return event;
     }
 
+    public boolean fillInLogContainerData(LauncherEvent event, View v) {
+        // Fill in grid(x,y), pageIndex of the child and container type of the parent
+        LogContainerProvider provider = getLaunchProviderRecursive(v);
+        if (v == null || !(v.getTag() instanceof ItemInfo) || provider == null) {
+            return false;
+        }
+        ItemInfo itemInfo = (ItemInfo) v.getTag();
+        provider.fillInLogContainerData(v, itemInfo, event.srcTarget[0], event.srcTarget[1]);
+        return true;
+    }
+
     public void logAppLaunch(View v, Intent intent) {
         LauncherEvent ev = createLauncherEvent(v, intent);
         if (ev == null) {
@@ -148,10 +154,30 @@
         dispatchUserEvent(ev, intent);
     }
 
-    public void logActionOnItem(int action, int itemType) {
-        LauncherEvent event = LoggerUtils.initLauncherEvent(Action.TOUCH, Target.ITEM);
-        event.action.touch = action;
-        event.srcTarget[0].itemType = itemType;
+    public void logActionCommand(int command, int containerType) {
+        logActionCommand(command, containerType, 0);
+    }
+
+    public void logActionCommand(int command, int containerType, int pageIndex) {
+        LauncherEvent event = LoggerUtils.initLauncherEvent(command, true);
+        event.srcTarget[0].containerType = containerType;
+        event.srcTarget[0].pageIndex = pageIndex;
+        dispatchUserEvent(event, null);
+    }
+
+    /**
+     * TODO: Make this function work when a container view is passed as the 2nd param.
+     */
+    public void logActionCommand(int command, View itemView, int containerType) {
+        LauncherEvent event = LoggerUtils.initLauncherEvent(Action.COMMAND, itemView,
+                Target.CONTAINER);
+        event.action.command = command;
+        if (fillInLogContainerData(event, itemView)) {
+            // TODO: Remove the following two lines once fillInLogContainerData can take in a
+            // container view.
+            event.srcTarget[0].type = Target.CONTAINER;
+            event.srcTarget[0].containerType = containerType;
+        }
         dispatchUserEvent(event, null);
     }
 
@@ -215,7 +241,6 @@
     }
     public void logDragNDrop(DropTarget.DragObject dragObj, View dropTargetAsView) {
         LauncherEvent event = LoggerUtils.initLauncherEvent(Action.TOUCH,
-                dragObj.dragView,
                 dragObj.originalDragInfo,
                 Target.CONTAINER,
                 dropTargetAsView);