• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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