Merge "Add FeatureFlag for ENABLE_FOUR_COLUMNS."
diff --git a/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java
index 3e9f82b..cc3b7b6 100644
--- a/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java
+++ b/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java
@@ -57,7 +57,6 @@
import android.os.CancellationSignal;
import android.os.Handler;
import android.os.Looper;
-import android.os.Trace;
import android.util.Pair;
import android.view.View;
@@ -140,7 +139,6 @@
// Progress = 0: All apps is fully pulled up, Progress = 1: All apps is fully pulled down.
public static final float ALL_APPS_PROGRESS_OFF_SCREEN = 1.3059858f;
- public static final String TRANSITION_OPEN_LAUNCHER = "transition:OpenLauncher";
protected final BaseQuickstepLauncher mLauncher;
@@ -805,11 +803,10 @@
== PackageManager.PERMISSION_GRANTED;
}
- private void addCujInstrumentation(Animator anim, int cuj, String transition) {
+ private void addCujInstrumentation(Animator anim, int cuj) {
anim.addListener(new AnimationSuccessListener() {
@Override
public void onAnimationStart(Animator animation) {
- Trace.beginAsyncSection(transition, 0);
InteractionJankMonitorWrapper.begin(cuj);
super.onAnimationStart(animation);
}
@@ -824,12 +821,6 @@
public void onAnimationSuccess(Animator animator) {
InteractionJankMonitorWrapper.end(cuj);
}
-
- @Override
- public void onAnimationEnd(Animator animation) {
- super.onAnimationEnd(animation);
- Trace.endAsyncSection(TRANSITION_OPEN_LAUNCHER, 0);
- }
});
}
@@ -898,8 +889,7 @@
if (launcherIsATargetWithMode(appTargets, MODE_OPENING)
|| mLauncher.isForceInvisible()) {
addCujInstrumentation(
- anim, InteractionJankMonitorWrapper.CUJ_APP_CLOSE_TO_HOME,
- TRANSITION_OPEN_LAUNCHER);
+ anim, InteractionJankMonitorWrapper.CUJ_APP_CLOSE_TO_HOME);
// Only register the content animation for cancellation when state changes
mLauncher.getStateManager().setCurrentAnimation(anim);
@@ -971,9 +961,7 @@
addCujInstrumentation(anim,
launchingFromRecents
? InteractionJankMonitorWrapper.CUJ_APP_LAUNCH_FROM_RECENTS
- : InteractionJankMonitorWrapper.CUJ_APP_LAUNCH_FROM_ICON,
- launchingFromRecents
- ? TRANSITION_LAUNCH_FROM_RECENTS : TRANSITION_LAUNCH_FROM_ICON);
+ : InteractionJankMonitorWrapper.CUJ_APP_LAUNCH_FROM_ICON);
if (launcherClosing) {
anim.addListener(mForceInvisibleListener);
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 4dbc0f3..4ed2425 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -20,7 +20,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.QuickstepAppTransitionManagerImpl.RECENTS_LAUNCH_DURATION;
-import static com.android.launcher3.QuickstepAppTransitionManagerImpl.TRANSITION_OPEN_LAUNCHER;
import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
@@ -33,6 +32,7 @@
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_QUICKSWITCH_RIGHT;
import static com.android.launcher3.util.DisplayController.getSingleFrameMs;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.launcher3.util.SystemUiController.UI_STATE_OVERVIEW;
import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
import static com.android.quickstep.GestureState.GestureEndTarget.HOME;
@@ -59,7 +59,6 @@
import android.graphics.Rect;
import android.os.Build;
import android.os.SystemClock;
-import android.os.Trace;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
@@ -1217,7 +1216,6 @@
anim.addAnimatorListener(new AnimationSuccessListener() {
@Override
public void onAnimationStart(Animator animation) {
- Trace.beginAsyncSection(TRANSITION_OPEN_LAUNCHER, 0);
InteractionJankMonitorWrapper.begin(cuj);
if (mActivity != null) {
removeLiveTileOverlay();
@@ -1240,12 +1238,6 @@
super.onAnimationCancel(animation);
InteractionJankMonitorWrapper.cancel(cuj);
}
-
- @Override
- public void onAnimationEnd(Animator animation) {
- super.onAnimationEnd(animation);
- Trace.endAsyncSection(TRANSITION_OPEN_LAUNCHER, 0);
- }
});
if (mRecentsAnimationTargets != null) {
mRecentsAnimationTargets.addReleaseCheck(anim);
@@ -1395,34 +1387,55 @@
if (mRecentsAnimationController != null) {
// Update the screenshot of the task
if (mTaskSnapshot == null) {
- mTaskSnapshot = mRecentsAnimationController.screenshotTask(runningTaskId);
+ UI_HELPER_EXECUTOR.execute(() -> {
+ final ThumbnailData taskSnapshot =
+ mRecentsAnimationController.screenshotTask(runningTaskId);
+ MAIN_EXECUTOR.execute(() -> {
+ mTaskSnapshot = taskSnapshot;
+ if (!updateThumbnail(runningTaskId)) {
+ setScreenshotCapturedState();
+ }
+ });
+ });
+ return;
}
- final TaskView taskView;
- if (mGestureState.getEndTarget() == HOME) {
- // Capture the screenshot before finishing the transition to home to ensure it's
- // taken in the correct orientation, but no need to update the thumbnail.
- taskView = null;
- } else {
- taskView = mRecentsView.updateThumbnail(runningTaskId, mTaskSnapshot);
- }
- if (taskView != null && !mCanceled) {
- // Defer finishing the animation until the next launcher frame with the
- // new thumbnail
- finishTransitionPosted = ViewUtils.postFrameDrawn(taskView,
- () -> mStateCallback.setStateOnUiThread(STATE_SCREENSHOT_CAPTURED),
- this::isCanceled);
- }
+ finishTransitionPosted = updateThumbnail(runningTaskId);
}
if (!finishTransitionPosted) {
- // If we haven't posted a draw callback, set the state immediately.
- Object traceToken = TraceHelper.INSTANCE.beginSection(SCREENSHOT_CAPTURED_EVT,
- TraceHelper.FLAG_CHECK_FOR_RACE_CONDITIONS);
- mStateCallback.setStateOnUiThread(STATE_SCREENSHOT_CAPTURED);
- TraceHelper.INSTANCE.endSection(traceToken);
+ setScreenshotCapturedState();
}
}
}
+ // Returns whether finish transition was posted.
+ private boolean updateThumbnail(int runningTaskId) {
+ boolean finishTransitionPosted = false;
+ final TaskView taskView;
+ if (mGestureState.getEndTarget() == HOME) {
+ // Capture the screenshot before finishing the transition to home to ensure it's
+ // taken in the correct orientation, but no need to update the thumbnail.
+ taskView = null;
+ } else {
+ taskView = mRecentsView.updateThumbnail(runningTaskId, mTaskSnapshot);
+ }
+ if (taskView != null && !mCanceled) {
+ // Defer finishing the animation until the next launcher frame with the
+ // new thumbnail
+ finishTransitionPosted = ViewUtils.postFrameDrawn(taskView,
+ () -> mStateCallback.setStateOnUiThread(STATE_SCREENSHOT_CAPTURED),
+ this::isCanceled);
+ }
+ return finishTransitionPosted;
+ }
+
+ private void setScreenshotCapturedState() {
+ // If we haven't posted a draw callback, set the state immediately.
+ Object traceToken = TraceHelper.INSTANCE.beginSection(SCREENSHOT_CAPTURED_EVT,
+ TraceHelper.FLAG_CHECK_FOR_RACE_CONDITIONS);
+ mStateCallback.setStateOnUiThread(STATE_SCREENSHOT_CAPTURED);
+ TraceHelper.INSTANCE.endSection(traceToken);
+ }
+
private void finishCurrentTransitionToRecents() {
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
mStateCallback.setStateOnUiThread(STATE_CURRENT_TASK_FINISHED);
diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
index 43581ca..2559a6f 100644
--- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
+++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
@@ -25,6 +25,7 @@
import android.content.Context;
import android.os.Build;
import android.os.SystemClock;
+import android.os.Trace;
import android.view.ViewConfiguration;
import androidx.annotation.BinderThread;
@@ -141,6 +142,7 @@
private class RecentsActivityCommand<T extends StatefulActivity<?>> implements Runnable {
+ private static final String TRANSITION_NAME = "Transition:toOverview";
protected final BaseActivityInterface<?, T> mActivityInterface;
private final long mCreateTime;
private final AppToOverviewAnimationProvider<T> mAnimationProvider;
@@ -224,8 +226,15 @@
wallpaperTargets);
animatorSet.addListener(new AnimatorListenerAdapter() {
@Override
+ public void onAnimationStart(Animator animation) {
+ Trace.beginAsyncSection(TRANSITION_NAME, 0);
+ super.onAnimationStart(animation);
+ }
+
+ @Override
public void onAnimationEnd(Animator animation) {
onTransitionComplete();
+ Trace.endAsyncSection(TRANSITION_NAME, 0);
}
});
return animatorSet;
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 1b55496..d94e623 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -251,13 +251,14 @@
* Builds proto for logging
*/
public WorkspaceItemInfo getItemInfo() {
- ComponentKey componentKey = TaskUtils.getLaunchComponentKeyForTask(getTask().key);
+ final Task task = getTask();
+ ComponentKey componentKey = TaskUtils.getLaunchComponentKeyForTask(task.key);
WorkspaceItemInfo stubInfo = new WorkspaceItemInfo();
stubInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_TASK;
stubInfo.container = LauncherSettings.Favorites.CONTAINER_TASKSWITCHER;
stubInfo.user = componentKey.user;
stubInfo.intent = new Intent().setComponent(componentKey.componentName);
- stubInfo.title = TaskUtils.getTitle(getContext(), getTask());
+ stubInfo.title = task.title;
stubInfo.screenId = getRecentsView().indexOfChild(this);
return stubInfo;
}
diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
index a9d0e61..7c02f3d 100644
--- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
+++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
@@ -396,6 +396,12 @@
@Override
public void onDragEnd(float velocity) {
+ if (mCurrentAnimation == null) {
+ // Unlikely, but we may have been canceled just before onDragEnd(). We assume whoever
+ // canceled us will handle a new state transition to clean up.
+ return;
+ }
+
boolean fling = mDetector.isFling(velocity);
boolean blockedFling = fling && mFlingBlockCheck.isBlocked();
diff --git a/src/com/android/launcher3/views/WorkEduView.java b/src/com/android/launcher3/views/WorkEduView.java
index d6737db..03d3026 100644
--- a/src/com/android/launcher3/views/WorkEduView.java
+++ b/src/com/android/launcher3/views/WorkEduView.java
@@ -60,7 +60,6 @@
private View mViewWrapper;
private Button mProceedButton;
private TextView mContentText;
- private AllAppsPagedView mAllAppsPagedView;
private int mNextWorkEduStep = WORK_EDU_PERSONAL_APPS;
@@ -101,13 +100,10 @@
// make sure layout does not shrink when we change the text
mContentText.post(() -> mContentText.setMinLines(mContentText.getLineCount()));
- if (mLauncher.getAppsView().getContentView() instanceof AllAppsPagedView) {
- mAllAppsPagedView = (AllAppsPagedView) mLauncher.getAppsView().getContentView();
- }
mProceedButton.setOnClickListener(view -> {
- if (mAllAppsPagedView != null) {
- mAllAppsPagedView.snapToPage(AllAppsContainerView.AdapterHolder.WORK);
+ if (getAllAppsPagedView() != null) {
+ getAllAppsPagedView().snapToPage(AllAppsContainerView.AdapterHolder.WORK);
}
goToWorkTab(true);
});
@@ -155,8 +151,8 @@
}
private void goToFirstPage() {
- if (mAllAppsPagedView != null) {
- mAllAppsPagedView.snapToPageImmediately(AllAppsContainerView.AdapterHolder.MAIN);
+ if (getAllAppsPagedView() != null) {
+ getAllAppsPagedView().snapToPageImmediately(AllAppsContainerView.AdapterHolder.MAIN);
}
}
@@ -171,6 +167,11 @@
mOpenCloseAnimator.start();
}
+ private AllAppsPagedView getAllAppsPagedView() {
+ View v = mLauncher.getAppsView().getContentView();
+ return (v instanceof AllAppsPagedView) ? (AllAppsPagedView) v : null;
+ }
+
/**
* Checks if user has not seen onboarding UI yet and shows it when user navigates to all apps
*/
diff --git a/tests/src/com/android/launcher3/ui/WorkTabTest.java b/tests/src/com/android/launcher3/ui/WorkTabTest.java
index 1e1cf04..ac0d355 100644
--- a/tests/src/com/android/launcher3/ui/WorkTabTest.java
+++ b/tests/src/com/android/launcher3/ui/WorkTabTest.java
@@ -82,6 +82,7 @@
mDevice.pressHome();
waitForLauncherCondition("Launcher didn't start", Objects::nonNull);
executeOnLauncher(launcher -> launcher.getStateManager().goToState(ALL_APPS));
+ waitForState("Launcher internal state didn't switch to All Apps", () -> ALL_APPS);
waitForLauncherCondition("Personal tab is missing",
launcher -> launcher.getAppsView().isPersonalTabVisible(), 60000);
waitForLauncherCondition("Work tab is missing",
@@ -180,6 +181,10 @@
// open work tab
executeOnLauncher(launcher -> launcher.getStateManager().goToState(ALL_APPS));
waitForState("Launcher did not switch to all apps", () -> ALL_APPS);
+ waitForLauncherCondition("Work tab not setup",
+ launcher -> launcher.getAppsView().getContentView() instanceof AllAppsPagedView,
+ 60000);
+
executeOnLauncher(launcher -> {
AllAppsPagedView pagedView = (AllAppsPagedView) launcher.getAppsView().getContentView();
pagedView.setCurrentPage(WORK_PAGE);
@@ -199,7 +204,7 @@
DragLayer dragLayer = l.getDragLayer();
return dragLayer.getChildCount() > 0 && dragLayer.getChildAt(
dragLayer.getChildCount() - 1) instanceof WorkEduView;
- });
+ }, 6000);
return getFromLauncher(launcher -> (WorkEduView) launcher.getDragLayer().getChildAt(
launcher.getDragLayer().getChildCount() - 1));
}