diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java index bb2ac738c3..b6e93bb8a9 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java @@ -260,7 +260,8 @@ public class TaskbarUIController { taskAttributes.getThumbnailView(), taskAttributes.getThumbnailView().getThumbnail(), null /* intent */, - null /* user */); + null /* user */, + info); return; } } @@ -273,7 +274,8 @@ public class TaskbarUIController { startingView, null /* thumbnail */, intent, - info.user); + info.user, + info); } ); } diff --git a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java index 9329e16909..dbaeafbee2 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java @@ -22,6 +22,7 @@ import static com.android.app.animation.Interpolators.FINAL_FRAME; import static com.android.app.animation.Interpolators.INSTANT; import static com.android.app.animation.Interpolators.LINEAR; import static com.android.launcher3.LauncherState.QUICK_SWITCH_FROM_HOME; +import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SPLIT_SELECTION_EXIT_HOME; import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE; import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_MODAL; import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE; @@ -111,7 +112,7 @@ public abstract class BaseRecentsViewStateController boolean exitingOverview = !FeatureFlags.enableSplitContextually() && !toState.overviewUi; if (mRecentsView.isSplitSelectionActive() && exitingOverview) { setter.add(mRecentsView.getSplitSelectController().getSplitAnimationController() - .createPlaceholderDismissAnim(mLauncher)); + .createPlaceholderDismissAnim(mLauncher, LAUNCHER_SPLIT_SELECTION_EXIT_HOME)); setter.setViewAlpha( mRecentsView.getSplitInstructionsView(), 0, diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java index c2a248db6e..fbbbdd0a2f 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java +++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java @@ -38,6 +38,8 @@ import static com.android.launcher3.LauncherState.OVERVIEW_SPLIT_SELECT; import static com.android.launcher3.compat.AccessibilityManagerCompat.sendCustomAccessibilityEvent; import static com.android.launcher3.config.FeatureFlags.enableSplitContextually; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_LAUNCH_TAP; +import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SPLIT_SELECTION_EXIT_INTERRUPTED; +import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SPLIT_SELECTION_EXIT_HOME; import static com.android.launcher3.model.data.ItemInfo.NO_MATCHING_ID; import static com.android.launcher3.popup.QuickstepSystemShortcut.getSplitSelectShortcutByPosition; import static com.android.launcher3.popup.SystemShortcut.APP_INFO; @@ -596,7 +598,7 @@ public class QuickstepLauncher extends Launcher { list.add(getDragController()); Consumer splitAnimator = animatorSet -> animatorSet.play(mSplitSelectStateController.getSplitAnimationController() - .createPlaceholderDismissAnim(this)); + .createPlaceholderDismissAnim(this, LAUNCHER_SPLIT_SELECTION_EXIT_HOME)); switch (mode) { case NO_BUTTON: list.add(new NoButtonQuickSwitchTouchController(this)); @@ -767,8 +769,10 @@ public class QuickstepLauncher extends Launcher { // If Launcher pauses before both split apps are selected, exit split screen. if (!mSplitSelectStateController.isBothSplitAppsConfirmed() && !mSplitSelectStateController.isLaunchingFirstAppFullscreen()) { + mSplitSelectStateController + .logExitReason(LAUNCHER_SPLIT_SELECTION_EXIT_INTERRUPTED); mSplitSelectStateController.getSplitAnimationController() - .playPlaceholderDismissAnim(this); + .playPlaceholderDismissAnim(this, LAUNCHER_SPLIT_SELECTION_EXIT_INTERRUPTED); } } } @@ -1042,17 +1046,17 @@ public class QuickstepLauncher extends Launcher { } @Override - protected void handleSplitAnimationGoingToHome() { - super.handleSplitAnimationGoingToHome(); + protected void handleSplitAnimationGoingToHome(StatsLogManager.EventEnum splitDismissReason) { + super.handleSplitAnimationGoingToHome(splitDismissReason); mSplitSelectStateController.getSplitAnimationController() - .playPlaceholderDismissAnim(this); + .playPlaceholderDismissAnim(this, splitDismissReason); } @Override - public void dismissSplitSelection() { - super.dismissSplitSelection(); + public void dismissSplitSelection(StatsLogManager.LauncherEvent splitDismissEvent) { + super.dismissSplitSelection(splitDismissEvent); mSplitSelectStateController.getSplitAnimationController() - .playPlaceholderDismissAnim(this); + .playPlaceholderDismissAnim(this, splitDismissEvent); } public T getActionsView() { diff --git a/quickstep/src/com/android/quickstep/util/AppPairsController.java b/quickstep/src/com/android/quickstep/util/AppPairsController.java index 839320ed3b..0be65ca155 100644 --- a/quickstep/src/com/android/quickstep/util/AppPairsController.java +++ b/quickstep/src/com/android/quickstep/util/AppPairsController.java @@ -162,10 +162,10 @@ public class AppPairsController { @Nullable Task foundTask2 = foundTasks[1]; if (foundTask2 != null) { - mSplitSelectStateController.setSecondTask(foundTask2); + mSplitSelectStateController.setSecondTask(foundTask2, app2); } else { mSplitSelectStateController.setSecondTask( - app2.intent, app2.user); + app2.intent, app2.user, app2); } mSplitSelectStateController.setLaunchingIconView(appPairIcon); diff --git a/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt b/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt index ad9f5ea1cc..76b3d7bdcd 100644 --- a/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt +++ b/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt @@ -46,6 +46,7 @@ import com.android.launcher3.Utilities import com.android.launcher3.anim.PendingAnimation import com.android.launcher3.apppairs.AppPairIcon import com.android.launcher3.config.FeatureFlags +import com.android.launcher3.logging.StatsLogManager.EventEnum import com.android.launcher3.statehandlers.DepthController import com.android.launcher3.statemanager.StateManager import com.android.launcher3.statemanager.StatefulActivity @@ -213,17 +214,21 @@ class SplitAnimationController(val splitSelectStateController: SplitSelectStateC } /** Does not play any animation if user is not currently in split selection state. */ - fun playPlaceholderDismissAnim(launcher: StatefulActivity<*>) { + fun playPlaceholderDismissAnim(launcher: StatefulActivity<*>, splitDismissEvent: EventEnum) { if (!splitSelectStateController.isSplitSelectActive) { return } - val anim = createPlaceholderDismissAnim(launcher) + val anim = createPlaceholderDismissAnim(launcher, splitDismissEvent) anim.start() } - /** Returns [AnimatorSet] which slides initial split placeholder view offscreen. */ - fun createPlaceholderDismissAnim(launcher: StatefulActivity<*>) : AnimatorSet { + /** + * Returns [AnimatorSet] which slides initial split placeholder view offscreen and logs an event + * for why split is being dismissed + */ + fun createPlaceholderDismissAnim(launcher: StatefulActivity<*>, + splitDismissEvent: EventEnum) : AnimatorSet { val animatorSet = AnimatorSet() val recentsView : RecentsView<*, *> = launcher.getOverviewPanel() val floatingTask: FloatingTaskView = splitSelectStateController.firstFloatingTaskView @@ -260,6 +265,7 @@ class SplitAnimationController(val splitSelectStateController: SplitSelectStateC splitSelectStateController.splitInstructionsView) } }) + splitSelectStateController.logExitReason(splitDismissEvent) return animatorSet } diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectDataHolder.kt b/quickstep/src/com/android/quickstep/util/SplitSelectDataHolder.kt index c013483bab..06edb14a1f 100644 --- a/quickstep/src/com/android/quickstep/util/SplitSelectDataHolder.kt +++ b/quickstep/src/com/android/quickstep/util/SplitSelectDataHolder.kt @@ -87,6 +87,7 @@ class SplitSelectDataHolder( @StagePosition private var initialStagePosition: Int = STAGE_POSITION_UNDEFINED private var itemInfo: ItemInfo? = null + private var secondItemInfo: ItemInfo? = null private var splitEvent: EventEnum? = null private var initialTaskId: Int = INVALID_TASK_ID @@ -144,8 +145,9 @@ class SplitSelectDataHolder( * To be called as soon as user selects the second task (even if animations aren't complete) * @param taskId The second task that will be launched. */ - fun setSecondTask(taskId: Int) { + fun setSecondTask(taskId: Int, itemInfo: ItemInfo) { secondTaskId = taskId + secondItemInfo = itemInfo } /** @@ -153,9 +155,10 @@ class SplitSelectDataHolder( * @param intent The second intent that will be launched. * @param user The user of that intent. */ - fun setSecondTask(intent: Intent, user: UserHandle) { + fun setSecondTask(intent: Intent, user: UserHandle, itemInfo: ItemInfo) { secondIntent = intent secondUser = user + secondItemInfo = itemInfo } /** @@ -163,9 +166,10 @@ class SplitSelectDataHolder( * Sets [secondUser] from that of the pendingIntent * @param pendingIntent The second PendingIntent that will be launched. */ - fun setSecondTask(pendingIntent: PendingIntent) { + fun setSecondTask(pendingIntent: PendingIntent, itemInfo: ItemInfo) { secondPendingIntent = pendingIntent secondUser = pendingIntent.creatorUserHandle + secondItemInfo = itemInfo } /** @@ -173,8 +177,8 @@ class SplitSelectDataHolder( * an extra intent from their RemoteResponse. * See [android.widget.RemoteViews.RemoteResponse.getLaunchOptions].first */ - fun setSecondWidget(pendingIntent: PendingIntent, widgetIntent: Intent?) { - setSecondTask(pendingIntent) + fun setSecondWidget(pendingIntent: PendingIntent, widgetIntent: Intent?, itemInfo: ItemInfo) { + setSecondTask(pendingIntent, itemInfo) widgetSecondIntent = widgetIntent } @@ -407,6 +411,10 @@ class SplitSelectDataHolder( return itemInfo } + fun getSecondItemInfo(): ItemInfo? { + return secondItemInfo + } + private fun isSecondTaskIntentSet(): Boolean { return secondTaskId != INVALID_TASK_ID || secondIntent != null || secondPendingIntent != null diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java index 3c90e0cf51..f06418bbd4 100644 --- a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java +++ b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java @@ -19,6 +19,10 @@ package com.android.quickstep.util; import static com.android.launcher3.Utilities.postAsyncCallback; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_DESKTOP_MODE_SPLIT_LEFT_TOP; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_DESKTOP_MODE_SPLIT_RIGHT_BOTTOM; +import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SPLIT_SELECTED_SECOND_APP; +import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SPLIT_SELECTION_COMPLETE; +import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SPLIT_SELECTION_EXIT_HOME; +import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SPLIT_SELECTION_INITIATED; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT; @@ -151,6 +155,11 @@ public class SplitSelectStateController { private SplitInstructionsView mSplitInstructionsView; private final List mSplitSelectionListeners = new ArrayList<>(); + /** + * Tracks metrics from when first app is selected to split launch or cancellation. This also + * gets passed over to shell when attempting to invoke split. + */ + private Pair mSessionInstanceIds; private final BackPressHandler mSplitBackHandler = new BackPressHandler() { @Override @@ -162,7 +171,8 @@ public class SplitSelectStateController { public void onBackInvoked() { // When exiting from split selection, leave current context to go to // homescreen as well - getSplitAnimationController().playPlaceholderDismissAnim(mContext); + getSplitAnimationController().playPlaceholderDismissAnim(mContext, + LAUNCHER_SPLIT_SELECTION_EXIT_HOME); if (mActivityBackCallback != null) { mActivityBackCallback.run(); } @@ -203,6 +213,7 @@ public class SplitSelectStateController { int alreadyRunningTask) { mSplitSelectDataHolder.setInitialTaskSelect(intent, stagePosition, itemInfo, splitEvent, alreadyRunningTask); + createAndLogInstanceIdsForSession(); } /** @@ -213,6 +224,7 @@ public class SplitSelectStateController { @StagePosition int stagePosition, @NonNull ItemInfo itemInfo, StatsLogManager.EventEnum splitEvent) { mSplitSelectDataHolder.setInitialTaskSelect(info, stagePosition, itemInfo, splitEvent); + createAndLogInstanceIdsForSession(); } /** @@ -330,14 +342,12 @@ public class SplitSelectStateController { */ public void launchSplitTasks(@PersistentSnapPosition int snapPosition, @Nullable Consumer callback) { - Pair instanceIds = - LogUtils.getShellShareableInstanceId(); - launchTasks(callback, false /* freezeTaskList */, snapPosition, instanceIds.first); + launchTasks(callback, false /* freezeTaskList */, snapPosition, mSessionInstanceIds.first); mStatsLogManager.logger() - .withItemInfo(mSplitSelectDataHolder.getItemInfo()) - .withInstanceId(instanceIds.second) - .log(mSplitSelectDataHolder.getSplitEvent()); + .withItemInfo(mSplitSelectDataHolder.getSecondItemInfo()) + .withInstanceId(mSessionInstanceIds.second) + .log(LAUNCHER_SPLIT_SELECTED_SECOND_APP); } /** @@ -363,12 +373,27 @@ public class SplitSelectStateController { launchSplitTasks(SNAP_TO_50_50, null); } + /** + * Use to log an event when user exists split selection when the second app **IS NOT** selected. + * This must be called before playing any exit animations since most animations will call + * {@link #resetState()} which removes {@link #mSessionInstanceIds}. + */ + public void logExitReason(StatsLogManager.EventEnum splitExitEvent) { + StatsLogManager.StatsLogger logger = mStatsLogManager.logger(); + if (mSessionInstanceIds != null) { + logger.withInstanceId(mSessionInstanceIds.second); + } else { + Log.w(TAG, "Missing session instanceIds"); + } + logger.log(splitExitEvent); + } + /** * To be called as soon as user selects the second task (even if animations aren't complete) * @param task The second task that will be launched. */ - public void setSecondTask(Task task) { - mSplitSelectDataHolder.setSecondTask(task.key.id); + public void setSecondTask(Task task, ItemInfo itemInfo) { + mSplitSelectDataHolder.setSecondTask(task.key.id, itemInfo); } /** @@ -376,20 +401,20 @@ public class SplitSelectStateController { * @param intent The second intent that will be launched. * @param user The user of that intent. */ - public void setSecondTask(Intent intent, UserHandle user) { - mSplitSelectDataHolder.setSecondTask(intent, user); + public void setSecondTask(Intent intent, UserHandle user, ItemInfo itemInfo) { + mSplitSelectDataHolder.setSecondTask(intent, user, itemInfo); } /** * To be called as soon as user selects the second app (even if animations aren't complete) * @param pendingIntent The second PendingIntent that will be launched. */ - public void setSecondTask(PendingIntent pendingIntent) { - mSplitSelectDataHolder.setSecondTask(pendingIntent); + public void setSecondTask(PendingIntent pendingIntent, ItemInfo itemInfo) { + mSplitSelectDataHolder.setSecondTask(pendingIntent, itemInfo); } public void setSecondWidget(PendingIntent pendingIntent, Intent widgetIntent) { - mSplitSelectDataHolder.setSecondWidget(pendingIntent, widgetIntent); + mSplitSelectDataHolder.setSecondWidget(pendingIntent, widgetIntent, null /*itemInfo*/); } /** @@ -578,7 +603,7 @@ public class SplitSelectStateController { final RemoteTransition remoteTransition = new RemoteTransition(animationRunner, ActivityThread.currentActivityThread().getApplicationThread(), "LaunchAppFullscreen"); - InstanceId instanceId = LogUtils.getShellShareableInstanceId().first; + InstanceId instanceId = mSessionInstanceIds.first; if (TaskAnimationManager.ENABLE_SHELL_TRANSITIONS) { switch (launchData.getSplitLaunchType()) { case SPLIT_SINGLE_TASK_FULLSCREEN -> mSystemUiProxy.startTasks(firstTaskId, @@ -630,6 +655,26 @@ public class SplitSelectStateController { ActivityThread.currentActivityThread().getApplicationThread()); } + /** + * Will initialize {@link #mSessionInstanceIds} if null and log the first split event from + * {@link #mSplitSelectDataHolder} + */ + private void createAndLogInstanceIdsForSession() { + if (mSessionInstanceIds != null) { + Log.w(TAG, "SessionIds should be null"); + } + // Log separately the start of the session and then the first app selected + mSessionInstanceIds = LogUtils.getShellShareableInstanceId(); + mStatsLogManager.logger() + .withInstanceId(mSessionInstanceIds.second) + .log(LAUNCHER_SPLIT_SELECTION_INITIATED); + + mStatsLogManager.logger() + .withItemInfo(mSplitSelectDataHolder.getItemInfo()) + .withInstanceId(mSessionInstanceIds.second) + .log(mSplitSelectDataHolder.getSplitEvent()); + } + public @StagePosition int getActiveSplitStagePosition() { return mSplitSelectDataHolder.getInitialStagePosition(); } @@ -804,6 +849,13 @@ public class SplitSelectStateController { mFirstFloatingTaskView = null; mSplitInstructionsView = null; mLaunchingFirstAppFullscreen = false; + + if (mSessionInstanceIds != null) { + mStatsLogManager.logger() + .withInstanceId(mSessionInstanceIds.second) + .log(LAUNCHER_SPLIT_SELECTION_COMPLETE); + } + mSessionInstanceIds = null; } /** diff --git a/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java b/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java index 50a5a832e1..445a540e5a 100644 --- a/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java +++ b/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java @@ -45,6 +45,7 @@ import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.icons.BitmapInfo; import com.android.launcher3.icons.IconCache; import com.android.launcher3.model.data.FolderInfo; +import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.PackageItemInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.quickstep.views.FloatingTaskView; @@ -134,7 +135,7 @@ public class SplitToWorkspaceController { return false; } - mController.setSecondTask(intent, user); + mController.setSecondTask(intent, user, (ItemInfo) tag); startWorkspaceAnimation(view, null /*bitmap*/, bitmapInfo.newIcon(mLauncher)); return true; diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java index 9bb9775a51..3f1d343663 100644 --- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java +++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java @@ -25,6 +25,7 @@ import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.LauncherState.OVERVIEW_MODAL_TASK; import static com.android.launcher3.LauncherState.OVERVIEW_SPLIT_SELECT; import static com.android.launcher3.LauncherState.SPRING_LOADED; +import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SPLIT_SELECTION_EXIT_HOME; import static com.android.quickstep.views.DesktopTaskView.isDesktopModeSupported; import android.annotation.TargetApi; @@ -92,7 +93,7 @@ public class LauncherRecentsView extends RecentsView = mock() private val handler: Handler = mock() private val context: StatefulActivity<*> = mock() private val recentsModel: RecentsModel = mock() private val pendingIntent: PendingIntent = mock() - lateinit var splitSelectStateController: SplitSelectStateController + private lateinit var splitSelectStateController: SplitSelectStateController private val primaryUserHandle = UserHandle(ActivityManager.RunningTaskInfo().userId) private val nonPrimaryUserHandle = UserHandle(ActivityManager.RunningTaskInfo().userId + 10) @@ -74,6 +78,9 @@ class SplitSelectStateControllerTest { @Before fun setup() { + `when`(statsLogManager.logger()).thenReturn(statsLogger) + `when`(statsLogger.withInstanceId(any())).thenReturn(statsLogger) + `when`(statsLogger.withItemInfo(any())).thenReturn(statsLogger) splitSelectStateController = SplitSelectStateController( context, @@ -593,9 +600,10 @@ class SplitSelectStateControllerTest { @Test fun secondPendingIntentSet() { val itemInfo = ItemInfo() + val itemInfo2 = ItemInfo() whenever(pendingIntent.creatorUserHandle).thenReturn(primaryUserHandle) splitSelectStateController.setInitialTaskSelect(null, 0, itemInfo, null, 1) - splitSelectStateController.setSecondTask(pendingIntent) + splitSelectStateController.setSecondTask(pendingIntent, itemInfo2) assertTrue(splitSelectStateController.isBothSplitAppsConfirmed) } diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 496cb4eb30..39b3fbf762 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -77,6 +77,7 @@ import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCH import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_EXIT; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ONRESUME; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ONSTOP; +import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SPLIT_SELECTION_EXIT_HOME; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SWIPELEFT; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SWIPERIGHT; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_WIDGET_RECONFIGURED; @@ -1580,7 +1581,7 @@ public class Launcher extends StatefulActivity } if (FeatureFlags.enableSplitContextually()) { - handleSplitAnimationGoingToHome(); + handleSplitAnimationGoingToHome(LAUNCHER_SPLIT_SELECTION_EXIT_HOME); } mOverlayManager.hideOverlay(isStarted() && !isForceInvisible()); handleGestureContract(intent); @@ -1596,7 +1597,7 @@ public class Launcher extends StatefulActivity } /** Handle animating away split placeholder view when user taps on home button */ - protected void handleSplitAnimationGoingToHome() { + protected void handleSplitAnimationGoingToHome(EventEnum splitDismissReason) { // Overridden } @@ -2667,7 +2668,7 @@ public class Launcher extends StatefulActivity } /** Call to dismiss the intermediary split selection state. */ - public void dismissSplitSelection() { + public void dismissSplitSelection(StatsLogManager.LauncherEvent splitDismissEvent) { // Overridden; move this into ActivityContext if necessary for Taskbar } diff --git a/src/com/android/launcher3/logging/StatsLogManager.java b/src/com/android/launcher3/logging/StatsLogManager.java index 2a0f0302e4..1447d05a98 100644 --- a/src/com/android/launcher3/logging/StatsLogManager.java +++ b/src/com/android/launcher3/logging/StatsLogManager.java @@ -199,6 +199,11 @@ public class StatsLogManager implements ResourceBasedOverride { @UiEvent(doc = "User tapped on app info system shortcut.") LAUNCHER_SYSTEM_SHORTCUT_APP_INFO_TAP(515), + /** + * @deprecated Use {@link #LAUNCHER_APP_ICON_MENU_SPLIT_LEFT_TOP} or + * {@link #LAUNCHER_APP_ICON_MENU_SPLIT_RIGHT_BOTTOM} + */ + @Deprecated @UiEvent(doc = "User tapped on split screen icon on a task menu.") LAUNCHER_SYSTEM_SHORTCUT_SPLIT_SCREEN_TAP(518), @@ -722,6 +727,27 @@ public class StatsLogManager implements ResourceBasedOverride { @UiEvent(doc = "User tapped on private space uninstall system shortcut.") LAUNCHER_PRIVATE_SPACE_UNINSTALL_SYSTEM_SHORTCUT_TAP(1608), + @UiEvent(doc = "User initiated split selection") + LAUNCHER_SPLIT_SELECTION_INITIATED(1618), + + @UiEvent(doc = "User finished a split selection session") + LAUNCHER_SPLIT_SELECTION_COMPLETE(1619), + + @UiEvent(doc = "User selected both apps for split screen") + LAUNCHER_SPLIT_SELECTED_SECOND_APP(1609), + + @UiEvent(doc = "User exited split selection by going home via swipe, button, or state " + + "transition") + LAUNCHER_SPLIT_SELECTION_EXIT_HOME(1610), + + @UiEvent(doc = "User exited split selection by tapping cancel in split instructions view") + LAUNCHER_SPLIT_SELECTION_EXIT_CANCEL_BUTTON(1611), + + @UiEvent(doc = "User exited split selection when another activity/app came to foreground" + + " after first app had been selected OR if user long-pressed on home. Default exit" + + " metric.") + LAUNCHER_SPLIT_SELECTION_EXIT_INTERRUPTED(1612), + // ADD MORE ; diff --git a/src/com/android/launcher3/touch/WorkspaceTouchListener.java b/src/com/android/launcher3/touch/WorkspaceTouchListener.java index 8c43f75c08..0ff10c26a5 100644 --- a/src/com/android/launcher3/touch/WorkspaceTouchListener.java +++ b/src/com/android/launcher3/touch/WorkspaceTouchListener.java @@ -24,6 +24,7 @@ import static android.view.MotionEvent.ACTION_UP; import static com.android.launcher3.LauncherState.ALL_APPS; import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_CLOSE_TAP_OUTSIDE; +import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SPLIT_SELECTION_EXIT_INTERRUPTED; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_WORKSPACE_LONGPRESS; import android.graphics.PointF; @@ -207,7 +208,7 @@ public class WorkspaceTouchListener extends GestureDetector.SimpleOnGestureListe mLauncher.getStatsLogManager().logger().log(LAUNCHER_WORKSPACE_LONGPRESS); mLauncher.showDefaultOptions(mTouchDownPoint.x, mTouchDownPoint.y); if (FeatureFlags.enableSplitContextually() && mLauncher.isSplitSelectionActive()) { - mLauncher.dismissSplitSelection(); + mLauncher.dismissSplitSelection(LAUNCHER_SPLIT_SELECTION_EXIT_INTERRUPTED); } } else { cancelLongPress();