Merge "Adding message popups to anomaly diagnoser" into ub-launcher3-qt-r1-dev
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java
index d34b604..72a9da6 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java
@@ -18,26 +18,49 @@
import static android.os.VibrationEffect.EFFECT_CLICK;
import static android.os.VibrationEffect.createPredefined;
+import static com.android.launcher3.Utilities.postAsyncCallback;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.quickstep.TouchInteractionService.BACKGROUND_EXECUTOR;
+import static com.android.quickstep.TouchInteractionService.MAIN_THREAD_EXECUTOR;
+import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG;
import android.annotation.TargetApi;
import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
+import android.content.Intent;
+import android.graphics.Point;
import android.graphics.PointF;
+import android.graphics.Rect;
import android.os.Build;
+import android.os.Handler;
+import android.os.Looper;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.provider.Settings;
import android.view.MotionEvent;
+import android.view.View;
+import android.view.WindowManager;
import android.view.animation.Interpolator;
+import com.android.launcher3.BaseDraggingActivity;
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.graphics.RotationMode;
+import com.android.quickstep.ActivityControlHelper.ActivityInitListener;
+import com.android.quickstep.SysUINavigationMode.Mode;
+import com.android.quickstep.inputconsumers.InputConsumer;
import com.android.quickstep.util.ClipAnimationHelper;
import com.android.quickstep.util.ClipAnimationHelper.TransformParams;
+import com.android.quickstep.util.SwipeAnimationTargetSet;
import com.android.quickstep.util.SwipeAnimationTargetSet.SwipeAnimationListener;
import com.android.quickstep.views.RecentsView;
+import com.android.quickstep.views.TaskView;
+import com.android.systemui.shared.system.InputConsumerController;
+import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
+import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
import java.util.function.Consumer;
@@ -47,7 +70,11 @@
* Base class for swipe up handler with some utility methods
*/
@TargetApi(Build.VERSION_CODES.Q)
-public abstract class BaseSwipeUpHandler implements SwipeAnimationListener {
+public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q extends RecentsView>
+ implements SwipeAnimationListener {
+
+ private static final String TAG = "BaseSwipeUpHandler";
+ protected static final Rect TEMP_RECT = new Rect();
// Start resisting when swiping past this factor of mTransitionDragLength.
private static final float DRAG_LENGTH_FACTOR_START_PULLBACK = 1.4f;
@@ -61,11 +88,16 @@
protected float mDragLengthFactor = 1;
protected final Context mContext;
+ protected final OverviewComponentObserver mOverviewComponentObserver;
+ protected final ActivityControlHelper<T> mActivityControlHelper;
+ protected final RecentsModel mRecentsModel;
+ protected final int mRunningTaskId;
protected final ClipAnimationHelper mClipAnimationHelper;
protected final TransformParams mTransformParams = new TransformParams();
private final Vibrator mVibrator;
+ protected final Mode mMode;
// Shift in the range of [0, 1].
// 0 => preview snapShot is completely visible, and hotseat is completely translated down
@@ -73,18 +105,52 @@
// visible.
protected final AnimatedFloat mCurrentShift = new AnimatedFloat(this::updateFinalShift);
- protected RecentsView mRecentsView;
+ protected final ActivityInitListener mActivityInitListener;
+ protected final RecentsAnimationWrapper mRecentsAnimationWrapper;
+
+ protected T mActivity;
+ protected Q mRecentsView;
+ protected DeviceProfile mDp;
+ private final int mPageSpacing;
protected Runnable mGestureEndCallback;
- protected BaseSwipeUpHandler(Context context) {
- mContext = context;
- mClipAnimationHelper = new ClipAnimationHelper(context);
+ protected final Handler mMainThreadHandler = MAIN_THREAD_EXECUTOR.getHandler();
+ protected MultiStateCallback mStateCallback;
+ protected boolean mCanceled;
+ protected int mFinishingRecentsAnimationForNewTaskId = -1;
+
+ protected BaseSwipeUpHandler(Context context,
+ OverviewComponentObserver overviewComponentObserver,
+ RecentsModel recentsModel, InputConsumerController inputConsumer, int runningTaskId) {
+ mContext = context;
+ mOverviewComponentObserver = overviewComponentObserver;
+ mActivityControlHelper = overviewComponentObserver.getActivityControlHelper();
+ mRecentsModel = recentsModel;
+ mActivityInitListener =
+ mActivityControlHelper.createActivityInitListener(this::onActivityInit);
+ mRunningTaskId = runningTaskId;
+ mRecentsAnimationWrapper = new RecentsAnimationWrapper(inputConsumer,
+ this::createNewInputProxyHandler);
+ mMode = SysUINavigationMode.getMode(context);
+
+ mClipAnimationHelper = new ClipAnimationHelper(context);
+ mPageSpacing = context.getResources().getDimensionPixelSize(R.dimen.recents_page_spacing);
mVibrator = context.getSystemService(Vibrator.class);
+ initTransitionEndpoints(InvariantDeviceProfile.INSTANCE.get(mContext)
+ .getDeviceProfile(mContext));
}
- public void performHapticFeedback() {
+ protected void setStateOnUiThread(int stateFlag) {
+ if (Looper.myLooper() == mMainThreadHandler.getLooper()) {
+ mStateCallback.setState(stateFlag);
+ } else {
+ postAsyncCallback(mMainThreadHandler, () -> mStateCallback.setState(stateFlag));
+ }
+ }
+
+ protected void performHapticFeedback() {
if (!mVibrator.hasVibrator()) {
return;
}
@@ -130,12 +196,135 @@
mGestureEndCallback = gestureEndCallback;
}
+ public abstract Intent getLaunchIntent();
+
+ protected void linkRecentsViewScroll() {
+ SyncRtSurfaceTransactionApplierCompat.create(mRecentsView, applier -> {
+ mTransformParams.setSyncTransactionApplier(applier);
+ mRecentsAnimationWrapper.runOnInit(() ->
+ mRecentsAnimationWrapper.targetSet.addDependentTransactionApplier(applier));
+ });
+
+ mRecentsView.setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) -> {
+ if (moveWindowWithRecentsScroll()) {
+ updateFinalShift();
+ }
+ });
+ mRecentsView.setRecentsAnimationWrapper(mRecentsAnimationWrapper);
+ mRecentsView.setClipAnimationHelper(mClipAnimationHelper);
+ }
+
+ protected void startNewTask(int successStateFlag, Consumer<Boolean> resultCallback) {
+ // Launch the task user scrolled to (mRecentsView.getNextPage()).
+ if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
+ // We finish recents animation inside launchTask() when live tile is enabled.
+ mRecentsView.getTaskViewAt(mRecentsView.getNextPage()).launchTask(false /* animate */,
+ true /* freezeTaskList */);
+ } else {
+ int taskId = mRecentsView.getTaskViewAt(mRecentsView.getNextPage()).getTask().key.id;
+ mFinishingRecentsAnimationForNewTaskId = taskId;
+ mRecentsAnimationWrapper.finish(true /* toRecents */, () -> {
+ if (!mCanceled) {
+ TaskView nextTask = mRecentsView.getTaskView(taskId);
+ if (nextTask != null) {
+ nextTask.launchTask(false /* animate */, true /* freezeTaskList */,
+ success -> {
+ resultCallback.accept(success);
+ if (!success) {
+ mActivityControlHelper.onLaunchTaskFailed(mActivity);
+ nextTask.notifyTaskLaunchFailed(TAG);
+ } else {
+ mActivityControlHelper.onLaunchTaskSuccess(mActivity);
+ }
+ }, mMainThreadHandler);
+ }
+ setStateOnUiThread(successStateFlag);
+ }
+ mCanceled = false;
+ mFinishingRecentsAnimationForNewTaskId = -1;
+ });
+ }
+ TOUCH_INTERACTION_LOG.addLog("finishRecentsAnimation", true);
+ }
+
+ @Override
+ public void onRecentsAnimationStart(SwipeAnimationTargetSet targetSet) {
+ DeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(mContext).getDeviceProfile(mContext);
+ final Rect overviewStackBounds;
+ RemoteAnimationTargetCompat runningTaskTarget = targetSet.findTask(mRunningTaskId);
+
+ if (targetSet.minimizedHomeBounds != null && runningTaskTarget != null) {
+ overviewStackBounds = mActivityControlHelper
+ .getOverviewWindowBounds(targetSet.minimizedHomeBounds, runningTaskTarget);
+ dp = dp.getMultiWindowProfile(mContext, new Point(
+ overviewStackBounds.width(), overviewStackBounds.height()));
+ } else {
+ // If we are not in multi-window mode, home insets should be same as system insets.
+ dp = dp.copy(mContext);
+ overviewStackBounds = getStackBounds(dp);
+ }
+ dp.updateInsets(targetSet.homeContentInsets);
+ dp.updateIsSeascape(mContext.getSystemService(WindowManager.class));
+ if (runningTaskTarget != null) {
+ mClipAnimationHelper.updateSource(overviewStackBounds, runningTaskTarget);
+ }
+
+ mClipAnimationHelper.prepareAnimation(dp, false /* isOpening */);
+ initTransitionEndpoints(dp);
+
+ mRecentsAnimationWrapper.setController(targetSet);
+ }
+
+ private Rect getStackBounds(DeviceProfile dp) {
+ if (mActivity != null) {
+ int loc[] = new int[2];
+ View rootView = mActivity.getRootView();
+ rootView.getLocationOnScreen(loc);
+ return new Rect(loc[0], loc[1], loc[0] + rootView.getWidth(),
+ loc[1] + rootView.getHeight());
+ } else {
+ return new Rect(0, 0, dp.widthPx, dp.heightPx);
+ }
+ }
+
+ protected void initTransitionEndpoints(DeviceProfile dp) {
+ mDp = dp;
+
+ mTransitionDragLength = mActivityControlHelper.getSwipeUpDestinationAndLength(
+ dp, mContext, TEMP_RECT);
+ if (!dp.isMultiWindowMode) {
+ // When updating the target rect, also update the home bounds since the location on
+ // screen of the launcher window may be stale (position is not updated until first
+ // traversal after the window is resized). We only do this for non-multiwindow because
+ // we otherwise use the minimized home bounds provided by the system.
+ mClipAnimationHelper.updateHomeBounds(getStackBounds(dp));
+ }
+ mClipAnimationHelper.updateTargetRect(TEMP_RECT);
+ if (mMode == Mode.NO_BUTTON) {
+ // We can drag all the way to the top of the screen.
+ mDragLengthFactor = (float) dp.heightPx / mTransitionDragLength;
+ }
+ }
+
+ /**
+ * Return true if the window should be translated horizontally if the recents view scrolls
+ */
+ protected abstract boolean moveWindowWithRecentsScroll();
+
+ protected abstract boolean onActivityInit(final T activity, Boolean alreadyOnHome);
+
+ /**
+ * Called to create a input proxy for the running task
+ */
+ @UiThread
+ protected abstract InputConsumer createNewInputProxyHandler();
+
/**
* Called when the value of {@link #mCurrentShift} changes
*/
+ @UiThread
public abstract void updateFinalShift();
-
/**
* Called when motion pause is detected
*/
@@ -150,15 +339,39 @@
@UiThread
public abstract void onGestureEnded(float endVelocity, PointF velocity, PointF downPos);
- public void onConsumerAboutToBeSwitched(SwipeSharedState sharedState) { }
+ public abstract void onConsumerAboutToBeSwitched(SwipeSharedState sharedState);
public void setIsLikelyToStartNewTask(boolean isLikelyToStartNewTask) { }
- public void initWhenReady() { }
+ public void initWhenReady() {
+ // Preload the plan
+ mRecentsModel.getTasks(null);
+
+ mActivityInitListener.register();
+ }
+
+ /**
+ * Applies the transform on the recents animation without any additional null checks
+ */
+ protected void applyTransformUnchecked() {
+ float shift = mCurrentShift.value;
+ float offsetX = mRecentsView == null ? 0 : mRecentsView.getScrollOffset();
+ float offsetScale = getTaskCurveScaleForOffsetX(offsetX,
+ mClipAnimationHelper.getTargetRect().width());
+ mTransformParams.setProgress(shift).setOffsetX(offsetX).setOffsetScale(offsetScale);
+ mClipAnimationHelper.applyTransform(mRecentsAnimationWrapper.targetSet,
+ mTransformParams);
+ }
+
+ private float getTaskCurveScaleForOffsetX(float offsetX, float taskWidth) {
+ float distanceToReachEdge = mDp.widthPx / 2 + taskWidth / 2 + mPageSpacing;
+ float interpolation = Math.min(1, offsetX / distanceToReachEdge);
+ return TaskView.getCurveScaleForInterpolation(interpolation);
+ }
public interface Factory {
BaseSwipeUpHandler newHandler(RunningTaskInfo runningTask,
- long touchTimeMs, boolean continuingLastGesture);
+ long touchTimeMs, boolean continuingLastGesture, boolean isLikelyToStartNewTask);
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java
index 61767e5..60e7b12 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java
@@ -87,12 +87,14 @@
@Override
protected void onNewIntent(Intent intent) {
- int taskID = intent.getIntExtra(EXTRA_TASK_ID, 0);
- IBinder thumbnail = intent.getExtras().getBinder(EXTRA_THUMBNAIL);
- if (taskID != 0 && thumbnail instanceof ObjectWrapper) {
- ThumbnailData thumbnailData = ((ObjectWrapper<ThumbnailData>) thumbnail).get();
- mFallbackRecentsView.showCurrentTask(taskID);
- mFallbackRecentsView.updateThumbnail(taskID, thumbnailData);
+ if (intent.getExtras() != null) {
+ int taskID = intent.getIntExtra(EXTRA_TASK_ID, 0);
+ IBinder thumbnail = intent.getExtras().getBinder(EXTRA_THUMBNAIL);
+ if (taskID != 0 && thumbnail instanceof ObjectWrapper) {
+ ThumbnailData thumbnailData = ((ObjectWrapper<ThumbnailData>) thumbnail).get();
+ mFallbackRecentsView.showCurrentTask(taskID);
+ mFallbackRecentsView.updateThumbnail(taskID, thumbnailData);
+ }
}
intent.removeExtra(EXTRA_TASK_ID);
intent.removeExtra(EXTRA_THUMBNAIL);
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
index 22c18d0..4bc4c76 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
@@ -649,20 +649,17 @@
final boolean shouldDefer;
final BaseSwipeUpHandler.Factory factory;
- final Intent homeIntent;
if (mMode == Mode.NO_BUTTON && !mOverviewComponentObserver.isHomeAndOverviewSame()) {
- shouldDefer = true;
+ shouldDefer = !sSwipeSharedState.recentsAnimationFinishInterrupted;
factory = mFallbackNoButtonFactory;
- homeIntent = mOverviewComponentObserver.getHomeIntent();
} else {
shouldDefer = mOverviewComponentObserver.getActivityControlHelper()
.deferStartingActivity(mActiveNavBarRegion, event);
factory = mWindowTreansformFactory;
- homeIntent = mOverviewComponentObserver.getOverviewIntent();
}
- return new OtherActivityInputConsumer(this, runningTaskInfo, homeIntent,
+ return new OtherActivityInputConsumer(this, runningTaskInfo,
shouldDefer, mOverviewCallbacks, this::onConsumerInactive,
sSwipeSharedState, mInputMonitorCompat, mSwipeTouchRegion,
disableHorizontalSwipe(event), factory);
@@ -708,6 +705,10 @@
if (!mIsUserUnlocked) {
return;
}
+ if (!mMode.hasGestures && !mOverviewComponentObserver.isHomeAndOverviewSame()) {
+ // Prevent the overview from being started before the real home on first boot.
+ return;
+ }
final ActivityControlHelper<BaseDraggingActivity> activityControl =
mOverviewComponentObserver.getActivityControlHelper();
@@ -805,16 +806,15 @@
}
private BaseSwipeUpHandler createWindowTransformSwipeHandler(RunningTaskInfo runningTask,
- long touchTimeMs, boolean continuingLastGesture) {
- return new WindowTransformSwipeHandler(
- runningTask, this, touchTimeMs,
- mOverviewComponentObserver.getActivityControlHelper(),
- continuingLastGesture, mInputConsumer, mRecentsModel);
+ long touchTimeMs, boolean continuingLastGesture, boolean isLikelyToStartNewTask) {
+ return new WindowTransformSwipeHandler(runningTask, this, touchTimeMs,
+ mOverviewComponentObserver, continuingLastGesture, mInputConsumer, mRecentsModel);
}
private BaseSwipeUpHandler createFallbackNoButtonSwipeHandler(RunningTaskInfo runningTask,
- long touchTimeMs, boolean continuingLastGesture) {
- return new FallbackNoButtonInputConsumer(this, mOverviewComponentObserver, runningTask);
+ long touchTimeMs, boolean continuingLastGesture, boolean isLikelyToStartNewTask) {
+ return new FallbackNoButtonInputConsumer(this, mOverviewComponentObserver, runningTask,
+ mRecentsModel, mInputConsumer, isLikelyToStartNewTask, continuingLastGesture);
}
public static void startRecentsActivityAsync(Intent intent, RecentsAnimationListener listener) {
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
index c60b28d..922f8e2 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
@@ -18,7 +18,6 @@
import static com.android.launcher3.BaseActivity.INVISIBLE_BY_STATE_HANDLER;
import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS;
import static com.android.launcher3.Utilities.SINGLE_FRAME_MS;
-import static com.android.launcher3.Utilities.postAsyncCallback;
import static com.android.launcher3.anim.Interpolators.ACCEL_1_5;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
import static com.android.launcher3.anim.Interpolators.LINEAR;
@@ -32,7 +31,6 @@
import static com.android.quickstep.ActivityControlHelper.AnimationFactory.ShelfAnimState.HIDE;
import static com.android.quickstep.ActivityControlHelper.AnimationFactory.ShelfAnimState.PEEK;
import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
-import static com.android.quickstep.TouchInteractionService.MAIN_THREAD_EXECUTOR;
import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG;
import static com.android.quickstep.WindowTransformSwipeHandler.GestureEndTarget.HOME;
import static com.android.quickstep.WindowTransformSwipeHandler.GestureEndTarget.LAST_TASK;
@@ -48,27 +46,22 @@
import android.annotation.TargetApi;
import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
+import android.content.Intent;
import android.graphics.Canvas;
-import android.graphics.Point;
import android.graphics.PointF;
-import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Build;
-import android.os.Handler;
-import android.os.Looper;
import android.os.SystemClock;
import android.util.Log;
import android.view.View;
import android.view.View.OnApplyWindowInsetsListener;
import android.view.ViewTreeObserver.OnDrawListener;
import android.view.WindowInsets;
-import android.view.WindowManager;
import android.view.animation.Interpolator;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimationSuccessListener;
@@ -82,7 +75,6 @@
import com.android.launcher3.util.RaceConditionTracker;
import com.android.launcher3.util.TraceHelper;
import com.android.launcher3.views.FloatingIconView;
-import com.android.quickstep.ActivityControlHelper.ActivityInitListener;
import com.android.quickstep.ActivityControlHelper.AnimationFactory;
import com.android.quickstep.ActivityControlHelper.AnimationFactory.ShelfAnimState;
import com.android.quickstep.ActivityControlHelper.HomeAnimationFactory;
@@ -94,24 +86,23 @@
import com.android.quickstep.util.RemoteAnimationTargetSet;
import com.android.quickstep.util.SwipeAnimationTargetSet;
import com.android.quickstep.views.LiveTileOverlay;
+import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.LatencyTrackerCompat;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
-import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
import com.android.systemui.shared.system.WindowCallbacksCompat;
import androidx.annotation.NonNull;
import androidx.annotation.UiThread;
@TargetApi(Build.VERSION_CODES.O)
-public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> extends BaseSwipeUpHandler
+public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
+ extends BaseSwipeUpHandler<T, RecentsView>
implements OnApplyWindowInsetsListener {
private static final String TAG = WindowTransformSwipeHandler.class.getSimpleName();
- private static final Rect TEMP_RECT = new Rect();
-
private static final String[] STATE_NAMES = DEBUG_STATES ? new String[16] : null;
private static int getFlagForIndex(int index, String name) {
@@ -219,35 +210,21 @@
// Either RectFSpringAnim (if animating home) or ObjectAnimator (from mCurrentShift) otherwise
private RunningWindowAnim mRunningWindowAnim;
private boolean mIsShelfPeeking;
- private DeviceProfile mDp;
private boolean mContinuingLastGesture;
// To avoid UI jump when gesture is started, we offset the animation by the threshold.
private float mShiftAtGestureStart = 0;
- private final Handler mMainThreadHandler = MAIN_THREAD_EXECUTOR.getHandler();
-
- private final ActivityControlHelper<T> mActivityControlHelper;
- private final ActivityInitListener mActivityInitListener;
- private final RecentsModel mRecentsModel;
-
- private final SysUINavigationMode.Mode mMode;
-
- private final int mRunningTaskId;
private ThumbnailData mTaskSnapshot;
- private MultiStateCallback mStateCallback;
// Used to control launcher components throughout the swipe gesture.
private AnimatorPlaybackController mLauncherTransitionController;
private boolean mHasLauncherTransitionControllerStarted;
- private T mActivity;
private AnimationFactory mAnimationFactory = (t) -> { };
private LiveTileOverlay mLiveTileOverlay = new LiveTileOverlay();
- private boolean mCanceled;
private boolean mWasLauncherAlreadyVisible;
- private int mFinishingRecentsAnimationForNewTaskId = -1;
private boolean mPassedOverviewThreshold;
private boolean mGestureStarted;
@@ -256,30 +233,17 @@
private PointF mDownPos;
private boolean mIsLikelyToStartNewTask;
- private final RecentsAnimationWrapper mRecentsAnimationWrapper;
-
private final long mTouchTimeMs;
private long mLauncherFrameDrawnTime;
public WindowTransformSwipeHandler(RunningTaskInfo runningTaskInfo, Context context,
- long touchTimeMs, ActivityControlHelper<T> controller, boolean continuingLastGesture,
+ long touchTimeMs, OverviewComponentObserver overviewComponentObserver,
+ boolean continuingLastGesture,
InputConsumerController inputConsumer, RecentsModel recentsModel) {
- super(context);
- mRunningTaskId = runningTaskInfo.id;
+ super(context, overviewComponentObserver, recentsModel, inputConsumer, runningTaskInfo.id);
mTouchTimeMs = touchTimeMs;
- mActivityControlHelper = controller;
- mRecentsModel = recentsModel;
- mActivityInitListener = mActivityControlHelper
- .createActivityInitListener(this::onActivityInit);
mContinuingLastGesture = continuingLastGesture;
- mRecentsAnimationWrapper = new RecentsAnimationWrapper(inputConsumer,
- this::createNewInputProxyHandler);
-
- mMode = SysUINavigationMode.getMode(context);
initStateCallbacks();
-
- DeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(mContext).getDeviceProfile(mContext);
- initTransitionEndpoints(dp);
}
private void initStateCallbacks() {
@@ -342,55 +306,8 @@
}
}
- private void setStateOnUiThread(int stateFlag) {
- if (Looper.myLooper() == mMainThreadHandler.getLooper()) {
- mStateCallback.setState(stateFlag);
- } else {
- postAsyncCallback(mMainThreadHandler, () -> mStateCallback.setState(stateFlag));
- }
- }
-
- private Rect getStackBounds(DeviceProfile dp) {
- if (mActivity != null) {
- int loc[] = new int[2];
- View rootView = mActivity.getRootView();
- rootView.getLocationOnScreen(loc);
- return new Rect(loc[0], loc[1], loc[0] + rootView.getWidth(),
- loc[1] + rootView.getHeight());
- } else {
- return new Rect(0, 0, dp.widthPx, dp.heightPx);
- }
- }
-
- private void initTransitionEndpoints(DeviceProfile dp) {
- mDp = dp;
-
- Rect tempRect = new Rect();
- mTransitionDragLength = mActivityControlHelper.getSwipeUpDestinationAndLength(
- dp, mContext, tempRect);
- if (!dp.isMultiWindowMode) {
- // When updating the target rect, also update the home bounds since the location on
- // screen of the launcher window may be stale (position is not updated until first
- // traversal after the window is resized). We only do this for non-multiwindow because
- // we otherwise use the minimized home bounds provided by the system.
- mClipAnimationHelper.updateHomeBounds(getStackBounds(dp));
- }
- mClipAnimationHelper.updateTargetRect(tempRect);
- if (mMode == Mode.NO_BUTTON) {
- // We can drag all the way to the top of the screen.
- mDragLengthFactor = (float) dp.heightPx / mTransitionDragLength;
- }
- }
-
@Override
- public void initWhenReady() {
- // Preload the plan
- mRecentsModel.getTasks(null);
-
- mActivityInitListener.register();
- }
-
- private boolean onActivityInit(final T activity, Boolean alreadyOnHome) {
+ protected boolean onActivityInit(final T activity, Boolean alreadyOnHome) {
if (mActivity == activity) {
return true;
}
@@ -411,19 +328,7 @@
}
mRecentsView = activity.getOverviewPanel();
- SyncRtSurfaceTransactionApplierCompat.create(mRecentsView, applier -> {
- mTransformParams.setSyncTransactionApplier(applier);
- mRecentsAnimationWrapper.runOnInit(() ->
- mRecentsAnimationWrapper.targetSet.addDependentTransactionApplier(applier));
- });
-
- mRecentsView.setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) -> {
- if (mGestureEndTarget != HOME) {
- updateFinalShift();
- }
- });
- mRecentsView.setRecentsAnimationWrapper(mRecentsAnimationWrapper);
- mRecentsView.setClipAnimationHelper(mClipAnimationHelper);
+ linkRecentsViewScroll();
mRecentsView.setLiveTileOverlay(mLiveTileOverlay);
mActivity.getRootView().getOverlay().add(mLiveTileOverlay);
@@ -438,6 +343,11 @@
return true;
}
+ @Override
+ protected boolean moveWindowWithRecentsScroll() {
+ return mGestureEndTarget != HOME;
+ }
+
private void onLauncherStart(final T activity) {
if (TestProtocol.sDebugTracing) {
Log.d(TestProtocol.NO_OVERVIEW_EVENT_TAG, "onLauncherStart");
@@ -654,20 +564,18 @@
updateLauncherTransitionProgress();
}
- @UiThread
+ @Override
+ public Intent getLaunchIntent() {
+ return mOverviewComponentObserver.getOverviewIntent();
+ }
+
@Override
public void updateFinalShift() {
- float shift = mCurrentShift.value;
SwipeAnimationTargetSet controller = mRecentsAnimationWrapper.getController();
if (controller != null) {
- float offsetX = mRecentsView == null ? 0 : mRecentsView.getScrollOffset();
- float offsetScale = getTaskCurveScaleForOffsetX(offsetX,
- mClipAnimationHelper.getTargetRect().width());
- mTransformParams.setProgress(shift).setOffsetX(offsetX).setOffsetScale(offsetScale);
- mClipAnimationHelper.applyTransform(mRecentsAnimationWrapper.targetSet,
- mTransformParams);
- updateSysUiFlags(shift);
+ applyTransformUnchecked();
+ updateSysUiFlags(mCurrentShift.value);
}
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
@@ -724,30 +632,7 @@
@Override
public void onRecentsAnimationStart(SwipeAnimationTargetSet targetSet) {
- DeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(mContext).getDeviceProfile(mContext);
- final Rect overviewStackBounds;
- RemoteAnimationTargetCompat runningTaskTarget = targetSet.findTask(mRunningTaskId);
-
- if (targetSet.minimizedHomeBounds != null && runningTaskTarget != null) {
- overviewStackBounds = mActivityControlHelper
- .getOverviewWindowBounds(targetSet.minimizedHomeBounds, runningTaskTarget);
- dp = dp.getMultiWindowProfile(mContext, new Point(
- targetSet.minimizedHomeBounds.width(), targetSet.minimizedHomeBounds.height()));
- } else {
- // If we are not in multi-window mode, home insets should be same as system insets.
- dp = dp.copy(mContext);
- overviewStackBounds = getStackBounds(dp);
- }
- dp.updateInsets(targetSet.homeContentInsets);
- dp.updateIsSeascape(mContext.getSystemService(WindowManager.class));
-
- if (runningTaskTarget != null) {
- mClipAnimationHelper.updateSource(overviewStackBounds, runningTaskTarget);
- }
- mClipAnimationHelper.prepareAnimation(dp, false /* isOpening */);
- initTransitionEndpoints(dp);
-
- mRecentsAnimationWrapper.setController(targetSet);
+ super.onRecentsAnimationStart(targetSet);
TOUCH_INTERACTION_LOG.addLog("startRecentsAnimationCallback", targetSet.apps.length);
setStateOnUiThread(STATE_APP_CONTROLLER_RECEIVED);
@@ -817,8 +702,8 @@
handleNormalGestureEnd(endVelocity, isFling, velocity, false /* isCancel */);
}
- @UiThread
- private InputConsumer createNewInputProxyHandler() {
+ @Override
+ protected InputConsumer createNewInputProxyHandler() {
endRunningWindowAnim(true /* cancel */);
endLauncherTransitionController();
if (!ENABLE_QUICKSTEP_LIVE_TILE.get()) {
@@ -928,7 +813,7 @@
if (Math.abs(endVelocity) > minFlingVelocity && mTransitionDragLength > 0) {
if (endTarget == RECENTS && mMode != Mode.NO_BUTTON) {
Interpolators.OvershootParams overshoot = new Interpolators.OvershootParams(
- startShift, endShift, endShift, velocityPxPerMs.y,
+ startShift, endShift, endShift, endVelocity / 1000,
mTransitionDragLength);
endShift = overshoot.end;
interpolator = overshoot.interpolator;
@@ -1208,40 +1093,15 @@
@UiThread
private void startNewTask() {
- // Launch the task user scrolled to (mRecentsView.getNextPage()).
- if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
- // We finish recents animation inside launchTask() when live tile is enabled.
- mRecentsView.getTaskViewAt(mRecentsView.getNextPage()).launchTask(false /* animate */,
- true /* freezeTaskList */);
- } else {
- int taskId = mRecentsView.getTaskViewAt(mRecentsView.getNextPage()).getTask().key.id;
- mFinishingRecentsAnimationForNewTaskId = taskId;
- mRecentsAnimationWrapper.finish(true /* toRecents */, () -> {
- if (!mCanceled) {
- TaskView nextTask = mRecentsView.getTaskView(taskId);
- if (nextTask != null) {
- nextTask.launchTask(false /* animate */, true /* freezeTaskList */,
- success -> {
- if (!success) {
- // We couldn't launch the task, so take user to overview so they can
- // decide what to do instead of staying in this broken state.
- endLauncherTransitionController();
- mActivityControlHelper.onLaunchTaskFailed(mActivity);
- nextTask.notifyTaskLaunchFailed(TAG);
- updateSysUiFlags(1 /* windowProgress == overview */);
- } else {
- mActivityControlHelper.onLaunchTaskSuccess(mActivity);
- }
- }, mMainThreadHandler);
- doLogGesture(NEW_TASK);
- }
- reset();
- }
- mCanceled = false;
- mFinishingRecentsAnimationForNewTaskId = -1;
- });
- }
- TOUCH_INTERACTION_LOG.addLog("finishRecentsAnimation", true);
+ startNewTask(STATE_HANDLER_INVALIDATED, success -> {
+ if (!success) {
+ // We couldn't launch the task, so take user to overview so they can
+ // decide what to do instead of staying in this broken state.
+ endLauncherTransitionController();
+ updateSysUiFlags(1 /* windowProgress == overview */);
+ }
+ doLogGesture(NEW_TASK);
+ });
}
private void reset() {
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java
index c2876180..2e9c0a3 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java
@@ -17,6 +17,7 @@
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
+import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
@@ -31,6 +32,10 @@
import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
+import com.android.systemui.shared.recents.model.Task;
+import com.android.systemui.shared.recents.model.Task.TaskKey;
+
+import java.util.ArrayList;
public class FallbackRecentsView extends RecentsView<RecentsActivity> {
@@ -54,6 +59,8 @@
private float mZoomScale = 1f;
private float mZoomTranslationY = 0f;
+ private RunningTaskInfo mRunningTaskInfo;
+
public FallbackRecentsView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
@@ -88,6 +95,12 @@
}
@Override
+ public void reset() {
+ super.reset();
+ resetViewUI();
+ }
+
+ @Override
protected void getTaskSize(DeviceProfile dp, Rect outRect) {
LayoutUtils.calculateFallbackTaskSize(getContext(), dp, outRect);
}
@@ -115,6 +128,12 @@
}
@Override
+ public void resetTaskVisuals() {
+ super.resetTaskVisuals();
+ setFullscreenProgress(mFullscreenProgress);
+ }
+
+ @Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
@@ -139,4 +158,41 @@
TRANSLATION_Y.set(this, Utilities.mapRange(mZoomInProgress, 0, mZoomTranslationY));
FULLSCREEN_PROGRESS.set(this, mZoomInProgress);
}
+
+ public void onGestureAnimationStart(RunningTaskInfo runningTaskInfo) {
+ mRunningTaskInfo = runningTaskInfo;
+ onGestureAnimationStart(runningTaskInfo == null ? -1 : runningTaskInfo.taskId);
+ }
+
+ @Override
+ public void setCurrentTask(int runningTaskId) {
+ super.setCurrentTask(runningTaskId);
+ if (mRunningTaskInfo != null && mRunningTaskInfo.taskId != runningTaskId) {
+ mRunningTaskInfo = null;
+ }
+ }
+
+ @Override
+ protected void applyLoadPlan(ArrayList<Task> tasks) {
+ // When quick-switching on 3p-launcher, we add a "dummy" tile corresponding to Launcher
+ // as well. This tile is never shown as we have setCurrentTaskHidden, but allows use to
+ // track the index of the next task appropriately, as it we are switching on any other app.
+ if (mRunningTaskInfo != null && mRunningTaskInfo.taskId == mRunningTaskId) {
+ // Check if the task list has running task
+ boolean found = false;
+ for (Task t : tasks) {
+ if (t.key.id == mRunningTaskId) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ ArrayList<Task> newList = new ArrayList<>(tasks.size() + 1);
+ newList.addAll(tasks);
+ newList.add(Task.from(new TaskKey(mRunningTaskInfo), mRunningTaskInfo, false));
+ tasks = newList;
+ }
+ }
+ super.applyLoadPlan(tasks);
+ }
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/FallbackNoButtonInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/FallbackNoButtonInputConsumer.java
index a5a8f38..7abf62d 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/FallbackNoButtonInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/FallbackNoButtonInputConsumer.java
@@ -15,43 +15,71 @@
*/
package com.android.quickstep.inputconsumers;
+import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
import static com.android.quickstep.RecentsActivity.EXTRA_TASK_ID;
import static com.android.quickstep.RecentsActivity.EXTRA_THUMBNAIL;
+import static com.android.quickstep.inputconsumers.FallbackNoButtonInputConsumer.GestureEndTarget.NEW_TASK;
import static com.android.quickstep.WindowTransformSwipeHandler.MIN_PROGRESS_FOR_OVERVIEW;
import static com.android.quickstep.inputconsumers.FallbackNoButtonInputConsumer.GestureEndTarget.HOME;
import static com.android.quickstep.inputconsumers.FallbackNoButtonInputConsumer.GestureEndTarget.LAST_TASK;
import static com.android.quickstep.inputconsumers.FallbackNoButtonInputConsumer.GestureEndTarget.RECENTS;
import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityOptions;
import android.content.Context;
import android.content.Intent;
import android.graphics.PointF;
-import android.graphics.Rect;
import android.os.Bundle;
-import android.view.WindowManager;
-import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.R;
-import com.android.quickstep.ActivityControlHelper;
+import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.quickstep.AnimatedFloat;
import com.android.quickstep.BaseSwipeUpHandler;
+import com.android.quickstep.MultiStateCallback;
import com.android.quickstep.OverviewComponentObserver;
+import com.android.quickstep.RecentsActivity;
+import com.android.quickstep.RecentsModel;
+import com.android.quickstep.SwipeSharedState;
+import com.android.quickstep.fallback.FallbackRecentsView;
import com.android.quickstep.util.ObjectWrapper;
import com.android.quickstep.util.SwipeAnimationTargetSet;
+import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.recents.model.ThumbnailData;
-import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.ActivityOptionsCompat;
+import com.android.systemui.shared.system.InputConsumerController;
-public class FallbackNoButtonInputConsumer extends BaseSwipeUpHandler {
+public class FallbackNoButtonInputConsumer extends
+ BaseSwipeUpHandler<RecentsActivity, FallbackRecentsView> {
+
+ private static final String[] STATE_NAMES = DEBUG_STATES ? new String[5] : null;
+
+ private static int getFlagForIndex(int index, String name) {
+ if (DEBUG_STATES) {
+ STATE_NAMES[index] = name;
+ }
+ return 1 << index;
+ }
+
+ private static final int STATE_RECENTS_PRESENT =
+ getFlagForIndex(0, "STATE_RECENTS_PRESENT");
+ private static final int STATE_HANDLER_INVALIDATED =
+ getFlagForIndex(1, "STATE_HANDLER_INVALIDATED");
+
+ private static final int STATE_GESTURE_CANCELLED =
+ getFlagForIndex(2, "STATE_GESTURE_CANCELLED");
+ private static final int STATE_GESTURE_COMPLETED =
+ getFlagForIndex(3, "STATE_GESTURE_COMPLETED");
+ private static final int STATE_APP_CONTROLLER_RECEIVED =
+ getFlagForIndex(4, "STATE_APP_CONTROLLER_RECEIVED");
public enum GestureEndTarget {
HOME(3, 100, 1),
RECENTS(1, 300, 0),
- LAST_TASK(0, 150, 1);
+ LAST_TASK(0, 150, 1),
+ NEW_TASK(0, 150, 1);
private final float mEndProgress;
private final long mDurationMultiplier;
@@ -64,53 +92,142 @@
}
}
- private final ActivityControlHelper mActivityControlHelper;
- private final OverviewComponentObserver mOverviewComponentObserver;
- private final int mRunningTaskId;
-
- private final DeviceProfile mDP;
- private final Rect mTargetRect = new Rect();
-
private final AnimatedFloat mLauncherAlpha = new AnimatedFloat(this::onLauncherAlphaChanged);
- private SwipeAnimationTargetSet mSwipeAnimationTargetSet;
-
private boolean mIsMotionPaused = false;
private GestureEndTarget mEndTarget;
+ private final boolean mInQuickSwitchMode;
+ private final boolean mContinuingLastGesture;
+ private final boolean mRunningOverHome;
+ private final boolean mSwipeUpOverHome;
+
+
+ private final RunningTaskInfo mRunningTaskInfo;
+
+ private Animator mFinishAnimation;
+
public FallbackNoButtonInputConsumer(Context context,
OverviewComponentObserver overviewComponentObserver,
- RunningTaskInfo runningTaskInfo) {
- super(context);
- mOverviewComponentObserver = overviewComponentObserver;
- mActivityControlHelper = overviewComponentObserver.getActivityControlHelper();
- mRunningTaskId = runningTaskInfo.id;
- mDP = InvariantDeviceProfile.INSTANCE.get(context).getDeviceProfile(context).copy(context);
+ RunningTaskInfo runningTaskInfo, RecentsModel recentsModel,
+ InputConsumerController inputConsumer,
+ boolean isLikelyToStartNewTask, boolean continuingLastGesture) {
+ super(context, overviewComponentObserver, recentsModel, inputConsumer, runningTaskInfo.id);
mLauncherAlpha.value = 1;
- mClipAnimationHelper.setBaseAlphaCallback((t, a) -> mLauncherAlpha.value);
- initTransitionTarget();
+ mRunningTaskInfo = runningTaskInfo;
+ mInQuickSwitchMode = isLikelyToStartNewTask || continuingLastGesture;
+ mContinuingLastGesture = continuingLastGesture;
+ mRunningOverHome = ActivityManagerWrapper.isHomeTask(runningTaskInfo);
+ mSwipeUpOverHome = mRunningOverHome && !mInQuickSwitchMode;
+
+ if (mSwipeUpOverHome) {
+ mClipAnimationHelper.setBaseAlphaCallback((t, a) -> 1 - mLauncherAlpha.value);
+ } else {
+ mClipAnimationHelper.setBaseAlphaCallback((t, a) -> mLauncherAlpha.value);
+ }
+
+ initStateCallbacks();
+ }
+
+ private void initStateCallbacks() {
+ mStateCallback = new MultiStateCallback(STATE_NAMES);
+
+ mStateCallback.addCallback(STATE_HANDLER_INVALIDATED,
+ this::onHandlerInvalidated);
+ mStateCallback.addCallback(STATE_RECENTS_PRESENT | STATE_HANDLER_INVALIDATED,
+ this::onHandlerInvalidatedWithRecents);
+
+ mStateCallback.addCallback(STATE_GESTURE_CANCELLED | STATE_APP_CONTROLLER_RECEIVED,
+ this::finishAnimationTargetSetAnimationComplete);
+
+ if (mInQuickSwitchMode) {
+ mStateCallback.addCallback(STATE_GESTURE_COMPLETED | STATE_APP_CONTROLLER_RECEIVED
+ | STATE_RECENTS_PRESENT,
+ this::finishAnimationTargetSet);
+ } else {
+ mStateCallback.addCallback(STATE_GESTURE_COMPLETED | STATE_APP_CONTROLLER_RECEIVED,
+ this::finishAnimationTargetSet);
+ }
}
private void onLauncherAlphaChanged() {
- if (mSwipeAnimationTargetSet != null && mEndTarget == null) {
- mClipAnimationHelper.applyTransform(mSwipeAnimationTargetSet, mTransformParams);
+ if (mRecentsAnimationWrapper.targetSet != null && mEndTarget == null) {
+ applyTransformUnchecked();
}
}
@Override
+ protected boolean onActivityInit(final RecentsActivity activity, Boolean alreadyOnHome) {
+ mActivity = activity;
+ mRecentsView = activity.getOverviewPanel();
+ linkRecentsViewScroll();
+ mRecentsView.setDisallowScrollToClearAll(true);
+ mRecentsView.getClearAllButton().setVisibilityAlpha(0);
+
+ mRecentsView.setZoomProgress(1);
+
+ if (!mContinuingLastGesture) {
+ if (mRunningOverHome) {
+ mRecentsView.onGestureAnimationStart(mRunningTaskInfo);
+ } else {
+ mRecentsView.onGestureAnimationStart(mRunningTaskId);
+ }
+ }
+ setStateOnUiThread(STATE_RECENTS_PRESENT);
+ return true;
+ }
+
+ @Override
+ protected boolean moveWindowWithRecentsScroll() {
+ return mInQuickSwitchMode;
+ }
+
+ @Override
+ public void initWhenReady() {
+ if (mInQuickSwitchMode) {
+ // Only init if we are in quickswitch mode
+ super.initWhenReady();
+ }
+ }
+
+ @Override
+ public void updateDisplacement(float displacement) {
+ if (!mInQuickSwitchMode) {
+ super.updateDisplacement(displacement);
+ }
+ }
+
+ @Override
+ protected InputConsumer createNewInputProxyHandler() {
+ // Just consume all input on the active task
+ return InputConsumer.NO_OP;
+ }
+
+ @Override
public void onMotionPauseChanged(boolean isPaused) {
- mIsMotionPaused = isPaused;
- mLauncherAlpha.animateToValue(mLauncherAlpha.value, isPaused ? 0 : 1)
- .setDuration(150).start();
- performHapticFeedback();
+ if (!mInQuickSwitchMode) {
+ mIsMotionPaused = isPaused;
+ mLauncherAlpha.animateToValue(mLauncherAlpha.value, isPaused ? 0 : 1)
+ .setDuration(150).start();
+ performHapticFeedback();
+ }
+ }
+
+ @Override
+ public Intent getLaunchIntent() {
+ if (mInQuickSwitchMode || mSwipeUpOverHome) {
+ return mOverviewComponentObserver.getOverviewIntent();
+ } else {
+ return mOverviewComponentObserver.getHomeIntent();
+ }
}
@Override
public void updateFinalShift() {
mTransformParams.setProgress(mCurrentShift.value);
- if (mSwipeAnimationTargetSet != null) {
- mClipAnimationHelper.applyTransform(mSwipeAnimationTargetSet, mTransformParams);
+ if (mRecentsAnimationWrapper.targetSet != null) {
+ applyTransformUnchecked();
}
}
@@ -118,41 +235,101 @@
public void onGestureCancelled() {
updateDisplacement(0);
mEndTarget = LAST_TASK;
- finishAnimationTargetSetAnimationComplete();
+ setStateOnUiThread(STATE_GESTURE_CANCELLED);
}
@Override
public void onGestureEnded(float endVelocity, PointF velocity, PointF downPos) {
- float flingThreshold = mContext.getResources()
- .getDimension(R.dimen.quickstep_fling_threshold_velocity);
- boolean isFling = Math.abs(endVelocity) > flingThreshold;
-
- if (isFling) {
- mEndTarget = endVelocity < 0 ? HOME : LAST_TASK;
- } else if (mIsMotionPaused) {
- mEndTarget = RECENTS;
+ if (mInQuickSwitchMode) {
+ // For now set it to non-null, it will be reset before starting the animation
+ mEndTarget = LAST_TASK;
} else {
- mEndTarget = mCurrentShift.value >= MIN_PROGRESS_FOR_OVERVIEW ? HOME : LAST_TASK;
+ float flingThreshold = mContext.getResources()
+ .getDimension(R.dimen.quickstep_fling_threshold_velocity);
+ boolean isFling = Math.abs(endVelocity) > flingThreshold;
+
+ if (isFling) {
+ mEndTarget = endVelocity < 0 ? HOME : LAST_TASK;
+ } else if (mIsMotionPaused) {
+ mEndTarget = RECENTS;
+ } else {
+ mEndTarget = mCurrentShift.value >= MIN_PROGRESS_FOR_OVERVIEW ? HOME : LAST_TASK;
+ }
}
- if (mSwipeAnimationTargetSet != null) {
- finishAnimationTargetSet();
+ setStateOnUiThread(STATE_GESTURE_COMPLETED);
+ }
+
+ @Override
+ public void onConsumerAboutToBeSwitched(SwipeSharedState sharedState) {
+ if (mInQuickSwitchMode && mEndTarget != null) {
+ sharedState.canGestureBeContinued = true;
+ sharedState.goingToLauncher = false;
+
+ mCanceled = true;
+ mCurrentShift.cancelAnimation();
+ if (mFinishAnimation != null) {
+ mFinishAnimation.cancel();
+ }
+
+ if (mRecentsView != null) {
+ if (mFinishingRecentsAnimationForNewTaskId != -1) {
+ TaskView newRunningTaskView = mRecentsView.getTaskView(
+ mFinishingRecentsAnimationForNewTaskId);
+ int newRunningTaskId = newRunningTaskView != null
+ ? newRunningTaskView.getTask().key.id
+ : -1;
+ mRecentsView.setCurrentTask(newRunningTaskId);
+ sharedState.setRecentsAnimationFinishInterrupted(newRunningTaskId);
+ }
+ mRecentsView.setOnScrollChangeListener(null);
+ }
+ } else {
+ setStateOnUiThread(STATE_HANDLER_INVALIDATED);
}
}
+
+ private void onHandlerInvalidated() {
+ mActivityInitListener.unregister();
+ if (mGestureEndCallback != null) {
+ mGestureEndCallback.run();
+ }
+ }
+
+ private void onHandlerInvalidatedWithRecents() {
+ mRecentsView.onGestureAnimationEnd();
+ mRecentsView.setDisallowScrollToClearAll(false);
+ mRecentsView.getClearAllButton().setVisibilityAlpha(1);
+ }
+
private void finishAnimationTargetSetAnimationComplete() {
switch (mEndTarget) {
- case HOME:
- mSwipeAnimationTargetSet.finishController(true, null, true);
+ case HOME: {
+ if (mSwipeUpOverHome) {
+ mRecentsAnimationWrapper.finish(false, null, false);
+ // Send a home intent to clear the task stack
+ mContext.startActivity(mOverviewComponentObserver.getHomeIntent());
+ } else {
+ mRecentsAnimationWrapper.finish(true, null, true);
+ }
break;
+ }
case LAST_TASK:
- mSwipeAnimationTargetSet.finishController(false, null, false);
+ mRecentsAnimationWrapper.finish(false, null, false);
break;
case RECENTS: {
+ if (mSwipeUpOverHome) {
+ mRecentsAnimationWrapper.finish(true, null, true);
+ break;
+ }
+
ThumbnailData thumbnail =
- mSwipeAnimationTargetSet.controller.screenshotTask(mRunningTaskId);
- mSwipeAnimationTargetSet.controller.setCancelWithDeferredScreenshot(true);
+ mRecentsAnimationWrapper.targetSet.controller.screenshotTask(mRunningTaskId);
+ mRecentsAnimationWrapper.setCancelWithDeferredScreenshot(true);
ActivityOptions options = ActivityOptions.makeCustomAnimation(mContext, 0, 0);
+ ActivityOptionsCompat.setFreezeRecentTasksList(options);
+
Bundle extras = new Bundle();
extras.putBinder(EXTRA_THUMBNAIL, new ObjectWrapper<>(thumbnail));
extras.putInt(EXTRA_TASK_ID, mRunningTaskId);
@@ -160,33 +337,58 @@
Intent intent = new Intent(mOverviewComponentObserver.getOverviewIntent())
.putExtras(extras);
mContext.startActivity(intent, options.toBundle());
- mSwipeAnimationTargetSet.controller.cleanupScreenshot();
+ mRecentsAnimationWrapper.targetSet.controller.cleanupScreenshot();
+ break;
+ }
+ case NEW_TASK: {
+ startNewTask(STATE_HANDLER_INVALIDATED, b -> {});
break;
}
}
- if (mGestureEndCallback != null) {
- mGestureEndCallback.run();
- }
+
+ setStateOnUiThread(STATE_HANDLER_INVALIDATED);
}
private void finishAnimationTargetSet() {
+ if (mInQuickSwitchMode) {
+ // Recalculate the end target, some views might have been initialized after
+ // gesture has ended.
+ if (mRecentsView == null || !mRecentsAnimationWrapper.hasTargets()) {
+ mEndTarget = LAST_TASK;
+ } else {
+ final int runningTaskIndex = mRecentsView.getRunningTaskIndex();
+ final int taskToLaunch = mRecentsView.getNextPage();
+ mEndTarget = (runningTaskIndex >= 0 && taskToLaunch != runningTaskIndex)
+ ? NEW_TASK : LAST_TASK;
+ }
+ }
+
float endProgress = mEndTarget.mEndProgress;
- if (mCurrentShift.value != endProgress) {
+ if (mCurrentShift.value != endProgress || mInQuickSwitchMode) {
AnimatorSet anim = new AnimatorSet();
anim.play(mLauncherAlpha.animateToValue(
mLauncherAlpha.value, mEndTarget.mLauncherAlpha));
anim.play(mCurrentShift.animateToValue(mCurrentShift.value, endProgress));
- anim.setDuration((long) (mEndTarget.mDurationMultiplier *
- Math.abs(endProgress - mCurrentShift.value)));
- anim.addListener(new AnimatorListenerAdapter() {
+
+ long duration = (long) (mEndTarget.mDurationMultiplier *
+ Math.abs(endProgress - mCurrentShift.value));
+ if (mRecentsView != null) {
+ duration = Math.max(duration, mRecentsView.getScroller().getDuration());
+ }
+
+ anim.setDuration(duration);
+ anim.addListener(new AnimationSuccessListener() {
+
@Override
- public void onAnimationEnd(Animator animation) {
+ public void onAnimationSuccess(Animator animator) {
finishAnimationTargetSetAnimationComplete();
+ mFinishAnimation = null;
}
});
anim.start();
+ mFinishAnimation = anim;
} else {
finishAnimationTargetSetAnimationComplete();
}
@@ -194,34 +396,20 @@
@Override
public void onRecentsAnimationStart(SwipeAnimationTargetSet targetSet) {
- mSwipeAnimationTargetSet = targetSet;
- Rect overviewStackBounds = new Rect(0, 0, mDP.widthPx, mDP.heightPx);
- RemoteAnimationTargetCompat runningTaskTarget = targetSet.findTask(mRunningTaskId);
+ super.onRecentsAnimationStart(targetSet);
+ mRecentsAnimationWrapper.enableInputConsumer();
- mDP.updateIsSeascape(mContext.getSystemService(WindowManager.class));
- if (targetSet.homeContentInsets != null) {
- mDP.updateInsets(targetSet.homeContentInsets);
+ if (mRunningOverHome) {
+ mClipAnimationHelper.prepareAnimation(mDp, true);
}
+ applyTransformUnchecked();
- if (runningTaskTarget != null) {
- mClipAnimationHelper.updateSource(overviewStackBounds, runningTaskTarget);
- }
- mClipAnimationHelper.prepareAnimation(mDP, false /* isOpening */);
- initTransitionTarget();
- mClipAnimationHelper.applyTransform(mSwipeAnimationTargetSet, mTransformParams);
-
- if (mEndTarget != null) {
- finishAnimationTargetSet();
- }
- }
-
- private void initTransitionTarget() {
- mTransitionDragLength = mActivityControlHelper.getSwipeUpDestinationAndLength(
- mDP, mContext, mTargetRect);
- mDragLengthFactor = (float) mDP.heightPx / mTransitionDragLength;
- mClipAnimationHelper.updateTargetRect(mTargetRect);
+ setStateOnUiThread(STATE_APP_CONTROLLER_RECEIVED);
}
@Override
- public void onRecentsAnimationCanceled() { }
+ public void onRecentsAnimationCanceled() {
+ mRecentsAnimationWrapper.setController(null);
+ setStateOnUiThread(STATE_HANDLER_INVALIDATED);
+ }
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
index 9114995..86766d9 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
@@ -35,7 +35,6 @@
import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
import android.content.ContextWrapper;
-import android.content.Intent;
import android.graphics.PointF;
import android.graphics.RectF;
import android.os.Build;
@@ -79,7 +78,6 @@
private final CachedEventDispatcher mRecentsViewDispatcher = new CachedEventDispatcher();
private final RunningTaskInfo mRunningTask;
- private final Intent mHomeIntent;
private final OverviewCallbacks mOverviewCallbacks;
private final SwipeSharedState mSwipeSharedState;
private final InputMonitorCompat mInputMonitorCompat;
@@ -117,12 +115,13 @@
private float mStartDisplacement;
private Handler mMainThreadHandler;
- private Runnable mCancelRecentsAnimationRunnable = () ->
+ private Runnable mCancelRecentsAnimationRunnable = () -> {
ActivityManagerWrapper.getInstance().cancelRecentsAnimation(
true /* restoreHomeStackPosition */);
+ };
public OtherActivityInputConsumer(Context base, RunningTaskInfo runningTaskInfo,
- Intent homeIntent, boolean isDeferredDownTarget, OverviewCallbacks overviewCallbacks,
+ boolean isDeferredDownTarget, OverviewCallbacks overviewCallbacks,
Consumer<OtherActivityInputConsumer> onCompleteCallback,
SwipeSharedState swipeSharedState, InputMonitorCompat inputMonitorCompat,
RectF swipeTouchRegion, boolean disableHorizontalSwipe,
@@ -131,7 +130,6 @@
mMainThreadHandler = new Handler(Looper.getMainLooper());
mRunningTask = runningTaskInfo;
- mHomeIntent = homeIntent;
mMode = SysUINavigationMode.getMode(base);
mSwipeTouchRegion = swipeTouchRegion;
mHandlerFactory = handlerFactory;
@@ -204,7 +202,7 @@
// Start the window animation on down to give more time for launcher to draw if the
// user didn't start the gesture over the back button
if (!mIsDeferredDownTarget) {
- startTouchTrackingForWindowAnimation(ev.getEventTime());
+ startTouchTrackingForWindowAnimation(ev.getEventTime(), false);
}
RaceConditionTracker.onEvent(DOWN_EVT, EXIT);
@@ -253,6 +251,10 @@
}
}
+ float horizontalDist = Math.abs(displacementX);
+ float upDist = -displacement;
+ boolean isLikelyToStartNewTask = horizontalDist > upDist;
+
if (!mPassedPilferInputSlop) {
float displacementY = mLastPos.y - mDownPos.y;
if (squaredHypot(displacementX, displacementY) >= mSquaredTouchSlop) {
@@ -268,7 +270,8 @@
if (mIsDeferredDownTarget) {
// Deferred gesture, start the animation and gesture tracking once
// we pass the actual touch slop
- startTouchTrackingForWindowAnimation(ev.getEventTime());
+ startTouchTrackingForWindowAnimation(
+ ev.getEventTime(), isLikelyToStartNewTask);
}
if (!mPassedWindowMoveSlop) {
mPassedWindowMoveSlop = true;
@@ -286,9 +289,6 @@
}
if (mMode == Mode.NO_BUTTON) {
- float horizontalDist = Math.abs(displacementX);
- float upDist = -displacement;
- boolean isLikelyToStartNewTask = horizontalDist > upDist;
mMotionPauseDetector.setDisallowPause(upDist < mMotionPauseMinDisplacement
|| isLikelyToStartNewTask);
mMotionPauseDetector.addPosition(displacement, ev.getEventTime());
@@ -320,12 +320,13 @@
mInteractionHandler.onGestureStarted();
}
- private void startTouchTrackingForWindowAnimation(long touchTimeMs) {
+ private void startTouchTrackingForWindowAnimation(
+ long touchTimeMs, boolean isLikelyToStartNewTask) {
TOUCH_INTERACTION_LOG.addLog("startRecentsAnimation");
RecentsAnimationListenerSet listenerSet = mSwipeSharedState.getActiveListener();
final BaseSwipeUpHandler handler = mHandlerFactory.newHandler(mRunningTask, touchTimeMs,
- listenerSet != null);
+ listenerSet != null, isLikelyToStartNewTask);
mInteractionHandler = handler;
handler.setGestureEndCallback(this::onInteractionGestureFinished);
@@ -340,7 +341,7 @@
RecentsAnimationListenerSet newListenerSet =
mSwipeSharedState.newRecentsAnimationListenerSet();
newListenerSet.addListener(handler);
- startRecentsActivityAsync(mHomeIntent, newListenerSet);
+ startRecentsActivityAsync(handler.getLaunchIntent(), newListenerSet);
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
index 432f8a1..66ddc72 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
@@ -269,7 +269,7 @@
private int mTaskListChangeId = -1;
// Only valid until the launcher state changes to NORMAL
- private int mRunningTaskId = -1;
+ protected int mRunningTaskId = -1;
private boolean mRunningTaskTileHidden;
private Task mTmpRunningTask;
@@ -289,7 +289,7 @@
@ViewDebug.ExportedProperty(category = "launcher")
private float mContentAlpha = 1;
@ViewDebug.ExportedProperty(category = "launcher")
- private float mFullscreenProgress = 0;
+ protected float mFullscreenProgress = 0;
// Keeps track of task id whose visual state should not be reset
private int mIgnoreResetTaskId = -1;
@@ -532,7 +532,7 @@
return true;
}
- private void applyLoadPlan(ArrayList<Task> tasks) {
+ protected void applyLoadPlan(ArrayList<Task> tasks) {
if (mPendingAnimation != null) {
mPendingAnimation.addEndListener((onEndListener) -> applyLoadPlan(tasks));
return;
@@ -604,6 +604,7 @@
TaskView taskView = (TaskView) getChildAt(i);
if (mIgnoreResetTaskId != taskView.getTask().key.id) {
taskView.resetVisualProperties();
+ taskView.setStableAlpha(mContentAlpha);
}
}
if (mRunningTaskTileHidden) {
@@ -854,12 +855,14 @@
* is called. Also scrolls the view to this task.
*/
public void showCurrentTask(int runningTaskId) {
- if (getChildCount() == 0) {
+ if (getTaskView(runningTaskId) == null) {
+ boolean wasEmpty = getChildCount() == 0;
// Add an empty view for now until the task plan is loaded and applied
final TaskView taskView = mTaskViewPool.getView();
- addView(taskView);
- addView(mClearAllButton);
-
+ addView(taskView, 0);
+ if (wasEmpty) {
+ addView(mClearAllButton);
+ }
// The temporary running task is only used for the duration between the start of the
// gesture and the task list is loaded and applied
mTmpRunningTask = new Task(new Task.TaskKey(runningTaskId, 0, new Intent(),
diff --git a/quickstep/res/values-fr/strings.xml b/quickstep/res/values-fr/strings.xml
index 5394f49..01dcff2 100644
--- a/quickstep/res/values-fr/strings.xml
+++ b/quickstep/res/values-fr/strings.xml
@@ -33,5 +33,5 @@
<string name="time_left_for_app" msgid="3111996412933644358">"Encore <xliff:g id="TIME">%1$s</xliff:g> aujourd\'hui"</string>
<string name="title_app_suggestions" msgid="4185902664111965088">"Suggestions d\'applications"</string>
<string name="all_apps_label" msgid="8542784161730910663">"Toutes les applications"</string>
- <string name="all_apps_prediction_tip" msgid="2672336544844936186">"Vos applications prévues"</string>
+ <string name="all_apps_prediction_tip" msgid="2672336544844936186">"Applications prévues pour vous"</string>
</resources>
diff --git a/quickstep/res/values-hi/strings.xml b/quickstep/res/values-hi/strings.xml
index 0467af4..387d509 100644
--- a/quickstep/res/values-hi/strings.xml
+++ b/quickstep/res/values-hi/strings.xml
@@ -27,7 +27,7 @@
<string name="accessibility_close_task" msgid="5354563209433803643">"बंद करें"</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ऐप्लिकेशन इस्तेमाल की सेटिंग"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"सभी ऐप्लिकेशन बंद करें"</string>
- <string name="accessibility_recent_apps" msgid="4058661986695117371">"हाल ही में इस्तेमाल किए गए एेप्लिकेशन"</string>
+ <string name="accessibility_recent_apps" msgid="4058661986695117371">"हाल ही में इस्तेमाल किए गए ऐप्लिकेशन"</string>
<string name="task_contents_description_with_remaining_time" msgid="4479688746574672685">"<xliff:g id="TASK_DESCRIPTION">%1$s</xliff:g>, <xliff:g id="REMAINING_TIME">%2$s</xliff:g>"</string>
<string name="shorter_duration_less_than_one_minute" msgid="4722015666335015336">"<1 मिनट"</string>
<string name="time_left_for_app" msgid="3111996412933644358">"आज <xliff:g id="TIME">%1$s</xliff:g> और चलेगा"</string>
diff --git a/quickstep/res/values-mr/strings.xml b/quickstep/res/values-mr/strings.xml
index 1ca558a..cccece7 100644
--- a/quickstep/res/values-mr/strings.xml
+++ b/quickstep/res/values-mr/strings.xml
@@ -27,7 +27,7 @@
<string name="accessibility_close_task" msgid="5354563209433803643">"बंद"</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"अॅप वापर सेटिंग्ज"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"सर्व साफ करा"</string>
- <string name="accessibility_recent_apps" msgid="4058661986695117371">"अलीकडील अॅप्स"</string>
+ <string name="accessibility_recent_apps" msgid="4058661986695117371">"अलीकडील अॅप्स"</string>
<string name="task_contents_description_with_remaining_time" msgid="4479688746574672685">"<xliff:g id="TASK_DESCRIPTION">%1$s</xliff:g>, <xliff:g id="REMAINING_TIME">%2$s</xliff:g>"</string>
<string name="shorter_duration_less_than_one_minute" msgid="4722015666335015336">"१मिहून कमी"</string>
<string name="time_left_for_app" msgid="3111996412933644358">"आज <xliff:g id="TIME">%1$s</xliff:g>शिल्लक आहे"</string>
diff --git a/quickstep/src/com/android/quickstep/RecentTasksList.java b/quickstep/src/com/android/quickstep/RecentTasksList.java
index 7a1d0e8..d807b89 100644
--- a/quickstep/src/com/android/quickstep/RecentTasksList.java
+++ b/quickstep/src/com/android/quickstep/RecentTasksList.java
@@ -28,8 +28,6 @@
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.KeyguardManagerCompat;
-import com.android.systemui.shared.system.RecentTaskInfoCompat;
-import com.android.systemui.shared.system.TaskDescriptionCompat;
import com.android.systemui.shared.system.TaskStackChangeListener;
import java.util.ArrayList;
import java.util.Collections;
@@ -86,8 +84,9 @@
: () -> callback.accept(copyOf(mTasks));
if (mLastLoadedId == mChangeId && (!mLastLoadHadKeysOnly || loadKeysOnly)) {
- // The list is up to date, callback with the same list
- mMainThreadExecutor.execute(resultCallback);
+ // The list is up to date, send the callback on the next frame,
+ // so that requestID can be returned first.
+ mMainThreadExecutor.getHandler().post(resultCallback);
return requestLoadId;
}
@@ -165,15 +164,11 @@
int taskCount = rawTasks.size();
for (int i = 0; i < taskCount; i++) {
ActivityManager.RecentTaskInfo rawTask = rawTasks.get(i);
- RecentTaskInfoCompat t = new RecentTaskInfoCompat(rawTask);
Task.TaskKey taskKey = new Task.TaskKey(rawTask);
Task task;
if (!loadKeysOnly) {
- ActivityManager.TaskDescription rawTd = t.getTaskDescription();
- TaskDescriptionCompat td = new TaskDescriptionCompat(rawTd);
- boolean isLocked = tmpLockedUsers.get(t.getUserId());
- task = new Task(taskKey, td.getPrimaryColor(), td.getBackgroundColor(),
- t.supportsSplitScreenMultiWindow(), isLocked, rawTd, t.getTopActivity());
+ boolean isLocked = tmpLockedUsers.get(taskKey.userId);
+ task = Task.from(taskKey, rawTask, isLocked);
} else {
task = new Task(taskKey);
}
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index 9e3bf2f..885fdbf 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -17,7 +17,6 @@
package com.android.quickstep;
import static com.android.launcher3.ui.TaplTestsLauncher3.getAppPackageName;
-
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
@@ -208,7 +207,7 @@
@Test
@NavigationModeSwitch
-// @PortraitLandscape
+ @PortraitLandscape
public void testBackground() throws Exception {
startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR));
final Background background = mLauncher.getBackground();
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index c0859d3..50f92da 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -88,7 +88,7 @@
<string name="notification_dots_title" msgid="9062440428204120317">"Punts de notificació"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"Activats"</string>
<string name="notification_dots_desc_off" msgid="1760796511504341095">"Desactivats"</string>
- <string name="title_missing_notification_access" msgid="7503287056163941064">"Cal que tingui accés a les notificacions"</string>
+ <string name="title_missing_notification_access" msgid="7503287056163941064">"Cal accés a les notificacions"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Per veure els punts de notificació, activa les notificacions de l\'aplicació <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Canvia la configuració"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Mostra els punts de notificació"</string>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index 3054214..211f735 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -30,10 +30,10 @@
<string name="home_screen" msgid="806512411299847073">"Layar utama"</string>
<string name="custom_actions" msgid="3747508247759093328">"Tindakan khusus"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Sentuh lama untuk memilih widget."</string>
- <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Tap dua kalip & tahan untuk mengambil widget atau menggunakan tindakan khusus."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Ketuk dua kali & tahan untuk mengambil widget atau menggunakan tindakan khusus."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"lebar %1$d x tinggi %2$d"</string>
- <string name="add_item_request_drag_hint" msgid="5899764264480397019">"Tap lama untuk menempatkan secara manual"</string>
+ <string name="add_item_request_drag_hint" msgid="5899764264480397019">"Sentuh lama untuk menempatkan secara manual"</string>
<string name="place_automatically" msgid="8064208734425456485">"Tambahkan otomatis"</string>
<string name="all_apps_search_bar_hint" msgid="1390553134053255246">"Telusuri aplikasi"</string>
<string name="all_apps_loading_message" msgid="5813968043155271636">"Memuat aplikasi…"</string>
@@ -41,8 +41,8 @@
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Telusuri aplikasi lainnya"</string>
<string name="label_application" msgid="8531721983832654978">"Aplikasi"</string>
<string name="notifications_header" msgid="1404149926117359025">"Notifikasi"</string>
- <string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Tap lama untuk memilih pintasan."</string>
- <string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Tap dua kali & tahan untuk memilih pintasan atau menggunakan tindakan khusus."</string>
+ <string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Sentuh lama untuk memilih pintasan."</string>
+ <string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Ketuk dua kali & tahan untuk memilih pintasan atau menggunakan tindakan khusus."</string>
<string name="out_of_space" msgid="4691004494942118364">"Tidak ada ruang lagi pada layar Utama ini."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Tidak ada ruang tersisa di baki Favorit"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Daftar aplikasi"</string>
@@ -73,8 +73,8 @@
<string name="workspace_scroll_format" msgid="8458889198184077399">"Layar utama %1$d dari %2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Halaman layar utama baru"</string>
<string name="folder_opened" msgid="94695026776264709">"Folder dibuka, <xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
- <string name="folder_tap_to_close" msgid="4625795376335528256">"Tap untuk menutup folder"</string>
- <string name="folder_tap_to_rename" msgid="4017685068016979677">"Tap untuk menyimpan ganti nama"</string>
+ <string name="folder_tap_to_close" msgid="4625795376335528256">"Ketuk untuk menutup folder"</string>
+ <string name="folder_tap_to_rename" msgid="4017685068016979677">"Ketuk untuk menyimpan ganti nama"</string>
<string name="folder_closed" msgid="4100806530910930934">"Folder ditutup"</string>
<string name="folder_renamed" msgid="1794088362165669656">"Folder diganti namanya menjadi <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format" msgid="6629239338071103179">"Folder: <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml
index 19c0697..49e3898 100644
--- a/res/values-mr/strings.xml
+++ b/res/values-mr/strings.xml
@@ -35,18 +35,18 @@
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d रूंद बाय %2$d उंच"</string>
<string name="add_item_request_drag_hint" msgid="5899764264480397019">"स्वतः ठेवण्यासाठी स्पर्श करा आणि धरून ठेवा"</string>
<string name="place_automatically" msgid="8064208734425456485">"आपोआप जोडा"</string>
- <string name="all_apps_search_bar_hint" msgid="1390553134053255246">"अॅप्स शोधा"</string>
- <string name="all_apps_loading_message" msgid="5813968043155271636">"अॅप्स लोड करत आहे…"</string>
- <string name="all_apps_no_search_results" msgid="3200346862396363786">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" शी जुळणारे कोणतेही अॅप्स आढळले नाहीत"</string>
- <string name="all_apps_search_market_message" msgid="1366263386197059176">"अधिक अॅप्स शोधा"</string>
+ <string name="all_apps_search_bar_hint" msgid="1390553134053255246">"अॅप्स शोधा"</string>
+ <string name="all_apps_loading_message" msgid="5813968043155271636">"अॅप्स लोड करत आहे…"</string>
+ <string name="all_apps_no_search_results" msgid="3200346862396363786">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" शी जुळणारे कोणतेही अॅप्स आढळले नाहीत"</string>
+ <string name="all_apps_search_market_message" msgid="1366263386197059176">"अधिक अॅप्स शोधा"</string>
<string name="label_application" msgid="8531721983832654978">"ॲप"</string>
<string name="notifications_header" msgid="1404149926117359025">"सूचना"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"शॉर्टकट निवडण्यासाठी स्पर्श करा आणि धरून ठेवा."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"शॉर्टकट निवडण्यासाठी किंवा कस्टम क्रिया वापरण्यासाठी दोनदा टॅप करा आणि धरून ठेवा."</string>
<string name="out_of_space" msgid="4691004494942118364">"या मुख्य स्क्रीनवर आणखी जागा नाही."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"आवडीच्या ट्रे मध्ये आणखी जागा नाही"</string>
- <string name="all_apps_button_label" msgid="8130441508702294465">"अॅप्स सूची"</string>
- <string name="all_apps_button_personal_label" msgid="1315764287305224468">"वैयक्तिक अॅप्स सूची"</string>
+ <string name="all_apps_button_label" msgid="8130441508702294465">"अॅप्स सूची"</string>
+ <string name="all_apps_button_personal_label" msgid="1315764287305224468">"वैयक्तिक अॅप्स सूची"</string>
<string name="all_apps_button_work_label" msgid="7270707118948892488">"कामाच्या ठिकाणी वापरली जाणाऱ्या अॅप्सची सूची"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"होम"</string>
<string name="remove_drop_target_label" msgid="7812859488053230776">"काढा"</string>
@@ -136,7 +136,7 @@
<string name="bottom_work_tab_user_education_title" msgid="5785851780786322825">"कामाची अॅप्स येथे मिळवा"</string>
<string name="bottom_work_tab_user_education_body" msgid="2818107472360579152">"प्रत्येक कार्य अॅपला एक बॅज असतो आणि तो तुमच्या संस्थेकडून सुरक्षित ठेवला जातो. अधिक सहज अॅक्सेससाठी अॅप्स तुमच्या होम स्क्रीनवर हलवा."</string>
<string name="work_mode_on_label" msgid="4781128097185272916">"तुमच्या संस्थेकडून व्यवस्थापित"</string>
- <string name="work_mode_off_label" msgid="3194894777601421047">"सूचना आणि अॅप्स बंद आहेत"</string>
+ <string name="work_mode_off_label" msgid="3194894777601421047">"सूचना आणि अॅप्स बंद आहेत"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"बंद करा"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"बंद केले"</string>
<string name="remote_action_failed" msgid="1383965239183576790">"हे करता आले नाही: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 34e267d..23b00d0 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -90,7 +90,7 @@
<string name="notification_dots_title" msgid="9062440428204120317">"Значки уведомлений"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"Включены"</string>
<string name="notification_dots_desc_off" msgid="1760796511504341095">"Отключены"</string>
- <string name="title_missing_notification_access" msgid="7503287056163941064">"Нет доступа к уведомлениям"</string>
+ <string name="title_missing_notification_access" msgid="7503287056163941064">"Нужен доступ к уведомлениям"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Чтобы показывать значки уведомлений, включите уведомления в приложении \"<xliff:g id="NAME">%1$s</xliff:g>\""</string>
<string name="title_change_settings" msgid="1376365968844349552">"Изменить настройки"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Показывать значки уведомлений"</string>
diff --git a/src/com/android/launcher3/anim/Interpolators.java b/src/com/android/launcher3/anim/Interpolators.java
index b169cb8..8443231 100644
--- a/src/com/android/launcher3/anim/Interpolators.java
+++ b/src/com/android/launcher3/anim/Interpolators.java
@@ -144,7 +144,8 @@
public static Interpolator clampToProgress(Interpolator interpolator, float lowerBound,
float upperBound) {
if (upperBound <= lowerBound) {
- throw new IllegalArgumentException("lowerBound must be less than upperBound");
+ throw new IllegalArgumentException(String.format(
+ "lowerBound (%f) must be less than upperBound (%f)", lowerBound, upperBound));
}
return t -> {
if (t < lowerBound) {