Log time spent on different UI surfaces

- When swipe happens on worskpace, elapsed container ms is reset
- Fling DOWN is also logged so that we now know how much time was spent on
  all apps screen
- If screen off or power button trigger onPause, log this event.

Bug: 67745115
Change-Id: Ie3a0090c78195a4a028de9935131e9e034dcf48a
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 4efb911..eda5bb1 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -292,6 +292,8 @@
     public ViewGroupFocusHelper mFocusHandler;
     private boolean mRotationEnabled = false;
 
+    private boolean mAppLaunchSuccess;
+
     @Thunk void setOrientation() {
         if (mRotationEnabled) {
             unlockScreenOrientation(true);
@@ -781,6 +783,10 @@
             mAppWidgetHost.stopListening();
         }
 
+        if (!mAppLaunchSuccess) {
+            getUserEventDispatcher().logActionCommand(Action.Command.STOP,
+                    mWorkspace.getState().containerType);
+        }
         NotificationListener.removeNotificationsChangedListener();
     }
 
@@ -827,6 +833,7 @@
         super.onResume();
         TraceHelper.partitionSection("ON_RESUME", "superCall");
 
+        mAppLaunchSuccess = false;
         getUserEventDispatcher().resetElapsedSessionMillis();
         mPaused = false;
         if (mOnResumeNeedsLoad) {
@@ -2115,7 +2122,6 @@
             throw new IllegalArgumentException("Input must have a valid intent");
         }
         startActivitySafely(v, intent, item);
-        getUserEventDispatcher().logAppLaunch(v, intent); // TODO for discovered apps b/35802115
     }
 
     /**
@@ -2276,9 +2282,10 @@
     }
 
     public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
+        mAppLaunchSuccess = false;
         if (mIsSafeModeEnabled && !Utilities.isSystemApp(this, intent)) {
             Toast.makeText(this, R.string.safemode_shortcut_error, Toast.LENGTH_SHORT).show();
-            return false;
+            return mAppLaunchSuccess;
         }
         // Only launch using the new animation if the shortcut has not opted out (this is a
         // private contract between launcher and may be ignored in the future).
@@ -2318,12 +2325,13 @@
                 btv.setStayPressed(true);
                 setOnResumeCallback(btv);
             }
-            return true;
+            mAppLaunchSuccess = true;
+            getUserEventDispatcher().logAppLaunch(v, intent); // TODO for discovered apps b/35802115
         } catch (ActivityNotFoundException|SecurityException e) {
             Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
             Log.e(TAG, "Unable to launch. tag=" + item + " intent=" + intent, e);
         }
-        return false;
+        return mAppLaunchSuccess;
     }
 
     @Override
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index 2243a9c..9247c54 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -26,7 +26,8 @@
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.graphics.GradientView;
 import com.android.launcher3.touch.SwipeDetector;
-import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
+import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
+import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
 import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
 import com.android.launcher3.util.SystemUiController;
 import com.android.launcher3.util.Themes;
@@ -207,16 +208,11 @@
 
         final int containerType = mTouchEventStartedOnHotseat
                 ? ContainerType.HOTSEAT : ContainerType.WORKSPACE;
-
         if (fling) {
             if (velocity < 0) {
                 calculateDuration(velocity, mAppsView.getTranslationY());
-
                 if (!mLauncher.isInState(LauncherState.ALL_APPS)) {
-                    mLauncher.getUserEventDispatcher().logActionOnContainer(
-                            Action.Touch.FLING,
-                            Action.Direction.UP,
-                            containerType);
+                    logSwipeOnContainer(Touch.FLING, Direction.UP, containerType);
                 }
                 mLauncher.showAppsView(true /* animated */);
                 if (hasSpringAnimationHandler()) {
@@ -226,26 +222,43 @@
                 }
             } else {
                 calculateDuration(velocity, Math.abs(mShiftRange - mAppsView.getTranslationY()));
-                mLauncher.showWorkspace(true);
+                if (mLauncher.isInState(LauncherState.ALL_APPS)) {
+                    logSwipeOnContainer(Touch.FLING, Direction.DOWN, ContainerType.ALLAPPS);
+                }
+                mLauncher.showWorkspace(true /* animated */);
             }
             // snap to top or bottom using the release velocity
         } else {
             if (mAppsView.getTranslationY() > mShiftRange / 2) {
                 calculateDuration(velocity, Math.abs(mShiftRange - mAppsView.getTranslationY()));
-                mLauncher.showWorkspace(true);
+                if (mLauncher.isInState(LauncherState.ALL_APPS)) {
+                    logSwipeOnContainer(Touch.SWIPE, Direction.DOWN, ContainerType.ALLAPPS);
+                }
+                mLauncher.showWorkspace(true /* animated */);
             } else {
                 calculateDuration(velocity, Math.abs(mAppsView.getTranslationY()));
                 if (!mLauncher.isInState(LauncherState.ALL_APPS)) {
-                    mLauncher.getUserEventDispatcher().logActionOnContainer(
-                            Action.Touch.SWIPE,
-                            Action.Direction.UP,
-                            containerType);
+                    logSwipeOnContainer(Touch.SWIPE, Direction.UP, containerType);
                 }
                 mLauncher.showAppsView(true /* animated */);
             }
         }
     }
 
+    /**
+     * Important, make sure that this method is called only when actual launcher state transition
+     * happen and not when user swipes in one direction only to cancel that swipe seconds later.
+     *
+     * @param touchType Swipe or Fling
+     * @param direction Up or Down
+     * @param containerType Workspace or Allapps
+     */
+    private void logSwipeOnContainer(int touchType, int direction, int containerType) {
+        mLauncher.getUserEventDispatcher().logActionOnContainer(
+                touchType, direction, containerType,
+                mLauncher.getWorkspace().getCurrentPage());
+    }
+
     public boolean isTransitioning() {
         return mDetector.isDraggingOrSettling();
     }
diff --git a/src/com/android/launcher3/logging/LoggerUtils.java b/src/com/android/launcher3/logging/LoggerUtils.java
index 81333b1..00ee009 100644
--- a/src/com/android/launcher3/logging/LoggerUtils.java
+++ b/src/com/android/launcher3/logging/LoggerUtils.java
@@ -91,7 +91,8 @@
                 return getFieldName(t.controlType, ControlType.class);
             case Target.Type.CONTAINER:
                 String str = getFieldName(t.containerType, ContainerType.class);
-                if (t.containerType == ContainerType.WORKSPACE) {
+                if (t.containerType == ContainerType.WORKSPACE ||
+                        t.containerType == ContainerType.HOTSEAT) {
                     str += " id=" + t.pageIndex;
                 } else if (t.containerType == ContainerType.FOLDER) {
                     str += " grid(" + t.gridX + "," + t.gridY+ ")";
@@ -105,13 +106,16 @@
     private static String getItemStr(Target t) {
         String typeStr = getFieldName(t.itemType, ItemType.class);
         if (t.packageNameHash != 0) {
-            typeStr += ", packageHash=" + t.packageNameHash + ", predictiveRank=" + t.predictedRank;
+            typeStr += ", packageHash=" + t.packageNameHash;
         }
         if (t.componentHash != 0) {
-            typeStr += ", componentHash=" + t.componentHash + ", predictiveRank=" + t.predictedRank;
+            typeStr += ", componentHash=" + t.componentHash;
         }
         if (t.intentHash != 0) {
-            typeStr += ", intentHash=" + t.intentHash + ", predictiveRank=" + t.predictedRank;
+            typeStr += ", intentHash=" + t.intentHash;
+        }
+        if (t.packageNameHash != 0 || t.componentHash != 0 || t.intentHash != 0) {
+            typeStr += ", predictiveRank=" + t.predictedRank;
         }
         return typeStr + ", grid(" + t.gridX + "," + t.gridY + "), span(" + t.spanX + "," + t.spanY
                 + "), pageIdx=" + t.pageIndex;
diff --git a/src/com/android/launcher3/logging/UserEventDispatcher.java b/src/com/android/launcher3/logging/UserEventDispatcher.java
index 1a6dade..243dbea 100644
--- a/src/com/android/launcher3/logging/UserEventDispatcher.java
+++ b/src/com/android/launcher3/logging/UserEventDispatcher.java
@@ -232,6 +232,10 @@
         event.action.dir = dir;
         event.srcTarget[0].pageIndex = pageIndex;
         dispatchUserEvent(event, null);
+
+        if (action == Action.Touch.SWIPE) {
+            resetElapsedContainerMillis();
+        }
     }
 
     public void logActionOnItem(int action, int dir, int itemType) {
@@ -323,6 +327,7 @@
                 ev.actionDurationMillis);
         log += "\n isInLandscapeMode " + ev.isInLandscapeMode;
         log += "\n isInMultiWindowMode " + ev.isInMultiWindowMode;
+        log += "\n";
         Log.d(TAG, log);
     }