blob: 3509ba72d058d27ac927ea2f2647bd906de02c10 [file] [log] [blame]
/*
* Copyright (C) 2017 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.server.wm;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import android.app.ActivityManager.RunningTaskInfo;
import android.os.UserHandle;
import android.util.ArraySet;
import com.android.internal.util.function.pooled.PooledConsumer;
import com.android.internal.util.function.pooled.PooledLambda;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.TreeSet;
/**
* Class for resolving the set of running tasks in the system.
*/
class RunningTasks {
// Comparator to sort by last active time (descending)
private static final Comparator<Task> LAST_ACTIVE_TIME_COMPARATOR =
(o1, o2) -> Long.signum(o2.lastActiveTime - o1.lastActiveTime);
private final TreeSet<Task> mTmpSortedSet = new TreeSet<>(LAST_ACTIVE_TIME_COMPARATOR);
private int mCallingUid;
private int mUserId;
private boolean mCrossUser;
private ArraySet<Integer> mProfileIds;
private boolean mAllowed;
private boolean mFilterOnlyVisibleRecents;
private ActivityStack mTopDisplayFocusStack;
private RecentTasks mRecentTasks;
void getTasks(int maxNum, List<RunningTaskInfo> list, boolean filterOnlyVisibleRecents,
RootWindowContainer root, int callingUid, boolean allowed, boolean crossUser,
ArraySet<Integer> profileIds) {
// Return early if there are no tasks to fetch
if (maxNum <= 0) {
return;
}
// Gather all of the tasks across all of the tasks, and add them to the sorted set
mTmpSortedSet.clear();
mCallingUid = callingUid;
mUserId = UserHandle.getUserId(callingUid);
mCrossUser = crossUser;
mProfileIds = profileIds;
mAllowed = allowed;
mFilterOnlyVisibleRecents = filterOnlyVisibleRecents;
mTopDisplayFocusStack = root.getTopDisplayFocusedStack();
mRecentTasks = root.mService.getRecentTasks();
final PooledConsumer c = PooledLambda.obtainConsumer(RunningTasks::processTask, this,
PooledLambda.__(Task.class));
root.forAllLeafTasks(c, false);
c.recycle();
// Take the first {@param maxNum} tasks and create running task infos for them
final Iterator<Task> iter = mTmpSortedSet.iterator();
while (iter.hasNext()) {
if (maxNum == 0) {
break;
}
final Task task = iter.next();
list.add(createRunningTaskInfo(task));
maxNum--;
}
}
private void processTask(Task task) {
if (task.getTopNonFinishingActivity() == null) {
// Skip if there are no activities in the task
return;
}
if (task.effectiveUid != mCallingUid) {
if (task.mUserId != mUserId && !mCrossUser && !mProfileIds.contains(task.mUserId)) {
// Skip if the caller does not have cross user permission or cannot access
// the task's profile
return;
}
if (!mAllowed && !task.isActivityTypeHome()) {
// Skip if the caller isn't allowed to fetch this task, except for the home
// task which we always return.
return;
}
}
if (mFilterOnlyVisibleRecents
&& task.getActivityType() != ACTIVITY_TYPE_HOME
&& task.getActivityType() != ACTIVITY_TYPE_RECENTS
&& !mRecentTasks.isVisibleRecentTask(task)) {
// Skip if this task wouldn't be visibile (ever) from recents, with an exception for the
// home & recent tasks
return;
}
final ActivityStack stack = task.getStack();
if (stack == mTopDisplayFocusStack && stack.getTopMostTask() == task) {
// For the focused stack top task, update the last stack active time so that it can be
// used to determine the order of the tasks (it may not be set for newly created tasks)
task.touchActiveTime();
}
mTmpSortedSet.add(task);
}
/** Constructs a {@link RunningTaskInfo} from a given {@param task}. */
private RunningTaskInfo createRunningTaskInfo(Task task) {
final RunningTaskInfo rti = task.getTaskInfo();
// Fill in some deprecated values
rti.id = rti.taskId;
return rti;
}
}