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

Commit 66f117cc authored by Nan Wu's avatar Nan Wu
Browse files

Don’t bring App to FG if only creator is allowed to do BAL(1/2)

Logs the incidents when an app is brought to the foreground caused by
a PendingIntent whose creator is allowed to do BAL, but the sender
does not . It does not change any behavior.

Bug: 296478675
Test: BackgroundActivityLaunchTest#testPI_onlyCreatorAllowsBAL_isBlocked
Change-Id: If28adf1f6c1c86b9934df35c650c229b6842fe3c
parent 4e01a48b
Loading
Loading
Loading
Loading
+43 −17
Original line number Diff line number Diff line
@@ -133,6 +133,7 @@ import com.android.server.statusbar.StatusBarManagerInternal;
import com.android.server.uri.NeededUriGrants;
import com.android.server.wm.ActivityMetricsLogger.LaunchingState;
import com.android.server.wm.BackgroundActivityStartController.BalCode;
import com.android.server.wm.BackgroundActivityStartController.BalVerdict;
import com.android.server.wm.LaunchParamsController.LaunchParams;
import com.android.server.wm.TaskFragment.EmbeddingCheckResult;

@@ -1090,14 +1091,14 @@ class ActivityStarter {
        ActivityOptions checkedOptions = options != null
                ? options.getOptions(intent, aInfo, callerApp, mSupervisor) : null;

        @BalCode int balCode = BAL_ALLOW_DEFAULT;
        final BalVerdict balVerdict;
        if (!abort) {
            try {
                Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER,
                        "shouldAbortBackgroundActivityStart");
                BackgroundActivityStartController balController =
                        mSupervisor.getBackgroundActivityLaunchController();
                BackgroundActivityStartController.BalVerdict balVerdict =
                balVerdict =
                        balController.checkBackgroundActivityStart(
                            callingUid,
                            callingPid,
@@ -1109,13 +1110,13 @@ class ActivityStarter {
                            request.forcedBalByPiSender,
                            intent,
                            checkedOptions);
                balCode = balVerdict.getCode();
                request.logMessage.append(" (").append(
                                BackgroundActivityStartController.balCodeToString(balCode))
                        .append(")");
                request.logMessage.append(" (").append(balVerdict).append(")");
            } finally {
                Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
            }
        } else {
            // Sets ALLOW_BY_DEFAULT as default value as the activity launch will be aborted anyway.
            balVerdict = BalVerdict.ALLOW_BY_DEFAULT;
        }

        if (request.allowPendingRemoteAnimationRegistryLookup) {
@@ -1293,13 +1294,13 @@ class ActivityStarter {
        WindowProcessController homeProcess = mService.mHomeProcess;
        boolean isHomeProcess = homeProcess != null
                && aInfo.applicationInfo.uid == homeProcess.mUid;
        if (balCode != BAL_BLOCK && !isHomeProcess) {
        if (balVerdict.allows() && !isHomeProcess) {
            mService.resumeAppSwitches();
        }

        mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,
                request.voiceInteractor, startFlags, checkedOptions,
                inTask, inTaskFragment, balCode, intentGrants, realCallingUid);
                inTask, inTaskFragment, balVerdict, intentGrants, realCallingUid);

        if (request.outActivity != null) {
            request.outActivity[0] = mLastStartActivityRecord;
@@ -1449,7 +1450,8 @@ class ActivityStarter {
    private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, ActivityOptions options, Task inTask,
            TaskFragment inTaskFragment, @BalCode int balCode,
            TaskFragment inTaskFragment,
            BalVerdict balVerdict,
            NeededUriGrants intentGrants, int realCallingUid) {
        int result = START_CANCELED;
        final Task startedActivityRootTask;
@@ -1468,7 +1470,7 @@ class ActivityStarter {
            try {
                Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner");
                result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,
                        startFlags, options, inTask, inTaskFragment, balCode,
                        startFlags, options, inTask, inTaskFragment, balVerdict,
                        intentGrants, realCallingUid);
            } finally {
                Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
@@ -1615,10 +1617,10 @@ class ActivityStarter {
    int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, ActivityOptions options, Task inTask,
            TaskFragment inTaskFragment, @BalCode int balCode,
            TaskFragment inTaskFragment, BalVerdict balVerdict,
            NeededUriGrants intentGrants, int realCallingUid) {
        setInitialState(r, options, inTask, inTaskFragment, startFlags, sourceRecord,
                voiceSession, voiceInteractor, balCode, realCallingUid);
                voiceSession, voiceInteractor, balVerdict.getCode(), realCallingUid);

        computeLaunchingTaskFlags();
        mIntent.setFlags(mLaunchFlags);
@@ -1696,7 +1698,8 @@ class ActivityStarter {
            }
            recordTransientLaunchIfNeeded(targetTaskTop);
            // Recycle the target task for this launch.
            startResult = recycleTask(targetTask, targetTaskTop, reusedTask, intentGrants);
            startResult =
                    recycleTask(targetTask, targetTaskTop, reusedTask, intentGrants, balVerdict);
            if (startResult != START_SUCCESS) {
                return startResult;
            }
@@ -1730,6 +1733,7 @@ class ActivityStarter {
        recordTransientLaunchIfNeeded(mLastStartActivityRecord);

        if (!mAvoidMoveToFront && mDoResume) {
            logOnlyCreatorAllowsBAL(balVerdict, realCallingUid, newTask);
            mTargetRootTask.getRootTask().moveToFront("reuseOrNewTask", targetTask);
            if (!mTargetRootTask.isTopRootTaskInDisplayArea() && mService.isDreaming()
                    && !dreamStopping) {
@@ -1800,6 +1804,7 @@ class ActivityStarter {
                // now update the focused root-task accordingly.
                if (!mAvoidMoveToFront && mTargetRootTask.isTopActivityFocusable()
                        && !mRootWindowContainer.isTopDisplayFocusedRootTask(mTargetRootTask)) {
                    logOnlyCreatorAllowsBAL(balVerdict, realCallingUid, newTask);
                    mTargetRootTask.moveToFront("startActivityInner");
                }
                mRootWindowContainer.resumeFocusedTasksTopActivities(
@@ -1817,7 +1822,7 @@ class ActivityStarter {
        // Note that mStartActivity and source should be in the same Task at this point.
        if (mOptions != null && mOptions.isLaunchIntoPip()
                && sourceRecord != null && sourceRecord.getTask() == mStartActivity.getTask()
                && balCode != BAL_BLOCK) {
                && balVerdict.allows()) {
            mRootWindowContainer.moveActivityToPinnedRootTask(mStartActivity,
                    sourceRecord, "launch-into-pip");
        }
@@ -1828,6 +1833,24 @@ class ActivityStarter {
        return START_SUCCESS;
    }

    private void logOnlyCreatorAllowsBAL(BalVerdict balVerdict,
            int realCallingUid, boolean newTask) {
        // TODO (b/296478675) eventually, we will prevent such case from happening
        // and probably also log that a BAL is prevented by android V.
        if (!newTask && balVerdict.onlyCreatorAllows()) {
            String realCallingPackage =
                    mService.mContext.getPackageManager().getNameForUid(realCallingUid);
            if (realCallingPackage == null) {
                realCallingPackage = "uid=" + realCallingUid;
            }
            Slog.wtf(TAG, "A background app is brought to the foreground due to a "
                    + "PendingIntent. However, only the creator of the PendingIntent allows BAL, "
                    + "while the sender does not allow BAL. realCallingPackage: "
                    + realCallingPackage + "; callingPackage: " + mRequest.callingPackage
                    + "; mTargetRootTask:" + mTargetRootTask);
        }
    }

    private void recordTransientLaunchIfNeeded(ActivityRecord r) {
        if (r == null || !mTransientLaunch) return;
        final TransitionController controller = r.mTransitionController;
@@ -1995,7 +2018,7 @@ class ActivityStarter {
     */
    @VisibleForTesting
    int recycleTask(Task targetTask, ActivityRecord targetTaskTop, Task reusedTask,
            NeededUriGrants intentGrants) {
            NeededUriGrants intentGrants, BalVerdict balVerdict) {
        // Should not recycle task which is from a different user, just adding the starting
        // activity to the task.
        if (targetTask.mUserId != mStartActivity.mUserId) {
@@ -2024,7 +2047,7 @@ class ActivityStarter {
        mRootWindowContainer.startPowerModeLaunchIfNeeded(false /* forceSend */,
                targetTaskTop);

        setTargetRootTaskIfNeeded(targetTaskTop);
        setTargetRootTaskIfNeeded(targetTaskTop, balVerdict);

        // When there is a reused activity and the current result is a trampoline activity,
        // set the reused activity as the result.
@@ -2040,6 +2063,7 @@ class ActivityStarter {
            if (!mMovedToFront && mDoResume) {
                ProtoLog.d(WM_DEBUG_TASKS, "Bring to front target: %s from %s", mTargetRootTask,
                        targetTaskTop);
                logOnlyCreatorAllowsBAL(balVerdict, mRealCallingUid, false);
                mTargetRootTask.moveToFront("intentActivityFound");
            }
            resumeTargetRootTaskIfNeeded();
@@ -2068,6 +2092,7 @@ class ActivityStarter {
            targetTaskTop.showStartingWindow(true /* taskSwitch */);
        } else if (mDoResume) {
            // Make sure the root task and its belonging display are moved to topmost.
            logOnlyCreatorAllowsBAL(balVerdict, mRealCallingUid, false);
            mTargetRootTask.moveToFront("intentActivityFound");
        }
        // We didn't do anything...  but it was needed (a.k.a., client don't use that intent!)
@@ -2663,7 +2688,7 @@ class ActivityStarter {
     * @param intentActivity Existing matching activity.
     * @return {@link ActivityRecord} brought to front.
     */
    private void setTargetRootTaskIfNeeded(ActivityRecord intentActivity) {
    private void setTargetRootTaskIfNeeded(ActivityRecord intentActivity, BalVerdict balVerdict) {
        intentActivity.getTaskFragment().clearLastPausedActivity();
        Task intentTask = intentActivity.getTask();
        // The intent task might be reparented while in getOrCreateRootTask, caches the original
@@ -2730,6 +2755,7 @@ class ActivityStarter {
                    // task on top there.
                    // Defer resuming the top activity while moving task to top, since the
                    // current task-top activity may not be the activity that should be resumed.
                    logOnlyCreatorAllowsBAL(balVerdict, mRealCallingUid, false);
                    mTargetRootTask.moveTaskToFront(intentTask, mNoAnimation, mOptions,
                            mStartActivity.appTimeTracker, DEFER_RESUME,
                            "bringingFoundTaskToFront");
+18 −0
Original line number Diff line number Diff line
@@ -433,10 +433,15 @@ public class BackgroundActivityStartController {
    static class BalVerdict {

        static final BalVerdict BLOCK = new BalVerdict(BAL_BLOCK, false, "Blocked");
        static final BalVerdict ALLOW_BY_DEFAULT =
                new BalVerdict(BAL_ALLOW_DEFAULT, false, "Default");
        private final @BalCode int mCode;
        private final boolean mBackground;
        private final String mMessage;
        private String mProcessInfo;
        // indicates BAL would be blocked because only creator of the PI has the privilege to allow
        // BAL, the sender does not have the privilege to allow BAL.
        private boolean mOnlyCreatorAllows;

        BalVerdict(@BalCode int balCode, boolean background, String message) {
            this.mBackground = background;
@@ -457,6 +462,15 @@ public class BackgroundActivityStartController {
            return !blocks();
        }

        BalVerdict setOnlyCreatorAllows(boolean onlyCreatorAllows) {
            mOnlyCreatorAllows = onlyCreatorAllows;
            return this;
        }

        boolean onlyCreatorAllows() {
            return mOnlyCreatorAllows;
        }

        public String toString() {
            StringBuilder builder = new StringBuilder();
            builder.append(balCodeToString(mCode));
@@ -566,6 +580,10 @@ public class BackgroundActivityStartController {
        BalVerdict resultForRealCaller = state.callerIsRealCaller() && resultForCaller.allows()
                ? resultForCaller
                : checkBackgroundActivityStartAllowedBySender(state, checkedOptions);
        if (state.isPendingIntent()) {
            resultForCaller.setOnlyCreatorAllows(
                    resultForCaller.allows() && resultForRealCaller.blocks());
        }

        if (resultForCaller.allows()
                && checkedOptions.getPendingIntentCreatorBackgroundActivityStartMode()
+5 −3
Original line number Diff line number Diff line
@@ -118,6 +118,7 @@ import com.android.compatibility.common.util.DeviceConfigStateHelper;
import com.android.internal.util.FrameworkStatsLog;
import com.android.server.am.PendingIntentRecord;
import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.wm.BackgroundActivityStartController.BalVerdict;
import com.android.server.wm.LaunchParamsController.LaunchParamsModifier;
import com.android.server.wm.utils.MockTracker;

@@ -1378,7 +1379,8 @@ public class ActivityStarterTests extends WindowTestsBase {
                .setUserId(10)
                .build();

        final int result = starter.recycleTask(task, null, null, null);
        final int result = starter.recycleTask(task, null, null, null,
                BalVerdict.ALLOW_BY_DEFAULT);
        assertThat(result == START_SUCCESS).isTrue();
        assertThat(starter.mAddingToTask).isTrue();
    }
@@ -1892,7 +1894,7 @@ public class ActivityStarterTests extends WindowTestsBase {
        starter.startActivityInner(target, source, null /* voiceSession */,
                null /* voiceInteractor */, 0 /* startFlags */,
                options, inTask, inTaskFragment,
                BackgroundActivityStartController.BAL_ALLOW_DEFAULT, null /* intentGrants */,
                -1 /* realCallingUid */);
                BalVerdict.ALLOW_BY_DEFAULT,
                null /* intentGrants */, -1 /* realCallingUid */);
    }
}
+3 −2
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;

import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.server.wm.BackgroundActivityStartController.BalVerdict;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -186,7 +187,7 @@ public class DisplayWindowPolicyControllerTests extends WindowTestsBase {
                /* options */null,
                /* inTask */null,
                /* inTaskFragment */ null,
                /* balCode */ BackgroundActivityStartController.BAL_ALLOW_DEFAULT,
                BalVerdict.ALLOW_BY_DEFAULT,
                /* intentGrants */null,
                /* realCaiingUid */ -1);

@@ -216,7 +217,7 @@ public class DisplayWindowPolicyControllerTests extends WindowTestsBase {
                /* options= */null,
                /* inTask= */null,
                /* inTaskFragment= */ null,
                /* balCode= */ BackgroundActivityStartController.BAL_ALLOW_DEFAULT,
                BalVerdict.ALLOW_BY_DEFAULT,
                /* intentGrants= */null,
                /* realCaiingUid */ -1);