Merge "Allow embedding activities cross apps" into sc-v2-dev
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index c881359..4e73bf3 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -24,6 +24,7 @@
 import static android.app.ActivityManager.START_CLASS_NOT_FOUND;
 import static android.app.ActivityManager.START_DELIVERED_TO_TOP;
 import static android.app.ActivityManager.START_FLAG_ONLY_IF_NEEDED;
+import static android.app.ActivityManager.START_PERMISSION_DENIED;
 import static android.app.ActivityManager.START_RETURN_INTENT_TO_CALLER;
 import static android.app.ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
 import static android.app.ActivityManager.START_SUCCESS;
@@ -744,7 +745,7 @@
                 Slog.w(TAG, "Unable to find app for caller " + mRequest.caller + " (pid="
                         + mRequest.callingPid + ") when starting: " + mRequest.intent.toString());
                 SafeActivityOptions.abort(mRequest.activityOptions);
-                return ActivityManager.START_PERMISSION_DENIED;
+                return START_PERMISSION_DENIED;
             }
         }
 
@@ -858,7 +859,7 @@
             } else {
                 Slog.w(TAG, "Unable to find app for caller " + caller + " (pid=" + callingPid
                         + ") when starting: " + intent.toString());
-                err = ActivityManager.START_PERMISSION_DENIED;
+                err = START_PERMISSION_DENIED;
             }
         }
 
@@ -1952,10 +1953,41 @@
             }
         }
 
+        if (mInTaskFragment != null && mInTaskFragment.getTask() != null) {
+            final int hostUid = mInTaskFragment.getTask().effectiveUid;
+            final int embeddingUid = targetTask != null ? targetTask.effectiveUid : r.getUid();
+            if (!canTaskBeEmbedded(hostUid, embeddingUid)) {
+                Slog.e(TAG, "Cannot embed activity to a task owned by " + hostUid + " targetTask= "
+                        + targetTask);
+                return START_PERMISSION_DENIED;
+            }
+        }
+
         return START_SUCCESS;
     }
 
     /**
+     * Return {@code true} if the {@param task} can embed another task.
+     * @param hostUid the uid of the host task
+     * @param embeddedUid the uid of the task the are going to be embedded
+     */
+    private boolean canTaskBeEmbedded(int hostUid, int embeddedUid) {
+        // Allowing the embedding if the task is owned by system.
+        if (hostUid == Process.SYSTEM_UID) {
+            return true;
+        }
+
+        // Allowing embedding if the host task is owned by an app that has the ACTIVITY_EMBEDDING
+        // permission
+        if (mService.checkPermission(ACTIVITY_EMBEDDING, -1, hostUid) == PERMISSION_GRANTED) {
+            return true;
+        }
+
+        // Allowing embedding if it is from the same app that owned the task
+        return hostUid == embeddedUid;
+    }
+
+    /**
      * Prepare the target task to be reused for this launch, which including:
      * - Position the target task on valid root task on preferred display.
      * - Comply to the specified activity launch flags
@@ -2736,31 +2768,6 @@
         mIntentDelivered = true;
     }
 
-    /**
-     * Return {@code true} if the {@param task} has child {@code TaskFragment}s and the
-     * {@param activity} can be embedded in. Otherwise, return {@code false}
-     */
-    private boolean canActivityBeEmbedded(@NonNull ActivityRecord activity, @NonNull Task task) {
-        if (task.isLeafTaskFragment()) {
-            return false;
-        }
-
-        final int taskUid = task.effectiveUid;
-        // Allowing the activity be embedded into leaf TaskFragment if the task is owned by system.
-        if (taskUid == Process.SYSTEM_UID) {
-            return true;
-        }
-
-        // Allowing embedding if the task is owned by an app that has the ACTIVITY_EMBEDDING
-        // permission
-        if (mService.checkPermission(ACTIVITY_EMBEDDING, -1, taskUid) == PERMISSION_GRANTED) {
-            return true;
-        }
-
-        // Allowing embedding if the activity is from the same app that owned the task
-        return activity.isUid(taskUid);
-    }
-
     private void addOrReparentStartingActivity(@NonNull Task task, String reason) {
         TaskFragment newParent = task;
         if (mInTaskFragment != null) {
@@ -2772,7 +2779,7 @@
             } else {
                 newParent = mInTaskFragment;
             }
-        } else if (canActivityBeEmbedded(mStartActivity, task)) {
+        } else {
             // Use the child TaskFragment (if any) as the new parent if the activity can be embedded
             final ActivityRecord top = task.topRunningActivity();
             newParent = top != null ? top.getTaskFragment() : task;