Merge "Revert "launcher: use a different task menu for foldables"" into sc-v2-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index c72f62d..b838a51 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -50,7 +50,7 @@
android:stateNotNeeded="true"
android:windowSoftInputMode="adjustPan"
android:screenOrientation="unspecified"
- android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize|density"
+ android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize"
android:resizeableActivity="true"
android:resumeWhilePausing="true"
android:taskAffinity=""
diff --git a/go/AndroidManifest-launcher.xml b/go/AndroidManifest-launcher.xml
index 6a8f715..2223036 100644
--- a/go/AndroidManifest-launcher.xml
+++ b/go/AndroidManifest-launcher.xml
@@ -49,7 +49,7 @@
android:stateNotNeeded="true"
android:windowSoftInputMode="adjustPan"
android:screenOrientation="unspecified"
- android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize|density|uiMode"
+ android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize|uiMode"
android:resizeableActivity="true"
android:resumeWhilePausing="true"
android:taskAffinity=""
diff --git a/quickstep/AndroidManifest-launcher.xml b/quickstep/AndroidManifest-launcher.xml
index 6808222..53910e3 100644
--- a/quickstep/AndroidManifest-launcher.xml
+++ b/quickstep/AndroidManifest-launcher.xml
@@ -49,7 +49,7 @@
android:stateNotNeeded="true"
android:windowSoftInputMode="adjustPan"
android:screenOrientation="unspecified"
- android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize|density"
+ android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize"
android:resizeableActivity="true"
android:resumeWhilePausing="true"
android:taskAffinity=""
diff --git a/quickstep/AndroidManifest.xml b/quickstep/AndroidManifest.xml
index 124cd57..0f92274 100644
--- a/quickstep/AndroidManifest.xml
+++ b/quickstep/AndroidManifest.xml
@@ -65,7 +65,7 @@
android:stateNotNeeded="true"
android:theme="@style/LauncherTheme"
android:screenOrientation="unspecified"
- android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize|density"
+ android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize"
android:resizeableActivity="true"
android:resumeWhilePausing="true"
android:taskAffinity=""/>
diff --git a/quickstep/res/drawable/bg_overview_clear_all_button.xml b/quickstep/res/drawable/bg_overview_clear_all_button.xml
index 47cbd9f..fb014f7 100644
--- a/quickstep/res/drawable/bg_overview_clear_all_button.xml
+++ b/quickstep/res/drawable/bg_overview_clear_all_button.xml
@@ -20,7 +20,7 @@
<item>
<shape android:shape="rectangle"
android:tint="?colorButtonNormal">
- <corners android:radius="18dp" />
+ <corners android:radius="24dp" />
<solid android:color="?androidprv:attr/colorSurface"/>
</shape>
</item>
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 98d43f1..0b534e3 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -46,7 +46,8 @@
<dimen name="overview_actions_margin_three_button">8dp</dimen>
<dimen name="overview_actions_horizontal_margin">16dp</dimen>
- <dimen name="overview_grid_side_margin">50dp</dimen>
+ <dimen name="overview_grid_side_margin_portrait">60dp</dimen>
+ <dimen name="overview_grid_side_margin_landscape">52dp</dimen>
<dimen name="overview_grid_row_spacing_portrait">17.13dp</dimen>
<dimen name="overview_grid_row_spacing_landscape">13.38dp</dimen>
<dimen name="overview_grid_focus_vertical_margin">0dp</dimen>
diff --git a/quickstep/res/values/styles.xml b/quickstep/res/values/styles.xml
index 40e18ec..2efe72e 100644
--- a/quickstep/res/values/styles.xml
+++ b/quickstep/res/values/styles.xml
@@ -137,8 +137,8 @@
<style name="OverviewClearAllButton" parent="@android:style/Widget.DeviceDefault.Button">
<item name="android:background">@drawable/bg_overview_clear_all_button</item>
- <item name="android:minWidth">85dp</item>
- <item name="android:minHeight">36dp</item>
+ <item name="android:minWidth">96dp</item>
+ <item name="android:minHeight">48dp</item>
<item name="android:stateListAnimator">@null</item>
</style>
diff --git a/quickstep/src/com/android/launcher3/LauncherInitListener.java b/quickstep/src/com/android/launcher3/LauncherInitListener.java
index 5fc79f0..35151f1 100644
--- a/quickstep/src/com/android/launcher3/LauncherInitListener.java
+++ b/quickstep/src/com/android/launcher3/LauncherInitListener.java
@@ -17,11 +17,8 @@
import android.animation.AnimatorSet;
import android.annotation.TargetApi;
-import android.content.Context;
-import android.content.Intent;
import android.os.Build;
import android.os.CancellationSignal;
-import android.os.Handler;
import com.android.quickstep.util.ActivityInitListener;
import com.android.quickstep.util.RemoteAnimationProvider;
@@ -78,11 +75,4 @@
mRemoteAnimationProvider = null;
super.unregister();
}
-
- @Override
- public void registerAndStartActivity(Intent intent, RemoteAnimationProvider animProvider,
- Context context, Handler handler, long duration) {
- mRemoteAnimationProvider = animProvider;
- super.registerAndStartActivity(intent, animProvider, context, handler, duration);
- }
}
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index 7e5bda5..2ccec44 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -285,7 +285,8 @@
long statusBarTransitionDelay = duration - STATUS_BAR_TRANSITION_DURATION
- STATUS_BAR_TRANSITION_PRE_DELAY;
RemoteAnimationAdapterCompat adapterCompat =
- new RemoteAnimationAdapterCompat(runner, duration, statusBarTransitionDelay);
+ new RemoteAnimationAdapterCompat(runner, duration, statusBarTransitionDelay,
+ mLauncher.getIApplicationThread());
return new ActivityOptionsWrapper(
ActivityOptionsCompat.makeRemoteAnimation(adapterCompat), onEndCallback);
}
@@ -1081,7 +1082,8 @@
new RemoteAnimationAdapterCompat(
new LauncherAnimationRunner(mHandler, mWallpaperOpenRunner,
false /* startAtFrontOfQueue */),
- CLOSING_TRANSITION_DURATION_MS, 0 /* statusBarTransitionDelay */));
+ CLOSING_TRANSITION_DURATION_MS, 0 /* statusBarTransitionDelay */,
+ mLauncher.getIApplicationThread()));
if (KEYGUARD_ANIMATION.get()) {
mKeyguardGoingAwayRunner = createWallpaperOpenRunner(true /* fromUnlock */);
@@ -1091,7 +1093,8 @@
new LauncherAnimationRunner(
mHandler, mKeyguardGoingAwayRunner,
true /* startAtFrontOfQueue */),
- CLOSING_TRANSITION_DURATION_MS, 0 /* statusBarTransitionDelay */));
+ CLOSING_TRANSITION_DURATION_MS, 0 /* statusBarTransitionDelay */,
+ mLauncher.getIApplicationThread()));
}
new ActivityCompat(mLauncher).registerRemoteAnimations(definition);
@@ -1109,7 +1112,7 @@
mWallpaperOpenTransitionRunner = createWallpaperOpenRunner(false /* fromUnlock */);
mLauncherOpenTransition = RemoteAnimationAdapterCompat.buildRemoteTransition(
new LauncherAnimationRunner(mHandler, mWallpaperOpenTransitionRunner,
- false /* startAtFrontOfQueue */));
+ false /* startAtFrontOfQueue */), mLauncher.getIApplicationThread());
mLauncherOpenTransition.addHomeOpenCheck(mLauncher.getComponentName());
SystemUiProxy.INSTANCE.getNoCreate().registerRemoteTransition(mLauncherOpenTransition);
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index ae647db..5bc454e 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -20,6 +20,7 @@
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_OPEN;
+import static com.android.launcher3.testing.TestProtocol.TASKBAR_WINDOW_CRASH;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
import static com.android.systemui.shared.system.WindowManagerWrapper.ITYPE_BOTTOM_TAPPABLE_ELEMENT;
@@ -60,6 +61,7 @@
import com.android.launcher3.logger.LauncherAtom;
import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.touch.ItemClickHandler;
import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.util.SettingsCache;
@@ -200,6 +202,9 @@
updateSysuiStateFlags(sharedState.sysuiStateFlags, true /* fromInit */);
mWindowManager.addView(mDragLayer, mWindowLayoutParams);
+ if (TestProtocol.sDebugTracing) {
+ Log.e(TASKBAR_WINDOW_CRASH, "Adding taskbar window");
+ }
}
public boolean isThreeButtonNav() {
@@ -330,6 +335,9 @@
setUIController(TaskbarUIController.DEFAULT);
mControllers.onDestroy();
mWindowManager.removeViewImmediate(mDragLayer);
+ if (TestProtocol.sDebugTracing) {
+ Log.e(TASKBAR_WINDOW_CRASH, "Removing taskbar window");
+ }
}
public void updateSysuiStateFlags(int systemUiStateFlags, boolean fromInit) {
@@ -510,20 +518,4 @@
protected boolean isUserSetupComplete() {
return mIsUserSetupComplete;
}
-
- /**
- * Called when we determine the touchable region.
- *
- * @param exclude {@code true} then the magnification region computation will omit the window.
- */
- public void excludeFromMagnificationRegion(boolean exclude) {
- if (exclude) {
- mWindowLayoutParams.privateFlags |=
- WindowManager.LayoutParams.PRIVATE_FLAG_EXCLUDE_FROM_SCREEN_MAGNIFICATION;
- } else {
- mWindowLayoutParams.privateFlags &=
- ~WindowManager.LayoutParams.PRIVATE_FLAG_EXCLUDE_FROM_SCREEN_MAGNIFICATION;
- }
- mWindowManager.updateViewLayout(mDragLayer, mWindowLayoutParams);
- }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
index 8c6185c..cec892f 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
@@ -137,14 +137,12 @@
// Always have nav buttons be touchable
mControllers.navbarButtonsViewController.addVisibleButtonsRegion(
mTaskbarDragLayer, insetsInfo.touchableRegion);
- boolean insetsIsTouchableRegion = true;
if (mTaskbarDragLayer.getAlpha() < AlphaUpdateListener.ALPHA_CUTOFF_THRESHOLD) {
// Let touches pass through us.
insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION);
} else if (mControllers.navbarButtonsViewController.isImeVisible()) {
insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_CONTENT);
- insetsIsTouchableRegion = false;
} else if (!mControllers.uiController.isTaskbarTouchable()) {
// Let touches pass through us.
insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION);
@@ -153,11 +151,9 @@
// Taskbar has some touchable elements, take over the full taskbar area
insetsInfo.setTouchableInsets(mActivity.isTaskbarWindowFullscreen()
? TOUCHABLE_INSETS_FRAME : TOUCHABLE_INSETS_CONTENT);
- insetsIsTouchableRegion = false;
} else {
insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION);
}
- mActivity.excludeFromMagnificationRegion(insetsIsTouchableRegion);
}
/**
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
index 089c265..53feaad 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
@@ -17,6 +17,8 @@
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
+
+import static com.android.launcher3.testing.TestProtocol.TASKBAR_WINDOW_CRASH;
import static com.android.launcher3.util.DisplayController.CHANGE_ACTIVE_SCREEN;
import static com.android.launcher3.util.DisplayController.CHANGE_DENSITY;
import static com.android.launcher3.util.DisplayController.CHANGE_SUPPORTED_BOUNDS;
@@ -29,6 +31,7 @@
import android.hardware.display.DisplayManager;
import android.net.Uri;
import android.provider.Settings;
+import android.util.Log;
import android.view.Display;
import androidx.annotation.NonNull;
@@ -39,6 +42,7 @@
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.statemanager.StatefulActivity;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.DisplayController.Info;
import com.android.launcher3.util.SettingsCache;
@@ -203,6 +207,10 @@
}
private void recreateTaskbar() {
+ if (TestProtocol.sDebugTracing) {
+ Log.e(TASKBAR_WINDOW_CRASH, "Recreating taskbar: mTaskbarActivityContext="
+ + mTaskbarActivityContext);
+ }
destroyExistingTaskbar();
DeviceProfile dp =
@@ -225,6 +233,9 @@
mTaskbarActivityContext.setUIController(
createTaskbarUIControllerForActivity(mActivity));
}
+ if (TestProtocol.sDebugTracing) {
+ Log.e(TASKBAR_WINDOW_CRASH, "Finished recreating taskbar");
+ }
}
public void onSystemUiFlagsChanged(int systemUiStateFlags) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
index 6fbef9b..a8a0b59 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
@@ -102,9 +102,7 @@
}
private void showIMESwitcher() {
- mService.getSystemService(InputMethodManager.class)
- .showInputMethodPickerFromSystem(true /* showAuxiliarySubtypes */,
- DEFAULT_DISPLAY);
+ SystemUiProxy.INSTANCE.getNoCreate().onImeSwitcherPressed();
}
private void notifyImeClick(boolean longClick) {
diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
index cf06036..944fb48 100644
--- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
@@ -308,7 +308,7 @@
Rect insets = dp.getInsets();
int topMargin = dp.overviewTaskThumbnailTopMarginPx;
int bottomMargin = getOverviewActionsHeight(context, dp);
- int sideMargin = res.getDimensionPixelSize(R.dimen.overview_grid_side_margin);
+ int sideMargin = dp.overviewGridSideMargin;
outRect.set(0, 0, dp.widthPx, dp.heightPx);
outRect.inset(Math.max(insets.left, sideMargin), insets.top + topMargin,
diff --git a/quickstep/src/com/android/quickstep/RecentTasksList.java b/quickstep/src/com/android/quickstep/RecentTasksList.java
index 3080f04..79dd633 100644
--- a/quickstep/src/com/android/quickstep/RecentTasksList.java
+++ b/quickstep/src/com/android/quickstep/RecentTasksList.java
@@ -22,35 +22,33 @@
import android.app.ActivityManager;
import android.os.Build;
import android.os.Process;
-import android.util.Log;
+import android.os.RemoteException;
import android.util.SparseBooleanArray;
import androidx.annotation.VisibleForTesting;
-import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.LooperExecutor;
+import com.android.systemui.shared.recents.model.GroupTask;
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.TaskStackChangeListener;
-import com.android.systemui.shared.system.TaskStackChangeListeners;
+import com.android.wm.shell.recents.IRecentTasksListener;
+import com.android.wm.shell.util.GroupedRecentTaskInfo;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.List;
import java.util.function.Consumer;
/**
* Manages the recent task list from the system, caching it as necessary.
*/
@TargetApi(Build.VERSION_CODES.R)
-public class RecentTasksList extends TaskStackChangeListener {
+public class RecentTasksList {
private static final TaskLoadResult INVALID_RESULT = new TaskLoadResult(-1, false, 0);
private final KeyguardManagerCompat mKeyguardManager;
private final LooperExecutor mMainThreadExecutor;
- private final ActivityManagerWrapper mActivityManagerWrapper;
+ private final SystemUiProxy mSysUiProxy;
// The list change id, increments as the task list changes in the system
private int mChangeId;
@@ -62,12 +60,17 @@
private TaskLoadResult mResultsUi = INVALID_RESULT;
public RecentTasksList(LooperExecutor mainThreadExecutor,
- KeyguardManagerCompat keyguardManager, ActivityManagerWrapper activityManagerWrapper) {
+ KeyguardManagerCompat keyguardManager, SystemUiProxy sysUiProxy) {
mMainThreadExecutor = mainThreadExecutor;
mKeyguardManager = keyguardManager;
mChangeId = 1;
- mActivityManagerWrapper = activityManagerWrapper;
- TaskStackChangeListeners.getInstance().registerTaskStackListener(this);
+ mSysUiProxy = sysUiProxy;
+ sysUiProxy.registerRecentTasksListener(new IRecentTasksListener.Stub() {
+ @Override
+ public void onRecentTasksChanged() throws RemoteException {
+ mMainThreadExecutor.execute(RecentTasksList.this::onRecentTasksChanged);
+ }
+ });
}
@VisibleForTesting
@@ -78,10 +81,11 @@
/**
* Fetches the task keys skipping any local cache.
*/
- public void getTaskKeys(int numTasks, Consumer<ArrayList<Task>> callback) {
+ public void getTaskKeys(int numTasks, Consumer<ArrayList<GroupTask>> callback) {
// Kick off task loading in the background
UI_HELPER_EXECUTOR.execute(() -> {
- ArrayList<Task> tasks = loadTasksInBackground(numTasks, -1, true /* loadKeysOnly */);
+ ArrayList<GroupTask> tasks = loadTasksInBackground(numTasks, -1,
+ true /* loadKeysOnly */);
mMainThreadExecutor.execute(() -> callback.accept(tasks));
});
}
@@ -93,14 +97,15 @@
* @param callback The callback to receive the list of recent tasks
* @return The change id of the current task list
*/
- public synchronized int getTasks(boolean loadKeysOnly, Consumer<ArrayList<Task>> callback) {
+ public synchronized int getTasks(boolean loadKeysOnly,
+ Consumer<ArrayList<GroupTask>> callback) {
final int requestLoadId = mChangeId;
if (mResultsUi.isValidForRequest(requestLoadId, loadKeysOnly)) {
// The list is up to date, send the callback on the next frame,
// so that requestID can be returned first.
if (callback != null) {
// Copy synchronously as the changeId might change by next frame
- ArrayList<Task> result = copyOf(mResultsUi);
+ ArrayList<GroupTask> result = copyOf(mResultsUi);
mMainThreadExecutor.post(() -> {
callback.accept(result);
});
@@ -120,7 +125,7 @@
mLoadingTasksInBackground = false;
mResultsUi = loadResult;
if (callback != null) {
- ArrayList<Task> result = copyOf(mResultsUi);
+ ArrayList<GroupTask> result = copyOf(mResultsUi);
callback.accept(result);
}
});
@@ -136,35 +141,7 @@
return mChangeId == changeId;
}
- @Override
- public void onTaskStackChanged() {
- invalidateLoadedTasks();
- }
-
- @Override
- public void onRecentTaskListUpdated() {
- // In some cases immediately after booting, the tasks in the system recent task list may be
- // loaded, but not in the active task hierarchy in the system. These tasks are displayed in
- // overview, but removing them don't result in a onTaskStackChanged() nor a onTaskRemoved()
- // callback (those are for changes to the active tasks), but the task list is still updated,
- // so we should also invalidate the change id to ensure we load a new list instead of
- // reusing a stale list.
- invalidateLoadedTasks();
- }
-
- @Override
- public void onTaskRemoved(int taskId) {
- invalidateLoadedTasks();
- }
-
-
- @Override
- public void onActivityPinned(String packageName, int userId, int taskId, int stackId) {
- invalidateLoadedTasks();
- }
-
- @Override
- public synchronized void onActivityUnpinned() {
+ public void onRecentTasksChanged() {
invalidateLoadedTasks();
}
@@ -180,8 +157,8 @@
@VisibleForTesting
TaskLoadResult loadTasksInBackground(int numTasks, int requestId, boolean loadKeysOnly) {
int currentUserId = Process.myUserHandle().getIdentifier();
- List<ActivityManager.RecentTaskInfo> rawTasks =
- mActivityManagerWrapper.getRecentTasks(numTasks, currentUserId);
+ ArrayList<GroupedRecentTaskInfo> rawTasks =
+ mSysUiProxy.getRecentTasks(numTasks, currentUserId);
// The raw tasks are given in most-recent to least-recent order, we need to reverse it
Collections.reverse(rawTasks);
@@ -197,45 +174,53 @@
};
TaskLoadResult allTasks = new TaskLoadResult(requestId, loadKeysOnly, rawTasks.size());
- for (ActivityManager.RecentTaskInfo rawTask : rawTasks) {
- Task.TaskKey taskKey = new Task.TaskKey(rawTask);
- Task task;
- if (!loadKeysOnly) {
- boolean isLocked = tmpLockedUsers.get(taskKey.userId);
- task = Task.from(taskKey, rawTask, isLocked);
- } else {
- task = new Task(taskKey);
+ for (GroupedRecentTaskInfo rawTask : rawTasks) {
+ ActivityManager.RecentTaskInfo taskInfo1 = rawTask.mTaskInfo1;
+ ActivityManager.RecentTaskInfo taskInfo2 = rawTask.mTaskInfo2;
+ Task.TaskKey task1Key = new Task.TaskKey(taskInfo1);
+ Task task1 = loadKeysOnly
+ ? new Task(task1Key)
+ : Task.from(task1Key, taskInfo1,
+ tmpLockedUsers.get(task1Key.userId) /* isLocked */);
+ task1.setLastSnapshotData(taskInfo1);
+ Task task2 = null;
+ if (taskInfo2 != null) {
+ Task.TaskKey task2Key = new Task.TaskKey(taskInfo2);
+ task2 = loadKeysOnly
+ ? new Task(task2Key)
+ : Task.from(task2Key, taskInfo2,
+ tmpLockedUsers.get(task2Key.userId) /* isLocked */);
+ task2.setLastSnapshotData(taskInfo2);
}
- task.setLastSnapshotData(rawTask);
- allTasks.add(task);
+ allTasks.add(new GroupTask(task1, task2));
}
return allTasks;
}
- private ArrayList<Task> copyOf(ArrayList<Task> tasks) {
- ArrayList<Task> newTasks = new ArrayList<>();
+ private ArrayList<GroupTask> copyOf(ArrayList<GroupTask> tasks) {
+ ArrayList<GroupTask> newTasks = new ArrayList<>();
for (int i = 0; i < tasks.size(); i++) {
- newTasks.add(new Task(tasks.get(i)));
+ newTasks.add(new GroupTask(tasks.get(i)));
}
return newTasks;
}
- private static class TaskLoadResult extends ArrayList<Task> {
+ private static class TaskLoadResult extends ArrayList<GroupTask> {
- final int mId;
+ final int mRequestId;
// If the result was loaded with keysOnly = true
final boolean mKeysOnly;
- TaskLoadResult(int id, boolean keysOnly, int size) {
+ TaskLoadResult(int requestId, boolean keysOnly, int size) {
super(size);
- mId = id;
+ mRequestId = requestId;
mKeysOnly = keysOnly;
}
boolean isValidForRequest(int requestId, boolean loadKeysOnly) {
- return mId == requestId && (!mKeysOnly || loadKeysOnly);
+ return mRequestId == requestId && (!mKeysOnly || loadKeysOnly);
}
}
}
\ No newline at end of file
diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java
index ad7e4df..09a0b7d 100644
--- a/quickstep/src/com/android/quickstep/RecentsActivity.java
+++ b/quickstep/src/com/android/quickstep/RecentsActivity.java
@@ -245,7 +245,7 @@
RemoteAnimationAdapterCompat adapterCompat = new RemoteAnimationAdapterCompat(
wrapper, RECENTS_LAUNCH_DURATION,
RECENTS_LAUNCH_DURATION - STATUS_BAR_TRANSITION_DURATION
- - STATUS_BAR_TRANSITION_PRE_DELAY);
+ - STATUS_BAR_TRANSITION_PRE_DELAY, getIApplicationThread());
final ActivityOptionsWrapper activityOptions = new ActivityOptionsWrapper(
ActivityOptionsCompat.makeRemoteAnimation(adapterCompat),
onEndCallback);
@@ -394,7 +394,8 @@
LauncherAnimationRunner runner = new LauncherAnimationRunner(
getMainThreadHandler(), mAnimationToHomeFactory, true);
RemoteAnimationAdapterCompat adapterCompat =
- new RemoteAnimationAdapterCompat(runner, HOME_APPEAR_DURATION, 0);
+ new RemoteAnimationAdapterCompat(runner, HOME_APPEAR_DURATION, 0,
+ getIApplicationThread());
startActivity(createHomeIntent(),
ActivityOptionsCompat.makeRemoteAnimation(adapterCompat).toBundle());
}
diff --git a/quickstep/src/com/android/quickstep/RecentsModel.java b/quickstep/src/com/android/quickstep/RecentsModel.java
index 1e82c8c..71153c6 100644
--- a/quickstep/src/com/android/quickstep/RecentsModel.java
+++ b/quickstep/src/com/android/quickstep/RecentsModel.java
@@ -34,6 +34,7 @@
import com.android.launcher3.icons.IconProvider.IconChangeListener;
import com.android.launcher3.util.Executors.SimpleThreadFactory;
import com.android.launcher3.util.MainThreadInitializedObject;
+import com.android.systemui.shared.recents.model.GroupTask;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -70,7 +71,7 @@
private RecentsModel(Context context) {
mContext = context;
mTaskList = new RecentTasksList(MAIN_EXECUTOR,
- new KeyguardManagerCompat(context), ActivityManagerWrapper.getInstance());
+ new KeyguardManagerCompat(context), SystemUiProxy.INSTANCE.get(context));
IconProvider iconProvider = new IconProvider(context);
mIconCache = new TaskIconCache(context, RECENTS_MODEL_EXECUTOR, iconProvider);
@@ -95,7 +96,7 @@
* always called on the UI thread.
* @return the request id associated with this call.
*/
- public int getTasks(Consumer<ArrayList<Task>> callback) {
+ public int getTasks(Consumer<ArrayList<GroupTask>> callback) {
return mTaskList.getTasks(false /* loadKeysOnly */, callback);
}
@@ -120,9 +121,9 @@
* @param callback Receives true if task is removed, false otherwise
*/
public void isTaskRemoved(int taskId, Consumer<Boolean> callback) {
- mTaskList.getTasks(true /* loadKeysOnly */, (tasks) -> {
- for (Task task : tasks) {
- if (task.key.id == taskId) {
+ mTaskList.getTasks(true /* loadKeysOnly */, (taskGroups) -> {
+ for (GroupTask group : taskGroups) {
+ if (group.containsTask(taskId)) {
callback.accept(false);
return;
}
@@ -148,14 +149,15 @@
ActivityManager.RunningTaskInfo runningTask =
ActivityManagerWrapper.getInstance().getRunningTask();
int runningTaskId = runningTask != null ? runningTask.id : -1;
- mTaskList.getTaskKeys(mThumbnailCache.getCacheSize(), tasks -> {
- for (Task task : tasks) {
- if (task.key.id == runningTaskId) {
+ mTaskList.getTaskKeys(mThumbnailCache.getCacheSize(), taskGroups -> {
+ for (GroupTask group : taskGroups) {
+ if (group.containsTask(runningTaskId)) {
// Skip the running task, it's not going to have an up-to-date snapshot by the
// time the user next enters overview
continue;
}
- mThumbnailCache.updateThumbnailInCache(task);
+ mThumbnailCache.updateThumbnailInCache(group.task1);
+ mThumbnailCache.updateThumbnailInCache(group.task2);
}
});
}
diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java
index b6f9d58..a875b69 100644
--- a/quickstep/src/com/android/quickstep/SystemUiProxy.java
+++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java
@@ -15,6 +15,8 @@
*/
package com.android.quickstep;
+import static android.app.ActivityManager.RECENT_IGNORE_UNAVAILABLE;
+
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import android.app.PendingIntent;
@@ -48,6 +50,9 @@
import com.android.wm.shell.onehanded.IOneHanded;
import com.android.wm.shell.pip.IPip;
import com.android.wm.shell.pip.IPipAnimationListener;
+import com.android.wm.shell.recents.IRecentTasks;
+import com.android.wm.shell.recents.IRecentTasksListener;
+import com.android.wm.shell.util.GroupedRecentTaskInfo;
import com.android.wm.shell.splitscreen.ISplitScreen;
import com.android.wm.shell.splitscreen.ISplitScreenListener;
import com.android.wm.shell.startingsurface.IStartingWindow;
@@ -55,6 +60,7 @@
import com.android.wm.shell.transition.IShellTransitions;
import java.util.ArrayList;
+import java.util.Arrays;
/**
* Holds the reference to SystemUI.
@@ -73,6 +79,7 @@
private IOneHanded mOneHanded;
private IShellTransitions mShellTransitions;
private IStartingWindow mStartingWindow;
+ private IRecentTasks mRecentTasks;
private final DeathRecipient mSystemUiProxyDeathRecipient = () -> {
MAIN_EXECUTOR.execute(() -> clearProxy());
};
@@ -83,6 +90,7 @@
private ISplitScreenListener mPendingSplitScreenListener;
private IStartingWindowListener mPendingStartingWindowListener;
private ISmartspaceCallback mPendingSmartspaceCallback;
+ private IRecentTasksListener mPendingRecentTasksListener;
private final ArrayList<RemoteTransitionCompat> mPendingRemoteTransitions = new ArrayList<>();
// Used to dedupe calls to SystemUI
@@ -118,6 +126,17 @@
}
@Override
+ public void onImeSwitcherPressed() {
+ if (mSystemUiProxy != null) {
+ try {
+ mSystemUiProxy.onImeSwitcherPressed();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed call onImeSwitcherPressed", e);
+ }
+ }
+ }
+
+ @Override
public void setHomeRotationEnabled(boolean enabled) {
if (mSystemUiProxy != null) {
try {
@@ -136,7 +155,7 @@
public void setProxy(ISystemUiProxy proxy, IPip pip, ISplitScreen splitScreen,
IOneHanded oneHanded, IShellTransitions shellTransitions,
- IStartingWindow startingWindow,
+ IStartingWindow startingWindow, IRecentTasks recentTasks,
ISmartspaceTransitionController smartSpaceTransitionController) {
unlinkToDeath();
mSystemUiProxy = proxy;
@@ -146,6 +165,7 @@
mShellTransitions = shellTransitions;
mStartingWindow = startingWindow;
mSmartspaceTransitionController = smartSpaceTransitionController;
+ mRecentTasks = recentTasks;
linkToDeath();
// re-attach the listeners once missing due to setProxy has not been initialized yet.
if (mPendingPipAnimationListener != null && mPip != null) {
@@ -168,6 +188,10 @@
registerRemoteTransition(mPendingRemoteTransitions.get(i));
}
mPendingRemoteTransitions.clear();
+ if (mPendingRecentTasksListener != null && mRecentTasks != null) {
+ registerRecentTasksListener(mPendingRecentTasksListener);
+ mPendingRecentTasksListener = null;
+ }
if (mPendingSetNavButtonAlpha != null) {
mPendingSetNavButtonAlpha.run();
@@ -176,7 +200,7 @@
}
public void clearProxy() {
- setProxy(null, null, null, null, null, null, null);
+ setProxy(null, null, null, null, null, null, null, null);
}
// TODO(141886704): Find a way to remove this
@@ -748,7 +772,6 @@
}
}
-
//
// SmartSpace transitions
//
@@ -764,4 +787,43 @@
mPendingSmartspaceCallback = callback;
}
}
+
+ //
+ // Recents
+ //
+
+ public void registerRecentTasksListener(IRecentTasksListener listener) {
+ if (mRecentTasks != null) {
+ try {
+ mRecentTasks.registerRecentTasksListener(listener);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed call registerRecentTasksListener", e);
+ }
+ } else {
+ mPendingRecentTasksListener = listener;
+ }
+ }
+
+ public void unregisterRecentTasksListener(IRecentTasksListener listener) {
+ if (mRecentTasks != null) {
+ try {
+ mRecentTasks.unregisterRecentTasksListener(listener);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed call unregisterRecentTasksListener");
+ }
+ }
+ mPendingRecentTasksListener = null;
+ }
+
+ public ArrayList<GroupedRecentTaskInfo> getRecentTasks(int numTasks, int userId) {
+ if (mRecentTasks != null) {
+ try {
+ return new ArrayList<>(Arrays.asList(mRecentTasks.getRecentTasks(numTasks,
+ RECENT_IGNORE_UNAVAILABLE, userId)));
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed call getRecentTasks", e);
+ }
+ }
+ return new ArrayList<>();
+ }
}
diff --git a/quickstep/src/com/android/quickstep/TaskAnimationManager.java b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
index 4b89981..258a0c2 100644
--- a/quickstep/src/com/android/quickstep/TaskAnimationManager.java
+++ b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
@@ -178,7 +178,8 @@
if (ENABLE_SHELL_TRANSITIONS) {
RemoteTransitionCompat transition = new RemoteTransitionCompat(mCallbacks,
- mController != null ? mController.getController() : null);
+ mController != null ? mController.getController() : null,
+ mCtx.getIApplicationThread());
Bundle options = ActivityOptionsCompat.makeRemoteTransition(transition)
.setTransientLaunch().toBundle();
mCtx.startActivity(intent, options);
diff --git a/quickstep/src/com/android/quickstep/TaskThumbnailCache.java b/quickstep/src/com/android/quickstep/TaskThumbnailCache.java
index a8a0219..eaa43cf 100644
--- a/quickstep/src/com/android/quickstep/TaskThumbnailCache.java
+++ b/quickstep/src/com/android/quickstep/TaskThumbnailCache.java
@@ -104,6 +104,9 @@
* Synchronously fetches the thumbnail for the given {@param task} and puts it in the cache.
*/
public void updateThumbnailInCache(Task task) {
+ if (task == null) {
+ return;
+ }
Preconditions.assertUIThread();
// Fetch the thumbnail for this task and put it in the cache
if (task.thumbnail == null) {
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index ecc4b2b..c037ac4 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -22,9 +22,11 @@
import static com.android.launcher3.config.FeatureFlags.ASSISTANT_GIVES_LAUNCHER_FOCUS;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
+import static com.android.launcher3.testing.TestProtocol.TASKBAR_WINDOW_CRASH;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.quickstep.GestureState.DEFAULT_STATE;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
+import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_RECENT_TASKS;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_ONE_HANDED;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_PIP;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_SHELL_TRANSITIONS;
@@ -112,6 +114,7 @@
import com.android.systemui.shared.tracing.ProtoTraceable;
import com.android.wm.shell.onehanded.IOneHanded;
import com.android.wm.shell.pip.IPip;
+import com.android.wm.shell.recents.IRecentTasks;
import com.android.wm.shell.splitscreen.ISplitScreen;
import com.android.wm.shell.startingsurface.IStartingWindow;
import com.android.wm.shell.transition.IShellTransitions;
@@ -170,9 +173,11 @@
ISmartspaceTransitionController smartspaceTransitionController =
ISmartspaceTransitionController.Stub.asInterface(
bundle.getBinder(KEY_EXTRA_SMARTSPACE_TRANSITION_CONTROLLER));
+ IRecentTasks recentTasks = IRecentTasks.Stub.asInterface(
+ bundle.getBinder(KEY_EXTRA_RECENT_TASKS));
MAIN_EXECUTOR.execute(() -> {
SystemUiProxy.INSTANCE.get(TouchInteractionService.this).setProxy(proxy, pip,
- splitscreen, onehanded, shellTransitions, startingWindow,
+ splitscreen, onehanded, shellTransitions, startingWindow, recentTasks,
smartspaceTransitionController);
TouchInteractionService.this.initInputMonitor();
preloadOverview(true /* fromInit */);
@@ -350,6 +355,9 @@
@Override
public void onCreate() {
super.onCreate();
+ if (TestProtocol.sDebugTracing) {
+ Log.e(TASKBAR_WINDOW_CRASH, "TIS created");
+ }
// Initialize anything here that is needed in direct boot mode.
// Everything else should be initialized in onUserUnlocked() below.
mMainChoreographer = Choreographer.getInstance();
@@ -511,6 +519,9 @@
@Override
public void onDestroy() {
Log.d(TAG, "Touch service destroyed: user=" + getUserId());
+ if (TestProtocol.sDebugTracing) {
+ Log.e(TASKBAR_WINDOW_CRASH, "TIS destroyed");
+ }
sIsInitialized = false;
if (mDeviceState.isUserUnlocked()) {
mInputConsumer.unregisterInputConsumer();
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
index 7e8b83e..48315d0 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
@@ -42,6 +42,7 @@
import com.android.quickstep.views.OverviewActionsView;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
+import com.android.systemui.shared.recents.model.GroupTask;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.Task.TaskKey;
@@ -153,29 +154,31 @@
}
@Override
- protected void applyLoadPlan(ArrayList<Task> tasks) {
+ protected void applyLoadPlan(ArrayList<GroupTask> taskGroups) {
// When quick-switching on 3p-launcher, we add a "stub" 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 if we are switching on any other app.
// TODO(b/195607777) Confirm home task info is front-most task and not mixed in with others
int runningTaskId = getTaskIdsForRunningTaskView()[0];
- if (mHomeTaskInfo != null && mHomeTaskInfo.taskId == runningTaskId && !tasks.isEmpty()) {
+ if (mHomeTaskInfo != null && mHomeTaskInfo.taskId == runningTaskId && !taskGroups.isEmpty()) {
// Check if the task list has running task
boolean found = false;
- for (Task t : tasks) {
- if (t.key.id == runningTaskId) {
+ for (GroupTask group : taskGroups) {
+ if (group.containsTask(runningTaskId)) {
found = true;
break;
}
}
if (!found) {
- ArrayList<Task> newList = new ArrayList<>(tasks.size() + 1);
- newList.addAll(tasks);
- newList.add(Task.from(new TaskKey(mHomeTaskInfo), mHomeTaskInfo, false));
- tasks = newList;
+ ArrayList<GroupTask> newList = new ArrayList<>(taskGroups.size() + 1);
+ newList.addAll(taskGroups);
+ newList.add(new GroupTask(
+ Task.from(new TaskKey(mHomeTaskInfo), mHomeTaskInfo, false),
+ null));
+ taskGroups = newList;
}
}
- super.applyLoadPlan(tasks);
+ super.applyLoadPlan(taskGroups);
}
@Override
diff --git a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java
index fb6cd8a..49d8203 100644
--- a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java
@@ -43,6 +43,13 @@
}
@Override
+ public Integer getSuccessFeedbackSubtitle() {
+ return mTutorialFragment.isAtFinalStep()
+ ? R.string.back_gesture_feedback_complete_without_follow_up
+ : R.string.back_gesture_feedback_complete_with_overview_follow_up;
+ }
+
+ @Override
protected int getMockAppTaskLayoutResId() {
return getMockAppTaskCurrentPageLayoutResId();
}
@@ -85,10 +92,7 @@
case BACK_COMPLETED_FROM_RIGHT:
mTutorialFragment.releaseFeedbackAnimation();
updateFakeAppTaskViewLayout(getMockAppTaskPreviousPageLayoutResId());
- int subtitleResId = mTutorialFragment.isAtFinalStep()
- ? R.string.back_gesture_feedback_complete_without_follow_up
- : R.string.back_gesture_feedback_complete_with_overview_follow_up;
- showFeedback(subtitleResId, true);
+ showSuccessFeedback();
break;
case BACK_CANCELLED_FROM_LEFT:
case BACK_CANCELLED_FROM_RIGHT:
diff --git a/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java b/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java
index 7fb7d29..c2524b1 100644
--- a/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java
+++ b/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java
@@ -35,10 +35,9 @@
/** Shows the gesture interactive sandbox in full screen mode. */
public class GestureSandboxActivity extends FragmentActivity {
- private static final String LOG_TAG = "GestureSandboxActivity";
-
private static final String KEY_TUTORIAL_STEPS = "tutorial_steps";
private static final String KEY_CURRENT_STEP = "current_step";
+ private static final String KEY_GESTURE_COMPLETE = "gesture_complete";
private TutorialType[] mTutorialSteps;
private TutorialType mCurrentTutorialStep;
@@ -56,7 +55,8 @@
Bundle args = savedInstanceState == null ? getIntent().getExtras() : savedInstanceState;
mTutorialSteps = getTutorialSteps(args);
mCurrentTutorialStep = mTutorialSteps[mCurrentStep - 1];
- mFragment = TutorialFragment.newInstance(mCurrentTutorialStep);
+ mFragment = TutorialFragment.newInstance(
+ mCurrentTutorialStep, args.getBoolean(KEY_GESTURE_COMPLETE, false));
getSupportFragmentManager().beginTransaction()
.add(R.id.gesture_tutorial_fragment_container, mFragment)
.commit();
@@ -87,6 +87,7 @@
protected void onSaveInstanceState(@NonNull Bundle savedInstanceState) {
savedInstanceState.putStringArray(KEY_TUTORIAL_STEPS, getTutorialStepNames());
savedInstanceState.putInt(KEY_CURRENT_STEP, mCurrentStep);
+ savedInstanceState.putBoolean(KEY_GESTURE_COMPLETE, mFragment.isGestureComplete());
super.onSaveInstanceState(savedInstanceState);
}
@@ -121,7 +122,7 @@
return;
}
mCurrentTutorialStep = mTutorialSteps[mCurrentStep];
- mFragment = TutorialFragment.newInstance(mCurrentTutorialStep);
+ mFragment = TutorialFragment.newInstance(mCurrentTutorialStep, false);
getSupportFragmentManager().beginTransaction()
.replace(R.id.gesture_tutorial_fragment_container, mFragment)
.runOnCommit(() -> mFragment.onAttachedToWindow())
diff --git a/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java
index bbb22e6..0bc3691 100644
--- a/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java
@@ -42,6 +42,13 @@
}
@Override
+ public Integer getSuccessFeedbackSubtitle() {
+ return mTutorialFragment.isAtFinalStep()
+ ? R.string.home_gesture_feedback_complete_without_follow_up
+ : R.string.home_gesture_feedback_complete_with_follow_up;
+ }
+
+ @Override
protected int getMockAppTaskLayoutResId() {
return mTutorialFragment.isLargeScreen()
? R.layout.gesture_tutorial_foldable_mock_webpage
@@ -84,10 +91,7 @@
case HOME_GESTURE_COMPLETED: {
mTutorialFragment.releaseFeedbackAnimation();
animateFakeTaskViewHome(finalVelocity, null);
- int subtitleResId = mTutorialFragment.isAtFinalStep()
- ? R.string.home_gesture_feedback_complete_without_follow_up
- : R.string.home_gesture_feedback_complete_with_follow_up;
- showFeedback(subtitleResId, true);
+ showSuccessFeedback();
break;
}
case HOME_NOT_STARTED_TOO_FAR_FROM_EDGE:
diff --git a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java
index 0fea0d7..f308f27 100644
--- a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java
@@ -52,6 +52,13 @@
}
@Override
+ public Integer getSuccessFeedbackSubtitle() {
+ return mTutorialFragment.getNumSteps() > 1 && mTutorialFragment.isAtFinalStep()
+ ? R.string.overview_gesture_feedback_complete_with_follow_up
+ : R.string.overview_gesture_feedback_complete_without_follow_up;
+ }
+
+ @Override
protected int getMockAppTaskLayoutResId() {
return mTutorialFragment.isLargeScreen()
? R.layout.gesture_tutorial_foldable_mock_conversation_list
@@ -106,11 +113,7 @@
mTutorialFragment.releaseFeedbackAnimation();
animateTaskViewToOverview();
onMotionPaused(true /*arbitrary value*/);
- int subtitleResId = mTutorialFragment.getNumSteps() > 1
- && mTutorialFragment.isAtFinalStep()
- ? R.string.overview_gesture_feedback_complete_with_follow_up
- : R.string.overview_gesture_feedback_complete_without_follow_up;
- showFeedback(subtitleResId, true);
+ showSuccessFeedback();
break;
case HOME_OR_OVERVIEW_NOT_STARTED_WRONG_SWIPE_DIRECTION:
case HOME_OR_OVERVIEW_CANCELLED:
diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialController.java b/quickstep/src/com/android/quickstep/interaction/TutorialController.java
index 81e18f6..4145393 100644
--- a/quickstep/src/com/android/quickstep/interaction/TutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/TutorialController.java
@@ -223,6 +223,11 @@
return null;
}
+ @StringRes
+ public Integer getSuccessFeedbackSubtitle() {
+ return null;
+ }
+
void showFeedback() {
if (mGestureCompleted) {
mFeedbackView.setTranslationY(0);
@@ -236,6 +241,13 @@
}
/**
+ * Show feedback reflecting a successful gesture attempt.
+ **/
+ void showSuccessFeedback() {
+ showFeedback(getSuccessFeedbackSubtitle(), true);
+ }
+
+ /**
* Show feedback reflecting a failed gesture attempt.
*
* @param subtitleResId Resource of the text to display.
diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
index 89be1a6..2fd7cde 100644
--- a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
+++ b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
@@ -49,8 +49,10 @@
private static final String LOG_TAG = "TutorialFragment";
static final String KEY_TUTORIAL_TYPE = "tutorial_type";
+ static final String KEY_GESTURE_COMPLETE = "gesture_complete";
TutorialType mTutorialType;
+ boolean mGestureComplete = false;
@Nullable TutorialController mTutorialController = null;
RootSandboxLayout mRootView;
View mFingerDotView;
@@ -67,7 +69,7 @@
private boolean mIsLargeScreen;
- public static TutorialFragment newInstance(TutorialType tutorialType) {
+ public static TutorialFragment newInstance(TutorialType tutorialType, boolean gestureComplete) {
TutorialFragment fragment = getFragmentForTutorialType(tutorialType);
if (fragment == null) {
fragment = new BackGestureTutorialFragment();
@@ -76,6 +78,7 @@
Bundle args = new Bundle();
args.putSerializable(KEY_TUTORIAL_TYPE, tutorialType);
+ args.putBoolean(KEY_GESTURE_COMPLETE, gestureComplete);
fragment.setArguments(args);
return fragment;
}
@@ -132,6 +135,7 @@
super.onCreate(savedInstanceState);
Bundle args = savedInstanceState != null ? savedInstanceState : getArguments();
mTutorialType = (TutorialType) args.getSerializable(KEY_TUTORIAL_TYPE);
+ mGestureComplete = args.getBoolean(KEY_GESTURE_COMPLETE, false);
mEdgeBackGestureHandler = new EdgeBackGestureHandler(getContext());
mNavBarGestureHandler = new NavBarGestureHandler(getContext());
@@ -186,11 +190,13 @@
}
void initializeFeedbackVideoView() {
- if (!updateFeedbackAnimation()) {
+ if (!updateFeedbackAnimation() || mTutorialController == null) {
return;
}
- if (!mIntroductionShown && mTutorialController != null) {
+ if (isGestureComplete()) {
+ mTutorialController.showSuccessFeedback();
+ } else if (!mIntroductionShown) {
Integer introTileStringResId = mTutorialController.getIntroductionTitle();
Integer introSubtitleResId = mTutorialController.getIntroductionSubtitle();
if (introTileStringResId != null && introSubtitleResId != null) {
@@ -372,6 +378,11 @@
return getCurrentStep() == getNumSteps();
}
+ boolean isGestureComplete() {
+ return mGestureComplete
+ || (mTutorialController != null && mTutorialController.isGestureCompleted());
+ }
+
@Nullable
private GestureSandboxActivity getGestureSandboxActivity() {
Context context = getContext();
diff --git a/quickstep/src/com/android/quickstep/util/ActivityInitListener.java b/quickstep/src/com/android/quickstep/util/ActivityInitListener.java
index b9879ab..aeec36f 100644
--- a/quickstep/src/com/android/quickstep/util/ActivityInitListener.java
+++ b/quickstep/src/com/android/quickstep/util/ActivityInitListener.java
@@ -15,11 +15,6 @@
*/
package com.android.quickstep.util;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.Handler;
-
import com.android.launcher3.BaseActivity;
import com.android.launcher3.util.ActivityTracker;
import com.android.launcher3.util.ActivityTracker.SchedulerCallback;
@@ -75,17 +70,4 @@
mIsRegistered = false;
mOnInitListener = null;
}
-
- /**
- * Starts the given intent with the provided animation. Unlike {@link #register(Intent)}, this
- * method will not call {@link #init} if the activity already exists, it will only call it when
- * we get handleIntent() for the provided intent that we're starting.
- */
- public void registerAndStartActivity(Intent intent, RemoteAnimationProvider animProvider,
- Context context, Handler handler, long duration) {
- register();
-
- Bundle options = animProvider.toActivityOptions(handler, duration, context).toBundle();
- context.startActivity(new Intent(intent), options);
- }
}
diff --git a/quickstep/src/com/android/quickstep/util/RemoteAnimationProvider.java b/quickstep/src/com/android/quickstep/util/RemoteAnimationProvider.java
index 98dbd47..ee82ae6 100644
--- a/quickstep/src/com/android/quickstep/util/RemoteAnimationProvider.java
+++ b/quickstep/src/com/android/quickstep/util/RemoteAnimationProvider.java
@@ -16,32 +16,14 @@
package com.android.quickstep.util;
import android.animation.AnimatorSet;
-import android.app.ActivityOptions;
-import android.content.Context;
-import android.os.Handler;
-import com.android.launcher3.LauncherAnimationRunner;
-import com.android.launcher3.LauncherAnimationRunner.RemoteAnimationFactory;
-import com.android.systemui.shared.system.ActivityOptionsCompat;
-import com.android.systemui.shared.system.RemoteAnimationAdapterCompat;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
public abstract class RemoteAnimationProvider {
- RemoteAnimationFactory mAnimationRunner;
-
public abstract AnimatorSet createWindowAnimation(RemoteAnimationTargetCompat[] appTargets,
RemoteAnimationTargetCompat[] wallpaperTargets);
- ActivityOptions toActivityOptions(Handler handler, long duration, Context context) {
- mAnimationRunner = (transit, appTargets, wallpaperTargets, nonApps, result) ->
- result.setAnimation(createWindowAnimation(appTargets, wallpaperTargets), context);
- final LauncherAnimationRunner wrapper = new LauncherAnimationRunner(
- handler, mAnimationRunner, false /* startAtFrontOfQueue */);
- return ActivityOptionsCompat.makeRemoteAnimation(
- new RemoteAnimationAdapterCompat(wrapper, duration, 0));
- }
-
/**
* @return the target with the lowest opaque layer for a certain app animation, or null.
*/
diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
index 1dae2c8..4c300ec 100644
--- a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
@@ -94,7 +94,8 @@
new RemoteSplitLaunchTransitionRunner(task1, task2);
mSystemUiProxy.startTasks(taskIds[0], null /* mainOptions */, taskIds[1],
null /* sideOptions */, STAGE_POSITION_BOTTOM_OR_RIGHT,
- new RemoteTransitionCompat(animationRunner, MAIN_EXECUTOR));
+ new RemoteTransitionCompat(animationRunner, MAIN_EXECUTOR,
+ ActivityThread.currentActivityThread().getApplicationThread()));
} else {
RemoteSplitLaunchAnimationRunner animationRunner =
new RemoteSplitLaunchAnimationRunner(task1, task2, callback);
diff --git a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
index 734c844..977c696 100644
--- a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
+++ b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
@@ -15,6 +15,7 @@
*/
package com.android.quickstep.util;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.states.RotationHelper.deltaRotation;
import static com.android.launcher3.touch.PagedOrientationHandler.MATRIX_POST_TRANSLATE;
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
@@ -99,6 +100,7 @@
private boolean mLayoutValid = false;
private int mOrientationStateId;
private StagedSplitBounds mStagedSplitBounds;
+ private boolean mDrawsBelowRecents;
public TaskViewSimulator(Context context, BaseActivityInterface sizeStrategy) {
mContext = context;
@@ -198,6 +200,10 @@
recentsViewScroll.value = scroll;
}
+ public void setDrawsBelowRecents(boolean drawsBelowRecents) {
+ mDrawsBelowRecents = drawsBelowRecents;
+ }
+
/**
* Adds animation for all the components corresponding to transition from an app to overview.
*/
@@ -351,6 +357,12 @@
builder.withMatrix(mMatrix)
.withWindowCrop(mTmpCropRect)
.withCornerRadius(getCurrentCornerRadius());
+
+ if (ENABLE_QUICKSTEP_LIVE_TILE.get() && params.getRecentsSurface() != null) {
+ // When relativeLayer = 0, it reverts the surfaces back to the original order.
+ builder.withRelativeLayerTo(params.getRecentsSurface(),
+ mDrawsBelowRecents ? Integer.MIN_VALUE : 0);
+ }
}
/**
diff --git a/quickstep/src/com/android/quickstep/views/ClearAllButton.java b/quickstep/src/com/android/quickstep/views/ClearAllButton.java
index 86be210..4f2ed4c 100644
--- a/quickstep/src/com/android/quickstep/views/ClearAllButton.java
+++ b/quickstep/src/com/android/quickstep/views/ClearAllButton.java
@@ -21,6 +21,7 @@
import android.util.FloatProperty;
import android.widget.Button;
+import com.android.launcher3.DeviceProfile;
import com.android.launcher3.statemanager.StatefulActivity;
import com.android.launcher3.touch.PagedOrientationHandler;
@@ -245,6 +246,9 @@
* Get the Y translation that is set in the original layout position, before scrolling.
*/
private float getOriginalTranslationY() {
- return mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx / 2.0f;
+ DeviceProfile deviceProfile = mActivity.getDeviceProfile();
+ return deviceProfile.overviewShowAsGrid
+ ? deviceProfile.overviewRowSpacing
+ : deviceProfile.overviewTaskThumbnailTopMarginPx / 2.0f;
}
}
diff --git a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
index 76d3591..5a8cbc1 100644
--- a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
+++ b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
@@ -20,6 +20,7 @@
import android.content.res.Configuration;
import android.graphics.Rect;
import android.util.AttributeSet;
+import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.FrameLayout;
@@ -30,6 +31,7 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Insettable;
import com.android.launcher3.R;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.MultiValueAlpha;
import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
import com.android.quickstep.SysUINavigationMode;
@@ -110,6 +112,11 @@
protected void onFinishInflate() {
super.onFinishInflate();
findViewById(R.id.action_screenshot).setOnClickListener(this);
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.NO_SCREENSHOT, "Inflated OverviewActionsView and added screenshot"
+ + " listener.");
+ }
+
mSplitButton = findViewById(R.id.action_split);
mSplitButton.setOnClickListener(this);
}
@@ -125,6 +132,11 @@
@Override
public void onClick(View view) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.NO_SCREENSHOT, "OverviewActionsView - onClick"
+ + " callbacks: " + mCallbacks + " view id: " + view.getId() + " "
+ + " is screenshot? " + (view.getId() == R.id.action_screenshot));
+ }
if (mCallbacks == null) {
return;
}
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 1a3bfa9..b5238c6 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -167,6 +167,7 @@
import com.android.quickstep.util.TransformParams;
import com.android.quickstep.util.VibratorWrapper;
import com.android.systemui.plugins.ResourceProvider;
+import com.android.systemui.shared.recents.model.GroupTask;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.Task.TaskKey;
import com.android.systemui.shared.recents.model.ThumbnailData;
@@ -1296,13 +1297,13 @@
updateGridProperties();
}
- protected void applyLoadPlan(ArrayList<Task> tasks) {
+ protected void applyLoadPlan(ArrayList<GroupTask> taskGroups) {
if (mPendingAnimation != null) {
- mPendingAnimation.addEndListener(success -> applyLoadPlan(tasks));
+ mPendingAnimation.addEndListener(success -> applyLoadPlan(taskGroups));
return;
}
- if (tasks == null || tasks.isEmpty()) {
+ if (taskGroups == null || taskGroups.isEmpty()) {
removeTasksViewsAndClearAllButton();
onTaskStackUpdated();
return;
@@ -1324,10 +1325,11 @@
LauncherSplitScreenListener.INSTANCE.getNoCreate().getPersistentSplitIds();
int requiredGroupTaskViews = splitTaskIds.length / 2;
+ // TODO(b/202740477): Update once grouped tasks are returned
// Subtract half the number of split tasks and not total number because we've already
// added a GroupedTaskView when swipe up gesture happens.
// This will need to change if we start showing GroupedTaskViews during swipe up from home
- int requiredTaskViewCount = tasks.size() - requiredGroupTaskViews;
+ int requiredTaskViewCount = taskGroups.size() - requiredGroupTaskViews;
if (getTaskViewCount() != requiredTaskViewCount) {
if (indexOfChild(mClearAllButton) != -1) {
@@ -1360,11 +1362,12 @@
+ " runningTaskViewId: " + mRunningTaskViewId
+ " forTaskView: " + getTaskViewFromTaskViewId(mRunningTaskViewId));
- for (int taskViewIndex = requiredTaskViewCount - 1, taskDataIndex = tasks.size() - 1;
+ for (int taskViewIndex = requiredTaskViewCount - 1, taskDataIndex = taskGroups.size() - 1;
taskViewIndex >= 0;
taskViewIndex--, taskDataIndex--) {
final int pageIndex = requiredTaskViewCount - taskViewIndex - 1;
- final Task task = tasks.get(taskDataIndex);
+ // TODO(b/202740477): Temporary assumption, to be updated once groups are actually used
+ final Task task = taskGroups.get(taskDataIndex).task1;
final TaskView taskView = (TaskView) getChildAt(pageIndex);
if (taskView instanceof GroupedTaskView) {
Task leftTop;
@@ -1372,11 +1375,11 @@
if (task.key.id == splitTaskIds[0]) {
leftTop = task;
taskDataIndex--;
- rightBottom = tasks.get(taskDataIndex);
+ rightBottom = taskGroups.get(taskDataIndex).task1;
} else {
rightBottom = task;
taskDataIndex--;
- leftTop = tasks.get(taskDataIndex);
+ leftTop = taskGroups.get(taskDataIndex).task1;
}
((GroupedTaskView) taskView).bind(leftTop, rightBottom, mOrientationState,
mSplitBoundsConfig);
@@ -1911,8 +1914,10 @@
}
}
setEnableDrawingLiveTile(false);
- runActionOnRemoteHandles(remoteTargetHandle -> remoteTargetHandle.getTransformParams()
- .setTargetSet(null));
+ runActionOnRemoteHandles(remoteTargetHandle -> {
+ remoteTargetHandle.getTransformParams().setTargetSet(null);
+ remoteTargetHandle.getTaskViewSimulator().setDrawsBelowRecents(true);
+ });
// These are relatively expensive and don't need to be done this frame (RecentsView isn't
// visible anyway), so defer by a frame to get off the critical path, e.g. app to home.
@@ -4368,12 +4373,13 @@
TaskViewSimulator tvs = remoteTargetHandle.getTaskViewSimulator();
tvs.setOrientationState(mOrientationState);
tvs.setDp(mActivity.getDeviceProfile());
+ tvs.setDrawsBelowRecents(true);
tvs.recentsViewScale.value = 1;
}
}
/** Helper to avoid writing some for-loops to iterate over {@link #mRemoteTargetHandles} */
- private void runActionOnRemoteHandles(Consumer<RemoteTargetHandle> consumer) {
+ public void runActionOnRemoteHandles(Consumer<RemoteTargetHandle> consumer) {
if (mRemoteTargetHandles == null) {
return;
}
diff --git a/quickstep/src/com/android/quickstep/views/TaskMenuView.java b/quickstep/src/com/android/quickstep/views/TaskMenuView.java
index 5c73fbb..77ac373 100644
--- a/quickstep/src/com/android/quickstep/views/TaskMenuView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskMenuView.java
@@ -16,6 +16,7 @@
package com.android.quickstep.views;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_UNDEFINED;
import static com.android.quickstep.views.TaskThumbnailView.DIM_ALPHA;
@@ -242,7 +243,17 @@
LayoutParams lp = (LayoutParams) menuOptionView.getLayoutParams();
mTaskView.getPagedOrientationHandler().setLayoutParamsForTaskMenuOptionItem(lp,
menuOptionView, mActivity.getDeviceProfile());
- menuOptionView.setOnClickListener(menuOption::onClick);
+ menuOptionView.setOnClickListener(view -> {
+ if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
+ RecentsView recentsView = mTaskView.getRecentsView();
+ recentsView.switchToScreenshot(null,
+ () -> recentsView.finishRecentsAnimation(true /* toRecents */,
+ false /* shouldPip */,
+ () -> menuOption.onClick(view)));
+ } else {
+ menuOption.onClick(view);
+ }
+ });
mOptionLayout.addView(menuOptionView);
}
diff --git a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
index a9db400..2d58ba5 100644
--- a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
@@ -31,6 +31,8 @@
import android.graphics.Insets;
import android.graphics.Matrix;
import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
@@ -78,6 +80,7 @@
private TaskOverlay mOverlay;
private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Paint mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ private final Paint mClearPaint = new Paint();
private final Paint mDimmingPaintAfterClearing = new Paint();
private final int mDimColor;
@@ -107,6 +110,7 @@
super(context, attrs, defStyleAttr);
mPaint.setFilterBitmap(true);
mBackgroundPaint.setColor(Color.WHITE);
+ mClearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
mActivity = BaseActivity.fromContext(context);
// Initialize with placeholder value. It is overridden later by TaskView
mFullscreenParams = TEMP_PARAMS.get(context);
@@ -271,6 +275,7 @@
float cornerRadius) {
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
if (mTask != null && getTaskView().isRunningTask() && !getTaskView().showScreenshot()) {
+ canvas.drawRoundRect(x, y, width, height, cornerRadius, cornerRadius, mClearPaint);
canvas.drawRoundRect(x, y, width, height, cornerRadius, cornerRadius,
mDimmingPaintAfterClearing);
return;
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index eef5fb3..f88b243 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -94,6 +94,7 @@
import com.android.quickstep.util.LauncherSplitScreenListener;
import com.android.quickstep.util.RecentsOrientedState;
import com.android.quickstep.util.TaskCornerRadius;
+import com.android.quickstep.util.TaskViewSimulator;
import com.android.quickstep.util.TransformParams;
import com.android.quickstep.views.TaskThumbnailView.PreviewPositionHelper;
import com.android.systemui.shared.recents.model.Task;
@@ -625,7 +626,21 @@
recentsView.getDepthController());
anim.addListener(new AnimatorListenerAdapter() {
@Override
+ public void onAnimationStart(Animator animator) {
+ recentsView.runActionOnRemoteHandles(
+ (Consumer<RemoteTargetHandle>) remoteTargetHandle ->
+ remoteTargetHandle
+ .getTaskViewSimulator()
+ .setDrawsBelowRecents(false));
+ }
+
+ @Override
public void onAnimationEnd(Animator animator) {
+ recentsView.runActionOnRemoteHandles(
+ (Consumer<RemoteTargetHandle>) remoteTargetHandle ->
+ remoteTargetHandle
+ .getTaskViewSimulator()
+ .setDrawsBelowRecents(true));
mIsClickableAsLiveTile = true;
}
});
@@ -821,15 +836,7 @@
if (confirmSecondSplitSelectApp()) {
return;
}
- if (ENABLE_QUICKSTEP_LIVE_TILE.get() && isRunningTask()) {
- RecentsView recentsView = getRecentsView();
- recentsView.switchToScreenshot(
- () -> recentsView.finishRecentsAnimation(true /* toRecents */,
- false /* shouldPip */,
- () -> showTaskMenu(iconView)));
- } else {
- showTaskMenu(iconView);
- }
+ showTaskMenu(iconView);
});
iconView.setOnLongClickListener(v -> {
requestDisallowInterceptTouchEvent(true);
diff --git a/quickstep/tests/src/com/android/quickstep/RecentTasksListTest.java b/quickstep/tests/src/com/android/quickstep/RecentTasksListTest.java
index 79ddf7a..6b2d5ed 100644
--- a/quickstep/tests/src/com/android/quickstep/RecentTasksListTest.java
+++ b/quickstep/tests/src/com/android/quickstep/RecentTasksListTest.java
@@ -30,70 +30,78 @@
import androidx.test.filters.SmallTest;
import com.android.launcher3.util.LooperExecutor;
+import com.android.systemui.shared.recents.model.GroupTask;
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.wm.shell.util.GroupedRecentTaskInfo;
import org.junit.Before;
import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@SmallTest
public class RecentTasksListTest {
- private ActivityManagerWrapper mockActivityManagerWrapper;
+ @Mock
+ private SystemUiProxy mockSystemUiProxy;
// Class under test
private RecentTasksList mRecentTasksList;
@Before
public void setup() {
+ MockitoAnnotations.initMocks(this);
LooperExecutor mockMainThreadExecutor = mock(LooperExecutor.class);
KeyguardManagerCompat mockKeyguardManagerCompat = mock(KeyguardManagerCompat.class);
- mockActivityManagerWrapper = mock(ActivityManagerWrapper.class);
mRecentTasksList = new RecentTasksList(mockMainThreadExecutor, mockKeyguardManagerCompat,
- mockActivityManagerWrapper);
+ mockSystemUiProxy);
}
@Test
- public void onTaskRemoved_doesNotFetchTasks() {
- mRecentTasksList.onTaskRemoved(0);
- verify(mockActivityManagerWrapper, times(0))
- .getRecentTasks(anyInt(), anyInt());
- }
-
- @Test
- public void onTaskStackChanged_doesNotFetchTasks() {
- mRecentTasksList.onTaskStackChanged();
- verify(mockActivityManagerWrapper, times(0))
+ public void onRecentTasksChanged_doesNotFetchTasks() {
+ mRecentTasksList.onRecentTasksChanged();
+ verify(mockSystemUiProxy, times(0))
.getRecentTasks(anyInt(), anyInt());
}
@Test
public void loadTasksInBackground_onlyKeys_noValidTaskDescription() {
- ActivityManager.RecentTaskInfo recentTaskInfo = new ActivityManager.RecentTaskInfo();
- when(mockActivityManagerWrapper.getRecentTasks(anyInt(), anyInt()))
- .thenReturn(Collections.singletonList(recentTaskInfo));
+ GroupedRecentTaskInfo recentTaskInfos = new GroupedRecentTaskInfo(
+ new ActivityManager.RecentTaskInfo(), new ActivityManager.RecentTaskInfo());
+ when(mockSystemUiProxy.getRecentTasks(anyInt(), anyInt()))
+ .thenReturn(new ArrayList<>(Collections.singletonList(recentTaskInfos)));
- List<Task> taskList = mRecentTasksList.loadTasksInBackground(Integer.MAX_VALUE, -1, true);
+ List<GroupTask> taskList = mRecentTasksList.loadTasksInBackground(Integer.MAX_VALUE, -1,
+ true);
assertEquals(1, taskList.size());
- assertNull(taskList.get(0).taskDescription.getLabel());
+ assertNull(taskList.get(0).task1.taskDescription.getLabel());
+ assertNull(taskList.get(0).task2.taskDescription.getLabel());
}
@Test
public void loadTasksInBackground_moreThanKeys_hasValidTaskDescription() {
String taskDescription = "Wheeee!";
- ActivityManager.RecentTaskInfo recentTaskInfo = new ActivityManager.RecentTaskInfo();
- recentTaskInfo.taskDescription = new ActivityManager.TaskDescription(taskDescription);
- when(mockActivityManagerWrapper.getRecentTasks(anyInt(), anyInt()))
- .thenReturn(Collections.singletonList(recentTaskInfo));
+ ActivityManager.RecentTaskInfo task1 = new ActivityManager.RecentTaskInfo();
+ task1.taskDescription = new ActivityManager.TaskDescription(taskDescription);
+ ActivityManager.RecentTaskInfo task2 = new ActivityManager.RecentTaskInfo();
+ task2.taskDescription = new ActivityManager.TaskDescription();
+ GroupedRecentTaskInfo recentTaskInfos = new GroupedRecentTaskInfo(
+ task1, task2);
+ when(mockSystemUiProxy.getRecentTasks(anyInt(), anyInt()))
+ .thenReturn(new ArrayList<>(Collections.singletonList(recentTaskInfos)));
- List<Task> taskList = mRecentTasksList.loadTasksInBackground(Integer.MAX_VALUE, -1, false);
+ List<GroupTask> taskList = mRecentTasksList.loadTasksInBackground(Integer.MAX_VALUE, -1,
+ false);
assertEquals(1, taskList.size());
- assertEquals(taskDescription, taskList.get(0).taskDescription.getLabel());
+ assertEquals(taskDescription, taskList.get(0).task1.taskDescription.getLabel());
+ assertNull(taskList.get(0).task2.taskDescription.getLabel());
}
}
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index 437a19b..ea65757 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -44,6 +44,7 @@
import org.junit.After;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -292,6 +293,7 @@
// TODO(b/204830798): test with all navigation modes(add @NavigationModeSwitch annotation)
// after the bug resolved.
+ @Ignore("b/205027405")
@Test
@PortraitLandscape
@ScreenRecord
diff --git a/res/layout/all_apps.xml b/res/layout/all_apps.xml
index a34baef..7f9f63e 100644
--- a/res/layout/all_apps.xml
+++ b/res/layout/all_apps.xml
@@ -43,15 +43,6 @@
<include layout="@layout/all_apps_personal_work_tabs" />
- <Button
- android:id="@+id/all_apps_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:text="@string/all_apps_label"
- android:background="@drawable/padded_rounded_action_button"
- android:visibility="gone"/>
-
</com.android.launcher3.allapps.FloatingHeaderView>
<include layout="@layout/search_container_all_apps" />
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 4d137c8..2cf929f 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -333,6 +333,8 @@
<dimen name="overview_actions_top_margin_gesture_grid_landscape">0dp</dimen>
<dimen name="overview_actions_bottom_margin_gesture_grid_landscape">0dp</dimen>
<dimen name="overview_actions_margin_three_button">0dp</dimen>
+ <dimen name="overview_grid_side_margin_portrait">0dp</dimen>
+ <dimen name="overview_grid_side_margin_landscape">0dp</dimen>
<dimen name="overview_grid_row_spacing_portrait">0dp</dimen>
<dimen name="overview_grid_row_spacing_landscape">0dp</dimen>
<dimen name="recents_page_spacing">0dp</dimen>
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 0b60b32..5c16b4c 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -193,6 +193,7 @@
public final int overviewActionsBottomMarginGesturePx;
public int overviewPageSpacing;
public int overviewRowSpacing;
+ public int overviewGridSideMargin;
// Widgets
public final PointF appWidgetScale = new PointF(1.0f, 1.0f);
@@ -399,6 +400,9 @@
overviewRowSpacing = isLandscape
? res.getDimensionPixelSize(R.dimen.overview_grid_row_spacing_landscape)
: res.getDimensionPixelSize(R.dimen.overview_grid_row_spacing_portrait);
+ overviewGridSideMargin = isLandscape
+ ? res.getDimensionPixelSize(R.dimen.overview_grid_side_margin_landscape)
+ : res.getDimensionPixelSize(R.dimen.overview_grid_side_margin_portrait);
// Calculate all of the remaining variables.
extraSpace = updateAvailableDimensions(res);
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index fc717c9..ce06c6e 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -329,6 +329,7 @@
}
updateWorkspaceScreensPadding();
+ updateWorkspaceWidgetsSizes();
}
private void updateWorkspaceScreensPadding() {
@@ -360,6 +361,25 @@
}
}
+ private void updateWorkspaceWidgetsSizes() {
+ int numberOfScreens = mScreenOrder.size();
+ for (int i = 0; i < numberOfScreens; i++) {
+ ShortcutAndWidgetContainer shortcutAndWidgetContainer =
+ mWorkspaceScreens.get(mScreenOrder.get(i)).getShortcutsAndWidgets();
+ int shortcutsAndWidgetCount = shortcutAndWidgetContainer.getChildCount();
+ for (int j = 0; j < shortcutsAndWidgetCount; j++) {
+ View view = shortcutAndWidgetContainer.getChildAt(j);
+ if (view instanceof LauncherAppWidgetHostView
+ && view.getTag() instanceof LauncherAppWidgetInfo) {
+ LauncherAppWidgetInfo launcherAppWidgetInfo =
+ (LauncherAppWidgetInfo) view.getTag();
+ WidgetSizes.updateWidgetSizeRanges((LauncherAppWidgetHostView) view,
+ mLauncher, launcherAppWidgetInfo.spanX, launcherAppWidgetInfo.spanY);
+ }
+ }
+ }
+ }
+
/**
* Estimates the size of an item using spans: hSpan, vSpan.
*
diff --git a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
index 874fe80..f089551 100644
--- a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
+++ b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
@@ -42,6 +42,7 @@
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.R;
import com.android.launcher3.model.data.AppInfo;
+import com.android.launcher3.model.data.ItemInfoWithIcon;
import com.android.launcher3.util.PackageManagerHelper;
import java.util.Arrays;
@@ -95,16 +96,15 @@
// The type of this item
public int viewType;
- /** App-only properties */
- // The section name of this app. Note that there can be multiple items with different
+ // The section name of this item. Note that there can be multiple items with different
// sectionNames in the same section
public String sectionName = null;
// The row that this item shows up on
public int rowIndex;
// The index of this app in the row
public int rowAppIndex;
- // The associated AppInfo for the app
- public AppInfo appInfo = null;
+ // The associated ItemInfoWithIcon for the item
+ public ItemInfoWithIcon itemInfo = null;
// The index of this app not including sections
public int appIndex = -1;
// Search section associated to result
@@ -119,7 +119,7 @@
item.viewType = VIEW_TYPE_ICON;
item.position = pos;
item.sectionName = sectionName;
- item.appInfo = appInfo;
+ item.itemInfo = appInfo;
item.appIndex = appIndex;
return item;
}
@@ -373,7 +373,7 @@
if (adapterProvider != null) {
return adapterProvider.onCreateViewHolder(mLayoutInflater, parent, viewType);
}
- throw new RuntimeException("Unexpected view type");
+ throw new RuntimeException("Unexpected view type" + viewType);
}
}
@@ -382,10 +382,13 @@
switch (holder.getItemViewType()) {
case VIEW_TYPE_ICON:
AdapterItem adapterItem = mApps.getAdapterItems().get(position);
- AppInfo info = adapterItem.appInfo;
BubbleTextView icon = (BubbleTextView) holder.itemView;
icon.reset();
- icon.applyFromApplicationInfo(info);
+ if (adapterItem.itemInfo instanceof AppInfo) {
+ icon.applyFromApplicationInfo((AppInfo) adapterItem.itemInfo);
+ } else {
+ icon.applyFromItemInfoWithIcon(adapterItem.itemInfo);
+ }
break;
case VIEW_TYPE_EMPTY_SEARCH:
TextView emptyViewText = (TextView) holder.itemView;
diff --git a/src/com/android/launcher3/allapps/FloatingHeaderView.java b/src/com/android/launcher3/allapps/FloatingHeaderView.java
index 3ca0303..85ee636 100644
--- a/src/com/android/launcher3/allapps/FloatingHeaderView.java
+++ b/src/com/android/launcher3/allapps/FloatingHeaderView.java
@@ -47,7 +47,6 @@
ValueAnimator.AnimatorUpdateListener, PluginListener<AllAppsRow>, Insettable,
OnHeightUpdatedListener {
- private static final long ALL_APPS_CONTENT_ANIM_DURATION = 150;
private final Rect mRVClip = new Rect(0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE);
private final Rect mHeaderClip = new Rect(0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE);
private final ValueAnimator mAnimator = ValueAnimator.ofInt(0, 0);
@@ -110,13 +109,6 @@
private FloatingHeaderRow[] mAllRows = FloatingHeaderRow.NO_ROWS;
- // members for handling suggestion state
- private final ValueAnimator mAllAppsContentAnimator = ValueAnimator.ofFloat(0, 0);
- private View mAllAppsButton;
- private int mAllAppsContentFadeInOffset;
- private boolean mInSuggestionMode = false;
-
-
public FloatingHeaderView(@NonNull Context context) {
this(context, null);
}
@@ -127,20 +119,12 @@
.getDimensionPixelSize(R.dimen.all_apps_header_top_padding);
mHeaderProtectionSupported = context.getResources().getBoolean(
R.bool.config_header_protection_supported);
- mAllAppsContentFadeInOffset = context.getResources()
- .getDimensionPixelSize(R.dimen.all_apps_content_fade_in_offset);
- mAllAppsContentAnimator.setDuration(ALL_APPS_CONTENT_ANIM_DURATION);
- mAllAppsContentAnimator.addUpdateListener(this::onAllAppsContentAnimationUpdate);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mTabLayout = findViewById(R.id.tabs);
- mAllAppsButton = findViewById(R.id.all_apps_button);
- if (mAllAppsButton != null) {
- mAllAppsButton.setOnClickListener(this::onAllAppsButtonClicked);
- }
// Find all floating header rows.
ArrayList<FloatingHeaderRow> rows = new ArrayList<>();
@@ -329,7 +313,6 @@
}
mTabLayout.setTranslationY(mTranslationY);
- setSuggestionMode(false);
int clipHeight = mHeaderTopPadding - getPaddingBottom();
mRVClip.top = mTabsHidden ? clipHeight : 0;
@@ -365,7 +348,6 @@
mTranslationY = 0;
applyVerticalMove();
}
- setSuggestionMode(false);
mHeaderCollapsed = false;
mSnappedScrolledY = -mMaxTranslation;
mCurrentRV.scrollToTop();
@@ -461,38 +443,6 @@
}
return Math.max(getHeight() - getPaddingTop() + mTranslationY, 0);
}
-
- /**
- * When suggestion mode is enabled, hides AllApps content view and shows AllApps button.
- */
- public void setSuggestionMode(boolean isSuggestMode) {
- if (mInSuggestionMode == isSuggestMode || mAllAppsButton == null) return;
- if (!FeatureFlags.ENABLE_ONE_SEARCH.get()) return;
- AllAppsContainerView allApps = (AllAppsContainerView) getParent();
- mInSuggestionMode = isSuggestMode;
- if (isSuggestMode) {
- mTabLayout.setVisibility(GONE);
- mAllAppsButton.setVisibility(VISIBLE);
- allApps.getContentView().setVisibility(GONE);
- } else {
- mTabLayout.setVisibility(mTabsHidden ? GONE : VISIBLE);
- mAllAppsButton.setVisibility(GONE);
- allApps.getContentView().setVisibility(VISIBLE);
- }
- }
-
- private void onAllAppsButtonClicked(View view) {
- setSuggestionMode(false);
- mAllAppsContentAnimator.start();
- }
-
- private void onAllAppsContentAnimationUpdate(ValueAnimator valueAnimator) {
- float prog = valueAnimator.getAnimatedFraction();
- View allAppsList = ((AllAppsContainerView) getParent()).getContentView();
- allAppsList.setAlpha(255 * prog);
- allAppsList.setTranslationY((1 - prog) * mAllAppsContentFadeInOffset);
- }
-
}
diff --git a/src/com/android/launcher3/testing/TestProtocol.java b/src/com/android/launcher3/testing/TestProtocol.java
index db28902..91c7221 100644
--- a/src/com/android/launcher3/testing/TestProtocol.java
+++ b/src/com/android/launcher3/testing/TestProtocol.java
@@ -121,6 +121,7 @@
public static final String REQUEST_MOCK_SENSOR_ROTATION = "mock-sensor-rotation";
public static final String PERMANENT_DIAG_TAG = "TaplTarget";
+ public static final String TASKBAR_WINDOW_CRASH = "b/201305599";
public static final String TASK_VIEW_ID_CRASH = "b/195430732";
public static final String NO_DROP_TARGET = "b/195031154";
public static final String NULL_INT_SET = "b/200572078";
diff --git a/tests/AndroidManifest-common.xml b/tests/AndroidManifest-common.xml
index aae8fb5..4390211 100644
--- a/tests/AndroidManifest-common.xml
+++ b/tests/AndroidManifest-common.xml
@@ -109,7 +109,7 @@
<activity
android:name="com.android.launcher3.testcomponent.TestLauncherActivity"
android:clearTaskOnLaunch="true"
- android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize|density"
+ android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize"
android:enabled="false"
android:label="Test launcher"
android:launchMode="singleTask"
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index 82163cb..b3457cd 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -346,13 +346,19 @@
}
// Cannot be used in TaplTests between a Tapl call injecting a gesture and a tapl call
- // expecting
- // the results of that gesture because the wait can hide flakeness.
+ // expecting the results of that gesture because the wait can hide flakeness.
protected void waitForState(String message, Supplier<LauncherState> state) {
waitForLauncherCondition(message,
launcher -> launcher.getStateManager().getCurrentStableState() == state.get());
}
+ // Cannot be used in TaplTests between a Tapl call injecting a gesture and a tapl call
+ // expecting the results of that gesture because the wait can hide flakeness.
+ protected void waitForStableState(String message, Supplier<LauncherState> state) {
+ waitForLauncherCondition(message,
+ launcher -> launcher.getStateManager().isInStableState(state.get()));
+ }
+
protected void waitForResumed(String message) {
waitForLauncherCondition(message, launcher -> launcher.hasBeenResumed());
}
diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
index 4007c26..f29ac23 100644
--- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
+++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
@@ -387,6 +387,7 @@
return appIcon;
}
+ @Ignore("b/205014516")
@Test
@PortraitLandscape
public void testDragToFolder() throws Exception {
@@ -413,6 +414,7 @@
folder.close();
}
+ @Ignore("b/205027405")
@Test
@PortraitLandscape
public void testPressBack() throws Exception {
diff --git a/tests/src/com/android/launcher3/ui/WorkProfileTest.java b/tests/src/com/android/launcher3/ui/WorkProfileTest.java
index 27a2375..2087bfe 100644
--- a/tests/src/com/android/launcher3/ui/WorkProfileTest.java
+++ b/tests/src/com/android/launcher3/ui/WorkProfileTest.java
@@ -91,9 +91,9 @@
public void workTabExists() {
mDevice.pressHome();
waitForLauncherCondition("Launcher didn't start", Objects::nonNull);
- waitForState("Launcher internal state didn't switch to Normal", () -> NORMAL);
+ waitForStableState("Launcher internal state didn't switch to Normal", () -> NORMAL);
executeOnLauncher(launcher -> launcher.getStateManager().goToState(ALL_APPS));
- waitForState("Launcher internal state didn't switch to All Apps", () -> ALL_APPS);
+ waitForStableState("Launcher internal state didn't switch to All Apps", () -> ALL_APPS);
waitForLauncherCondition("Personal tab is missing",
launcher -> launcher.getAppsView().isPersonalTabVisible(),
LauncherInstrumentation.WAIT_TIME_MS);