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.junit.Assert.assertEquals;
48 import static org.junit.Assert.assertThat;
49 import static org.junit.Assert.assertTrue;
50 import static org.junit.Assume.assumeTrue;
51 
52 import android.content.ComponentName;
53 import android.platform.test.annotations.Presubmit;
54 import android.provider.Settings;
55 import android.server.wm.settings.SettingsSession;
56 
57 import org.junit.Ignore;
58 import org.junit.Test;
59 
60 /**
61  * Build/Install/Run:
62  *     atest CtsWindowManagerDeviceTestCases:AssistantStackTests
63  */
64 @Presubmit
65 public class AssistantStackTests extends ActivityManagerTestBase {
66 
67     private int mAssistantDisplayId = DEFAULT_DISPLAY;
68     private int mDefaultWindowingMode;
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             mDefaultWindowingMode = getDefaultDisplayWindowingMode();
80         }
81     }
82 
83     @Test
testLaunchingAssistantActivityIntoAssistantStack()84     public void testLaunchingAssistantActivityIntoAssistantStack() throws Exception {
85         // Enable the assistant and launch an assistant activity
86         try (final AssistantSession assistantSession = new AssistantSession()) {
87             assistantSession.setVoiceInteractionService(ASSISTANT_VOICE_INTERACTION_SERVICE);
88 
89             launchActivityNoWait(LAUNCH_ASSISTANT_ACTIVITY_FROM_SESSION);
90             waitForValidStateWithActivityType(ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
91 
92             // Ensure that the activity launched in the fullscreen assistant stack
93             assertAssistantStackExists();
94             // In a multi-window environment the assistant might not be fullscreen
95             assumeTrue(mDefaultWindowingMode == WINDOWING_MODE_FULLSCREEN);
96             assertTrue("Expected assistant stack to be fullscreen",
97                     mWmState.getRootTaskByActivityType(
98                             ACTIVITY_TYPE_ASSISTANT).isFullscreen());
99         }
100     }
101 
102     @Test
testAssistantStackZOrder()103     public void testAssistantStackZOrder() throws Exception {
104         assumeTrue(assistantRunsOnPrimaryDisplay());
105         assumeTrue(supportsPip());
106         assumeTrue(supportsSplitScreenMultiWindow());
107 
108         // Launch a pinned stack task
109         launchActivity(PIP_ACTIVITY, extraString(EXTRA_ENTER_PIP, "true"));
110         waitForValidStateWithActivityTypeAndWindowingMode(
111                 PIP_ACTIVITY, ACTIVITY_TYPE_STANDARD, WINDOWING_MODE_PINNED);
112         mWmState.assertContainsStack("Must contain pinned stack.",
113                 WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD);
114 
115         // Dock a task
116         launchActivitiesInSplitScreen(
117                 getLaunchActivityBuilder().setTargetActivity(DOCKED_ACTIVITY),
118                 getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY));
119 
120         // Enable the assistant and launch an assistant activity, ensure it is on top
121         try (final AssistantSession assistantSession = new AssistantSession()) {
122             assistantSession.setVoiceInteractionService(ASSISTANT_VOICE_INTERACTION_SERVICE);
123 
124             launchActivityNoWait(LAUNCH_ASSISTANT_ACTIVITY_FROM_SESSION);
125             waitForValidStateWithActivityType(ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
126             assertAssistantStackExists();
127 
128             mWmState.assertFrontStack("Pinned stack should be on top.",
129                     WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD);
130             mWmState.assertFocusedRootTask("Assistant stack should be focused.",
131                     WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
132         }
133     }
134 
135     @Test
testAssistantStackLaunchNewTask()136     public void testAssistantStackLaunchNewTask() throws Exception {
137         assertAssistantStackCanLaunchAndReturnFromNewTask(mDefaultWindowingMode);
138     }
139 
140     @Test
141     @Ignore("b/77272253#comment10")
testAssistantStackLaunchNewTaskWithDockedStack()142     public void testAssistantStackLaunchNewTaskWithDockedStack() throws Exception {
143         assumeTrue(assistantRunsOnPrimaryDisplay());
144         assumeTrue(supportsSplitScreenMultiWindow());
145 
146         // Dock a task
147         launchActivitiesInSplitScreen(
148                 getLaunchActivityBuilder().setTargetActivity(DOCKED_ACTIVITY),
149                 getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY));
150 
151         //assertAssistantStackCanLaunchAndReturnFromNewTask(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
152     }
153 
assertAssistantStackCanLaunchAndReturnFromNewTask(int expectedWindowingMode)154     private void assertAssistantStackCanLaunchAndReturnFromNewTask(int expectedWindowingMode)
155             throws Exception {
156         // Enable the assistant and launch an assistant activity which will launch a new task
157         try (final AssistantSession assistantSession = new AssistantSession()) {
158             assistantSession.setVoiceInteractionService(ASSISTANT_VOICE_INTERACTION_SERVICE);
159 
160             launchActivityOnDisplayNoWait(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK, mAssistantDisplayId,
161                     extraString(EXTRA_ASSISTANT_LAUNCH_NEW_TASK, getActivityName(TEST_ACTIVITY)),
162                     extraString(EXTRA_ASSISTANT_DISPLAY_ID, Integer.toString(mAssistantDisplayId)));
163             // Ensure that the fullscreen stack is on top and the test activity is now visible
164             waitForValidStateWithActivityTypeAndWindowingMode(
165                     TEST_ACTIVITY, ACTIVITY_TYPE_STANDARD, expectedWindowingMode);
166         }
167 
168         if (isAssistantOnTopOfDream()) {
169             // If the assistant is configured to be always-on-top, then the new task should have
170             // been started behind it and the assistant stack should still be on top.
171             mWmState.assertFocusedActivity(
172                     "AssistantActivity should be focused", ASSISTANT_ACTIVITY);
173             mWmState.assertFrontStackActivityType(
174                     "Assistant stack should be on top.", ACTIVITY_TYPE_ASSISTANT);
175             mWmState.assertFocusedRootTask("Assistant stack should be focused.",
176                     WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
177         } else {
178             mWmState.assertFocusedActivity("TestActivity should be resumed", TEST_ACTIVITY);
179             mWmState.assertFrontStack("TestActivity stack should be on top.",
180                     expectedWindowingMode, ACTIVITY_TYPE_STANDARD);
181             mWmState.assertFocusedRootTask("TestActivity stack should be focused.",
182                     expectedWindowingMode, ACTIVITY_TYPE_STANDARD);
183         }
184 
185         // Now, tell it to finish itself and ensure that the assistant stack is brought back forward
186         mBroadcastActionTrigger.doAction(TEST_ACTIVITY_ACTION_FINISH_SELF);
187         mWmState.waitForFocusedStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
188         mWmState.assertFrontStackActivityType(
189                 "Assistant stack should be on top.", ACTIVITY_TYPE_ASSISTANT);
190         mWmState.assertFocusedRootTask("Assistant stack should be focused.",
191                 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
192     }
193 
194     @Test
testAssistantStackFinishToPreviousApp()195     public void testAssistantStackFinishToPreviousApp() throws Exception {
196         // If the Assistant is configured to be always-on-top, then the assistant activity
197         // started in setUp() will not allow any other activities to start. Therefore we should
198         // remove it before launching a fullscreen activity.
199         if (isAssistantOnTopOfDream()) {
200             removeRootTasksWithActivityTypes(ACTIVITY_TYPE_ASSISTANT);
201         }
202 
203         // Launch an assistant activity on top of an existing fullscreen activity, and ensure that
204         // the fullscreen activity is still visible and on top after the assistant activity finishes
205         launchActivityOnDisplay(TEST_ACTIVITY, WINDOWING_MODE_FULLSCREEN, mAssistantDisplayId);
206         try (final AssistantSession assistantSession = new AssistantSession()) {
207             assistantSession.setVoiceInteractionService(ASSISTANT_VOICE_INTERACTION_SERVICE);
208 
209             launchActivityNoWait(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
210                     extraString(EXTRA_ASSISTANT_FINISH_SELF, "true"));
211             mWmState.waitFor((amState) -> !amState.containsActivity(ASSISTANT_ACTIVITY),
212                     getActivityName(ASSISTANT_ACTIVITY) + " finished");
213         }
214         waitForValidStateWithActivityTypeAndWindowingMode(
215                 TEST_ACTIVITY, ACTIVITY_TYPE_STANDARD, mDefaultWindowingMode);
216         waitAndAssertTopResumedActivity(TEST_ACTIVITY, mAssistantDisplayId,
217                 "TestActivity should be resumed");
218         mWmState.assertFocusedActivity("TestActivity should be focused", TEST_ACTIVITY);
219         mWmState.assertFrontStack("Fullscreen stack should be on top.",
220                 mDefaultWindowingMode, ACTIVITY_TYPE_STANDARD);
221         mWmState.assertFocusedRootTask("Fullscreen stack should be focused.",
222                 mDefaultWindowingMode, ACTIVITY_TYPE_STANDARD);
223     }
224 
225     @Test
testDisallowEnterPiPFromAssistantStack()226     public void testDisallowEnterPiPFromAssistantStack() throws Exception {
227         try (final AssistantSession assistantSession = new AssistantSession()) {
228             assistantSession.setVoiceInteractionService(ASSISTANT_VOICE_INTERACTION_SERVICE);
229 
230             launchActivityNoWait(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
231                     extraString(EXTRA_ASSISTANT_ENTER_PIP, "true"));
232         }
233         waitForValidStateWithActivityType(ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
234         mWmState.assertDoesNotContainStack("Must not contain pinned stack.",
235                 WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD);
236     }
237 
238     @Test
testTranslucentAssistantActivityStackVisibility()239     public void testTranslucentAssistantActivityStackVisibility() throws Exception {
240         try (final AssistantSession assistantSession = new AssistantSession()) {
241             assistantSession.setVoiceInteractionService(ASSISTANT_VOICE_INTERACTION_SERVICE);
242 
243             // Go home, launch the assistant and check to see that home is visible
244             removeRootTasksInWindowingModes(WINDOWING_MODE_FULLSCREEN);
245             pressHomeButton();
246             resumeAppSwitches();
247             launchActivityNoWait(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
248                     extraString(EXTRA_ASSISTANT_IS_TRANSLUCENT, "true"));
249             waitForValidStateWithActivityType(
250                     TRANSLUCENT_ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
251             assertAssistantStackExists();
252             mWmState.waitForHomeActivityVisible();
253             if (hasHomeScreen()) {
254                 mWmState.assertHomeActivityVisible(true);
255             }
256 
257             // Launch a fullscreen app and then launch the assistant and check to see that it is
258             // also visible
259             removeRootTasksWithActivityTypes(ACTIVITY_TYPE_ASSISTANT);
260             launchActivityOnDisplay(TEST_ACTIVITY, WINDOWING_MODE_FULLSCREEN, mAssistantDisplayId);
261             launchActivityNoWait(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
262                     extraString(EXTRA_ASSISTANT_IS_TRANSLUCENT, "true"));
263             waitForValidStateWithActivityType(
264                     TRANSLUCENT_ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
265             assertAssistantStackExists();
266             mWmState.assertVisibility(TEST_ACTIVITY, true);
267 
268             // Go home, launch assistant, launch app into fullscreen with activity present, and go
269             // back.Ensure home is visible.
270             removeRootTasksWithActivityTypes(ACTIVITY_TYPE_ASSISTANT);
271             pressHomeButton();
272             resumeAppSwitches();
273             launchActivityNoWait(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
274                     extraString(EXTRA_ASSISTANT_IS_TRANSLUCENT, "true"),
275                     extraString(EXTRA_ASSISTANT_LAUNCH_NEW_TASK, getActivityName(TEST_ACTIVITY)));
276             waitForValidStateWithActivityTypeAndWindowingMode(
277                     TEST_ACTIVITY, ACTIVITY_TYPE_STANDARD, mDefaultWindowingMode);
278 
279             final ComponentName homeActivity = mWmState.getHomeActivityName();
280             int windowingMode = mWmState.getFocusedRootTaskWindowingMode();
281             // In a multi-window environment the home activity might not be fully covered
282             assumeTrue(windowingMode == WINDOWING_MODE_FULLSCREEN);
283             mWmState.waitAndAssertVisibilityGone(homeActivity);
284             mBroadcastActionTrigger.doAction(TEST_ACTIVITY_ACTION_FINISH_SELF);
285             mWmState.waitForFocusedStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
286             assertAssistantStackExists();
287             mWmState.waitForHomeActivityVisible();
288             if (hasHomeScreen()) {
289                 mWmState.assertHomeActivityVisible(true);
290             }
291 
292             // Launch a fullscreen and docked app and then launch the assistant and check to see
293             // that it
294             // is also visible
295             if (supportsSplitScreenMultiWindow() &&  assistantRunsOnPrimaryDisplay()) {
296                 removeRootTasksWithActivityTypes(ACTIVITY_TYPE_ASSISTANT);
297                 launchActivitiesInSplitScreen(
298                         getLaunchActivityBuilder().setTargetActivity(DOCKED_ACTIVITY),
299                         getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY));
300                 launchActivityNoWait(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
301                         extraString(EXTRA_ASSISTANT_IS_TRANSLUCENT, "true"));
302                 waitForValidStateWithActivityType(
303                         TRANSLUCENT_ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
304                 assertAssistantStackExists();
305                 mWmState.assertVisibility(DOCKED_ACTIVITY, true);
306                 mWmState.assertVisibility(TEST_ACTIVITY, true);
307             }
308         }
309     }
310 
311     @Test
testLaunchIntoSameTask()312     public void testLaunchIntoSameTask() throws Exception {
313         try (final AssistantSession assistantSession = new AssistantSession()) {
314             assistantSession.setVoiceInteractionService(ASSISTANT_VOICE_INTERACTION_SERVICE);
315 
316             // Launch the assistant
317             launchActivityOnDisplayNoWait(LAUNCH_ASSISTANT_ACTIVITY_FROM_SESSION,
318                     mAssistantDisplayId);
319             waitForValidStateWithActivityType(ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
320             assertAssistantStackExists();
321             mWmState.assertVisibility(ASSISTANT_ACTIVITY, true);
322             mWmState.assertFocusedRootTask("Expected assistant stack focused",
323                     WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
324             final WindowManagerState amState = mWmState;
325             assertThat(amState.getRootTaskByActivityType(ACTIVITY_TYPE_ASSISTANT).getTasks(),
326                     hasSize(1));
327             final int taskId = mWmState.getTaskByActivity(ASSISTANT_ACTIVITY)
328                     .mTaskId;
329 
330             // Launch a new fullscreen activity
331             // Using Animation Test Activity because it is opaque on all devices.
332             launchActivityOnDisplay(ANIMATION_TEST_ACTIVITY, WINDOWING_MODE_FULLSCREEN, mAssistantDisplayId);
333             // Wait for animation finished.
334             mWmState.waitForActivityState(ANIMATION_TEST_ACTIVITY, STATE_RESUMED);
335 
336             if (isAssistantOnTopOfDream()) {
337                 mWmState.assertVisibility(ASSISTANT_ACTIVITY, true);
338             } else {
339                 mWmState.waitAndAssertVisibilityGone(ASSISTANT_ACTIVITY);
340             }
341 
342             // Launch the assistant again and ensure that it goes into the same task
343             launchActivityOnDisplayNoWait(LAUNCH_ASSISTANT_ACTIVITY_FROM_SESSION,
344                     mAssistantDisplayId);
345             waitForValidStateWithActivityType(ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
346             assertAssistantStackExists();
347             mWmState.assertVisibility(ASSISTANT_ACTIVITY, true);
348             mWmState.assertFocusedRootTask("Expected assistant stack focused",
349                     WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
350             assertThat(amState.getRootTaskByActivityType(ACTIVITY_TYPE_ASSISTANT).getTasks(),
351                     hasSize(1));
352             assertEquals(taskId,
353                     mWmState.getTaskByActivity(ASSISTANT_ACTIVITY).mTaskId);
354 
355         }
356     }
357 
358     @Test
testPinnedStackWithAssistant()359     public void testPinnedStackWithAssistant() throws Exception {
360         assumeTrue(supportsPip());
361         assumeTrue(supportsSplitScreenMultiWindow());
362 
363         try (final AssistantSession assistantSession = new AssistantSession()) {
364             assistantSession.setVoiceInteractionService(ASSISTANT_VOICE_INTERACTION_SERVICE);
365 
366             // Launch a fullscreen activity and a PIP activity, then launch the assistant, and
367             // ensure that the test activity is still visible
368             launchActivity(TEST_ACTIVITY, WINDOWING_MODE_FULLSCREEN);
369             launchActivity(PIP_ACTIVITY, extraString(EXTRA_ENTER_PIP, "true"));
370             launchActivityNoWait(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
371                     extraString(EXTRA_ASSISTANT_IS_TRANSLUCENT, String.valueOf(true)));
372             waitForValidStateWithActivityType(
373                     TRANSLUCENT_ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
374             assertAssistantStackExists();
375             mWmState.assertVisibility(TRANSLUCENT_ASSISTANT_ACTIVITY, true);
376             mWmState.assertVisibility(PIP_ACTIVITY, true);
377             mWmState.assertVisibility(TEST_ACTIVITY, true);
378 
379         }
380     }
381 
waitForValidStateWithActivityType(ComponentName activityName, int activityType)382     private void waitForValidStateWithActivityType(ComponentName activityName, int activityType)
383             throws Exception {
384         mWmState.waitForValidState(new WaitForValidActivityState.Builder(activityName)
385                 .setActivityType(activityType)
386                 .build());
387     }
388 
waitForValidStateWithActivityTypeAndWindowingMode(ComponentName activityName, int activityType, int windowingMode)389     private void waitForValidStateWithActivityTypeAndWindowingMode(ComponentName activityName,
390             int activityType, int windowingMode) throws Exception {
391         mWmState.waitForValidState(new WaitForValidActivityState.Builder(activityName)
392                 .setActivityType(activityType)
393                 .setWindowingMode(windowingMode)
394                 .build());
395     }
396 
397     /**
398      * Asserts that the assistant stack exists.
399      */
assertAssistantStackExists()400     private void assertAssistantStackExists() throws Exception {
401         mWmState.assertContainsStack("Must contain assistant stack.",
402                 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
403     }
404 
405     // Any 2D Activity in VR mode is run on a special VR virtual display, so check if the Assistant
406     // is going to run on the same display as other tasks.
assistantRunsOnPrimaryDisplay()407     protected boolean assistantRunsOnPrimaryDisplay() {
408         return mAssistantDisplayId == DEFAULT_DISPLAY;
409     }
410 
411     /**
412      * @return Windowing Mode from the default display
413      */
getDefaultDisplayWindowingMode()414     private int getDefaultDisplayWindowingMode() {
415         mWmState.computeState();
416         return mWmState.getDisplay(DEFAULT_DISPLAY).getWindowingMode();
417     }
418 
419     /** Helper class to save, set, and restore
420      * {@link Settings.Secure#VOICE_INTERACTION_SERVICE} system preference.
421      */
422     private static class AssistantSession extends SettingsSession<String> {
AssistantSession()423         AssistantSession() {
424             super(Settings.Secure.getUriFor(Settings.Secure.VOICE_INTERACTION_SERVICE),
425                     Settings.Secure::getString, Settings.Secure::putString);
426         }
427 
setVoiceInteractionService(ComponentName assistantName)428         void setVoiceInteractionService(ComponentName assistantName) throws Exception {
429             super.set(getActivityName(assistantName));
430         }
431     }
432 }
433