diff --git a/protos/launcher_log.proto b/protos/launcher_log.proto index 0bbec188db..de74fcec5f 100644 --- a/protos/launcher_log.proto +++ b/protos/launcher_log.proto @@ -132,7 +132,9 @@ message Action { // not using the HOME_INTENT CANCEL = 3; // Indicates that a confirmation screen was cancelled CONFIRM = 4; // Indicates thata confirmation screen was accepted + STOP = 5; // Indicates onStop() was called (screen time out, power off) } + optional Type type = 1; optional Touch touch = 2; optional Direction dir = 3; diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 4efb911b77..eda5bb11ce 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -292,6 +292,8 @@ public class Launcher extends BaseActivity public ViewGroupFocusHelper mFocusHandler; private boolean mRotationEnabled = false; + private boolean mAppLaunchSuccess; + @Thunk void setOrientation() { if (mRotationEnabled) { unlockScreenOrientation(true); @@ -781,6 +783,10 @@ public class Launcher extends BaseActivity mAppWidgetHost.stopListening(); } + if (!mAppLaunchSuccess) { + getUserEventDispatcher().logActionCommand(Action.Command.STOP, + mWorkspace.getState().containerType); + } NotificationListener.removeNotificationsChangedListener(); } @@ -827,6 +833,7 @@ public class Launcher extends BaseActivity super.onResume(); TraceHelper.partitionSection("ON_RESUME", "superCall"); + mAppLaunchSuccess = false; getUserEventDispatcher().resetElapsedSessionMillis(); mPaused = false; if (mOnResumeNeedsLoad) { @@ -2115,7 +2122,6 @@ public class Launcher extends BaseActivity 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 class Launcher extends BaseActivity } 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 @@ public class Launcher extends BaseActivity 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 2243a9cd87..9247c54f7c 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.anim.SpringAnimationHandler; 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 @@ public class AllAppsTransitionController implements TouchController, SwipeDetect 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 @@ public class AllAppsTransitionController implements TouchController, SwipeDetect } } 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 81333b1a22..00ee0096ad 100644 --- a/src/com/android/launcher3/logging/LoggerUtils.java +++ b/src/com/android/launcher3/logging/LoggerUtils.java @@ -91,7 +91,8 @@ public class LoggerUtils { 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 @@ public class LoggerUtils { 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 1a6dade313..243dbeae67 100644 --- a/src/com/android/launcher3/logging/UserEventDispatcher.java +++ b/src/com/android/launcher3/logging/UserEventDispatcher.java @@ -232,6 +232,10 @@ public class UserEventDispatcher { 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 @@ public class UserEventDispatcher { ev.actionDurationMillis); log += "\n isInLandscapeMode " + ev.isInLandscapeMode; log += "\n isInMultiWindowMode " + ev.isInMultiWindowMode; + log += "\n"; Log.d(TAG, log); }