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 static final int FLAG_FILTER_ONLY_VISIBLE_RECENTS = 1; 40 static final int FLAG_ALLOWED = 1 << 1; 41 static final int FLAG_CROSS_USERS = 1 << 2; 42 static final int FLAG_KEEP_INTENT_EXTRA = 1 << 3; 43 44 // Comparator to sort by last active time (descending) 45 private static final Comparator<Task> LAST_ACTIVE_TIME_COMPARATOR = 46 (o1, o2) -> Long.signum(o2.lastActiveTime - o1.lastActiveTime); 47 48 private final TreeSet<Task> mTmpSortedSet = new TreeSet<>(LAST_ACTIVE_TIME_COMPARATOR); 49 50 private int mCallingUid; 51 private int mUserId; 52 private boolean mCrossUser; 53 private ArraySet<Integer> mProfileIds; 54 private boolean mAllowed; 55 private boolean mFilterOnlyVisibleRecents; 56 private Task mTopDisplayFocusRootTask; 57 private RecentTasks mRecentTasks; 58 private boolean mKeepIntentExtra; 59 getTasks(int maxNum, List<RunningTaskInfo> list, int flags, RootWindowContainer root, int callingUid, ArraySet<Integer> profileIds)60 void getTasks(int maxNum, List<RunningTaskInfo> list, int flags, 61 RootWindowContainer root, int callingUid, ArraySet<Integer> profileIds) { 62 // Return early if there are no tasks to fetch 63 if (maxNum <= 0) { 64 return; 65 } 66 67 // Gather all of the tasks across all of the tasks, and add them to the sorted set 68 mTmpSortedSet.clear(); 69 mCallingUid = callingUid; 70 mUserId = UserHandle.getUserId(callingUid); 71 mCrossUser = (flags & FLAG_CROSS_USERS) == FLAG_CROSS_USERS; 72 mProfileIds = profileIds; 73 mAllowed = (flags & FLAG_ALLOWED) == FLAG_ALLOWED; 74 mFilterOnlyVisibleRecents = 75 (flags & FLAG_FILTER_ONLY_VISIBLE_RECENTS) == FLAG_FILTER_ONLY_VISIBLE_RECENTS; 76 mTopDisplayFocusRootTask = root.getTopDisplayFocusedRootTask(); 77 mRecentTasks = root.mService.getRecentTasks(); 78 mKeepIntentExtra = (flags & FLAG_KEEP_INTENT_EXTRA) == FLAG_KEEP_INTENT_EXTRA; 79 80 final PooledConsumer c = PooledLambda.obtainConsumer(RunningTasks::processTask, this, 81 PooledLambda.__(Task.class)); 82 root.forAllLeafTasks(c, false); 83 c.recycle(); 84 85 // Take the first {@param maxNum} tasks and create running task infos for them 86 final Iterator<Task> iter = mTmpSortedSet.iterator(); 87 while (iter.hasNext()) { 88 if (maxNum == 0) { 89 break; 90 } 91 92 final Task task = iter.next(); 93 list.add(createRunningTaskInfo(task)); 94 maxNum--; 95 } 96 } 97 processTask(Task task)98 private void processTask(Task task) { 99 if (task.getTopNonFinishingActivity() == null) { 100 // Skip if there are no activities in the task 101 return; 102 } 103 if (task.effectiveUid != mCallingUid) { 104 if (task.mUserId != mUserId && !mCrossUser && !mProfileIds.contains(task.mUserId)) { 105 // Skip if the caller does not have cross user permission or cannot access 106 // the task's profile 107 return; 108 } 109 if (!mAllowed) { 110 // Skip if the caller isn't allowed to fetch this task 111 return; 112 } 113 } 114 if (mFilterOnlyVisibleRecents 115 && task.getActivityType() != ACTIVITY_TYPE_HOME 116 && task.getActivityType() != ACTIVITY_TYPE_RECENTS 117 && !mRecentTasks.isVisibleRecentTask(task)) { 118 // Skip if this task wouldn't be visibile (ever) from recents, with an exception for the 119 // home & recent tasks 120 return; 121 } 122 123 final Task rootTask = task.getRootTask(); 124 if (rootTask == mTopDisplayFocusRootTask && rootTask.getTopMostTask() == task) { 125 // For the focused top root task, update the last root task active time so that it 126 // can be used to determine the order of the tasks (it may not be set for newly 127 // created tasks) 128 task.touchActiveTime(); 129 } 130 131 mTmpSortedSet.add(task); 132 } 133 134 /** Constructs a {@link RunningTaskInfo} from a given {@param task}. */ createRunningTaskInfo(Task task)135 private RunningTaskInfo createRunningTaskInfo(Task task) { 136 final RunningTaskInfo rti = new RunningTaskInfo(); 137 task.fillTaskInfo(rti, !mKeepIntentExtra); 138 // Fill in some deprecated values 139 rti.id = rti.taskId; 140 return rti; 141 } 142 } 143