a5354e02a2
Bug: 111926330 Test: Swipe to last task, ensure it resets task list on timeout or interaction Change-Id: Id09215a4cfdea63a4be6fb69fced163ad3bc10bd
176 lines
6.6 KiB
Java
176 lines
6.6 KiB
Java
/*
|
|
* Copyright (C) 2014 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.annotation.TargetApi;
|
|
import android.app.ActivityManager;
|
|
import android.content.Context;
|
|
import android.os.Build;
|
|
import android.os.Process;
|
|
import android.util.SparseBooleanArray;
|
|
import com.android.launcher3.MainThreadExecutor;
|
|
import com.android.systemui.shared.recents.model.Task;
|
|
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
|
import com.android.systemui.shared.system.BackgroundExecutor;
|
|
import com.android.systemui.shared.system.KeyguardManagerCompat;
|
|
import com.android.systemui.shared.system.RecentTaskInfoCompat;
|
|
import com.android.systemui.shared.system.TaskDescriptionCompat;
|
|
import com.android.systemui.shared.system.TaskStackChangeListener;
|
|
import java.util.ArrayList;
|
|
import java.util.Collections;
|
|
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.P)
|
|
public class RecentTasksList extends TaskStackChangeListener {
|
|
|
|
private final KeyguardManagerCompat mKeyguardManager;
|
|
private final MainThreadExecutor mMainThreadExecutor;
|
|
private final BackgroundExecutor mBgThreadExecutor;
|
|
|
|
// The list change id, increments as the task list changes in the system
|
|
private int mChangeId;
|
|
// The last change id when the list was last loaded completely, must be <= the list change id
|
|
private int mLastLoadedId;
|
|
// The last change id was loaded with keysOnly = true
|
|
private boolean mLastLoadHadKeysOnly;
|
|
|
|
ArrayList<Task> mTasks = new ArrayList<>();
|
|
|
|
public RecentTasksList(Context context) {
|
|
mMainThreadExecutor = new MainThreadExecutor();
|
|
mBgThreadExecutor = BackgroundExecutor.get();
|
|
mKeyguardManager = new KeyguardManagerCompat(context);
|
|
mChangeId = 1;
|
|
ActivityManagerWrapper.getInstance().registerTaskStackListener(this);
|
|
}
|
|
|
|
/**
|
|
* Fetches the task keys skipping any local cache.
|
|
*/
|
|
public void getTaskKeys(int numTasks, Consumer<ArrayList<Task>> callback) {
|
|
// Kick off task loading in the background
|
|
mBgThreadExecutor.submit(() -> {
|
|
ArrayList<Task> tasks = loadTasksInBackground(numTasks, true /* loadKeysOnly */);
|
|
mMainThreadExecutor.execute(() -> callback.accept(tasks));
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Asynchronously fetches the list of recent tasks, reusing cached list if available.
|
|
*
|
|
* @param loadKeysOnly Whether to load other associated task data, or just the key
|
|
* @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) {
|
|
final int requestLoadId = mChangeId;
|
|
Runnable resultCallback = callback == null
|
|
? () -> { }
|
|
: () -> callback.accept(mTasks);
|
|
|
|
if (mLastLoadedId == mChangeId && (!mLastLoadHadKeysOnly || loadKeysOnly)) {
|
|
// The list is up to date, callback with the same list
|
|
mMainThreadExecutor.execute(resultCallback);
|
|
return requestLoadId;
|
|
}
|
|
|
|
// Kick off task loading in the background
|
|
mBgThreadExecutor.submit(() -> {
|
|
ArrayList<Task> tasks = loadTasksInBackground(Integer.MAX_VALUE, loadKeysOnly);
|
|
|
|
mMainThreadExecutor.execute(() -> {
|
|
mTasks = tasks;
|
|
mLastLoadedId = requestLoadId;
|
|
mLastLoadHadKeysOnly = loadKeysOnly;
|
|
resultCallback.run();
|
|
});
|
|
});
|
|
|
|
return requestLoadId;
|
|
}
|
|
|
|
/**
|
|
* @return Whether the provided {@param changeId} is the latest recent tasks list id.
|
|
*/
|
|
public synchronized boolean isTaskListValid(int changeId) {
|
|
return mChangeId == changeId;
|
|
}
|
|
|
|
@Override
|
|
public synchronized void onTaskStackChanged() {
|
|
mChangeId++;
|
|
}
|
|
|
|
@Override
|
|
public synchronized void onActivityPinned(String packageName, int userId, int taskId,
|
|
int stackId) {
|
|
mChangeId++;
|
|
}
|
|
|
|
@Override
|
|
public synchronized void onActivityUnpinned() {
|
|
mChangeId++;
|
|
}
|
|
|
|
/**
|
|
* Loads and creates a list of all the recent tasks.
|
|
*/
|
|
private ArrayList<Task> loadTasksInBackground(int numTasks,
|
|
boolean loadKeysOnly) {
|
|
int currentUserId = Process.myUserHandle().getIdentifier();
|
|
ArrayList<Task> allTasks = new ArrayList<>();
|
|
List<ActivityManager.RecentTaskInfo> rawTasks =
|
|
ActivityManagerWrapper.getInstance().getRecentTasks(numTasks, currentUserId);
|
|
// The raw tasks are given in most-recent to least-recent order, we need to reverse it
|
|
Collections.reverse(rawTasks);
|
|
|
|
SparseBooleanArray tmpLockedUsers = new SparseBooleanArray() {
|
|
@Override
|
|
public boolean get(int key) {
|
|
if (indexOfKey(key) < 0) {
|
|
// Fill the cached locked state as we fetch
|
|
put(key, mKeyguardManager.isDeviceLocked(key));
|
|
}
|
|
return super.get(key);
|
|
}
|
|
};
|
|
|
|
int taskCount = rawTasks.size();
|
|
for (int i = 0; i < taskCount; i++) {
|
|
ActivityManager.RecentTaskInfo rawTask = rawTasks.get(i);
|
|
RecentTaskInfoCompat t = new RecentTaskInfoCompat(rawTask);
|
|
Task.TaskKey taskKey = new Task.TaskKey(rawTask);
|
|
Task task;
|
|
if (!loadKeysOnly) {
|
|
ActivityManager.TaskDescription rawTd = t.getTaskDescription();
|
|
TaskDescriptionCompat td = new TaskDescriptionCompat(rawTd);
|
|
boolean isLocked = tmpLockedUsers.get(t.getUserId());
|
|
task = new Task(taskKey, td.getPrimaryColor(), td.getBackgroundColor(),
|
|
t.supportsSplitScreenMultiWindow(), isLocked, rawTd, t.getTopActivity());
|
|
} else {
|
|
task = new Task(taskKey);
|
|
}
|
|
allTasks.add(task);
|
|
}
|
|
|
|
return allTasks;
|
|
}
|
|
} |