blob: 822cb5a0c2d42eb4ebeb7f28147c71d183cabefd [file] [log] [blame]
Bryce Lee840c5662017-04-13 10:02:51 -07001/*
Wale Ogunwale59507092018-10-29 09:00:30 -07002 * Copyright (C) 2018 The Android Open Source Project
Bryce Lee840c5662017-04-13 10:02:51 -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
Bryce Lee840c5662017-04-13 10:02:51 -070015 */
16
Wale Ogunwale59507092018-10-29 09:00:30 -070017package com.android.server.wm;
Bryce Lee840c5662017-04-13 10:02:51 -070018
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -070019import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
20import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -070021import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
Wale Ogunwale0db64ac2020-04-11 10:00:42 -070022import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
Kazuki Takisef85197b2018-06-18 18:18:36 +090023import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -070024import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -070025import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
26import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
27import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
Evan Rosky10475742018-09-05 19:02:48 -070028import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
Louis Chang7b03ad92019-08-21 12:32:33 +080029import static android.content.pm.ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
Bryce Lee18d51592017-10-25 10:22:19 -070030
Louis Chang99d6f0e2020-02-21 12:14:32 +080031import static com.android.dx.mockito.inline.extended.ExtendedMockito.doCallRealMethod;
Louis Changcfe46212019-07-30 10:34:18 +080032import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
Tadashi G. Takaokaa7a66952018-11-16 15:04:21 +090033import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
34import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
Wale Ogunwale8a1860a2019-06-05 08:57:19 -070035import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
Tadashi G. Takaokaa7a66952018-11-16 15:04:21 +090036import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
Wale Ogunwale59507092018-10-29 09:00:30 -070037import static com.android.server.wm.ActivityStack.ActivityState.DESTROYING;
wilsonshih8824a8a2019-03-12 17:21:35 +080038import static com.android.server.wm.ActivityStack.ActivityState.FINISHING;
Wale Ogunwale59507092018-10-29 09:00:30 -070039import static com.android.server.wm.ActivityStack.ActivityState.PAUSING;
40import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
Riddle Hsuaaef7312019-01-24 19:00:58 +080041import static com.android.server.wm.ActivityStack.ActivityState.STOPPED;
Wale Ogunwale59507092018-10-29 09:00:30 -070042import static com.android.server.wm.ActivityStack.ActivityState.STOPPING;
Andrii Kulian0c869cc2019-02-06 19:50:32 -080043import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_INVISIBLE;
44import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE;
45import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
Garfield Tanf6cc5c92019-01-15 13:54:12 -080046import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE;
47import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
Wale Ogunwale0db64ac2020-04-11 10:00:42 -070048import static com.android.server.wm.Task.FLAG_FORCE_HIDDEN_FOR_TASK_ORG;
Louis Changcdec0802019-11-11 11:45:07 +080049import static com.android.server.wm.Task.REPARENT_MOVE_STACK_TO_FRONT;
Andrii Kulian86d676c2020-03-27 19:34:54 -070050import static com.android.server.wm.TaskDisplayArea.getStackAbove;
Evan Rosky36b06cd2020-04-02 19:32:22 -070051import static com.android.server.wm.WindowContainer.POSITION_TOP;
Bryce Lee18d51592017-10-25 10:22:19 -070052
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +090053import static com.google.common.truth.Truth.assertThat;
54
Bryce Lee5daa3122017-04-19 10:40:42 -070055import static org.junit.Assert.assertEquals;
David Stevens18abd0e2017-08-17 14:55:47 -070056import static org.junit.Assert.assertFalse;
Bryce Lee840c5662017-04-13 10:02:51 -070057import static org.junit.Assert.assertNotNull;
58import static org.junit.Assert.assertNull;
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -070059import static org.junit.Assert.assertTrue;
Riddle Hsu138ef932018-10-26 17:12:06 +080060import static org.mockito.ArgumentMatchers.any;
Riddle Hsue10cea52018-10-16 23:33:23 +080061import static org.mockito.ArgumentMatchers.anyBoolean;
Riddle Hsu8e5f6d22020-02-07 00:15:57 +080062import static org.mockito.ArgumentMatchers.anyString;
Riddle Hsue10cea52018-10-16 23:33:23 +080063import static org.mockito.ArgumentMatchers.eq;
Bryce Lee840c5662017-04-13 10:02:51 -070064
Riddle Hsu8e5f6d22020-02-07 00:15:57 +080065import android.app.ActivityManager;
66import android.app.IApplicationThread;
Riddle Hsuaaef7312019-01-24 19:00:58 +080067import android.content.ComponentName;
Bryce Lee3345c4e2017-04-25 07:40:41 -070068import android.content.pm.ActivityInfo;
Jeff Chang59db8992020-04-22 20:27:46 +080069import android.os.Binder;
Bryce Lee9f6affd2017-09-01 09:18:35 -070070import android.os.UserHandle;
Bryce Lee840c5662017-04-13 10:02:51 -070071import android.platform.test.annotations.Presubmit;
Bryce Lee840c5662017-04-13 10:02:51 -070072
Brett Chabota26eda92018-07-23 13:08:30 -070073import androidx.test.filters.SmallTest;
Brett Chabota26eda92018-07-23 13:08:30 -070074
Wale Ogunwale04a05ac2017-09-17 21:35:02 -070075import org.junit.Before;
Bryce Lee840c5662017-04-13 10:02:51 -070076import org.junit.Test;
Riddle Hsu73f53572019-09-23 23:13:01 +080077import org.junit.runner.RunWith;
Bryce Lee840c5662017-04-13 10:02:51 -070078
79/**
80 * Tests for the {@link ActivityStack} class.
81 *
82 * Build/Install/Run:
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +090083 * atest WmTests:ActivityStackTests
Bryce Lee840c5662017-04-13 10:02:51 -070084 */
85@SmallTest
86@Presubmit
Riddle Hsu73f53572019-09-23 23:13:01 +080087@RunWith(WindowTestRunner.class)
Bryce Lee840c5662017-04-13 10:02:51 -070088public class ActivityStackTests extends ActivityTestsBase {
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -070089 private TaskDisplayArea mDefaultTaskDisplayArea;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -070090 private ActivityStack mStack;
Louis Changcdec0802019-11-11 11:45:07 +080091 private Task mTask;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -070092
93 @Before
Wale Ogunwale04a05ac2017-09-17 21:35:02 -070094 public void setUp() throws Exception {
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -070095 mDefaultTaskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
96 mStack = mDefaultTaskDisplayArea.createStack(WINDOWING_MODE_UNDEFINED,
97 ACTIVITY_TYPE_STANDARD, true /* onTop */);
Wale Ogunwale8a1860a2019-06-05 08:57:19 -070098 spyOn(mStack);
Bryce Lee18d51592017-10-25 10:22:19 -070099 mTask = new TaskBuilder(mSupervisor).setStack(mStack).build();
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700100 }
101
Bryce Lee840c5662017-04-13 10:02:51 -0700102 @Test
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900103 public void testResumedActivity() {
Bryce Leec4ab62a2018-03-05 14:19:26 -0800104 final ActivityRecord r = new ActivityBuilder(mService).setTask(mTask).build();
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900105 assertNull(mStack.getResumedActivity());
Bryce Leec4ab62a2018-03-05 14:19:26 -0800106 r.setState(RESUMED, "testResumedActivity");
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900107 assertEquals(r, mStack.getResumedActivity());
Bryce Leec4ab62a2018-03-05 14:19:26 -0800108 r.setState(PAUSING, "testResumedActivity");
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900109 assertNull(mStack.getResumedActivity());
Bryce Lee84730a02018-04-03 14:10:04 -0700110 }
Bryce Leec4ab62a2018-03-05 14:19:26 -0800111
Bryce Lee84730a02018-04-03 14:10:04 -0700112 @Test
113 public void testResumedActivityFromTaskReparenting() {
114 final ActivityRecord r = new ActivityBuilder(mService).setTask(mTask).build();
115 // Ensure moving task between two stacks updates resumed activity
116 r.setState(RESUMED, "testResumedActivityFromTaskReparenting");
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900117 assertEquals(r, mStack.getResumedActivity());
Bryce Lee84730a02018-04-03 14:10:04 -0700118
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700119 final ActivityStack destStack = mDefaultTaskDisplayArea.createStack(
Bryce Lee84730a02018-04-03 14:10:04 -0700120 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
121
Louis Changcdec0802019-11-11 11:45:07 +0800122 mTask.reparent(destStack, true /* toTop */, Task.REPARENT_KEEP_STACK_AT_FRONT,
Bryce Lee84730a02018-04-03 14:10:04 -0700123 false /* animate */, true /* deferResume*/,
124 "testResumedActivityFromTaskReparenting");
125
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900126 assertNull(mStack.getResumedActivity());
127 assertEquals(r, destStack.getResumedActivity());
Bryce Lee84730a02018-04-03 14:10:04 -0700128 }
129
130 @Test
131 public void testResumedActivityFromActivityReparenting() {
132 final ActivityRecord r = new ActivityBuilder(mService).setTask(mTask).build();
133 // Ensure moving task between two stacks updates resumed activity
134 r.setState(RESUMED, "testResumedActivityFromActivityReparenting");
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900135 assertEquals(r, mStack.getResumedActivity());
Bryce Lee84730a02018-04-03 14:10:04 -0700136
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700137 final ActivityStack destStack = mDefaultTaskDisplayArea.createStack(
Bryce Lee84730a02018-04-03 14:10:04 -0700138 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700139 mTask.reparent(destStack, true /*toTop*/, REPARENT_MOVE_STACK_TO_FRONT, false, false,
140 "testResumedActivityFromActivityReparenting");
Bryce Lee84730a02018-04-03 14:10:04 -0700141
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900142 assertNull(mStack.getResumedActivity());
143 assertEquals(r, destStack.getResumedActivity());
Bryce Lee5daa3122017-04-19 10:40:42 -0700144 }
Bryce Lee3345c4e2017-04-25 07:40:41 -0700145
146 @Test
Evan Rosky36b06cd2020-04-02 19:32:22 -0700147 public void testPrimarySplitScreenMoveToBack() {
148 TestSplitOrganizer organizer = new TestSplitOrganizer(mService);
149 // We're testing an edge case here where we have primary + fullscreen rather than secondary.
150 organizer.setMoveToSecondaryOnEnter(false);
151
152 // Create primary splitscreen stack.
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700153 final ActivityStack primarySplitScreen = mDefaultTaskDisplayArea.createStack(
Winson Chung3e2980e2018-03-29 17:28:57 -0700154 WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, true /* onTop */);
Bryce Lee8cab4a02018-01-05 09:00:49 -0800155
156 // Assert windowing mode.
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900157 assertEquals(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, primarySplitScreen.getWindowingMode());
Bryce Lee8cab4a02018-01-05 09:00:49 -0800158
159 // Move primary to back.
160 primarySplitScreen.moveToBack("testPrimarySplitScreenToFullscreenWhenMovedToBack",
161 null /* task */);
162
163 // Assert that stack is at the bottom.
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700164 assertEquals(0, mDefaultTaskDisplayArea.getIndexOf(primarySplitScreen));
Bryce Lee8cab4a02018-01-05 09:00:49 -0800165
166 // Ensure no longer in splitscreen.
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900167 assertEquals(WINDOWING_MODE_FULLSCREEN, primarySplitScreen.getWindowingMode());
Evan Rosky10475742018-09-05 19:02:48 -0700168
169 // Ensure that the override mode is restored to undefined
Evan Roskydfe3da72018-10-26 17:21:06 -0700170 assertEquals(WINDOWING_MODE_UNDEFINED,
171 primarySplitScreen.getRequestedOverrideWindowingMode());
Evan Rosky10475742018-09-05 19:02:48 -0700172 }
173
174 @Test
Evan Rosky36b06cd2020-04-02 19:32:22 -0700175 public void testMoveToPrimarySplitScreenThenMoveToBack() {
176 TestSplitOrganizer organizer = new TestSplitOrganizer(mService);
Evan Rosky10475742018-09-05 19:02:48 -0700177 // This time, start with a fullscreen activitystack
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700178 final ActivityStack primarySplitScreen = mDefaultTaskDisplayArea.createStack(
Evan Rosky36b06cd2020-04-02 19:32:22 -0700179 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
Evan Rosky10475742018-09-05 19:02:48 -0700180
Evan Rosky36b06cd2020-04-02 19:32:22 -0700181 primarySplitScreen.reparent((ActivityStack) organizer.mPrimary, POSITION_TOP,
182 false /*moveParents*/, "test");
Evan Rosky10475742018-09-05 19:02:48 -0700183
184 // Assert windowing mode.
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900185 assertEquals(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, primarySplitScreen.getWindowingMode());
Evan Rosky10475742018-09-05 19:02:48 -0700186
187 // Move primary to back.
188 primarySplitScreen.moveToBack("testPrimarySplitScreenToFullscreenWhenMovedToBack",
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900189 null /* task */);
Evan Rosky10475742018-09-05 19:02:48 -0700190
191 // Assert that stack is at the bottom.
Evan Rosky36b06cd2020-04-02 19:32:22 -0700192 assertEquals(primarySplitScreen, organizer.mSecondary.getChildAt(0));
Evan Rosky10475742018-09-05 19:02:48 -0700193
194 // Ensure that the override mode is restored to what it was (fullscreen)
Evan Rosky36b06cd2020-04-02 19:32:22 -0700195 assertEquals(WINDOWING_MODE_UNDEFINED,
Evan Roskydfe3da72018-10-26 17:21:06 -0700196 primarySplitScreen.getRequestedOverrideWindowingMode());
Evan Rosky10475742018-09-05 19:02:48 -0700197 }
198
199 @Test
Evan Rosky36b06cd2020-04-02 19:32:22 -0700200 public void testSplitScreenMoveToBack() {
201 TestSplitOrganizer organizer = new TestSplitOrganizer(mService);
202 // Set up split-screen with primary on top and secondary containing the home task below
203 // another stack.
204 final ActivityStack primaryTask = mDefaultTaskDisplayArea.createStack(
205 WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, true /* onTop */);
206 final ActivityStack homeRoot = mDefaultTaskDisplayArea.getStack(
207 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME);
208 final ActivityStack secondaryTask = mDefaultTaskDisplayArea.createStack(
209 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD, true /* onTop */);
210 mDefaultTaskDisplayArea.positionStackAtTop((ActivityStack) organizer.mPrimary,
211 false /* includingParents */);
212
213 // Move primary to back.
214 primaryTask.moveToBack("test", null /* task */);
215
216 // Assert that the primaryTask is now below home in its parent but primary is left alone.
217 assertEquals(0, organizer.mPrimary.getChildCount());
218 assertEquals(primaryTask, organizer.mSecondary.getChildAt(0));
219 assertEquals(1, organizer.mPrimary.compareTo(organizer.mSecondary));
220 assertEquals(1, homeRoot.compareTo(primaryTask));
221 assertEquals(homeRoot.getParent(), primaryTask.getParent());
222
223 // Make sure windowing modes are correct
224 assertEquals(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, organizer.mPrimary.getWindowingMode());
225 assertEquals(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, primaryTask.getWindowingMode());
226
227 // Move secondary to back via parent (should be equivalent)
228 ((ActivityStack) organizer.mSecondary).moveToBack("test", secondaryTask);
229
230 // Assert that it is now in back but still in secondary split
231 assertEquals(1, homeRoot.compareTo(primaryTask));
232 assertEquals(secondaryTask, organizer.mSecondary.getChildAt(0));
233 assertEquals(1, primaryTask.compareTo(secondaryTask));
234 assertEquals(homeRoot.getParent(), secondaryTask.getParent());
235 }
236
237 @Test
Riddle Hsu9adc55f2020-04-28 17:07:33 +0800238 public void testRemoveOrganizedTask_UpdateStackReference() {
239 final ActivityStack rootHomeTask = mDefaultTaskDisplayArea.getRootHomeTask();
240 final ActivityRecord homeActivity = new ActivityBuilder(mService)
241 .setStack(rootHomeTask)
242 .setCreateTask(true)
243 .build();
244 final ActivityStack secondaryStack = (ActivityStack) WindowContainer.fromBinder(
245 mService.mTaskOrganizerController.createRootTask(rootHomeTask.getDisplayId(),
246 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY).token.asBinder());
247
248 rootHomeTask.reparent(secondaryStack, POSITION_TOP);
249 assertEquals(secondaryStack, rootHomeTask.getParent());
250
251 // This should call to {@link TaskDisplayArea#removeStackReferenceIfNeeded}.
252 homeActivity.removeImmediately();
253 assertNull(mDefaultTaskDisplayArea.getRootHomeTask());
254 }
255
256 @Test
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900257 public void testStackInheritsDisplayWindowingMode() {
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700258 final ActivityStack primarySplitScreen = mDefaultTaskDisplayArea.createStack(
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900259 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
Evan Rosky10475742018-09-05 19:02:48 -0700260
261 assertEquals(WINDOWING_MODE_FULLSCREEN, primarySplitScreen.getWindowingMode());
Evan Roskydfe3da72018-10-26 17:21:06 -0700262 assertEquals(WINDOWING_MODE_UNDEFINED,
263 primarySplitScreen.getRequestedOverrideWindowingMode());
Evan Rosky10475742018-09-05 19:02:48 -0700264
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700265 mDefaultTaskDisplayArea.setWindowingMode(WINDOWING_MODE_FREEFORM);
Evan Rosky10475742018-09-05 19:02:48 -0700266 assertEquals(WINDOWING_MODE_FREEFORM, primarySplitScreen.getWindowingMode());
Evan Roskydfe3da72018-10-26 17:21:06 -0700267 assertEquals(WINDOWING_MODE_UNDEFINED,
268 primarySplitScreen.getRequestedOverrideWindowingMode());
Evan Rosky10475742018-09-05 19:02:48 -0700269 }
270
271 @Test
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900272 public void testStackOverridesDisplayWindowingMode() {
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700273 final ActivityStack primarySplitScreen = mDefaultTaskDisplayArea.createStack(
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900274 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
Evan Rosky10475742018-09-05 19:02:48 -0700275
276 assertEquals(WINDOWING_MODE_FULLSCREEN, primarySplitScreen.getWindowingMode());
Evan Roskydfe3da72018-10-26 17:21:06 -0700277 assertEquals(WINDOWING_MODE_UNDEFINED,
278 primarySplitScreen.getRequestedOverrideWindowingMode());
Evan Rosky10475742018-09-05 19:02:48 -0700279
280 primarySplitScreen.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
281 // setting windowing mode should still work even though resolved mode is already fullscreen
Evan Roskydfe3da72018-10-26 17:21:06 -0700282 assertEquals(WINDOWING_MODE_FULLSCREEN,
283 primarySplitScreen.getRequestedOverrideWindowingMode());
Evan Rosky10475742018-09-05 19:02:48 -0700284
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700285 mDefaultTaskDisplayArea.setWindowingMode(WINDOWING_MODE_FREEFORM);
Evan Rosky10475742018-09-05 19:02:48 -0700286 assertEquals(WINDOWING_MODE_FULLSCREEN, primarySplitScreen.getWindowingMode());
Bryce Lee8cab4a02018-01-05 09:00:49 -0800287 }
288
289 @Test
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900290 public void testStopActivityWhenActivityDestroyed() {
Bryce Lee18d51592017-10-25 10:22:19 -0700291 final ActivityRecord r = new ActivityBuilder(mService).setTask(mTask).build();
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700292 r.info.flags |= ActivityInfo.FLAG_NO_HISTORY;
Andrii Kulian6a6c4f12018-07-16 21:23:33 -0700293 mStack.moveToFront("testStopActivityWithDestroy");
Andrii Kulian79d67982019-08-19 11:56:16 -0700294 r.stopIfPossible();
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700295 // Mostly testing to make sure there is a crash in the call part, so if we get here we are
296 // good-to-go!
Bryce Lee3345c4e2017-04-25 07:40:41 -0700297 }
Bryce Lee9f6affd2017-09-01 09:18:35 -0700298
299 @Test
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900300 public void testFindTaskWithOverlay() {
Bryce Lee18d51592017-10-25 10:22:19 -0700301 final ActivityRecord r = new ActivityBuilder(mService)
302 .setCreateTask(true)
303 .setStack(mStack)
304 .setUid(0)
305 .build();
Louis Changcdec0802019-11-11 11:45:07 +0800306 final Task task = r.getTask();
Bryce Lee9f6affd2017-09-01 09:18:35 -0700307 // Overlay must be for a different user to prevent recognizing a matching top activity
Bryce Lee18d51592017-10-25 10:22:19 -0700308 final ActivityRecord taskOverlay = new ActivityBuilder(mService).setTask(task)
309 .setUid(UserHandle.PER_USER_RANGE * 2).build();
Wale Ogunwale0b3d2922019-12-30 08:55:07 -0800310 taskOverlay.setTaskOverlay(true);
Bryce Lee9f6affd2017-09-01 09:18:35 -0700311
Louis Chang149d5c82019-12-30 09:47:39 +0800312 final RootWindowContainer.FindTaskResult result =
313 new RootWindowContainer.FindTaskResult();
Wale Ogunwalea38654f2019-11-17 20:37:15 -0800314 result.process(r, mStack);
Bryce Lee9f6affd2017-09-01 09:18:35 -0700315
Wale Ogunwale21e06482019-11-18 05:14:15 -0800316 assertEquals(r, task.getTopNonFinishingActivity(false /* includeOverlays */));
317 assertEquals(taskOverlay, task.getTopNonFinishingActivity(true /* includeOverlays */));
Louis Changc85b1a32018-08-14 16:40:53 +0800318 assertNotNull(result.mRecord);
Bryce Lee9f6affd2017-09-01 09:18:35 -0700319 }
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700320
321 @Test
Louis Changb05c8d82019-06-25 11:56:55 +0800322 public void testFindTaskAlias() {
323 final String targetActivity = "target.activity";
324 final String aliasActivity = "alias.activity";
325 final ComponentName target = new ComponentName(DEFAULT_COMPONENT_PACKAGE_NAME,
326 targetActivity);
327 final ComponentName alias = new ComponentName(DEFAULT_COMPONENT_PACKAGE_NAME,
328 aliasActivity);
Louis Changcdec0802019-11-11 11:45:07 +0800329 final Task task = new TaskBuilder(mService.mStackSupervisor).setStack(mStack).build();
Louis Changb05c8d82019-06-25 11:56:55 +0800330 task.origActivity = alias;
331 task.realActivity = target;
332 new ActivityBuilder(mService).setComponent(target).setTask(task).setTargetActivity(
333 targetActivity).build();
334
335 // Using target activity to find task.
336 final ActivityRecord r1 = new ActivityBuilder(mService).setComponent(
337 target).setTargetActivity(targetActivity).build();
Louis Chang149d5c82019-12-30 09:47:39 +0800338 RootWindowContainer.FindTaskResult result = new RootWindowContainer.FindTaskResult();
Wale Ogunwalea38654f2019-11-17 20:37:15 -0800339 result.process(r1, mStack);
Louis Changb05c8d82019-06-25 11:56:55 +0800340 assertThat(result.mRecord).isNotNull();
341
342 // Using alias activity to find task.
343 final ActivityRecord r2 = new ActivityBuilder(mService).setComponent(
344 alias).setTargetActivity(targetActivity).build();
Louis Chang149d5c82019-12-30 09:47:39 +0800345 result = new RootWindowContainer.FindTaskResult();
Wale Ogunwalea38654f2019-11-17 20:37:15 -0800346 result.process(r2, mStack);
Louis Changb05c8d82019-06-25 11:56:55 +0800347 assertThat(result.mRecord).isNotNull();
348 }
349
350 @Test
Riddle Hsu138ef932018-10-26 17:12:06 +0800351 public void testMoveStackToBackIncludingParent() {
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700352 final TaskDisplayArea taskDisplayArea = addNewDisplayContentAt(DisplayContent.POSITION_TOP)
353 .getDefaultTaskDisplayArea();
354 final ActivityStack stack1 = createStackForShouldBeVisibleTest(taskDisplayArea,
Riddle Hsu138ef932018-10-26 17:12:06 +0800355 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700356 final ActivityStack stack2 = createStackForShouldBeVisibleTest(taskDisplayArea,
Riddle Hsu138ef932018-10-26 17:12:06 +0800357 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
358
359 // Do not move display to back because there is still another stack.
Wale Ogunwale85fb19a2019-12-05 10:41:05 +0900360 stack2.moveToBack("testMoveStackToBackIncludingParent", stack2.getTopMostTask());
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700361 verify(stack2).positionChildAtBottom(any(), eq(false) /* includingParents */);
Riddle Hsu138ef932018-10-26 17:12:06 +0800362
363 // Also move display to back because there is only one stack left.
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700364 taskDisplayArea.removeStack(stack1);
Wale Ogunwale85fb19a2019-12-05 10:41:05 +0900365 stack2.moveToBack("testMoveStackToBackIncludingParent", stack2.getTopMostTask());
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700366 verify(stack2).positionChildAtBottom(any(), eq(true) /* includingParents */);
Riddle Hsu138ef932018-10-26 17:12:06 +0800367 }
368
369 @Test
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900370 public void testShouldBeVisible_Fullscreen() {
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700371 final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultTaskDisplayArea,
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700372 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700373 final ActivityStack pinnedStack = createStackForShouldBeVisibleTest(mDefaultTaskDisplayArea,
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700374 WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700375 // Add an activity to the pinned stack so it isn't considered empty for visibility check.
376 final ActivityRecord pinnedActivity = new ActivityBuilder(mService)
377 .setCreateTask(true)
378 .setStack(pinnedStack)
379 .build();
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700380
381 assertTrue(homeStack.shouldBeVisible(null /* starting */));
382 assertTrue(pinnedStack.shouldBeVisible(null /* starting */));
383
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700384 final ActivityStack fullscreenStack = createStackForShouldBeVisibleTest(
385 mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
386 true /* onTop */);
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700387 // Home stack shouldn't be visible behind an opaque fullscreen stack, but pinned stack
388 // should be visible since it is always on-top.
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800389 doReturn(false).when(fullscreenStack).isTranslucent(any());
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700390 assertFalse(homeStack.shouldBeVisible(null /* starting */));
391 assertTrue(pinnedStack.shouldBeVisible(null /* starting */));
392 assertTrue(fullscreenStack.shouldBeVisible(null /* starting */));
393
394 // Home stack should be visible behind a translucent fullscreen stack.
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800395 doReturn(true).when(fullscreenStack).isTranslucent(any());
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700396 assertTrue(homeStack.shouldBeVisible(null /* starting */));
397 assertTrue(pinnedStack.shouldBeVisible(null /* starting */));
398 }
399
400 @Test
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900401 public void testShouldBeVisible_SplitScreen() {
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700402 final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultTaskDisplayArea,
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700403 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800404 // Home stack should always be fullscreen for this test.
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700405 doReturn(false).when(homeStack).supportsSplitScreenWindowingMode();
406 final ActivityStack splitScreenPrimary =
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700407 createStackForShouldBeVisibleTest(mDefaultTaskDisplayArea,
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700408 WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, true /* onTop */);
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700409 final ActivityStack splitScreenSecondary =
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700410 createStackForShouldBeVisibleTest(mDefaultTaskDisplayArea,
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700411 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD, true /* onTop */);
412
413 // Home stack shouldn't be visible if both halves of split-screen are opaque.
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800414 doReturn(false).when(splitScreenPrimary).isTranslucent(any());
415 doReturn(false).when(splitScreenSecondary).isTranslucent(any());
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700416 assertFalse(homeStack.shouldBeVisible(null /* starting */));
417 assertTrue(splitScreenPrimary.shouldBeVisible(null /* starting */));
418 assertTrue(splitScreenSecondary.shouldBeVisible(null /* starting */));
Andrii Kulian0c869cc2019-02-06 19:50:32 -0800419 assertEquals(STACK_VISIBILITY_INVISIBLE, homeStack.getVisibility(null /* starting */));
420 assertEquals(STACK_VISIBILITY_VISIBLE,
421 splitScreenPrimary.getVisibility(null /* starting */));
422 assertEquals(STACK_VISIBILITY_VISIBLE,
423 splitScreenSecondary.getVisibility(null /* starting */));
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700424
425 // Home stack should be visible if one of the halves of split-screen is translucent.
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800426 doReturn(true).when(splitScreenPrimary).isTranslucent(any());
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700427 assertTrue(homeStack.shouldBeVisible(null /* starting */));
428 assertTrue(splitScreenPrimary.shouldBeVisible(null /* starting */));
429 assertTrue(splitScreenSecondary.shouldBeVisible(null /* starting */));
Andrii Kulian0c869cc2019-02-06 19:50:32 -0800430 assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
431 homeStack.getVisibility(null /* starting */));
432 assertEquals(STACK_VISIBILITY_VISIBLE,
433 splitScreenPrimary.getVisibility(null /* starting */));
434 assertEquals(STACK_VISIBILITY_VISIBLE,
435 splitScreenSecondary.getVisibility(null /* starting */));
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700436
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700437 final ActivityStack splitScreenSecondary2 =
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700438 createStackForShouldBeVisibleTest(mDefaultTaskDisplayArea,
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700439 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD, true /* onTop */);
440 // First split-screen secondary shouldn't be visible behind another opaque split-split
441 // secondary.
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800442 doReturn(false).when(splitScreenSecondary2).isTranslucent(any());
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700443 assertFalse(splitScreenSecondary.shouldBeVisible(null /* starting */));
444 assertTrue(splitScreenSecondary2.shouldBeVisible(null /* starting */));
Andrii Kulian0c869cc2019-02-06 19:50:32 -0800445 assertEquals(STACK_VISIBILITY_INVISIBLE,
446 splitScreenSecondary.getVisibility(null /* starting */));
447 assertEquals(STACK_VISIBILITY_VISIBLE,
448 splitScreenSecondary2.getVisibility(null /* starting */));
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700449
Wale Ogunwale8e923af2018-03-23 08:48:11 -0700450 // First split-screen secondary should be visible behind another translucent split-screen
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700451 // secondary.
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800452 doReturn(true).when(splitScreenSecondary2).isTranslucent(any());
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700453 assertTrue(splitScreenSecondary.shouldBeVisible(null /* starting */));
454 assertTrue(splitScreenSecondary2.shouldBeVisible(null /* starting */));
Andrii Kulian0c869cc2019-02-06 19:50:32 -0800455 assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
456 splitScreenSecondary.getVisibility(null /* starting */));
457 assertEquals(STACK_VISIBILITY_VISIBLE,
458 splitScreenSecondary2.getVisibility(null /* starting */));
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700459
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700460 final ActivityStack assistantStack = createStackForShouldBeVisibleTest(
461 mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_ASSISTANT,
462 true /* onTop */);
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700463
464 // Split-screen stacks shouldn't be visible behind an opaque fullscreen stack.
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800465 doReturn(false).when(assistantStack).isTranslucent(any());
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700466 assertTrue(assistantStack.shouldBeVisible(null /* starting */));
467 assertFalse(splitScreenPrimary.shouldBeVisible(null /* starting */));
468 assertFalse(splitScreenSecondary.shouldBeVisible(null /* starting */));
469 assertFalse(splitScreenSecondary2.shouldBeVisible(null /* starting */));
Andrii Kulian0c869cc2019-02-06 19:50:32 -0800470 assertEquals(STACK_VISIBILITY_VISIBLE,
471 assistantStack.getVisibility(null /* starting */));
472 assertEquals(STACK_VISIBILITY_INVISIBLE,
473 splitScreenPrimary.getVisibility(null /* starting */));
474 assertEquals(STACK_VISIBILITY_INVISIBLE,
475 splitScreenSecondary.getVisibility(null /* starting */));
476 assertEquals(STACK_VISIBILITY_INVISIBLE,
477 splitScreenSecondary2.getVisibility(null /* starting */));
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700478
479 // Split-screen stacks should be visible behind a translucent fullscreen stack.
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800480 doReturn(true).when(assistantStack).isTranslucent(any());
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700481 assertTrue(assistantStack.shouldBeVisible(null /* starting */));
482 assertTrue(splitScreenPrimary.shouldBeVisible(null /* starting */));
483 assertTrue(splitScreenSecondary.shouldBeVisible(null /* starting */));
484 assertTrue(splitScreenSecondary2.shouldBeVisible(null /* starting */));
Andrii Kulian0c869cc2019-02-06 19:50:32 -0800485 assertEquals(STACK_VISIBILITY_VISIBLE,
486 assistantStack.getVisibility(null /* starting */));
487 assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
488 splitScreenPrimary.getVisibility(null /* starting */));
489 assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
490 splitScreenSecondary.getVisibility(null /* starting */));
491 assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
492 splitScreenSecondary2.getVisibility(null /* starting */));
Wale Ogunwale8e923af2018-03-23 08:48:11 -0700493
Galia Peycheva7ecd6ef2020-03-26 19:59:40 +0100494 // Assistant stack shouldn't be visible behind translucent split-screen stack,
495 // unless it is configured to show on top of everything.
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800496 doReturn(false).when(assistantStack).isTranslucent(any());
497 doReturn(true).when(splitScreenPrimary).isTranslucent(any());
498 doReturn(true).when(splitScreenSecondary2).isTranslucent(any());
Wale Ogunwale8e923af2018-03-23 08:48:11 -0700499 splitScreenSecondary2.moveToFront("testShouldBeVisible_SplitScreen");
500 splitScreenPrimary.moveToFront("testShouldBeVisible_SplitScreen");
Galia Peycheva7ecd6ef2020-03-26 19:59:40 +0100501
502 if (isAssistantOnTop()) {
503 assertTrue(assistantStack.shouldBeVisible(null /* starting */));
504 assertFalse(splitScreenPrimary.shouldBeVisible(null /* starting */));
505 assertFalse(splitScreenSecondary2.shouldBeVisible(null /* starting */));
506 assertEquals(STACK_VISIBILITY_VISIBLE,
507 assistantStack.getVisibility(null /* starting */));
508 assertEquals(STACK_VISIBILITY_INVISIBLE,
509 splitScreenPrimary.getVisibility(null /* starting */));
510 assertEquals(STACK_VISIBILITY_INVISIBLE,
511 splitScreenSecondary.getVisibility(null /* starting */));
512 assertEquals(STACK_VISIBILITY_INVISIBLE,
513 splitScreenSecondary2.getVisibility(null /* starting */));
514 } else {
515 assertFalse(assistantStack.shouldBeVisible(null /* starting */));
516 assertTrue(splitScreenPrimary.shouldBeVisible(null /* starting */));
517 assertTrue(splitScreenSecondary2.shouldBeVisible(null /* starting */));
518 assertEquals(STACK_VISIBILITY_INVISIBLE,
519 assistantStack.getVisibility(null /* starting */));
520 assertEquals(STACK_VISIBILITY_VISIBLE,
521 splitScreenPrimary.getVisibility(null /* starting */));
522 assertEquals(STACK_VISIBILITY_INVISIBLE,
523 splitScreenSecondary.getVisibility(null /* starting */));
524 assertEquals(STACK_VISIBILITY_VISIBLE,
525 splitScreenSecondary2.getVisibility(null /* starting */));
526 }
Andrii Kulian0c869cc2019-02-06 19:50:32 -0800527 }
528
529 @Test
Wale Ogunwale0db64ac2020-04-11 10:00:42 -0700530 public void testGetVisibility_MultiLevel() {
531 final ActivityStack homeStack = createStackForShouldBeVisibleTest(
532 mDefaultTaskDisplayArea, WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME,
533 true /* onTop */);
534 final ActivityStack splitPrimary = createStackForShouldBeVisibleTest(
535 mDefaultTaskDisplayArea, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY,
536 ACTIVITY_TYPE_UNDEFINED, true /* onTop */);
537 final ActivityStack splitSecondary = createStackForShouldBeVisibleTest(
538 mDefaultTaskDisplayArea, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY,
539 ACTIVITY_TYPE_UNDEFINED, true /* onTop */);
540
541 doReturn(false).when(homeStack).isTranslucent(any());
542 doReturn(false).when(splitPrimary).isTranslucent(any());
543 doReturn(false).when(splitSecondary).isTranslucent(any());
544
545
546 // Re-parent home to split secondary.
547 homeStack.reparent(splitSecondary, POSITION_TOP);
548 // Current tasks should be visible.
549 assertEquals(STACK_VISIBILITY_VISIBLE, splitPrimary.getVisibility(null /* starting */));
550 assertEquals(STACK_VISIBILITY_VISIBLE, splitSecondary.getVisibility(null /* starting */));
551 // Home task should still be visible even though it is a child of another visible task.
552 assertEquals(STACK_VISIBILITY_VISIBLE, homeStack.getVisibility(null /* starting */));
553
554
555 // Add fullscreen translucent task that partially occludes split tasks
556 final ActivityStack translucentStack = createStandardStackForVisibilityTest(
557 WINDOWING_MODE_FULLSCREEN, true /* translucent */);
558 // Fullscreen translucent task should be visible
559 assertEquals(STACK_VISIBILITY_VISIBLE, translucentStack.getVisibility(null /* starting */));
560 // Split tasks should be visible behind translucent
561 assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
562 splitPrimary.getVisibility(null /* starting */));
563 assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
564 splitSecondary.getVisibility(null /* starting */));
565 // Home task should be visible behind translucent since its parent is visible behind
566 // translucent.
567 assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
568 homeStack.getVisibility(null /* starting */));
569
570
571 // Hide split-secondary
572 splitSecondary.setForceHidden(FLAG_FORCE_HIDDEN_FOR_TASK_ORG, true /* set */);
573 // Home split secondary and home task should be invisible.
574 assertEquals(STACK_VISIBILITY_INVISIBLE, splitSecondary.getVisibility(null /* starting */));
575 assertEquals(STACK_VISIBILITY_INVISIBLE, homeStack.getVisibility(null /* starting */));
576 }
577
578 @Test
Andrii Kulian0c869cc2019-02-06 19:50:32 -0800579 public void testGetVisibility_FullscreenBehindTranslucent() {
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700580 final ActivityStack bottomStack =
Andrii Kulian0c869cc2019-02-06 19:50:32 -0800581 createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
582 false /* translucent */);
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700583 final ActivityStack translucentStack =
Andrii Kulian0c869cc2019-02-06 19:50:32 -0800584 createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
585 true /* translucent */);
586
587 assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
588 bottomStack.getVisibility(null /* starting */));
589 assertEquals(STACK_VISIBILITY_VISIBLE,
590 translucentStack.getVisibility(null /* starting */));
591 }
592
593 @Test
594 public void testGetVisibility_FullscreenBehindTranslucentAndOpaque() {
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700595 final ActivityStack bottomStack =
Andrii Kulian0c869cc2019-02-06 19:50:32 -0800596 createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
597 false /* translucent */);
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700598 final ActivityStack translucentStack =
Andrii Kulian0c869cc2019-02-06 19:50:32 -0800599 createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
600 true /* translucent */);
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700601 final ActivityStack opaqueStack =
Andrii Kulian0c869cc2019-02-06 19:50:32 -0800602 createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
603 false /* translucent */);
604
605 assertEquals(STACK_VISIBILITY_INVISIBLE, bottomStack.getVisibility(null /* starting */));
606 assertEquals(STACK_VISIBILITY_INVISIBLE,
607 translucentStack.getVisibility(null /* starting */));
608 assertEquals(STACK_VISIBILITY_VISIBLE, opaqueStack.getVisibility(null /* starting */));
609 }
610
611 @Test
612 public void testGetVisibility_FullscreenBehindOpaqueAndTranslucent() {
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700613 final ActivityStack bottomStack =
Andrii Kulian0c869cc2019-02-06 19:50:32 -0800614 createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
615 false /* translucent */);
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700616 final ActivityStack opaqueStack =
Andrii Kulian0c869cc2019-02-06 19:50:32 -0800617 createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
618 false /* translucent */);
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700619 final ActivityStack translucentStack =
Andrii Kulian0c869cc2019-02-06 19:50:32 -0800620 createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
621 true /* translucent */);
622
623 assertEquals(STACK_VISIBILITY_INVISIBLE, bottomStack.getVisibility(null /* starting */));
624 assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
625 opaqueStack.getVisibility(null /* starting */));
626 assertEquals(STACK_VISIBILITY_VISIBLE,
627 translucentStack.getVisibility(null /* starting */));
628 }
629
630 @Test
631 public void testGetVisibility_FullscreenTranslucentBehindTranslucent() {
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700632 final ActivityStack bottomTranslucentStack =
Andrii Kulian0c869cc2019-02-06 19:50:32 -0800633 createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
634 true /* translucent */);
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700635 final ActivityStack translucentStack =
Andrii Kulian0c869cc2019-02-06 19:50:32 -0800636 createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
637 true /* translucent */);
638
639 assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
640 bottomTranslucentStack.getVisibility(null /* starting */));
641 assertEquals(STACK_VISIBILITY_VISIBLE,
642 translucentStack.getVisibility(null /* starting */));
643 }
644
645 @Test
646 public void testGetVisibility_FullscreenTranslucentBehindOpaque() {
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700647 final ActivityStack bottomTranslucentStack =
Andrii Kulian0c869cc2019-02-06 19:50:32 -0800648 createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
649 true /* translucent */);
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700650 final ActivityStack opaqueStack =
Andrii Kulian0c869cc2019-02-06 19:50:32 -0800651 createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
652 false /* translucent */);
653
654 assertEquals(STACK_VISIBILITY_INVISIBLE,
655 bottomTranslucentStack.getVisibility(null /* starting */));
656 assertEquals(STACK_VISIBILITY_VISIBLE, opaqueStack.getVisibility(null /* starting */));
657 }
658
659 @Test
660 public void testGetVisibility_FullscreenBehindTranslucentAndPip() {
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700661 final ActivityStack bottomStack =
Andrii Kulian0c869cc2019-02-06 19:50:32 -0800662 createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
663 false /* translucent */);
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700664 final ActivityStack translucentStack =
Andrii Kulian0c869cc2019-02-06 19:50:32 -0800665 createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
666 true /* translucent */);
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700667 final ActivityStack pinnedStack = createStackForShouldBeVisibleTest(mDefaultTaskDisplayArea,
Andrii Kulian0c869cc2019-02-06 19:50:32 -0800668 WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
669
670 assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
671 bottomStack.getVisibility(null /* starting */));
672 assertEquals(STACK_VISIBILITY_VISIBLE,
673 translucentStack.getVisibility(null /* starting */));
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700674 // Add an activity to the pinned stack so it isn't considered empty for visibility check.
675 final ActivityRecord pinnedActivity = new ActivityBuilder(mService)
676 .setCreateTask(true)
677 .setStack(pinnedStack)
678 .build();
Andrii Kulian0c869cc2019-02-06 19:50:32 -0800679 assertEquals(STACK_VISIBILITY_VISIBLE, pinnedStack.getVisibility(null /* starting */));
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700680 }
681
682 @Test
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900683 public void testShouldBeVisible_Finishing() {
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700684 final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultTaskDisplayArea,
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700685 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
Wale Ogunwale85fb19a2019-12-05 10:41:05 +0900686 ActivityRecord topRunningHomeActivity = homeStack.topRunningActivity();
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700687 if (topRunningHomeActivity == null) {
688 topRunningHomeActivity = new ActivityBuilder(mService)
689 .setStack(homeStack)
690 .setCreateTask(true)
691 .build();
692 }
693
694 final ActivityStack translucentStack = createStackForShouldBeVisibleTest(
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700695 mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
Winson Chung3e2980e2018-03-29 17:28:57 -0700696 true /* onTop */);
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800697 doReturn(true).when(translucentStack).isTranslucent(any());
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700698
699 assertTrue(homeStack.shouldBeVisible(null /* starting */));
700 assertTrue(translucentStack.shouldBeVisible(null /* starting */));
701
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700702 topRunningHomeActivity.finishing = true;
703 final ActivityRecord topRunningTranslucentActivity =
Wale Ogunwale85fb19a2019-12-05 10:41:05 +0900704 translucentStack.topRunningActivity();
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700705 topRunningTranslucentActivity.finishing = true;
706
Louis Changf2835df2018-10-17 15:14:45 +0800707 // Home stack should be visible even there are no running activities.
708 assertTrue(homeStack.shouldBeVisible(null /* starting */));
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700709 // Home should be visible if we are starting an activity within it.
710 assertTrue(homeStack.shouldBeVisible(topRunningHomeActivity /* starting */));
Louis Changf2835df2018-10-17 15:14:45 +0800711 // The translucent stack shouldn't be visible since its activity marked as finishing.
712 assertFalse(translucentStack.shouldBeVisible(null /* starting */));
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700713 }
714
Winson Chungd922b6b2018-02-16 16:41:50 -0800715 @Test
Jeff Chang24b0bf62019-12-19 19:15:07 +0800716 public void testShouldBeVisible_FullscreenBehindTranslucentInHomeStack() {
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700717 final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultTaskDisplayArea,
Jeff Chang24b0bf62019-12-19 19:15:07 +0800718 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
719
720 final ActivityRecord firstActivity = new ActivityBuilder(mService)
721 .setStack(homeStack)
722 .setCreateTask(true)
723 .build();
724 final Task task = firstActivity.getTask();
725 final ActivityRecord secondActivity = new ActivityBuilder(mService)
726 .setTask(task)
727 .build();
728
729 doReturn(false).when(secondActivity).occludesParent();
730 homeStack.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
731 false /* preserveWindows */);
732
733 assertTrue(firstActivity.shouldBeVisible());
734 }
735
736 @Test
Winson Chungd922b6b2018-02-16 16:41:50 -0800737 public void testMoveHomeStackBehindBottomMostVisibleStack_NoMoveHomeBehindFullscreen() {
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700738 mDefaultTaskDisplayArea.removeStack(mStack);
Winson Chungd922b6b2018-02-16 16:41:50 -0800739
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700740 final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultTaskDisplayArea,
Winson Chungd922b6b2018-02-16 16:41:50 -0800741 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700742 final ActivityStack fullscreenStack = createStackForShouldBeVisibleTest(
743 mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
744 true /* onTop */);
Winson Chungd922b6b2018-02-16 16:41:50 -0800745
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800746 doReturn(false).when(homeStack).isTranslucent(any());
747 doReturn(false).when(fullscreenStack).isTranslucent(any());
Winson Chungd922b6b2018-02-16 16:41:50 -0800748
749 // Ensure that we don't move the home stack if it is already behind the top fullscreen stack
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700750 int homeStackIndex = mDefaultTaskDisplayArea.getIndexOf(homeStack);
Andrii Kulian86d676c2020-03-27 19:34:54 -0700751 assertEquals(fullscreenStack, getStackAbove(homeStack));
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700752 mDefaultTaskDisplayArea.moveStackBehindBottomMostVisibleStack(homeStack);
753 assertEquals(homeStackIndex, mDefaultTaskDisplayArea.getIndexOf(homeStack));
Winson Chungd922b6b2018-02-16 16:41:50 -0800754 }
755
756 @Test
757 public void testMoveHomeStackBehindBottomMostVisibleStack_NoMoveHomeBehindTranslucent() {
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700758 mDefaultTaskDisplayArea.removeStack(mStack);
Winson Chungd922b6b2018-02-16 16:41:50 -0800759
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700760 final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultTaskDisplayArea,
Winson Chungd922b6b2018-02-16 16:41:50 -0800761 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700762 final ActivityStack fullscreenStack = createStackForShouldBeVisibleTest(
763 mDefaultTaskDisplayArea,
Winson Chungd922b6b2018-02-16 16:41:50 -0800764 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
765
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800766 doReturn(false).when(homeStack).isTranslucent(any());
767 doReturn(true).when(fullscreenStack).isTranslucent(any());
Winson Chungd922b6b2018-02-16 16:41:50 -0800768
769 // Ensure that we don't move the home stack if it is already behind the top fullscreen stack
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700770 int homeStackIndex = mDefaultTaskDisplayArea.getIndexOf(homeStack);
Andrii Kulian86d676c2020-03-27 19:34:54 -0700771 assertEquals(fullscreenStack, getStackAbove(homeStack));
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700772 mDefaultTaskDisplayArea.moveStackBehindBottomMostVisibleStack(homeStack);
773 assertEquals(homeStackIndex, mDefaultTaskDisplayArea.getIndexOf(homeStack));
Winson Chungd922b6b2018-02-16 16:41:50 -0800774 }
775
776 @Test
777 public void testMoveHomeStackBehindBottomMostVisibleStack_NoMoveHomeOnTop() {
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700778 mDefaultTaskDisplayArea.removeStack(mStack);
Winson Chungd922b6b2018-02-16 16:41:50 -0800779
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700780 final ActivityStack fullscreenStack = createStackForShouldBeVisibleTest(
781 mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
782 true /* onTop */);
783 final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultTaskDisplayArea,
Winson Chungd922b6b2018-02-16 16:41:50 -0800784 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
785
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800786 doReturn(false).when(homeStack).isTranslucent(any());
787 doReturn(false).when(fullscreenStack).isTranslucent(any());
Winson Chungd922b6b2018-02-16 16:41:50 -0800788
789 // Ensure we don't move the home stack if it is already on top
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700790 int homeStackIndex = mDefaultTaskDisplayArea.getIndexOf(homeStack);
Andrii Kulian86d676c2020-03-27 19:34:54 -0700791 assertNull(getStackAbove(homeStack));
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700792 mDefaultTaskDisplayArea.moveStackBehindBottomMostVisibleStack(homeStack);
793 assertEquals(homeStackIndex, mDefaultTaskDisplayArea.getIndexOf(homeStack));
Winson Chungd922b6b2018-02-16 16:41:50 -0800794 }
795
796 @Test
797 public void testMoveHomeStackBehindBottomMostVisibleStack_MoveHomeBehindFullscreen() {
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700798 mDefaultTaskDisplayArea.removeStack(mStack);
Winson Chungd922b6b2018-02-16 16:41:50 -0800799
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700800 final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultTaskDisplayArea,
Winson Chungd922b6b2018-02-16 16:41:50 -0800801 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700802 final ActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest(
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700803 mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
Winson Chung3e2980e2018-03-29 17:28:57 -0700804 true /* onTop */);
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700805 final ActivityStack fullscreenStack2 = createStackForShouldBeVisibleTest(
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700806 mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
Winson Chung3e2980e2018-03-29 17:28:57 -0700807 true /* onTop */);
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700808 final ActivityStack pinnedStack = createStackForShouldBeVisibleTest(mDefaultTaskDisplayArea,
Winson Chungd922b6b2018-02-16 16:41:50 -0800809 WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
810
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800811 doReturn(false).when(homeStack).isTranslucent(any());
812 doReturn(false).when(fullscreenStack1).isTranslucent(any());
813 doReturn(false).when(fullscreenStack2).isTranslucent(any());
Winson Chungd922b6b2018-02-16 16:41:50 -0800814
815 // Ensure that we move the home stack behind the bottom most fullscreen stack, ignoring the
816 // pinned stack
Andrii Kulian86d676c2020-03-27 19:34:54 -0700817 assertEquals(fullscreenStack1, getStackAbove(homeStack));
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700818 mDefaultTaskDisplayArea.moveStackBehindBottomMostVisibleStack(homeStack);
Andrii Kulian86d676c2020-03-27 19:34:54 -0700819 assertEquals(fullscreenStack2, getStackAbove(homeStack));
Winson Chungd922b6b2018-02-16 16:41:50 -0800820 }
821
822 @Test
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900823 public void
824 testMoveHomeStackBehindBottomMostVisibleStack_MoveHomeBehindFullscreenAndTranslucent() {
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700825 mDefaultTaskDisplayArea.removeStack(mStack);
Winson Chungd922b6b2018-02-16 16:41:50 -0800826
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700827 final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultTaskDisplayArea,
Winson Chungd922b6b2018-02-16 16:41:50 -0800828 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700829 final ActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest(
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700830 mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
Winson Chung3e2980e2018-03-29 17:28:57 -0700831 true /* onTop */);
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700832 final ActivityStack fullscreenStack2 = createStackForShouldBeVisibleTest(
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700833 mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
Winson Chung3e2980e2018-03-29 17:28:57 -0700834 true /* onTop */);
Winson Chungd922b6b2018-02-16 16:41:50 -0800835
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800836 doReturn(false).when(homeStack).isTranslucent(any());
837 doReturn(false).when(fullscreenStack1).isTranslucent(any());
838 doReturn(true).when(fullscreenStack2).isTranslucent(any());
Winson Chungd922b6b2018-02-16 16:41:50 -0800839
840 // Ensure that we move the home stack behind the bottom most non-translucent fullscreen
841 // stack
Andrii Kulian86d676c2020-03-27 19:34:54 -0700842 assertEquals(fullscreenStack1, getStackAbove(homeStack));
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700843 mDefaultTaskDisplayArea.moveStackBehindBottomMostVisibleStack(homeStack);
Andrii Kulian86d676c2020-03-27 19:34:54 -0700844 assertEquals(fullscreenStack1, getStackAbove(homeStack));
Winson Chungd922b6b2018-02-16 16:41:50 -0800845 }
846
847 @Test
848 public void testMoveHomeStackBehindStack_BehindHomeStack() {
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700849 mDefaultTaskDisplayArea.removeStack(mStack);
Winson Chungd922b6b2018-02-16 16:41:50 -0800850
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700851 final ActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest(
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700852 mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
Winson Chung3e2980e2018-03-29 17:28:57 -0700853 true /* onTop */);
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700854 final ActivityStack fullscreenStack2 = createStackForShouldBeVisibleTest(
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700855 mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
Winson Chung3e2980e2018-03-29 17:28:57 -0700856 true /* onTop */);
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700857 final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultTaskDisplayArea,
Winson Chungd922b6b2018-02-16 16:41:50 -0800858 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
859
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800860 doReturn(false).when(homeStack).isTranslucent(any());
861 doReturn(false).when(fullscreenStack1).isTranslucent(any());
862 doReturn(false).when(fullscreenStack2).isTranslucent(any());
Winson Chungd922b6b2018-02-16 16:41:50 -0800863
864 // Ensure we don't move the home stack behind itself
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700865 int homeStackIndex = mDefaultTaskDisplayArea.getIndexOf(homeStack);
866 mDefaultTaskDisplayArea.moveStackBehindStack(homeStack, homeStack);
867 assertEquals(homeStackIndex, mDefaultTaskDisplayArea.getIndexOf(homeStack));
Winson Chungd922b6b2018-02-16 16:41:50 -0800868 }
869
870 @Test
871 public void testMoveHomeStackBehindStack() {
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700872 mDefaultTaskDisplayArea.removeStack(mStack);
Winson Chungd922b6b2018-02-16 16:41:50 -0800873
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700874 final ActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest(
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700875 mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
Winson Chung3e2980e2018-03-29 17:28:57 -0700876 true /* onTop */);
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700877 final ActivityStack fullscreenStack2 = createStackForShouldBeVisibleTest(
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700878 mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
Winson Chung3e2980e2018-03-29 17:28:57 -0700879 true /* onTop */);
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700880 final ActivityStack fullscreenStack3 = createStackForShouldBeVisibleTest(
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700881 mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
Winson Chung3e2980e2018-03-29 17:28:57 -0700882 true /* onTop */);
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700883 final ActivityStack fullscreenStack4 = createStackForShouldBeVisibleTest(
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700884 mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
Winson Chung3e2980e2018-03-29 17:28:57 -0700885 true /* onTop */);
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700886 final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultTaskDisplayArea,
Winson Chungd922b6b2018-02-16 16:41:50 -0800887 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
888
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700889 mDefaultTaskDisplayArea.moveStackBehindStack(homeStack, fullscreenStack1);
Andrii Kulian86d676c2020-03-27 19:34:54 -0700890 assertEquals(fullscreenStack1, getStackAbove(homeStack));
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700891 mDefaultTaskDisplayArea.moveStackBehindStack(homeStack, fullscreenStack2);
Andrii Kulian86d676c2020-03-27 19:34:54 -0700892 assertEquals(fullscreenStack2, getStackAbove(homeStack));
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700893 mDefaultTaskDisplayArea.moveStackBehindStack(homeStack, fullscreenStack4);
Andrii Kulian86d676c2020-03-27 19:34:54 -0700894 assertEquals(fullscreenStack4, getStackAbove(homeStack));
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700895 mDefaultTaskDisplayArea.moveStackBehindStack(homeStack, fullscreenStack2);
Andrii Kulian86d676c2020-03-27 19:34:54 -0700896 assertEquals(fullscreenStack2, getStackAbove(homeStack));
Winson Chungd922b6b2018-02-16 16:41:50 -0800897 }
898
Wale Ogunwalebb285872018-03-01 13:05:30 -0800899 @Test
Kazuki Takisef85197b2018-06-18 18:18:36 +0900900 public void testSetAlwaysOnTop() {
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700901 final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultTaskDisplayArea,
Kazuki Takisef85197b2018-06-18 18:18:36 +0900902 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700903 final ActivityStack pinnedStack = createStackForShouldBeVisibleTest(mDefaultTaskDisplayArea,
Kazuki Takisef85197b2018-06-18 18:18:36 +0900904 WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
Andrii Kulian86d676c2020-03-27 19:34:54 -0700905 assertEquals(pinnedStack, getStackAbove(homeStack));
Kazuki Takisef85197b2018-06-18 18:18:36 +0900906
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700907 final ActivityStack alwaysOnTopStack = createStackForShouldBeVisibleTest(
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700908 mDefaultTaskDisplayArea, WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD,
Kazuki Takisef85197b2018-06-18 18:18:36 +0900909 true /* onTop */);
910 alwaysOnTopStack.setAlwaysOnTop(true);
911 assertTrue(alwaysOnTopStack.isAlwaysOnTop());
912 // Ensure (non-pinned) always on top stack is put below pinned stack.
Andrii Kulian86d676c2020-03-27 19:34:54 -0700913 assertEquals(pinnedStack, getStackAbove(alwaysOnTopStack));
Kazuki Takisef85197b2018-06-18 18:18:36 +0900914
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700915 final ActivityStack nonAlwaysOnTopStack = createStackForShouldBeVisibleTest(
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700916 mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
Kazuki Takisef85197b2018-06-18 18:18:36 +0900917 true /* onTop */);
918 // Ensure non always on top stack is put below always on top stacks.
Andrii Kulian86d676c2020-03-27 19:34:54 -0700919 assertEquals(alwaysOnTopStack, getStackAbove(nonAlwaysOnTopStack));
Kazuki Takisef85197b2018-06-18 18:18:36 +0900920
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700921 final ActivityStack alwaysOnTopStack2 = createStackForShouldBeVisibleTest(
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700922 mDefaultTaskDisplayArea, WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD,
Kazuki Takisef85197b2018-06-18 18:18:36 +0900923 true /* onTop */);
924 alwaysOnTopStack2.setAlwaysOnTop(true);
925 assertTrue(alwaysOnTopStack2.isAlwaysOnTop());
926 // Ensure newly created always on top stack is placed above other all always on top stacks.
Andrii Kulian86d676c2020-03-27 19:34:54 -0700927 assertEquals(pinnedStack, getStackAbove(alwaysOnTopStack2));
Kazuki Takisef85197b2018-06-18 18:18:36 +0900928
929 alwaysOnTopStack2.setAlwaysOnTop(false);
930 // Ensure, when always on top is turned off for a stack, the stack is put just below all
931 // other always on top stacks.
Andrii Kulian86d676c2020-03-27 19:34:54 -0700932 assertEquals(alwaysOnTopStack, getStackAbove(alwaysOnTopStack2));
Kazuki Takise048e2662018-06-27 17:05:11 +0900933 alwaysOnTopStack2.setAlwaysOnTop(true);
934
935 // Ensure always on top state changes properly when windowing mode changes.
936 alwaysOnTopStack2.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
937 assertFalse(alwaysOnTopStack2.isAlwaysOnTop());
Andrii Kulian86d676c2020-03-27 19:34:54 -0700938 assertEquals(alwaysOnTopStack, getStackAbove(alwaysOnTopStack2));
Kazuki Takise048e2662018-06-27 17:05:11 +0900939 alwaysOnTopStack2.setWindowingMode(WINDOWING_MODE_FREEFORM);
940 assertTrue(alwaysOnTopStack2.isAlwaysOnTop());
Andrii Kulian86d676c2020-03-27 19:34:54 -0700941 assertEquals(pinnedStack, getStackAbove(alwaysOnTopStack2));
Kazuki Takisef85197b2018-06-18 18:18:36 +0900942 }
943
944 @Test
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900945 public void testSplitScreenMoveToFront() {
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700946 final ActivityStack splitScreenPrimary = createStackForShouldBeVisibleTest(
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700947 mDefaultTaskDisplayArea, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY,
948 ACTIVITY_TYPE_STANDARD, true /* onTop */);
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700949 final ActivityStack splitScreenSecondary = createStackForShouldBeVisibleTest(
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700950 mDefaultTaskDisplayArea, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY,
951 ACTIVITY_TYPE_STANDARD, true /* onTop */);
952 final ActivityStack assistantStack = createStackForShouldBeVisibleTest(
953 mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_ASSISTANT,
Winson Chung3e2980e2018-03-29 17:28:57 -0700954 true /* onTop */);
Wale Ogunwalebb285872018-03-01 13:05:30 -0800955
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800956 doReturn(false).when(splitScreenPrimary).isTranslucent(any());
957 doReturn(false).when(splitScreenSecondary).isTranslucent(any());
958 doReturn(false).when(assistantStack).isTranslucent(any());
Wale Ogunwalebb285872018-03-01 13:05:30 -0800959
960 assertFalse(splitScreenPrimary.shouldBeVisible(null /* starting */));
961 assertFalse(splitScreenSecondary.shouldBeVisible(null /* starting */));
962 assertTrue(assistantStack.shouldBeVisible(null /* starting */));
963
964 splitScreenSecondary.moveToFront("testSplitScreenMoveToFront");
965
Galia Peycheva7ecd6ef2020-03-26 19:59:40 +0100966 if (isAssistantOnTop()) {
967 assertFalse(splitScreenPrimary.shouldBeVisible(null /* starting */));
968 assertFalse(splitScreenSecondary.shouldBeVisible(null /* starting */));
969 assertTrue(assistantStack.shouldBeVisible(null /* starting */));
970 } else {
971 assertTrue(splitScreenPrimary.shouldBeVisible(null /* starting */));
972 assertTrue(splitScreenSecondary.shouldBeVisible(null /* starting */));
973 assertFalse(assistantStack.shouldBeVisible(null /* starting */));
974 }
Wale Ogunwalebb285872018-03-01 13:05:30 -0800975 }
976
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700977 private ActivityStack createStandardStackForVisibilityTest(int windowingMode,
Andrii Kulian0c869cc2019-02-06 19:50:32 -0800978 boolean translucent) {
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700979 final ActivityStack stack = createStackForShouldBeVisibleTest(mDefaultTaskDisplayArea,
Andrii Kulian0c869cc2019-02-06 19:50:32 -0800980 windowingMode, ACTIVITY_TYPE_STANDARD, true /* onTop */);
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800981 doReturn(translucent).when(stack).isTranslucent(any());
Andrii Kulian0c869cc2019-02-06 19:50:32 -0800982 return stack;
983 }
984
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900985 @SuppressWarnings("TypeParameterUnusedInFormals")
Louis Chang2453d062019-11-19 22:30:48 +0800986 private ActivityStack createStackForShouldBeVisibleTest(
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700987 TaskDisplayArea taskDisplayArea, int windowingMode, int activityType, boolean onTop) {
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700988 final ActivityStack stack;
Andrii Kulian6a6c4f12018-07-16 21:23:33 -0700989 if (activityType == ACTIVITY_TYPE_HOME) {
990 // Home stack and activity are created in ActivityTestsBase#setupActivityManagerService
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700991 stack = mDefaultTaskDisplayArea.getStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME);
Andrii Kulian6a6c4f12018-07-16 21:23:33 -0700992 if (onTop) {
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700993 mDefaultTaskDisplayArea.positionStackAtTop(stack,
Andrii Kulian9ea12da2020-03-27 17:16:38 -0700994 false /* includingParents */);
Andrii Kulian6a6c4f12018-07-16 21:23:33 -0700995 } else {
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700996 mDefaultTaskDisplayArea.positionStackAtBottom(stack);
Andrii Kulian6a6c4f12018-07-16 21:23:33 -0700997 }
998 } else {
Louis Chang149d5c82019-12-30 09:47:39 +0800999 stack = new StackBuilder(mRootWindowContainer)
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -07001000 .setTaskDisplayArea(taskDisplayArea)
Wale Ogunwale8a1860a2019-06-05 08:57:19 -07001001 .setWindowingMode(windowingMode)
1002 .setActivityType(activityType)
1003 .setOnTop(onTop)
1004 .setCreateActivity(true)
1005 .build();
Andrii Kulian6a6c4f12018-07-16 21:23:33 -07001006 }
Louis Chang2453d062019-11-19 22:30:48 +08001007 return stack;
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -07001008 }
Bryce Leeb0f993f2018-03-02 15:38:01 -08001009
1010 @Test
Riddle Hsuaaef7312019-01-24 19:00:58 +08001011 public void testFinishDisabledPackageActivities_FinishAliveActivities() {
Bryce Leefbd263b42018-03-07 10:33:55 -08001012 final ActivityRecord firstActivity = new ActivityBuilder(mService).setTask(mTask).build();
1013 final ActivityRecord secondActivity = new ActivityBuilder(mService).setTask(mTask).build();
Riddle Hsuaaef7312019-01-24 19:00:58 +08001014 firstActivity.setState(STOPPED, "testFinishDisabledPackageActivities");
1015 secondActivity.setState(RESUMED, "testFinishDisabledPackageActivities");
1016 mStack.mResumedActivity = secondActivity;
Bryce Leefbd263b42018-03-07 10:33:55 -08001017
Riddle Hsuaaef7312019-01-24 19:00:58 +08001018 // Note the activities have non-null ActivityRecord.app, so it won't remove directly.
Louis Chang149d5c82019-12-30 09:47:39 +08001019 mRootWindowContainer.mFinishDisabledPackageActivitiesHelper.process(
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001020 firstActivity.packageName, null /* filterByClasses */, true /* doit */,
1021 true /* evenPersistent */, UserHandle.USER_ALL);
Riddle Hsuaaef7312019-01-24 19:00:58 +08001022
1023 // If the activity is disabled with {@link android.content.pm.PackageManager#DONT_KILL_APP}
1024 // the activity should still follow the normal flow to finish and destroy.
1025 assertThat(firstActivity.getState()).isEqualTo(DESTROYING);
1026 assertThat(secondActivity.getState()).isEqualTo(PAUSING);
1027 assertTrue(secondActivity.finishing);
1028 }
1029
1030 @Test
1031 public void testFinishDisabledPackageActivities_RemoveNonAliveActivities() {
1032 final ActivityRecord activity = new ActivityBuilder(mService).setTask(mTask).build();
1033
1034 // The overlay activity is not in the disabled package but it is in the same task.
1035 final ActivityRecord overlayActivity = new ActivityBuilder(mService).setTask(mTask)
1036 .setComponent(new ComponentName("package.overlay", ".OverlayActivity")).build();
1037 // If the task only remains overlay activity, the task should also be removed.
Andrii Kulian79d67982019-08-19 11:56:16 -07001038 // See {@link ActivityStack#removeFromHistory}.
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08001039 overlayActivity.setTaskOverlay(true);
Riddle Hsuaaef7312019-01-24 19:00:58 +08001040
1041 // The activity without an app means it will be removed immediately.
1042 // See {@link ActivityStack#destroyActivityLocked}.
1043 activity.app = null;
1044 overlayActivity.app = null;
Bryce Leefbd263b42018-03-07 10:33:55 -08001045
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001046 assertEquals(2, mTask.getChildCount());
Bryce Leefbd263b42018-03-07 10:33:55 -08001047
Louis Chang149d5c82019-12-30 09:47:39 +08001048 mRootWindowContainer.mFinishDisabledPackageActivitiesHelper.process(
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001049 activity.packageName, null /* filterByClasses */, true /* doit */,
1050 true /* evenPersistent */, UserHandle.USER_ALL);
Bryce Leefbd263b42018-03-07 10:33:55 -08001051
Riddle Hsuaaef7312019-01-24 19:00:58 +08001052 // Although the overlay activity is in another package, the non-overlay activities are
1053 // removed from the task. Since the overlay activity should be removed as well, the task
1054 // should be empty.
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001055 assertFalse(mTask.hasChild());
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001056 assertFalse(mStack.hasChild());
Bryce Leefbd263b42018-03-07 10:33:55 -08001057 }
1058
1059 @Test
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +09001060 public void testHandleAppDied() {
Bryce Leefbd263b42018-03-07 10:33:55 -08001061 final ActivityRecord firstActivity = new ActivityBuilder(mService).setTask(mTask).build();
1062 final ActivityRecord secondActivity = new ActivityBuilder(mService).setTask(mTask).build();
1063
1064 // Making the first activity a task overlay means it will be removed from the task's
1065 // activities as well once second activity is removed as handleAppDied processes the
1066 // activity list in reverse.
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08001067 firstActivity.setTaskOverlay(true);
Bryce Leefbd263b42018-03-07 10:33:55 -08001068 firstActivity.app = null;
1069
1070 // second activity will be immediately removed as it has no state.
Andrii Kulian06b8dcb2019-07-10 21:09:38 -07001071 secondActivity.setSavedState(null /* savedState */);
Bryce Leefbd263b42018-03-07 10:33:55 -08001072
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001073 assertEquals(2, mTask.getChildCount());
Bryce Leefbd263b42018-03-07 10:33:55 -08001074
Louis Chang149d5c82019-12-30 09:47:39 +08001075 mRootWindowContainer.handleAppDied(secondActivity.app);
Bryce Leefbd263b42018-03-07 10:33:55 -08001076
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001077 assertFalse(mTask.hasChild());
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001078 assertFalse(mStack.hasChild());
Bryce Leefbd263b42018-03-07 10:33:55 -08001079 }
Bryce Lee271617a2018-03-15 10:39:12 -07001080
1081 @Test
Garfield Tanf6cc5c92019-01-15 13:54:12 -08001082 public void testHandleAppDied_RelaunchesAfterCrashDuringWindowingModeResize() {
1083 final ActivityRecord activity = new ActivityBuilder(mService).setTask(mTask).build();
1084
1085 activity.mRelaunchReason = RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
1086 activity.launchCount = 1;
Andrii Kulian06b8dcb2019-07-10 21:09:38 -07001087 activity.setSavedState(null /* savedState */);
Garfield Tanf6cc5c92019-01-15 13:54:12 -08001088
Louis Chang149d5c82019-12-30 09:47:39 +08001089 mRootWindowContainer.handleAppDied(activity.app);
Garfield Tanf6cc5c92019-01-15 13:54:12 -08001090
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001091 assertEquals(1, mTask.getChildCount());
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001092 assertEquals(1, mStack.getChildCount());
Garfield Tanf6cc5c92019-01-15 13:54:12 -08001093 }
1094
1095 @Test
1096 public void testHandleAppDied_NotRelaunchAfterThreeCrashesDuringWindowingModeResize() {
1097 final ActivityRecord activity = new ActivityBuilder(mService).setTask(mTask).build();
1098
1099 activity.mRelaunchReason = RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
1100 activity.launchCount = 3;
Andrii Kulian06b8dcb2019-07-10 21:09:38 -07001101 activity.setSavedState(null /* savedState */);
Garfield Tanf6cc5c92019-01-15 13:54:12 -08001102
Louis Chang149d5c82019-12-30 09:47:39 +08001103 mRootWindowContainer.handleAppDied(activity.app);
Garfield Tanf6cc5c92019-01-15 13:54:12 -08001104
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001105 assertFalse(mTask.hasChild());
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001106 assertFalse(mStack.hasChild());
Garfield Tanf6cc5c92019-01-15 13:54:12 -08001107 }
1108
1109 @Test
1110 public void testHandleAppDied_RelaunchesAfterCrashDuringFreeResize() {
1111 final ActivityRecord activity = new ActivityBuilder(mService).setTask(mTask).build();
1112
1113 activity.mRelaunchReason = RELAUNCH_REASON_FREE_RESIZE;
1114 activity.launchCount = 1;
Andrii Kulian06b8dcb2019-07-10 21:09:38 -07001115 activity.setSavedState(null /* savedState */);
Garfield Tanf6cc5c92019-01-15 13:54:12 -08001116
Louis Chang149d5c82019-12-30 09:47:39 +08001117 mRootWindowContainer.handleAppDied(activity.app);
Garfield Tanf6cc5c92019-01-15 13:54:12 -08001118
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001119 assertEquals(1, mTask.getChildCount());
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001120 assertEquals(1, mStack.getChildCount());
Garfield Tanf6cc5c92019-01-15 13:54:12 -08001121 }
1122
1123 @Test
1124 public void testHandleAppDied_NotRelaunchAfterThreeCrashesDuringFreeResize() {
1125 final ActivityRecord activity = new ActivityBuilder(mService).setTask(mTask).build();
1126
1127 activity.mRelaunchReason = RELAUNCH_REASON_FREE_RESIZE;
1128 activity.launchCount = 3;
Andrii Kulian06b8dcb2019-07-10 21:09:38 -07001129 activity.setSavedState(null /* savedState */);
Garfield Tanf6cc5c92019-01-15 13:54:12 -08001130
Louis Chang149d5c82019-12-30 09:47:39 +08001131 mRootWindowContainer.handleAppDied(activity.app);
Garfield Tanf6cc5c92019-01-15 13:54:12 -08001132
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001133 assertFalse(mTask.hasChild());
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001134 assertFalse(mStack.hasChild());
Garfield Tanf6cc5c92019-01-15 13:54:12 -08001135 }
1136
1137 @Test
Louis Chang7b03ad92019-08-21 12:32:33 +08001138 public void testCompletePauseOnResumeWhilePausingActivity() {
1139 final ActivityRecord bottomActivity = new ActivityBuilder(mService).setTask(mTask).build();
1140 doReturn(true).when(bottomActivity).attachedToProcess();
1141 mStack.mPausingActivity = null;
1142 mStack.mResumedActivity = bottomActivity;
1143 final ActivityRecord topActivity = new ActivityBuilder(mService).setTask(mTask).build();
1144 topActivity.info.flags |= FLAG_RESUME_WHILE_PAUSING;
1145
1146 mStack.startPausingLocked(false /* userLeaving */, false /* uiSleeping */, topActivity);
1147 verify(mStack).completePauseLocked(anyBoolean(), eq(topActivity));
1148 }
1149
1150 @Test
wilsonshih8824a8a2019-03-12 17:21:35 +08001151 public void testWontFinishHomeStackImmediately() {
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -07001152 final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultTaskDisplayArea,
wilsonshih8824a8a2019-03-12 17:21:35 +08001153 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
1154
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001155 ActivityRecord activity = homeStack.topRunningActivity();
Wale Ogunwale8a1860a2019-06-05 08:57:19 -07001156 if (activity == null) {
1157 activity = new ActivityBuilder(mService)
1158 .setStack(homeStack)
1159 .setCreateTask(true)
1160 .build();
1161 }
1162
wilsonshih8824a8a2019-03-12 17:21:35 +08001163 // Home stack should not be destroyed immediately.
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07001164 final ActivityRecord activity1 = finishTopActivity(homeStack);
wilsonshih8824a8a2019-03-12 17:21:35 +08001165 assertEquals(FINISHING, activity1.getState());
1166 }
1167
1168 @Test
Riddle Hsue10cea52018-10-16 23:33:23 +08001169 public void testFinishCurrentActivity() {
1170 // Create 2 activities on a new display.
Louis Chang677921f2019-12-06 16:44:24 +08001171 final DisplayContent display = addNewDisplayContentAt(DisplayContent.POSITION_TOP);
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -07001172 final ActivityStack stack1 = createStackForShouldBeVisibleTest(
1173 display.getDefaultTaskDisplayArea(),
Riddle Hsue10cea52018-10-16 23:33:23 +08001174 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -07001175 final ActivityStack stack2 = createStackForShouldBeVisibleTest(
1176 display.getDefaultTaskDisplayArea(),
Riddle Hsue10cea52018-10-16 23:33:23 +08001177 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
1178
1179 // There is still an activity1 in stack1 so the activity2 should be added to finishing list
1180 // that will be destroyed until idle.
Issei Suzuki1669ea42019-11-06 14:20:59 +01001181 stack2.getTopNonFinishingActivity().mVisibleRequested = true;
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07001182 final ActivityRecord activity2 = finishTopActivity(stack2);
Louis Changf2835df2018-10-17 15:14:45 +08001183 assertEquals(STOPPING, activity2.getState());
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +09001184 assertThat(mSupervisor.mStoppingActivities).contains(activity2);
Riddle Hsue10cea52018-10-16 23:33:23 +08001185
1186 // The display becomes empty. Since there is no next activity to be idle, the activity
1187 // should be destroyed immediately with updating configuration to restore original state.
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07001188 final ActivityRecord activity1 = finishTopActivity(stack1);
Riddle Hsue10cea52018-10-16 23:33:23 +08001189 assertEquals(DESTROYING, activity1.getState());
Louis Chang149d5c82019-12-30 09:47:39 +08001190 verify(mRootWindowContainer).ensureVisibilityAndConfig(eq(null) /* starting */,
Riddle Hsue10cea52018-10-16 23:33:23 +08001191 eq(display.mDisplayId), anyBoolean(), anyBoolean());
1192 }
1193
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07001194 private ActivityRecord finishTopActivity(ActivityStack stack) {
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001195 final ActivityRecord activity = stack.topRunningActivity();
Riddle Hsue10cea52018-10-16 23:33:23 +08001196 assertNotNull(activity);
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07001197 activity.setState(STOPPED, "finishTopActivity");
Riddle Hsue10cea52018-10-16 23:33:23 +08001198 activity.makeFinishingLocked();
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07001199 activity.completeFinishing("finishTopActivity");
Riddle Hsue10cea52018-10-16 23:33:23 +08001200 return activity;
1201 }
1202
1203 @Test
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +09001204 public void testShouldSleepActivities() {
Bryce Lee271617a2018-03-15 10:39:12 -07001205 // When focused activity and keyguard is going away, we should not sleep regardless
1206 // of the display state
1207 verifyShouldSleepActivities(true /* focusedStack */, true /*keyguardGoingAway*/,
1208 true /* displaySleeping */, false /* expected*/);
1209
1210 // When not the focused stack, defer to display sleeping state.
1211 verifyShouldSleepActivities(false /* focusedStack */, true /*keyguardGoingAway*/,
1212 true /* displaySleeping */, true /* expected*/);
1213
1214 // If keyguard is going away, defer to the display sleeping state.
1215 verifyShouldSleepActivities(true /* focusedStack */, false /*keyguardGoingAway*/,
1216 true /* displaySleeping */, true /* expected*/);
1217 verifyShouldSleepActivities(true /* focusedStack */, false /*keyguardGoingAway*/,
1218 false /* displaySleeping */, false /* expected*/);
1219 }
1220
Winson Chung0f7ec962018-05-03 18:03:15 -07001221 @Test
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +09001222 public void testStackOrderChangedOnRemoveStack() {
Winson Chung0f7ec962018-05-03 18:03:15 -07001223 StackOrderChangedListener listener = new StackOrderChangedListener();
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -07001224 mDefaultTaskDisplayArea.registerStackOrderChangedListener(listener);
Winson Chung0f7ec962018-05-03 18:03:15 -07001225 try {
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -07001226 mDefaultTaskDisplayArea.removeStack(mStack);
Winson Chung0f7ec962018-05-03 18:03:15 -07001227 } finally {
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -07001228 mDefaultTaskDisplayArea.unregisterStackOrderChangedListener(listener);
Winson Chung0f7ec962018-05-03 18:03:15 -07001229 }
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +09001230 assertTrue(listener.mChanged);
Winson Chung0f7ec962018-05-03 18:03:15 -07001231 }
1232
1233 @Test
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +09001234 public void testStackOrderChangedOnAddPositionStack() {
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -07001235 mDefaultTaskDisplayArea.removeStack(mStack);
Winson Chung0f7ec962018-05-03 18:03:15 -07001236
1237 StackOrderChangedListener listener = new StackOrderChangedListener();
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -07001238 mDefaultTaskDisplayArea.registerStackOrderChangedListener(listener);
Winson Chung0f7ec962018-05-03 18:03:15 -07001239 try {
Louis Chang677921f2019-12-06 16:44:24 +08001240 mStack.mReparenting = true;
Vishnu Nair7c8a2472020-04-17 16:08:29 -07001241 mDefaultTaskDisplayArea.addChild(mStack, 0);
Winson Chung0f7ec962018-05-03 18:03:15 -07001242 } finally {
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -07001243 mDefaultTaskDisplayArea.unregisterStackOrderChangedListener(listener);
Winson Chung0f7ec962018-05-03 18:03:15 -07001244 }
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +09001245 assertTrue(listener.mChanged);
Winson Chung0f7ec962018-05-03 18:03:15 -07001246 }
1247
1248 @Test
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +09001249 public void testStackOrderChangedOnPositionStack() {
Winson Chung0f7ec962018-05-03 18:03:15 -07001250 StackOrderChangedListener listener = new StackOrderChangedListener();
1251 try {
Wale Ogunwale8a1860a2019-06-05 08:57:19 -07001252 final ActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest(
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -07001253 mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
Winson Chung0f7ec962018-05-03 18:03:15 -07001254 true /* onTop */);
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -07001255 mDefaultTaskDisplayArea.registerStackOrderChangedListener(listener);
1256 mDefaultTaskDisplayArea.positionStackAtBottom(fullscreenStack1);
Winson Chung0f7ec962018-05-03 18:03:15 -07001257 } finally {
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -07001258 mDefaultTaskDisplayArea.unregisterStackOrderChangedListener(listener);
Winson Chung0f7ec962018-05-03 18:03:15 -07001259 }
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +09001260 assertTrue(listener.mChanged);
Winson Chung0f7ec962018-05-03 18:03:15 -07001261 }
1262
Louis Changf7f7f9c2019-06-18 16:47:51 +08001263 @Test
Riddle Hsu8e5f6d22020-02-07 00:15:57 +08001264 public void testNavigateUpTo() {
1265 final ActivityStartController controller = mock(ActivityStartController.class);
1266 final ActivityStarter starter = new ActivityStarter(controller,
1267 mService, mService.mStackSupervisor, mock(ActivityStartInterceptor.class));
1268 doReturn(controller).when(mService).getActivityStartController();
1269 spyOn(starter);
1270 doReturn(ActivityManager.START_SUCCESS).when(starter).execute();
1271
1272 final ActivityRecord firstActivity = new ActivityBuilder(mService).setTask(mTask).build();
1273 final ActivityRecord secondActivity = new ActivityBuilder(mService).setTask(mTask)
1274 .setUid(firstActivity.getUid() + 1).build();
1275 doReturn(starter).when(controller).obtainStarter(eq(firstActivity.intent), anyString());
1276
1277 final IApplicationThread thread = secondActivity.app.getThread();
1278 secondActivity.app.setThread(null);
1279 // This should do nothing from a non-attached caller.
1280 assertFalse(mStack.navigateUpTo(secondActivity /* source record */,
1281 firstActivity.intent /* destIntent */, 0 /* resultCode */, null /* resultData */));
1282
1283 secondActivity.app.setThread(thread);
1284 assertTrue(mStack.navigateUpTo(secondActivity /* source record */,
1285 firstActivity.intent /* destIntent */, 0 /* resultCode */, null /* resultData */));
1286 // The firstActivity uses default launch mode, so the activities between it and itself will
1287 // be finished.
1288 assertTrue(secondActivity.finishing);
1289 assertTrue(firstActivity.finishing);
1290 // The caller uid of the new activity should be the current real caller.
1291 assertEquals(starter.mRequest.callingUid, secondActivity.getUid());
1292 }
1293
1294 @Test
Jeff Chang59db8992020-04-22 20:27:46 +08001295 public void testShouldUpRecreateTaskLockedWithCorrectAffinityFormat() {
1296 final String affinity = "affinity";
1297 final ActivityRecord activity = new ActivityBuilder(mService).setAffinity(affinity)
1298 .setUid(Binder.getCallingUid()).setCreateTask(true).build();
1299 activity.getTask().affinity = activity.taskAffinity;
1300
1301 assertFalse(mStack.shouldUpRecreateTaskLocked(activity, affinity));
1302 }
1303
1304 @Test
1305 public void testShouldUpRecreateTaskLockedWithWrongAffinityFormat() {
1306 final String affinity = "affinity";
1307 final ActivityRecord activity = new ActivityBuilder(mService).setAffinity(affinity)
1308 .setUid(Binder.getCallingUid()).setCreateTask(true).build();
1309 activity.getTask().affinity = activity.taskAffinity;
1310 final String fakeAffinity = activity.getUid() + activity.taskAffinity;
1311
1312 assertTrue(mStack.shouldUpRecreateTaskLocked(activity, fakeAffinity));
1313 }
1314
1315 @Test
Louis Changf7f7f9c2019-06-18 16:47:51 +08001316 public void testResetTaskWithFinishingActivities() {
1317 final ActivityRecord taskTop =
1318 new ActivityBuilder(mService).setStack(mStack).setCreateTask(true).build();
Louis Changcdec0802019-11-11 11:45:07 +08001319 // Make all activities in the task are finishing to simulate Task#getTopActivity
Louis Changf7f7f9c2019-06-18 16:47:51 +08001320 // returns null.
1321 taskTop.finishing = true;
1322
1323 final ActivityRecord newR = new ActivityBuilder(mService).build();
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001324 final ActivityRecord result = mStack.resetTaskIfNeeded(taskTop, newR);
Louis Changf7f7f9c2019-06-18 16:47:51 +08001325 assertThat(result).isEqualTo(taskTop);
1326 }
1327
Louis Changcfe46212019-07-30 10:34:18 +08001328 @Test
Louis Chang99d6f0e2020-02-21 12:14:32 +08001329 public void testCheckBehindFullscreenActivity() {
1330 final ActivityRecord bottomActivity =
1331 new ActivityBuilder(mService).setStack(mStack).setTask(mTask).build();
1332 final ActivityRecord topActivity =
1333 new ActivityBuilder(mService).setStack(mStack).setTask(mTask).build();
1334 doReturn(true).when(mStack).shouldBeVisible(any());
1335 assertTrue(mStack.checkBehindFullscreenActivity(bottomActivity,
1336 null /* handleBehindFullscreenActivity */));
1337 assertFalse(mStack.checkBehindFullscreenActivity(topActivity,
1338 null /* handleBehindFullscreenActivity */));
1339
1340 doReturn(false).when(topActivity).occludesParent();
1341 assertFalse(mStack.checkBehindFullscreenActivity(bottomActivity,
1342 null /* handleBehindFullscreenActivity */));
1343 assertFalse(mStack.checkBehindFullscreenActivity(topActivity,
1344 null /* handleBehindFullscreenActivity */));
1345
1346 final ActivityRecord finishingActivity =
1347 new ActivityBuilder(mService).setStack(mStack).setTask(mTask).build();
1348 finishingActivity.finishing = true;
1349 doCallRealMethod().when(finishingActivity).occludesParent();
1350 assertFalse(mStack.checkBehindFullscreenActivity(bottomActivity,
1351 null /* handleBehindFullscreenActivity */));
1352 assertFalse(mStack.checkBehindFullscreenActivity(topActivity,
1353 null /* handleBehindFullscreenActivity */));
1354 }
1355
1356 @Test
Riddle Hsu13c27ae2019-10-05 23:10:15 +08001357 public void testClearUnknownAppVisibilityBehindFullscreenActivity() {
1358 final UnknownAppVisibilityController unknownAppVisibilityController =
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -07001359 mDefaultTaskDisplayArea.mDisplayContent.mUnknownAppVisibilityController;
Riddle Hsu13c27ae2019-10-05 23:10:15 +08001360 final KeyguardController keyguardController = mSupervisor.getKeyguardController();
1361 doReturn(true).when(keyguardController).isKeyguardLocked();
1362
1363 // Start 2 activities that their processes have not yet started.
1364 final ActivityRecord[] activities = new ActivityRecord[2];
1365 mSupervisor.beginDeferResume();
1366 for (int i = 0; i < activities.length; i++) {
1367 final ActivityRecord r = new ActivityBuilder(mService).setTask(mTask).build();
1368 activities[i] = r;
1369 doReturn(null).when(mService).getProcessController(
1370 eq(r.processName), eq(r.info.applicationInfo.uid));
1371 r.setState(ActivityStack.ActivityState.INITIALIZING, "test");
1372 // Ensure precondition that the activity is opaque.
1373 assertTrue(r.occludesParent());
Wale Ogunwale076c3b12019-11-20 12:17:22 -08001374 mSupervisor.startSpecificActivity(r, false /* andResume */,
Riddle Hsu13c27ae2019-10-05 23:10:15 +08001375 false /* checkConfig */);
1376 }
1377 mSupervisor.endDeferResume();
1378
1379 doReturn(false).when(mService).isBooting();
1380 doReturn(true).when(mService).isBooted();
1381 // 2 activities are started while keyguard is locked, so they are waiting to be resolved.
1382 assertFalse(unknownAppVisibilityController.allResolved());
1383
1384 // Assume the top activity is going to resume and
Louis Chang149d5c82019-12-30 09:47:39 +08001385 // {@link RootWindowContainer#cancelInitializingActivities} should clear the unknown
Riddle Hsu13c27ae2019-10-05 23:10:15 +08001386 // visibility records that are occluded.
1387 mStack.resumeTopActivityUncheckedLocked(null /* prev */, null /* options */);
1388 // Assume the top activity relayouted, just remove it directly.
1389 unknownAppVisibilityController.appRemovedOrHidden(activities[1]);
1390 // All unresolved records should be removed.
1391 assertTrue(unknownAppVisibilityController.allResolved());
1392 }
1393
1394 @Test
Louis Changcfe46212019-07-30 10:34:18 +08001395 public void testNonTopVisibleActivityNotResume() {
1396 final ActivityRecord nonTopVisibleActivity =
1397 new ActivityBuilder(mService).setTask(mTask).build();
1398 new ActivityBuilder(mService).setTask(mTask).build();
1399 doReturn(false).when(nonTopVisibleActivity).attachedToProcess();
Riddle Hsu13c27ae2019-10-05 23:10:15 +08001400 doReturn(true).when(nonTopVisibleActivity).shouldBeVisible(anyBoolean(), anyBoolean());
Wale Ogunwale076c3b12019-11-20 12:17:22 -08001401 doNothing().when(mSupervisor).startSpecificActivity(any(), anyBoolean(),
Louis Changcfe46212019-07-30 10:34:18 +08001402 anyBoolean());
1403
Wale Ogunwale076c3b12019-11-20 12:17:22 -08001404 mStack.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
Louis Changcfe46212019-07-30 10:34:18 +08001405 false /* preserveWindows */);
Wale Ogunwale076c3b12019-11-20 12:17:22 -08001406 verify(mSupervisor).startSpecificActivity(any(), eq(false) /* andResume */,
Louis Changcfe46212019-07-30 10:34:18 +08001407 anyBoolean());
1408 }
1409
Galia Peycheva7ecd6ef2020-03-26 19:59:40 +01001410 private boolean isAssistantOnTop() {
1411 return mContext.getResources().getBoolean(
1412 com.android.internal.R.bool.config_assistantOnTopOfDream);
1413 }
1414
Bryce Lee271617a2018-03-15 10:39:12 -07001415 private void verifyShouldSleepActivities(boolean focusedStack,
1416 boolean keyguardGoingAway, boolean displaySleeping, boolean expected) {
Louis Chang677921f2019-12-06 16:44:24 +08001417 final DisplayContent display = mock(DisplayContent.class);
Bryce Lee271617a2018-03-15 10:39:12 -07001418 final KeyguardController keyguardController = mSupervisor.getKeyguardController();
1419
Louis Chang677921f2019-12-06 16:44:24 +08001420 doReturn(display).when(mStack).getDisplay();
Bryce Lee271617a2018-03-15 10:39:12 -07001421 doReturn(keyguardGoingAway).when(keyguardController).isKeyguardGoingAway();
1422 doReturn(displaySleeping).when(display).isSleeping();
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001423 doReturn(focusedStack).when(mStack).isFocusedStackOnDisplay();
Bryce Lee271617a2018-03-15 10:39:12 -07001424
1425 assertEquals(expected, mStack.shouldSleepActivities());
1426 }
Winson Chung0f7ec962018-05-03 18:03:15 -07001427
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +09001428 private static class StackOrderChangedListener
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -07001429 implements TaskDisplayArea.OnStackOrderChangedListener {
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +09001430 public boolean mChanged = false;
Winson Chung0f7ec962018-05-03 18:03:15 -07001431
1432 @Override
Winson Chung65d66d32018-12-13 17:48:39 -08001433 public void onStackOrderChanged(ActivityStack stack) {
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +09001434 mChanged = true;
Winson Chung0f7ec962018-05-03 18:03:15 -07001435 }
1436 }
Bryce Lee840c5662017-04-13 10:02:51 -07001437}