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

Commit bfd07e0f authored by Achim Thesmann's avatar Achim Thesmann
Browse files

Move base verdicts to BalState class

Instead of passing the verdicts around as separate objects they become
part of the BalState.

Test: atest BackgroundActivityLaunchTest
Bug: 306059525
Change-Id: If27f4b09cb1820d6a18e6d90ba1166cc1ea52313
parent 8877fcb3
Loading
Loading
Loading
Loading
+80 −73
Original line number Diff line number Diff line
@@ -61,6 +61,7 @@ import android.widget.Toast;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.Preconditions;
import com.android.server.UiThread;
import com.android.server.am.PendingIntentRecord;
import com.android.window.flags.Flags;
@@ -220,6 +221,8 @@ public class BackgroundActivityStartController {
        private final WindowProcessController mRealCallerApp;
        private final boolean mIsCallForResult;
        private final ActivityOptions mCheckedOptions;
        private BalVerdict mResultForCaller;
        private BalVerdict mResultForRealCaller;

        private BalState(int callingUid, int callingPid, final String callingPackage,
                 int realCallingUid, int realCallingPid,
@@ -371,8 +374,19 @@ public class BackgroundActivityStartController {
            return mCallingUid == mRealCallingUid;
        }

        private String dump(BalVerdict resultIfPiCreatorAllowsBal,
                            BalVerdict resultIfPiSenderAllowsBal) {
        public void setResultForCaller(BalVerdict resultForCaller) {
            Preconditions.checkState(mResultForCaller == null,
                    "mResultForCaller can only be set once");
            this.mResultForCaller = resultForCaller;
        }

        public void setResultForRealCaller(BalVerdict resultForRealCaller) {
            Preconditions.checkState(mResultForRealCaller == null,
                    "mResultForRealCaller can only be set once");
            this.mResultForRealCaller = resultForRealCaller;
        }

        private String dump() {
            StringBuilder sb = new StringBuilder(2048);
            sb.append("[callingPackage: ")
                    .append(getDebugPackageName(mCallingPackage, mCallingUid));
@@ -394,7 +408,7 @@ public class BackgroundActivityStartController {
            sb.append("; balAllowedByPiCreator: ").append(mBalAllowedByPiCreator);
            sb.append("; balAllowedByPiCreatorWithHardening: ")
                    .append(mBalAllowedByPiCreatorWithHardening);
            sb.append("; resultIfPiCreatorAllowsBal: ").append(resultIfPiCreatorAllowsBal);
            sb.append("; resultIfPiCreatorAllowsBal: ").append(mResultForCaller);
            sb.append("; hasRealCaller: ").append(hasRealCaller());
            sb.append("; isCallForResult: ").append(mIsCallForResult);
            sb.append("; isPendingIntent: ").append(isPendingIntent());
@@ -418,7 +432,7 @@ public class BackgroundActivityStartController {
                            .append(mRealCallerApp.hasActivityInVisibleTask());
                }
                sb.append("; balAllowedByPiSender: ").append(mBalAllowedByPiSender);
                sb.append("; resultIfPiSenderAllowsBal: ").append(resultIfPiSenderAllowsBal);
                sb.append("; resultIfPiSenderAllowsBal: ").append(mResultForRealCaller);
            }
            sb.append("]");
            return sb.toString();
@@ -561,23 +575,25 @@ public class BackgroundActivityStartController {
            // realCallingSdkSandboxUidToAppUid should probably just be used instead (or in addition
            // to realCallingUid when calculating resultForRealCaller below.
            if (mService.hasActiveVisibleWindow(realCallingSdkSandboxUidToAppUid)) {
                BalVerdict balVerdict = new BalVerdict(BAL_ALLOW_SDK_SANDBOX, /*background*/ false,
                        "uid in SDK sandbox has visible (non-toast) window");
                return allowBasedOnRealCaller(state, balVerdict, balVerdict);
                state.setResultForRealCaller(new BalVerdict(BAL_ALLOW_SDK_SANDBOX,
                        /*background*/ false,
                        "uid in SDK sandbox has visible (non-toast) window"));
                return allowBasedOnRealCaller(state);
            }
        }

        BalVerdict resultForCaller = checkBackgroundActivityStartAllowedByCaller(state);
        state.setResultForCaller(resultForCaller);

        if (!state.hasRealCaller()) {
            if (resultForCaller.allows()) {
                if (DEBUG_ACTIVITY_STARTS) {
                    Slog.d(TAG, "Background activity start allowed. "
                            + state.dump(resultForCaller, resultForCaller));
                            + state.dump());
                }
                return allowBasedOnCaller(state, resultForCaller, resultForCaller);
                return allowBasedOnCaller(state);
            }
            return abortLaunch(state, resultForCaller, resultForCaller);
            return abortLaunch(state);
        }

        // The realCaller result is only calculated for PendingIntents (indicated by a valid
@@ -591,6 +607,8 @@ public class BackgroundActivityStartController {
                ? resultForCaller
                : checkBackgroundActivityStartAllowedBySender(state, checkedOptions)
                        .setBasedOnRealCaller();
        state.setResultForRealCaller(resultForRealCaller);

        if (state.isPendingIntent()) {
            resultForCaller.setOnlyCreatorAllows(
                    resultForCaller.allows() && resultForRealCaller.blocks());
@@ -602,18 +620,18 @@ public class BackgroundActivityStartController {
                == ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED) {
            if (DEBUG_ACTIVITY_STARTS) {
                Slog.d(TAG, "Activity start explicitly allowed by caller. "
                        + state.dump(resultForCaller, resultForRealCaller));
                        + state.dump());
            }
            return allowBasedOnCaller(state, resultForCaller, resultForRealCaller);
            return allowBasedOnCaller(state);
        }
        if (resultForRealCaller.allows()
                && checkedOptions.getPendingIntentBackgroundActivityStartMode()
                == ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED) {
            if (DEBUG_ACTIVITY_STARTS) {
                Slog.d(TAG, "Activity start explicitly allowed by real caller. "
                        + state.dump(resultForCaller, resultForRealCaller));
                        + state.dump());
            }
            return allowBasedOnRealCaller(state, resultForCaller, resultForRealCaller);
            return allowBasedOnRealCaller(state);
        }
        // Handle PendingIntent cases with default behavior next
        boolean callerCanAllow = resultForCaller.allows()
@@ -628,26 +646,26 @@ public class BackgroundActivityStartController {
                // Will be allowed even with BAL hardening.
                if (DEBUG_ACTIVITY_STARTS) {
                    Slog.d(TAG, "Activity start allowed by caller. "
                            + state.dump(resultForCaller, resultForRealCaller));
                            + state.dump());
                }
                // return the realCaller result for backwards compatibility
                return allowBasedOnRealCaller(state, resultForCaller, resultForRealCaller);
                return allowBasedOnRealCaller(state);
            }
            if (state.mBalAllowedByPiCreator.allowsBackgroundActivityStarts()) {
                Slog.wtf(TAG,
                        "With Android 15 BAL hardening this activity start may be blocked"
                                + " if the PI creator upgrades target_sdk to 35+"
                                + " AND the PI sender upgrades target_sdk to 34+! "
                                + state.dump(resultForCaller, resultForRealCaller));
                                + state.dump());
                showBalRiskToast();
                // return the realCaller result for backwards compatibility
                return allowBasedOnRealCaller(state, resultForCaller, resultForRealCaller);
                return allowBasedOnRealCaller(state);
            }
            Slog.wtf(TAG,
                    "Without Android 15 BAL hardening this activity start would be allowed"
                            + " (missing opt in by PI creator or sender)! "
                            + state.dump(resultForCaller, resultForRealCaller));
            return abortLaunch(state, resultForCaller, resultForRealCaller);
                            + state.dump());
            return abortLaunch(state);
        }
        if (callerCanAllow) {
            // Allowed before V by creator
@@ -655,24 +673,24 @@ public class BackgroundActivityStartController {
                // Will be allowed even with BAL hardening.
                if (DEBUG_ACTIVITY_STARTS) {
                    Slog.d(TAG, "Activity start allowed by caller. "
                            + state.dump(resultForCaller, resultForRealCaller));
                            + state.dump());
                }
                return allowBasedOnCaller(state, resultForCaller, resultForRealCaller);
                return allowBasedOnCaller(state);
            }
            if (state.mBalAllowedByPiCreator.allowsBackgroundActivityStarts()) {
                Slog.wtf(TAG,
                        "With Android 15 BAL hardening this activity start may be blocked"
                                + " if the PI creator upgrades target_sdk to 35+! "
                                + " (missing opt in by PI creator)! "
                                + state.dump(resultForCaller, resultForRealCaller));
                                + state.dump());
                showBalRiskToast();
                return allowBasedOnCaller(state, resultForCaller, resultForRealCaller);
                return allowBasedOnCaller(state);
            }
            Slog.wtf(TAG,
                    "Without Android 15 BAL hardening this activity start would be allowed"
                            + " (missing opt in by PI creator)! "
                            + state.dump(resultForCaller, resultForRealCaller));
            return abortLaunch(state, resultForCaller, resultForRealCaller);
                            + state.dump());
            return abortLaunch(state);
        }
        if (realCallerCanAllow) {
            // Allowed before U by sender
@@ -681,43 +699,40 @@ public class BackgroundActivityStartController {
                        "With Android 14 BAL hardening this activity start will be blocked"
                                + " if the PI sender upgrades target_sdk to 34+! "
                                + " (missing opt in by PI sender)! "
                                + state.dump(resultForCaller, resultForRealCaller));
                                + state.dump());
                showBalRiskToast();
                return allowBasedOnRealCaller(state, resultForCaller, resultForRealCaller);
                return allowBasedOnRealCaller(state);
            }
            Slog.wtf(TAG, "Without Android 14 BAL hardening this activity start would be allowed"
                    + " (missing opt in by PI sender)! "
                    + state.dump(resultForCaller, resultForRealCaller));
            return abortLaunch(state, resultForCaller, resultForRealCaller);
                    + state.dump());
            return abortLaunch(state);
        }
        // neither the caller not the realCaller can allow or have explicitly opted out
        return abortLaunch(state, resultForCaller, resultForRealCaller);
        return abortLaunch(state);
    }

    private BalVerdict allowBasedOnCaller(BalState state, BalVerdict resultForCaller,
            BalVerdict resultForRealCaller) {
    private BalVerdict allowBasedOnCaller(BalState state) {
        if (DEBUG_ACTIVITY_STARTS) {
            Slog.d(TAG, "Background activity launch allowed based on caller. "
                    + state.dump(resultForCaller, resultForRealCaller));
                    + state.dump());
        }
        return statsLog(resultForCaller, resultForCaller, resultForRealCaller, state);
        return statsLog(state.mResultForCaller, state);
    }

    private BalVerdict allowBasedOnRealCaller(BalState state, BalVerdict resultForCaller,
            BalVerdict resultForRealCaller) {
    private BalVerdict allowBasedOnRealCaller(BalState state) {
        if (DEBUG_ACTIVITY_STARTS) {
            Slog.d(TAG, "Background activity launch allowed based on real caller. "
                    + state.dump(resultForCaller, resultForRealCaller));
                    + state.dump());
        }
        return statsLog(resultForRealCaller, resultForCaller, resultForRealCaller, state);
        return statsLog(state.mResultForRealCaller, state);
    }

    private BalVerdict abortLaunch(BalState state, BalVerdict resultForCaller,
            BalVerdict resultForRealCaller) {
    private BalVerdict abortLaunch(BalState state) {
        Slog.w(TAG, "Background activity launch blocked! "
                + state.dump(resultForCaller, resultForRealCaller));
                + state.dump());
        showBalBlockedToast();
        return statsLog(BalVerdict.BLOCK, resultForCaller, resultForRealCaller, state);
        return statsLog(BalVerdict.BLOCK, state);
    }

    /**
@@ -1464,8 +1479,7 @@ public class BackgroundActivityStartController {
                /* defaultValue= */ true);
    }

    private BalVerdict statsLog(BalVerdict finalVerdict,
            BalVerdict callerVerdict, BalVerdict realCallerVerdict, BalState state) {
    private BalVerdict statsLog(BalVerdict finalVerdict, BalState state) {
        if (finalVerdict.blocks() && mService.isActivityStartsLoggingEnabled()) {
            // log aborted activity start to TRON
            mSupervisor
@@ -1492,41 +1506,34 @@ public class BackgroundActivityStartController {
                && (callingUid == Process.SYSTEM_UID || realCallingUid == Process.SYSTEM_UID)) {
            String activityName = intent != null
                    ? requireNonNull(intent.getComponent()).flattenToShortString() : "";
            FrameworkStatsLog.write(FrameworkStatsLog.BAL_ALLOWED,
                    activityName,
                    BAL_ALLOW_PENDING_INTENT,
                    callingUid,
                    realCallingUid,
                    callerVerdict.getRawCode(),
                    state.mBalAllowedByPiCreator.allowsBackgroundActivityStarts(),
                    state.mCheckedOptions.getPendingIntentCreatorBackgroundActivityStartMode()
                            != ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED,
                    realCallerVerdict.getRawCode(),
                    state.mBalAllowedByPiSender.allowsBackgroundActivityStarts(),
                    state.mCheckedOptions.getPendingIntentBackgroundActivityStartMode()
                            != ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED
            );
            writeBalAllowedLog(activityName, BAL_ALLOW_PENDING_INTENT,
                    state);
        }
        if (code == BAL_ALLOW_PERMISSION || code == BAL_ALLOW_FOREGROUND
                || code == BAL_ALLOW_SAW_PERMISSION) {
            // We don't need to know which activity in this case.
            writeBalAllowedLog("", code, state);

        }
        return finalVerdict;
    }

    private static void writeBalAllowedLog(String activityName, int code, BalState state) {
        FrameworkStatsLog.write(FrameworkStatsLog.BAL_ALLOWED,
                    /*activityName*/ "",
                activityName,
                code,
                    callingUid,
                    realCallingUid,
                    callerVerdict.getRawCode(),
                state.mCallingUid,
                state.mRealCallingUid,
                state.mResultForCaller == null ? BAL_BLOCK : state.mResultForCaller.getRawCode(),
                state.mBalAllowedByPiCreator.allowsBackgroundActivityStarts(),
                state.mCheckedOptions.getPendingIntentCreatorBackgroundActivityStartMode()
                        != ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED,
                    realCallerVerdict.getRawCode(),
                state.mResultForRealCaller == null ? BAL_BLOCK
                        : state.mResultForRealCaller.getRawCode(),
                state.mBalAllowedByPiSender.allowsBackgroundActivityStarts(),
                state.mCheckedOptions.getPendingIntentBackgroundActivityStartMode()
                        != ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED
        );

        }
        return finalVerdict;
    }

    /**