Disallow launching non-embedded activity on virtual display. am: 470bb47655

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/opt/car/services/+/12998089

Change-Id: I033e4eb421ee42af4a880165687dc2c91cb1169d
diff --git a/src/com/android/server/wm/CarLaunchParamsModifier.java b/src/com/android/server/wm/CarLaunchParamsModifier.java
index 9e86c63..932c5a8 100644
--- a/src/com/android/server/wm/CarLaunchParamsModifier.java
+++ b/src/com/android/server/wm/CarLaunchParamsModifier.java
@@ -310,6 +310,13 @@
                             mSourcePreferredComponents, activity.info.getComponentName()) >= 0)) {
                 targetDisplayArea = source.noDisplay ? source.mHandoverTaskDisplayArea
                         : source.getDisplayArea();
+            } else if (originalDisplayArea == null
+                    && source != null && !source.getDisplayContent().isTrusted()
+                    && ((activity.info.flags & ActivityInfo.FLAG_ALLOW_EMBEDDED) == 0)) {
+                if (DBG) {
+                    Slog.d(TAG, "Disallow launch on virtual display for not-embedded activity.");
+                }
+                targetDisplayArea = getDefaultTaskDisplayAreaOnDisplay(Display.DEFAULT_DISPLAY);
             }
             if (userId == mCurrentDriverUser) {
                 // Respect the existing DisplayArea.
diff --git a/tests/src/com/android/server/wm/CarLaunchParamsModifierTest.java b/tests/src/com/android/server/wm/CarLaunchParamsModifierTest.java
index 5d9f8ba..53fd7ee 100644
--- a/tests/src/com/android/server/wm/CarLaunchParamsModifierTest.java
+++ b/tests/src/com/android/server/wm/CarLaunchParamsModifierTest.java
@@ -16,6 +16,11 @@
 
 package com.android.server.wm;
 
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.Display.FLAG_PRIVATE;
+import static android.view.Display.FLAG_TRUSTED;
+import static android.view.Display.INVALID_DISPLAY;
+
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
@@ -61,6 +66,7 @@
 public class CarLaunchParamsModifierTest {
     private static final int PASSENGER_DISPLAY_ID_10 = 10;
     private static final int PASSENGER_DISPLAY_ID_11 = 11;
+    private static final int VIRTUAL_DISPLAY_ID_2 = 2;
 
     private MockitoSession mMockingSession;
 
@@ -101,6 +107,10 @@
     private Display mDisplay11ForPassenger;
     @Mock
     private TaskDisplayArea mDisplayArea11ForPassenger;
+    @Mock
+    private Display mDisplay2Virtual;
+    @Mock
+    private TaskDisplayArea mDisplayArea2Virtual;
 
     // All mocks from here before CarLaunchParamsModifier are arguments for
     // LaunchParamsModifier.onCalculate() call.
@@ -132,6 +142,7 @@
         when(mRootWindowContainer.getDisplayContentOrCreate(displayId)).thenReturn(dc);
         when(dc.getDisplay()).thenReturn(display);
         when(dc.getDefaultTaskDisplayArea()).thenReturn(defaultTaskDisplayArea);
+        when(dc.isTrusted()).thenReturn((flags & FLAG_TRUSTED) == FLAG_TRUSTED);
     }
 
     @Before
@@ -153,13 +164,19 @@
         AttributeCache.init(getInstrumentation().getTargetContext());
         LocalServices.addService(ColorDisplayService.ColorDisplayServiceInternal.class,
                 mColorDisplayServiceInternal);
-        when(mActivityOptions.getLaunchDisplayId()).thenReturn(Display.INVALID_DISPLAY);
-        mockDisplay(mDisplay0ForDriver, mDisplayArea0ForDriver, 0, 0, 0);
+        when(mActivityOptions.getLaunchDisplayId()).thenReturn(INVALID_DISPLAY);
+        mockDisplay(mDisplay0ForDriver, mDisplayArea0ForDriver, DEFAULT_DISPLAY,
+                FLAG_TRUSTED, /* type */ 0);
         mockDisplay(mDisplay10ForPassenger, mDisplayArea10ForPassenger, PASSENGER_DISPLAY_ID_10,
-                /* flags */ 0, /* type */ 0);
+                FLAG_TRUSTED, /* type */ 0);
         mockDisplay(mDisplay11ForPassenger, mDisplayArea11ForPassenger, PASSENGER_DISPLAY_ID_11,
-                /* flags */ 0, /* type */ 0);
-        mockDisplay(mDisplay1Private, mDisplayArea1Private, 1, Display.FLAG_PRIVATE, 0);
+                FLAG_TRUSTED, /* type */ 0);
+        mockDisplay(mDisplay1Private, mDisplayArea1Private, 1,
+                FLAG_TRUSTED | FLAG_PRIVATE, /* type */ 0);
+        mockDisplay(mDisplay2Virtual, mDisplayArea2Virtual, VIRTUAL_DISPLAY_ID_2,
+                /* no-trusted */ FLAG_PRIVATE, /* type */ 0);
+        DisplayContent defaultDc = mRootWindowContainer.getDisplayContentOrCreate(DEFAULT_DISPLAY);
+        when(mActivityRecordSource.getDisplayContent()).thenReturn(defaultDc);
 
         mModifier = new CarLaunchParamsModifier(mContext);
         mModifier.init();
@@ -492,4 +509,26 @@
 
         assertNoDisplayIsAssigned(UserHandle.USER_SYSTEM);
     }
+
+    @Test
+    public void testEmbeddedActivityCanLaunchOnVirtualDisplay() {
+        // The launch request comes from the Activity in Virtual display.
+        DisplayContent dc = mRootWindowContainer.getDisplayContentOrCreate(VIRTUAL_DISPLAY_ID_2);
+        when(mActivityRecordSource.getDisplayContent()).thenReturn(dc);
+        mActivityRecordActivity = buildActivityRecord("testPackage", "testActivity");
+        mActivityRecordActivity.info.flags = ActivityInfo.FLAG_ALLOW_EMBEDDED;
+
+        // ATM will launch the Activity in the source display, since no display is assigned.
+        assertNoDisplayIsAssigned(UserHandle.USER_SYSTEM);
+    }
+
+    @Test
+    public void testNonEmbeddedActivityMoviesToDefaultDisplay() {
+        // The launch request comes from the Activity in Virtual display.
+        DisplayContent dc = mRootWindowContainer.getDisplayContentOrCreate(VIRTUAL_DISPLAY_ID_2);
+        when(mActivityRecordSource.getDisplayContent()).thenReturn(dc);
+        mActivityRecordActivity = buildActivityRecord("testPackage", "testActivity");
+
+        assertDisplayIsAssigned(UserHandle.USER_SYSTEM, mDisplayArea0ForDriver);
+    }
 }