Quick step/scrub/switch logging

- state transition happening due to Home and back is handled by
  specifying src target as 'from' container and dst target as the 'to'
  container
- Source and Destination container shows FROM and TO state for SWIPE/FLING
- event.isStateChange = true indicates that an action resulted in
  state transition
- Elapsed container millis is the screen time on the source container

Bug: 70181187

- logcat printout with setprop log.tag.UserEvent VERBOSE
1) State: WORKSPACE -> ALLAPPS
  action:FLING direction=UP
  Source child:HOTSEAT id=0	parent:WORKSPACE id=0
  Destination child:ALLAPPS
  Elapsed container 1225 ms, session 1225 ms, action 0 ms

2) ALLAPPS -> HOMESCREEN
  action:FLING direction=DOWN
  Source child:ALLAPPS	parent:ALLAPPS
  Destination child:WORKSPACE id=0
  Elapsed container 971 ms, session 2197 ms, action 0 ms

3) HOMESCREEN -> OVERVIEW
  action:FLING direction=UP
  Source child:NAVBAR	parent:WORKSPACE id=0
  Destination child:TASKSWITCHER
  Elapsed container 4834 ms, session 4834 ms, action 0 ms

4) OVERVIEW-> ALLAPPS
  action:FLING direction=UP
  Source child:TASK	parent:TASKSWITCHER
  Destination child:ALLAPPS
  Elapsed container 2176 ms, session 7010 ms, action 0 ms

5) ALLAPPS->OVERVIEW
  action:FLING direction=DOWN
  Source child:ALLAPPS	parent:ALLAPPS
  Destination child:TASKSWITCHER
  Elapsed container 3683 ms, session 10693 ms, action 0 ms

6) OVERVIEW-> HOMESCREEN
  action:FLING direction=DOWN
  Source child:TASK	parent:TASKSWITCHER
  Destination child:WORKSPACE id=0
  Elapsed container 2108 ms, session 12801 ms, action 0 ms

7) APPS-> OVERVIEW
  action:FLING direction=UP
  Source child:NAVBAR	parent:APP
  Destination child:TASKSWITCHER
  Elapsed container 104 ms, session 104 ms, action 0 ms

8) Quickscrub: action:DRAGANDDROP Source child: QUICK

9) Quickswitch: action:FLING Source child: QUICK

Change-Id: I5898230859ff600f48a2a873a40b670fe4d39a0d
This commit is contained in:
Hyunyoung Song 2018-02-14 13:40:25 -08:00
parent 224f58c4bc
commit b3fbc0ba8f
16 changed files with 219 additions and 47 deletions

View File

@ -68,6 +68,7 @@ enum ItemType {
SEARCHBOX = 6; SEARCHBOX = 6;
EDITTEXT = 7; EDITTEXT = 7;
NOTIFICATION = 8; NOTIFICATION = 8;
TASK = 9; // Each page of Recents UI (QuickStep)
} }
// Used to define what type of container a Target would represent. // Used to define what type of container a Target would represent.
@ -78,11 +79,14 @@ enum ContainerType {
FOLDER = 3; FOLDER = 3;
ALLAPPS = 4; ALLAPPS = 4;
WIDGETS = 5; WIDGETS = 5;
OVERVIEW = 6; OVERVIEW = 6; // Zoomed out workspace (without QuickStep)
PREDICTION = 7; PREDICTION = 7;
SEARCHRESULT = 8; SEARCHRESULT = 8;
DEEPSHORTCUTS = 9; DEEPSHORTCUTS = 9;
PINITEM = 10; // confirmation screen PINITEM = 10; // confirmation screen
NAVBAR = 11;
TASKSWITCHER = 12; // Recents UI Container (QuickStep)
APP = 13; // Foreground activity is another app (QuickStep)
} }
// Used to define what type of control a Target would represent. // Used to define what type of control a Target would represent.
@ -100,6 +104,7 @@ enum ControlType {
HOME_INTENT = 10; // Deprecated, use enum Command instead HOME_INTENT = 10; // Deprecated, use enum Command instead
BACK_BUTTON = 11; // Deprecated, use enum Command instead BACK_BUTTON = 11; // Deprecated, use enum Command instead
// GO_TO_PLAYSTORE // GO_TO_PLAYSTORE
QUICK_SCRUB_BUTTON = 12;
} }
// Used to define the action component of the LauncherEvent. // Used to define the action component of the LauncherEvent.
@ -141,6 +146,7 @@ message Action {
optional Command command = 4; optional Command command = 4;
// Log if the action was performed on outside of the container // Log if the action was performed on outside of the container
optional bool is_outside = 5; optional bool is_outside = 5;
optional bool is_state_change = 6;
} }
// //
@ -150,7 +156,6 @@ message Action {
// //
message LauncherEvent { message LauncherEvent {
required Action action = 1; required Action action = 1;
// List of targets that touch actions can be operated on. // List of targets that touch actions can be operated on.
repeated Target src_target = 2; repeated Target src_target = 2;
repeated Target dest_target = 3; repeated Target dest_target = 3;

View File

@ -30,8 +30,12 @@ import android.view.MotionEvent;
import com.android.launcher3.DeviceProfile; import com.android.launcher3.DeviceProfile;
import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener; import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
import com.android.launcher3.Launcher; import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.anim.SpringAnimationHandler; import com.android.launcher3.anim.SpringAnimationHandler;
import com.android.launcher3.dragndrop.DragLayer; import com.android.launcher3.dragndrop.DragLayer;
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.VerticalSwipeController; import com.android.launcher3.util.VerticalSwipeController;
import com.android.quickstep.RecentsView; import com.android.quickstep.RecentsView;
@ -100,6 +104,10 @@ public class EdgeSwipeController extends VerticalSwipeController implements
return isTransitionFlipped() ? DIRECTION_NEGATIVE : DIRECTION_POSITIVE; return isTransitionFlipped() ? DIRECTION_NEGATIVE : DIRECTION_POSITIVE;
} }
public EdgeSwipeController(Launcher l, LauncherState baseState) {
super(l, baseState);
}
@Override @Override
protected boolean isTransitionFlipped() { protected boolean isTransitionFlipped() {
return mLauncher.getDeviceProfile().isSeascape(); return mLauncher.getDeviceProfile().isSeascape();
@ -117,8 +125,21 @@ public class EdgeSwipeController extends VerticalSwipeController implements
builder.addTaggedData(319/*APP_TRANSITION_DELAY_MS*/, builder.addTaggedData(319/*APP_TRANSITION_DELAY_MS*/,
0/* zero time */); 0/* zero time */);
mMetricsLogger.write(builder); mMetricsLogger.write(builder);
// Add user event logging for launcher pipeline
int direction = Direction.UP;
if (mLauncher.getDeviceProfile().isLandscape) {
direction = Direction.LEFT;
if (mLauncher.getDeviceProfile().isSeascape()) {
direction = Direction.RIGHT;
}
}
mLauncher.getUserEventDispatcher().logStateChangeAction(
wasFling ? Touch.FLING : Touch.SWIPE, direction,
ContainerType.NAVBAR, ContainerType.WORKSPACE, // src target
ContainerType.TASKSWITCHER, // dst target
mLauncher.getWorkspace().getCurrentPage());
} }
// TODO: Log something
} }
@Override @Override

View File

@ -40,7 +40,7 @@ public class OverviewState extends LauncherState {
| FLAG_DISABLE_RESTORE; | FLAG_DISABLE_RESTORE;
public OverviewState(int id) { public OverviewState(int id) {
super(id, ContainerType.WORKSPACE, OVERVIEW_TRANSITION_MS, STATE_FLAGS); super(id, ContainerType.TASKSWITCHER, OVERVIEW_TRANSITION_MS, STATE_FLAGS);
} }
@Override @Override

View File

@ -31,6 +31,10 @@ import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.dragndrop.DragLayer; import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.touch.SwipeDetector; import com.android.launcher3.touch.SwipeDetector;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.launcher3.util.TouchController; import com.android.launcher3.util.TouchController;
import com.android.quickstep.RecentsView; import com.android.quickstep.RecentsView;
import com.android.quickstep.TaskView; import com.android.quickstep.TaskView;
@ -70,6 +74,7 @@ public class OverviewSwipeController extends AnimatorListenerAdapter
private float mDisplacementShift; private float mDisplacementShift;
private float mProgressMultiplier; private float mProgressMultiplier;
private float mEndDisplacement; private float mEndDisplacement;
private int mStartingTarget;
private TaskView mTaskBeingDragged; private TaskView mTaskBeingDragged;
@ -120,7 +125,6 @@ public class OverviewSwipeController extends AnimatorListenerAdapter
// calling the callbacks. // calling the callbacks.
final int directionsToDetectScroll; final int directionsToDetectScroll;
boolean ignoreSlopWhenSettling = false; boolean ignoreSlopWhenSettling = false;
if (mCurrentAnimation != null) { if (mCurrentAnimation != null) {
directionsToDetectScroll = SwipeDetector.DIRECTION_BOTH; directionsToDetectScroll = SwipeDetector.DIRECTION_BOTH;
ignoreSlopWhenSettling = true; ignoreSlopWhenSettling = true;
@ -139,12 +143,15 @@ public class OverviewSwipeController extends AnimatorListenerAdapter
// The tile can be dragged down to open the task. // The tile can be dragged down to open the task.
mTaskBeingDragged = (TaskView) view; mTaskBeingDragged = (TaskView) view;
directionsToDetectScroll = SwipeDetector.DIRECTION_BOTH; directionsToDetectScroll = SwipeDetector.DIRECTION_BOTH;
mStartingTarget = LauncherLogProto.ItemType.TASK;
} else if (isEventOverHotseat(ev)) { } else if (isEventOverHotseat(ev)) {
// The hotseat is being dragged // The hotseat is being dragged
directionsToDetectScroll = SwipeDetector.DIRECTION_POSITIVE; directionsToDetectScroll = SwipeDetector.DIRECTION_POSITIVE;
mSwipeDownEnabled = false; mSwipeDownEnabled = false;
mStartingTarget = ContainerType.HOTSEAT;
} else { } else {
mNoIntercept = true; mNoIntercept = true;
mStartingTarget = ContainerType.WORKSPACE;
return false; return false;
} }
} }
@ -249,8 +256,9 @@ public class OverviewSwipeController extends AnimatorListenerAdapter
@Override @Override
public void onDragEnd(float velocity, boolean fling) { public void onDragEnd(float velocity, boolean fling) {
final boolean goingToEnd; final boolean goingToEnd;
final int logAction;
if (fling) { if (fling) {
logAction = Touch.FLING;
boolean goingUp = velocity < 0; boolean goingUp = velocity < 0;
if (!goingUp && !mSwipeDownEnabled) { if (!goingUp && !mSwipeDownEnabled) {
goingToEnd = false; goingToEnd = false;
@ -269,6 +277,7 @@ public class OverviewSwipeController extends AnimatorListenerAdapter
goingToEnd = true; goingToEnd = true;
} }
} else { } else {
logAction = Touch.SWIPE;
goingToEnd = mCurrentAnimation.getProgressFraction() > SUCCESS_TRANSITION_PROGRESS; goingToEnd = mCurrentAnimation.getProgressFraction() > SUCCESS_TRANSITION_PROGRESS;
} }
@ -280,7 +289,7 @@ public class OverviewSwipeController extends AnimatorListenerAdapter
progress + velocity * SINGLE_FRAME_MS / Math.abs(mEndDisplacement), 0f, 1f); progress + velocity * SINGLE_FRAME_MS / Math.abs(mEndDisplacement), 0f, 1f);
mCurrentAnimation.setEndAction(() -> onCurrentAnimationEnd(goingToEnd)); mCurrentAnimation.setEndAction(() -> onCurrentAnimationEnd(goingToEnd, logAction));
ValueAnimator anim = mCurrentAnimation.getAnimationPlayer(); ValueAnimator anim = mCurrentAnimation.getAnimationPlayer();
anim.setFloatValues(nextFrameProgress, goingToEnd ? 1f : 0f); anim.setFloatValues(nextFrameProgress, goingToEnd ? 1f : 0f);
@ -289,19 +298,28 @@ public class OverviewSwipeController extends AnimatorListenerAdapter
anim.start(); anim.start();
} }
private void onCurrentAnimationEnd(boolean wasSuccess) { private void onCurrentAnimationEnd(boolean wasSuccess, int logAction) {
// TODO: Might be a good time to log something.
if (mTaskBeingDragged == null) { if (mTaskBeingDragged == null) {
LauncherState state = wasSuccess ? LauncherState state = wasSuccess ?
(mCurrentAnimationIsGoingUp ? ALL_APPS : NORMAL) : OVERVIEW; (mCurrentAnimationIsGoingUp ? ALL_APPS : NORMAL) : OVERVIEW;
mLauncher.getStateManager().goToState(state, false); mLauncher.getStateManager().goToState(state, false);
} else if (wasSuccess) { } else if (wasSuccess) {
if (mCurrentAnimationIsGoingUp) { if (mCurrentAnimationIsGoingUp) {
mRecentsView.onTaskDismissed(mTaskBeingDragged); mRecentsView.onTaskDismissed(mTaskBeingDragged);
} else { } else {
mTaskBeingDragged.launchTask(false); mTaskBeingDragged.launchTask(false);
mLauncher.getUserEventDispatcher().logTaskLaunch(logAction,
Direction.DOWN, mTaskBeingDragged.getTask().getTopComponent());
} }
} }
if (mTaskBeingDragged == null || (wasSuccess && mCurrentAnimationIsGoingUp)) {
mLauncher.getUserEventDispatcher().logStateChangeAction(logAction,
mCurrentAnimationIsGoingUp ? Direction.UP : Direction.DOWN,
mStartingTarget, ContainerType.TASKSWITCHER,
mLauncher.getStateManager().getState().containerType,
mRecentsView.getCurrentPage());
}
mDetector.finishedScrolling(); mDetector.finishedScrolling();
mTaskBeingDragged = null; mTaskBeingDragged = null;
mCurrentAnimation = null; mCurrentAnimation = null;

View File

@ -58,10 +58,12 @@ public class OverviewSwipeUpController extends VerticalSwipeController {
protected void onTransitionComplete(boolean wasFling, boolean stateChanged) { protected void onTransitionComplete(boolean wasFling, boolean stateChanged) {
if (stateChanged) { if (stateChanged) {
// Transition complete. log the action // Transition complete. log the action
mLauncher.getUserEventDispatcher().logActionOnContainer( mLauncher.getUserEventDispatcher().logStateChangeAction(
wasFling ? Touch.FLING : Touch.SWIPE, wasFling ? Touch.FLING : Touch.SWIPE,
Direction.UP, Direction.UP,
ContainerType.OVERVIEW, ContainerType.HOTSEAT,
ContainerType.TASKSWITCHER,
ContainerType.ALLAPPS,
mLauncher.getWorkspace().getCurrentPage()); mLauncher.getWorkspace().getCurrentPage());
} }

View File

@ -50,10 +50,7 @@ import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.launcher3.util.FloatRange; import com.android.launcher3.util.FloatRange;
import com.android.launcher3.util.TouchController; import com.android.launcher3.util.TouchController;
import com.android.quickstep.RecentsModel;
import com.android.quickstep.RecentsView;
import com.android.quickstep.TouchInteractionService; import com.android.quickstep.TouchInteractionService;
import com.android.systemui.shared.recents.model.RecentsTaskLoadPlan;
import java.util.ArrayList; import java.util.ArrayList;
@ -371,9 +368,12 @@ public class TwoStepSwipeController extends AnimatorListenerAdapter
private void onSwipeInteractionCompleted(LauncherState targetState, int logAction) { private void onSwipeInteractionCompleted(LauncherState targetState, int logAction) {
if (targetState != mFromState) { if (targetState != mFromState) {
// Transition complete. log the action // Transition complete. log the action
mLauncher.getUserEventDispatcher().logActionOnContainer(logAction, mLauncher.getUserEventDispatcher().logStateChangeAction(logAction,
mToState == ALL_APPS ? Direction.UP : Direction.DOWN, mToState == ALL_APPS ? Direction.UP : Direction.DOWN,
mStartContainerType, mLauncher.getWorkspace().getCurrentPage()); mStartContainerType,
mFromState.containerType,
mToState.containerType,
mLauncher.getWorkspace().getCurrentPage());
} }
clearState(); clearState();

View File

@ -19,8 +19,13 @@ package com.android.quickstep;
import android.view.HapticFeedbackConstants; import android.view.HapticFeedbackConstants;
import com.android.launcher3.Alarm; import com.android.launcher3.Alarm;
import com.android.launcher3.Launcher;
import com.android.launcher3.OnAlarmListener; import com.android.launcher3.OnAlarmListener;
import com.android.launcher3.Utilities; import com.android.launcher3.Utilities;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.launcher3.userevent.nano.LauncherLogProto.ControlType;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
/** /**
* Responds to quick scrub callbacks to page through and launch recent tasks. * Responds to quick scrub callbacks to page through and launch recent tasks.
@ -42,13 +47,15 @@ public class QuickScrubController implements OnAlarmListener {
private final Alarm mAutoAdvanceAlarm; private final Alarm mAutoAdvanceAlarm;
private final RecentsView mRecentsView; private final RecentsView mRecentsView;
private final Launcher mLauncher;
private boolean mInQuickScrub; private boolean mInQuickScrub;
private int mQuickScrubSection; private int mQuickScrubSection;
private int mStartPage; private int mStartPage;
private boolean mHasAlarmRun; private boolean mHasAlarmRun;
public QuickScrubController(RecentsView recentsView) { public QuickScrubController(Launcher launcher, RecentsView recentsView) {
mLauncher = launcher;
mRecentsView = recentsView; mRecentsView = recentsView;
if (ENABLE_AUTO_ADVANCE) { if (ENABLE_AUTO_ADVANCE) {
mAutoAdvanceAlarm = new Alarm(); mAutoAdvanceAlarm = new Alarm();
@ -61,6 +68,7 @@ public class QuickScrubController implements OnAlarmListener {
mStartPage = startingFromHome ? 0 : mRecentsView.getFirstTaskIndex(); mStartPage = startingFromHome ? 0 : mRecentsView.getFirstTaskIndex();
mQuickScrubSection = 0; mQuickScrubSection = 0;
mHasAlarmRun = false; mHasAlarmRun = false;
mLauncher.getUserEventDispatcher().resetActionDurationMillis();
} }
public void onQuickScrubEnd() { public void onQuickScrubEnd() {
@ -85,6 +93,9 @@ public class QuickScrubController implements OnAlarmListener {
// No page move needed, just launch it // No page move needed, just launch it
launchTaskRunnable.run(); launchTaskRunnable.run();
} }
mLauncher.getUserEventDispatcher().logActionOnControl(Touch.DRAGDROP,
ControlType.QUICK_SCRUB_BUTTON, null, mStartPage == 0 ?
ContainerType.WORKSPACE : ContainerType.APP);
} }
public void onQuickScrubProgress(float progress) { public void onQuickScrubProgress(float progress) {
@ -119,6 +130,9 @@ public class QuickScrubController implements OnAlarmListener {
break; break;
} }
} }
mLauncher.getUserEventDispatcher().logActionOnControl(Touch.FLING,
ControlType.QUICK_SCRUB_BUTTON, null, mStartPage == 0 ?
ContainerType.WORKSPACE : ContainerType.APP);
} }
public void snapToPageForCurrentQuickScrubSection() { public void snapToPageForCurrentQuickScrubSection() {

View File

@ -124,7 +124,7 @@ public class RecentsView extends PagedView implements Insettable {
setClipToOutline(true); setClipToOutline(true);
mLauncher = Launcher.getLauncher(context); mLauncher = Launcher.getLauncher(context);
mQuickScrubController = new QuickScrubController(this); mQuickScrubController = new QuickScrubController(mLauncher, this);
mModel = RecentsModel.getInstance(context); mModel = RecentsModel.getInstance(context);
mScrollState.isRtl = mIsRtl; mScrollState.isRtl = mIsRtl;

View File

@ -59,6 +59,10 @@ import com.android.launcher3.allapps.AllAppsTransitionController;
import com.android.launcher3.anim.AnimationSuccessListener; import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.Interpolators; import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
import com.android.launcher3.util.TraceHelper; import com.android.launcher3.util.TraceHelper;
import com.android.quickstep.TouchConsumer.InteractionType; import com.android.quickstep.TouchConsumer.InteractionType;
import com.android.systemui.shared.recents.model.ThumbnailData; import com.android.systemui.shared.recents.model.ThumbnailData;
@ -603,6 +607,30 @@ public class WindowTransformSwipeHandler extends BaseSwipeInteractionHandler {
} }
animateToProgress(endShift, duration); animateToProgress(endShift, duration);
int direction = Direction.UP;
if (mLauncher.getDeviceProfile().isLandscape) {
direction = Direction.LEFT;
if (mLauncher.getDeviceProfile().isSeascape()) {
direction = Direction.RIGHT;
}
}
int dstContainerType = LauncherLogProto.ContainerType.TASKSWITCHER;
if (Float.compare(endShift, 0) == 0) {
direction = Direction.DOWN;
if (mLauncher.getDeviceProfile().isLandscape) {
direction = Direction.RIGHT;
if (mLauncher.getDeviceProfile().isSeascape()) {
direction = Direction.LEFT;
}
}
dstContainerType = LauncherLogProto.ContainerType.APP;
}
mLauncher.getUserEventDispatcher().logStateChangeAction(
isFling ? Touch.FLING : Touch.SWIPE, direction,
LauncherLogProto.ContainerType.NAVBAR,
LauncherLogProto.ContainerType.APP,
dstContainerType,
0);
} }
/** Animates to the given progress, where 0 is the current app and 1 is overview. */ /** Animates to the given progress, where 0 is the current app and 1 is overview. */

View File

@ -92,7 +92,8 @@ public abstract class AbstractFloatingView extends LinearLayout implements Touch
public final void close(boolean animate) { public final void close(boolean animate) {
animate &= !Utilities.isPowerSaverOn(getContext()); animate &= !Utilities.isPowerSaverOn(getContext());
handleClose(animate); handleClose(animate);
Launcher.getLauncher(getContext()).getUserEventDispatcher().resetElapsedContainerMillis(); Launcher.getLauncher(getContext()).getUserEventDispatcher()
.resetElapsedContainerMillis("container closed");
} }
protected abstract void handleClose(boolean animate); protected abstract void handleClose(boolean animate);

View File

@ -783,7 +783,7 @@ public class Launcher extends BaseActivity
if (!mAppLaunchSuccess) { if (!mAppLaunchSuccess) {
getUserEventDispatcher().logActionCommand(Action.Command.STOP, getUserEventDispatcher().logActionCommand(Action.Command.STOP,
mStateManager.getState().containerType); mStateManager.getState().containerType, -1);
} }
NotificationListener.removeNotificationsChangedListener(); NotificationListener.removeNotificationsChangedListener();
getStateManager().moveToRestState(); getStateManager().moveToRestState();
@ -1280,7 +1280,8 @@ public class Launcher extends BaseActivity
} else if (alreadyOnHome) { } else if (alreadyOnHome) {
Target target = newContainerTarget(mStateManager.getState().containerType); Target target = newContainerTarget(mStateManager.getState().containerType);
target.pageIndex = mWorkspace.getCurrentPage(); target.pageIndex = mWorkspace.getCurrentPage();
ued.logActionCommand(Action.Command.HOME_INTENT, target); ued.logActionCommand(Action.Command.HOME_INTENT, target,
newContainerTarget(ContainerType.WORKSPACE));
} }
// In all these cases, only animate if we're already on home // In all these cases, only animate if we're already on home
@ -1656,7 +1657,8 @@ public class Launcher extends BaseActivity
topView.onBackPressed(); topView.onBackPressed();
} else if (!isInState(NORMAL)) { } else if (!isInState(NORMAL)) {
LauncherState lastState = mStateManager.getLastState(); LauncherState lastState = mStateManager.getLastState();
ued.logActionCommand(Action.Command.BACK, mStateManager.getState().containerType); ued.logActionCommand(Action.Command.BACK, mStateManager.getState().containerType,
lastState.containerType);
mStateManager.goToState(lastState); mStateManager.goToState(lastState);
} else { } else {
// Back button is a no-op here, but give at least some feedback for the button press // Back button is a no-op here, but give at least some feedback for the button press
@ -1682,7 +1684,7 @@ public class Launcher extends BaseActivity
if (v instanceof Workspace) { if (v instanceof Workspace) {
if (isInState(OVERVIEW)) { if (isInState(OVERVIEW)) {
getUserEventDispatcher().logActionOnContainer(LauncherLogProto.Action.Type.TOUCH, getUserEventDispatcher().logActionOnContainer(LauncherLogProto.Action.Touch.TAP,
LauncherLogProto.Action.Direction.NONE, LauncherLogProto.Action.Direction.NONE,
LauncherLogProto.ContainerType.OVERVIEW, mWorkspace.getCurrentPage()); LauncherLogProto.ContainerType.OVERVIEW, mWorkspace.getCurrentPage());
mStateManager.goToState(NORMAL); mStateManager.goToState(NORMAL);
@ -1693,7 +1695,7 @@ public class Launcher extends BaseActivity
if (v instanceof CellLayout) { if (v instanceof CellLayout) {
if (isInState(OVERVIEW)) { if (isInState(OVERVIEW)) {
int page = mWorkspace.indexOfChild(v); int page = mWorkspace.indexOfChild(v);
getUserEventDispatcher().logActionOnContainer(LauncherLogProto.Action.Type.TOUCH, getUserEventDispatcher().logActionOnContainer(LauncherLogProto.Action.Touch.TAP,
LauncherLogProto.Action.Direction.NONE, LauncherLogProto.Action.Direction.NONE,
LauncherLogProto.ContainerType.OVERVIEW, page); LauncherLogProto.ContainerType.OVERVIEW, page);
mWorkspace.snapToPageFromOverView(page); mWorkspace.snapToPageFromOverView(page);

View File

@ -302,7 +302,6 @@ public class LauncherStateManager {
state.onStateTransitionEnd(mLauncher); state.onStateTransitionEnd(mLauncher);
mLauncher.getWorkspace().setClipChildren(!state.disablePageClipping); mLauncher.getWorkspace().setClipChildren(!state.disablePageClipping);
mLauncher.getUserEventDispatcher().resetElapsedContainerMillis();
mLauncher.finishAutoCancelActionMode(); mLauncher.finishAutoCancelActionMode();
if (state == NORMAL) { if (state == NORMAL) {

View File

@ -1679,7 +1679,7 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
if (popupContainer != null) { if (popupContainer != null) {
dragOptions.preDragCondition = popupContainer.createPreDragCondition(); dragOptions.preDragCondition = popupContainer.createPreDragCondition();
mLauncher.getUserEventDispatcher().resetElapsedContainerMillis(); mLauncher.getUserEventDispatcher().resetElapsedContainerMillis("dragging started");
} }
} }

View File

@ -522,7 +522,7 @@ public class Folder extends AbstractFloatingView implements DragSource, View.OnC
onCompleteRunnable = new Runnable() { onCompleteRunnable = new Runnable() {
@Override @Override
public void run() { public void run() {
mLauncher.getUserEventDispatcher().resetElapsedContainerMillis(); mLauncher.getUserEventDispatcher().resetElapsedContainerMillis("folder opened");
} }
}; };
anim.addListener(new AnimatorListenerAdapter() { anim.addListener(new AnimatorListenerAdapter() {

View File

@ -71,7 +71,7 @@ public class LoggerUtils {
switch (action.type) { switch (action.type) {
case Action.Type.TOUCH: case Action.Type.TOUCH:
str += getFieldName(action.touch, Action.Touch.class); str += getFieldName(action.touch, Action.Touch.class);
if (action.touch == Action.Touch.SWIPE) { if (action.touch == Action.Touch.SWIPE || action.touch == Action.Touch.FLING) {
str += " direction=" + getFieldName(action.dir, Action.Direction.class); str += " direction=" + getFieldName(action.dir, Action.Direction.class);
} }
return str; return str;
@ -114,11 +114,20 @@ public class LoggerUtils {
if (t.intentHash != 0) { if (t.intentHash != 0) {
typeStr += ", intentHash=" + t.intentHash; typeStr += ", intentHash=" + t.intentHash;
} }
if (t.packageNameHash != 0 || t.componentHash != 0 || t.intentHash != 0) { if ((t.packageNameHash != 0 || t.componentHash != 0 || t.intentHash != 0) &&
typeStr += ", predictiveRank=" + t.predictedRank; t.itemType != ItemType.TASK) {
typeStr += ", predictiveRank=" + t.predictedRank + ", grid(" + t.gridX + "," + t.gridY
+ "), span(" + t.spanX + "," + t.spanY
+ "), pageIdx=" + t.pageIndex;
} }
return typeStr + ", grid(" + t.gridX + "," + t.gridY + "), span(" + t.spanX + "," + t.spanY return typeStr;
+ "), pageIdx=" + t.pageIndex; }
public static Target newItemTarget(int itemType) {
Target t = newTarget(Target.Type.ITEM);
t.itemType = itemType;
return t;
} }
public static Target newItemTarget(View v) { public static Target newItemTarget(View v) {

View File

@ -32,6 +32,7 @@ import com.android.launcher3.ItemInfo;
import com.android.launcher3.R; import com.android.launcher3.R;
import com.android.launcher3.Utilities; import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action; import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.launcher3.userevent.nano.LauncherLogProto.LauncherEvent; import com.android.launcher3.userevent.nano.LauncherLogProto.LauncherEvent;
@ -158,9 +159,23 @@ public class UserEventDispatcher {
dispatchUserEvent(event, intent); dispatchUserEvent(event, intent);
} }
public void logTaskLaunch(int action, int direction, ComponentName componentName){
LauncherEvent event = newLauncherEvent(newTouchAction(action), // TAP or SWIPE
newTarget(Target.Type.ITEM));
if (action == Action.Touch.SWIPE || action == Action.Touch.FLING) {
event.action.dir = direction;
}
event.srcTarget[0].itemType = LauncherLogProto.ItemType.TASK;
fillComponentInfo(event.srcTarget[0], componentName);
dispatchUserEvent(event, null);
}
protected void fillIntentInfo(Target target, Intent intent) { protected void fillIntentInfo(Target target, Intent intent) {
target.intentHash = intent.hashCode(); target.intentHash = intent.hashCode();
ComponentName cn = intent.getComponent(); fillComponentInfo(target, intent.getComponent());
}
private void fillComponentInfo(Target target, ComponentName cn) {
if (cn != null) { if (cn != null) {
target.packageNameHash = (mUuidStr + cn.getPackageName()).hashCode(); target.packageNameHash = (mUuidStr + cn.getPackageName()).hashCode();
target.componentHash = (mUuidStr + cn.flattenToString()).hashCode(); target.componentHash = (mUuidStr + cn.flattenToString()).hashCode();
@ -176,19 +191,29 @@ public class UserEventDispatcher {
dispatchUserEvent(event, null); dispatchUserEvent(event, null);
} }
public void logActionCommand(int command, int containerType) { public void logActionCommand(int command, Target srcTarget) {
logActionCommand(command, newContainerTarget(containerType)); logActionCommand(command, srcTarget, null);
} }
public void logActionCommand(int command, Target target) { public void logActionCommand(int command, int srcContainerType, int dstContainerType) {
LauncherEvent event = newLauncherEvent(newCommandAction(command), target); logActionCommand(command, newContainerTarget(srcContainerType),
dstContainerType >=0 ? newContainerTarget(dstContainerType) : null);
}
public void logActionCommand(int command, Target srcTarget, Target dstTarget) {
LauncherEvent event = newLauncherEvent(newCommandAction(command), srcTarget);
if (dstTarget != null) {
event.destTarget = new Target[1];
event.destTarget[0] = dstTarget;
event.action.isStateChange = true;
}
dispatchUserEvent(event, null); dispatchUserEvent(event, null);
} }
/** /**
* TODO: Make this function work when a container view is passed as the 2nd param. * TODO: Make this function work when a container view is passed as the 2nd param.
*/ */
public void logActionCommand(int command, View itemView, int containerType) { public void logActionCommand(int command, View itemView, int srcContainerType) {
LauncherEvent event = newLauncherEvent(newCommandAction(command), LauncherEvent event = newLauncherEvent(newCommandAction(command),
newItemTarget(itemView), newTarget(Target.Type.CONTAINER)); newItemTarget(itemView), newTarget(Target.Type.CONTAINER));
@ -196,22 +221,39 @@ public class UserEventDispatcher {
// TODO: Remove the following two lines once fillInLogContainerData can take in a // TODO: Remove the following two lines once fillInLogContainerData can take in a
// container view. // container view.
event.srcTarget[0].type = Target.Type.CONTAINER; event.srcTarget[0].type = Target.Type.CONTAINER;
event.srcTarget[0].containerType = containerType; event.srcTarget[0].containerType = srcContainerType;
} }
dispatchUserEvent(event, null); dispatchUserEvent(event, null);
} }
public void logActionOnControl(int action, int controlType) { public void logActionOnControl(int action, int controlType) {
logActionOnControl(action, controlType, null); logActionOnControl(action, controlType, null, -1);
}
public void logActionOnControl(int action, int controlType, int parentContainerType) {
logActionOnControl(action, controlType, null, parentContainerType);
} }
public void logActionOnControl(int action, int controlType, @Nullable View controlInContainer) { public void logActionOnControl(int action, int controlType, @Nullable View controlInContainer) {
logActionOnControl(action, controlType, controlInContainer, -1);
}
public void logActionOnControl(int action, int controlType, @Nullable View controlInContainer,
int parentContainerType) {
final LauncherEvent event = controlInContainer == null final LauncherEvent event = controlInContainer == null
? newLauncherEvent(newTouchAction(action), newTarget(Target.Type.CONTROL)) ? newLauncherEvent(newTouchAction(action), newTarget(Target.Type.CONTROL))
: newLauncherEvent(newTouchAction(action), newTarget(Target.Type.CONTROL), : newLauncherEvent(newTouchAction(action), newTarget(Target.Type.CONTROL),
newTarget(Target.Type.CONTAINER)); newTarget(Target.Type.CONTAINER));
event.srcTarget[0].controlType = controlType; event.srcTarget[0].controlType = controlType;
fillInLogContainerData(event, controlInContainer); if (controlInContainer != null) {
fillInLogContainerData(event, controlInContainer);
}
if (parentContainerType >= 0) {
event.srcTarget[1].containerType = parentContainerType;
}
if (action == Action.Touch.DRAGDROP) {
event.actionDurationMillis = SystemClock.uptimeMillis() - mActionDurationMillis;
}
dispatchUserEvent(event, null); dispatchUserEvent(event, null);
} }
@ -232,10 +274,35 @@ public class UserEventDispatcher {
event.action.dir = dir; event.action.dir = dir;
event.srcTarget[0].pageIndex = pageIndex; event.srcTarget[0].pageIndex = pageIndex;
dispatchUserEvent(event, null); dispatchUserEvent(event, null);
}
if (action == Action.Touch.SWIPE) { /**
resetElapsedContainerMillis(); * Used primarily for swipe up and down when state changes when swipe up happens from the
* navbar bezel, the {@param srcChildContainerType} is NAVBAR and
* {@param srcParentContainerType} is either one of the two
* (1) WORKSPACE: if the launcher the foreground activity
* (2) APP: if another app was the foreground activity
*/
public void logStateChangeAction(int action, int dir, int srcChildTargetType,
int srcParentContainerType, int dstContainerType,
int pageIndex) {
LauncherEvent event;
if (srcChildTargetType == LauncherLogProto.ItemType.TASK) {
event = newLauncherEvent(newTouchAction(action),
newItemTarget(srcChildTargetType),
newContainerTarget(srcParentContainerType));
} else {
event = newLauncherEvent(newTouchAction(action),
newContainerTarget(srcChildTargetType),
newContainerTarget(srcParentContainerType));
} }
event.destTarget = new Target[1];
event.destTarget[0] = newContainerTarget(dstContainerType);
event.action.dir = dir;
event.action.isStateChange = true;
event.srcTarget[0].pageIndex = pageIndex;
dispatchUserEvent(event, null);
resetElapsedContainerMillis("state changed");
} }
public void logActionOnItem(int action, int dir, int itemType) { public void logActionOnItem(int action, int dir, int itemType) {
@ -257,7 +324,7 @@ public class UserEventDispatcher {
provider.fillInLogContainerData(icon, info, event.srcTarget[0], event.srcTarget[1]); provider.fillInLogContainerData(icon, info, event.srcTarget[0], event.srcTarget[1]);
dispatchUserEvent(event, null); dispatchUserEvent(event, null);
resetElapsedContainerMillis(); resetElapsedContainerMillis("deep shortcut open");
} }
/* Currently we are only interested in whether this event happens or not and don't /* Currently we are only interested in whether this event happens or not and don't
@ -290,9 +357,15 @@ public class UserEventDispatcher {
/** /**
* Currently logs following containers: workspace, allapps, widget tray. * Currently logs following containers: workspace, allapps, widget tray.
* @param reason
*/ */
public final void resetElapsedContainerMillis() { public final void resetElapsedContainerMillis(String reason) {
mElapsedContainerMillis = SystemClock.uptimeMillis(); mElapsedContainerMillis = SystemClock.uptimeMillis();
if (!IS_VERBOSE) {
return;
}
Log.d(TAG, "resetElapsedContainerMillis reason=" + reason);
} }
public final void resetElapsedSessionMillis() { public final void resetElapsedSessionMillis() {
@ -321,13 +394,13 @@ public class UserEventDispatcher {
log += "\n Destination " + getTargetsStr(ev.destTarget); log += "\n Destination " + getTargetsStr(ev.destTarget);
} }
log += String.format(Locale.US, log += String.format(Locale.US,
"\n Elapsed container %d ms session %d ms action %d ms", "\n Elapsed container %d ms, session %d ms, action %d ms",
ev.elapsedContainerMillis, ev.elapsedContainerMillis,
ev.elapsedSessionMillis, ev.elapsedSessionMillis,
ev.actionDurationMillis); ev.actionDurationMillis);
log += "\n isInLandscapeMode " + ev.isInLandscapeMode; log += "\n isInLandscapeMode " + ev.isInLandscapeMode;
log += "\n isInMultiWindowMode " + ev.isInMultiWindowMode; log += "\n isInMultiWindowMode " + ev.isInMultiWindowMode;
log += "\n"; log += "\n\n";
Log.d(TAG, log); Log.d(TAG, log);
} }