DO NOT MERGE Add permission to launch activities on VD

1. Added permission ACTIVITY_EMBEDDING which allows apps to launch
activities on virtual displays.
2. Allow owner of display to launch activities from same app without
permission check to owned display.
3. Added permission checks for launching on secondary displays to
more target task/stack resolution paths in ActivityStarter.

Bug: 63117330
Test: android.server.cts.ActivityManagerDisplayTests
Test: go/wm-smoke
Change-Id: If169a77fb56241e06f7de20168dc38c4b0a217f5
(cherry picked from commit 71587649836d8e97c2ca00d968fc95293b59b0d3)
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 90d9149..fcdb91f 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -17,7 +17,6 @@
 package com.android.server.am;
 
 import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
-import static android.Manifest.permission.MANAGE_ACTIVITY_STACKS;
 import static android.Manifest.permission.START_ANY_ACTIVITY;
 import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
 import static android.app.ActivityManager.LOCK_TASK_MODE_LOCKED;
@@ -491,9 +490,27 @@
     }
 
     /** Check if placing task or activity on specified display is allowed. */
-    boolean canPlaceEntityOnDisplay(int displayId, boolean resizeable) {
-        return displayId == DEFAULT_DISPLAY || (mService.mSupportsMultiDisplay
-                && (resizeable || displayConfigMatchesGlobal(displayId)));
+    boolean canPlaceEntityOnDisplay(int displayId, boolean resizeable, int callingPid,
+            int callingUid, ActivityInfo activityInfo) {
+        if (displayId == DEFAULT_DISPLAY) {
+            // No restrictions for the default display.
+            return true;
+        }
+        if (!mService.mSupportsMultiDisplay) {
+            // Can't launch on secondary displays if feature is not supported.
+            return false;
+        }
+        if (!resizeable && !displayConfigMatchesGlobal(displayId)) {
+            // Can't apply wrong configuration to non-resizeable activities.
+            return false;
+        }
+        if (!isCallerAllowedToLaunchOnDisplay(callingPid, callingUid, displayId, activityInfo)) {
+            // Can't place activities to a display that has restricted launch rules.
+            // In this case the request should be made by explicitly adding target display id and
+            // by caller with corresponding permissions. See #isCallerAllowedToLaunchOnDisplay().
+            return false;
+        }
+        return true;
     }
 
     /**
@@ -1679,8 +1696,8 @@
             // Check if someone tries to launch an activity on a private display with a different
             // owner.
             final int launchDisplayId = options.getLaunchDisplayId();
-            if (launchDisplayId != INVALID_DISPLAY
-                    && !isCallerAllowedToLaunchOnDisplay(callingPid, callingUid, launchDisplayId)) {
+            if (launchDisplayId != INVALID_DISPLAY && !isCallerAllowedToLaunchOnDisplay(callingPid,
+                    callingUid, launchDisplayId, aInfo)) {
                 final String msg = "Permission Denial: starting " + intent.toString()
                         + " from " + callerApp + " (pid=" + callingPid
                         + ", uid=" + callingUid + ") with launchDisplayId="
@@ -1694,17 +1711,24 @@
     }
 
     /** Check if caller is allowed to launch activities on specified display. */
-    boolean isCallerAllowedToLaunchOnDisplay(int callingPid, int callingUid, int launchDisplayId) {
+    boolean isCallerAllowedToLaunchOnDisplay(int callingPid, int callingUid, int launchDisplayId,
+            ActivityInfo aInfo) {
         if (DEBUG_TASKS) Slog.d(TAG, "Launch on display check: displayId=" + launchDisplayId
                 + " callingPid=" + callingPid + " callingUid=" + callingUid);
 
+        if (callingPid == -1 && callingUid == -1) {
+            if (DEBUG_TASKS) Slog.d(TAG, "Launch on display check: no caller info, skip check");
+            return true;
+        }
+
         final ActivityDisplay activityDisplay = getActivityDisplayOrCreateLocked(launchDisplayId);
         if (activityDisplay == null) {
             Slog.w(TAG, "Launch on display check: display not found");
             return false;
         }
 
-        // Check if the caller can manage activity stacks.
+        // Check if the caller has enough privileges to embed activities and launch to private
+        // displays.
         final int startAnyPerm = mService.checkPermission(INTERNAL_SYSTEM_WINDOW, callingPid,
                 callingUid);
         if (startAnyPerm == PERMISSION_GRANTED) {
@@ -1714,12 +1738,15 @@
         }
 
         if (activityDisplay.mDisplay.getType() == TYPE_VIRTUAL
-                && activityDisplay.mDisplay.getOwnerUid() != SYSTEM_UID) {
+                && activityDisplay.mDisplay.getOwnerUid() != SYSTEM_UID
+                && activityDisplay.mDisplay.getOwnerUid() != aInfo.applicationInfo.uid) {
             // Limit launching on virtual displays, because their contents can be read from Surface
             // by apps that created them.
-            if (DEBUG_TASKS) Slog.d(TAG, "Launch on display check:"
-                    + " disallow launch on virtual display for not-embedded activity");
-            return false;
+            if ((aInfo.flags & ActivityInfo.FLAG_ALLOW_EMBEDDED) == 0) {
+                if (DEBUG_TASKS) Slog.d(TAG, "Launch on display check:"
+                        + " disallow launch on virtual display for not-embedded activity.");
+                return false;
+            }
         }
 
         if (!activityDisplay.isPrivate()) {