Loading services/core/java/com/android/server/wm/BackgroundActivityStartController.java +19 −4 Original line number Diff line number Diff line Loading @@ -307,6 +307,7 @@ public class BackgroundActivityStartController { private final int mCallingPid; private final @ActivityTaskManagerService.AppSwitchState int mAppSwitchState; private final boolean mCallingUidHasVisibleActivity; private final boolean mCallingUidHasVisibleNotPinnedActivity; private final boolean mCallingUidHasNonAppVisibleWindow; private final @ActivityManager.ProcessState int mCallingUidProcState; private final boolean mIsCallingUidPersistentSystemProcess; Loading @@ -316,6 +317,7 @@ public class BackgroundActivityStartController { private final int mRealCallingUid; private final int mRealCallingPid; private final boolean mRealCallingUidHasVisibleActivity; private final boolean mRealCallingUidHasVisibleNotPinnedActivity; private final boolean mRealCallingUidHasNonAppVisibleWindow; private final @ActivityManager.ProcessState int mRealCallingUidProcState; private final boolean mIsRealCallingUidPersistentSystemProcess; Loading Loading @@ -406,6 +408,8 @@ public class BackgroundActivityStartController { mCallingUidProcState <= ActivityManager.PROCESS_STATE_PERSISTENT_UI; mCallingUidHasVisibleActivity = getService().mVisibleActivityProcessTracker.hasVisibleActivity(callingUid); mCallingUidHasVisibleNotPinnedActivity = getService().mVisibleActivityProcessTracker .hasVisibleNotPinnedActivity(callingUid); mCallingUidHasNonAppVisibleWindow = getService().mActiveUids.hasNonAppVisibleWindow( callingUid); if (realCallingUid == NO_PROCESS_UID) { Loading @@ -413,11 +417,13 @@ public class BackgroundActivityStartController { mRealCallingUidProcState = PROCESS_STATE_NONEXISTENT; mRealCallingUidHasVisibleActivity = false; mRealCallingUidHasNonAppVisibleWindow = false; mRealCallingUidHasVisibleNotPinnedActivity = false; mRealCallerApp = null; mIsRealCallingUidPersistentSystemProcess = false; } else if (callingUid == realCallingUid) { mRealCallingUidProcState = mCallingUidProcState; mRealCallingUidHasVisibleActivity = mCallingUidHasVisibleActivity; mRealCallingUidHasVisibleNotPinnedActivity = mCallingUidHasVisibleNotPinnedActivity; mRealCallingUidHasNonAppVisibleWindow = mCallingUidHasNonAppVisibleWindow; // In the PendingIntent case callerApp is not passed in, so resolve it ourselves. mRealCallerApp = callerApp == null Loading @@ -429,6 +435,9 @@ public class BackgroundActivityStartController { mRealCallingUidHasVisibleActivity = getService().mVisibleActivityProcessTracker.hasVisibleActivity( realCallingUid); mRealCallingUidHasVisibleNotPinnedActivity = getService().mVisibleActivityProcessTracker.hasVisibleNotPinnedActivity( realCallingUid); mRealCallingUidHasNonAppVisibleWindow = getService().mActiveUids.hasNonAppVisibleWindow(realCallingUid); mRealCallerApp = getService().getProcessController(realCallingPid, realCallingUid); Loading Loading @@ -562,6 +571,8 @@ public class BackgroundActivityStartController { sb.append("; callingPid: ").append(mCallingPid); sb.append("; appSwitchState: ").append(mAppSwitchState); sb.append("; callingUidHasVisibleActivity: ").append(mCallingUidHasVisibleActivity); sb.append("; callingUidHasVisibleNotPinnedActivity: ") .append(mCallingUidHasVisibleNotPinnedActivity); sb.append("; callingUidHasNonAppVisibleWindow: ").append( mCallingUidHasNonAppVisibleWindow); sb.append("; callingUidProcState: ").append(DebugUtils.valueToString( Loading Loading @@ -596,6 +607,8 @@ public class BackgroundActivityStartController { sb.append("; realCallingPid: ").append(mRealCallingPid); sb.append("; realCallingUidHasVisibleActivity: ") .append(mRealCallingUidHasVisibleActivity); sb.append("; realCallingUidHasVisibleNotPinnedActivity: ") .append(mRealCallingUidHasVisibleNotPinnedActivity); sb.append("; realCallingUidHasNonAppVisibleWindow: ") .append(mRealCallingUidHasNonAppVisibleWindow); sb.append("; realCallingUidProcState: ").append(DebugUtils.valueToString( Loading Loading @@ -1033,8 +1046,9 @@ public class BackgroundActivityStartController { final boolean appSwitchAllowedOrFg = state.mAppSwitchState == APP_SWITCH_ALLOW || state.mAppSwitchState == APP_SWITCH_FG_ONLY || isHomeApp(state.mCallingUid, state.mCallingPackage); if (appSwitchAllowedOrFg && state.mCallingUidHasVisibleActivity) { return new BalVerdict(BAL_ALLOW_VISIBLE_WINDOW, "callingUid has visible window"); if (appSwitchAllowedOrFg && state.mCallingUidHasVisibleNotPinnedActivity) { return new BalVerdict(BAL_ALLOW_VISIBLE_WINDOW, "callingUid has visible non-pinned window"); } return BalVerdict.BLOCK; }; Loading Loading @@ -1162,8 +1176,9 @@ public class BackgroundActivityStartController { final boolean appSwitchAllowedOrFg = state.mAppSwitchState == APP_SWITCH_ALLOW || state.mAppSwitchState == APP_SWITCH_FG_ONLY || isHomeApp(state.mRealCallingUid, state.mRealCallingPackage); if (appSwitchAllowedOrFg && state.mRealCallingUidHasVisibleActivity) { return new BalVerdict(BAL_ALLOW_VISIBLE_WINDOW, "realCallingUid has visible window"); if (appSwitchAllowedOrFg && state.mRealCallingUidHasVisibleNotPinnedActivity) { return new BalVerdict(BAL_ALLOW_VISIBLE_WINDOW, "realCallingUid has visible non-pinned window"); } return BalVerdict.BLOCK; }; Loading services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java +7 −4 Original line number Diff line number Diff line Loading @@ -118,7 +118,8 @@ class BackgroundLaunchProcessController { BalVerdict areBackgroundActivityStartsAllowed( int pid, int uid, String packageName, int appSwitchState, BalCheckConfiguration checkConfiguration, boolean hasActivityInVisibleTask, boolean hasBackgroundActivityStartPrivileges, boolean hasActivityInVisibleTask, boolean inPinnedWindow, boolean hasBackgroundActivityStartPrivileges, long lastStopAppSwitchesTime, long lastActivityLaunchTime, long lastActivityFinishTime) { // Allow if the proc is instrumenting with background activity starts privs. Loading @@ -140,9 +141,11 @@ class BackgroundLaunchProcessController { && isBoundByForegroundUid()) { return new BalVerdict(BAL_ALLOW_BOUND_BY_FOREGROUND, "process bound by foreground uid"); } // Allow if the caller has an activity in any foreground task. if (checkConfiguration.checkOtherExemptions && hasActivityInVisibleTask && appSwitchState != APP_SWITCH_DISALLOW) { // Allow if the caller has an activity in any foreground task, unless it's a pinned window // and not a foreground service start. if ((checkConfiguration.isCheckingForFgsStart || !inPinnedWindow) && checkConfiguration.checkOtherExemptions && hasActivityInVisibleTask && appSwitchState != APP_SWITCH_DISALLOW) { return new BalVerdict(BAL_ALLOW_FOREGROUND, /*background*/ "process has activity in foreground task"); } Loading services/core/java/com/android/server/wm/VisibleActivityProcessTracker.java +10 −2 Original line number Diff line number Diff line Loading @@ -80,14 +80,22 @@ class VisibleActivityProcessTracker { * {@link ActivityRecord#mVisibleRequested} or {@link ActivityRecord#isVisible()} is true. */ boolean hasVisibleActivity(int uid) { return match(uid, null /* predicate */); return match(uid, WindowContainer.alwaysTruePredicate()); } /** * Returns {@code true} if the uid has a process that contains an activity with * {@link ActivityRecord#mVisibleRequested} or {@link ActivityRecord#isVisible()} is true. */ boolean hasVisibleNotPinnedActivity(int uid) { return match(uid, wpc -> !wpc.inPinnedWindowingMode()); } private boolean match(int uid, Predicate<WindowProcessController> predicate) { synchronized (mProcMap) { for (int i = mProcMap.size() - 1; i >= 0; i--) { final WindowProcessController wpc = mProcMap.keyAt(i); if (wpc.mUid == uid && (predicate == null || predicate.test(wpc))) { if (wpc.mUid == uid && predicate.test(wpc)) { return true; } } Loading services/core/java/com/android/server/wm/WindowProcessController.java +2 −1 Original line number Diff line number Diff line Loading @@ -724,7 +724,8 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio int appSwitchState, BalCheckConfiguration checkConfiguration) { return mBgLaunchController.areBackgroundActivityStartsAllowed(mPid, mUid, mInfo.packageName, appSwitchState, checkConfiguration, hasActivityInVisibleTask(), mInstrumentingWithBackgroundActivityStartPrivileges, hasActivityInVisibleTask(), inPinnedWindowingMode(), mInstrumentingWithBackgroundActivityStartPrivileges, mAtm.getLastStopAppSwitchesTime(), mLastActivityLaunchTime, mLastActivityFinishTime); } Loading services/tests/wmtests/src/com/android/server/wm/BackgroundActivityStartControllerExemptionTests.java +106 −8 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ import android.platform.test.annotations.Presubmit; import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.CheckFlagsRule; import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.platform.test.flag.junit.SetFlagsRule; import android.provider.DeviceConfig; import android.util.Pair; import android.view.WindowManager; Loading @@ -64,6 +65,7 @@ import com.android.window.flags.Flags; import org.junit.After; import org.junit.Before; import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; Loading @@ -88,6 +90,10 @@ import java.util.Set; @RunWith(JUnit4.class) public class BackgroundActivityStartControllerExemptionTests { @ClassRule public static final SetFlagsRule.ClassRule mClassRule = new SetFlagsRule.ClassRule(); @Rule public final SetFlagsRule mSetFlagsRule = mClassRule.createSetFlagsRule(); private static final int REGULAR_UID_1 = 10100; private static final int REGULAR_UID_2 = 10200; private static final int NO_UID = -1; Loading Loading @@ -265,6 +271,8 @@ public class BackgroundActivityStartControllerExemptionTests { // setup state when(mVisibleActivityProcessTracker.hasVisibleActivity(eq(callingUid))).thenReturn(true); when(mVisibleActivityProcessTracker.hasVisibleNotPinnedActivity(eq(callingUid))) .thenReturn(false); when(mService.getBalAppSwitchesState()).thenReturn(APP_SWITCH_ALLOW); // prepare call Loading @@ -277,6 +285,7 @@ public class BackgroundActivityStartControllerExemptionTests { originatingPendingIntent, allowBalExemptionForSystemProcess, mResultRecord, intent, checkedOptions); assertThat(balState.toString()).contains("callingUidHasVisibleActivity: true"); assertThat(balState.toString()).contains("callingUidHasVisibleNotPinnedActivity: false"); assertThat(balState.toString()).contains("callingUidHasNonAppVisibleWindow: false"); // call Loading @@ -285,8 +294,47 @@ public class BackgroundActivityStartControllerExemptionTests { balState.setResultForCaller(callerVerdict); // assertions assertWithMessage(balState.toString()).that(callerVerdict.getCode()).isEqualTo( BAL_ALLOW_VISIBLE_WINDOW); assertWithMessage(balState + " -> " + callerVerdict) .that(callerVerdict.getCode()) .isEqualTo(BAL_BLOCK); } @Test public void testCaller_appHasVisiblePinnedWindow() { 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(true); when(mVisibleActivityProcessTracker.hasVisibleNotPinnedActivity(eq(callingUid))) .thenReturn(true); when(mService.getBalAppSwitchesState()).thenReturn(APP_SWITCH_ALLOW); // prepare call PendingIntentRecord originatingPendingIntent = mPendingIntentRecord; boolean allowBalExemptionForSystemProcess = false; Intent intent = TEST_INTENT; ActivityOptions checkedOptions = mCheckedOptions; BackgroundActivityStartController.BalState balState = mController.new BalState(callingUid, callingPid, callingPackage, realCallingUid, realCallingPid, mCallerApp, originatingPendingIntent, allowBalExemptionForSystemProcess, mResultRecord, intent, checkedOptions); assertThat(balState.toString()).contains("callingUidHasVisibleActivity: true"); assertThat(balState.toString()).contains("callingUidHasVisibleNotPinnedActivity: true"); assertThat(balState.toString()).contains("callingUidHasNonAppVisibleWindow: false"); // call BalVerdict callerVerdict = mController.checkBackgroundActivityStartAllowedByCaller( balState); balState.setResultForCaller(callerVerdict); // assertions assertWithMessage(balState + " -> " + callerVerdict) .that(callerVerdict.getCode()) .isEqualTo(BAL_ALLOW_VISIBLE_WINDOW); } @Test Loading @@ -298,8 +346,10 @@ public class BackgroundActivityStartControllerExemptionTests { int realCallingPid = REGULAR_PID_2; // setup state when(mVisibleActivityProcessTracker.hasVisibleActivity(eq(realCallingUid))).thenReturn( true); when(mVisibleActivityProcessTracker.hasVisibleActivity(eq(realCallingUid))) .thenReturn(true); when(mVisibleActivityProcessTracker.hasVisibleNotPinnedActivity(eq(realCallingUid))) .thenReturn(false); when(mService.getBalAppSwitchesState()).thenReturn(APP_SWITCH_ALLOW); // prepare call Loading @@ -312,6 +362,8 @@ public class BackgroundActivityStartControllerExemptionTests { originatingPendingIntent, allowBalExemptionForSystemProcess, mResultRecord, intent, checkedOptions); assertThat(balState.toString()).contains("realCallingUidHasVisibleActivity: true"); assertThat(balState.toString()) .contains("realCallingUidHasVisibleNotPinnedActivity: false"); assertThat(balState.toString()).contains("realCallingUidHasNonAppVisibleWindow: false"); // call Loading @@ -320,8 +372,48 @@ public class BackgroundActivityStartControllerExemptionTests { balState.setResultForRealCaller(realCallerVerdict); // assertions assertWithMessage(balState.toString()).that(realCallerVerdict.getCode()).isEqualTo( BAL_ALLOW_VISIBLE_WINDOW); assertWithMessage(balState + " -> " + realCallerVerdict) .that(realCallerVerdict.getCode()) .isEqualTo(BAL_BLOCK); } @Test public void testRealCaller_appHasNotPinnedVisibleWindow() { 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(realCallingUid))) .thenReturn(true); when(mVisibleActivityProcessTracker.hasVisibleNotPinnedActivity(eq(realCallingUid))) .thenReturn(true); when(mService.getBalAppSwitchesState()).thenReturn(APP_SWITCH_ALLOW); // prepare call PendingIntentRecord originatingPendingIntent = mPendingIntentRecord; boolean allowBalExemptionForSystemProcess = false; Intent intent = TEST_INTENT; ActivityOptions checkedOptions = mCheckedOptions; BackgroundActivityStartController.BalState balState = mController.new BalState(callingUid, callingPid, callingPackage, realCallingUid, realCallingPid, mCallerApp, originatingPendingIntent, allowBalExemptionForSystemProcess, mResultRecord, intent, checkedOptions); assertThat(balState.toString()).contains("realCallingUidHasVisibleActivity: true"); assertThat(balState.toString()).contains("realCallingUidHasVisibleNotPinnedActivity: true"); assertThat(balState.toString()).contains("realCallingUidHasNonAppVisibleWindow: false"); // call BalVerdict realCallerVerdict = mController.checkBackgroundActivityStartAllowedByRealCaller( balState); balState.setResultForRealCaller(realCallerVerdict); // assertions assertWithMessage(balState + " -> " + realCallerVerdict) .that(realCallerVerdict.getCode()) .isEqualTo(BAL_ALLOW_VISIBLE_WINDOW); } @Test Loading Loading @@ -405,6 +497,8 @@ public class BackgroundActivityStartControllerExemptionTests { // setup state when(mVisibleActivityProcessTracker.hasVisibleActivity(eq(callingUid))).thenReturn(true); when(mVisibleActivityProcessTracker.hasVisibleNotPinnedActivity(eq(callingUid))) .thenReturn(true); when(mService.getBalAppSwitchesState()).thenReturn(APP_SWITCH_ALLOW); // prepare call Loading @@ -419,6 +513,7 @@ public class BackgroundActivityStartControllerExemptionTests { originatingPendingIntent, allowBalExemptionForSystemProcess, mResultRecord, intent, checkedOptions); assertThat(balState.toString()).contains("callingUidHasVisibleActivity: true"); assertThat(balState.toString()).contains("callingUidHasVisibleNotPinnedActivity: true"); assertThat(balState.toString()).contains("callingUidHasNonAppVisibleWindow: false"); // call Loading @@ -441,8 +536,10 @@ public class BackgroundActivityStartControllerExemptionTests { int realCallingPid = REGULAR_PID_2; // setup state when(mVisibleActivityProcessTracker.hasVisibleActivity(eq(realCallingUid))).thenReturn( true); when(mVisibleActivityProcessTracker.hasVisibleActivity(eq(realCallingUid))) .thenReturn(true); when(mVisibleActivityProcessTracker.hasVisibleNotPinnedActivity(eq(realCallingUid))) .thenReturn(true); when(mService.getBalAppSwitchesState()).thenReturn(APP_SWITCH_ALLOW); // prepare call Loading @@ -457,6 +554,7 @@ public class BackgroundActivityStartControllerExemptionTests { originatingPendingIntent, allowBalExemptionForSystemProcess, mResultRecord, intent, checkedOptions); assertThat(balState.toString()).contains("realCallingUidHasVisibleActivity: true"); assertThat(balState.toString()).contains("realCallingUidHasVisibleNotPinnedActivity: true"); assertThat(balState.toString()).contains("realCallingUidHasNonAppVisibleWindow: false"); // call Loading Loading
services/core/java/com/android/server/wm/BackgroundActivityStartController.java +19 −4 Original line number Diff line number Diff line Loading @@ -307,6 +307,7 @@ public class BackgroundActivityStartController { private final int mCallingPid; private final @ActivityTaskManagerService.AppSwitchState int mAppSwitchState; private final boolean mCallingUidHasVisibleActivity; private final boolean mCallingUidHasVisibleNotPinnedActivity; private final boolean mCallingUidHasNonAppVisibleWindow; private final @ActivityManager.ProcessState int mCallingUidProcState; private final boolean mIsCallingUidPersistentSystemProcess; Loading @@ -316,6 +317,7 @@ public class BackgroundActivityStartController { private final int mRealCallingUid; private final int mRealCallingPid; private final boolean mRealCallingUidHasVisibleActivity; private final boolean mRealCallingUidHasVisibleNotPinnedActivity; private final boolean mRealCallingUidHasNonAppVisibleWindow; private final @ActivityManager.ProcessState int mRealCallingUidProcState; private final boolean mIsRealCallingUidPersistentSystemProcess; Loading Loading @@ -406,6 +408,8 @@ public class BackgroundActivityStartController { mCallingUidProcState <= ActivityManager.PROCESS_STATE_PERSISTENT_UI; mCallingUidHasVisibleActivity = getService().mVisibleActivityProcessTracker.hasVisibleActivity(callingUid); mCallingUidHasVisibleNotPinnedActivity = getService().mVisibleActivityProcessTracker .hasVisibleNotPinnedActivity(callingUid); mCallingUidHasNonAppVisibleWindow = getService().mActiveUids.hasNonAppVisibleWindow( callingUid); if (realCallingUid == NO_PROCESS_UID) { Loading @@ -413,11 +417,13 @@ public class BackgroundActivityStartController { mRealCallingUidProcState = PROCESS_STATE_NONEXISTENT; mRealCallingUidHasVisibleActivity = false; mRealCallingUidHasNonAppVisibleWindow = false; mRealCallingUidHasVisibleNotPinnedActivity = false; mRealCallerApp = null; mIsRealCallingUidPersistentSystemProcess = false; } else if (callingUid == realCallingUid) { mRealCallingUidProcState = mCallingUidProcState; mRealCallingUidHasVisibleActivity = mCallingUidHasVisibleActivity; mRealCallingUidHasVisibleNotPinnedActivity = mCallingUidHasVisibleNotPinnedActivity; mRealCallingUidHasNonAppVisibleWindow = mCallingUidHasNonAppVisibleWindow; // In the PendingIntent case callerApp is not passed in, so resolve it ourselves. mRealCallerApp = callerApp == null Loading @@ -429,6 +435,9 @@ public class BackgroundActivityStartController { mRealCallingUidHasVisibleActivity = getService().mVisibleActivityProcessTracker.hasVisibleActivity( realCallingUid); mRealCallingUidHasVisibleNotPinnedActivity = getService().mVisibleActivityProcessTracker.hasVisibleNotPinnedActivity( realCallingUid); mRealCallingUidHasNonAppVisibleWindow = getService().mActiveUids.hasNonAppVisibleWindow(realCallingUid); mRealCallerApp = getService().getProcessController(realCallingPid, realCallingUid); Loading Loading @@ -562,6 +571,8 @@ public class BackgroundActivityStartController { sb.append("; callingPid: ").append(mCallingPid); sb.append("; appSwitchState: ").append(mAppSwitchState); sb.append("; callingUidHasVisibleActivity: ").append(mCallingUidHasVisibleActivity); sb.append("; callingUidHasVisibleNotPinnedActivity: ") .append(mCallingUidHasVisibleNotPinnedActivity); sb.append("; callingUidHasNonAppVisibleWindow: ").append( mCallingUidHasNonAppVisibleWindow); sb.append("; callingUidProcState: ").append(DebugUtils.valueToString( Loading Loading @@ -596,6 +607,8 @@ public class BackgroundActivityStartController { sb.append("; realCallingPid: ").append(mRealCallingPid); sb.append("; realCallingUidHasVisibleActivity: ") .append(mRealCallingUidHasVisibleActivity); sb.append("; realCallingUidHasVisibleNotPinnedActivity: ") .append(mRealCallingUidHasVisibleNotPinnedActivity); sb.append("; realCallingUidHasNonAppVisibleWindow: ") .append(mRealCallingUidHasNonAppVisibleWindow); sb.append("; realCallingUidProcState: ").append(DebugUtils.valueToString( Loading Loading @@ -1033,8 +1046,9 @@ public class BackgroundActivityStartController { final boolean appSwitchAllowedOrFg = state.mAppSwitchState == APP_SWITCH_ALLOW || state.mAppSwitchState == APP_SWITCH_FG_ONLY || isHomeApp(state.mCallingUid, state.mCallingPackage); if (appSwitchAllowedOrFg && state.mCallingUidHasVisibleActivity) { return new BalVerdict(BAL_ALLOW_VISIBLE_WINDOW, "callingUid has visible window"); if (appSwitchAllowedOrFg && state.mCallingUidHasVisibleNotPinnedActivity) { return new BalVerdict(BAL_ALLOW_VISIBLE_WINDOW, "callingUid has visible non-pinned window"); } return BalVerdict.BLOCK; }; Loading Loading @@ -1162,8 +1176,9 @@ public class BackgroundActivityStartController { final boolean appSwitchAllowedOrFg = state.mAppSwitchState == APP_SWITCH_ALLOW || state.mAppSwitchState == APP_SWITCH_FG_ONLY || isHomeApp(state.mRealCallingUid, state.mRealCallingPackage); if (appSwitchAllowedOrFg && state.mRealCallingUidHasVisibleActivity) { return new BalVerdict(BAL_ALLOW_VISIBLE_WINDOW, "realCallingUid has visible window"); if (appSwitchAllowedOrFg && state.mRealCallingUidHasVisibleNotPinnedActivity) { return new BalVerdict(BAL_ALLOW_VISIBLE_WINDOW, "realCallingUid has visible non-pinned window"); } return BalVerdict.BLOCK; }; Loading
services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java +7 −4 Original line number Diff line number Diff line Loading @@ -118,7 +118,8 @@ class BackgroundLaunchProcessController { BalVerdict areBackgroundActivityStartsAllowed( int pid, int uid, String packageName, int appSwitchState, BalCheckConfiguration checkConfiguration, boolean hasActivityInVisibleTask, boolean hasBackgroundActivityStartPrivileges, boolean hasActivityInVisibleTask, boolean inPinnedWindow, boolean hasBackgroundActivityStartPrivileges, long lastStopAppSwitchesTime, long lastActivityLaunchTime, long lastActivityFinishTime) { // Allow if the proc is instrumenting with background activity starts privs. Loading @@ -140,9 +141,11 @@ class BackgroundLaunchProcessController { && isBoundByForegroundUid()) { return new BalVerdict(BAL_ALLOW_BOUND_BY_FOREGROUND, "process bound by foreground uid"); } // Allow if the caller has an activity in any foreground task. if (checkConfiguration.checkOtherExemptions && hasActivityInVisibleTask && appSwitchState != APP_SWITCH_DISALLOW) { // Allow if the caller has an activity in any foreground task, unless it's a pinned window // and not a foreground service start. if ((checkConfiguration.isCheckingForFgsStart || !inPinnedWindow) && checkConfiguration.checkOtherExemptions && hasActivityInVisibleTask && appSwitchState != APP_SWITCH_DISALLOW) { return new BalVerdict(BAL_ALLOW_FOREGROUND, /*background*/ "process has activity in foreground task"); } Loading
services/core/java/com/android/server/wm/VisibleActivityProcessTracker.java +10 −2 Original line number Diff line number Diff line Loading @@ -80,14 +80,22 @@ class VisibleActivityProcessTracker { * {@link ActivityRecord#mVisibleRequested} or {@link ActivityRecord#isVisible()} is true. */ boolean hasVisibleActivity(int uid) { return match(uid, null /* predicate */); return match(uid, WindowContainer.alwaysTruePredicate()); } /** * Returns {@code true} if the uid has a process that contains an activity with * {@link ActivityRecord#mVisibleRequested} or {@link ActivityRecord#isVisible()} is true. */ boolean hasVisibleNotPinnedActivity(int uid) { return match(uid, wpc -> !wpc.inPinnedWindowingMode()); } private boolean match(int uid, Predicate<WindowProcessController> predicate) { synchronized (mProcMap) { for (int i = mProcMap.size() - 1; i >= 0; i--) { final WindowProcessController wpc = mProcMap.keyAt(i); if (wpc.mUid == uid && (predicate == null || predicate.test(wpc))) { if (wpc.mUid == uid && predicate.test(wpc)) { return true; } } Loading
services/core/java/com/android/server/wm/WindowProcessController.java +2 −1 Original line number Diff line number Diff line Loading @@ -724,7 +724,8 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio int appSwitchState, BalCheckConfiguration checkConfiguration) { return mBgLaunchController.areBackgroundActivityStartsAllowed(mPid, mUid, mInfo.packageName, appSwitchState, checkConfiguration, hasActivityInVisibleTask(), mInstrumentingWithBackgroundActivityStartPrivileges, hasActivityInVisibleTask(), inPinnedWindowingMode(), mInstrumentingWithBackgroundActivityStartPrivileges, mAtm.getLastStopAppSwitchesTime(), mLastActivityLaunchTime, mLastActivityFinishTime); } Loading
services/tests/wmtests/src/com/android/server/wm/BackgroundActivityStartControllerExemptionTests.java +106 −8 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ import android.platform.test.annotations.Presubmit; import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.CheckFlagsRule; import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.platform.test.flag.junit.SetFlagsRule; import android.provider.DeviceConfig; import android.util.Pair; import android.view.WindowManager; Loading @@ -64,6 +65,7 @@ import com.android.window.flags.Flags; import org.junit.After; import org.junit.Before; import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; Loading @@ -88,6 +90,10 @@ import java.util.Set; @RunWith(JUnit4.class) public class BackgroundActivityStartControllerExemptionTests { @ClassRule public static final SetFlagsRule.ClassRule mClassRule = new SetFlagsRule.ClassRule(); @Rule public final SetFlagsRule mSetFlagsRule = mClassRule.createSetFlagsRule(); private static final int REGULAR_UID_1 = 10100; private static final int REGULAR_UID_2 = 10200; private static final int NO_UID = -1; Loading Loading @@ -265,6 +271,8 @@ public class BackgroundActivityStartControllerExemptionTests { // setup state when(mVisibleActivityProcessTracker.hasVisibleActivity(eq(callingUid))).thenReturn(true); when(mVisibleActivityProcessTracker.hasVisibleNotPinnedActivity(eq(callingUid))) .thenReturn(false); when(mService.getBalAppSwitchesState()).thenReturn(APP_SWITCH_ALLOW); // prepare call Loading @@ -277,6 +285,7 @@ public class BackgroundActivityStartControllerExemptionTests { originatingPendingIntent, allowBalExemptionForSystemProcess, mResultRecord, intent, checkedOptions); assertThat(balState.toString()).contains("callingUidHasVisibleActivity: true"); assertThat(balState.toString()).contains("callingUidHasVisibleNotPinnedActivity: false"); assertThat(balState.toString()).contains("callingUidHasNonAppVisibleWindow: false"); // call Loading @@ -285,8 +294,47 @@ public class BackgroundActivityStartControllerExemptionTests { balState.setResultForCaller(callerVerdict); // assertions assertWithMessage(balState.toString()).that(callerVerdict.getCode()).isEqualTo( BAL_ALLOW_VISIBLE_WINDOW); assertWithMessage(balState + " -> " + callerVerdict) .that(callerVerdict.getCode()) .isEqualTo(BAL_BLOCK); } @Test public void testCaller_appHasVisiblePinnedWindow() { 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(true); when(mVisibleActivityProcessTracker.hasVisibleNotPinnedActivity(eq(callingUid))) .thenReturn(true); when(mService.getBalAppSwitchesState()).thenReturn(APP_SWITCH_ALLOW); // prepare call PendingIntentRecord originatingPendingIntent = mPendingIntentRecord; boolean allowBalExemptionForSystemProcess = false; Intent intent = TEST_INTENT; ActivityOptions checkedOptions = mCheckedOptions; BackgroundActivityStartController.BalState balState = mController.new BalState(callingUid, callingPid, callingPackage, realCallingUid, realCallingPid, mCallerApp, originatingPendingIntent, allowBalExemptionForSystemProcess, mResultRecord, intent, checkedOptions); assertThat(balState.toString()).contains("callingUidHasVisibleActivity: true"); assertThat(balState.toString()).contains("callingUidHasVisibleNotPinnedActivity: true"); assertThat(balState.toString()).contains("callingUidHasNonAppVisibleWindow: false"); // call BalVerdict callerVerdict = mController.checkBackgroundActivityStartAllowedByCaller( balState); balState.setResultForCaller(callerVerdict); // assertions assertWithMessage(balState + " -> " + callerVerdict) .that(callerVerdict.getCode()) .isEqualTo(BAL_ALLOW_VISIBLE_WINDOW); } @Test Loading @@ -298,8 +346,10 @@ public class BackgroundActivityStartControllerExemptionTests { int realCallingPid = REGULAR_PID_2; // setup state when(mVisibleActivityProcessTracker.hasVisibleActivity(eq(realCallingUid))).thenReturn( true); when(mVisibleActivityProcessTracker.hasVisibleActivity(eq(realCallingUid))) .thenReturn(true); when(mVisibleActivityProcessTracker.hasVisibleNotPinnedActivity(eq(realCallingUid))) .thenReturn(false); when(mService.getBalAppSwitchesState()).thenReturn(APP_SWITCH_ALLOW); // prepare call Loading @@ -312,6 +362,8 @@ public class BackgroundActivityStartControllerExemptionTests { originatingPendingIntent, allowBalExemptionForSystemProcess, mResultRecord, intent, checkedOptions); assertThat(balState.toString()).contains("realCallingUidHasVisibleActivity: true"); assertThat(balState.toString()) .contains("realCallingUidHasVisibleNotPinnedActivity: false"); assertThat(balState.toString()).contains("realCallingUidHasNonAppVisibleWindow: false"); // call Loading @@ -320,8 +372,48 @@ public class BackgroundActivityStartControllerExemptionTests { balState.setResultForRealCaller(realCallerVerdict); // assertions assertWithMessage(balState.toString()).that(realCallerVerdict.getCode()).isEqualTo( BAL_ALLOW_VISIBLE_WINDOW); assertWithMessage(balState + " -> " + realCallerVerdict) .that(realCallerVerdict.getCode()) .isEqualTo(BAL_BLOCK); } @Test public void testRealCaller_appHasNotPinnedVisibleWindow() { 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(realCallingUid))) .thenReturn(true); when(mVisibleActivityProcessTracker.hasVisibleNotPinnedActivity(eq(realCallingUid))) .thenReturn(true); when(mService.getBalAppSwitchesState()).thenReturn(APP_SWITCH_ALLOW); // prepare call PendingIntentRecord originatingPendingIntent = mPendingIntentRecord; boolean allowBalExemptionForSystemProcess = false; Intent intent = TEST_INTENT; ActivityOptions checkedOptions = mCheckedOptions; BackgroundActivityStartController.BalState balState = mController.new BalState(callingUid, callingPid, callingPackage, realCallingUid, realCallingPid, mCallerApp, originatingPendingIntent, allowBalExemptionForSystemProcess, mResultRecord, intent, checkedOptions); assertThat(balState.toString()).contains("realCallingUidHasVisibleActivity: true"); assertThat(balState.toString()).contains("realCallingUidHasVisibleNotPinnedActivity: true"); assertThat(balState.toString()).contains("realCallingUidHasNonAppVisibleWindow: false"); // call BalVerdict realCallerVerdict = mController.checkBackgroundActivityStartAllowedByRealCaller( balState); balState.setResultForRealCaller(realCallerVerdict); // assertions assertWithMessage(balState + " -> " + realCallerVerdict) .that(realCallerVerdict.getCode()) .isEqualTo(BAL_ALLOW_VISIBLE_WINDOW); } @Test Loading Loading @@ -405,6 +497,8 @@ public class BackgroundActivityStartControllerExemptionTests { // setup state when(mVisibleActivityProcessTracker.hasVisibleActivity(eq(callingUid))).thenReturn(true); when(mVisibleActivityProcessTracker.hasVisibleNotPinnedActivity(eq(callingUid))) .thenReturn(true); when(mService.getBalAppSwitchesState()).thenReturn(APP_SWITCH_ALLOW); // prepare call Loading @@ -419,6 +513,7 @@ public class BackgroundActivityStartControllerExemptionTests { originatingPendingIntent, allowBalExemptionForSystemProcess, mResultRecord, intent, checkedOptions); assertThat(balState.toString()).contains("callingUidHasVisibleActivity: true"); assertThat(balState.toString()).contains("callingUidHasVisibleNotPinnedActivity: true"); assertThat(balState.toString()).contains("callingUidHasNonAppVisibleWindow: false"); // call Loading @@ -441,8 +536,10 @@ public class BackgroundActivityStartControllerExemptionTests { int realCallingPid = REGULAR_PID_2; // setup state when(mVisibleActivityProcessTracker.hasVisibleActivity(eq(realCallingUid))).thenReturn( true); when(mVisibleActivityProcessTracker.hasVisibleActivity(eq(realCallingUid))) .thenReturn(true); when(mVisibleActivityProcessTracker.hasVisibleNotPinnedActivity(eq(realCallingUid))) .thenReturn(true); when(mService.getBalAppSwitchesState()).thenReturn(APP_SWITCH_ALLOW); // prepare call Loading @@ -457,6 +554,7 @@ public class BackgroundActivityStartControllerExemptionTests { originatingPendingIntent, allowBalExemptionForSystemProcess, mResultRecord, intent, checkedOptions); assertThat(balState.toString()).contains("realCallingUidHasVisibleActivity: true"); assertThat(balState.toString()).contains("realCallingUidHasVisibleNotPinnedActivity: true"); assertThat(balState.toString()).contains("realCallingUidHasNonAppVisibleWindow: false"); // call Loading