Use system recent tasks stabilization

Bug: 111926330
Test: Swipe to last task, ensure it resets task list on timeout or interaction

Change-Id: Id09215a4cfdea63a4be6fb69fced163ad3bc10bd
This commit is contained in:
Winson Chung
2019-03-26 14:36:52 -07:00
parent 14b2f9dd57
commit a5354e02a2
6 changed files with 31 additions and 181 deletions

View File

@@ -851,16 +851,6 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
Interpolator interpolator, GestureEndTarget target, PointF velocityPxPerMs) {
mGestureEndTarget = target;
if (mGestureEndTarget.canBeContinued) {
// Because we might continue this gesture, e.g. for consecutive quick switch, we need to
// stabilize the task list so that tasks don't rearrange in the middle of the gesture.
RecentsModel.INSTANCE.get(mContext).startStabilizationSession();
} else if (mGestureEndTarget.isLauncher) {
// Otherwise, if we're going to home or overview,
// we reset the tasks to a consistent start state.
RecentsModel.INSTANCE.get(mContext).endStabilizationSession();
}
if (mGestureEndTarget == HOME) {
HomeAnimationFactory homeAnimFactory;
if (mActivity != null) {
@@ -1003,10 +993,12 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
// Launch the task user scrolled to (mRecentsView.getNextPage()).
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
// We finish recents animation inside launchTask() when live tile is enabled.
mRecentsView.getTaskViewAt(mRecentsView.getNextPage()).launchTask(false);
mRecentsView.getTaskViewAt(mRecentsView.getNextPage()).launchTask(false /* animate */,
true /* freezeTaskList */);
} else {
mRecentsAnimationWrapper.finish(true /* toRecents */, () -> {
mRecentsView.getTaskViewAt(mRecentsView.getNextPage()).launchTask(false);
mRecentsView.getTaskViewAt(mRecentsView.getNextPage()).launchTask(
false /* animate */, true /* freezeTaskList */);
});
}
TOUCH_INTERACTION_LOG.addLog("finishRecentsAnimation", false);

View File

@@ -250,7 +250,11 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
}
public void launchTask(boolean animate) {
launchTask(animate, (result) -> {
launchTask(animate, false /* freezeTaskList */);
}
public void launchTask(boolean animate, boolean freezeTaskList) {
launchTask(animate, freezeTaskList, (result) -> {
if (!result) {
notifyTaskLaunchFailed(TAG);
}
@@ -259,25 +263,33 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
public void launchTask(boolean animate, Consumer<Boolean> resultCallback,
Handler resultCallbackHandler) {
launchTask(animate, false /* freezeTaskList */, resultCallback, resultCallbackHandler);
}
public void launchTask(boolean animate, boolean freezeTaskList, Consumer<Boolean> resultCallback,
Handler resultCallbackHandler) {
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
if (isRunningTask()) {
getRecentsView().finishRecentsAnimation(false /* toRecents */,
() -> resultCallbackHandler.post(() -> resultCallback.accept(true)));
} else {
launchTaskInternal(animate, resultCallback, resultCallbackHandler);
launchTaskInternal(animate, freezeTaskList, resultCallback, resultCallbackHandler);
}
} else {
launchTaskInternal(animate, resultCallback, resultCallbackHandler);
launchTaskInternal(animate, freezeTaskList, resultCallback, resultCallbackHandler);
}
}
private void launchTaskInternal(boolean animate, Consumer<Boolean> resultCallback,
Handler resultCallbackHandler) {
private void launchTaskInternal(boolean animate, boolean freezeTaskList,
Consumer<Boolean> resultCallback, Handler resultCallbackHandler) {
if (mTask != null) {
final ActivityOptions opts;
if (animate) {
opts = ((BaseDraggingActivity) fromContext(getContext()))
.getActivityLaunchOptions(this);
if (freezeTaskList) {
ActivityOptionsCompat.setFreezeRecentTasksList(opts);
}
ActivityManagerWrapper.getInstance().startActivityFromRecentsAsync(mTask.key,
opts, resultCallback, resultCallbackHandler);
} else {
@@ -288,6 +300,9 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
resultCallbackHandler.post(() -> resultCallback.accept(true));
}
}, resultCallbackHandler);
if (freezeTaskList) {
ActivityOptionsCompat.setFreezeRecentTasksList(opts);
}
ActivityManagerWrapper.getInstance().startActivityFromRecentsAsync(mTask.key,
opts, (success) -> {
if (resultCallback != null && !success) {

View File

@@ -70,6 +70,11 @@ public class NavBarModeOverlayResourceObserver extends BroadcastReceiver {
NAV_BAR_INTERACTION_MODE_RES_NAME));
}
public static boolean isLegacyModeEnabled(Context context) {
return QuickStepContract.isLegacyMode(getSystemIntegerRes(context,
NAV_BAR_INTERACTION_MODE_RES_NAME));
}
private static int getSystemIntegerRes(Context context, String resName) {
Resources res = context.getResources();
int resId = res.getIdentifier(resName, "integer", "android");
@@ -81,4 +86,4 @@ public class NavBarModeOverlayResourceObserver extends BroadcastReceiver {
return -1;
}
}
}
}

View File

@@ -44,7 +44,6 @@ public class RecentTasksList extends TaskStackChangeListener {
private final KeyguardManagerCompat mKeyguardManager;
private final MainThreadExecutor mMainThreadExecutor;
private final BackgroundExecutor mBgThreadExecutor;
private final TaskListStabilizer mStabilizer = new TaskListStabilizer();
// The list change id, increments as the task list changes in the system
private int mChangeId;
@@ -74,14 +73,6 @@ public class RecentTasksList extends TaskStackChangeListener {
});
}
public void startStabilizationSession() {
mStabilizer.startStabilizationSession();
}
public void endStabilizationSession() {
mStabilizer.endStabilizationSession();
}
/**
* Asynchronously fetches the list of recent tasks, reusing cached list if available.
*
@@ -93,7 +84,7 @@ public class RecentTasksList extends TaskStackChangeListener {
final int requestLoadId = mChangeId;
Runnable resultCallback = callback == null
? () -> { }
: () -> callback.accept(mStabilizer.reorder(mTasks));
: () -> callback.accept(mTasks);
if (mLastLoadedId == mChangeId && (!mLastLoadHadKeysOnly || loadKeysOnly)) {
// The list is up to date, callback with the same list

View File

@@ -90,14 +90,6 @@ public class RecentsModel extends TaskStackChangeListener {
return mThumbnailCache;
}
public void startStabilizationSession() {
mTaskList.startStabilizationSession();
}
public void endStabilizationSession() {
mTaskList.endStabilizationSession();
}
/**
* Fetches the list of recent tasks.
*

View File

@@ -1,145 +0,0 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.quickstep;
import android.app.ActivityManager.RecentTaskInfo;
import android.content.ComponentName;
import android.os.Process;
import android.os.SystemClock;
import com.android.launcher3.util.IntArray;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.Task.TaskKey;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.TaskStackChangeListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Keeps the task list stable during quick switch gestures. So if you swipe right to switch from app
* A to B, you can then swipe right again to get to app C or left to get back to A.
*/
public class TaskListStabilizer {
private static final long TASK_CACHE_TIMEOUT_MS = 5000;
private final TaskStackChangeListener mTaskStackListener = new TaskStackChangeListener() {
@Override
public void onTaskCreated(int taskId, ComponentName componentName) {
endStabilizationSession();
}
@Override
public void onTaskRemoved(int taskId) {
endStabilizationSession();
}
};
// Task ids ordered based on recency, 0th index is the least recent task
private final IntArray mSystemOrder;
private final IntArray mStabilizedOrder;
// Wrapper objects used for sorting tasks
private final ArrayList<TaskWrapper> mTaskWrappers = new ArrayList<>();
private boolean mInStabilizationSession;
private long mSessionStartTime;
public TaskListStabilizer() {
// Initialize the task ids map
List<RecentTaskInfo> rawTasks = ActivityManagerWrapper.getInstance().getRecentTasks(
Integer.MAX_VALUE, Process.myUserHandle().getIdentifier());
mSystemOrder = new IntArray(rawTasks.size());
for (RecentTaskInfo info : rawTasks) {
mSystemOrder.add(new TaskKey(info).id);
}
// We will lazily copy the task id's from mSystemOrder when a stabilization session starts.
mStabilizedOrder = new IntArray(rawTasks.size());
ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
}
public synchronized void startStabilizationSession() {
if (!mInStabilizationSession) {
mStabilizedOrder.clear();
mStabilizedOrder.addAll(mSystemOrder);
}
mInStabilizationSession = true;
mSessionStartTime = SystemClock.uptimeMillis();
}
public synchronized void endStabilizationSession() {
mInStabilizationSession = false;
}
public synchronized ArrayList<Task> reorder(ArrayList<Task> tasks) {
mSystemOrder.clear();
for (Task task : tasks) {
mSystemOrder.add(task.key.id);
}
if ((SystemClock.uptimeMillis() - mSessionStartTime) > TASK_CACHE_TIMEOUT_MS) {
endStabilizationSession();
}
if (!mInStabilizationSession) {
return tasks;
}
// Ensure that we have enough wrappers
int taskCount = tasks.size();
for (int i = taskCount - mTaskWrappers.size(); i > 0; i--) {
mTaskWrappers.add(new TaskWrapper());
}
List<TaskWrapper> listToSort = mTaskWrappers.size() == taskCount
? mTaskWrappers : mTaskWrappers.subList(0, taskCount);
int missingTaskIndex = -taskCount;
for (int i = 0; i < taskCount; i++){
TaskWrapper wrapper = listToSort.get(i);
wrapper.task = tasks.get(i);
wrapper.index = mStabilizedOrder.indexOf(wrapper.task.key.id);
// Ensure that missing tasks are put in the front, in the order they appear in the
// original list
if (wrapper.index < 0) {
wrapper.index = missingTaskIndex;
missingTaskIndex++;
}
}
Collections.sort(listToSort);
ArrayList<Task> result = new ArrayList<>(taskCount);
for (int i = 0; i < taskCount; i++) {
result.add(listToSort.get(i).task);
}
return result;
}
private static class TaskWrapper implements Comparable<TaskWrapper> {
Task task;
int index;
@Override
public int compareTo(TaskWrapper other) {
return Integer.compare(index, other.index);
}
}
}