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

Commit e93dcc71 authored by Louis Chang's avatar Louis Chang Committed by Android (Google) Code Review
Browse files

Merge "Fix top app unable to start activity due to BAL" into main

parents ad66e910 cfd627c8
Loading
Loading
Loading
Loading
+18 −5
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.server.wm;

import static android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND;
import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
import static android.app.ActivityManager.PROCESS_STATE_TOP;
import static android.app.ActivityOptions.BackgroundActivityStartMode;
import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED;
import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOW_ALWAYS;
@@ -1096,11 +1097,11 @@ public class BackgroundActivityStartController {
                    mCheckCallerProcessInGracePeriod);
        }
        return evaluateChain(state, basedOnRealCaller, mCheckCallerVisible,
                mCheckCallerNonAppVisible, mCheckCallerProcessAllowsForeground,
                mCheckCallerIsAllowlistedUid, mCheckCallerIsAllowlistedComponent,
                mCheckCallerHasBackgroundPermission, mCheckCallerHasSawPermission,
                mCheckCallerHasBgStartAppOp, mCheckCallerProcessAllowsBackground,
                mCheckCallerProcessInGracePeriod);
                mCheckCallerNonAppVisible, mCheckCallerNonActivityTop,
                mCheckCallerProcessAllowsForeground, mCheckCallerIsAllowlistedUid,
                mCheckCallerIsAllowlistedComponent, mCheckCallerHasBackgroundPermission,
                mCheckCallerHasSawPermission, mCheckCallerHasBgStartAppOp,
                mCheckCallerProcessAllowsBackground, mCheckCallerProcessInGracePeriod);
    }

    interface BalExemptionCheck {
@@ -1149,6 +1150,18 @@ public class BackgroundActivityStartController {
        return BalVerdict.BLOCK;
    };

    private final BalExemptionCheck mCheckCallerNonActivityTop = state -> {
        // Allows if the UID process state is at the top and the app is not yet hosting any
        // activities. This is possible if the application starts an activity within its
        // `Application#onCreate` method when the process started, identifying a visible activity
        // from that app is not possible because the application process has not yet fully attached.
        if (state.mCallerApp != null && !state.mCallerApp.hasActivities()
                && state.mCallingUidProcState == PROCESS_STATE_TOP) {
            return new BalVerdict(BAL_ALLOW_FOREGROUND, "callingUid is the current top");
        }
        return BalVerdict.BLOCK;
    };

    private BalVerdict checkNonAppVisibleWindow(int uid, boolean hasNonAppVisibleWindow) {
        if (hasNonAppVisibleWindow) {
            SparseIntArray nonAppVisibleWindowDetails =
+42 −0
Original line number Diff line number Diff line
@@ -16,9 +16,11 @@

package com.android.server.wm;

import static android.app.ActivityManager.PROCESS_STATE_TOP;
import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED;
import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOW_ALWAYS;
import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOW_IF_VISIBLE;
import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED;

import static com.android.server.wm.ActivityTaskManagerService.APP_SWITCH_ALLOW;
import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_ALLOWLISTED_COMPONENT;
@@ -300,6 +302,46 @@ public class BackgroundActivityStartControllerExemptionTests {
                .isEqualTo(BAL_BLOCK);
    }

    @Test
    public void testCaller_appIsTop() {
        int callingUid = REGULAR_UID_1;
        int callingPid = REGULAR_PID_1;
        final String callingPackage = REGULAR_PACKAGE_1;
        int realCallingUid = REGULAR_UID_2;
        int realCallingPid = REGULAR_PID_2;

        // setup state
        when(mVisibleActivityProcessTracker.hasVisibleActivity(eq(callingUid))).thenReturn(false);
        when(mVisibleActivityProcessTracker.hasVisibleNotPinnedActivity(eq(callingUid)))
                .thenReturn(false);
        when(mService.getBalAppSwitchesState()).thenReturn(APP_SWITCH_ALLOW);
        mActiveUids.onUidActive(callingUid, PROCESS_STATE_TOP);

        // prepare call
        PendingIntentRecord originatingPendingIntent = null;
        boolean allowBalExemptionForSystemProcess = false;
        Intent intent = TEST_INTENT;
        ActivityOptions checkedOptions = mCheckedOptions
                .setPendingIntentCreatorBackgroundActivityStartMode(
                        MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED);
        BackgroundActivityStartController.BalState balState = mController.new BalState(callingUid,
                callingPid, callingPackage, realCallingUid, realCallingPid, mCallerApp,
                originatingPendingIntent, allowBalExemptionForSystemProcess, mResultRecord, intent,
                checkedOptions);
        assertThat(balState.toString()).contains("callingUidHasVisibleActivity: false");
        assertThat(balState.toString()).contains("callingUidHasVisibleNotPinnedActivity: false");
        assertThat(balState.toString()).contains("callingUidHasNonAppVisibleWindow: false");

        // call
        BalVerdict callerVerdict = mController.checkBackgroundActivityStartAllowedByCaller(
                balState);
        balState.setResultForCaller(callerVerdict);

        // assertions
        assertWithMessage(balState.toString()).that(callerVerdict.getCode()).isEqualTo(
                BAL_ALLOW_FOREGROUND);
    }

    @Test
    public void testCaller_appHasVisiblePinnedWindow() {
        int callingUid = REGULAR_UID_1;