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

Commit c1e88d01 authored by Jiaming Liu's avatar Jiaming Liu
Browse files

[AE] Abort activity launch for finishing cross-uid TF

There is a race condition if a cross-uid embedded activity launches
another activity and then the TF is finished. In this case, depending on
the timing, ActivityStarter might place the new activity in a wrong
TaskFragment. For activities launched by a cross-uid embedded activity,
we always expect the new activity to be launched into the same TF. If
the TF is finishing, the best thing we can do seems to be aborting the
activity launch, as if it was launched into the TF and then finished
together with the TF.

Bug: 427881773
Test: Manually tested on Settings; atest ActivityStarterTest TaskFragmentTest
Flag: com.android.window.flags.activity_embedding_abort_cross_uid_launch_in_finishing_task_fragment
Change-Id: I65addba032ca8708b1d6906485cfe4f9ec9b1377
parent aeda457c
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -189,6 +189,16 @@ flag {
    }
}

flag {
    namespace: "windowing_sdk"
    name: "activity_embedding_abort_cross_uid_launch_in_finishing_task_fragment"
    description: "Aborts cross-uid activity launch from a finishing TaskFragment to avoid race conditions"
    bug: "427881773"
    metadata {
        purpose: PURPOSE_BUGFIX
    }
}

flag {
    namespace: "windowing_sdk"
    name: "dispose_task_fragment_synchronously"
+3 −0
Original line number Diff line number Diff line
@@ -1245,6 +1245,9 @@ class ActivityStarter {
                callingPid, resolvedType, aInfo.applicationInfo);
        abort |= !mService.getPermissionPolicyInternal().checkStartActivity(intent, callingUid,
                callingPackage);
        abort |= sourceRecord != null && sourceRecord.getTaskFragment() != null
                && sourceRecord.getTaskFragment().shouldAbortActivityLaunchOnFinishingTf(
                        sourceRecord);

        if (intentCreatorUid != Request.DEFAULT_INTENT_CREATOR_UID) {
            try {
+27 −0
Original line number Diff line number Diff line
@@ -1288,6 +1288,33 @@ class TaskFragment extends WindowContainer<WindowContainer> {
                : (isFocusable() && getWindowConfiguration().canReceiveKeys());
    }

    /**
     * Returns whether the activity launch by the source activity in this TaskFragment should be
     * aborted. Currently only activity launches from a cross-uid embedded source within a finishing
     * TaskFragment are aborted.
     *
     * @param source an activity in this TaskFragment that launches another activity.
     */
    boolean shouldAbortActivityLaunchOnFinishingTf(@NonNull ActivityRecord source) {
        if (!Flags.activityEmbeddingAbortCrossUidLaunchInFinishingTaskFragment()) {
            return false;
        }
        // If the source activity is a cross-uid embedded activity, the newly launched activity is
        // always expected to be in the same TaskFragment. If this TaskFragment is being removed, we
        // should not allow a new activity to be launched by the source, because it may be placed
        // into a wrong TaskFragment due to current limitations in cross-uid activity launch
        // tracking.
        // TODO(b/293800510) Improve cross-uid activity launch tracking.
        boolean abort = isEmbedded() && isRemovalRequested()
                && mTaskFragmentOrganizerUid != INVALID_UID
                && source.getUid() != mTaskFragmentOrganizerUid;
        if (abort) {
            Slog.w(TAG, "Activity launch aborted for cross-uid launch from " + source
                    + " in a finishing TaskFragment");
        }
        return abort;
    }

    /**
     * Returns the visibility state of this TaskFragment.
     *