From 0324c82d00740e26eef0c6f07df44829d5e8e5fb Mon Sep 17 00:00:00 2001 From: Ilyas Sung Date: Tue, 7 Feb 2023 11:37:27 +0000 Subject: [PATCH] Added Exemption Check for OP_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION Bug: 246330879 Test: atest ActivityManagerServiceTest atest com.android.server.wm.ActivityStarterTests Change-Id: I07e17929ea02218da66f967f15e45326bc564fb5 --- .../android/server/wm/ActivityStarter.java | 4 +- .../wm/BackgroundActivityStartController.java | 27 ++++++- .../wm/BackgroundLaunchProcessController.java | 6 +- .../server/wm/ActivityStarterTests.java | 77 +++++++++++-------- 4 files changed, 74 insertions(+), 40 deletions(-) diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index 9ca20154212dc..ad5ca9598f42f 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -77,9 +77,9 @@ import static com.android.server.wm.ActivityTaskSupervisor.ON_TOP; import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS; import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_ALLOWLISTED_COMPONENT; import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_ALLOWLISTED_UID; -import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_BAL_PERMISSION; import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_DEFAULT; import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_PENDING_INTENT; +import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_PERMISSION; import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_VISIBLE_WINDOW; import static com.android.server.wm.BackgroundActivityStartController.BAL_BLOCK; import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.PHASE_BOUNDS; @@ -1937,7 +1937,7 @@ class ActivityStarter { // BAL exception only allowed for new tasks if (taskToFront) { if (mBalCode == BAL_ALLOW_ALLOWLISTED_COMPONENT - || mBalCode == BAL_ALLOW_BAL_PERMISSION + || mBalCode == BAL_ALLOW_PERMISSION || mBalCode == BAL_ALLOW_PENDING_INTENT) { return true; } diff --git a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java index e1fdeca167daf..f452378e998a0 100644 --- a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java +++ b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java @@ -18,6 +18,7 @@ package com.android.server.wm; import static android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND; import static android.content.pm.PackageManager.PERMISSION_GRANTED; +import static android.provider.DeviceConfig.NAMESPACE_WINDOW_MANAGER; import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ACTIVITY_STARTS; import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM; @@ -31,6 +32,7 @@ import android.annotation.IntDef; import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityOptions; +import android.app.AppOpsManager; import android.app.BackgroundStartPrivileges; import android.app.ComponentOptions; import android.content.ComponentName; @@ -38,6 +40,7 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.os.Process; import android.os.UserHandle; +import android.provider.DeviceConfig; import android.util.ArraySet; import android.util.DebugUtils; import android.util.Slog; @@ -67,7 +70,7 @@ public class BackgroundActivityStartController { BAL_ALLOW_ALLOWLISTED_COMPONENT, BAL_ALLOW_VISIBLE_WINDOW, BAL_ALLOW_PENDING_INTENT, - BAL_ALLOW_BAL_PERMISSION, + BAL_ALLOW_PERMISSION, BAL_ALLOW_SAW_PERMISSION, BAL_ALLOW_GRACE_PERIOD, BAL_ALLOW_FOREGROUND, @@ -96,7 +99,7 @@ public class BackgroundActivityStartController { /** App has START_ACTIVITIES_FROM_BACKGROUND permission or BAL instrumentation privileges * granted to it */ - static final int BAL_ALLOW_BAL_PERMISSION = 6; + static final int BAL_ALLOW_PERMISSION = 6; /** Process has SYSTEM_ALERT_WINDOW permission granted to it */ static final int BAL_ALLOW_SAW_PERMISSION = 7; @@ -310,7 +313,7 @@ public class BackgroundActivityStartController { if (ActivityTaskManagerService.checkPermission(START_ACTIVITIES_FROM_BACKGROUND, callingPid, callingUid) == PERMISSION_GRANTED) { return logStartAllowedAndReturnCode(/*background*/ true, callingUid, - BAL_ALLOW_BAL_PERMISSION, + BAL_ALLOW_PERMISSION, "START_ACTIVITIES_FROM_BACKGROUND permission granted"); } // don't abort if the caller has the same uid as the recents component @@ -339,6 +342,17 @@ public class BackgroundActivityStartController { return logStartAllowedAndReturnCode(/*background*/ true, callingUid, BAL_ALLOW_SAW_PERMISSION, "SYSTEM_ALERT_WINDOW permission is granted"); } + // don't abort if the callingUid and callingPackage have the + // OP_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION appop + if (isSystemExemptFlagEnabled() && mService.getAppOpsManager().checkOpNoThrow( + AppOpsManager.OP_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION, + callingUid, + callingPackage) + == AppOpsManager.MODE_ALLOWED) { + return logStartAllowedAndReturnCode(/*background*/ true, callingUid, + BAL_ALLOW_PERMISSION, + "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 @@ -461,4 +475,11 @@ public class BackgroundActivityStartController { } return code; } + + private static boolean isSystemExemptFlagEnabled() { + return DeviceConfig.getBoolean( + NAMESPACE_WINDOW_MANAGER, + /* name= */ "system_exempt_from_activity_bg_start_restriction_enabled", + /* defaultValue= */ true); + } } diff --git a/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java b/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java index f94fd2bb772f2..9298afcdda3bc 100644 --- a/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java +++ b/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java @@ -23,9 +23,9 @@ import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLAS 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.BackgroundActivityStartController.BAL_ALLOW_BAL_PERMISSION; import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_FOREGROUND; import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_GRACE_PERIOD; +import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_PERMISSION; import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_VISIBLE_WINDOW; import static com.android.server.wm.BackgroundActivityStartController.BAL_BLOCK; @@ -109,7 +109,7 @@ class BackgroundLaunchProcessController { + ")] Activity start allowed: process instrumenting with background " + "activity starts privileges"); } - return BAL_ALLOW_BAL_PERMISSION; + return BAL_ALLOW_PERMISSION; } // Allow if the flag was explicitly set. if (isBackgroundStartAllowedByToken(uid, packageName, isCheckingForFgsStart)) { @@ -117,7 +117,7 @@ class BackgroundLaunchProcessController { Slog.d(TAG, "[Process(" + pid + ")] Activity start allowed: process allowed by token"); } - return BAL_ALLOW_BAL_PERMISSION; + return BAL_ALLOW_PERMISSION; } // Allow if the caller is bound by a UID that's currently foreground. if (isBoundByForegroundUid()) { diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java index eabbc7688a639..7b19e1f4db425 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java @@ -82,6 +82,7 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.notNull; import android.app.ActivityOptions; +import android.app.AppOpsManager; import android.app.BackgroundStartPrivileges; import android.app.IApplicationThread; import android.app.PictureInPictureParams; @@ -160,6 +161,7 @@ public class ActivityStarterTests extends WindowTestsBase { private ActivityStartController mController; private ActivityMetricsLogger mActivityMetricsLogger; private PackageManagerInternal mMockPackageManager; + private AppOpsManager mAppOpsManager; @Before public void setUp() throws Exception { @@ -169,6 +171,10 @@ public class ActivityStarterTests extends WindowTestsBase { doReturn(balController).when(mController).getBackgroundActivityLaunchController(); mActivityMetricsLogger = mock(ActivityMetricsLogger.class); clearInvocations(mActivityMetricsLogger); + mAppOpsManager = mAtm.getAppOpsManager(); + doReturn(AppOpsManager.MODE_DEFAULT).when(mAppOpsManager).checkOpNoThrow( + eq(AppOpsManager.OP_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION), + anyInt(), any()); mDeviceConfig.set(ENABLE_DEFAULT_RESCIND_BAL_PRIVILEGES_FROM_PENDING_INTENT_SENDER, String.valueOf(true)); } @@ -635,7 +641,7 @@ public class ActivityStarterTests extends WindowTestsBase { runAndVerifyBackgroundActivityStartsSubtest("allowed_noStartsAborted", false, UNIMPORTANT_UID, false, PROCESS_STATE_BOUND_TOP, UNIMPORTANT_UID2, false, PROCESS_STATE_BOUND_TOP, - false, false, false, false, false); + false, false, false, false, false, false, false); } /** @@ -649,7 +655,7 @@ public class ActivityStarterTests extends WindowTestsBase { "disallowed_unsupportedUsecase_aborted", true, UNIMPORTANT_UID, false, PROCESS_STATE_BOUND_TOP, UNIMPORTANT_UID2, false, PROCESS_STATE_BOUND_TOP, - false, false, false, false, false); + false, false, false, false, false, false, false); } /** @@ -663,7 +669,7 @@ public class ActivityStarterTests extends WindowTestsBase { "disallowed_callingUidProcessStateTop_aborted", true, UNIMPORTANT_UID, false, PROCESS_STATE_TOP, UNIMPORTANT_UID2, false, PROCESS_STATE_BOUND_TOP, - false, false, false, false, false); + false, false, false, false, false, false, false); } /** @@ -677,7 +683,7 @@ public class ActivityStarterTests extends WindowTestsBase { "disallowed_realCallingUidProcessStateTop_aborted", true, UNIMPORTANT_UID, false, PROCESS_STATE_BOUND_TOP, UNIMPORTANT_UID2, false, PROCESS_STATE_TOP, - false, false, false, false, false); + false, false, false, false, false, false, false); } /** @@ -691,7 +697,7 @@ public class ActivityStarterTests extends WindowTestsBase { "disallowed_hasForegroundActivities_aborted", true, UNIMPORTANT_UID, false, PROCESS_STATE_BOUND_TOP, UNIMPORTANT_UID2, false, PROCESS_STATE_BOUND_TOP, - true, false, false, false, false); + true, false, false, false, false, false, false); } /** @@ -705,7 +711,7 @@ public class ActivityStarterTests extends WindowTestsBase { "disallowed_pinned_singleinstance_aborted", true, UNIMPORTANT_UID, false, PROCESS_STATE_BOUND_TOP, UNIMPORTANT_UID2, false, PROCESS_STATE_BOUND_TOP, - false, false, false, false, false, true); + false, false, false, false, false, true, false); } /** @@ -719,7 +725,7 @@ public class ActivityStarterTests extends WindowTestsBase { runAndVerifyBackgroundActivityStartsSubtest("disallowed_rootUid_notAborted", false, Process.ROOT_UID, false, PROCESS_STATE_BOUND_TOP, UNIMPORTANT_UID2, false, PROCESS_STATE_BOUND_TOP, - false, false, false, false, false); + false, false, false, false, false, false, false); } /** @@ -733,7 +739,7 @@ public class ActivityStarterTests extends WindowTestsBase { runAndVerifyBackgroundActivityStartsSubtest("disallowed_systemUid_notAborted", false, Process.SYSTEM_UID, false, PROCESS_STATE_BOUND_TOP, UNIMPORTANT_UID2, false, PROCESS_STATE_BOUND_TOP, - false, false, false, false, false); + false, false, false, false, false, false, false); } /** @@ -747,7 +753,7 @@ public class ActivityStarterTests extends WindowTestsBase { runAndVerifyBackgroundActivityStartsSubtest("disallowed_nfcUid_notAborted", false, Process.NFC_UID, false, PROCESS_STATE_BOUND_TOP, UNIMPORTANT_UID2, false, PROCESS_STATE_BOUND_TOP, - false, false, false, false, false); + false, false, false, false, false, false, false); } /** @@ -762,7 +768,7 @@ public class ActivityStarterTests extends WindowTestsBase { "disallowed_callingUidHasVisibleWindow_notAborted", false, UNIMPORTANT_UID, true, PROCESS_STATE_BOUND_TOP, UNIMPORTANT_UID2, false, PROCESS_STATE_BOUND_TOP, - false, false, false, false, false); + false, false, false, false, false, false, false); } /** @@ -778,7 +784,7 @@ public class ActivityStarterTests extends WindowTestsBase { "disallowed_realCallingUidHasVisibleWindow_abortedInU", true, UNIMPORTANT_UID, false, PROCESS_STATE_BOUND_TOP, UNIMPORTANT_UID2, true, PROCESS_STATE_BOUND_TOP, - false, false, false, false, false, false); + false, false, false, false, false, false, false); } /** @@ -793,7 +799,7 @@ public class ActivityStarterTests extends WindowTestsBase { "disallowed_callerIsRecents_notAborted", false, UNIMPORTANT_UID, false, PROCESS_STATE_BOUND_TOP, UNIMPORTANT_UID2, false, PROCESS_STATE_BOUND_TOP, - false, true, false, false, false); + false, true, false, false, false, false, false); } /** @@ -808,7 +814,7 @@ public class ActivityStarterTests extends WindowTestsBase { "disallowed_callerIsAllowed_notAborted", false, UNIMPORTANT_UID, false, PROCESS_STATE_BOUND_TOP, UNIMPORTANT_UID2, false, PROCESS_STATE_BOUND_TOP, - false, false, true, false, false); + false, false, true, false, false, false, false); } /** @@ -824,7 +830,7 @@ public class ActivityStarterTests extends WindowTestsBase { false, UNIMPORTANT_UID, false, PROCESS_STATE_BOUND_TOP, UNIMPORTANT_UID2, false, PROCESS_STATE_BOUND_TOP, - false, false, false, true, false); + false, false, false, true, false, false, false); } /** @@ -840,7 +846,22 @@ public class ActivityStarterTests extends WindowTestsBase { "disallowed_callingPackageNameIsDeviceOwner_notAborted", false, UNIMPORTANT_UID, false, PROCESS_STATE_BOUND_TOP, UNIMPORTANT_UID2, false, PROCESS_STATE_BOUND_TOP, - false, false, false, false, true); + false, false, false, false, true, false, false); + } + + /** + * This test ensures that supported usecases aren't aborted when background starts are + * disallowed. Each scenarios tests one condition that makes them supported in isolation. In + * this case the caller has the OP_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION appop. + */ + @Test + public void testBackgroundActivityStartsDisallowed_callerHasSystemExemptAppOpNotAborted() { + doReturn(false).when(mAtm).isBackgroundActivityStartsEnabled(); + runAndVerifyBackgroundActivityStartsSubtest( + "disallowed_callerHasSystemExemptAppOpNotAborted", false, + UNIMPORTANT_UID, false, PROCESS_STATE_BOUND_TOP, + UNIMPORTANT_UID2, false, PROCESS_STATE_BOUND_TOP, + false, false, false, false, false, false, true); } /** @@ -856,22 +877,7 @@ public class ActivityStarterTests extends WindowTestsBase { "disallowed_callingPackageNameIsIme_notAborted", false, CURRENT_IME_UID, false, PROCESS_STATE_BOUND_TOP, UNIMPORTANT_UID2, false, PROCESS_STATE_BOUND_TOP, - false, false, false, false, false); - } - - private void runAndVerifyBackgroundActivityStartsSubtest(String name, boolean shouldHaveAborted, - int callingUid, boolean callingUidHasVisibleWindow, int callingUidProcState, - int realCallingUid, boolean realCallingUidHasVisibleWindow, int realCallingUidProcState, - boolean hasForegroundActivities, boolean callerIsRecents, - boolean callerIsTempAllowed, - boolean callerIsInstrumentingWithBackgroundActivityStartPrivileges, - boolean isCallingUidDeviceOwner) { - runAndVerifyBackgroundActivityStartsSubtest(name, shouldHaveAborted, callingUid, - callingUidHasVisibleWindow, callingUidProcState, realCallingUid, - realCallingUidHasVisibleWindow, realCallingUidProcState, - hasForegroundActivities, callerIsRecents, callerIsTempAllowed, - callerIsInstrumentingWithBackgroundActivityStartPrivileges, - isCallingUidDeviceOwner, false /* isPinnedSingleInstance */); + false, false, false, false, false, false, false); } private void runAndVerifyBackgroundActivityStartsSubtest(String name, boolean shouldHaveAborted, @@ -881,7 +887,8 @@ public class ActivityStarterTests extends WindowTestsBase { boolean callerIsTempAllowed, boolean callerIsInstrumentingWithBackgroundActivityStartPrivileges, boolean isCallingUidDeviceOwner, - boolean isPinnedSingleInstance) { + boolean isPinnedSingleInstance, + boolean hasSystemExemptAppOp) { // window visibility doReturn(callingUidHasVisibleWindow).when(mAtm).hasActiveVisibleWindow(callingUid); doReturn(realCallingUidHasVisibleWindow).when(mAtm).hasActiveVisibleWindow(realCallingUid); @@ -914,6 +921,12 @@ public class ActivityStarterTests extends WindowTestsBase { // callingUid is the device owner doReturn(isCallingUidDeviceOwner).when(mAtm).isDeviceOwner(callingUid); + // caller has OP_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION appop + doReturn(hasSystemExemptAppOp ? AppOpsManager.MODE_ALLOWED + : AppOpsManager.MODE_DEFAULT).when(mAppOpsManager).checkOpNoThrow( + eq(AppOpsManager.OP_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION), + anyInt(), any()); + int launchMode = LAUNCH_MULTIPLE; if (isPinnedSingleInstance) { final ActivityRecord baseActivity =