/* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package com.android.server.wm; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.server.wm.RunningTasks.FLAG_ALLOWED; import static com.android.server.wm.RunningTasks.FLAG_CROSS_USERS; import static com.android.server.wm.RunningTasks.FLAG_KEEP_INTENT_EXTRA; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import android.app.ActivityManager.RunningTaskInfo; import android.content.ComponentName; import android.os.Bundle; import android.platform.test.annotations.Presubmit; import android.util.ArraySet; import androidx.test.filters.MediumTest; import com.google.common.truth.Correspondence; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import java.util.ArrayList; /** * Build/Install/Run: * atest WmTests:RunningTasksTest */ @MediumTest @Presubmit @RunWith(WindowTestRunner.class) public class RunningTasksTest extends WindowTestsBase { private static final ArraySet PROFILE_IDS = new ArraySet<>(); private static final Correspondence TASKINFO_HAS_ID = Correspondence.transforming((RunningTaskInfo t) -> t.taskId, "has id"); private RunningTasks mRunningTasks; @Before public void setUp() throws Exception { mRunningTasks = new RunningTasks(); } @Test public void testTaskInfo_expectNoExtrasByDefault() { final DisplayContent display = new TestDisplayContent.Builder(mAtm, 1000, 2500).build(); final int numTasks = 10; for (int i = 0; i < numTasks; i++) { final Task stack = new TaskBuilder(mSupervisor) .setDisplay(display) .setOnTop(true) .build(); final Bundle data = new Bundle(); data.putInt("key", 100); createTask(stack, ".Task" + i, i, data); } final int numFetchTasks = 5; final ArrayList tasks = new ArrayList<>(); mRunningTasks.getTasks(numFetchTasks, tasks, FLAG_ALLOWED | FLAG_CROSS_USERS, mAtm.getRecentTasks(), mRootWindowContainer, -1 /* callingUid */, PROFILE_IDS); assertThat(tasks).hasSize(numFetchTasks); for (int i = 0; i < tasks.size(); i++) { final Bundle extras = tasks.get(i).baseIntent.getExtras(); assertTrue(extras == null || extras.isEmpty()); } } @Test public void testTaskInfo_expectExtrasWithKeepExtraFlag() { final DisplayContent display = new TestDisplayContent.Builder(mAtm, 1000, 2500).build(); final int numTasks = 10; for (int i = 0; i < numTasks; i++) { final Task stack = new TaskBuilder(mSupervisor) .setDisplay(display) .setOnTop(true) .build(); final Bundle data = new Bundle(); data.putInt("key", 100); createTask(stack, ".Task" + i, i, data); } final int numFetchTasks = 5; final ArrayList tasks = new ArrayList<>(); mRunningTasks.getTasks(numFetchTasks, tasks, FLAG_ALLOWED | FLAG_CROSS_USERS | FLAG_KEEP_INTENT_EXTRA, mAtm.getRecentTasks(), mRootWindowContainer, -1 /* callingUid */, PROFILE_IDS); assertThat(tasks).hasSize(numFetchTasks); for (int i = 0; i < tasks.size(); i++) { final Bundle extras = tasks.get(i).baseIntent.getExtras(); assertNotNull(extras); assertEquals(100, extras.getInt("key")); } } @Test public void testGetTasksSortByFocusAndVisibility() { final DisplayContent display = new TestDisplayContent.Builder(mAtm, 1000, 2500).build(); final Task stack = new TaskBuilder(mSupervisor) .setDisplay(display) .setOnTop(true) .build(); final int numTasks = 10; final ArrayList tasks = new ArrayList<>(); for (int i = 0; i < numTasks; i++) { final Task task = createTask(stack, ".Task" + i, i, null); doReturn(false).when(task).isVisible(); tasks.add(task); } final Task focusedTask = tasks.get(numTasks - 1); doReturn(true).when(focusedTask).isVisible(); display.mFocusedApp = focusedTask.getTopNonFinishingActivity(); final Task visibleTaskTop = tasks.get(numTasks - 2); doReturn(true).when(visibleTaskTop).isVisible(); final Task visibleTaskBottom = tasks.get(numTasks - 3); doReturn(true).when(visibleTaskBottom).isVisible(); // Ensure that the focused Task is on top, visible tasks below, then invisible tasks. final int numFetchTasks = 5; final ArrayList fetchTasks = new ArrayList<>(); mRunningTasks.getTasks(numFetchTasks, fetchTasks, FLAG_ALLOWED | FLAG_CROSS_USERS | FLAG_KEEP_INTENT_EXTRA, mAtm.getRecentTasks(), mRootWindowContainer, -1 /* callingUid */, PROFILE_IDS); assertThat(fetchTasks).hasSize(numFetchTasks); for (int i = 0; i < numFetchTasks; i++) { assertEquals(numTasks - i - 1, fetchTasks.get(i).id); } // Ensure that requesting more than the total number of tasks only returns the subset // and does not crash fetchTasks.clear(); mRunningTasks.getTasks(100, fetchTasks, FLAG_ALLOWED | FLAG_CROSS_USERS | FLAG_KEEP_INTENT_EXTRA, mAtm.getRecentTasks(), mRootWindowContainer, -1 /* callingUid */, PROFILE_IDS); assertThat(fetchTasks).hasSize(numTasks); for (int i = 0; i < numTasks; i++) { assertEquals(numTasks - i - 1, fetchTasks.get(i).id); } } /** * Create a task with a single activity in it. */ private Task createTask(Task stack, String className, int taskId, Bundle extras) { final Task task = new TaskBuilder(mAtm.mTaskSupervisor) .setComponent(new ComponentName(mContext.getPackageName(), className)) .setTaskId(taskId) .setParentTask(stack) .build(); final ActivityRecord activity = new ActivityBuilder(mAtm) .setTask(task) .setComponent(new ComponentName(mContext.getPackageName(), ".TaskActivity")) .setIntentExtras(extras) .build(); task.intent = activity.intent; return task; } @Test public void testMultipleDisplays() { final DisplayContent display0 = new TestDisplayContent.Builder(mAtm, 1000, 2500).build(); final DisplayContent display1 = new TestDisplayContent.Builder(mAtm, 1000, 2500).build(); final int numTasks = 10; final ArrayList tasks = new ArrayList<>(); for (int i = 0; i < numTasks; i++) { final Task stack = new TaskBuilder(mSupervisor) .setDisplay(i % 2 == 0 ? display0 : display1) .setOnTop(true) .build(); final Task task = createTask(stack, ".Task" + i, i, null); tasks.add(task); } final int numFetchTasks = numTasks; final ArrayList fetchTasks = new ArrayList<>(); mRunningTasks.getTasks(numFetchTasks, fetchTasks, FLAG_ALLOWED | FLAG_CROSS_USERS, mAtm.getRecentTasks(), display0, -1 /* callingUid */, PROFILE_IDS); assertThat(fetchTasks).hasSize(numTasks / 2); assertThat(fetchTasks).comparingElementsUsing(TASKINFO_HAS_ID) .containsExactly(0, 2, 4, 6, 8); fetchTasks.clear(); mRunningTasks.getTasks(numFetchTasks, fetchTasks, FLAG_ALLOWED | FLAG_CROSS_USERS, mAtm.getRecentTasks(), display1, -1 /* callingUid */, PROFILE_IDS); assertThat(fetchTasks).hasSize(numTasks / 2); assertThat(fetchTasks).comparingElementsUsing(TASKINFO_HAS_ID) .containsExactly(1, 3, 5, 7, 9); fetchTasks.clear(); mRunningTasks.getTasks(numFetchTasks, fetchTasks, FLAG_ALLOWED | FLAG_CROSS_USERS, mAtm.getRecentTasks(), mRootWindowContainer, -1 /* callingUid */, PROFILE_IDS); assertThat(fetchTasks).hasSize(numTasks); assertThat(fetchTasks).comparingElementsUsing(TASKINFO_HAS_ID) .containsExactly(0, 1, 2, 3, 4, 5, 6, 7, 8, 9); } }