161c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung/*
261c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung * Copyright (C) 2017 The Android Open Source Project
361c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung *
461c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung * Licensed under the Apache License, Version 2.0 (the "License");
561c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung * you may not use this file except in compliance with the License.
661c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung * You may obtain a copy of the License at
761c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung *
861c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung *      http://www.apache.org/licenses/LICENSE-2.0
961c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung *
1061c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung * Unless required by applicable law or agreed to in writing, software
1161c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung * distributed under the License is distributed on an "AS IS" BASIS,
1261c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1361c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung * See the License for the specific language governing permissions and
1461c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung * limitations under the License.
1561c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung */
1661c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung
1761c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chungpackage com.android.server.am;
1861c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung
1961c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chungimport static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
2061c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chungimport static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
2161c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chungimport static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
2261c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chungimport static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
2361c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chungimport static android.view.Display.DEFAULT_DISPLAY;
2461c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung
2561c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chungimport static com.android.server.am.ActivityDisplay.POSITION_BOTTOM;
2661c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung
2761c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chungimport static org.junit.Assert.assertTrue;
2861c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung
2961c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chungimport android.app.ActivityManager.RunningTaskInfo;
3061c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chungimport android.content.ComponentName;
3161c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chungimport android.content.Context;
3261c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chungimport android.platform.test.annotations.Presubmit;
3361c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chungimport android.support.test.InstrumentationRegistry;
3461c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chungimport android.support.test.filters.MediumTest;
3561c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chungimport android.support.test.runner.AndroidJUnit4;
3661c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chungimport android.util.SparseArray;
3761c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung
3861c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chungimport org.junit.Before;
3961c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chungimport org.junit.Test;
4061c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chungimport org.junit.runner.RunWith;
4161c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung
4261c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chungimport java.util.ArrayList;
4361c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung
4461c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung/**
4561c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung * runtest --path frameworks/base/services/tests/servicestests/src/com/android/server/am/RunningTasksTest.java
4661c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung */
4761c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung@MediumTest
4861c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung@Presubmit
4961c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung@RunWith(AndroidJUnit4.class)
5061c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chungpublic class RunningTasksTest extends ActivityTestsBase {
5161c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung
5261c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung    private Context mContext = InstrumentationRegistry.getContext();
5361c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung    private ActivityManagerService mService;
5461c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung
5561c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung    private RunningTasks mRunningTasks;
5661c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung
5761c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung    @Before
5861c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung    @Override
5961c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung    public void setUp() throws Exception {
6061c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung        super.setUp();
6161c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung
6261c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung        mService = createActivityManagerService();
6361c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung        mRunningTasks = new RunningTasks();
6461c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung    }
6561c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung
6661c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung    @Test
6761c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung    public void testCollectTasksByLastActiveTime() throws Exception {
6861c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung        // Create a number of stacks with tasks (of incrementing active time)
6961c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung        final ActivityStackSupervisor supervisor = mService.mStackSupervisor;
7061c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung        final SparseArray<ActivityDisplay> displays = new SparseArray<>();
71343f65a43039036896a1d550c49f2f71fea5047cWinson Chung        final ActivityDisplay display = new TestActivityDisplay(supervisor, DEFAULT_DISPLAY);
7261c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung        displays.put(DEFAULT_DISPLAY, display);
7361c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung
7461c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung        final int numStacks = 2;
7561c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung        for (int stackIndex = 0; stackIndex < numStacks; stackIndex++) {
7661c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung            final ActivityStack stack = new TestActivityStack(display, stackIndex, supervisor,
7761c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung                    WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true);
7861c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung            display.addChild(stack, POSITION_BOTTOM);
7961c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung        }
8061c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung
8161c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung        final int numTasks = 10;
8261c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung        int activeTime = 0;
8361c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung        for (int i = 0; i < numTasks; i++) {
8461c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung            createTask(display.getChildAt(i % numStacks), ".Task" + i, i, activeTime++);
8561c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung        }
8661c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung
8761c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung        // Ensure that the latest tasks were returned in order of decreasing last active time,
8861c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung        // collected from all tasks across all the stacks
8961c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung        final int numFetchTasks = 5;
9061c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung        ArrayList<RunningTaskInfo> tasks = new ArrayList<>();
9161c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung        mRunningTasks.getTasks(5, tasks, ACTIVITY_TYPE_UNDEFINED, WINDOWING_MODE_UNDEFINED,
9261c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung                displays, -1 /* callingUid */, true /* allowed */);
9361c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung        assertTrue(tasks.size() == numFetchTasks);
9461c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung        for (int i = 0; i < numFetchTasks; i++) {
9561c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung            assertTrue(tasks.get(i).id == (numTasks - i - 1));
9661c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung        }
9761c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung
9861c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung        // Ensure that requesting more than the total number of tasks only returns the subset
9961c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung        // and does not crash
10061c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung        tasks.clear();
10161c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung        mRunningTasks.getTasks(100, tasks, ACTIVITY_TYPE_UNDEFINED, WINDOWING_MODE_UNDEFINED,
10261c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung                displays, -1 /* callingUid */, true /* allowed */);
10361c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung        assertTrue(tasks.size() == numTasks);
10461c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung        for (int i = 0; i < numTasks; i++) {
10561c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung            assertTrue(tasks.get(i).id == (numTasks - i - 1));
10661c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung        }
10761c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung    }
10861c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung
10961c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung    /**
11061c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung     * Create a task with a single activity in it, with the given last active time.
11161c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung     */
11261c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung    private TaskRecord createTask(ActivityStack stack, String className, int taskId,
11361c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung            int lastActiveTime) {
11461c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung        final TaskRecord task = new TaskBuilder(mService.mStackSupervisor)
11561c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung                .setComponent(new ComponentName(mContext.getPackageName(), className))
11661c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung                .setTaskId(taskId)
11761c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung                .setStack(stack)
11861c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung                .build();
11961c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung        task.lastActiveTime = lastActiveTime;
12061c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung        final ActivityRecord activity = new ActivityBuilder(mService)
12161c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung                .setTask(task)
12261c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung                .setComponent(new ComponentName(mContext.getPackageName(), ".TaskActivity"))
12361c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung                .build();
12461c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung        return task;
12561c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung    }
12661c9e5a62933a9fe933ce5e6a4343cd0fbd8a532Winson Chung}