From 6407d54e339ff78dc5aecda9aee5076267a3ae9d Mon Sep 17 00:00:00 2001 From: Louis Chang Date: Tue, 13 Jul 2021 12:32:45 +0800 Subject: [PATCH] Start activity in the embedded TaskFragment if allowed If the task already contains child TaskFragments, an activity should be started in the child TaskFragments, but only doing so if the activity is allowed to be embedded. Currently, an app can embed its activities into its own task. Only system or apps with ACTIVITY_EMBEDDING permission can embed activities of another app. Bug: 193456000 Bug: 189386461 Test: wm presubmit Change-Id: I8707f5f79deb23cc9b2b8d647382416dce6a6e9d --- .../android/server/wm/ActivityStarter.java | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index 5c9fdc3580e88..c90eba0c13591 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -16,6 +16,7 @@ package com.android.server.wm; +import static android.Manifest.permission.ACTIVITY_EMBEDDING; import static android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND; import static android.app.Activity.RESULT_CANCELED; import static android.app.ActivityManager.START_ABORTED; @@ -2717,6 +2718,31 @@ class ActivityStarter { 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) { @@ -2728,7 +2754,12 @@ class ActivityStarter { } else { newParent = mInTaskFragment; } + } else if (canActivityBeEmbedded(mStartActivity, task)) { + // 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; } + if (mStartActivity.getTaskFragment() == null || mStartActivity.getTaskFragment() == newParent) { newParent.addChild(mStartActivity, POSITION_TOP);