From 9bd862e588aad4971f0f4383412b20ddeb0ff4b4 Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Fri, 6 Apr 2018 12:25:10 -0700 Subject: [PATCH] Log dismissing or launching recent tasks We now pass the log action (e.g. SWIPE or FLING) to the pending animation, so that the end listener can log appropriately. This is used when swiping down or up on a task, for example. Bug: 73783784 Change-Id: I5c2eee24e8b23cf4af68d503d3435a6d8088dd8a --- .../PortraitStatesTouchController.java | 3 +- .../uioverrides/TaskViewTouchController.java | 13 ++------- .../src/com/android/quickstep/TaskUtils.java | 5 ++++ .../android/quickstep/views/RecentsView.java | 29 ++++++++++++++----- .../com/android/quickstep/views/TaskView.java | 12 +++++++- .../logging/UserEventDispatcher.java | 24 ++++++++------- .../AbstractStateChangeTouchController.java | 20 ++++++------- .../launcher3/util/PendingAnimation.java | 20 +++++++++---- 8 files changed, 81 insertions(+), 45 deletions(-) diff --git a/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java index 1b65ca0b05..59715769d2 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java @@ -37,6 +37,7 @@ import com.android.launcher3.anim.AnimatorSetBuilder; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.touch.AbstractStateChangeTouchController; import com.android.launcher3.touch.SwipeDetector; +import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; import com.android.quickstep.TouchInteractionService; import com.android.quickstep.util.SysuiEventLogger; @@ -182,7 +183,7 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr } if (mPendingAnimation != null) { - mPendingAnimation.finish(false); + mPendingAnimation.finish(false, Touch.SWIPE); mPendingAnimation = null; } diff --git a/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java index e73b2197fb..84a60bd9a0 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java @@ -30,11 +30,10 @@ import com.android.launcher3.Utilities; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.touch.SwipeDetector; -import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; +import com.android.launcher3.util.PendingAnimation; import com.android.launcher3.util.TouchController; import com.android.launcher3.views.BaseDragLayer; -import com.android.launcher3.util.PendingAnimation; import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.TaskView; @@ -152,7 +151,7 @@ public abstract class TaskViewTouchController mCurrentAnimation.setPlayFraction(0); } if (mPendingAnimation != null) { - mPendingAnimation.finish(false); + mPendingAnimation.finish(false, Touch.SWIPE); mPendingAnimation = null; } @@ -249,15 +248,9 @@ public abstract class TaskViewTouchController private void onCurrentAnimationEnd(boolean wasSuccess, int logAction) { if (mPendingAnimation != null) { - mPendingAnimation.finish(wasSuccess); + mPendingAnimation.finish(wasSuccess, logAction); mPendingAnimation = null; } - if (wasSuccess) { - if (!mCurrentAnimationIsGoingUp) { - mActivity.getUserEventDispatcher().logTaskLaunch(logAction, - Direction.DOWN, mTaskBeingDragged.getTask().getTopComponent()); - } - } mDetector.finishedScrolling(); mTaskBeingDragged = null; mCurrentAnimation = null; diff --git a/quickstep/src/com/android/quickstep/TaskUtils.java b/quickstep/src/com/android/quickstep/TaskUtils.java index 2df951b86e..5bf1d07db4 100644 --- a/quickstep/src/com/android/quickstep/TaskUtils.java +++ b/quickstep/src/com/android/quickstep/TaskUtils.java @@ -24,6 +24,7 @@ import android.util.Log; import com.android.launcher3.compat.LauncherAppsCompat; import com.android.launcher3.compat.UserManagerCompat; +import com.android.launcher3.util.ComponentKey; import com.android.systemui.shared.recents.model.Task; /** @@ -48,4 +49,8 @@ public class TaskUtils { return userManagerCompat.getBadgedLabelForUser( applicationInfo.loadLabel(packageManager), user); } + + public static ComponentKey getComponentKeyForTask(Task.TaskKey taskKey) { + return new ComponentKey(taskKey.getComponent(), UserHandle.of(taskKey.userId)); + } } diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index d95619c055..b22e2b68e1 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -59,12 +59,15 @@ import com.android.launcher3.Utilities; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.PropertyListBuilder; import com.android.launcher3.config.FeatureFlags; +import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; +import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; import com.android.launcher3.util.PendingAnimation; import com.android.launcher3.util.Themes; import com.android.quickstep.QuickScrubController; import com.android.quickstep.RecentsAnimationInterpolator; import com.android.quickstep.RecentsAnimationInterpolator.TaskWindowBounds; import com.android.quickstep.RecentsModel; +import com.android.quickstep.TaskUtils; import com.android.systemui.shared.recents.model.RecentsTaskLoadPlan; import com.android.systemui.shared.recents.model.RecentsTaskLoader; import com.android.systemui.shared.recents.model.Task; @@ -324,7 +327,7 @@ public abstract class RecentsView private void applyLoadPlan(RecentsTaskLoadPlan loadPlan) { if (mPendingAnimation != null) { - mPendingAnimation.addEndListener((b) -> applyLoadPlan(loadPlan)); + mPendingAnimation.addEndListener((onEndListener) -> applyLoadPlan(loadPlan)); return; } TaskStack stack = loadPlan != null ? loadPlan.getTaskStack() : null; @@ -748,10 +751,16 @@ public abstract class RecentsView } mPendingAnimation = pendingAnimation; - mPendingAnimation.addEndListener((isSuccess) -> { - if (isSuccess) { + mPendingAnimation.addEndListener((onEndListener) -> { + if (onEndListener.isSuccess) { if (removeTask) { - ActivityManagerWrapper.getInstance().removeTask(taskView.getTask().key.id); + Task task = taskView.getTask(); + if (task != null) { + ActivityManagerWrapper.getInstance().removeTask(task.key.id); + mActivity.getUserEventDispatcher().logTaskLaunchOrDismiss( + onEndListener.logAction, Direction.UP, + TaskUtils.getComponentKeyForTask(task.key)); + } } removeView(taskView); if (getChildCount() == 0) { @@ -793,7 +802,7 @@ public abstract class RecentsView AnimatorPlaybackController controller = AnimatorPlaybackController.wrap( pendingAnim.anim, DISMISS_TASK_DURATION); controller.dispatchOnStart(); - controller.setEndAction(() -> pendingAnim.finish(true)); + controller.setEndAction(() -> pendingAnim.finish(true, Touch.SWIPE)); controller.getAnimationPlayer().setInterpolator(FAST_OUT_SLOW_IN); controller.start(); } @@ -1050,9 +1059,15 @@ public abstract class RecentsView anim.setDuration(duration); mPendingAnimation = new PendingAnimation(anim); - mPendingAnimation.addEndListener((isSuccess) -> { - if (isSuccess) { + mPendingAnimation.addEndListener((onEndListener) -> { + if (onEndListener.isSuccess) { tv.launchTask(false); + Task task = tv.getTask(); + if (task != null) { + mActivity.getUserEventDispatcher().logTaskLaunchOrDismiss( + onEndListener.logAction, Direction.DOWN, + TaskUtils.getComponentKeyForTask(task.key)); + } } else { resetTaskVisuals(); } diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java index 42da472b5c..c04f825f9b 100644 --- a/quickstep/src/com/android/quickstep/views/TaskView.java +++ b/quickstep/src/com/android/quickstep/views/TaskView.java @@ -31,11 +31,15 @@ import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.ImageView; +import com.android.launcher3.BaseActivity; import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.DeviceProfile; import com.android.launcher3.R; +import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; +import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; import com.android.quickstep.RecentsAnimationInterpolator; import com.android.quickstep.TaskSystemShortcut; +import com.android.quickstep.TaskUtils; import com.android.quickstep.views.RecentsView.PageCallbacks; import com.android.quickstep.views.RecentsView.ScrollState; import com.android.systemui.shared.recents.model.Task; @@ -82,7 +86,13 @@ public class TaskView extends FrameLayout implements TaskCallbacks, PageCallback public TaskView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); - setOnClickListener((view) -> launchTask(true /* animate */)); + setOnClickListener((view) -> { + if (mTask != null) { + launchTask(true /* animate */); + BaseActivity.fromContext(context).getUserEventDispatcher().logTaskLaunchOrDismiss( + Touch.TAP, Direction.NONE, TaskUtils.getComponentKeyForTask(mTask.key)); + } + }); setOutlineProvider(new TaskOutlineProvider(getResources())); } diff --git a/src/com/android/launcher3/logging/UserEventDispatcher.java b/src/com/android/launcher3/logging/UserEventDispatcher.java index 90355bd67c..bf870cca01 100644 --- a/src/com/android/launcher3/logging/UserEventDispatcher.java +++ b/src/com/android/launcher3/logging/UserEventDispatcher.java @@ -16,6 +16,14 @@ package com.android.launcher3.logging; +import static com.android.launcher3.logging.LoggerUtils.newCommandAction; +import static com.android.launcher3.logging.LoggerUtils.newContainerTarget; +import static com.android.launcher3.logging.LoggerUtils.newDropTarget; +import static com.android.launcher3.logging.LoggerUtils.newItemTarget; +import static com.android.launcher3.logging.LoggerUtils.newLauncherEvent; +import static com.android.launcher3.logging.LoggerUtils.newTarget; +import static com.android.launcher3.logging.LoggerUtils.newTouchAction; + import android.app.PendingIntent; import android.content.ComponentName; import android.content.Context; @@ -38,20 +46,13 @@ import com.android.launcher3.userevent.nano.LauncherLogProto.Action; import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; import com.android.launcher3.userevent.nano.LauncherLogProto.LauncherEvent; import com.android.launcher3.userevent.nano.LauncherLogProto.Target; +import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.InstantAppResolver; import com.android.launcher3.util.LogConfig; import java.util.Locale; import java.util.UUID; -import static com.android.launcher3.logging.LoggerUtils.newCommandAction; -import static com.android.launcher3.logging.LoggerUtils.newContainerTarget; -import static com.android.launcher3.logging.LoggerUtils.newDropTarget; -import static com.android.launcher3.logging.LoggerUtils.newItemTarget; -import static com.android.launcher3.logging.LoggerUtils.newLauncherEvent; -import static com.android.launcher3.logging.LoggerUtils.newTarget; -import static com.android.launcher3.logging.LoggerUtils.newTouchAction; - /** * Manages the creation of {@link LauncherEvent}. * To debug this class, execute following command before side loading a new apk. @@ -162,14 +163,15 @@ public class UserEventDispatcher { dispatchUserEvent(event, intent); } - public void logTaskLaunch(int action, int direction, ComponentName componentName){ - LauncherEvent event = newLauncherEvent(newTouchAction(action), // TAP or SWIPE + public void logTaskLaunchOrDismiss(int action, int direction, ComponentKey componentKey) { + LauncherEvent event = newLauncherEvent(newTouchAction(action), // TAP or SWIPE or FLING newTarget(Target.Type.ITEM)); if (action == Action.Touch.SWIPE || action == Action.Touch.FLING) { + // Direction DOWN means the task was launched, UP means it was dismissed. event.action.dir = direction; } event.srcTarget[0].itemType = LauncherLogProto.ItemType.TASK; - fillComponentInfo(event.srcTarget[0], componentName); + fillComponentInfo(event.srcTarget[0], componentKey.componentName); dispatchUserEvent(event, null); } diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java index 9726704ddb..c875cf9bc7 100644 --- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java +++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java @@ -246,24 +246,24 @@ public abstract class AbstractStateChangeTouchController extends AnimatorListene } protected void onSwipeInteractionCompleted(LauncherState targetState, int logAction) { - if (targetState != mFromState) { - // Transition complete. log the action - mLauncher.getUserEventDispatcher().logStateChangeAction(logAction, - getDirectionForLog(), - mStartContainerType, - mFromState.containerType, - mToState.containerType, - mLauncher.getWorkspace().getCurrentPage()); - } clearState(); boolean shouldGoToTargetState = true; if (mPendingAnimation != null) { boolean reachedTarget = mToState == targetState; - mPendingAnimation.finish(reachedTarget); + mPendingAnimation.finish(reachedTarget, logAction); mPendingAnimation = null; shouldGoToTargetState = !reachedTarget; } if (shouldGoToTargetState) { + if (targetState != mFromState) { + // Transition complete. log the action + mLauncher.getUserEventDispatcher().logStateChangeAction(logAction, + getDirectionForLog(), + mStartContainerType, + mFromState.containerType, + mToState.containerType, + mLauncher.getWorkspace().getCurrentPage()); + } mLauncher.getStateManager().goToState(targetState, false /* animated */); } } diff --git a/src/com/android/launcher3/util/PendingAnimation.java b/src/com/android/launcher3/util/PendingAnimation.java index 4116d56e1d..617a38bbed 100644 --- a/src/com/android/launcher3/util/PendingAnimation.java +++ b/src/com/android/launcher3/util/PendingAnimation.java @@ -32,7 +32,7 @@ import java.util.function.Consumer; @TargetApi(Build.VERSION_CODES.O) public class PendingAnimation { - private final ArrayList> mEndListeners = new ArrayList<>(); + private final ArrayList> mEndListeners = new ArrayList<>(); public final AnimatorSet anim; @@ -40,14 +40,24 @@ public class PendingAnimation { this.anim = anim; } - public void finish(boolean isSuccess) { - for (Consumer listeners : mEndListeners) { - listeners.accept(isSuccess); + public void finish(boolean isSuccess, int logAction) { + for (Consumer listeners : mEndListeners) { + listeners.accept(new OnEndListener(isSuccess, logAction)); } mEndListeners.clear(); } - public void addEndListener(Consumer listener) { + public void addEndListener(Consumer listener) { mEndListeners.add(listener); } + + public static class OnEndListener { + public boolean isSuccess; + public int logAction; + + public OnEndListener(boolean isSuccess, int logAction) { + this.isSuccess = isSuccess; + this.logAction = logAction; + } + } }