Merge "Adding waiting for Launcher initialization" into ub-launcher3-rvc-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 1515ffa..ea0d840 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java
@@ -120,7 +120,7 @@
protected MultiStateCallback mStateCallback;
protected boolean mCanceled;
- protected int mFinishingRecentsAnimationForNewTaskId = -1;
+ protected int mLastStartedTaskId = -1;
private RecentsOrientedState mOrientedState;
@@ -199,7 +199,7 @@
mRecentsAnimationTargets));
}
- protected void startNewTask(int successStateFlag, Consumer<Boolean> resultCallback) {
+ protected void startNewTask(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.
@@ -210,18 +210,17 @@
if (!mCanceled) {
TaskView nextTask = mRecentsView.getTaskView(taskId);
if (nextTask != null) {
+ mLastStartedTaskId = taskId;
nextTask.launchTask(false /* animate */, true /* freezeTaskList */,
success -> {
resultCallback.accept(success);
if (!success) {
mActivityInterface.onLaunchTaskFailed();
nextTask.notifyTaskLaunchFailed(TAG);
- } else {
- mActivityInterface.onLaunchTaskSuccess();
+ mRecentsAnimationController.finish(true /* toRecents */, null);
}
}, MAIN_EXECUTOR.getHandler());
}
- mStateCallback.setStateOnUiThread(successStateFlag);
}
mCanceled = false;
}
@@ -241,6 +240,7 @@
}
/**
+ * TODO can we remove this now that we don't finish the controller until onTaskAppeared()?
* @return whether the recents animation has started and there are valid app targets.
*/
protected boolean hasTargets() {
@@ -306,6 +306,30 @@
}
}
+ @Override
+ public void onTaskAppeared(RemoteAnimationTargetCompat appearedTaskTarget) {
+ if (mRecentsAnimationController != null) {
+ if (handleTaskAppeared(appearedTaskTarget)) {
+ mRecentsAnimationController.finish(false /* toRecents */,
+ null /* onFinishComplete */);
+ mActivityInterface.onLaunchTaskSuccess();
+ }
+ }
+ }
+
+ /** @return Whether this was the task we were waiting to appear, and thus handled it. */
+ protected abstract boolean handleTaskAppeared(RemoteAnimationTargetCompat appearedTaskTarget);
+
+ /**
+ * @return The index of the TaskView in RecentsView whose taskId matches the task that will
+ * resume if we finish the controller.
+ */
+ protected int getLastAppearedTaskIndex() {
+ return mGestureState.getLastAppearedTaskId() != -1
+ ? mRecentsView.getTaskIndexForId(mGestureState.getLastAppearedTaskId())
+ : mRecentsView.getRunningTaskIndex();
+ }
+
private Rect getStackBounds(DeviceProfile dp) {
if (mActivity != null) {
int loc[] = new int[2];
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackSwipeHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackSwipeHandler.java
index 894bd0c..d24b16a 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackSwipeHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackSwipeHandler.java
@@ -46,11 +46,11 @@
import com.android.quickstep.GestureState.GestureEndTarget;
import com.android.quickstep.fallback.FallbackRecentsView;
import com.android.quickstep.util.RectFSpringAnim;
-import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.ActivityOptionsCompat;
import com.android.systemui.shared.system.InputConsumerController;
+import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
/**
* Handles the navigation gestures when a 3rd party launcher is the default home activity.
@@ -320,15 +320,6 @@
}
if (mRecentsView != null) {
- if (mFinishingRecentsAnimationForNewTaskId != -1) {
- TaskView newRunningTaskView = mRecentsView.getTaskView(
- mFinishingRecentsAnimationForNewTaskId);
- int newRunningTaskId = newRunningTaskView != null
- ? newRunningTaskView.getTask().key.id
- : -1;
- mRecentsView.setCurrentTask(newRunningTaskId);
- mGestureState.setFinishingRecentsAnimationTaskId(newRunningTaskId);
- }
mRecentsView.setOnScrollChangeListener(null);
}
} else {
@@ -401,7 +392,7 @@
break;
}
case NEW_TASK: {
- startNewTask(STATE_HANDLER_INVALIDATED, b -> {});
+ startNewTask(success -> { });
break;
}
}
@@ -416,7 +407,7 @@
if (mRecentsView == null || !hasTargets()) {
mGestureState.setEndTarget(LAST_TASK);
} else {
- final int runningTaskIndex = mRecentsView.getRunningTaskIndex();
+ final int runningTaskIndex = getLastAppearedTaskIndex();
final int taskToLaunch = mRecentsView.getNextPage();
mGestureState.setEndTarget(
(runningTaskIndex >= 0 && taskToLaunch != runningTaskIndex)
@@ -494,6 +485,11 @@
super.onRecentsAnimationCanceled(thumbnailData);
}
+ @Override
+ protected boolean handleTaskAppeared(RemoteAnimationTargetCompat appearedTaskTarget) {
+ return true;
+ }
+
/**
* Creates an animation that transforms the current app window into the home app.
* @param startProgress The progress of {@link #mCurrentShift} to start the window from.
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java
index 5e688fb..d4175e2 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java
@@ -36,6 +36,7 @@
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.UserHandle;
+import android.util.Log;
import android.util.Pair;
import android.view.MotionEvent;
import android.view.View;
@@ -55,6 +56,7 @@
import com.android.launcher3.appprediction.PredictionUiStateManager;
import com.android.launcher3.statehandlers.DepthController;
import com.android.launcher3.statehandlers.DepthController.ClampedDepthProperty;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.views.FloatingIconView;
import com.android.quickstep.SysUINavigationMode.Mode;
@@ -383,6 +385,9 @@
@Override
public boolean switchToRecentsIfVisible(Runnable onCompleteCallback) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.OVERIEW_NOT_ALLAPPS, "switchToRecentsIfVisible");
+ }
Launcher launcher = getVisibleLauncher();
if (launcher == null) {
return false;
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandler.java
index a9c4f4a..e0393c7 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandler.java
@@ -32,7 +32,6 @@
import static com.android.quickstep.GestureState.GestureEndTarget.RECENTS;
import static com.android.quickstep.GestureState.STATE_END_TARGET_ANIMATION_FINISHED;
import static com.android.quickstep.GestureState.STATE_RECENTS_SCROLLING_FINISHED;
-import static com.android.quickstep.GestureState.STATE_TASK_APPEARED_DURING_SWITCH;
import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
import static com.android.quickstep.SysUINavigationMode.Mode.TWO_BUTTONS;
import static com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState.HIDE;
@@ -264,8 +263,6 @@
| STATE_RECENTS_SCROLLING_FINISHED,
this::onSettledOnEndTarget);
- mGestureState.runOnceAtState(STATE_TASK_APPEARED_DURING_SWITCH, this::onTaskAppeared);
-
mStateCallback.runOnceAtState(STATE_HANDLER_INVALIDATED, this::invalidateHandler);
mStateCallback.runOnceAtState(STATE_LAUNCHER_PRESENT | STATE_HANDLER_INVALIDATED,
this::invalidateHandlerWithLauncher);
@@ -769,20 +766,16 @@
}
}
- private void onTaskAppeared() {
- RemoteAnimationTargetCompat app = mGestureState.getAnimationTarget();
- if (mRecentsAnimationController != null && app != null) {
-
- // TODO(b/152480470): Update Task target animation after onTaskAppeared holistically.
- /* android.util.Log.d("LauncherSwipeHandler", "onTaskAppeared");
-
- final boolean result = mRecentsAnimationController.removeTaskTarget(app);
- mGestureState.setAnimationTarget(null);
- android.util.Log.d("LauncherSwipeHandler", "removeTask, result=" + result); */
-
- mRecentsAnimationController.finish(false /* toRecents */,
- null /* onFinishComplete */);
+ @Override
+ protected boolean handleTaskAppeared(RemoteAnimationTargetCompat appearedTaskTarget) {
+ if (mStateCallback.hasStates(STATE_HANDLER_INVALIDATED)) {
+ return false;
}
+ if (appearedTaskTarget.taskId == mLastStartedTaskId) {
+ reset();
+ return true;
+ }
+ return false;
}
private GestureEndTarget calculateEndTarget(PointF velocity, float endVelocity, boolean isFling,
@@ -1029,12 +1022,22 @@
// skip doing any future work here for the current gesture.
return;
}
- if (target == NEW_TASK && mRecentsView != null
- && mRecentsView.getNextPage() == mRecentsView.getRunningTaskIndex()) {
- // We are about to launch the current running task, so use LAST_TASK state
- // instead of NEW_TASK. This could happen, for example, if our scroll is
- // aborted after we determined the target to be NEW_TASK.
- mGestureState.setEndTarget(LAST_TASK);
+ if (mRecentsView != null) {
+ int taskToLaunch = mRecentsView.getNextPage();
+ int runningTask = getLastAppearedTaskIndex();
+ if (target == NEW_TASK && taskToLaunch == runningTask) {
+ // We are about to launch the current running task, so use LAST_TASK
+ // state instead of NEW_TASK. This could happen, for example, if our
+ // scroll is aborted after we determined the target to be NEW_TASK.
+ mGestureState.setEndTarget(LAST_TASK);
+ } else if (target == LAST_TASK && taskToLaunch != runningTask) {
+ // We are about to re-launch the previously running task, but we can't
+ // just finish the controller like we normally would because that would
+ // instead resume the last task that appeared. As a workaround, launch
+ // the task as if it were a new task.
+ // TODO: is this expected?
+ mGestureState.setEndTarget(NEW_TASK);
+ }
}
mGestureState.setState(STATE_END_TARGET_ANIMATION_FINISHED);
}
@@ -1158,8 +1161,9 @@
@UiThread
private void startNewTaskInternal() {
- startNewTask(STATE_HANDLER_INVALIDATED, success -> {
+ startNewTask(success -> {
if (!success) {
+ reset();
// 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();
@@ -1184,19 +1188,6 @@
.getAnimationPlayer().isStarted()) {
mLauncherTransitionController.getAnimationPlayer().cancel();
}
-
- if (mFinishingRecentsAnimationForNewTaskId != -1) {
- // If we are canceling mid-starting a new task, switch to the screenshot since the
- // recents animation has finished
- switchToScreenshot();
- TaskView newRunningTaskView = mRecentsView.getTaskView(
- mFinishingRecentsAnimationForNewTaskId);
- int newRunningTaskId = newRunningTaskView != null
- ? newRunningTaskView.getTask().key.id
- : -1;
- mRecentsView.setCurrentTask(newRunningTaskId);
- mGestureState.setFinishingRecentsAnimationTaskId(newRunningTaskId);
- }
}
private void invalidateHandler() {
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 ce7a141..8eb15cf 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
@@ -30,8 +30,6 @@
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_TRACING_ENABLED;
import android.annotation.TargetApi;
-import android.app.ActivityManager;
-import android.app.ActivityManager.RunningTaskInfo;
import android.app.PendingIntent;
import android.app.RemoteAction;
import android.app.Service;
@@ -518,8 +516,12 @@
private GestureState createGestureState() {
GestureState gestureState = new GestureState(mOverviewComponentObserver,
ActiveGestureLog.INSTANCE.generateAndSetLogId());
- gestureState.updateRunningTask(TraceHelper.whitelistIpcs("getRunningTask.0",
- () -> mAM.getRunningTask(false /* filterOnlyVisibleRecents */)));
+ if (mTaskAnimationManager.isRecentsAnimationRunning()) {
+ gestureState.updateRunningTask(mGestureState.getRunningTask());
+ } else {
+ gestureState.updateRunningTask(TraceHelper.whitelistIpcs("getRunningTask.0",
+ () -> mAM.getRunningTask(false /* filterOnlyVisibleRecents */)));
+ }
return gestureState;
}
@@ -637,14 +639,7 @@
runningComponent != null && runningComponent.equals(homeComponent);
}
- if (previousGestureState.getFinishingRecentsAnimationTaskId() > 0) {
- // If the finish animation was interrupted, then continue using the other activity input
- // consumer but with the next task as the running task
- RunningTaskInfo info = new ActivityManager.RunningTaskInfo();
- info.id = previousGestureState.getFinishingRecentsAnimationTaskId();
- gestureState.updateRunningTask(info);
- return createOtherActivityInputConsumer(previousGestureState, gestureState, event);
- } else if (gestureState.getRunningTask() == null) {
+ if (gestureState.getRunningTask() == null) {
return mResetGestureInputConsumer;
} else if (previousGestureState.isRunningAnimationToLauncher()
|| gestureState.getActivityInterface().isResumed()
@@ -658,25 +653,22 @@
} else if (mDeviceState.isGestureBlockedActivity(gestureState.getRunningTask())) {
return mResetGestureInputConsumer;
} else {
- return createOtherActivityInputConsumer(previousGestureState, gestureState, event);
+ return createOtherActivityInputConsumer(gestureState, event);
}
}
- private InputConsumer createOtherActivityInputConsumer(GestureState previousGestureState,
- GestureState gestureState, MotionEvent event) {
+ private InputConsumer createOtherActivityInputConsumer(GestureState gestureState,
+ MotionEvent event) {
- final boolean shouldDefer;
final BaseSwipeUpHandler.Factory factory;
-
if (!mOverviewComponentObserver.isHomeAndOverviewSame()) {
- shouldDefer = previousGestureState.getFinishingRecentsAnimationTaskId() < 0;
factory = mFallbackSwipeHandlerFactory;
} else {
- shouldDefer = gestureState.getActivityInterface().deferStartingActivity(mDeviceState,
- event);
factory = mLauncherSwipeHandlerFactory;
}
+ final boolean shouldDefer = !mOverviewComponentObserver.isHomeAndOverviewSame()
+ || gestureState.getActivityInterface().deferStartingActivity(mDeviceState, event);
final boolean disableHorizontalSwipe = mDeviceState.isInExclusionRegion(event);
return new OtherActivityInputConsumer(this, mDeviceState, mTaskAnimationManager,
gestureState, shouldDefer, this::onConsumerInactive,
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java
index a95908d..832f0e2 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java
@@ -19,7 +19,6 @@
import static com.android.launcher3.states.RotationHelper.deltaRotation;
import static com.android.launcher3.touch.PagedOrientationHandler.MATRIX_POST_TRANSLATE;
-import static com.android.quickstep.util.RecentsOrientedState.isFixedRotationTransformEnabled;
import static com.android.quickstep.util.RecentsOrientedState.postDisplayRotation;
import static com.android.systemui.shared.system.WindowManagerWrapper.WINDOWING_MODE_FULLSCREEN;
@@ -67,7 +66,7 @@
// Thumbnail view properties
private final Rect mThumbnailPosition = new Rect();
private final ThumbnailData mThumbnailData = new ThumbnailData();
- private final PreviewPositionHelper mPositionHelper;
+ private final PreviewPositionHelper mPositionHelper = new PreviewPositionHelper();
private final Matrix mInversePositionMatrix = new Matrix();
// TaskView properties
@@ -87,7 +86,6 @@
public TaskViewSimulator(Context context, WindowSizeStrategy sizeStrategy) {
mContext = context;
mSizeStrategy = sizeStrategy;
- mPositionHelper = new PreviewPositionHelper(context);
mOrientationState = new RecentsOrientedState(context, sizeStrategy, i -> { });
// We do not need to attach listeners as the simulator is created just for the gesture
@@ -173,12 +171,12 @@
mLayoutValid = true;
getFullScreenScale();
- mThumbnailData.rotation = isFixedRotationTransformEnabled(mContext)
- ? mOrientationState.getDisplayRotation() : mPositionHelper.getCurrentRotation();
+ mThumbnailData.rotation = mOrientationState.getDisplayRotation();
- mPositionHelper.updateThumbnailMatrix(mThumbnailPosition, mThumbnailData,
- mTaskRect.width(), mTaskRect.height(), mDp);
-
+ mPositionHelper.updateThumbnailMatrix(
+ mThumbnailPosition, mThumbnailData,
+ mTaskRect.width(), mTaskRect.height(),
+ mDp, mOrientationState.getLauncherRotation());
mPositionHelper.getMatrix().invert(mInversePositionMatrix);
PagedOrientationHandler poh = mOrientationState.getOrientationHandler();
@@ -188,7 +186,6 @@
mScrollValid = false;
}
-
if (!mScrollValid) {
mScrollValid = true;
int start = mOrientationState.getOrientationHandler()
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java
index 8a6bd84..6d3077e 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java
@@ -371,4 +371,16 @@
protected DepthController getDepthController() {
return mActivity.getDepthController();
}
+
+ @Override
+ public void setModalStateEnabled(boolean isModalState) {
+ super.setModalStateEnabled(isModalState);
+ if (isModalState) {
+ mActivity.getStateManager().goToState(LauncherState.OVERVIEW_MODAL_TASK);
+ } else {
+ if (mActivity.isInState(LauncherState.OVERVIEW_MODAL_TASK)) {
+ mActivity.getStateManager().goToState(LauncherState.OVERVIEW);
+ }
+ }
+ }
}
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 4f6f970..49aca30 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
@@ -977,7 +977,15 @@
}
public int getRunningTaskIndex() {
- TaskView tv = getRunningTaskView();
+ return getTaskIndexForId(mRunningTaskId);
+ }
+
+ /**
+ * Get the index of the task view whose id matches {@param taskId}.
+ * @return -1 if there is no task view for the task id, else the index of the task view.
+ */
+ public int getTaskIndexForId(int taskId) {
+ TaskView tv = getTaskView(taskId);
return tv == null ? -1 : indexOfChild(tv);
}
@@ -2178,6 +2186,12 @@
}
/**
+ * Enables or disables modal state for RecentsView
+ * @param isModalState
+ */
+ public void setModalStateEnabled(boolean isModalState) { }
+
+ /**
* Used to register callbacks for when our empty message state changes.
*
* @see #setOnEmptyMessageUpdatedListener(OnEmptyMessageUpdatedListener)
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
index b837a21..a3e360f 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
@@ -90,7 +90,7 @@
// Contains the portion of the thumbnail that is clipped when fullscreen progress = 0.
private final Rect mPreviewRect = new Rect();
- private final PreviewPositionHelper mPreviewPositionHelper;
+ private final PreviewPositionHelper mPreviewPositionHelper = new PreviewPositionHelper();
// Initialize with dummy value. It is overridden later by TaskView
private TaskView.FullscreenDrawParams mFullscreenParams = TEMP_PARAMS;
@@ -122,7 +122,6 @@
mDimmingPaintAfterClearing.setColor(Color.BLACK);
mActivity = BaseActivity.fromContext(context);
mIsDarkTextTheme = Themes.getAttrBoolean(mActivity, R.attr.isWorkspaceDarkText);
- mPreviewPositionHelper = new PreviewPositionHelper(context);
}
/**
@@ -349,8 +348,11 @@
if (mBitmapShader != null && mThumbnailData != null) {
mPreviewRect.set(0, 0, mThumbnailData.thumbnail.getWidth(),
mThumbnailData.thumbnail.getHeight());
+ int currentRotation = ConfigurationCompat.getWindowConfigurationRotation(
+ mActivity.getResources().getConfiguration());
mPreviewPositionHelper.updateThumbnailMatrix(mPreviewRect, mThumbnailData,
- getMeasuredWidth(), getMeasuredHeight(), mActivity.getDeviceProfile());
+ getMeasuredWidth(), getMeasuredHeight(), mActivity.getDeviceProfile(),
+ currentRotation);
mBitmapShader.setLocalMatrix(mPreviewPositionHelper.mMatrix);
mPaint.setShader(mBitmapShader);
@@ -417,17 +419,6 @@
private float mClipBottom = -1;
private boolean mIsOrientationChanged;
- private final Context mContext;
-
- public PreviewPositionHelper(Context context) {
- mContext = context;
- }
-
- public int getCurrentRotation() {
- return ConfigurationCompat.getWindowConfigurationRotation(
- mContext.getResources().getConfiguration());
- }
-
public Matrix getMatrix() {
return mMatrix;
}
@@ -436,7 +427,7 @@
* Updates the matrix based on the provided parameters
*/
public void updateThumbnailMatrix(Rect thumbnailPosition, ThumbnailData thumbnailData,
- int canvasWidth, int canvasHeight, DeviceProfile dp) {
+ int canvasWidth, int canvasHeight, DeviceProfile dp, int currentRotation) {
boolean isRotated = false;
boolean isOrientationDifferent;
mClipBottom = -1;
@@ -451,7 +442,6 @@
final float thumbnailScale;
int thumbnailRotation = thumbnailData.rotation;
- int currentRotation = getCurrentRotation();
int deltaRotate = getRotationDelta(currentRotation, thumbnailRotation);
Rect deviceInsets = dp.getInsets();
diff --git a/quickstep/robolectric_tests/src/com/android/quickstep/RecentsActivityTest.java b/quickstep/robolectric_tests/src/com/android/quickstep/RecentsActivityTest.java
new file mode 100644
index 0000000..93b64e6
--- /dev/null
+++ b/quickstep/robolectric_tests/src/com/android/quickstep/RecentsActivityTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep;
+
+import static com.android.launcher3.util.LauncherUIHelper.doLayout;
+
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+
+import com.android.quickstep.fallback.FallbackRecentsView;
+import com.android.systemui.shared.recents.model.ThumbnailData;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.Robolectric;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.android.controller.ActivityController;
+import org.robolectric.annotation.LooperMode;
+import org.robolectric.annotation.LooperMode.Mode;
+import org.robolectric.shadows.ShadowLooper;
+import org.robolectric.util.ReflectionHelpers;
+
+
+@RunWith(RobolectricTestRunner.class)
+@LooperMode(Mode.PAUSED)
+public class RecentsActivityTest {
+
+ @Test
+ public void testRecentsActivityCreates() {
+ ActivityController<RecentsActivity> controller =
+ Robolectric.buildActivity(RecentsActivity.class);
+
+ RecentsActivity launcher = controller.setup().get();
+ doLayout(launcher);
+
+ // TODO: Ensure that LauncherAppState is not created
+ }
+
+ @Test
+ public void testRecets_showCurrentTask() {
+ ActivityController<RecentsActivity> controller =
+ Robolectric.buildActivity(RecentsActivity.class);
+
+ RecentsActivity activity = controller.setup().get();
+ doLayout(activity);
+
+ FallbackRecentsView frv = activity.getOverviewPanel();
+ frv.showCurrentTask(22);
+ doLayout(activity);
+
+ ThumbnailData thumbnailData = new ThumbnailData();
+ ReflectionHelpers.setField(thumbnailData, "thumbnail",
+ Bitmap.createBitmap(300, 500, Config.ARGB_8888));
+ frv.switchToScreenshot(thumbnailData, () -> { });
+ ShadowLooper.idleMainLooper();
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java b/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java
index 2cb23f1..fc60434 100644
--- a/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java
+++ b/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java
@@ -26,6 +26,7 @@
import android.content.Context;
import android.os.Build;
import android.os.Handler;
+import android.util.Log;
import androidx.annotation.BinderThread;
import androidx.annotation.UiThread;
@@ -37,6 +38,8 @@
public abstract class LauncherAnimationRunner implements RemoteAnimationRunnerCompat,
WrappedAnimationRunnerImpl {
+ private static final String TAG = "LauncherAnimationRunner";
+
private final Handler mHandler;
private final boolean mStartAtFrontOfQueue;
private AnimationResult mAnimationResult;
@@ -151,7 +154,16 @@
// Because t=0 has the app icon in its original spot, we can skip the
// first frame and have the same movement one frame earlier.
- mAnimator.setCurrentPlayTime(getSingleFrameMs(context));
+ int singleFrameMs = getSingleFrameMs(context);
+ long playTime = singleFrameMs;
+ // b/153821199 Add logs to debug crash but ensure release builds do not crash.
+ if (Utilities.IS_DEBUG_DEVICE) {
+ Log.e(TAG, "Total duration=[" + mAnimator.getTotalDuration()
+ + "], singleFrameMs=[" + singleFrameMs + "], mAnimator=" + mAnimator);
+ } else {
+ playTime = Math.min(singleFrameMs, mAnimator.getTotalDuration());
+ }
+ mAnimator.setCurrentPlayTime(playTime);
}
}
}
diff --git a/quickstep/src/com/android/quickstep/GestureState.java b/quickstep/src/com/android/quickstep/GestureState.java
index 544f420..f06e1a6 100644
--- a/quickstep/src/com/android/quickstep/GestureState.java
+++ b/quickstep/src/com/android/quickstep/GestureState.java
@@ -15,6 +15,7 @@
*/
package com.android.quickstep;
+import static com.android.quickstep.GestureState.GestureEndTarget.NEW_TASK;
import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
import android.app.ActivityManager;
@@ -110,10 +111,6 @@
public static final int STATE_RECENTS_SCROLLING_FINISHED =
getFlagForIndex("STATE_RECENTS_SCROLLING_FINISHED");
- // Called when the new task appeared from quick switching.
- public static final int STATE_TASK_APPEARED_DURING_SWITCH =
- getFlagForIndex("STATE_TASK_APPEARED_DURING_SWITCH");
-
// Needed to interact with the current activity
private final Intent mHomeIntent;
private final Intent mOverviewIntent;
@@ -123,9 +120,7 @@
private ActivityManager.RunningTaskInfo mRunningTask;
private GestureEndTarget mEndTarget;
- private RemoteAnimationTargetCompat mAnimationTarget;
- // TODO: This can be removed once we stop finishing the animation when starting a new task
- private int mFinishingRecentsAnimationTaskId = -1;
+ private RemoteAnimationTargetCompat mLastAppearedTaskTarget;
public GestureState(OverviewComponentObserver componentObserver, int gestureId) {
mHomeIntent = componentObserver.getHomeIntent();
@@ -143,7 +138,7 @@
mGestureId = other.mGestureId;
mRunningTask = other.mRunningTask;
mEndTarget = other.mEndTarget;
- mFinishingRecentsAnimationTaskId = other.mFinishingRecentsAnimationTaskId;
+ mLastAppearedTaskTarget = other.mLastAppearedTaskTarget;
}
public GestureState() {
@@ -226,20 +221,26 @@
}
/**
+ * Updates the last task that appeared during this gesture.
+ */
+ public void updateLastAppearedTaskTarget(RemoteAnimationTargetCompat lastAppearedTaskTarget) {
+ mLastAppearedTaskTarget = lastAppearedTaskTarget;
+ }
+
+ /**
+ * @return The id of the task that appeared during this gesture.
+ */
+ public int getLastAppearedTaskId() {
+ return mLastAppearedTaskTarget != null ? mLastAppearedTaskTarget.taskId : -1;
+ }
+
+ /**
* @return the end target for this gesture (if known).
*/
public GestureEndTarget getEndTarget() {
return mEndTarget;
}
- public void setAnimationTarget(RemoteAnimationTargetCompat target) {
- mAnimationTarget = target;
- }
-
- public RemoteAnimationTargetCompat getAnimationTarget() {
- return mAnimationTarget;
- }
-
/**
* Sets the end target of this gesture and immediately notifies the state changes.
*/
@@ -260,29 +261,8 @@
}
/**
- * @return the id for the task that was about to be launched following the finish of the recents
- * animation. Only defined between when the finish-recents call was made and the launch
- * activity call is made.
- */
- public int getFinishingRecentsAnimationTaskId() {
- return mFinishingRecentsAnimationTaskId;
- }
-
- /**
- * Sets the id for the task will be launched after the recents animation is finished. Once the
- * animation has finished then the id will be reset to -1.
- */
- public void setFinishingRecentsAnimationTaskId(int taskId) {
- mFinishingRecentsAnimationTaskId = taskId;
- mStateCallback.runOnceAtState(STATE_RECENTS_ANIMATION_FINISHED, () -> {
- mFinishingRecentsAnimationTaskId = -1;
- });
- }
-
- /**
* @return whether the current gesture is still running a recents animation to a state in the
* Launcher or Recents activity.
- * Updates the running task for the gesture to be the given {@param runningTask}.
*/
public boolean isRunningAnimationToLauncher() {
return isRecentsAnimationRunning() && mEndTarget != null && mEndTarget.isLauncher;
@@ -314,18 +294,12 @@
mStateCallback.setState(STATE_RECENTS_ANIMATION_ENDED);
}
- @Override
- public void onTaskAppeared(RemoteAnimationTargetCompat app) {
- mAnimationTarget = app;
- mStateCallback.setState(STATE_TASK_APPEARED_DURING_SWITCH);
- }
-
public void dump(PrintWriter pw) {
pw.println("GestureState:");
pw.println(" gestureID=" + mGestureId);
pw.println(" runningTask=" + mRunningTask);
pw.println(" endTarget=" + mEndTarget);
- pw.println(" finishingRecentsAnimationTaskId=" + mFinishingRecentsAnimationTaskId);
+ pw.println(" lastAppearedTaskTarget=" + mLastAppearedTaskTarget);
pw.println(" isRecentsAnimationRunning=" + isRecentsAnimationRunning());
}
}
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java b/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java
index 103ea4e..a21c714 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java
@@ -159,6 +159,6 @@
/**
* Callback made when a task started from the recents is ready for an app transition.
*/
- default void onTaskAppeared(RemoteAnimationTargetCompat app) {}
+ default void onTaskAppeared(RemoteAnimationTargetCompat appearedTaskTarget) {}
}
}
diff --git a/quickstep/src/com/android/quickstep/TaskAnimationManager.java b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
index 21e8c92..cad51f4 100644
--- a/quickstep/src/com/android/quickstep/TaskAnimationManager.java
+++ b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
@@ -18,6 +18,7 @@
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.quickstep.GestureState.STATE_RECENTS_ANIMATION_INITIALIZED;
+import static com.android.quickstep.GestureState.STATE_RECENTS_ANIMATION_STARTED;
import android.content.Intent;
import android.util.Log;
@@ -28,6 +29,7 @@
import com.android.launcher3.config.FeatureFlags;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAnimationListener {
@@ -36,6 +38,7 @@
private RecentsAnimationTargets mTargets;
// Temporary until we can hook into gesture state events
private GestureState mLastGestureState;
+ private RemoteAnimationTargetCompat mLastAppearedTaskTarget;
/**
* Preloads the recents animation.
@@ -79,6 +82,8 @@
}
mController = controller;
mTargets = targets;
+ mLastAppearedTaskTarget = mTargets.findTask(mLastGestureState.getRunningTaskId());
+ mLastGestureState.updateLastAppearedTaskTarget(mLastAppearedTaskTarget);
}
@Override
@@ -96,6 +101,20 @@
public void onRecentsAnimationFinished(RecentsAnimationController controller) {
cleanUpRecentsAnimation(null /* canceledThumbnail */);
}
+
+ @Override
+ public void onTaskAppeared(RemoteAnimationTargetCompat appearedTaskTarget) {
+ if (mController != null) {
+ if (mLastAppearedTaskTarget == null
+ || appearedTaskTarget.taskId != mLastAppearedTaskTarget.taskId) {
+ if (mLastAppearedTaskTarget != null) {
+ mController.removeTaskTarget(mLastAppearedTaskTarget);
+ }
+ mLastAppearedTaskTarget = appearedTaskTarget;
+ mLastGestureState.updateLastAppearedTaskTarget(mLastAppearedTaskTarget);
+ }
+ }
+ }
});
mCallbacks.addListener(gestureState);
mCallbacks.addListener(listener);
@@ -112,6 +131,9 @@
mCallbacks.removeListener(mLastGestureState);
mLastGestureState = gestureState;
mCallbacks.addListener(gestureState);
+ gestureState.setState(STATE_RECENTS_ANIMATION_INITIALIZED
+ | STATE_RECENTS_ANIMATION_STARTED);
+ gestureState.updateLastAppearedTaskTarget(mLastAppearedTaskTarget);
return mCallbacks;
}
@@ -171,6 +193,7 @@
mCallbacks = null;
mTargets = null;
mLastGestureState = null;
+ mLastAppearedTaskTarget = null;
}
public void dump() {
diff --git a/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java b/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
index 7d52571..a5d4568 100644
--- a/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
+++ b/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
@@ -19,11 +19,13 @@
import android.content.Context;
import android.content.res.Resources;
+import android.util.Log;
import android.view.MotionEvent;
import com.android.launcher3.Alarm;
import com.android.launcher3.R;
import com.android.launcher3.compat.AccessibilityManagerCompat;
+import com.android.launcher3.testing.TestProtocol;
/**
* Given positions along x- or y-axis, tracks velocity and acceleration and determines when there is
@@ -84,6 +86,9 @@
mSpeedSlow = res.getDimension(R.dimen.motion_pause_detector_speed_slow);
mSpeedSomewhatFast = res.getDimension(R.dimen.motion_pause_detector_speed_somewhat_fast);
mSpeedFast = res.getDimension(R.dimen.motion_pause_detector_speed_fast);
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.PAUSE_NOT_DETECTED, "creating alarm");
+ }
mForcePauseTimeout = new Alarm();
mForcePauseTimeout.setOnAlarmListener(alarm -> updatePaused(true /* isPaused */));
mMakePauseHarderToTrigger = makePauseHarderToTrigger;
@@ -120,6 +125,9 @@
* @param pointerIndex Index for the pointer being tracked in the motion event
*/
public void addPosition(MotionEvent ev, int pointerIndex) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.PAUSE_NOT_DETECTED, "setting alarm");
+ }
mForcePauseTimeout.setAlarm(mMakePauseHarderToTrigger
? HARDER_TRIGGER_TIMEOUT
: FORCE_PAUSE_TIMEOUT);
@@ -167,6 +175,9 @@
}
private void updatePaused(boolean isPaused) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.PAUSE_NOT_DETECTED, "updatePaused: " + isPaused);
+ }
if (mDisallowPause) {
isPaused = false;
}
@@ -188,6 +199,9 @@
setOnMotionPauseListener(null);
mIsPaused = mHasEverBeenPaused = false;
mSlowStartTime = 0;
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.PAUSE_NOT_DETECTED, "canceling alarm");
+ }
mForcePauseTimeout.cancelAlarm();
}
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index 21cd04e..48b97fa 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -20,7 +20,6 @@
import static com.android.launcher3.provider.LauncherDbUtils.copyTable;
import static com.android.launcher3.provider.LauncherDbUtils.dropTable;
import static com.android.launcher3.provider.LauncherDbUtils.tableExists;
-import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import android.annotation.TargetApi;
import android.app.backup.BackupManager;
@@ -48,7 +47,6 @@
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
-import android.os.Handler;
import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
@@ -85,6 +83,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Locale;
+import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
public class LauncherProvider extends ContentProvider {
@@ -92,8 +91,7 @@
private static final boolean LOGD = false;
private static final String DOWNGRADE_SCHEMA_FILE = "downgrade_schema.json";
- private static final String TOKEN_RESTORE_BACKUP_TABLE = "restore_backup_table";
- private static final long RESTORE_BACKUP_TABLE_DELAY = 60000;
+ private static final long RESTORE_BACKUP_TABLE_DELAY = TimeUnit.SECONDS.toMillis(30);
/**
* Represents the schema of the database. Changes in scheme need not be backwards compatible.
@@ -107,6 +105,8 @@
protected DatabaseHelper mOpenHelper;
+ private long mLastRestoreTimestamp = 0L;
+
/**
* $ adb shell dumpsys activity provider com.android.launcher3
*/
@@ -412,11 +412,12 @@
return null;
}
case LauncherSettings.Settings.METHOD_RESTORE_BACKUP_TABLE: {
- final Handler handler = MODEL_EXECUTOR.getHandler();
- handler.removeCallbacksAndMessages(TOKEN_RESTORE_BACKUP_TABLE);
- handler.postDelayed(() -> RestoreDbTask.restoreIfPossible(
- getContext(), mOpenHelper, new BackupManager(getContext())),
- TOKEN_RESTORE_BACKUP_TABLE, RESTORE_BACKUP_TABLE_DELAY);
+ final long ts = System.currentTimeMillis();
+ if (ts - mLastRestoreTimestamp > RESTORE_BACKUP_TABLE_DELAY) {
+ mLastRestoreTimestamp = ts;
+ RestoreDbTask.restoreIfPossible(
+ getContext(), mOpenHelper, new BackupManager(getContext()));
+ }
return null;
}
case LauncherSettings.Settings.METHOD_UPDATE_CURRENT_OPEN_HELPER: {
diff --git a/src/com/android/launcher3/LauncherStateManager.java b/src/com/android/launcher3/LauncherStateManager.java
index 1aae201..f6de48e 100644
--- a/src/com/android/launcher3/LauncherStateManager.java
+++ b/src/com/android/launcher3/LauncherStateManager.java
@@ -25,12 +25,14 @@
import android.animation.AnimatorSet;
import android.os.Handler;
import android.os.Looper;
+import android.util.Log;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.states.StateAnimationConfig;
import com.android.launcher3.states.StateAnimationConfig.AnimationFlags;
+import com.android.launcher3.testing.TestProtocol;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -334,6 +336,10 @@
}
private PendingAnimation createAnimationToNewWorkspaceInternal(final LauncherState state) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.OVERIEW_NOT_ALLAPPS, "createAnimationToNewWorkspaceInternal: "
+ + state.ordinal);
+ }
PendingAnimation builder = new PendingAnimation(mConfig.duration);
for (StateHandler handler : getStateHandlers()) {
handler.setStateWithAnimation(state, mConfig, builder);
@@ -348,6 +354,9 @@
@Override
public void onAnimationSuccess(Animator animator) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.OVERIEW_NOT_ALLAPPS, "onAnimationSuccess: " + state.ordinal);
+ }
onStateTransitionEnd(state);
}
});
diff --git a/src/com/android/launcher3/pm/InstallSessionHelper.java b/src/com/android/launcher3/pm/InstallSessionHelper.java
index 976d7ba..901d27f 100644
--- a/src/com/android/launcher3/pm/InstallSessionHelper.java
+++ b/src/com/android/launcher3/pm/InstallSessionHelper.java
@@ -56,8 +56,6 @@
// Set<String> of session ids of promise icons that have been added to the home screen
// as FLAG_PROMISE_NEW_INSTALLS.
protected static final String PROMISE_ICON_IDS = "promise_icon_ids";
- public static final String KEY_INSTALL_SESSION_CREATED_TIMESTAMP =
- "key_install_session_created_timestamp";
private static final boolean DEBUG = false;
@@ -166,14 +164,13 @@
}
/**
- * Attempt to restore workspace layout if the session is triggered due to device restore and it
- * has a newer timestamp.
+ * Attempt to restore workspace layout if the session is triggered due to device restore.
*/
public boolean restoreDbIfApplicable(@NonNull final SessionInfo info) {
if (!Utilities.ATLEAST_OREO || !FeatureFlags.ENABLE_DATABASE_RESTORE.get()) {
return false;
}
- if (isRestore(info) && hasNewerTimestamp(mAppContext, info)) {
+ if (isRestore(info)) {
LauncherSettings.Settings.call(mAppContext.getContentResolver(),
LauncherSettings.Settings.METHOD_RESTORE_BACKUP_TABLE);
return true;
@@ -186,13 +183,6 @@
return info.getInstallReason() == PackageManager.INSTALL_REASON_DEVICE_RESTORE;
}
- private static boolean hasNewerTimestamp(
- @NonNull final Context context, @NonNull final SessionInfo info) {
- return PackageManagerHelper.getSessionCreatedTimeInMillis(info)
- > Utilities.getDevicePrefs(context).getLong(
- KEY_INSTALL_SESSION_CREATED_TIMESTAMP, 0);
- }
-
public boolean promiseIconAddedForId(int sessionId) {
return mPromiseIconIds.contains(sessionId);
}
diff --git a/src/com/android/launcher3/provider/RestoreDbTask.java b/src/com/android/launcher3/provider/RestoreDbTask.java
index 33eff57..53183bf 100644
--- a/src/com/android/launcher3/provider/RestoreDbTask.java
+++ b/src/com/android/launcher3/provider/RestoreDbTask.java
@@ -16,7 +16,6 @@
package com.android.launcher3.provider;
-import static com.android.launcher3.pm.InstallSessionHelper.KEY_INSTALL_SESSION_CREATED_TIMESTAMP;
import static com.android.launcher3.provider.LauncherDbUtils.dropTable;
import android.app.backup.BackupManager;
@@ -87,13 +86,10 @@
*/
public static boolean restoreIfPossible(@NonNull Context context,
@NonNull DatabaseHelper helper, @NonNull BackupManager backupManager) {
- Utilities.getDevicePrefs(context).edit().putLong(
- KEY_INSTALL_SESSION_CREATED_TIMESTAMP, System.currentTimeMillis()).apply();
final SQLiteDatabase db = helper.getWritableDatabase();
try (SQLiteTransaction t = new SQLiteTransaction(db)) {
RestoreDbTask task = new RestoreDbTask();
task.restoreWorkspace(context, db, helper, backupManager);
- task.restoreAppWidgetIdsIfExists(context);
t.commit();
return true;
} catch (Exception e) {
@@ -107,7 +103,6 @@
*/
private void backupWorkspace(Context context, SQLiteDatabase db) throws Exception {
InvariantDeviceProfile idp = LauncherAppState.getIDP(context);
- // TODO(pinyaoting): Support backing up workspace with multiple grid options.
new GridBackupTable(context, db, idp.numHotseatIcons, idp.numColumns, idp.numRows)
.doBackup(getDefaultProfileId(db), GridBackupTable.OPTION_REQUIRES_SANITIZATION);
}
@@ -115,13 +110,17 @@
private void restoreWorkspace(@NonNull Context context, @NonNull SQLiteDatabase db,
@NonNull DatabaseHelper helper, @NonNull BackupManager backupManager)
throws Exception {
- // TODO(pinyaoting): Support restoring workspace with multiple grid options.
final InvariantDeviceProfile idp = LauncherAppState.getIDP(context);
GridBackupTable backupTable = new GridBackupTable(context, db, idp.numHotseatIcons,
idp.numColumns, idp.numRows);
if (backupTable.restoreFromRawBackupIfAvailable(getDefaultProfileId(db))) {
- sanitizeDB(helper, db, backupManager);
+ int itemsDeleted = sanitizeDB(helper, db, backupManager);
LauncherAppState.getInstance(context).getModel().forceReload();
+ restoreAppWidgetIdsIfExists(context);
+ if (itemsDeleted == 0) {
+ // all the items are restored, we no longer need the backup table
+ dropTable(db, Favorites.BACKUP_TABLE_NAME);
+ }
}
}
@@ -132,8 +131,10 @@
* the restored apps get installed.
* 3. If the user serial for any restored profile is different than that of the previous
* device, update the entries to the new profile id.
+ *
+ * @return number of items deleted.
*/
- private void sanitizeDB(DatabaseHelper helper, SQLiteDatabase db, BackupManager backupManager)
+ private int sanitizeDB(DatabaseHelper helper, SQLiteDatabase db, BackupManager backupManager)
throws Exception {
// Primary user ids
long myProfileId = helper.getDefaultUserSerial();
@@ -210,6 +211,7 @@
if (myProfileId != oldProfileId) {
changeDefaultColumn(db, myProfileId);
}
+ return itemsDeleted;
}
/**
diff --git a/src/com/android/launcher3/testing/TestProtocol.java b/src/com/android/launcher3/testing/TestProtocol.java
index fba6269..0aab495 100644
--- a/src/com/android/launcher3/testing/TestProtocol.java
+++ b/src/com/android/launcher3/testing/TestProtocol.java
@@ -99,4 +99,6 @@
public static final String REQUEST_MOCK_SENSOR_ROTATION = "mock-sensor-rotation";
public static final String PERMANENT_DIAG_TAG = "TaplTarget";
+ public static final String PAUSE_NOT_DETECTED = "b/139891609";
+ public static final String OVERIEW_NOT_ALLAPPS = "b/156095088";
}
diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
index cbc5257..dd9c3fa 100644
--- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
+++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
@@ -31,6 +31,7 @@
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.os.SystemClock;
+import android.util.Log;
import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
@@ -43,6 +44,7 @@
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.states.StateAnimationConfig;
import com.android.launcher3.states.StateAnimationConfig.AnimationFlags;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
@@ -194,6 +196,10 @@
mFromState = newFromState;
mToState = newToState;
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.OVERIEW_NOT_ALLAPPS, "reinitCurrentAnimation: "
+ + newToState.ordinal);
+ }
mStartProgress = 0;
mPassedOverviewAtomicThreshold = false;
diff --git a/src/com/android/launcher3/views/Snackbar.java b/src/com/android/launcher3/views/Snackbar.java
index dc0e2e0..513ce59 100644
--- a/src/com/android/launcher3/views/Snackbar.java
+++ b/src/com/android/launcher3/views/Snackbar.java
@@ -29,7 +29,7 @@
import android.widget.TextView;
import com.android.launcher3.AbstractFloatingView;
-import com.android.launcher3.Launcher;
+import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.R;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.compat.AccessibilityManagerCompat;
@@ -44,7 +44,7 @@
private static final long HIDE_DURATION_MS = 180;
private static final int TIMEOUT_DURATION_MS = 4000;
- private final Launcher mLauncher;
+ private final BaseDraggingActivity mActivity;
private Runnable mOnDismissed;
public Snackbar(Context context, AttributeSet attrs) {
@@ -53,25 +53,25 @@
public Snackbar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
- mLauncher = Launcher.getLauncher(context);
+ mActivity = BaseDraggingActivity.fromContext(context);
inflate(context, R.layout.snackbar, this);
}
- public static void show(Launcher launcher, int labelStringResId, int actionStringResId,
- Runnable onDismissed, Runnable onActionClicked) {
- closeOpenViews(launcher, true, TYPE_SNACKBAR);
- Snackbar snackbar = new Snackbar(launcher, null);
+ public static void show(BaseDraggingActivity activity, int labelStringResId,
+ int actionStringResId, Runnable onDismissed, Runnable onActionClicked) {
+ closeOpenViews(activity, true, TYPE_SNACKBAR);
+ Snackbar snackbar = new Snackbar(activity, null);
// Set some properties here since inflated xml only contains the children.
snackbar.setOrientation(HORIZONTAL);
snackbar.setGravity(Gravity.CENTER_VERTICAL);
- Resources res = launcher.getResources();
+ Resources res = activity.getResources();
snackbar.setElevation(res.getDimension(R.dimen.snackbar_elevation));
int padding = res.getDimensionPixelSize(R.dimen.snackbar_padding);
snackbar.setPadding(padding, padding, padding, padding);
snackbar.setBackgroundResource(R.drawable.round_rect_primary);
snackbar.mIsOpen = true;
- DragLayer dragLayer = launcher.getDragLayer();
+ BaseDragLayer dragLayer = activity.getDragLayer();
dragLayer.addView(snackbar);
DragLayer.LayoutParams params = (DragLayer.LayoutParams) snackbar.getLayoutParams();
@@ -80,7 +80,7 @@
int maxMarginLeftRight = res.getDimensionPixelSize(R.dimen.snackbar_max_margin_left_right);
int minMarginLeftRight = res.getDimensionPixelSize(R.dimen.snackbar_min_margin_left_right);
int marginBottom = res.getDimensionPixelSize(R.dimen.snackbar_margin_bottom);
- Rect insets = launcher.getDeviceProfile().getInsets();
+ Rect insets = activity.getDeviceProfile().getInsets();
int maxWidth = dragLayer.getWidth() - minMarginLeftRight * 2 - insets.left - insets.right;
int minWidth = dragLayer.getWidth() - maxMarginLeftRight * 2 - insets.left - insets.right;
params.width = minWidth;
@@ -135,7 +135,7 @@
.setDuration(SHOW_DURATION_MS)
.setInterpolator(Interpolators.ACCEL_DEACCEL)
.start();
- int timeout = AccessibilityManagerCompat.getRecommendedTimeoutMillis(launcher,
+ int timeout = AccessibilityManagerCompat.getRecommendedTimeoutMillis(activity,
TIMEOUT_DURATION_MS, FLAG_CONTENT_TEXT | FLAG_CONTENT_CONTROLS);
snackbar.postDelayed(() -> snackbar.close(true), timeout);
}
@@ -160,7 +160,7 @@
}
private void onClosed() {
- mLauncher.getDragLayer().removeView(this);
+ mActivity.getDragLayer().removeView(this);
if (mOnDismissed != null) {
mOnDismissed.run();
}
@@ -179,7 +179,7 @@
@Override
public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
- DragLayer dl = mLauncher.getDragLayer();
+ BaseDragLayer dl = mActivity.getDragLayer();
if (!dl.isEventOverView(this, ev)) {
close(true);
}
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 667e2d4..a57e9d9 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -938,9 +938,9 @@
executeAndWaitForEvent(
command,
event -> isSwitchToStateEvent(event, expectedState, actualEvents),
- () -> "Failed to receive an event for the state change: expected "
+ () -> "Failed to receive an event for the state change: expected ["
+ TestProtocol.stateOrdinalToString(expectedState)
- + ", actual: " + eventListToString(actualEvents));
+ + "], actual: " + eventListToString(actualEvents));
}
private boolean isSwitchToStateEvent(