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