Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6407d54e authored by Louis Chang's avatar Louis Chang
Browse files

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
parent f335f847
Loading
Loading
Loading
Loading
+31 −0
Original line number Diff line number Diff line
@@ -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);