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
This commit is contained in:
Louis Chang
2021-07-13 12:32:45 +08:00
parent f335f84742
commit 6407d54e33

View File

@@ -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);