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

Commit c9ed451b authored by Achim Thesmann's avatar Achim Thesmann Committed by Android (Google) Code Review
Browse files

Merge "Add wtf logging if only allowed by token" into main

parents 70db4754 aa418e9e
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -14544,23 +14544,23 @@ public class NotificationManagerService extends SystemService {
     */
    private class NotificationTrampolineCallback implements BackgroundActivityStartCallback {
        @Override
        public boolean isActivityStartAllowed(Collection<IBinder> tokens, int uid,
                String packageName) {
        public BackgroundActivityStartCallbackResult isActivityStartAllowed(
                Collection<IBinder> tokens, int uid, String packageName) {
            checkArgument(!tokens.isEmpty());
            for (IBinder token : tokens) {
                if (token != ALLOWLIST_TOKEN) {
                    // We only block or warn if the start is exclusively due to notification
                    return true;
                    return RESULT_TRUE;
                }
            }
            String logcatMessage =
                    "Indirect notification activity start (trampoline) from " + packageName;
            if (blockTrampoline(uid)) {
                Slog.e(TAG, logcatMessage + " blocked");
                return false;
                return RESULT_FALSE;
            } else {
                Slog.w(TAG, logcatMessage + ", this should be avoided for performance reasons");
                return true;
                return new BackgroundActivityStartCallbackResult(true, ALLOWLIST_TOKEN);
            }
        }
+12 −1
Original line number Diff line number Diff line
@@ -24,6 +24,16 @@ import java.util.Collection;
 * Callback to decide activity starts and related operations based on originating tokens.
 */
public interface BackgroundActivityStartCallback {
    BackgroundActivityStartCallbackResult RESULT_FALSE =
            new BackgroundActivityStartCallbackResult(false, null);
    BackgroundActivityStartCallbackResult RESULT_TRUE =
            new BackgroundActivityStartCallbackResult(true, null);

    record BackgroundActivityStartCallbackResult(
            boolean allowed,
            IBinder token
    ) {}

    /**
     * Returns true if the background activity start originating from {@code tokens} should be
     * allowed or not.
@@ -34,7 +44,8 @@ public interface BackgroundActivityStartCallback {
     * This will be called holding the WM and local lock, don't do anything costly or invoke AM/WM
     * methods here directly.
     */
    boolean isActivityStartAllowed(Collection<IBinder> tokens, int uid, String packageName);
    BackgroundActivityStartCallbackResult isActivityStartAllowed(Collection<IBinder> tokens,
            int uid, String packageName);

    /**
     * Returns whether {@code uid} can send {@link android.content.Intent
+6 −2
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ import static com.android.window.flags.Flags.balRequireOptInByPendingIntentCreat
import static com.android.window.flags.Flags.balShowToastsBlocked;
import static com.android.window.flags.Flags.balStrictModeGracePeriod;
import static com.android.window.flags.Flags.balStrictModeRo;
import static com.android.window.flags.Flags.balAdditionalLogging;

import static java.lang.annotation.RetentionPolicy.SOURCE;
import static java.util.Objects.requireNonNull;
@@ -1939,6 +1940,7 @@ public class BackgroundActivityStartController {
            }
        }
        logIfOnlyAllowedBy(finalVerdict, state, BAL_ALLOW_NON_APP_VISIBLE_WINDOW);
        logIfOnlyAllowedBy(finalVerdict, state, BAL_ALLOW_TOKEN);

        if (balImprovedMetrics()) {
            if (shouldLogStats(finalVerdict, state)) {
@@ -1998,8 +2000,10 @@ public class BackgroundActivityStartController {
                return false;
            } else {
                // log to determine grace period length distribution
                if (balAdditionalLogging()) {
                    Slog.wtf(TAG, "Activity start ONLY allowed by " + balCodeToString(balCode) + " "
                            + finalVerdict.mMessage + ": " + state);
                }
                return true;
            }
        }
+29 −13
Original line number Diff line number Diff line
@@ -128,11 +128,16 @@ class BackgroundLaunchProcessController {
            return new BalVerdict(BAL_ALLOW_PERMISSION, /*background*/
                    "process instrumenting with background activity starts privileges");
        }
        // Allow if the flag was explicitly set.
        if (checkConfiguration.checkOtherExemptions && isBackgroundStartAllowedByToken(uid,
                packageName, checkConfiguration.isCheckingForFgsStart)) {
            return new BalVerdict(balImprovedMetrics() ? BAL_ALLOW_TOKEN : BAL_ALLOW_PERMISSION,
                    /*background*/  "process allowed by token");
        // Allow if the token is explicitly allowed.
        if (checkConfiguration.checkOtherExemptions) {
            BalVerdict tokenVerdict = isBackgroundStartAllowedByToken(uid,
                    packageName, checkConfiguration.isCheckingForFgsStart);
            if (tokenVerdict.allows()) {
                if (!balImprovedMetrics()) {
                    return new BalVerdict(BAL_ALLOW_PERMISSION, tokenVerdict.toString());
                }
                return tokenVerdict;
            }
        }
        // Allow if the caller is bound by a UID that's currently foreground.
        // But still respect the appSwitchState.
@@ -174,42 +179,53 @@ class BackgroundLaunchProcessController {
     * isCheckingForFgsStart is false, we ask the callback if the start is allowed for these tokens,
     * otherwise if there is no callback we allow.
     */
    private boolean isBackgroundStartAllowedByToken(int uid, String packageName,
    private BalVerdict isBackgroundStartAllowedByToken(int uid, String packageName,
            boolean isCheckingForFgsStart) {
        synchronized (this) {
            if (mBackgroundStartPrivileges == null
                    || mBackgroundStartPrivileges.isEmpty()) {
                // no tokens to allow anything
                return false;
                return BalVerdict.BLOCK;
            }
            if (isCheckingForFgsStart) {
                // check if any token allows foreground service starts
                for (int i = mBackgroundStartPrivileges.size(); i-- > 0; ) {
                    if (mBackgroundStartPrivileges.valueAt(i).allowsBackgroundFgsStarts()) {
                        return true;
                        return new BalVerdict(BAL_ALLOW_TOKEN, "process allowed by token");
                    }
                }
                return false;
                return BalVerdict.BLOCK;
            }
            if (mBackgroundActivityStartCallback == null) {
                // without a callback just check if any token allows background activity starts
                for (int i = mBackgroundStartPrivileges.size(); i-- > 0; ) {
                    if (mBackgroundStartPrivileges.valueAt(i)
                            .allowsBackgroundActivityStarts()) {
                        return true;
                        return new BalVerdict(BAL_ALLOW_TOKEN, "process allowed by token");
                    }
                }
                return false;
                return BalVerdict.BLOCK;
            }
            List<IBinder> binderTokens = getOriginatingTokensThatAllowBal();
            if (binderTokens.isEmpty()) {
                // no tokens to allow anything
                return false;
                return BalVerdict.BLOCK;
            }

            // The callback will decide.
            return mBackgroundActivityStartCallback.isActivityStartAllowed(
            BackgroundActivityStartCallback.BackgroundActivityStartCallbackResult
                    activityStartAllowed = mBackgroundActivityStartCallback.isActivityStartAllowed(
                    binderTokens, uid, packageName);
            if (!activityStartAllowed.allowed()) {
                return BalVerdict.BLOCK;
            }
            if (activityStartAllowed.token() == null) {
                return new BalVerdict(BAL_ALLOW_TOKEN,
                        "process allowed by callback (token ignored) tokens: " + binderTokens);
            }
            return new BalVerdict(BAL_ALLOW_TOKEN,
                    "process allowed by callback (token: " + activityStartAllowed.token()
                            + ") tokens: " + binderTokens);
        }
    }

+4 −4
Original line number Diff line number Diff line
@@ -74,14 +74,14 @@ public class BackgroundLaunchProcessControllerTests {

    BackgroundActivityStartCallback mCallback = new BackgroundActivityStartCallback() {
        @Override
        public boolean isActivityStartAllowed(Collection<IBinder> tokens, int uid,
                String packageName) {
        public BackgroundActivityStartCallbackResult isActivityStartAllowed(
                Collection<IBinder> tokens, int uid, String packageName) {
            for (IBinder token : tokens) {
                if (token == null || mActivityStartAllowed.contains(token)) {
                    return true;
                    return new BackgroundActivityStartCallbackResult(true, token);
                }
            }
            return false;
            return RESULT_FALSE;
        }

        @Override