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
17package com.android.server.am;
18
19import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
20import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
21
22import android.app.ActivityManager.RunningTaskInfo;
23import android.app.WindowConfiguration.ActivityType;
24import android.app.WindowConfiguration.WindowingMode;
25import android.util.SparseArray;
26
27import java.util.ArrayList;
28import java.util.Comparator;
29import java.util.Iterator;
30import java.util.List;
31import java.util.TreeSet;
32
33/**
34 * Class for resolving the set of running tasks in the system.
35 */
36class RunningTasks {
37
38    // Comparator to sort by last active time (descending)
39    private static final Comparator<TaskRecord> LAST_ACTIVE_TIME_COMPARATOR =
40            (o1, o2) -> Long.signum(o2.lastActiveTime - o1.lastActiveTime);
41
42    private final TaskRecord.TaskActivitiesReport mTmpReport =
43            new TaskRecord.TaskActivitiesReport();
44    private final TreeSet<TaskRecord> mTmpSortedSet = new TreeSet<>(LAST_ACTIVE_TIME_COMPARATOR);
45    private final ArrayList<TaskRecord> mTmpStackTasks = new ArrayList<>();
46
47    void getTasks(int maxNum, List<RunningTaskInfo> list, @ActivityType int ignoreActivityType,
48            @WindowingMode int ignoreWindowingMode, SparseArray<ActivityDisplay> activityDisplays,
49            int callingUid, boolean allowed) {
50        // Return early if there are no tasks to fetch
51        if (maxNum <= 0) {
52            return;
53        }
54
55        // Gather all of the tasks across all of the tasks, and add them to the sorted set
56        mTmpSortedSet.clear();
57        mTmpStackTasks.clear();
58        final int numDisplays = activityDisplays.size();
59        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
60            final ActivityDisplay display = activityDisplays.valueAt(displayNdx);
61            for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
62                final ActivityStack stack = display.getChildAt(stackNdx);
63                stack.getRunningTasks(mTmpStackTasks, ignoreActivityType, ignoreWindowingMode,
64                        callingUid, allowed);
65                for (int i = mTmpStackTasks.size() - 1; i >= 0; i--) {
66                    mTmpSortedSet.addAll(mTmpStackTasks);
67                }
68            }
69        }
70
71        // Take the first {@param maxNum} tasks and create running task infos for them
72        final Iterator<TaskRecord> iter = mTmpSortedSet.iterator();
73        while (iter.hasNext()) {
74            if (maxNum == 0) {
75                break;
76            }
77
78            final TaskRecord task = iter.next();
79            list.add(createRunningTaskInfo(task));
80            maxNum--;
81        }
82    }
83
84    /**
85     * Constructs a {@link RunningTaskInfo} from a given {@param task}.
86     */
87    private RunningTaskInfo createRunningTaskInfo(TaskRecord task) {
88        task.getNumRunningActivities(mTmpReport);
89
90        final RunningTaskInfo ci = new RunningTaskInfo();
91        ci.id = task.taskId;
92        ci.stackId = task.getStackId();
93        ci.baseActivity = mTmpReport.base.intent.getComponent();
94        ci.topActivity = mTmpReport.top.intent.getComponent();
95        ci.lastActiveTime = task.lastActiveTime;
96        ci.description = task.lastDescription;
97        ci.numActivities = mTmpReport.numActivities;
98        ci.numRunning = mTmpReport.numRunning;
99        ci.supportsSplitScreenMultiWindow = task.supportsSplitScreenWindowingMode();
100        ci.resizeMode = task.mResizeMode;
101        ci.configuration.setTo(task.getConfiguration());
102        return ci;
103    }
104}
105