blob: dc307b547a63f79273acc9a9abdd888bbed8610b [file] [log] [blame]
Garfield Tan9b1efea2017-12-05 16:43:46 -08001/*
Wale Ogunwale59507092018-10-29 09:00:30 -07002 * Copyright (C) 2018 The Android Open Source Project
Garfield Tan9b1efea2017-12-05 16:43:46 -08003 *
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
Garfield Tan9b1efea2017-12-05 16:43:46 -080015 */
16
Wale Ogunwale59507092018-10-29 09:00:30 -070017package com.android.server.wm;
Garfield Tan9b1efea2017-12-05 16:43:46 -080018
Evan Rosky1ac84462018-11-13 11:25:30 -080019import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
20import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
21import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
Bryce Lee1a990e52018-04-23 10:54:11 -070022import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
23import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
Evan Rosky730f6e82018-12-03 17:40:11 -080024import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
25import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
26import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
Riddle Hsu88e3c8732019-02-18 19:15:12 +080027import static android.util.DisplayMetrics.DENSITY_DEFAULT;
Evan Rosky730f6e82018-12-03 17:40:11 -080028
29import static com.android.server.wm.WindowContainer.POSITION_TOP;
Bryce Lee1a990e52018-04-23 10:54:11 -070030
Riddle Hsu2f9acd22018-11-06 23:44:43 +080031import static org.hamcrest.Matchers.not;
32import static org.hamcrest.Matchers.sameInstance;
Garfield Tan367b35a2017-12-13 12:16:21 -080033import static org.junit.Assert.assertEquals;
Garfield Tan9b1efea2017-12-05 16:43:46 -080034import static org.junit.Assert.assertFalse;
35import static org.junit.Assert.assertNotNull;
Riddle Hsu2f9acd22018-11-06 23:44:43 +080036import static org.junit.Assert.assertThat;
Garfield Tan9b1efea2017-12-05 16:43:46 -080037import static org.junit.Assert.assertTrue;
Garfield Tan49dae102019-02-04 09:51:59 -080038import static org.mockito.Mockito.mock;
Garfield Tan9b1efea2017-12-05 16:43:46 -080039
40import android.app.ActivityManager;
Mark Renoufc808f062019-02-07 15:20:37 -050041import android.app.TaskInfo;
Garfield Tan9b1efea2017-12-05 16:43:46 -080042import android.content.ComponentName;
43import android.content.Intent;
44import android.content.pm.ActivityInfo;
Louis Chang96c7b832018-12-27 09:27:53 +080045import android.content.pm.ApplicationInfo;
Evan Rosky1ac84462018-11-13 11:25:30 -080046import android.content.res.Configuration;
Garfield Tan367b35a2017-12-13 12:16:21 -080047import android.graphics.Rect;
Garfield Tan9b1efea2017-12-05 16:43:46 -080048import android.platform.test.annotations.Presubmit;
49import android.service.voice.IVoiceInteractionSession;
Evan Rosky60dba2f2019-02-01 10:58:38 -080050import android.util.DisplayMetrics;
Garfield Tan367b35a2017-12-13 12:16:21 -080051import android.util.Xml;
Evan Rosky1ac84462018-11-13 11:25:30 -080052import android.view.DisplayInfo;
Garfield Tan9b1efea2017-12-05 16:43:46 -080053
Brett Chabota26eda92018-07-23 13:08:30 -070054import androidx.test.filters.MediumTest;
Brett Chabota26eda92018-07-23 13:08:30 -070055
Garfield Tan9b1efea2017-12-05 16:43:46 -080056import com.android.internal.app.IVoiceInteractor;
Wale Ogunwale59507092018-10-29 09:00:30 -070057import com.android.server.wm.TaskRecord.TaskRecordFactory;
Garfield Tan9b1efea2017-12-05 16:43:46 -080058
59import org.junit.Before;
60import org.junit.Test;
Garfield Tan49dae102019-02-04 09:51:59 -080061import org.mockito.Mockito;
Garfield Tan9b1efea2017-12-05 16:43:46 -080062import org.xmlpull.v1.XmlPullParser;
63import org.xmlpull.v1.XmlPullParserException;
Garfield Tan367b35a2017-12-13 12:16:21 -080064import org.xmlpull.v1.XmlSerializer;
Garfield Tan9b1efea2017-12-05 16:43:46 -080065
Tadashi G. Takaoka88df5c32018-11-21 16:33:57 +090066import java.io.ByteArrayInputStream;
67import java.io.ByteArrayOutputStream;
Garfield Tan9b1efea2017-12-05 16:43:46 -080068import java.io.IOException;
Tadashi G. Takaoka88df5c32018-11-21 16:33:57 +090069import java.io.InputStreamReader;
Garfield Tan367b35a2017-12-13 12:16:21 -080070import java.io.Reader;
Garfield Tan9b1efea2017-12-05 16:43:46 -080071import java.util.ArrayList;
72
73/**
74 * Tests for exercising {@link TaskRecord}.
75 *
76 * Build/Install/Run:
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +090077 * atest WmTests:TaskRecordTests
Garfield Tan9b1efea2017-12-05 16:43:46 -080078 */
79@MediumTest
80@Presubmit
Garfield Tan367b35a2017-12-13 12:16:21 -080081public class TaskRecordTests extends ActivityTestsBase {
82
83 private static final String TASK_TAG = "task";
84
Evan Rosky1ac84462018-11-13 11:25:30 -080085 private Rect mParentBounds;
86
Garfield Tan9b1efea2017-12-05 16:43:46 -080087 @Before
88 public void setUp() throws Exception {
89 TaskRecord.setTaskRecordFactory(null);
Evan Rosky1ac84462018-11-13 11:25:30 -080090 mParentBounds = new Rect(10 /*left*/, 30 /*top*/, 80 /*right*/, 60 /*bottom*/);
Garfield Tan367b35a2017-12-13 12:16:21 -080091 }
92
93 @Test
94 public void testRestoreWindowedTask() throws Exception {
95 final TaskRecord expected = createTaskRecord(64);
96 expected.mLastNonFullscreenBounds = new Rect(50, 50, 100, 100);
97
Tadashi G. Takaoka88df5c32018-11-21 16:33:57 +090098 final byte[] serializedBytes = serializeToBytes(expected);
99 final TaskRecord actual = restoreFromBytes(serializedBytes);
100 assertEquals(expected.taskId, actual.taskId);
101 assertEquals(expected.mLastNonFullscreenBounds, actual.mLastNonFullscreenBounds);
Garfield Tan9b1efea2017-12-05 16:43:46 -0800102 }
103
104 @Test
105 public void testDefaultTaskFactoryNotNull() throws Exception {
106 assertNotNull(TaskRecord.getTaskRecordFactory());
107 }
108
Riddle Hsu2f9acd22018-11-06 23:44:43 +0800109 /** Ensure we have no chance to modify the original intent. */
110 @Test
111 public void testCopyBaseIntentForTaskInfo() {
112 final TaskRecord task = createTaskRecord(1);
113 task.lastTaskDescription = new ActivityManager.TaskDescription();
Mark Renoufc808f062019-02-07 15:20:37 -0500114 final TaskInfo info = task.getTaskInfo();
Riddle Hsu2f9acd22018-11-06 23:44:43 +0800115
116 // The intent of info should be a copy so assert that they are different instances.
117 assertThat(info.baseIntent, not(sameInstance(task.getBaseIntent())));
118 }
119
Garfield Tan9b1efea2017-12-05 16:43:46 -0800120 @Test
121 public void testCreateTestRecordUsingCustomizedFactory() throws Exception {
122 TestTaskRecordFactory factory = new TestTaskRecordFactory();
123 TaskRecord.setTaskRecordFactory(factory);
124
125 assertFalse(factory.mCreated);
126
127 TaskRecord.create(null, 0, null, null, null, null);
128
129 assertTrue(factory.mCreated);
130 }
131
Bryce Lee1a990e52018-04-23 10:54:11 -0700132 @Test
133 public void testReturnsToHomeStack() throws Exception {
134 final TaskRecord task = createTaskRecord(1);
135 assertFalse(task.returnsToHomeStack());
136 task.intent = null;
137 assertFalse(task.returnsToHomeStack());
138 task.intent = new Intent();
139 assertFalse(task.returnsToHomeStack());
140 task.intent.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME);
141 assertTrue(task.returnsToHomeStack());
142 }
143
Evan Rosky1ac84462018-11-13 11:25:30 -0800144 /** Ensures that empty bounds are not propagated to the configuration. */
145 @Test
146 public void testAppBounds_EmptyBounds() {
147 final Rect emptyBounds = new Rect();
148 testStackBoundsConfiguration(WINDOWING_MODE_FULLSCREEN, mParentBounds, emptyBounds,
149 null /*ExpectedBounds*/);
150 }
151
152 /** Ensures that bounds on freeform stacks are not clipped. */
153 @Test
154 public void testAppBounds_FreeFormBounds() {
155 final Rect freeFormBounds = new Rect(mParentBounds);
156 freeFormBounds.offset(10, 10);
157 testStackBoundsConfiguration(WINDOWING_MODE_FREEFORM, mParentBounds, freeFormBounds,
158 freeFormBounds);
159 }
160
161 /** Ensures that fully contained bounds are not clipped. */
162 @Test
163 public void testAppBounds_ContainedBounds() {
164 final Rect insetBounds = new Rect(mParentBounds);
165 insetBounds.inset(5, 5, 5, 5);
166 testStackBoundsConfiguration(
Evan Rosky730f6e82018-12-03 17:40:11 -0800167 WINDOWING_MODE_FREEFORM, mParentBounds, insetBounds, insetBounds);
Evan Rosky1ac84462018-11-13 11:25:30 -0800168 }
169
Evan Rosky60dba2f2019-02-01 10:58:38 -0800170 @Test
171 public void testFitWithinBounds() {
172 final Rect parentBounds = new Rect(10, 10, 200, 200);
173 ActivityDisplay display = mService.mRootActivityContainer.getDefaultDisplay();
174 ActivityStack stack = display.createStack(WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD,
175 true /* onTop */);
176 TaskRecord task = new TaskBuilder(mSupervisor).setStack(stack).build();
177 final Configuration parentConfig = stack.getConfiguration();
178 parentConfig.windowConfiguration.setBounds(parentBounds);
179 parentConfig.densityDpi = DisplayMetrics.DENSITY_DEFAULT;
180
181 // check top and left
182 Rect reqBounds = new Rect(-190, -190, 0, 0);
183 task.setBounds(reqBounds);
184 // Make sure part of it is exposed
185 assertTrue(task.getBounds().right > parentBounds.left);
186 assertTrue(task.getBounds().bottom > parentBounds.top);
187 // Should still be more-or-less in that corner
188 assertTrue(task.getBounds().left <= parentBounds.left);
189 assertTrue(task.getBounds().top <= parentBounds.top);
190
191 assertEquals(reqBounds.width(), task.getBounds().width());
192 assertEquals(reqBounds.height(), task.getBounds().height());
193
194 // check bottom and right
195 reqBounds = new Rect(210, 210, 400, 400);
196 task.setBounds(reqBounds);
197 // Make sure part of it is exposed
198 assertTrue(task.getBounds().left < parentBounds.right);
199 assertTrue(task.getBounds().top < parentBounds.bottom);
200 // Should still be more-or-less in that corner
201 assertTrue(task.getBounds().right >= parentBounds.right);
202 assertTrue(task.getBounds().bottom >= parentBounds.bottom);
203
204 assertEquals(reqBounds.width(), task.getBounds().width());
205 assertEquals(reqBounds.height(), task.getBounds().height());
206 }
207
Evan Rosky730f6e82018-12-03 17:40:11 -0800208 /** Tests that the task bounds adjust properly to changes between FULLSCREEN and FREEFORM */
Evan Rosky1ac84462018-11-13 11:25:30 -0800209 @Test
Evan Rosky730f6e82018-12-03 17:40:11 -0800210 public void testBoundsOnModeChangeFreeformToFullscreen() {
Evan Rosky1ac84462018-11-13 11:25:30 -0800211 ActivityDisplay display = mService.mRootActivityContainer.getDefaultDisplay();
Evan Rosky730f6e82018-12-03 17:40:11 -0800212 ActivityStack stack = new StackBuilder(mRootActivityContainer).setDisplay(display)
213 .setWindowingMode(WINDOWING_MODE_FREEFORM).build();
214 TaskRecord task = stack.getChildAt(0);
215 task.getRootActivity().mAppWindowToken.setOrientation(SCREEN_ORIENTATION_UNSPECIFIED);
Evan Rosky1ac84462018-11-13 11:25:30 -0800216 DisplayInfo info = new DisplayInfo();
217 display.mDisplay.getDisplayInfo(info);
218 final Rect fullScreenBounds = new Rect(0, 0, info.logicalWidth, info.logicalHeight);
Evan Rosky730f6e82018-12-03 17:40:11 -0800219 final Rect freeformBounds = new Rect(fullScreenBounds);
220 freeformBounds.inset((int) (freeformBounds.width() * 0.2),
221 (int) (freeformBounds.height() * 0.2));
222 task.setBounds(freeformBounds);
223
224 assertEquals(freeformBounds, task.getBounds());
225
226 // FULLSCREEN inherits bounds
227 stack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
228 assertEquals(fullScreenBounds, task.getBounds());
229 assertEquals(freeformBounds, task.mLastNonFullscreenBounds);
230
231 // FREEFORM restores bounds
232 stack.setWindowingMode(WINDOWING_MODE_FREEFORM);
233 assertEquals(freeformBounds, task.getBounds());
234 }
235
236 /**
237 * This is a temporary hack to trigger an onConfigurationChange at the task level after an
238 * orientation is requested. Normally this is done by the onDescendentOrientationChanged call
239 * up the WM hierarchy, but since the WM hierarchy is mocked out, it doesn't happen here.
240 * TODO: remove this when we either get a WM hierarchy or when hierarchies are merged.
241 */
242 private void setActivityRequestedOrientation(ActivityRecord activity, int orientation) {
243 activity.setRequestedOrientation(orientation);
244 ConfigurationContainer taskRecord = activity.getParent();
245 taskRecord.onConfigurationChanged(taskRecord.getParent().getConfiguration());
246 }
247
248 /**
249 * Tests that a task with forced orientation has orientation-consistent bounds within the
250 * parent.
251 */
252 @Test
253 public void testFullscreenBoundsForcedOrientation() {
254 final Rect fullScreenBounds = new Rect(0, 0, 1920, 1080);
255 final Rect fullScreenBoundsPort = new Rect(0, 0, 1080, 1920);
256 DisplayInfo info = new DisplayInfo();
257 info.logicalWidth = fullScreenBounds.width();
258 info.logicalHeight = fullScreenBounds.height();
259 ActivityDisplay display = addNewActivityDisplayAt(info, POSITION_TOP);
260 assertTrue(mRootActivityContainer.getActivityDisplay(display.mDisplayId) != null);
Evan Rosky130d94f2019-01-15 10:18:17 -0800261 // Override display orientation. Normally this is available via DisplayContent, but DC
262 // is mocked-out.
263 display.getRequestedOverrideConfiguration().orientation =
264 Configuration.ORIENTATION_LANDSCAPE;
265 display.onRequestedOverrideConfigurationChanged(
266 display.getRequestedOverrideConfiguration());
Evan Rosky730f6e82018-12-03 17:40:11 -0800267 ActivityStack stack = new StackBuilder(mRootActivityContainer)
268 .setWindowingMode(WINDOWING_MODE_FULLSCREEN).setDisplay(display).build();
269 TaskRecord task = stack.getChildAt(0);
Evan Rosky130d94f2019-01-15 10:18:17 -0800270 ActivityRecord root = task.getTopActivity();
271 assertEquals(root, task.getTopActivity());
Evan Rosky730f6e82018-12-03 17:40:11 -0800272
273 assertEquals(fullScreenBounds, task.getBounds());
274
275 // Setting app to fixed portrait fits within parent
276 setActivityRequestedOrientation(root, SCREEN_ORIENTATION_PORTRAIT);
277 assertEquals(root, task.getRootActivity());
278 assertEquals(SCREEN_ORIENTATION_PORTRAIT, task.getRootActivity().getOrientation());
279 assertTrue(task.getBounds().width() < task.getBounds().height());
280 assertEquals(fullScreenBounds.height(), task.getBounds().height());
281
Evan Rosky130d94f2019-01-15 10:18:17 -0800282 // Top activity gets used
283 ActivityRecord top = new ActivityBuilder(mService).setTask(task).setStack(stack).build();
284 assertEquals(top, task.getTopActivity());
285 setActivityRequestedOrientation(top, SCREEN_ORIENTATION_LANDSCAPE);
286 assertTrue(task.getBounds().width() > task.getBounds().height());
287 assertEquals(task.getBounds().width(), fullScreenBounds.width());
Evan Rosky730f6e82018-12-03 17:40:11 -0800288
289 // Setting app to unspecified restores
Evan Rosky130d94f2019-01-15 10:18:17 -0800290 setActivityRequestedOrientation(top, SCREEN_ORIENTATION_UNSPECIFIED);
Evan Rosky730f6e82018-12-03 17:40:11 -0800291 assertEquals(fullScreenBounds, task.getBounds());
292
293 // Setting app to fixed landscape and changing display
Evan Rosky130d94f2019-01-15 10:18:17 -0800294 setActivityRequestedOrientation(top, SCREEN_ORIENTATION_LANDSCAPE);
295 // simulate display orientation changing (normally done via DisplayContent)
296 display.getRequestedOverrideConfiguration().orientation =
297 Configuration.ORIENTATION_PORTRAIT;
Evan Rosky730f6e82018-12-03 17:40:11 -0800298 display.setBounds(fullScreenBoundsPort);
299 assertTrue(task.getBounds().width() > task.getBounds().height());
300 assertEquals(fullScreenBoundsPort.width(), task.getBounds().width());
301
302 // in FREEFORM, no constraint
303 final Rect freeformBounds = new Rect(display.getBounds());
304 freeformBounds.inset((int) (freeformBounds.width() * 0.2),
305 (int) (freeformBounds.height() * 0.2));
306 stack.setWindowingMode(WINDOWING_MODE_FREEFORM);
307 task.setBounds(freeformBounds);
308 assertEquals(freeformBounds, task.getBounds());
309
310 // FULLSCREEN letterboxes bounds
311 stack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
312 assertTrue(task.getBounds().width() > task.getBounds().height());
313 assertEquals(fullScreenBoundsPort.width(), task.getBounds().width());
314
315 // FREEFORM restores bounds as before
316 stack.setWindowingMode(WINDOWING_MODE_FREEFORM);
317 assertEquals(freeformBounds, task.getBounds());
Evan Rosky1ac84462018-11-13 11:25:30 -0800318 }
319
Yunfan Chenf93c06f2019-01-17 07:01:49 +0000320 @Test
Garfield Tan49dae102019-02-04 09:51:59 -0800321 public void testIgnoresForcedOrientationWhenParentHandles() {
322 final Rect fullScreenBounds = new Rect(0, 0, 1920, 1080);
323 DisplayInfo info = new DisplayInfo();
324 info.logicalWidth = fullScreenBounds.width();
325 info.logicalHeight = fullScreenBounds.height();
326 ActivityDisplay display = addNewActivityDisplayAt(info, POSITION_TOP);
Yunfan Chenf93c06f2019-01-17 07:01:49 +0000327
Garfield Tan49dae102019-02-04 09:51:59 -0800328 display.getRequestedOverrideConfiguration().orientation =
329 Configuration.ORIENTATION_LANDSCAPE;
330 display.onRequestedOverrideConfigurationChanged(
331 display.getRequestedOverrideConfiguration());
332 ActivityStack stack = new StackBuilder(mRootActivityContainer)
Yunfan Chenf93c06f2019-01-17 07:01:49 +0000333 .setWindowingMode(WINDOWING_MODE_FULLSCREEN).setDisplay(display).build();
Garfield Tan49dae102019-02-04 09:51:59 -0800334 TaskRecord task = stack.getChildAt(0);
335 ActivityRecord root = task.getTopActivity();
Yunfan Chenf93c06f2019-01-17 07:01:49 +0000336
Garfield Tan49dae102019-02-04 09:51:59 -0800337 final WindowContainer parentWindowContainer = mock(WindowContainer.class);
338 Mockito.doReturn(parentWindowContainer).when(task.mTask).getParent();
339 Mockito.doReturn(true).when(parentWindowContainer)
340 .handlesOrientationChangeFromDescendant();
Yunfan Chenf93c06f2019-01-17 07:01:49 +0000341
Garfield Tan49dae102019-02-04 09:51:59 -0800342 // Setting app to fixed portrait fits within parent, but TaskRecord shouldn't adjust the
343 // bounds because its parent says it will handle it at a later time.
344 setActivityRequestedOrientation(root, SCREEN_ORIENTATION_PORTRAIT);
345 assertEquals(root, task.getRootActivity());
346 assertEquals(SCREEN_ORIENTATION_PORTRAIT, task.getRootActivity().getOrientation());
347 assertEquals(fullScreenBounds, task.getBounds());
Yunfan Chenf93c06f2019-01-17 07:01:49 +0000348 }
349
Riddle Hsu88e3c8732019-02-18 19:15:12 +0800350 @Test
351 public void testComputeConfigResourceOverrides() {
352 final TaskRecord task = new TaskBuilder(mSupervisor).build();
353 final Configuration inOutConfig = new Configuration();
354 final Configuration parentConfig = new Configuration();
355 final int longSide = 1200;
356 final int shortSide = 600;
357 parentConfig.densityDpi = 400;
358 parentConfig.screenHeightDp = 200; // 200 * 400 / 160 = 500px
359 parentConfig.screenWidthDp = 100; // 100 * 400 / 160 = 250px
360
361 // Portrait bounds.
362 inOutConfig.windowConfiguration.getBounds().set(0, 0, shortSide, longSide);
363 // By default, the parent bounds should limit the existing input bounds.
364 task.computeConfigResourceOverrides(inOutConfig, parentConfig);
365
366 assertEquals(parentConfig.screenHeightDp, inOutConfig.screenHeightDp);
367 assertEquals(parentConfig.screenWidthDp, inOutConfig.screenWidthDp);
368 assertEquals(Configuration.ORIENTATION_PORTRAIT, inOutConfig.orientation);
369
370 inOutConfig.setToDefaults();
371 // Landscape bounds.
372 inOutConfig.windowConfiguration.getBounds().set(0, 0, longSide, shortSide);
373 // Without limiting to be inside the parent bounds, the out screen size should keep relative
374 // to the input bounds.
375 task.computeConfigResourceOverrides(inOutConfig, parentConfig,
376 false /* insideParentBounds */);
377
378 assertEquals(shortSide * DENSITY_DEFAULT / parentConfig.densityDpi,
379 inOutConfig.screenHeightDp);
380 assertEquals(longSide * DENSITY_DEFAULT / parentConfig.densityDpi,
381 inOutConfig.screenWidthDp);
382 assertEquals(Configuration.ORIENTATION_LANDSCAPE, inOutConfig.orientation);
383 }
384
Louis Chang96c7b832018-12-27 09:27:53 +0800385 /** Ensures that the alias intent won't have target component resolved. */
386 @Test
387 public void testTaskIntentActivityAlias() {
Louis Chang23df1a62019-01-09 15:10:49 +0800388 final String aliasClassName = DEFAULT_COMPONENT_PACKAGE_NAME + ".aliasActivity";
389 final String targetClassName = DEFAULT_COMPONENT_PACKAGE_NAME + ".targetActivity";
390 final ComponentName aliasComponent =
391 new ComponentName(DEFAULT_COMPONENT_PACKAGE_NAME, aliasClassName);
392 final ComponentName targetComponent =
393 new ComponentName(DEFAULT_COMPONENT_PACKAGE_NAME, targetClassName);
394
Louis Chang96c7b832018-12-27 09:27:53 +0800395 final Intent intent = new Intent();
Louis Chang23df1a62019-01-09 15:10:49 +0800396 intent.setComponent(aliasComponent);
Louis Chang96c7b832018-12-27 09:27:53 +0800397 final ActivityInfo info = new ActivityInfo();
398 info.applicationInfo = new ApplicationInfo();
399 info.packageName = DEFAULT_COMPONENT_PACKAGE_NAME;
Louis Chang23df1a62019-01-09 15:10:49 +0800400 info.targetActivity = targetClassName;
Louis Chang96c7b832018-12-27 09:27:53 +0800401
402 final TaskRecord task = TaskRecord.create(mService, 1 /* taskId */, info, intent,
403 null /* taskDescription */);
Louis Chang23df1a62019-01-09 15:10:49 +0800404 assertEquals("The alias activity component should be saved in task intent.", aliasClassName,
Louis Chang96c7b832018-12-27 09:27:53 +0800405 task.intent.getComponent().getClassName());
Louis Chang23df1a62019-01-09 15:10:49 +0800406
407 ActivityRecord aliasActivity = new ActivityBuilder(mService).setComponent(
408 aliasComponent).setTargetActivity(targetClassName).build();
409 assertEquals("Should be the same intent filter.", true,
410 task.isSameIntentFilter(aliasActivity));
411
412 ActivityRecord targetActivity = new ActivityBuilder(mService).setComponent(
413 targetComponent).build();
414 assertEquals("Should be the same intent filter.", true,
415 task.isSameIntentFilter(targetActivity));
416
417 ActivityRecord defaultActivity = new ActivityBuilder(mService).build();
418 assertEquals("Should not be the same intent filter.", false,
419 task.isSameIntentFilter(defaultActivity));
Louis Chang96c7b832018-12-27 09:27:53 +0800420 }
421
Evan Rosky1ac84462018-11-13 11:25:30 -0800422 private void testStackBoundsConfiguration(int windowingMode, Rect parentBounds, Rect bounds,
423 Rect expectedConfigBounds) {
424
425 ActivityDisplay display = mService.mRootActivityContainer.getDefaultDisplay();
426 ActivityStack stack = display.createStack(windowingMode, ACTIVITY_TYPE_STANDARD,
427 true /* onTop */);
428 TaskRecord task = new TaskBuilder(mSupervisor).setStack(stack).build();
429
430 final Configuration parentConfig = stack.getConfiguration();
431 parentConfig.windowConfiguration.setAppBounds(parentBounds);
432 task.setBounds(bounds);
433
434 task.resolveOverrideConfiguration(parentConfig);
435 // Assert that both expected and actual are null or are equal to each other
436 assertEquals(expectedConfigBounds,
437 task.getResolvedOverrideConfiguration().windowConfiguration.getAppBounds());
438 }
439
Tadashi G. Takaoka88df5c32018-11-21 16:33:57 +0900440 private byte[] serializeToBytes(TaskRecord r) throws IOException, XmlPullParserException {
441 try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
Garfield Tan367b35a2017-12-13 12:16:21 -0800442 final XmlSerializer serializer = Xml.newSerializer();
443 serializer.setOutput(os, "UTF-8");
444 serializer.startDocument(null, true);
445 serializer.startTag(null, TASK_TAG);
446 r.saveToXml(serializer);
447 serializer.endTag(null, TASK_TAG);
448 serializer.endDocument();
Garfield Tan367b35a2017-12-13 12:16:21 -0800449
Tadashi G. Takaoka88df5c32018-11-21 16:33:57 +0900450 os.flush();
451 return os.toByteArray();
452 }
Garfield Tan367b35a2017-12-13 12:16:21 -0800453 }
454
Tadashi G. Takaoka88df5c32018-11-21 16:33:57 +0900455 private TaskRecord restoreFromBytes(byte[] in) throws IOException, XmlPullParserException {
456 try (Reader reader = new InputStreamReader(new ByteArrayInputStream(in))) {
Garfield Tan367b35a2017-12-13 12:16:21 -0800457 final XmlPullParser parser = Xml.newPullParser();
458 parser.setInput(reader);
459 assertEquals(XmlPullParser.START_TAG, parser.next());
460 assertEquals(TASK_TAG, parser.getName());
461 return TaskRecord.restoreFromXml(parser, mService.mStackSupervisor);
462 }
463 }
464
465 private TaskRecord createTaskRecord(int taskId) {
Wale Ogunwale31913b52018-10-13 08:29:31 -0700466 return new TaskRecord(mService, taskId, new Intent(), null, null, null,
Kazuki Takisec2e17bf2018-07-17 17:46:38 +0900467 ActivityBuilder.getDefaultComponent(), null, false, false, false, 0, 10050, null,
468 new ArrayList<>(), 0, false, null, 0, 0, 0, 0, 0, null, 0, false, false, false, 0, 0
469 );
Garfield Tan367b35a2017-12-13 12:16:21 -0800470 }
471
Garfield Tan9b1efea2017-12-05 16:43:46 -0800472 private static class TestTaskRecordFactory extends TaskRecordFactory {
473 private boolean mCreated = false;
474
475 @Override
Wale Ogunwaled95c06b2018-05-08 10:35:38 -0700476 TaskRecord create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
Garfield Tan9b1efea2017-12-05 16:43:46 -0800477 Intent intent,
478 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
479 mCreated = true;
480 return null;
481 }
482
483 @Override
Wale Ogunwaled95c06b2018-05-08 10:35:38 -0700484 TaskRecord create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
Garfield Tan9b1efea2017-12-05 16:43:46 -0800485 Intent intent,
486 ActivityManager.TaskDescription taskDescription) {
487 mCreated = true;
488 return null;
489 }
490
491 @Override
Wale Ogunwaled95c06b2018-05-08 10:35:38 -0700492 TaskRecord create(ActivityTaskManagerService service, int taskId, Intent intent,
Garfield Tan9b1efea2017-12-05 16:43:46 -0800493 Intent affinityIntent, String affinity, String rootAffinity,
494 ComponentName realActivity,
495 ComponentName origActivity, boolean rootWasReset, boolean autoRemoveRecents,
496 boolean askedCompatMode, int userId, int effectiveUid, String lastDescription,
497 ArrayList<ActivityRecord> activities, long lastTimeMoved,
498 boolean neverRelinquishIdentity,
499 ActivityManager.TaskDescription lastTaskDescription,
500 int taskAffiliation, int prevTaskId, int nextTaskId, int taskAffiliationColor,
501 int callingUid, String callingPackage, int resizeMode,
502 boolean supportsPictureInPicture,
503 boolean realActivitySuspended, boolean userSetupComplete, int minWidth,
504 int minHeight) {
505 mCreated = true;
506 return null;
507 }
508
509 @Override
510 TaskRecord restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
511 throws IOException, XmlPullParserException {
512 mCreated = true;
513 return null;
514 }
515 }
516}