Merge "Fixing window transform not changing monotonically with shift" into ub-launcher3-master
diff --git a/protos/launcher_log.proto b/protos/launcher_log.proto
index de74fce..3b983d2 100644
--- a/protos/launcher_log.proto
+++ b/protos/launcher_log.proto
@@ -68,6 +68,7 @@
SEARCHBOX = 6;
EDITTEXT = 7;
NOTIFICATION = 8;
+ TASK = 9; // Each page of Recents UI (QuickStep)
}
// Used to define what type of container a Target would represent.
@@ -78,11 +79,14 @@
FOLDER = 3;
ALLAPPS = 4;
WIDGETS = 5;
- OVERVIEW = 6;
+ OVERVIEW = 6; // Zoomed out workspace (without QuickStep)
PREDICTION = 7;
SEARCHRESULT = 8;
DEEPSHORTCUTS = 9;
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.
@@ -100,6 +104,7 @@
HOME_INTENT = 10; // Deprecated, use enum Command instead
BACK_BUTTON = 11; // Deprecated, use enum Command instead
// GO_TO_PLAYSTORE
+ QUICK_SCRUB_BUTTON = 12;
}
// Used to define the action component of the LauncherEvent.
@@ -141,6 +146,7 @@
optional Command command = 4;
// Log if the action was performed on outside of the container
optional bool is_outside = 5;
+ optional bool is_state_change = 6;
}
//
@@ -150,7 +156,6 @@
//
message LauncherEvent {
required Action action = 1;
-
// List of targets that touch actions can be operated on.
repeated Target src_target = 2;
repeated Target dest_target = 3;
diff --git a/quickstep/src/com/android/launcher3/uioverrides/EdgeSwipeController.java b/quickstep/src/com/android/launcher3/uioverrides/EdgeSwipeController.java
index bf55bd6..3d2830d 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/EdgeSwipeController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/EdgeSwipeController.java
@@ -30,8 +30,12 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherState;
import com.android.launcher3.anim.SpringAnimationHandler;
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.quickstep.RecentsView;
@@ -100,6 +104,10 @@
return isTransitionFlipped() ? DIRECTION_NEGATIVE : DIRECTION_POSITIVE;
}
+ public EdgeSwipeController(Launcher l, LauncherState baseState) {
+ super(l, baseState);
+ }
+
@Override
protected boolean isTransitionFlipped() {
return mLauncher.getDeviceProfile().isSeascape();
@@ -117,8 +125,21 @@
builder.addTaggedData(319/*APP_TRANSITION_DELAY_MS*/,
0/* zero time */);
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
diff --git a/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
index 5706d32..9ba2308 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
@@ -40,7 +40,7 @@
| FLAG_DISABLE_RESTORE;
public OverviewState(int id) {
- super(id, ContainerType.WORKSPACE, OVERVIEW_TRANSITION_MS, STATE_FLAGS);
+ super(id, ContainerType.TASKSWITCHER, OVERVIEW_TRANSITION_MS, STATE_FLAGS);
}
@Override
diff --git a/quickstep/src/com/android/launcher3/uioverrides/OverviewSwipeController.java b/quickstep/src/com/android/launcher3/uioverrides/OverviewSwipeController.java
index 1fd541a..468a561 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/OverviewSwipeController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/OverviewSwipeController.java
@@ -31,6 +31,10 @@
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.dragndrop.DragLayer;
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.quickstep.RecentsView;
import com.android.quickstep.TaskView;
@@ -70,6 +74,7 @@
private float mDisplacementShift;
private float mProgressMultiplier;
private float mEndDisplacement;
+ private int mStartingTarget;
private TaskView mTaskBeingDragged;
@@ -120,7 +125,6 @@
// calling the callbacks.
final int directionsToDetectScroll;
boolean ignoreSlopWhenSettling = false;
-
if (mCurrentAnimation != null) {
directionsToDetectScroll = SwipeDetector.DIRECTION_BOTH;
ignoreSlopWhenSettling = true;
@@ -139,12 +143,15 @@
// The tile can be dragged down to open the task.
mTaskBeingDragged = (TaskView) view;
directionsToDetectScroll = SwipeDetector.DIRECTION_BOTH;
+ mStartingTarget = LauncherLogProto.ItemType.TASK;
} else if (isEventOverHotseat(ev)) {
// The hotseat is being dragged
directionsToDetectScroll = SwipeDetector.DIRECTION_POSITIVE;
mSwipeDownEnabled = false;
+ mStartingTarget = ContainerType.HOTSEAT;
} else {
mNoIntercept = true;
+ mStartingTarget = ContainerType.WORKSPACE;
return false;
}
}
@@ -249,8 +256,9 @@
@Override
public void onDragEnd(float velocity, boolean fling) {
final boolean goingToEnd;
-
+ final int logAction;
if (fling) {
+ logAction = Touch.FLING;
boolean goingUp = velocity < 0;
if (!goingUp && !mSwipeDownEnabled) {
goingToEnd = false;
@@ -269,6 +277,7 @@
goingToEnd = true;
}
} else {
+ logAction = Touch.SWIPE;
goingToEnd = mCurrentAnimation.getProgressFraction() > SUCCESS_TRANSITION_PROGRESS;
}
@@ -280,7 +289,7 @@
progress + velocity * SINGLE_FRAME_MS / Math.abs(mEndDisplacement), 0f, 1f);
- mCurrentAnimation.setEndAction(() -> onCurrentAnimationEnd(goingToEnd));
+ mCurrentAnimation.setEndAction(() -> onCurrentAnimationEnd(goingToEnd, logAction));
ValueAnimator anim = mCurrentAnimation.getAnimationPlayer();
anim.setFloatValues(nextFrameProgress, goingToEnd ? 1f : 0f);
@@ -289,19 +298,28 @@
anim.start();
}
- private void onCurrentAnimationEnd(boolean wasSuccess) {
- // TODO: Might be a good time to log something.
+ private void onCurrentAnimationEnd(boolean wasSuccess, int logAction) {
if (mTaskBeingDragged == null) {
LauncherState state = wasSuccess ?
(mCurrentAnimationIsGoingUp ? ALL_APPS : NORMAL) : OVERVIEW;
mLauncher.getStateManager().goToState(state, false);
+
} else if (wasSuccess) {
if (mCurrentAnimationIsGoingUp) {
mRecentsView.onTaskDismissed(mTaskBeingDragged);
} else {
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();
mTaskBeingDragged = null;
mCurrentAnimation = null;
diff --git a/quickstep/src/com/android/launcher3/uioverrides/OverviewSwipeUpController.java b/quickstep/src/com/android/launcher3/uioverrides/OverviewSwipeUpController.java
index 3ae8f41..4fb3886 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/OverviewSwipeUpController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/OverviewSwipeUpController.java
@@ -58,10 +58,12 @@
protected void onTransitionComplete(boolean wasFling, boolean stateChanged) {
if (stateChanged) {
// Transition complete. log the action
- mLauncher.getUserEventDispatcher().logActionOnContainer(
+ mLauncher.getUserEventDispatcher().logStateChangeAction(
wasFling ? Touch.FLING : Touch.SWIPE,
Direction.UP,
- ContainerType.OVERVIEW,
+ ContainerType.HOTSEAT,
+ ContainerType.TASKSWITCHER,
+ ContainerType.ALLAPPS,
mLauncher.getWorkspace().getCurrentPage());
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/TwoStepSwipeController.java b/quickstep/src/com/android/launcher3/uioverrides/TwoStepSwipeController.java
index fb59946..2695054 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/TwoStepSwipeController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/TwoStepSwipeController.java
@@ -50,10 +50,7 @@
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.launcher3.util.FloatRange;
import com.android.launcher3.util.TouchController;
-import com.android.quickstep.RecentsModel;
-import com.android.quickstep.RecentsView;
import com.android.quickstep.TouchInteractionService;
-import com.android.systemui.shared.recents.model.RecentsTaskLoadPlan;
import java.util.ArrayList;
@@ -371,9 +368,12 @@
private void onSwipeInteractionCompleted(LauncherState targetState, int logAction) {
if (targetState != mFromState) {
// Transition complete. log the action
- mLauncher.getUserEventDispatcher().logActionOnContainer(logAction,
+ mLauncher.getUserEventDispatcher().logStateChangeAction(logAction,
mToState == ALL_APPS ? Direction.UP : Direction.DOWN,
- mStartContainerType, mLauncher.getWorkspace().getCurrentPage());
+ mStartContainerType,
+ mFromState.containerType,
+ mToState.containerType,
+ mLauncher.getWorkspace().getCurrentPage());
}
clearState();
diff --git a/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java b/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java
index 19e1cca..604b60b 100644
--- a/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java
+++ b/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java
@@ -21,6 +21,7 @@
import static android.view.MotionEvent.ACTION_POINTER_UP;
import static android.view.MotionEvent.ACTION_UP;
import static android.view.MotionEvent.INVALID_POINTER_ID;
+
import static com.android.quickstep.RemoteRunnable.executeSafely;
import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_BACK;
import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_NONE;
@@ -211,7 +212,7 @@
notifyGestureStarted();
}
- } else {
+ } else if (mInteractionHandler != null) {
// Move
mInteractionHandler.updateDisplacement(displacement - mStartDisplacement);
}
@@ -322,7 +323,7 @@
switchToMainChoreographer();
}
});
- handler.initWhenReady(mMainThreadExecutor);
+ handler.initWhenReady();
Runnable startActivity = () -> ActivityManagerWrapper.getInstance()
.startRecentsActivity(mHomeIntent,
@@ -338,7 +339,7 @@
RemoteAnimationTargetCompat[] apps, Rect homeContentInsets,
Rect minimizedHomeBounds) {
if (mInteractionHandler == handler) {
- handler.setRecentsAnimation(controller, apps, homeContentInsets,
+ handler.onRecentsAnimationStart(controller, apps, homeContentInsets,
minimizedHomeBounds);
} else {
controller.finish(false /* toHome */);
@@ -357,7 +358,7 @@
public void onAnimationCanceled() {
if (mInteractionHandler == handler) {
- handler.setRecentsAnimation(null, null, null, null);
+ handler.onRecentsAnimationCanceled();
}
}
}, null, null);
@@ -381,7 +382,7 @@
* the animation can still be running.
*/
private void finishTouchTracking() {
- if (mTouchThresholdCrossed) {
+ if (mTouchThresholdCrossed && mInteractionHandler != null) {
mVelocityTracker.computeCurrentVelocity(1000,
ViewConfiguration.get(this).getScaledMaximumFlingVelocity());
diff --git a/quickstep/src/com/android/quickstep/QuickScrubController.java b/quickstep/src/com/android/quickstep/QuickScrubController.java
index bda9688..f28d51c 100644
--- a/quickstep/src/com/android/quickstep/QuickScrubController.java
+++ b/quickstep/src/com/android/quickstep/QuickScrubController.java
@@ -19,8 +19,13 @@
import android.view.HapticFeedbackConstants;
import com.android.launcher3.Alarm;
+import com.android.launcher3.Launcher;
import com.android.launcher3.OnAlarmListener;
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.
@@ -42,13 +47,15 @@
private final Alarm mAutoAdvanceAlarm;
private final RecentsView mRecentsView;
+ private final Launcher mLauncher;
private boolean mInQuickScrub;
private int mQuickScrubSection;
private int mStartPage;
private boolean mHasAlarmRun;
- public QuickScrubController(RecentsView recentsView) {
+ public QuickScrubController(Launcher launcher, RecentsView recentsView) {
+ mLauncher = launcher;
mRecentsView = recentsView;
if (ENABLE_AUTO_ADVANCE) {
mAutoAdvanceAlarm = new Alarm();
@@ -61,6 +68,7 @@
mStartPage = startingFromHome ? 0 : mRecentsView.getFirstTaskIndex();
mQuickScrubSection = 0;
mHasAlarmRun = false;
+ mLauncher.getUserEventDispatcher().resetActionDurationMillis();
}
public void onQuickScrubEnd() {
@@ -85,6 +93,9 @@
// No page move needed, just launch it
launchTaskRunnable.run();
}
+ mLauncher.getUserEventDispatcher().logActionOnControl(Touch.DRAGDROP,
+ ControlType.QUICK_SCRUB_BUTTON, null, mStartPage == 0 ?
+ ContainerType.WORKSPACE : ContainerType.APP);
}
public void onQuickScrubProgress(float progress) {
@@ -119,6 +130,9 @@
break;
}
}
+ mLauncher.getUserEventDispatcher().logActionOnControl(Touch.FLING,
+ ControlType.QUICK_SCRUB_BUTTON, null, mStartPage == 0 ?
+ ContainerType.WORKSPACE : ContainerType.APP);
}
public void snapToPageForCurrentQuickScrubSection() {
diff --git a/quickstep/src/com/android/quickstep/RecentsView.java b/quickstep/src/com/android/quickstep/RecentsView.java
index cb510c8..c400ffd 100644
--- a/quickstep/src/com/android/quickstep/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/RecentsView.java
@@ -16,6 +16,10 @@
package com.android.quickstep;
+import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.quickstep.TaskView.CURVE_FACTOR;
+import static com.android.quickstep.TaskView.CURVE_INTERPOLATOR;
+
import android.animation.LayoutTransition;
import android.content.Context;
import android.graphics.Bitmap;
@@ -54,10 +58,6 @@
import java.util.ArrayList;
-import static com.android.launcher3.LauncherState.NORMAL;
-import static com.android.quickstep.TaskView.CURVE_FACTOR;
-import static com.android.quickstep.TaskView.CURVE_INTERPOLATOR;
-
/**
* A list of recent tasks.
*/
@@ -108,6 +108,8 @@
private Matrix mFadeMatrix;
private boolean mScrimOnLeft;
+ private boolean mFirstTaskIconScaledDown = false;
+
public RecentsView(Context context) {
this(context, null);
}
@@ -124,7 +126,7 @@
setClipToOutline(true);
mLauncher = Launcher.getLauncher(context);
- mQuickScrubController = new QuickScrubController(this);
+ mQuickScrubController = new QuickScrubController(mLauncher, this);
mModel = RecentsModel.getInstance(context);
mScrollState.isRtl = mIsRtl;
@@ -298,6 +300,7 @@
taskView.setAlpha(1f);
loader.loadTaskData(task);
}
+ applyIconScale(false /* animate */);
if (oldChildCount != getChildCount()) {
mQuickScrubController.snapToPageForCurrentQuickScrubSection();
@@ -486,6 +489,26 @@
return mQuickScrubController;
}
+ public void setFirstTaskIconScaledDown(boolean isScaledDown, boolean animate) {
+ if (mFirstTaskIconScaledDown == isScaledDown) {
+ return;
+ }
+ mFirstTaskIconScaledDown = isScaledDown;
+ applyIconScale(animate);
+ }
+
+ private void applyIconScale(boolean animate) {
+ float scale = mFirstTaskIconScaledDown ? 0 : 1;
+ TaskView firstTask = (TaskView) getChildAt(mFirstTaskIndex);
+ if (firstTask != null) {
+ if (animate) {
+ firstTask.animateIconToScale(scale);
+ } else {
+ firstTask.setIconScale(scale);
+ }
+ }
+ }
+
@Override
public void draw(Canvas canvas) {
if (mScrim == null) {
diff --git a/quickstep/src/com/android/quickstep/TaskView.java b/quickstep/src/com/android/quickstep/TaskView.java
index 8865a42..f21742a 100644
--- a/quickstep/src/com/android/quickstep/TaskView.java
+++ b/quickstep/src/com/android/quickstep/TaskView.java
@@ -19,7 +19,6 @@
import static com.android.quickstep.RecentsView.SCROLL_TYPE_TASK;
import static com.android.quickstep.RecentsView.SCROLL_TYPE_WORKSPACE;
-import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.app.ActivityOptions;
import android.content.Context;
@@ -28,7 +27,6 @@
import android.graphics.Rect;
import android.os.Handler;
import android.util.AttributeSet;
-import android.util.Property;
import android.view.View;
import android.view.ViewOutlineProvider;
import android.widget.FrameLayout;
@@ -68,23 +66,9 @@
private static final long SCALE_ICON_DURATION = 120;
- private static final Property<TaskView, Float> SCALE_ICON_PROPERTY =
- new Property<TaskView, Float>(Float.TYPE, "scale_icon") {
- @Override
- public Float get(TaskView taskView) {
- return taskView.mIconScale;
- }
-
- @Override
- public void set(TaskView taskView, Float iconScale) {
- taskView.setIconScale(iconScale);
- }
- };
-
private Task mTask;
private TaskThumbnailView mSnapshotView;
private ImageView mIconView;
- private float mIconScale = 1f;
public TaskView(Context context) {
this(context, null);
@@ -185,16 +169,13 @@
}
public void animateIconToScale(float scale) {
- ObjectAnimator.ofFloat(this, SCALE_ICON_PROPERTY, scale)
- .setDuration(SCALE_ICON_DURATION).start();
+ mIconView.animate().scaleX(scale).scaleY(scale).setDuration(SCALE_ICON_DURATION).start();
}
protected void setIconScale(float iconScale) {
- mIconScale = iconScale;
- if (mIconView != null) {
- mIconView.setScaleX(mIconScale);
- mIconView.setScaleY(mIconScale);
- }
+ mIconView.animate().cancel();
+ mIconView.setScaleX(iconScale);
+ mIconView.setScaleY(iconScale);
}
@Override
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 8cd2c02..91ea29b 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -37,6 +37,7 @@
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
+import android.util.SparseArray;
import android.view.Choreographer;
import android.view.MotionEvent;
import android.view.View;
@@ -47,6 +48,7 @@
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.R;
import com.android.launcher3.uioverrides.UiFactory;
+import com.android.launcher3.util.TraceHelper;
import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.shared.recents.ISystemUiProxy;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -58,6 +60,15 @@
@TargetApi(Build.VERSION_CODES.O)
public class TouchInteractionService extends Service {
+ private static final SparseArray<String> sMotionEventNames;
+
+ static {
+ sMotionEventNames = new SparseArray<>(3);
+ sMotionEventNames.put(ACTION_DOWN, "ACTION_DOWN");
+ sMotionEventNames.put(ACTION_UP, "ACTION_UP");
+ sMotionEventNames.put(ACTION_CANCEL, "ACTION_CANCEL");
+ }
+
public static final int EDGE_NAV_BAR = 1 << 8;
private static final String TAG = "TouchInteractionService";
@@ -71,12 +82,19 @@
@Override
public void onPreMotionEvent(@HitTarget int downHitTarget) throws RemoteException {
+ TraceHelper.beginSection("SysUiBinder");
onBinderPreMotionEvent(downHitTarget);
+ TraceHelper.partitionSection("SysUiBinder", "Down target " + downHitTarget);
}
@Override
public void onMotionEvent(MotionEvent ev) {
mEventQueue.queue(ev);
+
+ String name = sMotionEventNames.get(ev.getActionMasked());
+ if (name != null){
+ TraceHelper.partitionSection("SysUiBinder", name);
+ }
}
@Override
@@ -93,12 +111,14 @@
@Override
public void onQuickSwitch() {
mEventQueue.onQuickSwitch();
+ TraceHelper.endSection("SysUiBinder", "onQuickSwitch");
}
@Override
public void onQuickScrubStart() {
mEventQueue.onQuickScrubStart();
sQuickScrubEnabled = true;
+ TraceHelper.partitionSection("SysUiBinder", "onQuickScrubStart");
}
@Override
@@ -109,6 +129,7 @@
@Override
public void onQuickScrubEnd() {
mEventQueue.onQuickScrubEnd();
+ TraceHelper.endSection("SysUiBinder", "onQuickScrubEnd");
sQuickScrubEnabled = false;
}
};
diff --git a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
index ecea314..ab564ed 100644
--- a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
+++ b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
@@ -60,6 +60,10 @@
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
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.quickstep.TouchConsumer.InteractionType;
import com.android.systemui.shared.recents.model.ThumbnailData;
@@ -79,31 +83,35 @@
// Launcher UI related states
private static final int STATE_LAUNCHER_PRESENT = 1 << 0;
- private static final int STATE_LAUNCHER_DRAWN = 1 << 1;
- private static final int STATE_ACTIVITY_MULTIPLIER_COMPLETE = 1 << 2;
+ private static final int STATE_LAUNCHER_STARTED = 1 << 1;
+ private static final int STATE_LAUNCHER_DRAWN = 1 << 2;
+ private static final int STATE_ACTIVITY_MULTIPLIER_COMPLETE = 1 << 3;
// Internal initialization states
- private static final int STATE_APP_CONTROLLER_RECEIVED = 1 << 3;
+ private static final int STATE_APP_CONTROLLER_RECEIVED = 1 << 4;
// Interaction finish states
- private static final int STATE_SCALED_CONTROLLER_RECENTS = 1 << 4;
- private static final int STATE_SCALED_CONTROLLER_APP = 1 << 5;
+ private static final int STATE_SCALED_CONTROLLER_RECENTS = 1 << 5;
+ private static final int STATE_SCALED_CONTROLLER_APP = 1 << 6;
- private static final int STATE_HANDLER_INVALIDATED = 1 << 6;
- private static final int STATE_GESTURE_STARTED = 1 << 7;
+ private static final int STATE_HANDLER_INVALIDATED = 1 << 7;
+ private static final int STATE_GESTURE_STARTED = 1 << 8;
+ private static final int STATE_GESTURE_CANCELLED = 1 << 9;
// States for quick switch/scrub
- private static final int STATE_SWITCH_TO_SCREENSHOT_COMPLETE = 1 << 8;
- private static final int STATE_QUICK_SWITCH = 1 << 9;
- private static final int STATE_QUICK_SCRUB_START = 1 << 10;
- private static final int STATE_QUICK_SCRUB_END = 1 << 11;
+ private static final int STATE_SWITCH_TO_SCREENSHOT_COMPLETE = 1 << 10;
+ private static final int STATE_QUICK_SWITCH = 1 << 11;
+ private static final int STATE_QUICK_SCRUB_START = 1 << 12;
+ private static final int STATE_QUICK_SCRUB_END = 1 << 13;
private static final int LAUNCHER_UI_STATES =
- STATE_LAUNCHER_PRESENT | STATE_LAUNCHER_DRAWN | STATE_ACTIVITY_MULTIPLIER_COMPLETE;
+ STATE_LAUNCHER_PRESENT | STATE_LAUNCHER_DRAWN | STATE_ACTIVITY_MULTIPLIER_COMPLETE
+ | STATE_LAUNCHER_STARTED;
// For debugging, keep in sync with above states
private static final String[] STATES = new String[] {
"STATE_LAUNCHER_PRESENT",
+ "STATE_LAUNCHER_STARTED",
"STATE_LAUNCHER_DRAWN",
"STATE_ACTIVITY_MULTIPLIER_COMPLETE",
"STATE_APP_CONTROLLER_RECEIVED",
@@ -111,6 +119,7 @@
"STATE_SCALED_CONTROLLER_APP",
"STATE_HANDLER_INVALIDATED",
"STATE_GESTURE_STARTED",
+ "STATE_GESTURE_CANCELLED",
"STATE_SWITCH_TO_SCREENSHOT_COMPLETE",
"STATE_QUICK_SWITCH",
"STATE_QUICK_SCRUB_START",
@@ -201,6 +210,8 @@
this::launcherFrameDrawn);
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_GESTURE_STARTED,
this::notifyGestureStarted);
+ mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_LAUNCHER_STARTED
+ | STATE_GESTURE_CANCELLED, this::resetStateForAnimationCancel);
mStateCallback.addCallback(STATE_SCALED_CONTROLLER_APP | STATE_APP_CONTROLLER_RECEIVED,
this::resumeLastTask);
@@ -310,37 +321,53 @@
// For the duration of the gesture, lock the screen orientation to ensure that we do not
// rotate mid-quickscrub
mLauncher.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);
+ mRecentsView = mLauncher.getOverviewPanel();
+ mQuickScrubController = mRecentsView.getQuickScrubController();
+ mLauncherLayoutListener = new LauncherLayoutListener(mLauncher);
+ mStateCallback.setState(STATE_LAUNCHER_PRESENT);
+ if (alreadyOnHome) {
+ onLauncherStart(launcher);
+ } else {
+ launcher.setOnStartCallback(this::onLauncherStart);
+ }
+ return true;
+ }
+
+ private void onLauncherStart(final Launcher launcher) {
+ if (mLauncher != launcher) {
+ return;
+ }
+ if ((mStateCallback.getState() & STATE_HANDLER_INVALIDATED) != 0) {
+ return;
+ }
+
+ mStateCallback.setState(STATE_LAUNCHER_STARTED);
LauncherState startState = mLauncher.getStateManager().getState();
if (startState.disableRestore) {
startState = mLauncher.getStateManager().getRestState();
}
mLauncher.getStateManager().setRestState(startState);
- AbstractFloatingView.closeAllOpenViews(launcher, alreadyOnHome);
+ AbstractFloatingView.closeAllOpenViews(mLauncher, mWasLauncherAlreadyVisible);
- mRecentsView = mLauncher.getOverviewPanel();
- mQuickScrubController = mRecentsView.getQuickScrubController();
- mLauncherLayoutListener = new LauncherLayoutListener(mLauncher);
- final int state;
if (mWasLauncherAlreadyVisible) {
DeviceProfile dp = mLauncher.getDeviceProfile();
long accuracy = 2 * Math.max(dp.widthPx, dp.heightPx);
- mLauncherTransitionController = launcher.getStateManager()
+ mLauncherTransitionController = mLauncher.getStateManager()
.createAnimationToNewWorkspace(OVERVIEW, accuracy);
mLauncherTransitionController.dispatchOnStart();
mLauncherTransitionController.setPlayFraction(mCurrentShift.value);
- state = STATE_ACTIVITY_MULTIPLIER_COMPLETE | STATE_LAUNCHER_DRAWN
- | STATE_LAUNCHER_PRESENT;
+ mStateCallback.setState(STATE_ACTIVITY_MULTIPLIER_COMPLETE | STATE_LAUNCHER_DRAWN);
} else {
TraceHelper.beginSection("WTS-init");
- launcher.getStateManager().goToState(OVERVIEW, false);
+ mLauncher.getStateManager().goToState(OVERVIEW, false);
TraceHelper.partitionSection("WTS-init", "State changed");
// TODO: Implement a better animation for fading in
- View rootView = launcher.getRootView();
+ View rootView = mLauncher.getRootView();
rootView.setAlpha(0);
rootView.getViewTreeObserver().addOnDrawListener(new OnDrawListener() {
@@ -356,17 +383,14 @@
mStateCallback.setState(STATE_LAUNCHER_DRAWN);
}
});
- state = STATE_LAUNCHER_PRESENT;
// Optimization, hide the all apps view to prevent layout while initializing
mLauncher.getAppsView().setVisibility(View.GONE);
}
mRecentsView.showTask(mRunningTaskId);
+ mRecentsView.setFirstTaskIconScaledDown(true /* isScaledDown */, false /* animate */);
mLauncherLayoutListener.open();
-
- mStateCallback.setState(state);
- return true;
}
public void setLauncherOnDrawCallback(Runnable callback) {
@@ -520,7 +544,7 @@
}
}
- public void setRecentsAnimation(RecentsAnimationControllerCompat controller,
+ public void onRecentsAnimationStart(RecentsAnimationControllerCompat controller,
RemoteAnimationTargetCompat[] apps, Rect homeContentInsets, Rect minimizedHomeBounds) {
if (apps != null) {
// Use the top closing app to determine the insets for the animation
@@ -561,11 +585,14 @@
setStateOnUiThread(STATE_APP_CONTROLLER_RECEIVED);
}
- public void onGestureStarted() {
- if (mLauncher != null) {
- notifyGestureStarted();
- }
+ public void onRecentsAnimationCanceled() {
+ mRecentsAnimationWrapper.setController(null, null);
+ clearReference();
+ setStateOnUiThread(STATE_GESTURE_CANCELLED | STATE_HANDLER_INVALIDATED);
+ }
+ public void onGestureStarted() {
+ notifyGestureStarted();
setStateOnUiThread(STATE_GESTURE_STARTED);
mGestureStarted = true;
mRecentsAnimationWrapper.enableInputConsumer();
@@ -576,15 +603,10 @@
* on both background and UI threads
*/
private void notifyGestureStarted() {
- mLauncher.onQuickstepGestureStarted(mWasLauncherAlreadyVisible);
-
- mMainExecutor.execute(() -> {
- // Prepare to animate the first icon.
- View currentRecentsPage = mRecentsView.getPageAt(mRecentsView.getCurrentPage());
- if (currentRecentsPage instanceof TaskView) {
- ((TaskView) currentRecentsPage).setIconScale(0f);
- }
- });
+ final Launcher curLauncher = mLauncher;
+ if (curLauncher != null) {
+ curLauncher.onQuickstepGestureStarted(mWasLauncherAlreadyVisible);
+ }
}
@WorkerThread
@@ -611,6 +633,30 @@
}
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. */
@@ -658,6 +704,13 @@
// Restore the requested orientation to the user preference after the gesture has ended
mLauncher.updateRequestedOrientation();
+ mRecentsView.setFirstTaskIconScaledDown(false /* isScaledDown */, false /* animate */);
+ }
+
+ private void resetStateForAnimationCancel() {
+ LauncherState startState = mLauncher.getStateManager().getRestState();
+ boolean animate = mWasLauncherAlreadyVisible || mGestureStarted;
+ mLauncher.getStateManager().goToState(startState, animate);
}
public void layoutListenerClosed() {
@@ -690,10 +743,7 @@
mLauncher.getStateManager().reapplyState();
// Animate the first icon.
- View currentRecentsPage = mRecentsView.getPageAt(mRecentsView.getCurrentPage());
- if (currentRecentsPage instanceof TaskView) {
- ((TaskView) currentRecentsPage).animateIconToScale(1f);
- }
+ mRecentsView.setFirstTaskIconScaledDown(false /* isScaledDown */, true /* animate */);
}
public void onQuickScrubEnd() {
diff --git a/src/com/android/launcher3/AbstractFloatingView.java b/src/com/android/launcher3/AbstractFloatingView.java
index 12f022f..fc5ce8f 100644
--- a/src/com/android/launcher3/AbstractFloatingView.java
+++ b/src/com/android/launcher3/AbstractFloatingView.java
@@ -92,7 +92,8 @@
public final void close(boolean animate) {
animate &= !Utilities.isPowerSaverOn(getContext());
handleClose(animate);
- Launcher.getLauncher(getContext()).getUserEventDispatcher().resetElapsedContainerMillis();
+ Launcher.getLauncher(getContext()).getUserEventDispatcher()
+ .resetElapsedContainerMillis("container closed");
}
protected abstract void handleClose(boolean animate);
diff --git a/src/com/android/launcher3/FirstFrameAnimatorHelper.java b/src/com/android/launcher3/FirstFrameAnimatorHelper.java
index cea7e43..4eac4a4 100644
--- a/src/com/android/launcher3/FirstFrameAnimatorHelper.java
+++ b/src/com/android/launcher3/FirstFrameAnimatorHelper.java
@@ -73,13 +73,7 @@
view.getViewTreeObserver().removeOnDrawListener(sGlobalDrawListener);
}
- TraceHelper.beginSection("TICK");
- sGlobalDrawListener = new ViewTreeObserver.OnDrawListener() {
- public void onDraw() {
- sGlobalFrameCounter++;
- TraceHelper.partitionSection("TICK", "Frame drawn");
- }
- };
+ sGlobalDrawListener = () -> sGlobalFrameCounter++;
view.getViewTreeObserver().addOnDrawListener(sGlobalDrawListener);
sVisible = true;
}
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index b4093b7..b87511a 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -239,6 +239,7 @@
@Thunk boolean mWorkspaceLoading = true;
+ private OnStartCallback mOnStartCallback;
private OnResumeCallback mOnResumeCallback;
private ViewOnDrawExecutor mPendingExecutor;
@@ -783,7 +784,7 @@
if (!mAppLaunchSuccess) {
getUserEventDispatcher().logActionCommand(Action.Command.STOP,
- mStateManager.getState().containerType);
+ mStateManager.getState().containerType, -1);
}
NotificationListener.removeNotificationsChangedListener();
getStateManager().moveToRestState();
@@ -794,6 +795,10 @@
super.onStart();
FirstFrameAnimatorHelper.setIsVisible(true);
+ if (mOnStartCallback != null) {
+ mOnStartCallback.onLauncherStart(this);
+ mOnStartCallback = null;
+ }
if (mLauncherCallbacks != null) {
mLauncherCallbacks.onStart();
}
@@ -1280,7 +1285,8 @@
} else if (alreadyOnHome) {
Target target = newContainerTarget(mStateManager.getState().containerType);
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
@@ -1656,7 +1662,8 @@
topView.onBackPressed();
} else if (!isInState(NORMAL)) {
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);
} else {
// Back button is a no-op here, but give at least some feedback for the button press
@@ -1682,7 +1689,7 @@
if (v instanceof Workspace) {
if (isInState(OVERVIEW)) {
- getUserEventDispatcher().logActionOnContainer(LauncherLogProto.Action.Type.TOUCH,
+ getUserEventDispatcher().logActionOnContainer(LauncherLogProto.Action.Touch.TAP,
LauncherLogProto.Action.Direction.NONE,
LauncherLogProto.ContainerType.OVERVIEW, mWorkspace.getCurrentPage());
mStateManager.goToState(NORMAL);
@@ -1693,7 +1700,7 @@
if (v instanceof CellLayout) {
if (isInState(OVERVIEW)) {
int page = mWorkspace.indexOfChild(v);
- getUserEventDispatcher().logActionOnContainer(LauncherLogProto.Action.Type.TOUCH,
+ getUserEventDispatcher().logActionOnContainer(LauncherLogProto.Action.Touch.TAP,
LauncherLogProto.Action.Direction.NONE,
LauncherLogProto.ContainerType.OVERVIEW, page);
mWorkspace.snapToPageFromOverView(page);
@@ -2175,6 +2182,10 @@
mOnResumeCallback = callback;
}
+ public void setOnStartCallback(OnStartCallback callback) {
+ mOnStartCallback = callback;
+ }
+
/**
* Implementation of the method from LauncherModel.Callbacks.
*/
@@ -2880,4 +2891,12 @@
void onLauncherResume();
}
+
+ /**
+ * Callback for listening for onStart
+ */
+ public interface OnStartCallback {
+
+ void onLauncherStart(Launcher launcher);
+ }
}
diff --git a/src/com/android/launcher3/LauncherStateManager.java b/src/com/android/launcher3/LauncherStateManager.java
index 170fcd7..2f8687d 100644
--- a/src/com/android/launcher3/LauncherStateManager.java
+++ b/src/com/android/launcher3/LauncherStateManager.java
@@ -302,7 +302,6 @@
state.onStateTransitionEnd(mLauncher);
mLauncher.getWorkspace().setClipChildren(!state.disablePageClipping);
- mLauncher.getUserEventDispatcher().resetElapsedContainerMillis();
mLauncher.finishAutoCancelActionMode();
if (state == NORMAL) {
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 11523a5..1414946 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -1679,7 +1679,7 @@
if (popupContainer != null) {
dragOptions.preDragCondition = popupContainer.createPreDragCondition();
- mLauncher.getUserEventDispatcher().resetElapsedContainerMillis();
+ mLauncher.getUserEventDispatcher().resetElapsedContainerMillis("dragging started");
}
}
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index 8abafb0..993663e 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -522,7 +522,7 @@
onCompleteRunnable = new Runnable() {
@Override
public void run() {
- mLauncher.getUserEventDispatcher().resetElapsedContainerMillis();
+ mLauncher.getUserEventDispatcher().resetElapsedContainerMillis("folder opened");
}
};
anim.addListener(new AnimatorListenerAdapter() {
diff --git a/src/com/android/launcher3/logging/LoggerUtils.java b/src/com/android/launcher3/logging/LoggerUtils.java
index 00ee009..c608a23 100644
--- a/src/com/android/launcher3/logging/LoggerUtils.java
+++ b/src/com/android/launcher3/logging/LoggerUtils.java
@@ -71,7 +71,7 @@
switch (action.type) {
case Action.Type.TOUCH:
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);
}
return str;
@@ -114,11 +114,20 @@
if (t.intentHash != 0) {
typeStr += ", intentHash=" + t.intentHash;
}
- if (t.packageNameHash != 0 || t.componentHash != 0 || t.intentHash != 0) {
- typeStr += ", predictiveRank=" + t.predictedRank;
+ if ((t.packageNameHash != 0 || t.componentHash != 0 || t.intentHash != 0) &&
+ 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
- + "), pageIdx=" + t.pageIndex;
+ return typeStr;
+ }
+
+ public static Target newItemTarget(int itemType) {
+ Target t = newTarget(Target.Type.ITEM);
+ t.itemType = itemType;
+ return t;
}
public static Target newItemTarget(View v) {
diff --git a/src/com/android/launcher3/logging/UserEventDispatcher.java b/src/com/android/launcher3/logging/UserEventDispatcher.java
index 243dbea..b7de400 100644
--- a/src/com/android/launcher3/logging/UserEventDispatcher.java
+++ b/src/com/android/launcher3/logging/UserEventDispatcher.java
@@ -32,6 +32,7 @@
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
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.ContainerType;
import com.android.launcher3.userevent.nano.LauncherLogProto.LauncherEvent;
@@ -158,9 +159,23 @@
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) {
target.intentHash = intent.hashCode();
- ComponentName cn = intent.getComponent();
+ fillComponentInfo(target, intent.getComponent());
+ }
+
+ private void fillComponentInfo(Target target, ComponentName cn) {
if (cn != null) {
target.packageNameHash = (mUuidStr + cn.getPackageName()).hashCode();
target.componentHash = (mUuidStr + cn.flattenToString()).hashCode();
@@ -176,19 +191,29 @@
dispatchUserEvent(event, null);
}
- public void logActionCommand(int command, int containerType) {
- logActionCommand(command, newContainerTarget(containerType));
+ public void logActionCommand(int command, Target srcTarget) {
+ logActionCommand(command, srcTarget, null);
}
- public void logActionCommand(int command, Target target) {
- LauncherEvent event = newLauncherEvent(newCommandAction(command), target);
+ public void logActionCommand(int command, int srcContainerType, int dstContainerType) {
+ 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);
}
/**
* 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),
newItemTarget(itemView), newTarget(Target.Type.CONTAINER));
@@ -196,22 +221,39 @@
// TODO: Remove the following two lines once fillInLogContainerData can take in a
// container view.
event.srcTarget[0].type = Target.Type.CONTAINER;
- event.srcTarget[0].containerType = containerType;
+ event.srcTarget[0].containerType = srcContainerType;
}
dispatchUserEvent(event, null);
}
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) {
+ logActionOnControl(action, controlType, controlInContainer, -1);
+ }
+
+ public void logActionOnControl(int action, int controlType, @Nullable View controlInContainer,
+ int parentContainerType) {
final LauncherEvent event = controlInContainer == null
? newLauncherEvent(newTouchAction(action), newTarget(Target.Type.CONTROL))
: newLauncherEvent(newTouchAction(action), newTarget(Target.Type.CONTROL),
newTarget(Target.Type.CONTAINER));
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);
}
@@ -232,10 +274,35 @@
event.action.dir = dir;
event.srcTarget[0].pageIndex = pageIndex;
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) {
@@ -257,7 +324,7 @@
provider.fillInLogContainerData(icon, info, event.srcTarget[0], event.srcTarget[1]);
dispatchUserEvent(event, null);
- resetElapsedContainerMillis();
+ resetElapsedContainerMillis("deep shortcut open");
}
/* Currently we are only interested in whether this event happens or not and don't
@@ -290,9 +357,15 @@
/**
* Currently logs following containers: workspace, allapps, widget tray.
+ * @param reason
*/
- public final void resetElapsedContainerMillis() {
+ public final void resetElapsedContainerMillis(String reason) {
mElapsedContainerMillis = SystemClock.uptimeMillis();
+ if (!IS_VERBOSE) {
+ return;
+ }
+ Log.d(TAG, "resetElapsedContainerMillis reason=" + reason);
+
}
public final void resetElapsedSessionMillis() {
@@ -321,13 +394,13 @@
log += "\n Destination " + getTargetsStr(ev.destTarget);
}
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.elapsedSessionMillis,
ev.actionDurationMillis);
log += "\n isInLandscapeMode " + ev.isInLandscapeMode;
log += "\n isInMultiWindowMode " + ev.isInMultiWindowMode;
- log += "\n";
+ log += "\n\n";
Log.d(TAG, log);
}
diff --git a/src/com/android/launcher3/notification/NotificationListener.java b/src/com/android/launcher3/notification/NotificationListener.java
index 114b2b8..cbdabf3 100644
--- a/src/com/android/launcher3/notification/NotificationListener.java
+++ b/src/com/android/launcher3/notification/NotificationListener.java
@@ -16,6 +16,8 @@
package com.android.launcher3.notification;
+import static com.android.launcher3.SettingsActivity.NOTIFICATION_BADGING;
+
import android.annotation.TargetApi;
import android.app.Notification;
import android.app.NotificationChannel;
@@ -43,8 +45,6 @@
import java.util.Map;
import java.util.Set;
-import static com.android.launcher3.SettingsActivity.NOTIFICATION_BADGING;
-
/**
* A {@link NotificationListenerService} that sends updates to its
* {@link NotificationsChangedListener} when notifications are posted or canceled,
@@ -71,6 +71,8 @@
private final Ranking mTempRanking = new Ranking();
/** Maps groupKey's to the corresponding group of notifications. */
private final Map<String, NotificationGroup> mNotificationGroupMap = new HashMap<>();
+ /** Maps keys to their corresponding current group key */
+ private final Map<String, String> mNotificationGroupKeyMap = new HashMap<>();
private SettingsObserver mNotificationBadgingObserver;
@@ -258,6 +260,48 @@
}
}
+ @Override
+ public void onNotificationRankingUpdate(RankingMap rankingMap) {
+ super.onNotificationRankingUpdate(rankingMap);
+ String[] keys = rankingMap.getOrderedKeys();
+ for (StatusBarNotification sbn : getActiveNotifications(keys)) {
+ updateGroupKeyIfNecessary(sbn);
+ }
+ }
+
+ private void updateGroupKeyIfNecessary(StatusBarNotification sbn) {
+ String childKey = sbn.getKey();
+ String oldGroupKey = mNotificationGroupKeyMap.get(childKey);
+ String newGroupKey = sbn.getGroupKey();
+ if (oldGroupKey == null || !oldGroupKey.equals(newGroupKey)) {
+ // The group key has changed.
+ mNotificationGroupKeyMap.put(childKey, newGroupKey);
+ if (oldGroupKey != null && mNotificationGroupMap.containsKey(oldGroupKey)) {
+ // Remove the child key from the old group.
+ NotificationGroup oldGroup = mNotificationGroupMap.get(oldGroupKey);
+ oldGroup.removeChildKey(childKey);
+ if (oldGroup.isEmpty()) {
+ mNotificationGroupMap.remove(oldGroupKey);
+ }
+ }
+ }
+ if (sbn.isGroup() && newGroupKey != null) {
+ // Maintain group info so we can cancel the summary when the last child is canceled.
+ NotificationGroup notificationGroup = mNotificationGroupMap.get(newGroupKey);
+ if (notificationGroup == null) {
+ notificationGroup = new NotificationGroup();
+ mNotificationGroupMap.put(newGroupKey, notificationGroup);
+ }
+ boolean isGroupSummary = (sbn.getNotification().flags
+ & Notification.FLAG_GROUP_SUMMARY) != 0;
+ if (isGroupSummary) {
+ notificationGroup.setGroupSummaryKey(childKey);
+ } else {
+ notificationGroup.addChildKey(childKey);
+ }
+ }
+ }
+
/** This makes a potentially expensive binder call and should be run on a background thread. */
public List<StatusBarNotification> getNotificationsForKeys(List<NotificationKeyData> keys) {
StatusBarNotification[] notifications = NotificationListener.this
@@ -295,20 +339,7 @@
private boolean shouldBeFilteredOut(StatusBarNotification sbn) {
Notification notification = sbn.getNotification();
- boolean isGroupHeader = (notification.flags & Notification.FLAG_GROUP_SUMMARY) != 0;
- if (sbn.isGroup()) {
- // Maintain group info so we can cancel the summary when the last child is canceled.
- NotificationGroup notificationGroup = mNotificationGroupMap.get(sbn.getGroupKey());
- if (notificationGroup == null) {
- notificationGroup = new NotificationGroup();
- mNotificationGroupMap.put(sbn.getGroupKey(), notificationGroup);
- }
- if (isGroupHeader) {
- notificationGroup.setGroupSummaryKey(sbn.getKey());
- } else {
- notificationGroup.addChildKey(sbn.getKey());
- }
- }
+ updateGroupKeyIfNecessary(sbn);
getCurrentRanking().getRanking(sbn.getKey(), mTempRanking);
if (!mTempRanking.canShowBadge()) {
@@ -324,6 +355,7 @@
CharSequence title = notification.extras.getCharSequence(Notification.EXTRA_TITLE);
CharSequence text = notification.extras.getCharSequence(Notification.EXTRA_TEXT);
boolean missingTitleAndText = TextUtils.isEmpty(title) && TextUtils.isEmpty(text);
+ boolean isGroupHeader = (notification.flags & Notification.FLAG_GROUP_SUMMARY) != 0;
return (isGroupHeader || missingTitleAndText);
}
diff --git a/src/com/android/launcher3/states/InternalStateHandler.java b/src/com/android/launcher3/states/InternalStateHandler.java
index 7298383..d3c0fef 100644
--- a/src/com/android/launcher3/states/InternalStateHandler.java
+++ b/src/com/android/launcher3/states/InternalStateHandler.java
@@ -24,7 +24,6 @@
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherModel.Callbacks;
import com.android.launcher3.MainThreadExecutor;
-import com.android.launcher3.util.Preconditions;
import java.lang.ref.WeakReference;
@@ -38,7 +37,7 @@
public static final String EXTRA_STATE_HANDLER = "launcher.state_handler";
- private static WeakReference<InternalStateHandler> sPendingHandler = new WeakReference<>(null);
+ private static final Scheduler sScheduler = new Scheduler();
/**
* Initializes the handler when the launcher is ready.
@@ -53,30 +52,12 @@
return intent;
}
- public final void initWhenReady(MainThreadExecutor executor) {
- sPendingHandler = new WeakReference<>(this);
- executor.execute(this::initIfReadOnUIThread);
- }
-
- private void initIfReadOnUIThread() {
- LauncherAppState app = LauncherAppState.getInstanceNoCreate();
- if (app == null) {
- return;
- }
- Callbacks cb = app.getModel().getCallback();
- if (!(cb instanceof Launcher)) {
- return;
- }
- Launcher launcher = (Launcher) cb;
- if (!init(launcher, launcher.isStarted())) {
- sPendingHandler.clear();
- }
+ public final void initWhenReady() {
+ sScheduler.schedule(this);
}
public void clearReference() {
- if (sPendingHandler.get() == this) {
- sPendingHandler.clear();
- }
+ sScheduler.clearReference(this);
}
public static boolean handleCreate(Launcher launcher, Intent intent) {
@@ -101,14 +82,53 @@
}
}
if (!result && !explicitIntent) {
- InternalStateHandler pendingHandler = sPendingHandler.get();
- if (pendingHandler != null) {
- if (!pendingHandler.init(launcher, alreadyOnHome)) {
- sPendingHandler.clear();
- }
- result = true;
- }
+ result = sScheduler.initIfPending(launcher, alreadyOnHome);
}
return result;
}
+
+ private static class Scheduler implements Runnable {
+
+ private WeakReference<InternalStateHandler> mPendingHandler = new WeakReference<>(null);
+ private MainThreadExecutor mMainThreadExecutor;
+
+ public synchronized void schedule(InternalStateHandler handler) {
+ mPendingHandler = new WeakReference<>(handler);
+ if (mMainThreadExecutor == null) {
+ mMainThreadExecutor = new MainThreadExecutor();
+ }
+ mMainThreadExecutor.execute(this);
+ }
+
+ @Override
+ public void run() {
+ LauncherAppState app = LauncherAppState.getInstanceNoCreate();
+ if (app == null) {
+ return;
+ }
+ Callbacks cb = app.getModel().getCallback();
+ if (!(cb instanceof Launcher)) {
+ return;
+ }
+ Launcher launcher = (Launcher) cb;
+ initIfPending(launcher, launcher.isStarted());
+ }
+
+ public synchronized boolean initIfPending(Launcher launcher, boolean alreadyOnHome) {
+ InternalStateHandler pendingHandler = mPendingHandler.get();
+ if (pendingHandler != null) {
+ if (!pendingHandler.init(launcher, alreadyOnHome)) {
+ mPendingHandler.clear();
+ }
+ return true;
+ }
+ return false;
+ }
+
+ public synchronized void clearReference(InternalStateHandler handler) {
+ if (mPendingHandler.get() == handler) {
+ mPendingHandler.clear();
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/src/com/android/launcher3/util/TraceHelper.java b/src/com/android/launcher3/util/TraceHelper.java
index bde9c0a..ac381cc 100644
--- a/src/com/android/launcher3/util/TraceHelper.java
+++ b/src/com/android/launcher3/util/TraceHelper.java
@@ -15,12 +15,16 @@
*/
package com.android.launcher3.util;
+import static android.util.Log.VERBOSE;
+import static android.util.Log.isLoggable;
+
import android.os.SystemClock;
import android.os.Trace;
import android.util.ArrayMap;
import android.util.Log;
import android.util.MutableLong;
+import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
/**
@@ -31,7 +35,8 @@
*/
public class TraceHelper {
- private static final boolean ENABLED = FeatureFlags.IS_DOGFOOD_BUILD;
+ private static final boolean FORCE_LOG = Utilities.IS_DEBUG_DEVICE;
+ private static final boolean ENABLED = FORCE_LOG || FeatureFlags.IS_DOGFOOD_BUILD;
private static final boolean SYSTEM_TRACE = false;
private static final ArrayMap<String, MutableLong> sUpTimes = ENABLED ? new ArrayMap<>() : null;
@@ -40,7 +45,7 @@
if (ENABLED) {
MutableLong time = sUpTimes.get(sectionName);
if (time == null) {
- time = new MutableLong(Log.isLoggable(sectionName, Log.VERBOSE) ? 0 : -1);
+ time = new MutableLong((FORCE_LOG || isLoggable(sectionName, VERBOSE)) ? 0 : -1);
sUpTimes.put(sectionName, time);
}
if (time.value >= 0) {