Merge "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" into ub-launcher3-master
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/RecentsView.java b/quickstep/src/com/android/quickstep/RecentsView.java
index 8ff0a86..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);
}
@@ -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/WindowTransformSwipeHandler.java b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
index 0e8dea6..28bf19c 100644
--- a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
+++ b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
@@ -81,32 +81,36 @@
// 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",
@@ -114,6 +118,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",
@@ -205,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);
@@ -307,37 +314,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() {
@@ -353,17 +376,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) {
@@ -516,7 +536,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
@@ -557,11 +577,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();
@@ -572,15 +595,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
@@ -678,6 +696,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() {
@@ -710,10 +735,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/Launcher.java b/src/com/android/launcher3/Launcher.java
index f76d4eb..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;
@@ -794,6 +795,10 @@
super.onStart();
FirstFrameAnimatorHelper.setIsVisible(true);
+ if (mOnStartCallback != null) {
+ mOnStartCallback.onLauncherStart(this);
+ mOnStartCallback = null;
+ }
if (mLauncherCallbacks != null) {
mLauncherCallbacks.onStart();
}
@@ -2177,6 +2182,10 @@
mOnResumeCallback = callback;
}
+ public void setOnStartCallback(OnStartCallback callback) {
+ mOnStartCallback = callback;
+ }
+
/**
* Implementation of the method from LauncherModel.Callbacks.
*/
@@ -2882,4 +2891,12 @@
void onLauncherResume();
}
+
+ /**
+ * Callback for listening for onStart
+ */
+ public interface OnStartCallback {
+
+ void onLauncherStart(Launcher launcher);
+ }
}
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