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.SystemClock; 24 import android.os.UserHandle; 25 import android.util.ArraySet; 26 27 import java.util.ArrayList; 28 import java.util.List; 29 import java.util.function.Consumer; 30 31 /** 32 * Class for resolving the set of running tasks in the system. 33 */ 34 class RunningTasks implements Consumer<Task> { 35 36 static final int FLAG_FILTER_ONLY_VISIBLE_RECENTS = 1; 37 static final int FLAG_ALLOWED = 1 << 1; 38 static final int FLAG_CROSS_USERS = 1 << 2; 39 static final int FLAG_KEEP_INTENT_EXTRA = 1 << 3; 40 41 // Tasks are sorted in order {focusedVisibleTasks, visibleTasks, invisibleTasks}. 42 private final ArrayList<Task> mTmpSortedTasks = new ArrayList<>(); 43 // mTmpVisibleTasks, mTmpInvisibleTasks and mTmpFocusedTasks are sorted from top 44 // to bottom. 45 private final ArrayList<Task> mTmpVisibleTasks = new ArrayList<>(); 46 private final ArrayList<Task> mTmpInvisibleTasks = new ArrayList<>(); 47 private final ArrayList<Task> mTmpFocusedTasks = new ArrayList<>(); 48 49 private int mCallingUid; 50 private int mUserId; 51 private boolean mCrossUser; 52 private ArraySet<Integer> mProfileIds; 53 private boolean mAllowed; 54 private boolean mFilterOnlyVisibleRecents; 55 private RecentTasks mRecentTasks; 56 private boolean mKeepIntentExtra; 57 getTasks(int maxNum, List<RunningTaskInfo> list, int flags, RecentTasks recentTasks, WindowContainer<?> root, int callingUid, ArraySet<Integer> profileIds)58 void getTasks(int maxNum, List<RunningTaskInfo> list, int flags, RecentTasks recentTasks, 59 WindowContainer<?> root, int callingUid, ArraySet<Integer> profileIds) { 60 // Return early if there are no tasks to fetch 61 if (maxNum <= 0) { 62 return; 63 } 64 65 mCallingUid = callingUid; 66 mUserId = UserHandle.getUserId(callingUid); 67 mCrossUser = (flags & FLAG_CROSS_USERS) == FLAG_CROSS_USERS; 68 mProfileIds = profileIds; 69 mAllowed = (flags & FLAG_ALLOWED) == FLAG_ALLOWED; 70 mFilterOnlyVisibleRecents = 71 (flags & FLAG_FILTER_ONLY_VISIBLE_RECENTS) == FLAG_FILTER_ONLY_VISIBLE_RECENTS; 72 mRecentTasks = recentTasks; 73 mKeepIntentExtra = (flags & FLAG_KEEP_INTENT_EXTRA) == FLAG_KEEP_INTENT_EXTRA; 74 75 if (root instanceof RootWindowContainer) { 76 ((RootWindowContainer) root).forAllDisplays(dc -> { 77 final Task focusedTask = dc.mFocusedApp != null ? dc.mFocusedApp.getTask() : null; 78 if (focusedTask != null) { 79 mTmpFocusedTasks.add(focusedTask); 80 } 81 processTaskInWindowContainer(dc); 82 }); 83 } else { 84 final DisplayContent dc = root.getDisplayContent(); 85 final Task focusedTask = dc != null 86 ? (dc.mFocusedApp != null ? dc.mFocusedApp.getTask() : null) 87 : null; 88 // May not be include focusedTask if root is DisplayArea. 89 final boolean rootContainsFocusedTask = focusedTask != null 90 && focusedTask.isDescendantOf(root); 91 if (rootContainsFocusedTask) { 92 mTmpFocusedTasks.add(focusedTask); 93 } 94 processTaskInWindowContainer(root); 95 } 96 97 final int visibleTaskCount = mTmpVisibleTasks.size(); 98 for (int i = 0; i < mTmpFocusedTasks.size(); i++) { 99 final Task focusedTask = mTmpFocusedTasks.get(i); 100 final boolean containsFocusedTask = mTmpVisibleTasks.remove(focusedTask); 101 if (containsFocusedTask) { 102 // Put the visible focused task at the first position. 103 mTmpSortedTasks.add(focusedTask); 104 } 105 } 106 if (!mTmpVisibleTasks.isEmpty()) { 107 mTmpSortedTasks.addAll(mTmpVisibleTasks); 108 } 109 if (!mTmpInvisibleTasks.isEmpty()) { 110 mTmpSortedTasks.addAll(mTmpInvisibleTasks); 111 } 112 113 // Take the first {@param maxNum} tasks and create running task infos for them 114 final int size = Math.min(maxNum, mTmpSortedTasks.size()); 115 final long now = SystemClock.elapsedRealtime(); 116 for (int i = 0; i < size; i++) { 117 final Task task = mTmpSortedTasks.get(i); 118 // Override the last active to current time for the visible tasks because the visible 119 // tasks can be considered to be currently active, the values are descending as 120 // the item order. 121 final long visibleActiveTime = i < visibleTaskCount ? now + size - i : -1; 122 list.add(createRunningTaskInfo(task, visibleActiveTime)); 123 } 124 125 mTmpFocusedTasks.clear(); 126 mTmpVisibleTasks.clear(); 127 mTmpInvisibleTasks.clear(); 128 mTmpSortedTasks.clear(); 129 } 130 131 private void processTaskInWindowContainer(WindowContainer wc) { 132 wc.forAllLeafTasks(this, true /* traverseTopToBottom */); 133 } 134 135 @Override 136 public void accept(Task task) { 137 if (task.getTopNonFinishingActivity() == null) { 138 // Skip if there are no activities in the task 139 return; 140 } 141 if (task.effectiveUid != mCallingUid) { 142 if (task.mUserId != mUserId && !mCrossUser && !mProfileIds.contains(task.mUserId)) { 143 // Skip if the caller does not have cross user permission or cannot access 144 // the task's profile 145 return; 146 } 147 if (!mAllowed) { 148 // Skip if the caller isn't allowed to fetch this task 149 return; 150 } 151 } 152 if (mFilterOnlyVisibleRecents 153 && task.getActivityType() != ACTIVITY_TYPE_HOME 154 && task.getActivityType() != ACTIVITY_TYPE_RECENTS 155 && !mRecentTasks.isVisibleRecentTask(task)) { 156 // Skip if this task wouldn't be visibile (ever) from recents, with an exception for the 157 // home & recent tasks 158 return; 159 } 160 if (task.isVisibleRequested()) { 161 mTmpVisibleTasks.add(task); 162 } else { 163 mTmpInvisibleTasks.add(task); 164 } 165 } 166 167 /** Constructs a {@link RunningTaskInfo} from a given {@param task}. */ 168 private RunningTaskInfo createRunningTaskInfo(Task task, long visibleActiveTime) { 169 final RunningTaskInfo rti = new RunningTaskInfo(); 170 task.fillTaskInfo(rti, !mKeepIntentExtra); 171 if (visibleActiveTime > 0) { 172 rti.lastActiveTime = visibleActiveTime; 173 } 174 // Fill in some deprecated values 175 rti.id = rti.taskId; 176 177 if (!mAllowed) { 178 Task.trimIneffectiveInfo(task, rti); 179 } 180 return rti; 181 } 182 } 183