summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Achim Thesmann <achim@google.com> 2024-09-03 07:06:19 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2024-09-03 07:06:19 +0000
commitc53e36a6757852197e600c97070cfabc18615770 (patch)
treece416404780f2f09bdff63efb849b52b4001e0db
parent3131d5db97cc635f2c2dfabeb5017b888ae9d56d (diff)
parent35fe27825cb36ad48a19bf174f68f4ff5e5b9e55 (diff)
Merge changes I36f5f7cd,Idb69119a,I5740fea0 into main
* changes: Implement ALLOW_IF_VISIBLE opt-in Split checks for visibility and other exemptions Introduce BAL Configuration object
-rw-r--r--services/core/java/com/android/server/wm/BackgroundActivityStartController.java113
-rw-r--r--services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java43
-rw-r--r--services/core/java/com/android/server/wm/WindowProcessController.java14
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/BackgroundActivityStartControllerExemptionTests.java142
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/BackgroundActivityStartControllerTests.java13
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/BackgroundLaunchProcessControllerTests.java28
6 files changed, 279 insertions, 74 deletions
diff --git a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
index a5cea34bf79d..2259b5a5b08c 100644
--- a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
+++ b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
@@ -21,10 +21,10 @@ import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
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;
+import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOW_IF_VISIBLE;
import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_COMPAT;
import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_DENIED;
import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED;
-import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOW_IF_VISIBLE;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE;
@@ -39,13 +39,15 @@ import static com.android.server.wm.ActivityStarter.ASM_RESTRICTIONS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ACTIVITY_STARTS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.ActivityTaskManagerService.ACTIVITY_BG_START_GRACE_PERIOD_MS;
import static com.android.server.wm.ActivityTaskManagerService.APP_SWITCH_ALLOW;
import static com.android.server.wm.ActivityTaskManagerService.APP_SWITCH_FG_ONLY;
import static com.android.server.wm.ActivityTaskSupervisor.getApplicationLabel;
import static com.android.server.wm.PendingRemoteAnimationRegistry.TIMEOUT_MS;
+import static com.android.window.flags.Flags.balAdditionalStartModes;
import static com.android.window.flags.Flags.balDontBringExistingBackgroundTaskStackToFg;
-import static com.android.window.flags.Flags.balImprovedMetrics;
import static com.android.window.flags.Flags.balImproveRealCallerVisibilityCheck;
+import static com.android.window.flags.Flags.balImprovedMetrics;
import static com.android.window.flags.Flags.balRequireOptInByPendingIntentCreator;
import static com.android.window.flags.Flags.balRequireOptInSameUid;
import static com.android.window.flags.Flags.balRespectAppSwitchStateWhenCheckBoundByForegroundUid;
@@ -84,6 +86,7 @@ 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.server.wm.BackgroundLaunchProcessController.BalCheckConfiguration;
import java.lang.annotation.Retention;
import java.util.ArrayList;
@@ -107,6 +110,17 @@ public class BackgroundActivityStartController {
private static final int ASM_GRACEPERIOD_MAX_REPEATS = 5;
private static final int NO_PROCESS_UID = -1;
+ private static final BalCheckConfiguration BAL_CHECK_FOREGROUND = new BalCheckConfiguration(
+ /* isCheckingForFgsStarts */ false,
+ /* checkVisibility */ true,
+ /* checkOtherExemptions */ false,
+ ACTIVITY_BG_START_GRACE_PERIOD_MS);
+ private static final BalCheckConfiguration BAL_CHECK_BACKGROUND = new BalCheckConfiguration(
+ /* isCheckingForFgsStarts */ false,
+ /* checkVisibility */ false,
+ /* checkOtherExemptions */ true,
+ ACTIVITY_BG_START_GRACE_PERIOD_MS);
+
static final String AUTO_OPT_IN_NOT_PENDING_INTENT = "notPendingIntent";
static final String AUTO_OPT_IN_CALL_FOR_RESULT = "callForResult";
static final String AUTO_OPT_IN_SAME_UID = "sameUid";
@@ -412,6 +426,8 @@ public class BackgroundActivityStartController {
int callingUid, String callingPackage, ActivityOptions checkedOptions) {
switch (checkedOptions.getPendingIntentCreatorBackgroundActivityStartMode()) {
case MODE_BACKGROUND_ACTIVITY_START_ALLOWED:
+ case MODE_BACKGROUND_ACTIVITY_START_ALLOW_IF_VISIBLE:
+ case MODE_BACKGROUND_ACTIVITY_START_ALLOW_ALWAYS:
return BackgroundStartPrivileges.ALLOW_BAL;
case MODE_BACKGROUND_ACTIVITY_START_DENIED:
return BackgroundStartPrivileges.NONE;
@@ -752,7 +768,7 @@ public class BackgroundActivityStartController {
// PendingIntents is null).
BalVerdict resultForRealCaller = state.callerIsRealCaller() && resultForCaller.allows()
? resultForCaller
- : checkBackgroundActivityStartAllowedBySender(state)
+ : checkBackgroundActivityStartAllowedByRealCaller(state)
.setBasedOnRealCaller();
state.setResultForRealCaller(resultForRealCaller);
@@ -827,6 +843,37 @@ public class BackgroundActivityStartController {
* or {@link #BAL_BLOCK} if the launch should be blocked
*/
BalVerdict checkBackgroundActivityStartAllowedByCaller(BalState state) {
+ if (state.isPendingIntent()) {
+ // PendingIntents should mostly be allowed by the sender (real caller) or a permission
+ // the creator of the PendingIntent has. Visibility should be the exceptional case, so
+ // test it last (this does not change the result, just the bal code).
+ BalVerdict result = BalVerdict.BLOCK;
+ if (!(balAdditionalStartModes()
+ && state.mCheckedOptions.getPendingIntentCreatorBackgroundActivityStartMode()
+ == MODE_BACKGROUND_ACTIVITY_START_ALLOW_IF_VISIBLE)) {
+ result = checkBackgroundActivityStartAllowedByCallerInBackground(state);
+ }
+ if (result == BalVerdict.BLOCK) {
+ result = checkBackgroundActivityStartAllowedByCallerInForeground(state);
+
+ }
+ return result;
+ } else {
+ BalVerdict result = checkBackgroundActivityStartAllowedByCallerInForeground(state);
+ if (result == BalVerdict.BLOCK && !(balAdditionalStartModes()
+ && state.mCheckedOptions.getPendingIntentCreatorBackgroundActivityStartMode()
+ == MODE_BACKGROUND_ACTIVITY_START_ALLOW_IF_VISIBLE)) {
+ result = checkBackgroundActivityStartAllowedByCallerInBackground(state);
+ }
+ 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 checkBackgroundActivityStartAllowedByCallerInForeground(BalState state) {
// This is used to block background activity launch even if the app is still
// visible to user after user clicking home button.
@@ -842,7 +889,16 @@ public class BackgroundActivityStartController {
return new BalVerdict(BAL_ALLOW_NON_APP_VISIBLE_WINDOW,
/*background*/ false, "callingUid has non-app visible window");
}
+ // 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 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) {
// don't abort for the most important UIDs
final int callingAppId = UserHandle.getAppId(state.mCallingUid);
if (state.mCallingUid == Process.ROOT_UID
@@ -922,25 +978,29 @@ public class BackgroundActivityStartController {
"OP_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION appop is granted");
}
- // If we don't have callerApp at this point, no caller was provided to startActivity().
- // That's the case for PendingIntent-based starts, since the creator's process might not be
- // up and alive.
// Don't abort if the callerApp or other processes of that uid are allowed in any way.
- BalVerdict callerAppAllowsBal = checkProcessAllowsBal(state.mCallerApp, state);
- if (callerAppAllowsBal.allows()) {
- return callerAppAllowsBal;
- }
-
- // If we are here, it means all exemptions based on the creator failed
- return BalVerdict.BLOCK;
+ return 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 checkBackgroundActivityStartAllowedBySender(BalState state) {
+ BalVerdict checkBackgroundActivityStartAllowedByRealCaller(BalState state) {
+ BalVerdict result = checkBackgroundActivityStartAllowedByRealCallerInForeground(state);
+ if (result == BalVerdict.BLOCK && !(balAdditionalStartModes()
+ && state.mCheckedOptions.getPendingIntentBackgroundActivityStartMode()
+ == MODE_BACKGROUND_ACTIVITY_START_ALLOW_IF_VISIBLE)) {
+ result = checkBackgroundActivityStartAllowedByRealCallerInBackground(state);
+ }
+ 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) {
// 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.
@@ -966,6 +1026,16 @@ public class BackgroundActivityStartController {
}
}
+ // 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) {
if (state.mCheckedOptions.getPendingIntentBackgroundActivityStartMode()
== MODE_BACKGROUND_ACTIVITY_START_ALLOW_ALWAYS
&& hasBalPermission(state.mRealCallingUid, state.mRealCallingPid)) {
@@ -992,14 +1062,7 @@ public class BackgroundActivityStartController {
}
// don't abort if the callerApp or other processes of that uid are allowed in any way
- BalVerdict realCallerAppAllowsBal =
- checkProcessAllowsBal(state.mRealCallerApp, state);
- if (realCallerAppAllowsBal.allows()) {
- return realCallerAppAllowsBal;
- }
-
- // If we are here, it means all exemptions based on PI sender failed
- return BalVerdict.BLOCK;
+ return checkProcessAllowsBal(state.mRealCallerApp, state, BAL_CHECK_BACKGROUND);
}
@VisibleForTesting boolean hasBalPermission(int uid, int pid) {
@@ -1015,13 +1078,13 @@ public class BackgroundActivityStartController {
* exceptions.
*/
@VisibleForTesting BalVerdict checkProcessAllowsBal(WindowProcessController app,
- BalState state) {
+ BalState state, BalCheckConfiguration balCheckConfiguration) {
if (app == null) {
return BalVerdict.BLOCK;
}
// first check the original calling process
final BalVerdict balAllowedForCaller = app
- .areBackgroundActivityStartsAllowed(state.mAppSwitchState);
+ .areBackgroundActivityStartsAllowed(state.mAppSwitchState, balCheckConfiguration);
if (balAllowedForCaller.allows()) {
return balAllowedForCaller.withProcessInfo("callerApp process", app);
} else {
@@ -1033,7 +1096,7 @@ public class BackgroundActivityStartController {
final WindowProcessController proc = uidProcesses.valueAt(i);
if (proc != app) {
BalVerdict balAllowedForUid = proc.areBackgroundActivityStartsAllowed(
- state.mAppSwitchState);
+ state.mAppSwitchState, balCheckConfiguration);
if (balAllowedForUid.allows()) {
return balAllowedForUid.withProcessInfo("process", proc);
}
diff --git a/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java b/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java
index 5f5365dca1e9..1073713cca52 100644
--- a/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java
+++ b/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java
@@ -98,42 +98,63 @@ class BackgroundLaunchProcessController {
mBackgroundActivityStartCallback = callback;
}
+ record BalCheckConfiguration(
+ boolean isCheckingForFgsStart,
+ boolean checkVisibility,
+ boolean checkOtherExemptions,
+ long gracePeriod
+ ) {
+ }
+
+ /**
+ * Check configuration for foreground service starts.
+ *
+ * The check executes all parts of the BAL checks and uses the same grace period,
+ * so FGS is allowed whenever BAL is allowed.
+ */
+ static final BalCheckConfiguration CHECK_FOR_FGS_START = new BalCheckConfiguration(
+ /* isCheckingForFgsStarts */ true,
+ /* checkVisibility */ true,
+ /* checkOtherExemptions */ true,
+ ACTIVITY_BG_START_GRACE_PERIOD_MS);
+
BalVerdict areBackgroundActivityStartsAllowed(
int pid, int uid, String packageName,
- int appSwitchState, boolean isCheckingForFgsStart,
+ int appSwitchState, BalCheckConfiguration checkConfiguration,
boolean hasActivityInVisibleTask, boolean hasBackgroundActivityStartPrivileges,
long lastStopAppSwitchesTime, long lastActivityLaunchTime,
long lastActivityFinishTime) {
// Allow if the proc is instrumenting with background activity starts privs.
- if (hasBackgroundActivityStartPrivileges) {
+ if (checkConfiguration.checkOtherExemptions && hasBackgroundActivityStartPrivileges) {
return new BalVerdict(BAL_ALLOW_PERMISSION, /*background*/ true,
"process instrumenting with background activity starts privileges");
}
// Allow if the flag was explicitly set.
- if (isBackgroundStartAllowedByToken(uid, packageName, isCheckingForFgsStart)) {
+ if (checkConfiguration.checkOtherExemptions && isBackgroundStartAllowedByToken(uid,
+ packageName, checkConfiguration.isCheckingForFgsStart)) {
return new BalVerdict(balImprovedMetrics() ? BAL_ALLOW_TOKEN : BAL_ALLOW_PERMISSION,
/*background*/ true, "process allowed by token");
}
// Allow if the caller is bound by a UID that's currently foreground.
// But still respect the appSwitchState.
- boolean allowBoundByForegroundUid =
+ if (checkConfiguration.checkVisibility && (
Flags.balRespectAppSwitchStateWhenCheckBoundByForegroundUid()
- ? appSwitchState != APP_SWITCH_DISALLOW && isBoundByForegroundUid()
- : isBoundByForegroundUid();
- if (allowBoundByForegroundUid) {
+ ? appSwitchState != APP_SWITCH_DISALLOW && isBoundByForegroundUid()
+ : isBoundByForegroundUid())) {
return new BalVerdict(balImprovedMetrics() ? BAL_ALLOW_BOUND_BY_FOREGROUND
: BAL_ALLOW_VISIBLE_WINDOW, /*background*/ false,
"process bound by foreground uid");
}
// Allow if the caller has an activity in any foreground task.
- if (hasActivityInVisibleTask && appSwitchState != APP_SWITCH_DISALLOW) {
+ if (checkConfiguration.checkVisibility && hasActivityInVisibleTask
+ && appSwitchState != APP_SWITCH_DISALLOW) {
return new BalVerdict(BAL_ALLOW_FOREGROUND, /*background*/ false,
"process has activity in foreground task");
}
// If app switching is not allowed, we ignore all the start activity grace period
// exception so apps cannot start itself in onPause() after pressing home button.
- if (appSwitchState == APP_SWITCH_ALLOW) {
+ if (checkConfiguration.checkOtherExemptions && appSwitchState == APP_SWITCH_ALLOW) {
// Allow if any activity in the caller has either started or finished very recently, and
// it must be started or finished after last stop app switches time.
if (lastActivityLaunchTime > lastStopAppSwitchesTime
@@ -141,9 +162,9 @@ class BackgroundLaunchProcessController {
final long now = SystemClock.uptimeMillis();
long timeSinceLastStartOrFinish = now - Math.max(lastActivityLaunchTime,
lastActivityFinishTime);
- if (timeSinceLastStartOrFinish < ACTIVITY_BG_START_GRACE_PERIOD_MS) {
+ if (timeSinceLastStartOrFinish < checkConfiguration.gracePeriod) {
return new BalVerdict(BAL_ALLOW_GRACE_PERIOD, /*background*/ true,
- "within " + ACTIVITY_BG_START_GRACE_PERIOD_MS + "ms grace period ("
+ "within " + checkConfiguration.gracePeriod + "ms grace period ("
+ timeSinceLastStartOrFinish + "ms)");
}
}
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index d96ebc6655ac..b6b36c716a53 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -89,6 +89,7 @@ import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.Watchdog;
import com.android.server.grammaticalinflection.GrammaticalInflectionManagerInternal;
import com.android.server.wm.ActivityTaskManagerService.HotPath;
+import com.android.server.wm.BackgroundLaunchProcessController.BalCheckConfiguration;
import java.io.IOException;
import java.io.PrintWriter;
@@ -695,20 +696,13 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
public boolean areBackgroundFgsStartsAllowed() {
return areBackgroundActivityStartsAllowed(
mAtm.getBalAppSwitchesState(),
- true /* isCheckingForFgsStart */).allows();
+ BackgroundLaunchProcessController.CHECK_FOR_FGS_START).allows();
}
BackgroundActivityStartController.BalVerdict areBackgroundActivityStartsAllowed(
- int appSwitchState) {
- return areBackgroundActivityStartsAllowed(
- appSwitchState,
- false /* isCheckingForFgsStart */);
- }
-
- private BackgroundActivityStartController.BalVerdict areBackgroundActivityStartsAllowed(
- int appSwitchState, boolean isCheckingForFgsStart) {
+ int appSwitchState, BalCheckConfiguration checkConfiguration) {
return mBgLaunchController.areBackgroundActivityStartsAllowed(mPid, mUid,
- mInfo.packageName, appSwitchState, isCheckingForFgsStart,
+ mInfo.packageName, appSwitchState, checkConfiguration,
hasActivityInVisibleTask(), mInstrumentingWithBackgroundActivityStartPrivileges,
mAtm.getLastStopAppSwitchesTime(),
mLastActivityLaunchTime, mLastActivityFinishTime);
diff --git a/services/tests/wmtests/src/com/android/server/wm/BackgroundActivityStartControllerExemptionTests.java b/services/tests/wmtests/src/com/android/server/wm/BackgroundActivityStartControllerExemptionTests.java
index 6e488188eb87..3910904337b2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/BackgroundActivityStartControllerExemptionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/BackgroundActivityStartControllerExemptionTests.java
@@ -18,6 +18,7 @@ package com.android.server.wm;
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 com.android.server.wm.ActivityTaskManagerService.APP_SWITCH_ALLOW;
import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_ALLOWLISTED_COMPONENT;
@@ -25,9 +26,11 @@ import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_
import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_PERMISSION;
import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_SAW_PERMISSION;
import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_VISIBLE_WINDOW;
+import static com.android.server.wm.BackgroundActivityStartController.BAL_BLOCK;
import static com.google.common.truth.Truth.assertWithMessage;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
@@ -43,6 +46,9 @@ import android.content.Intent;
import android.content.pm.PackageManagerInternal;
import android.os.UserHandle;
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.provider.DeviceConfig;
import android.util.Pair;
@@ -52,6 +58,7 @@ import com.android.compatibility.common.util.DeviceConfigStateHelper;
import com.android.modules.utils.testing.ExtendedMockitoRule;
import com.android.server.am.PendingIntentRecord;
import com.android.server.wm.BackgroundActivityStartController.BalVerdict;
+import com.android.window.flags.Flags;
import org.junit.After;
import org.junit.Before;
@@ -95,7 +102,9 @@ public class BackgroundActivityStartControllerExemptionTests {
@Rule
public final ExtendedMockitoRule extendedMockitoRule =
new ExtendedMockitoRule.Builder(this).setStrictness(Strictness.LENIENT).build();
-
+ @Rule
+ public final CheckFlagsRule mCheckFlagsRule =
+ DeviceFlagsValueProvider.createCheckFlagsRule();
TestableBackgroundActivityStartController mController;
@Mock
ActivityMetricsLogger mActivityMetricsLogger;
@@ -186,7 +195,7 @@ public class BackgroundActivityStartControllerExemptionTests {
when(mAppOpsManager.checkOpNoThrow(
eq(AppOpsManager.OP_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION),
anyInt(), anyString())).thenReturn(AppOpsManager.MODE_DEFAULT);
- when(mCallerApp.areBackgroundActivityStartsAllowed(anyInt())).thenReturn(
+ when(mCallerApp.areBackgroundActivityStartsAllowed(anyInt(), any())).thenReturn(
BalVerdict.BLOCK);
}
@@ -227,7 +236,7 @@ public class BackgroundActivityStartControllerExemptionTests {
// call
BalVerdict callerVerdict = mController.checkBackgroundActivityStartAllowedByCaller(
balState);
- BalVerdict realCallerVerdict = mController.checkBackgroundActivityStartAllowedBySender(
+ BalVerdict realCallerVerdict = mController.checkBackgroundActivityStartAllowedByRealCaller(
balState);
balState.setResultForCaller(callerVerdict);
@@ -295,7 +304,77 @@ public class BackgroundActivityStartControllerExemptionTests {
checkedOptions);
// call
- BalVerdict realCallerVerdict = mController.checkBackgroundActivityStartAllowedBySender(
+ BalVerdict realCallerVerdict = mController.checkBackgroundActivityStartAllowedByRealCaller(
+ balState);
+ balState.setResultForRealCaller(realCallerVerdict);
+
+ // assertions
+ assertWithMessage(balState.toString()).that(realCallerVerdict.getCode()).isEqualTo(
+ BAL_ALLOW_VISIBLE_WINDOW);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_BAL_ADDITIONAL_START_MODES)
+ public void testCaller_appHasVisibleWindowWithIfVisibleOptIn() {
+ 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(mService.hasActiveVisibleWindow(eq(callingUid))).thenReturn(true);
+ when(mService.getBalAppSwitchesState()).thenReturn(APP_SWITCH_ALLOW);
+
+ // prepare call
+ PendingIntentRecord originatingPendingIntent = mPendingIntentRecord;
+ BackgroundStartPrivileges forcedBalByPiSender = BackgroundStartPrivileges.NONE;
+ Intent intent = TEST_INTENT;
+ ActivityOptions checkedOptions = mCheckedOptions
+ .setPendingIntentCreatorBackgroundActivityStartMode(
+ MODE_BACKGROUND_ACTIVITY_START_ALLOW_IF_VISIBLE);
+ BackgroundActivityStartController.BalState balState = mController.new BalState(callingUid,
+ callingPid, callingPackage, realCallingUid, realCallingPid, mCallerApp,
+ originatingPendingIntent, forcedBalByPiSender, mResultRecord, intent,
+ checkedOptions);
+
+ // call
+ BalVerdict callerVerdict = mController.checkBackgroundActivityStartAllowedByCaller(
+ balState);
+ balState.setResultForCaller(callerVerdict);
+
+ // assertions
+ assertWithMessage(balState.toString()).that(callerVerdict.getCode()).isEqualTo(
+ BAL_ALLOW_VISIBLE_WINDOW);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_BAL_ADDITIONAL_START_MODES)
+ public void testRealCaller_appHasVisibleWindowWithIfVisibleOptIn() {
+ 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(mService.hasActiveVisibleWindow(eq(realCallingUid))).thenReturn(true);
+ when(mService.getBalAppSwitchesState()).thenReturn(APP_SWITCH_ALLOW);
+
+ // prepare call
+ PendingIntentRecord originatingPendingIntent = mPendingIntentRecord;
+ BackgroundStartPrivileges forcedBalByPiSender = BackgroundStartPrivileges.NONE;
+ Intent intent = TEST_INTENT;
+ ActivityOptions checkedOptions = mCheckedOptions
+ .setPendingIntentCreatorBackgroundActivityStartMode(
+ MODE_BACKGROUND_ACTIVITY_START_ALLOW_IF_VISIBLE);
+ BackgroundActivityStartController.BalState balState = mController.new BalState(callingUid,
+ callingPid, callingPackage, realCallingUid, realCallingPid, mCallerApp,
+ originatingPendingIntent, forcedBalByPiSender, mResultRecord, intent,
+ checkedOptions);
+
+ // call
+ BalVerdict realCallerVerdict = mController.checkBackgroundActivityStartAllowedByRealCaller(
balState);
balState.setResultForRealCaller(realCallerVerdict);
@@ -320,7 +399,7 @@ public class BackgroundActivityStartControllerExemptionTests {
int realCallingPid = REGULAR_PID_2;
// setup state
- when(mCallerApp.areBackgroundActivityStartsAllowed(anyInt())).thenReturn(
+ when(mCallerApp.areBackgroundActivityStartsAllowed(anyInt(), any())).thenReturn(
new BalVerdict(BAL_ALLOW_FOREGROUND, false, "allowed"));
when(mService.getBalAppSwitchesState()).thenReturn(APP_SWITCH_ALLOW);
@@ -357,7 +436,7 @@ public class BackgroundActivityStartControllerExemptionTests {
mService.getProcessController(eq(realCallingPid), eq(realCallingUid))).thenReturn(
mCallerApp);
when(mService.getBalAppSwitchesState()).thenReturn(APP_SWITCH_ALLOW);
- when(mCallerApp.areBackgroundActivityStartsAllowed(anyInt())).thenReturn(
+ when(mCallerApp.areBackgroundActivityStartsAllowed(anyInt(), any())).thenReturn(
new BalVerdict(BAL_ALLOW_FOREGROUND, false, "allowed"));
// prepare call
@@ -371,7 +450,7 @@ public class BackgroundActivityStartControllerExemptionTests {
checkedOptions);
// call
- BalVerdict realCallerVerdict = mController.checkBackgroundActivityStartAllowedBySender(
+ BalVerdict realCallerVerdict = mController.checkBackgroundActivityStartAllowedByRealCaller(
balState);
balState.setResultForRealCaller(realCallerVerdict);
@@ -404,9 +483,9 @@ public class BackgroundActivityStartControllerExemptionTests {
mService.getProcessController(eq(realCallingPid), eq(realCallingUid))).thenReturn(
mCallerApp);
when(mService.getBalAppSwitchesState()).thenReturn(APP_SWITCH_ALLOW);
- when(mCallerApp.areBackgroundActivityStartsAllowed(anyInt())).thenReturn(
+ when(mCallerApp.areBackgroundActivityStartsAllowed(anyInt(), any())).thenReturn(
BalVerdict.BLOCK);
- when(otherProcess.areBackgroundActivityStartsAllowed(anyInt())).thenReturn(
+ when(otherProcess.areBackgroundActivityStartsAllowed(anyInt(), any())).thenReturn(
new BalVerdict(BAL_ALLOW_FOREGROUND, false, "allowed"));
// prepare call
@@ -420,7 +499,7 @@ public class BackgroundActivityStartControllerExemptionTests {
checkedOptions);
// call
- BalVerdict realCallerVerdict = mController.checkBackgroundActivityStartAllowedBySender(
+ BalVerdict realCallerVerdict = mController.checkBackgroundActivityStartAllowedByRealCaller(
balState);
balState.setResultForRealCaller(realCallerVerdict);
@@ -456,7 +535,7 @@ public class BackgroundActivityStartControllerExemptionTests {
checkedOptions);
// call
- BalVerdict realCallerVerdict = mController.checkBackgroundActivityStartAllowedBySender(
+ BalVerdict realCallerVerdict = mController.checkBackgroundActivityStartAllowedByRealCaller(
balState);
balState.setResultForRealCaller(realCallerVerdict);
@@ -466,6 +545,45 @@ public class BackgroundActivityStartControllerExemptionTests {
}
@Test
+ @RequiresFlagsEnabled(Flags.FLAG_BAL_ADDITIONAL_START_MODES)
+ public void testRealCaller_isCompanionAppWithOptInIfVisible() {
+ // The app has a service that is bound by a different, visible app. The app bound to the
+ // service must remain visible for the app in the background to start activities
+ // successfully.
+ 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
+ final int realCallingUserId = UserHandle.getUserId(realCallingUid);
+ when(mService.isAssociatedCompanionApp(eq(realCallingUserId),
+ eq(realCallingUid))).thenReturn(true);
+
+ // prepare call
+ PendingIntentRecord originatingPendingIntent = mPendingIntentRecord;
+ BackgroundStartPrivileges forcedBalByPiSender = BackgroundStartPrivileges.NONE;
+ Intent intent = TEST_INTENT;
+ ActivityOptions checkedOptions = mCheckedOptions
+ .setPendingIntentBackgroundActivityStartMode(
+ MODE_BACKGROUND_ACTIVITY_START_ALLOW_IF_VISIBLE);
+ BackgroundActivityStartController.BalState balState = mController.new BalState(callingUid,
+ callingPid, callingPackage, realCallingUid, realCallingPid, null,
+ originatingPendingIntent, forcedBalByPiSender, mResultRecord, intent,
+ checkedOptions);
+
+ // call
+ BalVerdict realCallerVerdict = mController.checkBackgroundActivityStartAllowedByRealCaller(
+ balState);
+ balState.setResultForRealCaller(realCallerVerdict);
+
+ // assertions
+ assertWithMessage(balState.toString()).that(realCallerVerdict.getCode()).isEqualTo(
+ BAL_BLOCK);
+ }
+
+ @Test
public void testCaller_balPermission() {
int callingUid = REGULAR_UID_1;
int callingPid = REGULAR_PID_1;
@@ -523,7 +641,7 @@ public class BackgroundActivityStartControllerExemptionTests {
checkedOptions);
// call
- BalVerdict realCallerVerdict = mController.checkBackgroundActivityStartAllowedBySender(
+ BalVerdict realCallerVerdict = mController.checkBackgroundActivityStartAllowedByRealCaller(
balState);
balState.setResultForRealCaller(realCallerVerdict);
diff --git a/services/tests/wmtests/src/com/android/server/wm/BackgroundActivityStartControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/BackgroundActivityStartControllerTests.java
index e364264fc74f..6ec789599482 100644
--- a/services/tests/wmtests/src/com/android/server/wm/BackgroundActivityStartControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/BackgroundActivityStartControllerTests.java
@@ -24,6 +24,7 @@ import static com.android.window.flags.Flags.balImprovedMetrics;
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
@@ -43,6 +44,7 @@ import androidx.test.filters.SmallTest;
import com.android.compatibility.common.util.DeviceConfigStateHelper;
import com.android.server.am.PendingIntentRecord;
import com.android.server.wm.BackgroundActivityStartController.BalVerdict;
+import com.android.server.wm.BackgroundLaunchProcessController.BalCheckConfiguration;
import org.junit.After;
import org.junit.Before;
@@ -167,9 +169,9 @@ public class BackgroundActivityStartControllerTests {
}
@Override
- BalVerdict checkBackgroundActivityStartAllowedBySender(BalState state) {
+ BalVerdict checkBackgroundActivityStartAllowedByRealCaller(BalState state) {
return mRealCallerVerdict.orElseGet(
- () -> super.checkBackgroundActivityStartAllowedBySender(state));
+ () -> super.checkBackgroundActivityStartAllowedByRealCaller(state));
}
public void setRealCallerVerdict(BalVerdict verdict) {
@@ -177,11 +179,12 @@ public class BackgroundActivityStartControllerTests {
}
@Override
- BalVerdict checkProcessAllowsBal(WindowProcessController app, BalState state) {
+ BalVerdict checkProcessAllowsBal(WindowProcessController app, BalState state,
+ BalCheckConfiguration checkConfiguration) {
if (mProcessVerdicts.containsKey(app)) {
return mProcessVerdicts.get(app);
}
- return super.checkProcessAllowsBal(app, state);
+ return super.checkProcessAllowsBal(app, state, checkConfiguration);
}
}
@@ -209,7 +212,7 @@ public class BackgroundActivityStartControllerTests {
Mockito.when(mAppOpsManager.checkOpNoThrow(
eq(AppOpsManager.OP_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION),
anyInt(), anyString())).thenReturn(AppOpsManager.MODE_DEFAULT);
- Mockito.when(mCallerApp.areBackgroundActivityStartsAllowed(anyInt())).thenReturn(
+ Mockito.when(mCallerApp.areBackgroundActivityStartsAllowed(anyInt(), any())).thenReturn(
BalVerdict.BLOCK);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/BackgroundLaunchProcessControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/BackgroundLaunchProcessControllerTests.java
index c9c7e92d71cd..27e147d98b1f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/BackgroundLaunchProcessControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/BackgroundLaunchProcessControllerTests.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static com.android.server.wm.ActivityTaskManagerService.ACTIVITY_BG_START_GRACE_PERIOD_MS;
import static com.android.server.wm.ActivityTaskManagerService.APP_SWITCH_ALLOW;
import static com.android.server.wm.ActivityTaskManagerService.APP_SWITCH_DISALLOW;
import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_BOUND_BY_FOREGROUND;
@@ -95,7 +96,12 @@ public class BackgroundLaunchProcessControllerTests {
int mUid = 234;
String mPackageName = "package.name";
int mAppSwitchState = APP_SWITCH_DISALLOW;
- boolean mIsCheckingForFgsStart = false;
+ BackgroundLaunchProcessController.BalCheckConfiguration mBalCheckConfiguration =
+ new BackgroundLaunchProcessController.BalCheckConfiguration(
+ /* isCheckingForFgsStarts */ false,
+ /* checkVisibility */ true,
+ /* checkOtherExemptions */ true,
+ ACTIVITY_BG_START_GRACE_PERIOD_MS);
boolean mHasActivityInVisibleTask = false;
boolean mHasBackgroundActivityStartPrivileges = false;
long mLastStopAppSwitchesTime = 0L;
@@ -106,7 +112,7 @@ public class BackgroundLaunchProcessControllerTests {
public void testNothingAllows() {
BalVerdict balVerdict = mController.areBackgroundActivityStartsAllowed(
mPid, mUid, mPackageName,
- mAppSwitchState, mIsCheckingForFgsStart,
+ mAppSwitchState, mBalCheckConfiguration,
mHasActivityInVisibleTask, mHasBackgroundActivityStartPrivileges,
mLastStopAppSwitchesTime, mLastActivityLaunchTime,
mLastActivityFinishTime);
@@ -118,7 +124,7 @@ public class BackgroundLaunchProcessControllerTests {
mHasBackgroundActivityStartPrivileges = true;
BalVerdict balVerdict = mController.areBackgroundActivityStartsAllowed(
mPid, mUid, mPackageName,
- mAppSwitchState, mIsCheckingForFgsStart,
+ mAppSwitchState, mBalCheckConfiguration,
mHasActivityInVisibleTask, mHasBackgroundActivityStartPrivileges,
mLastStopAppSwitchesTime, mLastActivityLaunchTime,
mLastActivityFinishTime);
@@ -136,7 +142,7 @@ public class BackgroundLaunchProcessControllerTests {
BackgroundStartPrivileges.ALLOW_BAL);
BalVerdict balVerdict = mController.areBackgroundActivityStartsAllowed(
mPid, mUid, mPackageName,
- mAppSwitchState, mIsCheckingForFgsStart,
+ mAppSwitchState, mBalCheckConfiguration,
mHasActivityInVisibleTask, mHasBackgroundActivityStartPrivileges,
mLastStopAppSwitchesTime, mLastActivityLaunchTime,
mLastActivityFinishTime);
@@ -154,7 +160,7 @@ public class BackgroundLaunchProcessControllerTests {
BackgroundStartPrivileges.ALLOW_BAL);
BalVerdict balVerdict = mController.areBackgroundActivityStartsAllowed(
mPid, mUid, mPackageName,
- mAppSwitchState, mIsCheckingForFgsStart,
+ mAppSwitchState, mBalCheckConfiguration,
mHasActivityInVisibleTask, mHasBackgroundActivityStartPrivileges,
mLastStopAppSwitchesTime, mLastActivityLaunchTime,
mLastActivityFinishTime);
@@ -170,7 +176,7 @@ public class BackgroundLaunchProcessControllerTests {
BackgroundStartPrivileges.ALLOW_BAL);
BalVerdict balVerdict = mController.areBackgroundActivityStartsAllowed(
mPid, mUid, mPackageName,
- mAppSwitchState, mIsCheckingForFgsStart,
+ mAppSwitchState, mBalCheckConfiguration,
mHasActivityInVisibleTask, mHasBackgroundActivityStartPrivileges,
mLastStopAppSwitchesTime, mLastActivityLaunchTime,
mLastActivityFinishTime);
@@ -186,7 +192,7 @@ public class BackgroundLaunchProcessControllerTests {
BackgroundStartPrivileges.ALLOW_BAL);
BalVerdict balVerdict = mController.areBackgroundActivityStartsAllowed(
mPid, mUid, mPackageName,
- mAppSwitchState, mIsCheckingForFgsStart,
+ mAppSwitchState, mBalCheckConfiguration,
mHasActivityInVisibleTask, mHasBackgroundActivityStartPrivileges,
mLastStopAppSwitchesTime, mLastActivityLaunchTime,
mLastActivityFinishTime);
@@ -201,7 +207,7 @@ public class BackgroundLaunchProcessControllerTests {
mHasActiveVisibleWindow.add(999);
BalVerdict balVerdict = mController.areBackgroundActivityStartsAllowed(
mPid, mUid, mPackageName,
- mAppSwitchState, mIsCheckingForFgsStart,
+ mAppSwitchState, mBalCheckConfiguration,
mHasActivityInVisibleTask, mHasBackgroundActivityStartPrivileges,
mLastStopAppSwitchesTime, mLastActivityLaunchTime,
mLastActivityFinishTime);
@@ -216,7 +222,7 @@ public class BackgroundLaunchProcessControllerTests {
mHasActiveVisibleWindow.add(999);
BalVerdict balVerdict = mController.areBackgroundActivityStartsAllowed(
mPid, mUid, mPackageName,
- mAppSwitchState, mIsCheckingForFgsStart,
+ mAppSwitchState, mBalCheckConfiguration,
mHasActivityInVisibleTask, mHasBackgroundActivityStartPrivileges,
mLastStopAppSwitchesTime, mLastActivityLaunchTime,
mLastActivityFinishTime);
@@ -229,7 +235,7 @@ public class BackgroundLaunchProcessControllerTests {
mHasActivityInVisibleTask = true;
BalVerdict balVerdict = mController.areBackgroundActivityStartsAllowed(
mPid, mUid, mPackageName,
- mAppSwitchState, mIsCheckingForFgsStart,
+ mAppSwitchState, mBalCheckConfiguration,
mHasActivityInVisibleTask, mHasBackgroundActivityStartPrivileges,
mLastStopAppSwitchesTime, mLastActivityLaunchTime,
mLastActivityFinishTime);
@@ -245,7 +251,7 @@ public class BackgroundLaunchProcessControllerTests {
mLastActivityFinishTime = now - 100;
BalVerdict balVerdict = mController.areBackgroundActivityStartsAllowed(
mPid, mUid, mPackageName,
- mAppSwitchState, mIsCheckingForFgsStart,
+ mAppSwitchState, mBalCheckConfiguration,
mHasActivityInVisibleTask, mHasBackgroundActivityStartPrivileges,
mLastStopAppSwitchesTime, mLastActivityLaunchTime,
mLastActivityFinishTime);