1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17 package com.android.server.wm; 18 19 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; 20 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; 21 22 import android.app.ActivityManager.RunningTaskInfo; 23 import android.os.UserHandle; 24 import android.util.ArraySet; 25 26 import com.android.internal.util.function.pooled.PooledConsumer; 27 import com.android.internal.util.function.pooled.PooledLambda; 28 29 import java.util.Comparator; 30 import java.util.Iterator; 31 import java.util.List; 32 import java.util.TreeSet; 33 34 /** 35 * Class for resolving the set of running tasks in the system. 36 */ 37 class RunningTasks { 38 39 // Comparator to sort by last active time (descending) 40 private static final Comparator<Task> LAST_ACTIVE_TIME_COMPARATOR = 41 (o1, o2) -> Long.signum(o2.lastActiveTime - o1.lastActiveTime); 42 43 private final TreeSet<Task> mTmpSortedSet = new TreeSet<>(LAST_ACTIVE_TIME_COMPARATOR); 44 45 private int mCallingUid; 46 private int mUserId; 47 private boolean mCrossUser; 48 private ArraySet<Integer> mProfileIds; 49 private boolean mAllowed; 50 private boolean mFilterOnlyVisibleRecents; 51 private ActivityStack mTopDisplayFocusStack; 52 private RecentTasks mRecentTasks; 53 getTasks(int maxNum, List<RunningTaskInfo> list, boolean filterOnlyVisibleRecents, RootWindowContainer root, int callingUid, boolean allowed, boolean crossUser, ArraySet<Integer> profileIds)54 void getTasks(int maxNum, List<RunningTaskInfo> list, boolean filterOnlyVisibleRecents, 55 RootWindowContainer root, int callingUid, boolean allowed, boolean crossUser, 56 ArraySet<Integer> profileIds) { 57 // Return early if there are no tasks to fetch 58 if (maxNum <= 0) { 59 return; 60 } 61 62 // Gather all of the tasks across all of the tasks, and add them to the sorted set 63 mTmpSortedSet.clear(); 64 mCallingUid = callingUid; 65 mUserId = UserHandle.getUserId(callingUid); 66 mCrossUser = crossUser; 67 mProfileIds = profileIds; 68 mAllowed = allowed; 69 mFilterOnlyVisibleRecents = filterOnlyVisibleRecents; 70 mTopDisplayFocusStack = root.getTopDisplayFocusedStack(); 71 mRecentTasks = root.mService.getRecentTasks(); 72 73 final PooledConsumer c = PooledLambda.obtainConsumer(RunningTasks::processTask, this, 74 PooledLambda.__(Task.class)); 75 root.forAllLeafTasks(c, false); 76 c.recycle(); 77 78 // Take the first {@param maxNum} tasks and create running task infos for them 79 final Iterator<Task> iter = mTmpSortedSet.iterator(); 80 while (iter.hasNext()) { 81 if (maxNum == 0) { 82 break; 83 } 84 85 final Task task = iter.next(); 86 list.add(createRunningTaskInfo(task)); 87 maxNum--; 88 } 89 } 90 processTask(Task task)91 private void processTask(Task task) { 92 if (task.getTopNonFinishingActivity() == null) { 93 // Skip if there are no activities in the task 94 return; 95 } 96 if (task.effectiveUid != mCallingUid) { 97 if (task.mUserId != mUserId && !mCrossUser && !mProfileIds.contains(task.mUserId)) { 98 // Skip if the caller does not have cross user permission or cannot access 99 // the task's profile 100 return; 101 } 102 if (!mAllowed && !task.isActivityTypeHome()) { 103 // Skip if the caller isn't allowed to fetch this task, except for the home 104 // task which we always return. 105 return; 106 } 107 } 108 if (mFilterOnlyVisibleRecents 109 && task.getActivityType() != ACTIVITY_TYPE_HOME 110 && task.getActivityType() != ACTIVITY_TYPE_RECENTS 111 && !mRecentTasks.isVisibleRecentTask(task)) { 112 // Skip if this task wouldn't be visibile (ever) from recents, with an exception for the 113 // home & recent tasks 114 return; 115 } 116 117 final ActivityStack stack = task.getStack(); 118 if (stack == mTopDisplayFocusStack && stack.getTopMostTask() == task) { 119 // For the focused stack top task, update the last stack active time so that it can be 120 // used to determine the order of the tasks (it may not be set for newly created tasks) 121 task.touchActiveTime(); 122 } 123 124 mTmpSortedSet.add(task); 125 } 126 127 /** Constructs a {@link RunningTaskInfo} from a given {@param task}. */ createRunningTaskInfo(Task task)128 private RunningTaskInfo createRunningTaskInfo(Task task) { 129 final RunningTaskInfo rti = task.getTaskInfo(); 130 // Fill in some deprecated values 131 rti.id = rti.taskId; 132 return rti; 133 } 134 } 135