• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
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
14  * limitations under the License
15  */
16 
17 package android.server.wm;
18 
19 import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
20 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
21 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
22 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
23 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
24 import static android.server.wm.CliIntentExtra.extraString;
25 import static android.server.wm.ComponentNameUtils.getActivityName;
26 import static android.server.wm.UiDeviceUtils.pressHomeButton;
27 import static android.server.wm.WindowManagerState.STATE_RESUMED;
28 import static android.server.wm.app.Components.ANIMATION_TEST_ACTIVITY;
29 import static android.server.wm.app.Components.ASSISTANT_ACTIVITY;
30 import static android.server.wm.app.Components.ASSISTANT_VOICE_INTERACTION_SERVICE;
31 import static android.server.wm.app.Components.AssistantActivity.EXTRA_ASSISTANT_DISPLAY_ID;
32 import static android.server.wm.app.Components.AssistantActivity.EXTRA_ASSISTANT_ENTER_PIP;
33 import static android.server.wm.app.Components.AssistantActivity.EXTRA_ASSISTANT_FINISH_SELF;
34 import static android.server.wm.app.Components.AssistantActivity.EXTRA_ASSISTANT_LAUNCH_NEW_TASK;
35 import static android.server.wm.app.Components.DOCKED_ACTIVITY;
36 import static android.server.wm.app.Components.LAUNCH_ASSISTANT_ACTIVITY_FROM_SESSION;
37 import static android.server.wm.app.Components.LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK;
38 import static android.server.wm.app.Components.LaunchAssistantActivityIntoAssistantStack.EXTRA_ASSISTANT_IS_TRANSLUCENT;
39 import static android.server.wm.app.Components.PIP_ACTIVITY;
40 import static android.server.wm.app.Components.PipActivity.EXTRA_ENTER_PIP;
41 import static android.server.wm.app.Components.TEST_ACTIVITY;
42 import static android.server.wm.app.Components.TRANSLUCENT_ASSISTANT_ACTIVITY;
43 import static android.server.wm.app.Components.TestActivity.TEST_ACTIVITY_ACTION_FINISH_SELF;
44 import static android.view.Display.DEFAULT_DISPLAY;
45 
46 import static org.hamcrest.Matchers.hasSize;
47 import static org.hamcrest.Matchers.lessThanOrEqualTo;
48 import static org.junit.Assert.assertEquals;
49 import static org.junit.Assert.assertThat;
50 import static org.junit.Assert.assertTrue;
51 import static org.junit.Assume.assumeTrue;
52 
53 import android.content.ComponentName;
54 import android.platform.test.annotations.Presubmit;
55 import android.provider.Settings;
56 import android.server.wm.settings.SettingsSession;
57 
58 import org.junit.Ignore;
59 import org.junit.Test;
60 
61 /**
62  * Build/Install/Run:
63  *     atest CtsWindowManagerDeviceTestCases:AssistantStackTests
64  */
65 @Presubmit
66 public class AssistantStackTests extends ActivityManagerTestBase {
67 
68     private int mAssistantDisplayId = DEFAULT_DISPLAY;
69 
setUp()70     public void setUp() throws Exception {
71         super.setUp();
72         try (final AssistantSession assistantSession = new AssistantSession()) {
73             assistantSession.setVoiceInteractionService(ASSISTANT_VOICE_INTERACTION_SERVICE);
74             launchActivityNoWait(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK);
75             waitForValidStateWithActivityType(ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
76             WindowManagerState.Task assistantStack =
77                     mWmState.getRootTaskByActivityType(ACTIVITY_TYPE_ASSISTANT);
78             mAssistantDisplayId = assistantStack.mDisplayId;
79         }
80     }
81 
82     @Test
testLaunchingAssistantActivityIntoAssistantStack()83     public void testLaunchingAssistantActivityIntoAssistantStack() throws Exception {
84         // Enable the assistant and launch an assistant activity
85         try (final AssistantSession assistantSession = new AssistantSession()) {
86             assistantSession.setVoiceInteractionService(ASSISTANT_VOICE_INTERACTION_SERVICE);
87 
88             launchActivityNoWait(LAUNCH_ASSISTANT_ACTIVITY_FROM_SESSION);
89             waitForValidStateWithActivityType(ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
90 
91             // Ensure that the activity launched in the fullscreen assistant stack
92             assertAssistantStackExists();
93             // In a multi-window environment the assistant might not be fullscreen
94             assumeTrue(getDefaultDisplayWindowingMode() == WINDOWING_MODE_FULLSCREEN);
95             assertTrue("Expected assistant stack to be fullscreen",
96                     mWmState.getRootTaskByActivityType(
97                             ACTIVITY_TYPE_ASSISTANT).isFullscreen());
98         }
99     }
100 
101     @Test
testAssistantStackZOrder()102     public void testAssistantStackZOrder() throws Exception {
103         assumeTrue(assistantRunsOnPrimaryDisplay());
104         assumeTrue(supportsPip());
105         assumeTrue(supportsSplitScreenMultiWindow());
106 
107         // Launch a pinned stack task
108         launchActivity(PIP_ACTIVITY, extraString(EXTRA_ENTER_PIP, "true"));
109         waitForValidStateWithActivityTypeAndWindowingMode(
110                 PIP_ACTIVITY, ACTIVITY_TYPE_STANDARD, WINDOWING_MODE_PINNED);
111         mWmState.assertContainsStack("Must contain pinned stack.",
112                 WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD);
113 
114         // Dock a task
115         launchActivitiesInSplitScreen(
116                 getLaunchActivityBuilder().setTargetActivity(DOCKED_ACTIVITY),
117                 getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY));
118 
119         // Enable the assistant and launch an assistant activity, ensure it is on top
120         try (final AssistantSession assistantSession = new AssistantSession()) {
121             assistantSession.setVoiceInteractionService(ASSISTANT_VOICE_INTERACTION_SERVICE);
122 
123             launchActivityNoWait(LAUNCH_ASSISTANT_ACTIVITY_FROM_SESSION);
124             waitForValidStateWithActivityType(ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
125             assertAssistantStackExists();
126 
127             mWmState.assertFrontStack("Pinned stack should be on top.",
128                     WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD);
129             mWmState.assertFocusedRootTask("Assistant stack should be focused.",
130                     WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
131         }
132     }
133 
134     @Test
testAssistantStackLaunchNewTask()135     public void testAssistantStackLaunchNewTask() throws Exception {
136         assertAssistantStackCanLaunchAndReturnFromNewTask();
137     }
138 
139     @Test
140     @Ignore("b/77272253#comment10")
testAssistantStackLaunchNewTaskWithDockedStack()141     public void testAssistantStackLaunchNewTaskWithDockedStack() throws Exception {
142         assumeTrue(assistantRunsOnPrimaryDisplay());
143         assumeTrue(supportsSplitScreenMultiWindow());
144 
145         // Dock a task
146         launchActivitiesInSplitScreen(
147                 getLaunchActivityBuilder().setTargetActivity(DOCKED_ACTIVITY),
148                 getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY));
149 
150         //assertAssistantStackCanLaunchAndReturnFromNewTask(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
151     }
152 
assertAssistantStackCanLaunchAndReturnFromNewTask()153     private void assertAssistantStackCanLaunchAndReturnFromNewTask()
154             throws Exception {
155         // Enable the assistant and launch an assistant activity which will launch a new task
156         try (final AssistantSession assistantSession = new AssistantSession()) {
157             assistantSession.setVoiceInteractionService(ASSISTANT_VOICE_INTERACTION_SERVICE);
158 
159             launchActivityOnDisplayNoWait(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK, mAssistantDisplayId,
160                     extraString(EXTRA_ASSISTANT_LAUNCH_NEW_TASK, getActivityName(TEST_ACTIVITY)),
161                     extraString(EXTRA_ASSISTANT_DISPLAY_ID, Integer.toString(mAssistantDisplayId)));
162             // Ensure that the fullscreen stack is on top and the test activity is now visible
163             waitForValidStateWithActivityType(TEST_ACTIVITY, ACTIVITY_TYPE_STANDARD);
164         }
165 
166         if (isAssistantOnTopOfDream()) {
167             // If the assistant is configured to be always-on-top, then the new task should have
168             // been started behind it and the assistant stack should still be on top.
169             mWmState.assertFocusedActivity(
170                     "AssistantActivity should be focused", ASSISTANT_ACTIVITY);
171             mWmState.assertFrontStackActivityType(
172                     "Assistant stack should be on top.", ACTIVITY_TYPE_ASSISTANT);
173             mWmState.assertFocusedRootTask("Assistant stack should be focused.",
174                     WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
175         } else {
176             mWmState.assertFocusedActivity("TestActivity should be resumed", TEST_ACTIVITY);
177             mWmState.assertFrontStack("TestActivity stack should be on top.",
178                     WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD);
179             mWmState.assertFocusedRootTask("TestActivity stack should be focused.",
180                     WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD);
181         }
182 
183         // Now, tell it to finish itself and ensure that the assistant stack is brought back forward
184         mBroadcastActionTrigger.doAction(TEST_ACTIVITY_ACTION_FINISH_SELF);
185         mWmState.waitForFocusedStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
186         mWmState.assertFrontStackActivityType(
187                 "Assistant stack should be on top.", ACTIVITY_TYPE_ASSISTANT);
188         mWmState.assertFocusedRootTask("Assistant stack should be focused.",
189                 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
190     }
191 
192     @Test
testAssistantStackFinishToPreviousApp()193     public void testAssistantStackFinishToPreviousApp() throws Exception {
194         // If the Assistant is configured to be always-on-top, then the assistant activity
195         // started in setUp() will not allow any other activities to start. Therefore we should
196         // remove it before launching a fullscreen activity.
197         if (isAssistantOnTopOfDream()) {
198             removeRootTasksWithActivityTypes(ACTIVITY_TYPE_ASSISTANT);
199         }
200 
201         // Launch an assistant activity on top of an existing activity, and ensure that the activity
202         // is still visible and on top after the assistant activity finishes
203         launchActivityOnDisplay(TEST_ACTIVITY, mAssistantDisplayId);
204         try (final AssistantSession assistantSession = new AssistantSession()) {
205             assistantSession.setVoiceInteractionService(ASSISTANT_VOICE_INTERACTION_SERVICE);
206 
207             launchActivityNoWait(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
208                     extraString(EXTRA_ASSISTANT_FINISH_SELF, "true"));
209             mWmState.waitFor((amState) -> !amState.containsActivity(ASSISTANT_ACTIVITY),
210                     getActivityName(ASSISTANT_ACTIVITY) + " finished");
211         }
212         waitForValidStateWithActivityType(TEST_ACTIVITY, ACTIVITY_TYPE_STANDARD);
213         waitAndAssertTopResumedActivity(TEST_ACTIVITY, mAssistantDisplayId,
214                 "TestActivity should be resumed");
215         mWmState.assertFocusedActivity("TestActivity should be focused", TEST_ACTIVITY);
216 
217         mWmState.assertFrontStack("TestActivity stack should be on top.",
218                 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD);
219         mWmState.assertFocusedRootTask("TestActivity stack should be focused.",
220                 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD);
221     }
222 
223     @Test
testDisallowEnterPiPFromAssistantStack()224     public void testDisallowEnterPiPFromAssistantStack() throws Exception {
225         try (final AssistantSession assistantSession = new AssistantSession()) {
226             assistantSession.setVoiceInteractionService(ASSISTANT_VOICE_INTERACTION_SERVICE);
227 
228             launchActivityNoWait(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
229                     extraString(EXTRA_ASSISTANT_ENTER_PIP, "true"));
230         }
231         waitForValidStateWithActivityType(ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
232         mWmState.assertDoesNotContainStack("Must not contain pinned stack.",
233                 WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD);
234     }
235 
236     @Test
testTranslucentAssistantActivityStackVisibility()237     public void testTranslucentAssistantActivityStackVisibility() throws Exception {
238         try (final AssistantSession assistantSession = new AssistantSession()) {
239             assistantSession.setVoiceInteractionService(ASSISTANT_VOICE_INTERACTION_SERVICE);
240 
241             // Go home, launch the assistant and check to see that home is visible
242             removeRootTasksInWindowingModes(WINDOWING_MODE_FULLSCREEN);
243             pressHomeButton();
244             resumeAppSwitches();
245             launchActivityNoWait(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
246                     extraString(EXTRA_ASSISTANT_IS_TRANSLUCENT, "true"));
247             waitForValidStateWithActivityType(
248                     TRANSLUCENT_ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
249             assertAssistantStackExists();
250             mWmState.waitForHomeActivityVisible();
251             if (hasHomeScreen()) {
252                 mWmState.assertHomeActivityVisible(true);
253             }
254 
255             // Launch a fullscreen app and then launch the assistant and check to see that it is
256             // also visible
257             removeRootTasksWithActivityTypes(ACTIVITY_TYPE_ASSISTANT);
258             launchActivityOnDisplay(TEST_ACTIVITY, WINDOWING_MODE_FULLSCREEN, mAssistantDisplayId);
259             launchActivityNoWait(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
260                     extraString(EXTRA_ASSISTANT_IS_TRANSLUCENT, "true"));
261             waitForValidStateWithActivityType(
262                     TRANSLUCENT_ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
263             assertAssistantStackExists();
264             mWmState.assertVisibility(TEST_ACTIVITY, true);
265 
266             // Go home, launch assistant, launch app into fullscreen with activity present, and go
267             // back.Ensure home is visible.
268             removeRootTasksWithActivityTypes(ACTIVITY_TYPE_ASSISTANT);
269             pressHomeButton();
270             resumeAppSwitches();
271             launchActivityNoWait(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
272                     extraString(EXTRA_ASSISTANT_IS_TRANSLUCENT, "true"),
273                     extraString(EXTRA_ASSISTANT_LAUNCH_NEW_TASK, getActivityName(TEST_ACTIVITY)));
274             waitForValidStateWithActivityType(TEST_ACTIVITY, ACTIVITY_TYPE_STANDARD);
275 
276             final ComponentName homeActivity = mWmState.getHomeActivityName();
277             int windowingMode = mWmState.getFocusedRootTaskWindowingMode();
278             // In a multi-window environment the home activity might not be fully covered
279             assumeTrue(windowingMode == WINDOWING_MODE_FULLSCREEN);
280 
281             // A WM Shell can implement a policy where there are more than one default
282             // Task Display Areas.
283             // If there are two task display areas, for example, left and right.
284             // When an activity is organized in left task display area it is still running in
285             // WINDOWING_MODE_FULLSCREEN. Having said that, home activity in default task display
286             // area is not fully covered. Thus, home activity is still resumed and visible.
287             // More than that, in the current AOSP 11 implementation, visibility and activity
288             // lifecycle work differently if activities are in the same task display area or in
289             // different task display areas.
290             // For example, if two task display areas have the exact same bounds,
291             // for the user, an activity running in the top task display area covers the activity
292             // running in the bottom task display area. However, because they are in separate
293             // display areas they will be both resumed.
294             // There can be cases where the bounds match but because tasks are in different
295             // task display area they are both resumed.
296             // So we check the activity bounds for two activities to confirm if task display
297             // areas are the same. If not the same, we will skip the visibility asserting test.
298             if (compareActivityBounds(homeActivity,
299                     ComponentName.unflattenFromString(mWmState.getFocusedActivity()))) {
300                 mWmState.waitAndAssertVisibilityGone(homeActivity);
301             }
302 
303             mBroadcastActionTrigger.doAction(TEST_ACTIVITY_ACTION_FINISH_SELF);
304             mWmState.waitForFocusedStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
305             assertAssistantStackExists();
306             mWmState.waitForHomeActivityVisible();
307             if (hasHomeScreen()) {
308                 mWmState.assertHomeActivityVisible(true);
309             }
310 
311             // Launch a fullscreen and docked app and then launch the assistant and check to see
312             // that it
313             // is also visible
314             if (supportsSplitScreenMultiWindow() &&  assistantRunsOnPrimaryDisplay()) {
315                 removeRootTasksWithActivityTypes(ACTIVITY_TYPE_ASSISTANT);
316                 launchActivitiesInSplitScreen(
317                         getLaunchActivityBuilder().setTargetActivity(DOCKED_ACTIVITY),
318                         getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY));
319                 launchActivityNoWait(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
320                         extraString(EXTRA_ASSISTANT_IS_TRANSLUCENT, "true"));
321                 waitForValidStateWithActivityType(
322                         TRANSLUCENT_ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
323                 assertAssistantStackExists();
324                 mWmState.assertVisibility(DOCKED_ACTIVITY, true);
325                 mWmState.assertVisibility(TEST_ACTIVITY, true);
326             }
327         }
328     }
329 
330     @Test
testLaunchIntoSameTask()331     public void testLaunchIntoSameTask() throws Exception {
332         try (final AssistantSession assistantSession = new AssistantSession()) {
333             assistantSession.setVoiceInteractionService(ASSISTANT_VOICE_INTERACTION_SERVICE);
334 
335             // Launch the assistant
336             launchActivityOnDisplayNoWait(LAUNCH_ASSISTANT_ACTIVITY_FROM_SESSION,
337                     mAssistantDisplayId);
338             waitForValidStateWithActivityType(ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
339             assertAssistantStackExists();
340             mWmState.assertVisibility(ASSISTANT_ACTIVITY, true);
341             mWmState.assertFocusedRootTask("Expected assistant stack focused",
342                     WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
343             final WindowManagerState amState = mWmState;
344             // If activity is hosted by created-by-organizer root task, the root task captured by
345             // WindowManagerState will have 0 child task. Otherwise, root task contains 1 child
346             // task.
347             assertThat(amState.getRootTaskByActivityType(ACTIVITY_TYPE_ASSISTANT).getTasks(),
348                     hasSize(lessThanOrEqualTo(1)));
349             final int taskId = mWmState.getTaskByActivity(ASSISTANT_ACTIVITY)
350                     .mTaskId;
351 
352             // Launch a new fullscreen activity
353             // Using Animation Test Activity because it is opaque on all devices.
354             int launchTDAId = mWmState.getTaskDisplayAreaFeatureId(ASSISTANT_ACTIVITY);
355             launchActivityOnTaskDisplayArea(ANIMATION_TEST_ACTIVITY, WINDOWING_MODE_FULLSCREEN,
356                     launchTDAId, mAssistantDisplayId);
357             // If the activity is not launched in same TDA, ASSISTANT_ACTIVITY will be visible.
358             assumeTrue("Should launch in same TDA",
359                     mWmState.getTaskDisplayArea(ASSISTANT_ACTIVITY)
360                             == mWmState.getTaskDisplayArea(ANIMATION_TEST_ACTIVITY)
361             );
362             // Wait for animation finished.
363             mWmState.waitForActivityState(ANIMATION_TEST_ACTIVITY, STATE_RESUMED);
364 
365             if (isAssistantOnTopOfDream()) {
366                 mWmState.assertVisibility(ASSISTANT_ACTIVITY, true);
367             } else {
368                 mWmState.waitAndAssertVisibilityGone(ASSISTANT_ACTIVITY);
369             }
370 
371             // Launch the assistant again and ensure that it goes into the same task
372             launchActivityOnDisplayNoWait(LAUNCH_ASSISTANT_ACTIVITY_FROM_SESSION,
373                     mAssistantDisplayId);
374             waitForValidStateWithActivityType(ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
375             assertAssistantStackExists();
376             mWmState.assertVisibility(ASSISTANT_ACTIVITY, true);
377             mWmState.assertFocusedRootTask("Expected assistant stack focused",
378                     WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
379             // If activity is hosted by created-by-organizer root task, the root task captured by
380             // WindowManagerState will have 0 child task. Otherwise, root task contains 1 child
381             // task.
382             assertThat(amState.getRootTaskByActivityType(ACTIVITY_TYPE_ASSISTANT).getTasks(),
383                     hasSize(lessThanOrEqualTo(1)));
384             assertEquals(taskId,
385                     mWmState.getTaskByActivity(ASSISTANT_ACTIVITY).mTaskId);
386 
387         }
388     }
389 
390     @Test
testPinnedStackWithAssistant()391     public void testPinnedStackWithAssistant() throws Exception {
392         assumeTrue(supportsPip());
393         assumeTrue(supportsSplitScreenMultiWindow());
394 
395         try (final AssistantSession assistantSession = new AssistantSession()) {
396             assistantSession.setVoiceInteractionService(ASSISTANT_VOICE_INTERACTION_SERVICE);
397 
398             // Launch a fullscreen activity and a PIP activity, then launch the assistant, and
399             // ensure that the test activity is still visible
400             launchActivity(TEST_ACTIVITY, WINDOWING_MODE_FULLSCREEN);
401             launchActivity(PIP_ACTIVITY, extraString(EXTRA_ENTER_PIP, "true"));
402             launchActivityNoWait(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
403                     extraString(EXTRA_ASSISTANT_IS_TRANSLUCENT, String.valueOf(true)));
404             waitForValidStateWithActivityType(
405                     TRANSLUCENT_ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
406             assertAssistantStackExists();
407             mWmState.assertVisibility(TRANSLUCENT_ASSISTANT_ACTIVITY, true);
408             mWmState.assertVisibility(PIP_ACTIVITY, true);
409             mWmState.assertVisibility(TEST_ACTIVITY, true);
410 
411         }
412     }
413 
waitForValidStateWithActivityType(ComponentName activityName, int activityType)414     private void waitForValidStateWithActivityType(ComponentName activityName, int activityType)
415             throws Exception {
416         mWmState.waitForValidState(new WaitForValidActivityState.Builder(activityName)
417                 .setActivityType(activityType)
418                 .build());
419     }
420 
waitForValidStateWithActivityTypeAndWindowingMode(ComponentName activityName, int activityType, int windowingMode)421     private void waitForValidStateWithActivityTypeAndWindowingMode(ComponentName activityName,
422             int activityType, int windowingMode) throws Exception {
423         mWmState.waitForValidState(new WaitForValidActivityState.Builder(activityName)
424                 .setActivityType(activityType)
425                 .setWindowingMode(windowingMode)
426                 .build());
427     }
428 
429     /**
430      * Asserts that the assistant stack exists.
431      */
assertAssistantStackExists()432     private void assertAssistantStackExists() throws Exception {
433         mWmState.assertContainsStack("Must contain assistant stack.",
434                 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
435     }
436 
437     // Any 2D Activity in VR mode is run on a special VR virtual display, so check if the Assistant
438     // is going to run on the same display as other tasks.
assistantRunsOnPrimaryDisplay()439     protected boolean assistantRunsOnPrimaryDisplay() {
440         return mAssistantDisplayId == DEFAULT_DISPLAY;
441     }
442 
443     /**
444      * @return Windowing Mode from the default display
445      */
getDefaultDisplayWindowingMode()446     private int getDefaultDisplayWindowingMode() {
447         mWmState.computeState();
448         return mWmState.getDisplay(DEFAULT_DISPLAY).getWindowingMode();
449     }
450 
451     /** Helper class to save, set, and restore
452      * {@link Settings.Secure#VOICE_INTERACTION_SERVICE} system preference.
453      */
454     private static class AssistantSession extends SettingsSession<String> {
AssistantSession()455         AssistantSession() {
456             super(Settings.Secure.getUriFor(Settings.Secure.VOICE_INTERACTION_SERVICE),
457                     Settings.Secure::getString, Settings.Secure::putString);
458         }
459 
setVoiceInteractionService(ComponentName assistantName)460         void setVoiceInteractionService(ComponentName assistantName) throws Exception {
461             super.set(getActivityName(assistantName));
462         }
463     }
464 
465     /**
466      * Compare if bounds were the same between activities
467      */
compareActivityBounds(ComponentName activityName1, ComponentName activityName2)468     private boolean compareActivityBounds(ComponentName activityName1,
469             ComponentName activityName2) {
470         if (mWmState.getTaskByActivity(activityName1).getBounds()
471                 .equals(mWmState.getTaskByActivity(activityName2).getBounds())) {
472             return true;
473         }
474         return false;
475     }
476 }
477