Home | History | Annotate | Download | only in am
      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.am;
     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_SPLIT_SCREEN_PRIMARY;
     24 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
     25 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
     26 import static android.server.am.ActivityManagerState.STATE_RESUMED;
     27 import static android.server.am.ComponentNameUtils.getActivityName;
     28 import static android.server.am.Components.ANIMATION_TEST_ACTIVITY;
     29 import static android.server.am.Components.ASSISTANT_ACTIVITY;
     30 import static android.server.am.Components.ASSISTANT_VOICE_INTERACTION_SERVICE;
     31 import static android.server.am.Components.AssistantActivity.EXTRA_ASSISTANT_DISPLAY_ID;
     32 import static android.server.am.Components.AssistantActivity.EXTRA_ASSISTANT_ENTER_PIP;
     33 import static android.server.am.Components.AssistantActivity.EXTRA_ASSISTANT_FINISH_SELF;
     34 import static android.server.am.Components.AssistantActivity.EXTRA_ASSISTANT_LAUNCH_NEW_TASK;
     35 import static android.server.am.Components.DOCKED_ACTIVITY;
     36 import static android.server.am.Components.LAUNCH_ASSISTANT_ACTIVITY_FROM_SESSION;
     37 import static android.server.am.Components.LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK;
     38 import static android.server.am.Components.LaunchAssistantActivityIntoAssistantStack
     39         .EXTRA_ASSISTANT_IS_TRANSLUCENT;
     40 import static android.server.am.Components.PIP_ACTIVITY;
     41 import static android.server.am.Components.PipActivity.EXTRA_ENTER_PIP;
     42 import static android.server.am.Components.TEST_ACTIVITY;
     43 import static android.server.am.Components.TRANSLUCENT_ASSISTANT_ACTIVITY;
     44 import static android.server.am.Components.TestActivity.TEST_ACTIVITY_ACTION_FINISH_SELF;
     45 import static android.server.am.UiDeviceUtils.pressBackButton;
     46 import static android.view.Display.DEFAULT_DISPLAY;
     47 
     48 import static org.hamcrest.Matchers.hasSize;
     49 import static org.junit.Assert.assertEquals;
     50 import static org.junit.Assert.assertThat;
     51 import static org.junit.Assert.assertTrue;
     52 import static org.junit.Assume.assumeTrue;
     53 
     54 import android.content.ComponentName;
     55 import android.platform.test.annotations.Presubmit;
     56 import android.provider.Settings;
     57 import android.server.am.settings.SettingsSession;
     58 import android.support.test.filters.FlakyTest;
     59 
     60 import org.junit.Ignore;
     61 import org.junit.Test;
     62 
     63 /**
     64  * Build/Install/Run:
     65  *     atest CtsActivityManagerDeviceTestCases:ActivityManagerAssistantStackTests
     66  */
     67 //@Presubmit b/67706642
     68 @FlakyTest(bugId = 71875631)
     69 public class ActivityManagerAssistantStackTests extends ActivityManagerTestBase {
     70 
     71     private int mAssistantDisplayId = DEFAULT_DISPLAY;
     72 
     73     public void setUp() throws Exception {
     74         super.setUp();
     75         try (final AssistantSession assistantSession = new AssistantSession()) {
     76             assistantSession.setVoiceInteractionService(ASSISTANT_VOICE_INTERACTION_SERVICE);
     77             launchActivityNoWait(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK);
     78             waitForValidStateWithActivityType(ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
     79             ActivityManagerState.ActivityStack assistantStack =
     80                     mAmWmState.getAmState().getStackByActivityType(ACTIVITY_TYPE_ASSISTANT);
     81             mAssistantDisplayId = assistantStack.mDisplayId;
     82         }
     83     }
     84 
     85     @Test
     86     @Presubmit
     87     public void testLaunchingAssistantActivityIntoAssistantStack() throws Exception {
     88         // Enable the assistant and launch an assistant activity
     89         try (final AssistantSession assistantSession = new AssistantSession()) {
     90             assistantSession.setVoiceInteractionService(ASSISTANT_VOICE_INTERACTION_SERVICE);
     91 
     92             launchActivityNoWait(LAUNCH_ASSISTANT_ACTIVITY_FROM_SESSION);
     93             waitForValidStateWithActivityType(ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
     94 
     95             // Ensure that the activity launched in the fullscreen assistant stack
     96             assertAssistantStackExists();
     97             assertTrue("Expected assistant stack to be fullscreen",
     98                     mAmWmState.getAmState().getStackByActivityType(
     99                             ACTIVITY_TYPE_ASSISTANT).isFullscreen());
    100         }
    101     }
    102 
    103     @FlakyTest(bugId = 69573940)
    104     @Presubmit
    105     @Test
    106     public void testAssistantStackZOrder() throws Exception {
    107         assumeTrue(assistantRunsOnPrimaryDisplay());
    108         assumeTrue(supportsPip());
    109         assumeTrue(supportsSplitScreenMultiWindow());
    110 
    111         // Launch a pinned stack task
    112         launchActivity(PIP_ACTIVITY, EXTRA_ENTER_PIP, "true");
    113         waitForValidStateWithActivityTypeAndWindowingMode(
    114                 PIP_ACTIVITY, ACTIVITY_TYPE_STANDARD, WINDOWING_MODE_PINNED);
    115         mAmWmState.assertContainsStack("Must contain pinned stack.",
    116                 WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD);
    117 
    118         // Dock a task
    119         launchActivitiesInSplitScreen(
    120                 getLaunchActivityBuilder().setTargetActivity(DOCKED_ACTIVITY),
    121                 getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY));
    122         mAmWmState.assertContainsStack("Must contain fullscreen stack.",
    123                 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD);
    124         mAmWmState.assertContainsStack("Must contain docked stack.",
    125                 WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD);
    126 
    127         // Enable the assistant and launch an assistant activity, ensure it is on top
    128         try (final AssistantSession assistantSession = new AssistantSession()) {
    129             assistantSession.setVoiceInteractionService(ASSISTANT_VOICE_INTERACTION_SERVICE);
    130 
    131             launchActivityNoWait(LAUNCH_ASSISTANT_ACTIVITY_FROM_SESSION);
    132             waitForValidStateWithActivityType(ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
    133             assertAssistantStackExists();
    134 
    135             mAmWmState.assertFrontStack("Pinned stack should be on top.",
    136                     WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD);
    137             mAmWmState.assertFocusedStack("Assistant stack should be focused.",
    138                     WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
    139         }
    140     }
    141 
    142     @Test
    143     @Presubmit
    144     public void testAssistantStackLaunchNewTask() throws Exception {
    145         assertAssistantStackCanLaunchAndReturnFromNewTask(WINDOWING_MODE_FULLSCREEN);
    146     }
    147 
    148     @Test
    149     @Presubmit
    150     @Ignore("b/77272253#comment10")
    151     public void testAssistantStackLaunchNewTaskWithDockedStack() throws Exception {
    152         assumeTrue(assistantRunsOnPrimaryDisplay());
    153         assumeTrue(supportsSplitScreenMultiWindow());
    154 
    155         // Dock a task
    156         launchActivitiesInSplitScreen(
    157                 getLaunchActivityBuilder().setTargetActivity(DOCKED_ACTIVITY),
    158                 getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY));
    159         mAmWmState.assertContainsStack("Must contain fullscreen stack.",
    160                 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD);
    161         mAmWmState.assertContainsStack("Must contain docked stack.",
    162                 WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD);
    163 
    164         assertAssistantStackCanLaunchAndReturnFromNewTask(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
    165     }
    166 
    167     private void assertAssistantStackCanLaunchAndReturnFromNewTask(int expectedWindowingMode)
    168             throws Exception {
    169         // Enable the assistant and launch an assistant activity which will launch a new task
    170         try (final AssistantSession assistantSession = new AssistantSession()) {
    171             assistantSession.setVoiceInteractionService(ASSISTANT_VOICE_INTERACTION_SERVICE);
    172 
    173             launchActivityOnDisplayNoWait(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK, mAssistantDisplayId,
    174                     EXTRA_ASSISTANT_LAUNCH_NEW_TASK, getActivityName(TEST_ACTIVITY),
    175                     EXTRA_ASSISTANT_DISPLAY_ID, Integer.toString(mAssistantDisplayId));
    176             // Ensure that the fullscreen stack is on top and the test activity is now visible
    177             waitForValidStateWithActivityTypeAndWindowingMode(
    178                     TEST_ACTIVITY, ACTIVITY_TYPE_STANDARD, expectedWindowingMode);
    179         }
    180 
    181         mAmWmState.assertFocusedActivity("TestActivity should be resumed", TEST_ACTIVITY);
    182         mAmWmState.assertFrontStack("Fullscreen stack should be on top.",
    183                 expectedWindowingMode, ACTIVITY_TYPE_STANDARD);
    184         mAmWmState.assertFocusedStack("Fullscreen stack should be focused.",
    185                 expectedWindowingMode, ACTIVITY_TYPE_STANDARD);
    186 
    187         // Now, tell it to finish itself and ensure that the assistant stack is brought back forward
    188         executeShellCommand("am broadcast -a " + TEST_ACTIVITY_ACTION_FINISH_SELF);
    189         mAmWmState.waitForFocusedStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
    190         mAmWmState.assertFrontStackActivityType(
    191                 "Assistant stack should be on top.", ACTIVITY_TYPE_ASSISTANT);
    192         mAmWmState.assertFocusedStack("Assistant stack should be focused.",
    193                 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
    194     }
    195 
    196     @Test
    197     @Presubmit
    198     @FlakyTest(bugId = 71875631)
    199     public void testAssistantStackFinishToPreviousApp() throws Exception {
    200         // Launch an assistant activity on top of an existing fullscreen activity, and ensure that
    201         // the fullscreen activity is still visible and on top after the assistant activity finishes
    202         launchActivityOnDisplay(TEST_ACTIVITY, mAssistantDisplayId);
    203         try (final AssistantSession assistantSession = new AssistantSession()) {
    204             assistantSession.setVoiceInteractionService(ASSISTANT_VOICE_INTERACTION_SERVICE);
    205 
    206             launchActivityNoWait(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
    207                     EXTRA_ASSISTANT_FINISH_SELF, "true");
    208             mAmWmState.waitFor((amState, wmState) -> !amState.containsActivity(ASSISTANT_ACTIVITY),
    209                     "Waiting for " + getActivityName(ASSISTANT_ACTIVITY) + " finished");
    210         }
    211         waitForValidStateWithActivityTypeAndWindowingMode(
    212                 TEST_ACTIVITY, ACTIVITY_TYPE_STANDARD, WINDOWING_MODE_FULLSCREEN);
    213         mAmWmState.waitForActivityState(TEST_ACTIVITY, STATE_RESUMED);
    214         mAmWmState.assertFocusedActivity("TestActivity should be resumed", TEST_ACTIVITY);
    215         mAmWmState.assertFrontStack("Fullscreen stack should be on top.",
    216                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
    217         mAmWmState.assertFocusedStack("Fullscreen stack should be focused.",
    218                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
    219     }
    220 
    221     @Test
    222     @Presubmit
    223     @FlakyTest(bugId = 71875631)
    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                     EXTRA_ASSISTANT_ENTER_PIP, "true");
    230         }
    231         waitForValidStateWithActivityType(ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
    232         mAmWmState.assertDoesNotContainStack("Must not contain pinned stack.",
    233                 WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD);
    234     }
    235 
    236     @FlakyTest(bugId = 69573940)
    237     @Presubmit
    238     @Test
    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             removeStacksInWindowingModes(WINDOWING_MODE_FULLSCREEN,
    245                     WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
    246             launchHomeActivity();
    247             launchActivityNoWait(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
    248                     EXTRA_ASSISTANT_IS_TRANSLUCENT, "true");
    249             waitForValidStateWithActivityType(
    250                     TRANSLUCENT_ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
    251             assertAssistantStackExists();
    252             mAmWmState.waitForHomeActivityVisible();
    253             if (hasHomeScreen()) {
    254                 mAmWmState.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             removeStacksWithActivityTypes(ACTIVITY_TYPE_ASSISTANT);
    260             launchActivityOnDisplay(TEST_ACTIVITY, mAssistantDisplayId);
    261             launchActivityNoWait(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
    262                     EXTRA_ASSISTANT_IS_TRANSLUCENT, "true");
    263             waitForValidStateWithActivityType(
    264                     TRANSLUCENT_ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
    265             assertAssistantStackExists();
    266             mAmWmState.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             removeStacksWithActivityTypes(ACTIVITY_TYPE_ASSISTANT);
    271             launchHomeActivity();
    272             launchActivityNoWait(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
    273                     EXTRA_ASSISTANT_IS_TRANSLUCENT, "true",
    274                     EXTRA_ASSISTANT_LAUNCH_NEW_TASK, getActivityName(TEST_ACTIVITY));
    275             waitForValidStateWithActivityTypeAndWindowingMode(
    276                     TEST_ACTIVITY, ACTIVITY_TYPE_STANDARD, WINDOWING_MODE_FULLSCREEN);
    277             boolean isTranslucent = mAmWmState.getAmState().isActivityTranslucent(TEST_ACTIVITY);
    278             // Home should be visible if the occluding activity is translucent, else home shouldn't
    279             // be visible.
    280             mAmWmState.assertHomeActivityVisible(isTranslucent);
    281             pressBackButton();
    282             mAmWmState.waitForFocusedStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
    283             assertAssistantStackExists();
    284             mAmWmState.waitForHomeActivityVisible();
    285             if (hasHomeScreen()) {
    286                 mAmWmState.assertHomeActivityVisible(true);
    287             }
    288 
    289             // Launch a fullscreen and docked app and then launch the assistant and check to see
    290             // that it
    291             // is also visible
    292             if (supportsSplitScreenMultiWindow() &&  assistantRunsOnPrimaryDisplay()) {
    293                 removeStacksWithActivityTypes(ACTIVITY_TYPE_ASSISTANT);
    294                 launchActivitiesInSplitScreen(
    295                         getLaunchActivityBuilder().setTargetActivity(DOCKED_ACTIVITY),
    296                         getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY));
    297                 mAmWmState.assertContainsStack("Must contain docked stack.",
    298                         WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD);
    299                 launchActivityNoWait(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
    300                         EXTRA_ASSISTANT_IS_TRANSLUCENT, "true");
    301                 waitForValidStateWithActivityType(
    302                         TRANSLUCENT_ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
    303                 assertAssistantStackExists();
    304                 mAmWmState.assertVisibility(DOCKED_ACTIVITY, true);
    305                 mAmWmState.assertVisibility(TEST_ACTIVITY, true);
    306             }
    307         }
    308     }
    309 
    310     @FlakyTest(bugId = 69229402)
    311     @Test
    312     @Presubmit
    313     public void testLaunchIntoSameTask() throws Exception {
    314         try (final AssistantSession assistantSession = new AssistantSession()) {
    315             assistantSession.setVoiceInteractionService(ASSISTANT_VOICE_INTERACTION_SERVICE);
    316 
    317             // Launch the assistant
    318             launchActivityOnDisplayNoWait(LAUNCH_ASSISTANT_ACTIVITY_FROM_SESSION,
    319                     mAssistantDisplayId);
    320             waitForValidStateWithActivityType(ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
    321             assertAssistantStackExists();
    322             mAmWmState.assertVisibility(ASSISTANT_ACTIVITY, true);
    323             mAmWmState.assertFocusedStack("Expected assistant stack focused",
    324                     WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
    325             final ActivityManagerState amState = mAmWmState.getAmState();
    326             assertThat(amState.getStackByActivityType(ACTIVITY_TYPE_ASSISTANT).getTasks(),
    327                     hasSize(1));
    328             final int taskId = mAmWmState.getAmState().getTaskByActivity(ASSISTANT_ACTIVITY)
    329                     .mTaskId;
    330 
    331             // Launch a new fullscreen activity
    332             // Using Animation Test Activity because it is opaque on all devices.
    333             launchActivityOnDisplay(ANIMATION_TEST_ACTIVITY, mAssistantDisplayId);
    334             // Wait for animation finished.
    335             mAmWmState.waitForActivityState(ANIMATION_TEST_ACTIVITY, STATE_RESUMED);
    336             mAmWmState.assertVisibility(ASSISTANT_ACTIVITY, false);
    337 
    338             // Launch the assistant again and ensure that it goes into the same task
    339             launchActivityOnDisplayNoWait(LAUNCH_ASSISTANT_ACTIVITY_FROM_SESSION,
    340                     mAssistantDisplayId);
    341             waitForValidStateWithActivityType(ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
    342             assertAssistantStackExists();
    343             mAmWmState.assertVisibility(ASSISTANT_ACTIVITY, true);
    344             mAmWmState.assertFocusedStack("Expected assistant stack focused",
    345                     WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
    346             assertThat(amState.getStackByActivityType(ACTIVITY_TYPE_ASSISTANT).getTasks(),
    347                     hasSize(1));
    348             assertEquals(taskId,
    349                     mAmWmState.getAmState().getTaskByActivity(ASSISTANT_ACTIVITY).mTaskId);
    350 
    351         }
    352     }
    353 
    354     @Test
    355     public void testPinnedStackWithAssistant() throws Exception {
    356         assumeTrue(supportsPip());
    357         assumeTrue(supportsSplitScreenMultiWindow());
    358 
    359         try (final AssistantSession assistantSession = new AssistantSession()) {
    360             assistantSession.setVoiceInteractionService(ASSISTANT_VOICE_INTERACTION_SERVICE);
    361 
    362             // Launch a fullscreen activity and a PIP activity, then launch the assistant, and
    363             // ensure that the test activity is still visible
    364             launchActivity(TEST_ACTIVITY);
    365             launchActivity(PIP_ACTIVITY, EXTRA_ENTER_PIP, "true");
    366             launchActivityNoWait(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
    367                     EXTRA_ASSISTANT_IS_TRANSLUCENT, String.valueOf(true));
    368             waitForValidStateWithActivityType(
    369                     TRANSLUCENT_ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
    370             assertAssistantStackExists();
    371             mAmWmState.assertVisibility(TRANSLUCENT_ASSISTANT_ACTIVITY, true);
    372             mAmWmState.assertVisibility(PIP_ACTIVITY, true);
    373             mAmWmState.assertVisibility(TEST_ACTIVITY, true);
    374 
    375         }
    376     }
    377 
    378     private void waitForValidStateWithActivityType(ComponentName activityName, int activityType)
    379             throws Exception {
    380         mAmWmState.waitForValidState(new WaitForValidActivityState.Builder(activityName)
    381                 .setActivityType(activityType)
    382                 .build());
    383     }
    384 
    385     private void waitForValidStateWithActivityTypeAndWindowingMode(ComponentName activityName,
    386             int activityType, int windowingMode) throws Exception {
    387         mAmWmState.waitForValidState(new WaitForValidActivityState.Builder(activityName)
    388                 .setActivityType(activityType)
    389                 .setWindowingMode(windowingMode)
    390                 .build());
    391     }
    392 
    393     /**
    394      * Asserts that the assistant stack exists.
    395      */
    396     private void assertAssistantStackExists() throws Exception {
    397         mAmWmState.assertContainsStack("Must contain assistant stack.",
    398                 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
    399     }
    400 
    401     // Any 2D Activity in VR mode is run on a special VR virtual display, so check if the Assistant
    402     // is going to run on the same display as other tasks.
    403     protected boolean assistantRunsOnPrimaryDisplay() {
    404         return mAssistantDisplayId == DEFAULT_DISPLAY;
    405     }
    406 
    407     /** Helper class to save, set, and restore
    408      * {@link Settings.Secure#VOICE_INTERACTION_SERVICE} system preference.
    409      */
    410     private static class AssistantSession extends SettingsSession<String> {
    411         AssistantSession() {
    412             super(Settings.Secure.getUriFor(Settings.Secure.VOICE_INTERACTION_SERVICE),
    413                     Settings.Secure::getString, Settings.Secure::putString);
    414         }
    415 
    416         void setVoiceInteractionService(ComponentName assistantName) throws Exception {
    417             super.set(getActivityName(assistantName));
    418         }
    419     }
    420 }
    421