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

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

Merge changes Ib1e2e57e,I4c0888f7 into main

* changes:
  Refactor real caller exemptions
  Refactor caller exemptions
parents 6aeb0c44 ae7f387e
Loading
Loading
Loading
Loading
+122 −38
Original line number Diff line number Diff line
@@ -144,9 +144,9 @@ public class BackgroundActivityStartController {
                    .setPendingIntentCreatorBackgroundActivityStartMode(
                            MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED);

    private final ActivityTaskManagerService mService;
    private ActivityTaskManagerService mService;

    private final ActivityTaskSupervisor mSupervisor;
    private ActivityTaskSupervisor mSupervisor;
    @GuardedBy("mStrictModeBalCallbacks")
    private final SparseArray<ArrayMap<IBinder, IBackgroundActivityLaunchCallback>>
            mStrictModeBalCallbacks = new SparseArray<>();
@@ -1026,11 +1026,21 @@ public class BackgroundActivityStartController {
        }
    }

    /**
     * @return A code denoting which BAL rule allows an activity to be started,
     * or {@link #BAL_BLOCK} if the launch should be blocked
     */
    BalVerdict checkBackgroundActivityStartAllowedByCallerInForeground(BalState state) {
    interface BalExemptionCheck {
        BalVerdict evaluate(BalState state);
    }

    private BalVerdict evaluateChain(BalState state, BalExemptionCheck... checks) {
        for (BalExemptionCheck check : checks) {
            BalVerdict verdict = check.evaluate(state);
            if (verdict != BalVerdict.BLOCK) {
                return verdict;
            }
        }
        return BalVerdict.BLOCK;
    }

    private final BalExemptionCheck mCheckCallerVisible = state -> {
        // This is used to block background activity launch even if the app is still
        // visible to user after user clicking home button.

@@ -1044,21 +1054,19 @@ public class BackgroundActivityStartController {
            return new BalVerdict(BAL_ALLOW_VISIBLE_WINDOW,
                    /*background*/ false, "callingUid has visible window");
        }
        return BalVerdict.BLOCK;
    };

    private final BalExemptionCheck mCheckCallerNonAppVisible = state -> {
        if (state.mCallingUidHasNonAppVisibleWindow) {
            return new BalVerdict(BAL_ALLOW_NON_APP_VISIBLE_WINDOW,
                    /*background*/ false, "callingUid has non-app visible window "
                    + mService.mActiveUids.getNonAppVisibleWindowDetails(state.mCallingUid));
        }
        // Don't abort if the callerApp or other processes of that uid are considered to be in the
        // foreground.
        return checkProcessAllowsBal(state.mCallerApp, state, BAL_CHECK_FOREGROUND);
    }
        return BalVerdict.BLOCK;
    };

    /**
     * @return A code denoting which BAL rule allows an activity to be started,
     * or {@link #BAL_BLOCK} if the launch should be blocked
     */
    BalVerdict checkBackgroundActivityStartAllowedByCallerInBackground(BalState state) {
    private final BalExemptionCheck mCheckCallerIsAllowlistedUid = state -> {
        // don't abort for the most important UIDs
        final int callingAppId = UserHandle.getAppId(state.mCallingUid);
        if (state.mCallingUid == Process.ROOT_UID
@@ -1068,7 +1076,10 @@ public class BackgroundActivityStartController {
                    BAL_ALLOW_ALLOWLISTED_UID, /*background*/ false,
                    "Important callingUid");
        }
        return BalVerdict.BLOCK;
    };

    private final BalExemptionCheck mCheckCallerIsAllowlistedComponent = state -> {
        // Always allow home application to start activities.
        if (isHomeApp(state.mCallingUid, state.mCallingPackage)) {
            return new BalVerdict(BAL_ALLOW_ALLOWLISTED_COMPONENT,
@@ -1076,6 +1087,7 @@ public class BackgroundActivityStartController {
                    "Home app");
        }

        final int callingAppId = UserHandle.getAppId(state.mCallingUid);
        // IME should always be allowed to start activity, like IME settings.
        final WindowState imeWindow =
                mService.mRootWindowContainer.getCurrentInputMethodWindow();
@@ -1091,12 +1103,6 @@ public class BackgroundActivityStartController {
                    /*background*/ false, "callingUid is persistent system process");
        }

        // don't abort if the callingUid has START_ACTIVITIES_FROM_BACKGROUND permission
        if (hasBalPermission(state.mCallingUid, state.mCallingPid)) {
            return new BalVerdict(BAL_ALLOW_PERMISSION,
                    /*background*/ true,
                    "START_ACTIVITIES_FROM_BACKGROUND permission granted");
        }
        // don't abort if the caller has the same uid as the recents component
        if (mSupervisor.mRecentTasks.isCallerRecents(state.mCallingUid)) {
            return new BalVerdict(BAL_ALLOW_ALLOWLISTED_COMPONENT,
@@ -1118,12 +1124,28 @@ public class BackgroundActivityStartController {
            return new BalVerdict(BAL_ALLOW_ALLOWLISTED_COMPONENT,
                    /*background*/ true, "Companion App");
        }
        return BalVerdict.BLOCK;
    };

    private final BalExemptionCheck mCheckCallerHasBackgroundPermission = state -> {
        // don't abort if the callingUid has START_ACTIVITIES_FROM_BACKGROUND permission
        if (hasBalPermission(state.mCallingUid, state.mCallingPid)) {
            return new BalVerdict(BAL_ALLOW_PERMISSION,
                    /*background*/ true,
                    "START_ACTIVITIES_FROM_BACKGROUND permission granted");
        }
        return BalVerdict.BLOCK;
    };
    private final BalExemptionCheck mCheckCallerHasSawPermission = state -> {
        // don't abort if the callingUid has SYSTEM_ALERT_WINDOW permission
        if (mService.hasSystemAlertWindowPermission(state.mCallingUid, state.mCallingPid,
                state.mCallingPackage)) {
            return new BalVerdict(BAL_ALLOW_SAW_PERMISSION,
                    /*background*/ true, "SYSTEM_ALERT_WINDOW permission is granted");
        }
        return BalVerdict.BLOCK;
    };
    private final BalExemptionCheck mCheckCallerHasBgStartAppOp = state -> {
        // don't abort if the callingUid and callingPackage have the
        // OP_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION appop
        if (isSystemExemptFlagEnabled() && mService.getAppOpsManager().checkOpNoThrow(
@@ -1132,9 +1154,36 @@ public class BackgroundActivityStartController {
            return new BalVerdict(BAL_ALLOW_PERMISSION, /*background*/ true,
                    "OP_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION appop is granted");
        }
        return BalVerdict.BLOCK;
    };


    // Don't abort if the callerApp or other processes of that uid are considered to be in the
    // foreground.
    private final BalExemptionCheck mCheckCallerProcessAllowsForeground =
            state -> checkProcessAllowsBal(state.mCallerApp, state, BAL_CHECK_FOREGROUND);
    // Don't abort if the callerApp or other processes of that uid are allowed in any way.
        return checkProcessAllowsBal(state.mCallerApp, state, BAL_CHECK_BACKGROUND);
    private final BalExemptionCheck mCheckCallerProcessAllowsBackground =
            state -> checkProcessAllowsBal(state.mCallerApp, state, BAL_CHECK_BACKGROUND);

    /**
     * @return A code denoting which BAL rule allows an activity to be started,
     * or {@link #BAL_BLOCK} if the launch should be blocked
     */
    BalVerdict checkBackgroundActivityStartAllowedByCallerInForeground(BalState state) {
        return evaluateChain(state, mCheckCallerVisible, mCheckCallerNonAppVisible,
                mCheckCallerProcessAllowsForeground);
    }

    /**
     * @return A code denoting which BAL rule allows an activity to be started,
     * or {@link #BAL_BLOCK} if the launch should be blocked
     */
    BalVerdict checkBackgroundActivityStartAllowedByCallerInBackground(BalState state) {
        return evaluateChain(state, mCheckCallerIsAllowlistedUid,
                mCheckCallerIsAllowlistedComponent, mCheckCallerHasBackgroundPermission,
                mCheckCallerHasSawPermission, mCheckCallerHasBgStartAppOp,
                mCheckCallerProcessAllowsBackground);
    }

    /**
@@ -1151,11 +1200,7 @@ public class BackgroundActivityStartController {
        return result;
    }

    /**
     * @return A code denoting which BAL rule allows an activity to be started,
     * or {@link #BAL_BLOCK} if the launch should be blocked
     */
    BalVerdict checkBackgroundActivityStartAllowedByRealCallerInForeground(BalState state) {
    private final BalExemptionCheck mCheckRealCallerVisible = state -> {
        // Normal apps with visible app window will be allowed to start activity if app switching
        // is allowed, or apps like live wallpaper with non app visible window will be allowed.
        // The home app can start apps even if app switches are usually disallowed.
@@ -1166,22 +1211,30 @@ public class BackgroundActivityStartController {
            return new BalVerdict(BAL_ALLOW_VISIBLE_WINDOW,
                    /*background*/ false, "realCallingUid has visible window");
        }
        return BalVerdict.BLOCK;
    };

    private final BalExemptionCheck mCheckRealCallerNonAppVisible = state -> {
        if (state.mRealCallingUidHasNonAppVisibleWindow) {
            return new BalVerdict(BAL_ALLOW_NON_APP_VISIBLE_WINDOW,
                    /*background*/ false, "realCallingUid has non-app visible window "
                    + mService.mActiveUids.getNonAppVisibleWindowDetails(state.mRealCallingUid));
        }
        return BalVerdict.BLOCK;
    };

    private final BalExemptionCheck mCheckRealCallerProcessAllowsBalForeground = state -> {
        // Don't abort if the realCallerApp or other processes of that uid are considered to be in
        // the foreground.
        return checkProcessAllowsBal(state.mRealCallerApp, state, BAL_CHECK_FOREGROUND);
    }
    };

    /**
     * @return A code denoting which BAL rule allows an activity to be started,
     * or {@link #BAL_BLOCK} if the launch should be blocked
     */
    BalVerdict checkBackgroundActivityStartAllowedByRealCallerInBackground(BalState state) {
    private final BalExemptionCheck mCheckRealCallerProcessAllowsBalBackground = state -> {
        // don't abort if the callerApp or other processes of that uid are allowed in any way
        return checkProcessAllowsBal(state.mRealCallerApp, state, BAL_CHECK_BACKGROUND);
    };

    private final BalExemptionCheck mCheckRealCallerBalPermission = state -> {
        boolean allowAlways = state.mCheckedOptions.getPendingIntentBackgroundActivityStartMode()
                == MODE_BACKGROUND_ACTIVITY_START_ALLOW_ALWAYS;
        if (allowAlways
@@ -1190,7 +1243,12 @@ public class BackgroundActivityStartController {
                    /*background*/ false,
                    "realCallingUid has BAL permission.");
        }
        return BalVerdict.BLOCK;
    };

    private final BalExemptionCheck mCheckRealCallerSawPermission = state -> {
        boolean allowAlways = state.mCheckedOptions.getPendingIntentBackgroundActivityStartMode()
                == MODE_BACKGROUND_ACTIVITY_START_ALLOW_ALWAYS;
        // don't abort if the realCallingUid has SYSTEM_ALERT_WINDOW permission
        if (allowAlways
                && mService.hasSystemAlertWindowPermission(state.mRealCallingUid,
@@ -1198,7 +1256,12 @@ public class BackgroundActivityStartController {
            return new BalVerdict(BAL_ALLOW_SAW_PERMISSION,
                    /*background*/ true, "SYSTEM_ALERT_WINDOW permission is granted");
        }
        return BalVerdict.BLOCK;
    };

    private final BalExemptionCheck mCheckRealCallerAllowlistedUid = state -> {
        boolean allowAlways = state.mCheckedOptions.getPendingIntentBackgroundActivityStartMode()
                == MODE_BACKGROUND_ACTIVITY_START_ALLOW_ALWAYS;
        // if the realCallingUid is a persistent system process, abort if the IntentSender
        // wasn't allowed to start an activity
        if ((allowAlways || state.mAllowBalExemptionForSystemProcess)
@@ -1208,6 +1271,10 @@ public class BackgroundActivityStartController {
                    "realCallingUid is persistent system process AND intent "
                            + "sender forced to allow.");
        }
        return BalVerdict.BLOCK;
    };

    private final BalExemptionCheck mCheckRealCallerAllowlistedComponent = state -> {
        // don't abort if the realCallingUid is an associated companion app
        if (mService.isAssociatedCompanionApp(
                UserHandle.getUserId(state.mRealCallingUid), state.mRealCallingUid)) {
@@ -1215,9 +1282,26 @@ public class BackgroundActivityStartController {
                    /*background*/ false,
                    "realCallingUid is a companion app.");
        }
        return BalVerdict.BLOCK;
    };

    /**
     * @return A code denoting which BAL rule allows an activity to be started,
     * or {@link #BAL_BLOCK} if the launch should be blocked
     */
    BalVerdict checkBackgroundActivityStartAllowedByRealCallerInForeground(BalState state) {
        return evaluateChain(state, mCheckRealCallerVisible, mCheckRealCallerNonAppVisible,
                mCheckRealCallerProcessAllowsBalForeground);
    }

        // don't abort if the callerApp or other processes of that uid are allowed in any way
        return checkProcessAllowsBal(state.mRealCallerApp, state, BAL_CHECK_BACKGROUND);
    /**
     * @return A code denoting which BAL rule allows an activity to be started,
     * or {@link #BAL_BLOCK} if the launch should be blocked
     */
    BalVerdict checkBackgroundActivityStartAllowedByRealCallerInBackground(BalState state) {
        return evaluateChain(state, mCheckRealCallerBalPermission, mCheckRealCallerSawPermission,
                mCheckRealCallerAllowlistedUid, mCheckRealCallerAllowlistedComponent,
                mCheckRealCallerProcessAllowsBalBackground);
    }

    @VisibleForTesting boolean hasBalPermission(int uid, int pid) {