25
25
import android .app .Instrumentation .ActivityResult ;
26
26
import android .content .ComponentName ;
27
27
import android .content .Intent ;
28
+ import android .content .pm .PackageManager ;
29
+ import android .content .pm .PackageManager .Property ;
28
30
import android .os .Build .VERSION ;
29
31
import android .os .Bundle ;
30
32
import android .os .Looper ;
@@ -200,7 +202,7 @@ private ActivityScenario(Class<A> activityClass) {
200
202
*/
201
203
public static <A extends Activity > ActivityScenario <A > launch (Class <A > activityClass ) {
202
204
ActivityScenario <A > scenario = new ActivityScenario <>(checkNotNull (activityClass ));
203
- scenario .launchInternal (/*activityOptions=*/ null , /*launchActivityForResult=*/ false );
205
+ scenario .checkXrAndLaunchInternal (/* activityOptions= */ null );
204
206
return scenario ;
205
207
}
206
208
@@ -213,7 +215,7 @@ public static <A extends Activity> ActivityScenario<A> launch(Class<A> activityC
213
215
public static <A extends Activity > ActivityScenario <A > launch (
214
216
Class <A > activityClass , @ Nullable Bundle activityOptions ) {
215
217
ActivityScenario <A > scenario = new ActivityScenario <>(checkNotNull (activityClass ));
216
- scenario .launchInternal (activityOptions , /*launchActivityForResult=*/ false );
218
+ scenario .checkXrAndLaunchInternal (activityOptions );
217
219
return scenario ;
218
220
}
219
221
@@ -234,7 +236,7 @@ public static <A extends Activity> ActivityScenario<A> launch(
234
236
*/
235
237
public static <A extends Activity > ActivityScenario <A > launch (Intent startActivityIntent ) {
236
238
ActivityScenario <A > scenario = new ActivityScenario <>(checkNotNull (startActivityIntent ));
237
- scenario .launchInternal (/*activityOptions=*/ null , /*launchActivityForResult=*/ false );
239
+ scenario .checkXrAndLaunchInternal (/* activityOptions= */ null );
238
240
return scenario ;
239
241
}
240
242
@@ -249,7 +251,7 @@ public static <A extends Activity> ActivityScenario<A> launch(Intent startActivi
249
251
public static <A extends Activity > ActivityScenario <A > launch (
250
252
Intent startActivityIntent , @ Nullable Bundle activityOptions ) {
251
253
ActivityScenario <A > scenario = new ActivityScenario <>(checkNotNull (startActivityIntent ));
252
- scenario .launchInternal (activityOptions , /*launchActivityForResult=*/ false );
254
+ scenario .checkXrAndLaunchInternal (activityOptions );
253
255
return scenario ;
254
256
}
255
257
@@ -383,6 +385,39 @@ private void launchInternal(@Nullable Bundle activityOptions, boolean launchActi
383
385
}
384
386
}
385
387
388
+ /**
389
+ * An internal helper method for handling launching the activity for the given scenario instance
390
+ * on XR devices.
391
+ *
392
+ * @param activityOptions activity options bundle to be passed when launching this activity
393
+ */
394
+ private void checkXrAndLaunchInternal (@ Nullable Bundle activityOptions ) {
395
+ // Activities cannot be launched in full screen mode from the application context on XR devices.
396
+ // Check if the current device is an XR device and fall back to launching activity for result
397
+ // if the android.window.PROPERTY_XR_ACTIVITY_START_MODE property is set to full screen mode
398
+ // so that the bootstrap activity can act as a temporary focused activity which the requested
399
+ // activity is launched from.
400
+ PackageManager packageManager = getInstrumentation ().getTargetContext ().getPackageManager ();
401
+ if (packageManager .hasSystemFeature ("android.software.xr.immersive" )) {
402
+ String packageName = getInstrumentation ().getTargetContext ().getPackageName ();
403
+ try {
404
+ Property startMode =
405
+ packageManager .getProperty (
406
+ "android.window.PROPERTY_XR_ACTIVITY_START_MODE" , packageName );
407
+ if (startMode .getString ().equals ("XR_ACTIVITY_START_MODE_FULL_SPACE_MANAGED" )
408
+ || startMode .getString ().equals ("XR_ACTIVITY_START_MODE_FULL_SPACE_UNMANAGED" )) {
409
+ launchInternal (activityOptions , true );
410
+ } else {
411
+ launchInternal (activityOptions , false );
412
+ }
413
+ } catch (PackageManager .NameNotFoundException e ) {
414
+ launchInternal (activityOptions , false );
415
+ }
416
+ } else {
417
+ launchInternal (activityOptions , false );
418
+ }
419
+ }
420
+
386
421
/**
387
422
* Finishes the managed activity and cleans up device's state. This method blocks execution until
388
423
* the activity becomes {@link State#DESTROYED}.
0 commit comments