blob: a1999c90170286627b24d880ad740af80ff62569 [file] [log] [blame]
Winson Chung1dbc8112017-09-28 18:05:31 -07001/*
Wale Ogunwale59507092018-10-29 09:00:30 -07002 * Copyright (C) 2018 The Android Open Source Project
Winson Chung1dbc8112017-09-28 18:05:31 -07003 *
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
Wale Ogunwale59507092018-10-29 09:00:30 -070014 * limitations under the License
Winson Chung1dbc8112017-09-28 18:05:31 -070015 */
16
Wale Ogunwale59507092018-10-29 09:00:30 -070017package com.android.server.wm;
Winson Chung1dbc8112017-09-28 18:05:31 -070018
Winson Chungd2730072019-02-22 14:10:27 -080019import static android.app.ActivityManager.RECENT_WITH_EXCLUDED;
Wale Ogunwale65ebd952018-04-25 15:41:44 -070020import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
Winson Chung6c9dcad2018-03-13 16:57:55 -070021import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
Winson Chung1dbc8112017-09-28 18:05:31 -070022import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
Winson Chung3f0e59a2017-10-25 10:19:05 -070023import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
Winson Chung1dbc8112017-09-28 18:05:31 -070024import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
Winson Chung27f81882018-04-19 14:45:03 -070025import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
Winson Chung3f0e59a2017-10-25 10:19:05 -070026import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
Winson Chungd6aa3db2017-10-05 17:18:43 -070027import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
Winson Chung079221f2017-12-13 17:43:34 -080028import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
Winson Chung1dbc8112017-09-28 18:05:31 -070029import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
Winson Chung6c9dcad2018-03-13 16:57:55 -070030import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
Winson Chung0ec2a352017-10-26 11:38:30 -070031import static android.view.Display.DEFAULT_DISPLAY;
Winson Chung1dbc8112017-09-28 18:05:31 -070032
Winson Chungd2730072019-02-22 14:10:27 -080033import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
Tadashi G. Takaokaa7a66952018-11-16 15:04:21 +090034import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
Winson Chungd2730072019-02-22 14:10:27 -080035import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
Tadashi G. Takaokaa7a66952018-11-16 15:04:21 +090036
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +090037import static com.google.common.truth.Truth.assertThat;
38import static com.google.common.truth.Truth.assertWithMessage;
39
Riddle Hsu090ac6f2018-10-31 12:55:29 +080040import static org.junit.Assert.assertEquals;
Winson Chung1dbc8112017-09-28 18:05:31 -070041import static org.junit.Assert.assertFalse;
42import static org.junit.Assert.assertTrue;
Winson Chung3f0e59a2017-10-25 10:19:05 -070043import static org.junit.Assert.fail;
44import static org.mockito.ArgumentMatchers.anyInt;
45import static org.mockito.ArgumentMatchers.anyString;
Winson Chung1dbc8112017-09-28 18:05:31 -070046
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +090047import static java.lang.Integer.MAX_VALUE;
48
Winson Chung3f0e59a2017-10-25 10:19:05 -070049import android.app.ActivityManager.RecentTaskInfo;
50import android.app.ActivityManager.RunningTaskInfo;
Wale Ogunwale65ebd952018-04-25 15:41:44 -070051import android.app.ActivityTaskManager;
Winson Chunge6439102018-07-30 15:48:01 -070052import android.app.WindowConfiguration;
Winson Chung1dbc8112017-09-28 18:05:31 -070053import android.content.ComponentName;
54import android.content.Context;
Winson Chung3f0e59a2017-10-25 10:19:05 -070055import android.content.pm.PackageManager;
56import android.content.pm.ParceledListSlice;
Winson Chungd6aa3db2017-10-05 17:18:43 -070057import android.content.pm.UserInfo;
Winson Chungc790b6c2018-03-19 11:23:25 -070058import android.content.res.Configuration;
Winson Chung3f0e59a2017-10-25 10:19:05 -070059import android.graphics.Rect;
60import android.os.Bundle;
61import android.os.Looper;
62import android.os.RemoteException;
Winson Chungd6aa3db2017-10-05 17:18:43 -070063import android.os.SystemClock;
Winson Chung1dbc8112017-09-28 18:05:31 -070064import android.platform.test.annotations.Presubmit;
Winson Chungd6aa3db2017-10-05 17:18:43 -070065import android.util.MutableLong;
Winson Chung1dbc8112017-09-28 18:05:31 -070066import android.util.SparseBooleanArray;
67
Brett Chabota26eda92018-07-23 13:08:30 -070068import androidx.test.filters.MediumTest;
Brett Chabota26eda92018-07-23 13:08:30 -070069
Wale Ogunwale59507092018-10-29 09:00:30 -070070import com.android.server.wm.RecentTasks.Callbacks;
Winson Chung1dbc8112017-09-28 18:05:31 -070071
Winson Chung1dbc8112017-09-28 18:05:31 -070072import org.junit.Before;
73import org.junit.Test;
John Reck3d294e72018-09-21 20:26:48 +000074
Winson Chung1dbc8112017-09-28 18:05:31 -070075import java.io.File;
76import java.util.ArrayList;
Winson Chung3f0e59a2017-10-25 10:19:05 -070077import java.util.HashSet;
Winson Chung1dbc8112017-09-28 18:05:31 -070078import java.util.List;
Winson Chung0ec2a352017-10-26 11:38:30 -070079import java.util.Random;
Winson Chung3f0e59a2017-10-25 10:19:05 -070080import java.util.Set;
Winson Chung1dbc8112017-09-28 18:05:31 -070081
82/**
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +090083 * Build/Install/Run:
84 * atest WmTests:RecentTasksTest
Winson Chung1dbc8112017-09-28 18:05:31 -070085 */
86@MediumTest
87@Presubmit
Winson Chung1dbc8112017-09-28 18:05:31 -070088public class RecentTasksTest extends ActivityTestsBase {
89 private static final int TEST_USER_0_ID = 0;
90 private static final int TEST_USER_1_ID = 10;
Winson Chungd6aa3db2017-10-05 17:18:43 -070091 private static final int TEST_QUIET_USER_ID = 20;
92 private static final UserInfo DEFAULT_USER_INFO = new UserInfo();
93 private static final UserInfo QUIET_USER_INFO = new UserInfo();
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +090094 private static int sLastTaskId = 1;
95 private static int sLastStackId = 1;
96 private static final int INVALID_STACK_ID = 999;
Winson Chung1dbc8112017-09-28 18:05:31 -070097
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +090098 private TestActivityTaskManagerService mTestService;
Winson Chung0ec2a352017-10-26 11:38:30 -070099 private ActivityDisplay mDisplay;
100 private ActivityDisplay mOtherDisplay;
Mark Renouf2aaf4cd2019-02-19 17:24:43 -0500101 private ActivityDisplay mSingleTaskDisplay;
Winson Chung1dbc8112017-09-28 18:05:31 -0700102 private ActivityStack mStack;
Winson Chung0ec2a352017-10-26 11:38:30 -0700103 private ActivityStack mHomeStack;
Winson Chung1dbc8112017-09-28 18:05:31 -0700104 private TestTaskPersister mTaskPersister;
Winson Chung0ec2a352017-10-26 11:38:30 -0700105 private TestRecentTasks mRecentTasks;
106 private TestRunningTasks mRunningTasks;
Winson Chung1dbc8112017-09-28 18:05:31 -0700107
Winson Chungc790b6c2018-03-19 11:23:25 -0700108 private ArrayList<TaskRecord> mTasks;
109 private ArrayList<TaskRecord> mSameDocumentTasks;
Winson Chung1dbc8112017-09-28 18:05:31 -0700110
111 private CallbacksRecorder mCallbacksRecorder;
112
113 @Before
Winson Chung1dbc8112017-09-28 18:05:31 -0700114 public void setUp() throws Exception {
Winson Chung3f0e59a2017-10-25 10:19:05 -0700115 mTaskPersister = new TestTaskPersister(mContext.getFilesDir());
Wale Ogunwaleb73f3962018-11-20 07:58:22 -0800116 mTestService = new MyTestActivityTaskManagerService(mContext);
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900117 mRecentTasks = (TestRecentTasks) mTestService.getRecentTasks();
Winson Chung3f0e59a2017-10-25 10:19:05 -0700118 mRecentTasks.loadParametersFromResources(mContext.getResources());
Wale Ogunwaled32da472018-11-16 07:19:28 -0800119 mRunningTasks = (TestRunningTasks) mTestService.mStackSupervisor.mRunningTasks;
120 mHomeStack = mTestService.mRootActivityContainer.getDefaultDisplay().getOrCreateStack(
Winson Chung6c9dcad2018-03-13 16:57:55 -0700121 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
Wale Ogunwaled32da472018-11-16 07:19:28 -0800122 mStack = mTestService.mRootActivityContainer.getDefaultDisplay().createStack(
Winson Chung1dbc8112017-09-28 18:05:31 -0700123 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
Winson Chung1dbc8112017-09-28 18:05:31 -0700124 mCallbacksRecorder = new CallbacksRecorder();
125 mRecentTasks.registerCallback(mCallbacksRecorder);
Winson Chungd6aa3db2017-10-05 17:18:43 -0700126 QUIET_USER_INFO.flags = UserInfo.FLAG_MANAGED_PROFILE | UserInfo.FLAG_QUIET_MODE;
Winson Chung1dbc8112017-09-28 18:05:31 -0700127
Winson Chungc790b6c2018-03-19 11:23:25 -0700128 mTasks = new ArrayList<>();
Winson Chung0ec2a352017-10-26 11:38:30 -0700129 mTasks.add(createTaskBuilder(".Task1").build());
130 mTasks.add(createTaskBuilder(".Task2").build());
131 mTasks.add(createTaskBuilder(".Task3").build());
132 mTasks.add(createTaskBuilder(".Task4").build());
133 mTasks.add(createTaskBuilder(".Task5").build());
Winson Chung1dbc8112017-09-28 18:05:31 -0700134
Winson Chungc790b6c2018-03-19 11:23:25 -0700135 mSameDocumentTasks = new ArrayList<>();
Winson Chung0ec2a352017-10-26 11:38:30 -0700136 mSameDocumentTasks.add(createDocumentTask(".DocumentTask1"));
137 mSameDocumentTasks.add(createDocumentTask(".DocumentTask1"));
Winson Chung1dbc8112017-09-28 18:05:31 -0700138 }
139
140 @Test
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900141 public void testCallbacks() {
Winson Chung1dbc8112017-09-28 18:05:31 -0700142 // Add some tasks
143 mRecentTasks.add(mTasks.get(0));
144 mRecentTasks.add(mTasks.get(1));
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900145 assertThat(mCallbacksRecorder.mAdded).contains(mTasks.get(0));
146 assertThat(mCallbacksRecorder.mAdded).contains(mTasks.get(1));
147 assertThat(mCallbacksRecorder.mTrimmed).isEmpty();
148 assertThat(mCallbacksRecorder.mRemoved).isEmpty();
Winson Chung1dbc8112017-09-28 18:05:31 -0700149 mCallbacksRecorder.clear();
150
151 // Remove some tasks
152 mRecentTasks.remove(mTasks.get(0));
153 mRecentTasks.remove(mTasks.get(1));
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900154 assertThat(mCallbacksRecorder.mAdded).isEmpty();
155 assertThat(mCallbacksRecorder.mTrimmed).isEmpty();
156 assertThat(mCallbacksRecorder.mRemoved).contains(mTasks.get(0));
157 assertThat(mCallbacksRecorder.mRemoved).contains(mTasks.get(1));
Winson Chung1dbc8112017-09-28 18:05:31 -0700158 mCallbacksRecorder.clear();
159
Winson Chung1dbc8112017-09-28 18:05:31 -0700160 // Remove the callback, ensure we don't get any calls
161 mRecentTasks.unregisterCallback(mCallbacksRecorder);
162 mRecentTasks.add(mTasks.get(0));
163 mRecentTasks.remove(mTasks.get(0));
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900164 assertThat(mCallbacksRecorder.mAdded).isEmpty();
165 assertThat(mCallbacksRecorder.mTrimmed).isEmpty();
166 assertThat(mCallbacksRecorder.mRemoved).isEmpty();
Winson Chung1dbc8112017-09-28 18:05:31 -0700167 }
168
169 @Test
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900170 public void testAddTasksNoMultiple_expectNoTrim() {
Winson Chung079221f2017-12-13 17:43:34 -0800171 // Add same non-multiple-task document tasks will remove the task (to re-add it) but not
172 // trim it
173 TaskRecord documentTask1 = createDocumentTask(".DocumentTask1");
174 TaskRecord documentTask2 = createDocumentTask(".DocumentTask1");
175 mRecentTasks.add(documentTask1);
176 mRecentTasks.add(documentTask2);
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900177 assertThat(mCallbacksRecorder.mAdded).contains(documentTask1);
178 assertThat(mCallbacksRecorder.mAdded).contains(documentTask2);
179 assertThat(mCallbacksRecorder.mTrimmed).isEmpty();
180 assertThat(mCallbacksRecorder.mRemoved).contains(documentTask1);
Winson Chung079221f2017-12-13 17:43:34 -0800181 }
182
183 @Test
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900184 public void testAddTasksMaxTaskRecents_expectNoTrim() {
Winson Chung079221f2017-12-13 17:43:34 -0800185 // Add a task hitting max-recents for that app will remove the task (to add the next one)
186 // but not trim it
187 TaskRecord documentTask1 = createDocumentTask(".DocumentTask1");
188 TaskRecord documentTask2 = createDocumentTask(".DocumentTask1");
189 documentTask1.maxRecents = 1;
190 documentTask2.maxRecents = 1;
191 mRecentTasks.add(documentTask1);
192 mRecentTasks.add(documentTask2);
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900193 assertThat(mCallbacksRecorder.mAdded).contains(documentTask1);
194 assertThat(mCallbacksRecorder.mAdded).contains(documentTask2);
195 assertThat(mCallbacksRecorder.mTrimmed).isEmpty();
196 assertThat(mCallbacksRecorder.mRemoved).contains(documentTask1);
Winson Chung079221f2017-12-13 17:43:34 -0800197 }
198
199 @Test
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900200 public void testAddTasksSameTask_expectNoTrim() {
Winson Chung079221f2017-12-13 17:43:34 -0800201 // Add a task that is already in the task list does not trigger any callbacks, it just
202 // moves in the list
203 TaskRecord documentTask1 = createDocumentTask(".DocumentTask1");
204 mRecentTasks.add(documentTask1);
205 mRecentTasks.add(documentTask1);
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900206 assertThat(mCallbacksRecorder.mAdded).hasSize(1);
207 assertThat(mCallbacksRecorder.mAdded).contains(documentTask1);
208 assertThat(mCallbacksRecorder.mTrimmed).isEmpty();
209 assertThat(mCallbacksRecorder.mRemoved).isEmpty();
Winson Chung079221f2017-12-13 17:43:34 -0800210 }
211
212 @Test
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900213 public void testAddTasksMultipleDocumentTasks_expectNoTrim() {
Winson Chung079221f2017-12-13 17:43:34 -0800214 // Add same multiple-task document tasks does not trim the first tasks
215 TaskRecord documentTask1 = createDocumentTask(".DocumentTask1",
216 FLAG_ACTIVITY_MULTIPLE_TASK);
217 TaskRecord documentTask2 = createDocumentTask(".DocumentTask1",
218 FLAG_ACTIVITY_MULTIPLE_TASK);
219 mRecentTasks.add(documentTask1);
220 mRecentTasks.add(documentTask2);
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900221 assertThat(mCallbacksRecorder.mAdded).hasSize(2);
222 assertThat(mCallbacksRecorder.mAdded).contains(documentTask1);
223 assertThat(mCallbacksRecorder.mAdded).contains(documentTask2);
224 assertThat(mCallbacksRecorder.mTrimmed).isEmpty();
225 assertThat(mCallbacksRecorder.mRemoved).isEmpty();
Winson Chung079221f2017-12-13 17:43:34 -0800226 }
227
228 @Test
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900229 public void testAddTasksMultipleTasks_expectRemovedNoTrim() {
Winson Chung6c9dcad2018-03-13 16:57:55 -0700230 // Add multiple same-affinity non-document tasks, ensure that it removes the other task,
231 // but that it does not trim it
232 TaskRecord task1 = createTaskBuilder(".Task1")
233 .setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK)
234 .build();
235 TaskRecord task2 = createTaskBuilder(".Task1")
236 .setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK)
237 .build();
238 mRecentTasks.add(task1);
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900239 assertThat(mCallbacksRecorder.mAdded).hasSize(1);
240 assertThat(mCallbacksRecorder.mAdded).contains(task1);
241 assertThat(mCallbacksRecorder.mTrimmed).isEmpty();
242 assertThat(mCallbacksRecorder.mRemoved).isEmpty();
Winson Chung6c9dcad2018-03-13 16:57:55 -0700243 mCallbacksRecorder.clear();
244 mRecentTasks.add(task2);
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900245 assertThat(mCallbacksRecorder.mAdded).hasSize(1);
246 assertThat(mCallbacksRecorder.mAdded).contains(task2);
247 assertThat(mCallbacksRecorder.mTrimmed).isEmpty();
248 assertThat(mCallbacksRecorder.mRemoved).hasSize(1);
249 assertThat(mCallbacksRecorder.mRemoved).contains(task1);
Winson Chung6c9dcad2018-03-13 16:57:55 -0700250 }
251
252 @Test
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900253 public void testAddTasksDifferentStacks_expectNoRemove() {
Winson Chung6c9dcad2018-03-13 16:57:55 -0700254 // Adding the same task with different activity types should not trigger removal of the
255 // other task
256 TaskRecord task1 = createTaskBuilder(".Task1")
257 .setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK)
258 .setStack(mHomeStack).build();
259 TaskRecord task2 = createTaskBuilder(".Task1")
260 .setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK)
261 .setStack(mStack).build();
262 mRecentTasks.add(task1);
263 mRecentTasks.add(task2);
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900264 assertThat(mCallbacksRecorder.mAdded).hasSize(2);
265 assertThat(mCallbacksRecorder.mAdded).contains(task1);
266 assertThat(mCallbacksRecorder.mAdded).contains(task2);
267 assertThat(mCallbacksRecorder.mTrimmed).isEmpty();
268 assertThat(mCallbacksRecorder.mRemoved).isEmpty();
Winson Chungc790b6c2018-03-19 11:23:25 -0700269 }
Winson Chung6c9dcad2018-03-13 16:57:55 -0700270
Winson Chungc790b6c2018-03-19 11:23:25 -0700271 @Test
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900272 public void testAddTaskCompatibleActivityType_expectRemove() {
Winson Chung27f81882018-04-19 14:45:03 -0700273 // Test with undefined activity type since the type is not persisted by the task persister
274 // and we want to ensure that a new task will match a restored task
Winson Chungc790b6c2018-03-19 11:23:25 -0700275 TaskRecord task1 = createTaskBuilder(".Task1")
276 .setFlags(FLAG_ACTIVITY_NEW_TASK)
277 .setStack(mStack)
278 .build();
Winson Chunge6439102018-07-30 15:48:01 -0700279 setTaskActivityType(task1, ACTIVITY_TYPE_UNDEFINED);
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900280 assertThat(task1.getActivityType()).isEqualTo(ACTIVITY_TYPE_UNDEFINED);
Winson Chungc790b6c2018-03-19 11:23:25 -0700281 mRecentTasks.add(task1);
282 mCallbacksRecorder.clear();
283
284 TaskRecord task2 = createTaskBuilder(".Task1")
285 .setFlags(FLAG_ACTIVITY_NEW_TASK)
286 .setStack(mStack)
287 .build();
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900288 assertEquals(ACTIVITY_TYPE_STANDARD, task2.getActivityType());
Winson Chungc790b6c2018-03-19 11:23:25 -0700289 mRecentTasks.add(task2);
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900290 assertThat(mCallbacksRecorder.mAdded).hasSize(1);
291 assertThat(mCallbacksRecorder.mAdded).contains(task2);
292 assertThat(mCallbacksRecorder.mTrimmed).isEmpty();
293 assertThat(mCallbacksRecorder.mRemoved).hasSize(1);
294 assertThat(mCallbacksRecorder.mRemoved).contains(task1);
Winson Chung6c9dcad2018-03-13 16:57:55 -0700295 }
296
297 @Test
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900298 public void testAddTaskCompatibleActivityTypeDifferentUser_expectNoRemove() {
Winson Chungb7667272018-04-06 10:18:39 -0700299 TaskRecord task1 = createTaskBuilder(".Task1")
300 .setFlags(FLAG_ACTIVITY_NEW_TASK)
301 .setStack(mStack)
302 .setUserId(TEST_USER_0_ID)
303 .build();
Winson Chunge6439102018-07-30 15:48:01 -0700304 setTaskActivityType(task1, ACTIVITY_TYPE_UNDEFINED);
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900305 assertEquals(ACTIVITY_TYPE_UNDEFINED, task1.getActivityType());
Winson Chungb7667272018-04-06 10:18:39 -0700306 mRecentTasks.add(task1);
307 mCallbacksRecorder.clear();
308
309 TaskRecord task2 = createTaskBuilder(".Task1")
310 .setFlags(FLAG_ACTIVITY_NEW_TASK)
311 .setStack(mStack)
312 .setUserId(TEST_USER_1_ID)
313 .build();
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900314 assertEquals(ACTIVITY_TYPE_STANDARD, task2.getActivityType());
Winson Chungb7667272018-04-06 10:18:39 -0700315 mRecentTasks.add(task2);
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900316 assertThat(mCallbacksRecorder.mAdded).hasSize(1);
317 assertThat(mCallbacksRecorder.mAdded).contains(task2);
318 assertThat(mCallbacksRecorder.mTrimmed).isEmpty();
319 assertThat(mCallbacksRecorder.mRemoved).isEmpty();
Winson Chungb7667272018-04-06 10:18:39 -0700320 }
321
322 @Test
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900323 public void testAddTaskCompatibleWindowingMode_expectRemove() {
Winson Chung27f81882018-04-19 14:45:03 -0700324 TaskRecord task1 = createTaskBuilder(".Task1")
325 .setFlags(FLAG_ACTIVITY_NEW_TASK)
326 .setStack(mStack)
327 .build();
Winson Chunge6439102018-07-30 15:48:01 -0700328 setTaskWindowingMode(task1, WINDOWING_MODE_UNDEFINED);
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900329 assertEquals(WINDOWING_MODE_UNDEFINED, task1.getWindowingMode());
Winson Chung27f81882018-04-19 14:45:03 -0700330 mRecentTasks.add(task1);
331 mCallbacksRecorder.clear();
332
Winson Chung27f81882018-04-19 14:45:03 -0700333 TaskRecord task2 = createTaskBuilder(".Task1")
334 .setFlags(FLAG_ACTIVITY_NEW_TASK)
335 .setStack(mStack)
336 .build();
Winson Chunge6439102018-07-30 15:48:01 -0700337 setTaskWindowingMode(task2, WINDOWING_MODE_FULLSCREEN);
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900338 assertEquals(WINDOWING_MODE_FULLSCREEN, task2.getWindowingMode());
Winson Chung27f81882018-04-19 14:45:03 -0700339 mRecentTasks.add(task2);
340
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900341 assertThat(mCallbacksRecorder.mAdded).hasSize(1);
342 assertThat(mCallbacksRecorder.mAdded).contains(task2);
343 assertThat(mCallbacksRecorder.mTrimmed).isEmpty();
344 assertThat(mCallbacksRecorder.mRemoved).hasSize(1);
345 assertThat(mCallbacksRecorder.mRemoved).contains(task1);
Winson Chung27f81882018-04-19 14:45:03 -0700346 }
347
348 @Test
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900349 public void testAddTaskIncompatibleWindowingMode_expectNoRemove() {
Winson Chung27f81882018-04-19 14:45:03 -0700350 TaskRecord task1 = createTaskBuilder(".Task1")
351 .setFlags(FLAG_ACTIVITY_NEW_TASK)
352 .setStack(mStack)
353 .build();
Winson Chunge6439102018-07-30 15:48:01 -0700354 setTaskWindowingMode(task1, WINDOWING_MODE_FULLSCREEN);
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900355 assertEquals(WINDOWING_MODE_FULLSCREEN, task1.getWindowingMode());
Winson Chung27f81882018-04-19 14:45:03 -0700356 mRecentTasks.add(task1);
357
Winson Chung27f81882018-04-19 14:45:03 -0700358 TaskRecord task2 = createTaskBuilder(".Task1")
359 .setFlags(FLAG_ACTIVITY_NEW_TASK)
360 .setStack(mStack)
361 .build();
Winson Chunge6439102018-07-30 15:48:01 -0700362 setTaskWindowingMode(task2, WINDOWING_MODE_PINNED);
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900363 assertEquals(WINDOWING_MODE_PINNED, task2.getWindowingMode());
Winson Chung27f81882018-04-19 14:45:03 -0700364 mRecentTasks.add(task2);
365
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900366 assertThat(mCallbacksRecorder.mAdded).hasSize(2);
367 assertThat(mCallbacksRecorder.mAdded).contains(task1);
368 assertThat(mCallbacksRecorder.mAdded).contains(task2);
369 assertThat(mCallbacksRecorder.mTrimmed).isEmpty();
370 assertThat(mCallbacksRecorder.mRemoved).isEmpty();
Winson Chung27f81882018-04-19 14:45:03 -0700371 }
372
373 @Test
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900374 public void testUsersTasks() {
Winson Chung0ec2a352017-10-26 11:38:30 -0700375 mRecentTasks.setOnlyTestVisibleRange();
376
Winson Chung1dbc8112017-09-28 18:05:31 -0700377 // Setup some tasks for the users
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900378 mTaskPersister.mUserTaskIdsOverride = new SparseBooleanArray();
379 mTaskPersister.mUserTaskIdsOverride.put(1, true);
380 mTaskPersister.mUserTaskIdsOverride.put(2, true);
381 mTaskPersister.mUserTasksOverride = new ArrayList<>();
382 mTaskPersister.mUserTasksOverride.add(createTaskBuilder(".UserTask1").build());
383 mTaskPersister.mUserTasksOverride.add(createTaskBuilder(".UserTask2").build());
Winson Chung1dbc8112017-09-28 18:05:31 -0700384
385 // Assert no user tasks are initially loaded
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900386 assertThat(mRecentTasks.usersWithRecentsLoadedLocked()).hasLength(0);
Winson Chung1dbc8112017-09-28 18:05:31 -0700387
388 // Load user 0 tasks
389 mRecentTasks.loadUserRecentsLocked(TEST_USER_0_ID);
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900390 assertThat(mRecentTasks.usersWithRecentsLoadedLocked()).asList().contains(TEST_USER_0_ID);
Winson Chung1dbc8112017-09-28 18:05:31 -0700391 assertTrue(mRecentTasks.containsTaskId(1, TEST_USER_0_ID));
392 assertTrue(mRecentTasks.containsTaskId(2, TEST_USER_0_ID));
393
394 // Load user 1 tasks
395 mRecentTasks.loadUserRecentsLocked(TEST_USER_1_ID);
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900396 assertThat(mRecentTasks.usersWithRecentsLoadedLocked()).asList().contains(TEST_USER_0_ID);
397 assertThat(mRecentTasks.usersWithRecentsLoadedLocked()).asList().contains(TEST_USER_1_ID);
Winson Chung1dbc8112017-09-28 18:05:31 -0700398 assertTrue(mRecentTasks.containsTaskId(1, TEST_USER_0_ID));
399 assertTrue(mRecentTasks.containsTaskId(2, TEST_USER_0_ID));
400 assertTrue(mRecentTasks.containsTaskId(1, TEST_USER_1_ID));
401 assertTrue(mRecentTasks.containsTaskId(2, TEST_USER_1_ID));
402
403 // Unload user 1 tasks
404 mRecentTasks.unloadUserDataFromMemoryLocked(TEST_USER_1_ID);
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900405 assertThat(mRecentTasks.usersWithRecentsLoadedLocked()).asList().contains(TEST_USER_0_ID);
406 assertThat(mRecentTasks.usersWithRecentsLoadedLocked()).asList()
407 .doesNotContain(TEST_USER_1_ID);
Winson Chung1dbc8112017-09-28 18:05:31 -0700408 assertTrue(mRecentTasks.containsTaskId(1, TEST_USER_0_ID));
409 assertTrue(mRecentTasks.containsTaskId(2, TEST_USER_0_ID));
410
411 // Unload user 0 tasks
412 mRecentTasks.unloadUserDataFromMemoryLocked(TEST_USER_0_ID);
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900413 assertThat(mRecentTasks.usersWithRecentsLoadedLocked()).asList()
414 .doesNotContain(TEST_USER_0_ID);
415 assertThat(mRecentTasks.usersWithRecentsLoadedLocked()).asList()
416 .doesNotContain(TEST_USER_1_ID);
Winson Chung1dbc8112017-09-28 18:05:31 -0700417 }
418
Winson Chungd6aa3db2017-10-05 17:18:43 -0700419 @Test
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900420 public void testOrderedIteration() {
Winson Chung0ec2a352017-10-26 11:38:30 -0700421 mRecentTasks.setOnlyTestVisibleRange();
422 TaskRecord task1 = createTaskBuilder(".Task1").build();
423 task1.lastActiveTime = new Random().nextInt();
424 TaskRecord task2 = createTaskBuilder(".Task1").build();
425 task2.lastActiveTime = new Random().nextInt();
426 TaskRecord task3 = createTaskBuilder(".Task1").build();
427 task3.lastActiveTime = new Random().nextInt();
428 TaskRecord task4 = createTaskBuilder(".Task1").build();
429 task4.lastActiveTime = new Random().nextInt();
430 mRecentTasks.add(task1);
431 mRecentTasks.add(task2);
432 mRecentTasks.add(task3);
433 mRecentTasks.add(task4);
434
Winson Chungd6aa3db2017-10-05 17:18:43 -0700435 MutableLong prevLastActiveTime = new MutableLong(0);
436 final ArrayList<TaskRecord> tasks = mRecentTasks.getRawTasks();
437 for (int i = 0; i < tasks.size(); i++) {
438 final TaskRecord task = tasks.get(i);
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900439 assertThat(prevLastActiveTime.value).isLessThan(task.lastActiveTime);
Winson Chungd6aa3db2017-10-05 17:18:43 -0700440 prevLastActiveTime.value = task.lastActiveTime;
441 }
442 }
443
444 @Test
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900445 public void testTrimToGlobalMaxNumRecents() {
Winson Chung0ec2a352017-10-26 11:38:30 -0700446 mRecentTasks.setOnlyTestVisibleRange();
447
Winson Chungd6aa3db2017-10-05 17:18:43 -0700448 // Limit the global maximum number of recent tasks to a fixed size
449 mRecentTasks.setGlobalMaxNumTasks(2 /* globalMaxNumTasks */);
450
451 // Add N+1 tasks
452 mRecentTasks.add(mTasks.get(0));
453 mRecentTasks.add(mTasks.get(1));
454 mRecentTasks.add(mTasks.get(2));
455
456 // Ensure that the last task was trimmed as an inactive task
457 assertTrimmed(mTasks.get(0));
458 }
459
460 @Test
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900461 public void testTrimQuietProfileTasks() {
Winson Chung0ec2a352017-10-26 11:38:30 -0700462 mRecentTasks.setOnlyTestVisibleRange();
463 TaskRecord qt1 = createTaskBuilder(".QuietTask1").setUserId(TEST_QUIET_USER_ID).build();
464 TaskRecord qt2 = createTaskBuilder(".QuietTask2").setUserId(TEST_QUIET_USER_ID).build();
Winson Chungd6aa3db2017-10-05 17:18:43 -0700465 mRecentTasks.add(qt1);
466 mRecentTasks.add(qt2);
467
468 mRecentTasks.add(mTasks.get(0));
469 mRecentTasks.add(mTasks.get(1));
470
471 // Ensure that the quiet user's tasks was trimmed once the new tasks were added
472 assertTrimmed(qt1, qt2);
473 }
474
475 @Test
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900476 public void testSessionDuration() {
Winson Chung0ec2a352017-10-26 11:38:30 -0700477 mRecentTasks.setOnlyTestVisibleRange();
Winson Chungd6aa3db2017-10-05 17:18:43 -0700478 mRecentTasks.setParameters(-1 /* min */, -1 /* max */, 50 /* ms */);
479
Winson Chung0ec2a352017-10-26 11:38:30 -0700480 TaskRecord t1 = createTaskBuilder(".Task1").build();
Winson Chungd6aa3db2017-10-05 17:18:43 -0700481 t1.touchActiveTime();
482 mRecentTasks.add(t1);
483
484 // Force a small sleep just beyond the session duration
485 SystemClock.sleep(75);
486
Winson Chung0ec2a352017-10-26 11:38:30 -0700487 TaskRecord t2 = createTaskBuilder(".Task2").build();
Winson Chungd6aa3db2017-10-05 17:18:43 -0700488 t2.touchActiveTime();
489 mRecentTasks.add(t2);
490
491 // Assert that the old task has been removed due to being out of the active session
492 assertTrimmed(t1);
493 }
494
495 @Test
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900496 public void testVisibleTasks_excludedFromRecents() {
Winson Chung0ec2a352017-10-26 11:38:30 -0700497 mRecentTasks.setOnlyTestVisibleRange();
Winson Chungd6aa3db2017-10-05 17:18:43 -0700498 mRecentTasks.setParameters(-1 /* min */, 4 /* max */, -1 /* ms */);
499
Winson Chung0ec2a352017-10-26 11:38:30 -0700500 TaskRecord excludedTask1 = createTaskBuilder(".ExcludedTask1")
501 .setFlags(FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
502 .build();
503 TaskRecord excludedTask2 = createTaskBuilder(".ExcludedTask2")
504 .setFlags(FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
505 .build();
Winson Chungd6aa3db2017-10-05 17:18:43 -0700506
507 mRecentTasks.add(excludedTask1);
508 mRecentTasks.add(mTasks.get(0));
509 mRecentTasks.add(mTasks.get(1));
510 mRecentTasks.add(mTasks.get(2));
511 mRecentTasks.add(excludedTask2);
512
513 // The last excluded task should be trimmed, while the first-most excluded task should not
514 assertTrimmed(excludedTask1);
515 }
516
517 @Test
Winson Chungd2730072019-02-22 14:10:27 -0800518 public void testVisibleTasks_excludedFromRecents_firstTaskNotVisible() {
519 // Create some set of tasks, some of which are visible and some are not
520 TaskRecord homeTask = setTaskActivityType(
521 createTaskBuilder("com.android.pkg1", ".HomeTask").build(),
522 ACTIVITY_TYPE_HOME);
523 homeTask.mUserSetupComplete = true;
524 mRecentTasks.add(homeTask);
525 TaskRecord excludedTask1 = createTaskBuilder(".ExcludedTask1")
526 .setFlags(FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
527 .build();
528 excludedTask1.mUserSetupComplete = true;
529 mRecentTasks.add(excludedTask1);
530
531 // Expect that the first visible excluded-from-recents task is visible
532 assertGetRecentTasksOrder(0 /* flags */, excludedTask1);
533 }
534
535 @Test
536 public void testVisibleTasks_excludedFromRecents_withExcluded() {
537 // Create some set of tasks, some of which are visible and some are not
538 TaskRecord t1 = createTaskBuilder("com.android.pkg1", ".Task1").build();
539 t1.mUserSetupComplete = true;
540 mRecentTasks.add(t1);
541 TaskRecord homeTask = setTaskActivityType(
542 createTaskBuilder("com.android.pkg1", ".HomeTask").build(),
543 ACTIVITY_TYPE_HOME);
544 homeTask.mUserSetupComplete = true;
545 mRecentTasks.add(homeTask);
546 TaskRecord excludedTask1 = createTaskBuilder(".ExcludedTask1")
547 .setFlags(FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
548 .build();
549 excludedTask1.mUserSetupComplete = true;
550 mRecentTasks.add(excludedTask1);
551 TaskRecord excludedTask2 = createTaskBuilder(".ExcludedTask2")
552 .setFlags(FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
553 .build();
554 excludedTask2.mUserSetupComplete = true;
555 mRecentTasks.add(excludedTask2);
556 TaskRecord t2 = createTaskBuilder("com.android.pkg2", ".Task1").build();
557 t2.mUserSetupComplete = true;
558 mRecentTasks.add(t2);
559
560 assertGetRecentTasksOrder(RECENT_WITH_EXCLUDED, t2, excludedTask2, excludedTask1, t1);
561 }
562
563 @Test
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900564 public void testVisibleTasks_minNum() {
Winson Chung0ec2a352017-10-26 11:38:30 -0700565 mRecentTasks.setOnlyTestVisibleRange();
Winson Chungd6aa3db2017-10-05 17:18:43 -0700566 mRecentTasks.setParameters(5 /* min */, -1 /* max */, 25 /* ms */);
567
568 for (int i = 0; i < 4; i++) {
569 final TaskRecord task = mTasks.get(i);
570 task.touchActiveTime();
571 mRecentTasks.add(task);
572 }
573
574 // Force a small sleep just beyond the session duration
575 SystemClock.sleep(50);
576
577 // Add a new task to trigger tasks to be trimmed
578 mRecentTasks.add(mTasks.get(4));
579
580 // Ensure that there are a minimum number of tasks regardless of session length
Winson Chung0ec2a352017-10-26 11:38:30 -0700581 assertNoTasksTrimmed();
Winson Chungd6aa3db2017-10-05 17:18:43 -0700582 }
583
584 @Test
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900585 public void testVisibleTasks_maxNum() {
Winson Chung0ec2a352017-10-26 11:38:30 -0700586 mRecentTasks.setOnlyTestVisibleRange();
Winson Chungd6aa3db2017-10-05 17:18:43 -0700587 mRecentTasks.setParameters(-1 /* min */, 3 /* max */, -1 /* ms */);
588
589 for (int i = 0; i < 5; i++) {
590 final TaskRecord task = mTasks.get(i);
591 task.touchActiveTime();
592 mRecentTasks.add(task);
593 }
594
595 // Ensure that only the last number of max tasks are kept
596 assertTrimmed(mTasks.get(0), mTasks.get(1));
597 }
598
Mark Renouf2aaf4cd2019-02-19 17:24:43 -0500599 /**
600 * Tests that tasks on singleTaskDisplay are not visible and not trimmed/removed.
601 */
602 @Test
603 public void testVisibleTasks_singleTaskDisplay() {
604 mRecentTasks.setOnlyTestVisibleRange();
605 mRecentTasks.setParameters(-1 /* min */, 3 /* max */, -1 /* ms */);
606
607 ActivityStack singleTaskStack = mSingleTaskDisplay.createStack(
608 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
609
610 TaskRecord excludedTask1 = createTaskBuilder(".ExcludedTask1")
611 .setStack(singleTaskStack)
612 .build();
613
614 assertFalse("Tasks on singleTaskDisplay should not be visible recents",
615 mRecentTasks.isVisibleRecentTask(excludedTask1));
616
617 mRecentTasks.add(excludedTask1);
618
619 // Add N+1 visible tasks.
620 mRecentTasks.add(mTasks.get(0));
621 mRecentTasks.add(mTasks.get(1));
622 mRecentTasks.add(mTasks.get(2));
623 mRecentTasks.add(mTasks.get(3));
624
625 // excludedTask is not trimmed.
626 assertTrimmed(mTasks.get(0));
627
Winson Chung42fa21f2019-04-02 16:23:46 -0700628 mRecentTasks.removeAllVisibleTasks(TEST_USER_0_ID);
Mark Renouf2aaf4cd2019-02-19 17:24:43 -0500629
630 // Only visible tasks removed.
631 assertTrimmed(mTasks.get(0), mTasks.get(1), mTasks.get(2), mTasks.get(3));
632 }
633
Winson Chung3f0e59a2017-10-25 10:19:05 -0700634 @Test
Winson Chungc5fe7ff2019-02-19 14:49:25 -0800635 public void testFreezeTaskListOrder_reorderExistingTask() {
636 // Add some tasks
637 mRecentTasks.add(mTasks.get(0));
638 mRecentTasks.add(mTasks.get(1));
639 mRecentTasks.add(mTasks.get(2));
640 mRecentTasks.add(mTasks.get(3));
641 mRecentTasks.add(mTasks.get(4));
642 mCallbacksRecorder.clear();
643
644 // Freeze the list
645 mRecentTasks.setFreezeTaskListReordering();
646 assertTrue(mRecentTasks.isFreezeTaskListReorderingSet());
647
648 // Relaunch a few tasks
649 mRecentTasks.add(mTasks.get(3));
650 mRecentTasks.add(mTasks.get(2));
651
652 // Commit the task ordering with a specific task focused
653 mRecentTasks.resetFreezeTaskListReordering(mTasks.get(2));
654 assertFalse(mRecentTasks.isFreezeTaskListReorderingSet());
655
656 // Ensure that the order of the task list is the same as before, but with the focused task
657 // at the front
658 assertRecentTasksOrder(mTasks.get(2),
659 mTasks.get(4),
660 mTasks.get(3),
661 mTasks.get(1),
662 mTasks.get(0));
663
664 assertThat(mCallbacksRecorder.mAdded).isEmpty();
665 assertThat(mCallbacksRecorder.mTrimmed).isEmpty();
666 assertThat(mCallbacksRecorder.mRemoved).isEmpty();
667 }
668
669 @Test
670 public void testFreezeTaskListOrder_addRemoveTasks() {
671 // Add some tasks
672 mRecentTasks.add(mTasks.get(0));
673 mRecentTasks.add(mTasks.get(1));
674 mRecentTasks.add(mTasks.get(2));
675 mCallbacksRecorder.clear();
676
677 // Freeze the list
678 mRecentTasks.setFreezeTaskListReordering();
679 assertTrue(mRecentTasks.isFreezeTaskListReorderingSet());
680
681 // Add and remove some tasks
682 mRecentTasks.add(mTasks.get(3));
683 mRecentTasks.add(mTasks.get(4));
684 mRecentTasks.remove(mTasks.get(0));
685 mRecentTasks.remove(mTasks.get(1));
686
687 // Unfreeze the list
688 mRecentTasks.resetFreezeTaskListReordering(null);
689 assertFalse(mRecentTasks.isFreezeTaskListReorderingSet());
690
691 // Ensure that the order of the task list accounts for the added and removed tasks (added
692 // at the end)
693 assertRecentTasksOrder(mTasks.get(4),
694 mTasks.get(3),
695 mTasks.get(2));
696
697 assertThat(mCallbacksRecorder.mAdded).hasSize(2);
698 assertThat(mCallbacksRecorder.mAdded).contains(mTasks.get(3));
699 assertThat(mCallbacksRecorder.mAdded).contains(mTasks.get(4));
700 assertThat(mCallbacksRecorder.mRemoved).hasSize(2);
701 assertThat(mCallbacksRecorder.mRemoved).contains(mTasks.get(0));
702 assertThat(mCallbacksRecorder.mRemoved).contains(mTasks.get(1));
703 }
704
705 @Test
706 public void testFreezeTaskListOrder_timeout() {
707 // Add some tasks
708 mRecentTasks.add(mTasks.get(0));
709 mRecentTasks.add(mTasks.get(1));
710 mRecentTasks.add(mTasks.get(2));
711 mRecentTasks.add(mTasks.get(3));
712 mRecentTasks.add(mTasks.get(4));
713
714 // Freeze the list
Winson Chungc5fe7ff2019-02-19 14:49:25 -0800715 mRecentTasks.setFreezeTaskListReordering();
716 assertTrue(mRecentTasks.isFreezeTaskListReorderingSet());
717
718 // Relaunch a few tasks
719 mRecentTasks.add(mTasks.get(2));
720 mRecentTasks.add(mTasks.get(1));
721
Winson Chungc5fe7ff2019-02-19 14:49:25 -0800722 ActivityStack stack = mTasks.get(2).getStack();
723 stack.moveToFront("", mTasks.get(2));
724 doReturn(stack).when(mTestService.mRootActivityContainer).getTopDisplayFocusedStack();
Winson Chung1fe58e92019-04-10 14:18:06 -0700725
726 // Simulate the reset from the timeout
Winson Chungc5fe7ff2019-02-19 14:49:25 -0800727 mRecentTasks.resetFreezeTaskListReorderingOnTimeout();
728 assertFalse(mRecentTasks.isFreezeTaskListReorderingSet());
729
730 // Ensure that the order of the task list is the same as before, but with the focused task
731 // at the front
732 assertRecentTasksOrder(mTasks.get(2),
733 mTasks.get(4),
734 mTasks.get(3),
735 mTasks.get(1),
736 mTasks.get(0));
737 }
738
739 @Test
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900740 public void testBackStackTasks_expectNoTrim() {
Winson Chung0ec2a352017-10-26 11:38:30 -0700741 mRecentTasks.setParameters(-1 /* min */, 1 /* max */, -1 /* ms */);
742
743 final MyTestActivityStackSupervisor supervisor =
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900744 (MyTestActivityStackSupervisor) mTestService.mStackSupervisor;
Louis Changbd48dca2018-08-29 17:44:34 +0800745 final ActivityStack homeStack = mDisplay.getHomeStack();
Winson Chung0ec2a352017-10-26 11:38:30 -0700746 final ActivityStack aboveHomeStack = new MyTestActivityStack(mDisplay, supervisor);
Winson Chung0ec2a352017-10-26 11:38:30 -0700747
748 // Add a number of tasks (beyond the max) but ensure that nothing is trimmed because all
749 // the tasks belong in stacks above the home stack
750 mRecentTasks.add(createTaskBuilder(".HomeTask1").setStack(homeStack).build());
751 mRecentTasks.add(createTaskBuilder(".Task1").setStack(aboveHomeStack).build());
752 mRecentTasks.add(createTaskBuilder(".Task2").setStack(aboveHomeStack).build());
753 mRecentTasks.add(createTaskBuilder(".Task3").setStack(aboveHomeStack).build());
754
755 assertNoTasksTrimmed();
756 }
757
758 @Test
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900759 public void testBehindHomeStackTasks_expectTaskTrimmed() {
Winson Chung0ec2a352017-10-26 11:38:30 -0700760 mRecentTasks.setParameters(-1 /* min */, 1 /* max */, -1 /* ms */);
761
762 final MyTestActivityStackSupervisor supervisor =
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900763 (MyTestActivityStackSupervisor) mTestService.mStackSupervisor;
Winson Chung0ec2a352017-10-26 11:38:30 -0700764 final ActivityStack behindHomeStack = new MyTestActivityStack(mDisplay, supervisor);
Louis Changbd48dca2018-08-29 17:44:34 +0800765 final ActivityStack homeStack = mDisplay.getHomeStack();
Winson Chung0ec2a352017-10-26 11:38:30 -0700766 final ActivityStack aboveHomeStack = new MyTestActivityStack(mDisplay, supervisor);
Winson Chung0ec2a352017-10-26 11:38:30 -0700767
768 // Add a number of tasks (beyond the max) but ensure that only the task in the stack behind
769 // the home stack is trimmed once a new task is added
770 final TaskRecord behindHomeTask = createTaskBuilder(".Task1")
771 .setStack(behindHomeStack)
772 .build();
773 mRecentTasks.add(behindHomeTask);
774 mRecentTasks.add(createTaskBuilder(".HomeTask1").setStack(homeStack).build());
775 mRecentTasks.add(createTaskBuilder(".Task2").setStack(aboveHomeStack).build());
776
777 assertTrimmed(behindHomeTask);
778 }
779
780 @Test
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900781 public void testOtherDisplayTasks_expectNoTrim() {
Winson Chung0ec2a352017-10-26 11:38:30 -0700782 mRecentTasks.setParameters(-1 /* min */, 1 /* max */, -1 /* ms */);
783
784 final MyTestActivityStackSupervisor supervisor =
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900785 (MyTestActivityStackSupervisor) mTestService.mStackSupervisor;
Louis Changbd48dca2018-08-29 17:44:34 +0800786 final ActivityStack homeStack = mDisplay.getHomeStack();
Winson Chung0ec2a352017-10-26 11:38:30 -0700787 final ActivityStack otherDisplayStack = new MyTestActivityStack(mOtherDisplay, supervisor);
Winson Chung0ec2a352017-10-26 11:38:30 -0700788
789 // Add a number of tasks (beyond the max) on each display, ensure that the tasks are not
790 // removed
791 mRecentTasks.add(createTaskBuilder(".HomeTask1").setStack(homeStack).build());
792 mRecentTasks.add(createTaskBuilder(".Task1").setStack(otherDisplayStack).build());
793 mRecentTasks.add(createTaskBuilder(".Task2").setStack(otherDisplayStack).build());
794 mRecentTasks.add(createTaskBuilder(".HomeTask2").setStack(homeStack).build());
795
796 assertNoTasksTrimmed();
797 }
798
799 @Test
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900800 public void testRemovePackageByName() {
Winson Chung99720d42018-04-09 11:28:46 -0700801 // Add a number of tasks with the same package name
802 mRecentTasks.add(createTaskBuilder("com.android.pkg1", ".Task1").build());
803 mRecentTasks.add(createTaskBuilder("com.android.pkg2", ".Task2").build());
804 mRecentTasks.add(createTaskBuilder("com.android.pkg3", ".Task3").build());
805 mRecentTasks.add(createTaskBuilder("com.android.pkg1", ".Task4").build());
806 mRecentTasks.removeTasksByPackageName("com.android.pkg1", TEST_USER_0_ID);
807
808 final ArrayList<TaskRecord> tasks = mRecentTasks.getRawTasks();
809 for (int i = 0; i < tasks.size(); i++) {
810 if (tasks.get(i).intent.getComponent().getPackageName().equals("com.android.pkg1")) {
811 fail("Expected com.android.pkg1 tasks to be removed");
812 }
813 }
814 }
815
816 @Test
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900817 public void testRemoveAllVisibleTasks() {
Winson Chunge6439102018-07-30 15:48:01 -0700818 mRecentTasks.setParameters(-1 /* min */, 3 /* max */, 100 /* ms */);
819
820 // Create some set of tasks, some of which are visible and some are not
821 TaskRecord t1 = createTaskBuilder("com.android.pkg1", ".Task1").build();
822 mRecentTasks.add(t1);
823 mRecentTasks.add(setTaskActivityType(
824 createTaskBuilder("com.android.pkg1", ".HomeTask").build(),
825 ACTIVITY_TYPE_HOME));
826 TaskRecord t2 = createTaskBuilder("com.android.pkg2", ".Task2").build();
827 mRecentTasks.add(t2);
828 mRecentTasks.add(setTaskWindowingMode(
829 createTaskBuilder("com.android.pkg1", ".PipTask").build(),
830 WINDOWING_MODE_PINNED));
831 TaskRecord t3 = createTaskBuilder("com.android.pkg3", ".Task3").build();
832 mRecentTasks.add(t3);
833
834 // Create some more tasks that are out of visible range, but are still visible
835 TaskRecord t4 = createTaskBuilder("com.android.pkg3", ".Task4").build();
836 mRecentTasks.add(t4);
837 TaskRecord t5 = createTaskBuilder("com.android.pkg3", ".Task5").build();
838 mRecentTasks.add(t5);
839
840 // Create some more tasks that are out of the active session range, but are still visible
841 TaskRecord t6 = createTaskBuilder("com.android.pkg3", ".Task6").build();
842 t6.lastActiveTime = SystemClock.elapsedRealtime() - 200;
843 mRecentTasks.add(t6);
844 TaskRecord t7 = createTaskBuilder("com.android.pkg3", ".Task7").build();
845 t7.lastActiveTime = SystemClock.elapsedRealtime() - 200;
846 mRecentTasks.add(t7);
847
848 // Remove all the visible tasks and ensure that they are removed
Winson Chung42fa21f2019-04-02 16:23:46 -0700849 mRecentTasks.removeAllVisibleTasks(TEST_USER_0_ID);
Winson Chunge6439102018-07-30 15:48:01 -0700850 assertTrimmed(t1, t2, t3, t4, t5, t6, t7);
851 }
852
853 @Test
Winson Chung42fa21f2019-04-02 16:23:46 -0700854 public void testRemoveAllVisibleTasksPerUser() {
855 mRecentTasks.setParameters(-1 /* min */, 3 /* max */, 100 /* ms */);
856
857 // Create a visible task per user
858 TaskRecord t1 = createTaskBuilder(".Task1")
859 .setUserId(TEST_USER_0_ID)
860 .build();
861 mRecentTasks.add(t1);
862
Winson Chungcdd4c3f2019-04-17 15:40:11 -0700863 TaskRecord t2 = createTaskBuilder(".Task2")
864 .setUserId(TEST_QUIET_USER_ID)
Winson Chung42fa21f2019-04-02 16:23:46 -0700865 .build();
866 mRecentTasks.add(t2);
867
Winson Chungcdd4c3f2019-04-17 15:40:11 -0700868 TaskRecord t3 = createTaskBuilder(".Task3")
869 .setUserId(TEST_USER_1_ID)
870 .build();
871 mRecentTasks.add(t3);
872
Winson Chung42fa21f2019-04-02 16:23:46 -0700873 // Remove all the visible tasks and ensure that they are removed
874 mRecentTasks.removeAllVisibleTasks(TEST_USER_0_ID);
Winson Chungcdd4c3f2019-04-17 15:40:11 -0700875 assertTrimmed(t1, t2);
Winson Chung42fa21f2019-04-02 16:23:46 -0700876 }
877
878 @Test
Riddle Hsu090ac6f2018-10-31 12:55:29 +0800879 public void testNotRestoreRecentTaskApis() {
880 final TaskRecord task = createTaskBuilder(".Task").build();
881 final int taskId = task.taskId;
882 mRecentTasks.add(task);
883 // Only keep the task in RecentTasks.
884 task.removeWindowContainer();
885 mStack.remove();
886
887 // The following APIs should not restore task from recents to the active list.
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900888 assertNotRestoreTask(() -> mTestService.setFocusedTask(taskId));
889 assertNotRestoreTask(() -> mTestService.startSystemLockTaskMode(taskId));
890 assertNotRestoreTask(() -> mTestService.cancelTaskWindowTransition(taskId));
Riddle Hsu090ac6f2018-10-31 12:55:29 +0800891 assertNotRestoreTask(
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900892 () -> mTestService.resizeTask(taskId, null /* bounds */, 0 /* resizeMode */));
Riddle Hsu090ac6f2018-10-31 12:55:29 +0800893 assertNotRestoreTask(
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900894 () -> mTestService.setTaskWindowingMode(taskId, WINDOWING_MODE_FULLSCREEN,
Riddle Hsu090ac6f2018-10-31 12:55:29 +0800895 false/* toTop */));
896 assertNotRestoreTask(
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900897 () -> mTestService.setTaskWindowingModeSplitScreenPrimary(taskId,
Riddle Hsu090ac6f2018-10-31 12:55:29 +0800898 SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT,
899 false /* toTop */, false /* animate */, null /* initialBounds */,
900 true /* showRecents */));
901 }
902
Winson Chungc5fe7ff2019-02-19 14:49:25 -0800903 /**
Winson Chungd2730072019-02-22 14:10:27 -0800904 * Ensures that the raw recent tasks list is in the provided order. Note that the expected tasks
Winson Chungc5fe7ff2019-02-19 14:49:25 -0800905 * should be ordered from least to most recent.
906 */
907 private void assertRecentTasksOrder(TaskRecord... expectedTasks) {
908 ArrayList<TaskRecord> tasks = mRecentTasks.getRawTasks();
909 assertTrue(expectedTasks.length == tasks.size());
910 for (int i = 0; i < tasks.size(); i++) {
911 assertTrue(expectedTasks[i] == tasks.get(i));
912 }
913 }
914
Winson Chungd2730072019-02-22 14:10:27 -0800915 /**
916 * Ensures that the recent tasks list is in the provided order. Note that the expected tasks
917 * should be ordered from least to most recent.
918 */
919 private void assertGetRecentTasksOrder(int getRecentTaskFlags, TaskRecord... expectedTasks) {
920 doNothing().when(mRecentTasks).loadUserRecentsLocked(anyInt());
921 doReturn(true).when(mRecentTasks).isUserRunning(anyInt(), anyInt());
922 List<RecentTaskInfo> infos = mRecentTasks.getRecentTasks(MAX_VALUE, getRecentTaskFlags,
923 true /* getTasksAllowed */, false /* getDetailedTasks */,
924 TEST_USER_0_ID, 0).getList();
925 assertTrue(expectedTasks.length == infos.size());
926 for (int i = 0; i < infos.size(); i++) {
927 assertTrue(expectedTasks[i].taskId == infos.get(i).taskId);
928 }
929 }
930
Riddle Hsu090ac6f2018-10-31 12:55:29 +0800931 private void assertNotRestoreTask(Runnable action) {
932 // Verify stack count doesn't change because task with fullscreen mode and standard type
933 // would have its own stack.
934 final int orignalStackCount = mDisplay.getChildCount();
935 action.run();
936 assertEquals(orignalStackCount, mDisplay.getChildCount());
937 }
938
939 @Test
Winson Chung3f0e59a2017-10-25 10:19:05 -0700940 public void testNotRecentsComponent_denyApiAccess() throws Exception {
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900941 doReturn(PackageManager.PERMISSION_DENIED).when(mTestService)
Wale Ogunwalea6191b42018-05-09 07:41:32 -0700942 .checkGetTasksPermission(anyString(), anyInt(), anyInt());
Winson Chung3f0e59a2017-10-25 10:19:05 -0700943 // Expect the following methods to fail due to recents component not being set
Winson Chung0ec2a352017-10-26 11:38:30 -0700944 mRecentTasks.setIsCallerRecentsOverride(TestRecentTasks.DENY_THROW_SECURITY_EXCEPTION);
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900945 doTestRecentTasksApis(false /* expectNoSecurityException */);
Winson Chung3f0e59a2017-10-25 10:19:05 -0700946 // Don't throw for the following tests
Winson Chung0ec2a352017-10-26 11:38:30 -0700947 mRecentTasks.setIsCallerRecentsOverride(TestRecentTasks.DENY);
Winson Chung3f0e59a2017-10-25 10:19:05 -0700948 testGetTasksApis(false /* expectNoSecurityException */);
949 }
950
951 @Test
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900952 public void testRecentsComponent_allowApiAccessWithoutPermissions() {
953 doReturn(PackageManager.PERMISSION_DENIED).when(mTestService)
Wale Ogunwalea6191b42018-05-09 07:41:32 -0700954 .checkGetTasksPermission(anyString(), anyInt(), anyInt());
Winson Chung3f0e59a2017-10-25 10:19:05 -0700955
956 // Set the recents component and ensure that the following calls do not fail
Winson Chung0ec2a352017-10-26 11:38:30 -0700957 mRecentTasks.setIsCallerRecentsOverride(TestRecentTasks.GRANT);
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900958 doTestRecentTasksApis(true /* expectNoSecurityException */);
Winson Chung3f0e59a2017-10-25 10:19:05 -0700959 testGetTasksApis(true /* expectNoSecurityException */);
960 }
961
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900962 private void doTestRecentTasksApis(boolean expectCallable) {
963 assertSecurityException(expectCallable, () -> mTestService.removeStack(INVALID_STACK_ID));
Winson Chung3f0e59a2017-10-25 10:19:05 -0700964 assertSecurityException(expectCallable,
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900965 () -> mTestService.removeStacksInWindowingModes(
966 new int[]{WINDOWING_MODE_UNDEFINED}));
Winson Chung3f0e59a2017-10-25 10:19:05 -0700967 assertSecurityException(expectCallable,
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900968 () -> mTestService.removeStacksWithActivityTypes(
969 new int[]{ACTIVITY_TYPE_UNDEFINED}));
970 assertSecurityException(expectCallable, () -> mTestService.removeTask(0));
Winson Chung3f0e59a2017-10-25 10:19:05 -0700971 assertSecurityException(expectCallable,
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900972 () -> mTestService.setTaskWindowingMode(0, WINDOWING_MODE_UNDEFINED, true));
Winson Chung3f0e59a2017-10-25 10:19:05 -0700973 assertSecurityException(expectCallable,
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900974 () -> mTestService.moveTaskToStack(0, INVALID_STACK_ID, true));
Winson Chung3f0e59a2017-10-25 10:19:05 -0700975 assertSecurityException(expectCallable,
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900976 () -> mTestService.setTaskWindowingModeSplitScreenPrimary(0,
Wale Ogunwalec59b4f62017-11-30 11:05:43 -0800977 SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT, true, true, new Rect(), true));
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900978 assertSecurityException(expectCallable, () -> mTestService.dismissSplitScreenMode(true));
979 assertSecurityException(expectCallable, () -> mTestService.dismissPip(true, 0));
Winson Chung3f0e59a2017-10-25 10:19:05 -0700980 assertSecurityException(expectCallable,
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900981 () -> mTestService.moveTopActivityToPinnedStack(INVALID_STACK_ID, new Rect()));
Winson Chung3f0e59a2017-10-25 10:19:05 -0700982 assertSecurityException(expectCallable,
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900983 () -> mTestService.resizeStack(INVALID_STACK_ID, new Rect(), true, true, true, 0));
Winson Chung3f0e59a2017-10-25 10:19:05 -0700984 assertSecurityException(expectCallable,
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900985 () -> mTestService.resizeDockedStack(new Rect(), new Rect(), new Rect(), new Rect(),
Winson Chung3f0e59a2017-10-25 10:19:05 -0700986 new Rect()));
987 assertSecurityException(expectCallable,
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900988 () -> mTestService.resizePinnedStack(new Rect(), new Rect()));
989 assertSecurityException(expectCallable, () -> mTestService.getAllStackInfos());
Winson Chung3f0e59a2017-10-25 10:19:05 -0700990 assertSecurityException(expectCallable,
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900991 () -> mTestService.getStackInfo(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_UNDEFINED));
Winson Chung3f0e59a2017-10-25 10:19:05 -0700992 assertSecurityException(expectCallable, () -> {
993 try {
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900994 mTestService.getFocusedStackInfo();
Winson Chung3f0e59a2017-10-25 10:19:05 -0700995 } catch (RemoteException e) {
996 // Ignore
997 }
998 });
999 assertSecurityException(expectCallable,
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +09001000 () -> mTestService.moveTasksToFullscreenStack(INVALID_STACK_ID, true));
Winson Chung3f0e59a2017-10-25 10:19:05 -07001001 assertSecurityException(expectCallable,
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +09001002 () -> mTestService.startActivityFromRecents(0, new Bundle()));
1003 assertSecurityException(expectCallable, () -> mTestService.getTaskSnapshot(0, true));
1004 assertSecurityException(expectCallable, () -> mTestService.registerTaskStackListener(null));
1005 assertSecurityException(expectCallable,
1006 () -> mTestService.unregisterTaskStackListener(null));
1007 assertSecurityException(expectCallable, () -> mTestService.getTaskDescription(0));
1008 assertSecurityException(expectCallable, () -> mTestService.cancelTaskWindowTransition(0));
1009 assertSecurityException(expectCallable, () -> mTestService.startRecentsActivity(null, null,
Winson Chunge2d72172018-01-25 17:46:20 +00001010 null));
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +09001011 assertSecurityException(expectCallable, () -> mTestService.cancelRecentsAnimation(true));
1012 assertSecurityException(expectCallable, () -> mTestService.stopAppSwitches());
1013 assertSecurityException(expectCallable, () -> mTestService.resumeAppSwitches());
Winson Chung3f0e59a2017-10-25 10:19:05 -07001014 }
1015
1016 private void testGetTasksApis(boolean expectCallable) {
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +09001017 mTestService.getRecentTasks(MAX_VALUE, 0, TEST_USER_0_ID);
1018 mTestService.getTasks(MAX_VALUE);
Winson Chung3f0e59a2017-10-25 10:19:05 -07001019 if (expectCallable) {
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +09001020 assertTrue(mRecentTasks.mLastAllowed);
1021 assertTrue(mRunningTasks.mLastAllowed);
Winson Chung3f0e59a2017-10-25 10:19:05 -07001022 } else {
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +09001023 assertFalse(mRecentTasks.mLastAllowed);
1024 assertFalse(mRunningTasks.mLastAllowed);
Winson Chung3f0e59a2017-10-25 10:19:05 -07001025 }
1026 }
1027
Winson Chung0ec2a352017-10-26 11:38:30 -07001028 private TaskBuilder createTaskBuilder(String className) {
Winson Chung99720d42018-04-09 11:28:46 -07001029 return createTaskBuilder(mContext.getPackageName(), className);
1030 }
1031
1032 private TaskBuilder createTaskBuilder(String packageName, String className) {
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +09001033 return new TaskBuilder(mTestService.mStackSupervisor)
Winson Chung99720d42018-04-09 11:28:46 -07001034 .setComponent(new ComponentName(packageName, className))
Winson Chung0ec2a352017-10-26 11:38:30 -07001035 .setStack(mStack)
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +09001036 .setTaskId(sLastTaskId++)
Winson Chung0ec2a352017-10-26 11:38:30 -07001037 .setUserId(TEST_USER_0_ID);
Winson Chung1dbc8112017-09-28 18:05:31 -07001038 }
1039
Winson Chung0ec2a352017-10-26 11:38:30 -07001040 private TaskRecord createDocumentTask(String className) {
Winson Chung079221f2017-12-13 17:43:34 -08001041 return createDocumentTask(className, 0);
1042 }
1043
1044 private TaskRecord createDocumentTask(String className, int flags) {
Winson Chung0ec2a352017-10-26 11:38:30 -07001045 TaskRecord task = createTaskBuilder(className)
Winson Chung079221f2017-12-13 17:43:34 -08001046 .setFlags(FLAG_ACTIVITY_NEW_DOCUMENT | flags)
Winson Chung0ec2a352017-10-26 11:38:30 -07001047 .build();
1048 task.affinity = null;
Wale Ogunwale65ebd952018-04-25 15:41:44 -07001049 task.maxRecents = ActivityTaskManager.getMaxAppRecentsLimitStatic();
Winson Chung1dbc8112017-09-28 18:05:31 -07001050 return task;
1051 }
1052
Winson Chunge6439102018-07-30 15:48:01 -07001053 private TaskRecord setTaskActivityType(TaskRecord task,
1054 @WindowConfiguration.ActivityType int activityType) {
1055 Configuration config1 = new Configuration();
1056 config1.windowConfiguration.setActivityType(activityType);
1057 task.onConfigurationChanged(config1);
1058 return task;
1059 }
1060
1061 private TaskRecord setTaskWindowingMode(TaskRecord task,
1062 @WindowConfiguration.WindowingMode int windowingMode) {
1063 Configuration config1 = new Configuration();
1064 config1.windowConfiguration.setWindowingMode(windowingMode);
1065 task.onConfigurationChanged(config1);
1066 return task;
1067 }
1068
Winson Chung0ec2a352017-10-26 11:38:30 -07001069 private void assertNoTasksTrimmed() {
1070 assertTrimmed();
1071 }
1072
Winson Chungd6aa3db2017-10-05 17:18:43 -07001073 private void assertTrimmed(TaskRecord... tasks) {
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +09001074 final ArrayList<TaskRecord> trimmed = mCallbacksRecorder.mTrimmed;
1075 final ArrayList<TaskRecord> removed = mCallbacksRecorder.mRemoved;
1076 assertWithMessage("Expected " + tasks.length + " trimmed tasks, got " + trimmed.size())
1077 .that(trimmed).hasSize(tasks.length);
1078 assertWithMessage("Expected " + tasks.length + " removed tasks, got " + removed.size())
1079 .that(removed).hasSize(tasks.length);
Winson Chungd6aa3db2017-10-05 17:18:43 -07001080 for (TaskRecord task : tasks) {
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +09001081 assertWithMessage("Expected trimmed task: " + task).that(trimmed).contains(task);
1082 assertWithMessage("Expected removed task: " + task).that(removed).contains(task);
Winson Chungd6aa3db2017-10-05 17:18:43 -07001083 }
1084 }
1085
Winson Chung3f0e59a2017-10-25 10:19:05 -07001086 private void assertSecurityException(boolean expectCallable, Runnable runnable) {
1087 boolean noSecurityException = true;
1088 try {
1089 runnable.run();
1090 } catch (SecurityException se) {
1091 noSecurityException = false;
1092 } catch (Exception e) {
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +09001093 // We only care about SecurityExceptions, fall through here.
Winson Chung3f0e59a2017-10-25 10:19:05 -07001094 }
1095 if (noSecurityException != expectCallable) {
1096 fail("Expected callable: " + expectCallable + " but got no security exception: "
1097 + noSecurityException);
1098 }
1099 }
1100
Wale Ogunwale16e505a2018-05-07 15:00:49 -07001101 private class MyTestActivityTaskManagerService extends TestActivityTaskManagerService {
1102 MyTestActivityTaskManagerService(Context context) {
1103 super(context);
1104 }
1105
1106 @Override
1107 protected RecentTasks createRecentTasks() {
Winson Chungd2730072019-02-22 14:10:27 -08001108 return spy(new TestRecentTasks(this, mTaskPersister));
Wale Ogunwale16e505a2018-05-07 15:00:49 -07001109 }
Wale Ogunwalec9e57de2018-05-08 14:28:07 -07001110
1111 @Override
Wale Ogunwaleb73f3962018-11-20 07:58:22 -08001112 protected ActivityStackSupervisor createStackSupervisor() {
1113 if (mTestStackSupervisor == null) {
1114 mTestStackSupervisor = new MyTestActivityStackSupervisor(this, mH.getLooper());
1115 }
1116 return mTestStackSupervisor;
Winson Chung3f0e59a2017-10-25 10:19:05 -07001117 }
Wale Ogunwaled32da472018-11-16 07:19:28 -08001118
1119 @Override
Wale Ogunwale3a256e62018-12-06 14:41:18 -08001120 void createDefaultDisplay() {
1121 super.createDefaultDisplay();
Wale Ogunwaled32da472018-11-16 07:19:28 -08001122 mDisplay = mRootActivityContainer.getActivityDisplay(DEFAULT_DISPLAY);
1123 mOtherDisplay = TestActivityDisplay.create(mTestStackSupervisor, DEFAULT_DISPLAY + 1);
Mark Renouf2aaf4cd2019-02-19 17:24:43 -05001124 mSingleTaskDisplay = TestActivityDisplay.create(mTestStackSupervisor,
1125 DEFAULT_DISPLAY + 2);
1126 mSingleTaskDisplay.setDisplayToSingleTaskInstance();
Wale Ogunwaled32da472018-11-16 07:19:28 -08001127 mRootActivityContainer.addChild(mOtherDisplay, ActivityDisplay.POSITION_TOP);
1128 mRootActivityContainer.addChild(mDisplay, ActivityDisplay.POSITION_TOP);
Mark Renouf2aaf4cd2019-02-19 17:24:43 -05001129 mRootActivityContainer.addChild(mSingleTaskDisplay, ActivityDisplay.POSITION_TOP);
Wale Ogunwaled32da472018-11-16 07:19:28 -08001130 }
Winson Chung3f0e59a2017-10-25 10:19:05 -07001131 }
1132
1133 private class MyTestActivityStackSupervisor extends TestActivityStackSupervisor {
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +09001134 MyTestActivityStackSupervisor(ActivityTaskManagerService service, Looper looper) {
Winson Chung3f0e59a2017-10-25 10:19:05 -07001135 super(service, looper);
1136 }
1137
1138 @Override
1139 RunningTasks createRunningTasks() {
1140 mRunningTasks = new TestRunningTasks();
1141 return mRunningTasks;
1142 }
Winson Chung0ec2a352017-10-26 11:38:30 -07001143 }
1144
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +09001145 private static class MyTestActivityStack extends TestActivityStack {
Winson Chung0ec2a352017-10-26 11:38:30 -07001146 private ActivityDisplay mDisplay = null;
1147
1148 MyTestActivityStack(ActivityDisplay display, ActivityStackSupervisor supervisor) {
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +09001149 super(display, sLastStackId++, supervisor, WINDOWING_MODE_FULLSCREEN,
Louis Changf2835df2018-10-17 15:14:45 +08001150 ACTIVITY_TYPE_STANDARD, true /* onTop */, false /* createActivity */);
Winson Chung0ec2a352017-10-26 11:38:30 -07001151 mDisplay = display;
1152 }
1153
1154 @Override
1155 ActivityDisplay getDisplay() {
1156 if (mDisplay != null) {
1157 return mDisplay;
1158 }
1159 return super.getDisplay();
1160 }
Winson Chung3f0e59a2017-10-25 10:19:05 -07001161 }
1162
Winson Chung1dbc8112017-09-28 18:05:31 -07001163 private static class CallbacksRecorder implements Callbacks {
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +09001164 public final ArrayList<TaskRecord> mAdded = new ArrayList<>();
1165 public final ArrayList<TaskRecord> mTrimmed = new ArrayList<>();
1166 public final ArrayList<TaskRecord> mRemoved = new ArrayList<>();
Winson Chung1dbc8112017-09-28 18:05:31 -07001167
1168 void clear() {
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +09001169 mAdded.clear();
1170 mTrimmed.clear();
1171 mRemoved.clear();
Winson Chung1dbc8112017-09-28 18:05:31 -07001172 }
1173
1174 @Override
1175 public void onRecentTaskAdded(TaskRecord task) {
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +09001176 mAdded.add(task);
Winson Chung1dbc8112017-09-28 18:05:31 -07001177 }
1178
1179 @Override
Winson Chunge6439102018-07-30 15:48:01 -07001180 public void onRecentTaskRemoved(TaskRecord task, boolean wasTrimmed, boolean killProcess) {
Winson Chungd6aa3db2017-10-05 17:18:43 -07001181 if (wasTrimmed) {
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +09001182 mTrimmed.add(task);
Winson Chungd6aa3db2017-10-05 17:18:43 -07001183 }
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +09001184 mRemoved.add(task);
Winson Chung1dbc8112017-09-28 18:05:31 -07001185 }
1186 }
1187
1188 private static class TestTaskPersister extends TaskPersister {
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +09001189 public SparseBooleanArray mUserTaskIdsOverride;
1190 public ArrayList<TaskRecord> mUserTasksOverride;
Winson Chung1dbc8112017-09-28 18:05:31 -07001191
1192 TestTaskPersister(File workingDir) {
1193 super(workingDir);
1194 }
1195
1196 @Override
1197 SparseBooleanArray loadPersistedTaskIdsForUser(int userId) {
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +09001198 if (mUserTaskIdsOverride != null) {
1199 return mUserTaskIdsOverride;
Winson Chung1dbc8112017-09-28 18:05:31 -07001200 }
1201 return super.loadPersistedTaskIdsForUser(userId);
1202 }
1203
1204 @Override
1205 List<TaskRecord> restoreTasksForUserLocked(int userId, SparseBooleanArray preaddedTasks) {
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +09001206 if (mUserTasksOverride != null) {
1207 return mUserTasksOverride;
Winson Chung1dbc8112017-09-28 18:05:31 -07001208 }
1209 return super.restoreTasksForUserLocked(userId, preaddedTasks);
1210 }
1211 }
Winson Chung3f0e59a2017-10-25 10:19:05 -07001212
1213 private static class TestRecentTasks extends RecentTasks {
1214 static final int GRANT = 0;
1215 static final int DENY = 1;
1216 static final int DENY_THROW_SECURITY_EXCEPTION = 2;
1217
1218 private boolean mOverrideIsCallerRecents;
Winson Chung0ec2a352017-10-26 11:38:30 -07001219 private boolean mIsTrimmableOverride;
Winson Chung3f0e59a2017-10-25 10:19:05 -07001220 private int mIsCallerRecentsPolicy;
Winson Chung0ec2a352017-10-26 11:38:30 -07001221
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +09001222 public boolean mLastAllowed;
Winson Chung3f0e59a2017-10-25 10:19:05 -07001223
Wale Ogunwale86b74462018-07-02 08:42:43 -07001224 TestRecentTasks(ActivityTaskManagerService service, TaskPersister taskPersister) {
1225 super(service, taskPersister);
1226 }
1227
1228 @Override
1229 Set<Integer> getProfileIds(int userId) {
1230 Set<Integer> profileIds = new HashSet<>();
1231 profileIds.add(TEST_USER_0_ID);
1232 profileIds.add(TEST_QUIET_USER_ID);
1233 return profileIds;
1234 }
1235
1236 @Override
1237 UserInfo getUserInfo(int userId) {
1238 switch (userId) {
1239 case TEST_USER_0_ID:
1240 case TEST_USER_1_ID:
1241 return DEFAULT_USER_INFO;
1242 case TEST_QUIET_USER_ID:
1243 return QUIET_USER_INFO;
1244 }
1245 return null;
1246 }
1247
1248 @Override
1249 int[] getCurrentProfileIds() {
1250 return new int[] { TEST_USER_0_ID, TEST_QUIET_USER_ID };
Winson Chung3f0e59a2017-10-25 10:19:05 -07001251 }
1252
1253 @Override
1254 boolean isCallerRecents(int callingUid) {
1255 if (mOverrideIsCallerRecents) {
1256 switch (mIsCallerRecentsPolicy) {
1257 case GRANT:
1258 return true;
1259 case DENY:
1260 return false;
1261 case DENY_THROW_SECURITY_EXCEPTION:
1262 throw new SecurityException();
1263 }
1264 }
1265 return super.isCallerRecents(callingUid);
1266 }
1267
1268 void setIsCallerRecentsOverride(int policy) {
1269 mOverrideIsCallerRecents = true;
1270 mIsCallerRecentsPolicy = policy;
1271 }
1272
Winson Chung0ec2a352017-10-26 11:38:30 -07001273 /**
1274 * To simplify the setup for some tests, the caller can request that we only rely on the
1275 * visible range test to determine what is trimmable. In this case, we don't try to
1276 * use the stack order to determine additionally if the task is trimmable when it is not
1277 * in the visible range.
1278 */
1279 void setOnlyTestVisibleRange() {
1280 mIsTrimmableOverride = true;
1281 }
1282
Winson Chung3f0e59a2017-10-25 10:19:05 -07001283 @Override
1284 ParceledListSlice<RecentTaskInfo> getRecentTasks(int maxNum, int flags,
1285 boolean getTasksAllowed,
1286 boolean getDetailedTasks, int userId, int callingUid) {
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +09001287 mLastAllowed = getTasksAllowed;
Winson Chung3f0e59a2017-10-25 10:19:05 -07001288 return super.getRecentTasks(maxNum, flags, getTasksAllowed, getDetailedTasks, userId,
1289 callingUid);
1290 }
Winson Chung0ec2a352017-10-26 11:38:30 -07001291
1292 @Override
1293 protected boolean isTrimmable(TaskRecord task) {
1294 return mIsTrimmableOverride || super.isTrimmable(task);
1295 }
Winson Chung3f0e59a2017-10-25 10:19:05 -07001296 }
1297
1298 private static class TestRunningTasks extends RunningTasks {
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +09001299 public boolean mLastAllowed;
Winson Chung3f0e59a2017-10-25 10:19:05 -07001300
1301 @Override
1302 void getTasks(int maxNum, List<RunningTaskInfo> list, int ignoreActivityType,
Riddle Hsu86cb7de2018-08-13 23:29:58 +08001303 int ignoreWindowingMode, ArrayList<ActivityDisplay> activityDisplays,
Winson Chung3f0e59a2017-10-25 10:19:05 -07001304 int callingUid, boolean allowed) {
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +09001305 mLastAllowed = allowed;
Winson Chung3f0e59a2017-10-25 10:19:05 -07001306 super.getTasks(maxNum, list, ignoreActivityType, ignoreWindowingMode, activityDisplays,
1307 callingUid, allowed);
1308 }
1309 }
Wale Ogunwalec59b4f62017-11-30 11:05:43 -08001310}