summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/wm/BackgroundActivityStartController.java116
-rw-r--r--services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java42
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java66
3 files changed, 153 insertions, 71 deletions
diff --git a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
index 2315795a003b..c7e44b347f6b 100644
--- a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
+++ b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
@@ -40,6 +40,7 @@ import android.util.ArraySet;
import android.util.DebugUtils;
import android.util.Slog;
+import com.android.internal.util.FrameworkStatsLog;
import com.android.server.am.PendingIntentRecord;
import java.lang.annotation.Retention;
@@ -169,22 +170,24 @@ public class BackgroundActivityStartController {
if (callingUid == Process.ROOT_UID
|| callingAppId == Process.SYSTEM_UID
|| callingAppId == Process.NFC_UID) {
- return logStartAllowedAndReturnCode(/*background*/ false, callingUid,
- BAL_ALLOW_ALLOWLISTED_UID, "Important callingUid");
+ return logStartAllowedAndReturnCode(BAL_ALLOW_ALLOWLISTED_UID, /*background*/ false,
+ callingUid, realCallingUid, intent, "Important callingUid");
}
// Always allow home application to start activities.
if (isHomeApp(callingUid, callingPackage)) {
- return logStartAllowedAndReturnCode(/*background*/ false, callingUid,
- BAL_ALLOW_ALLOWLISTED_COMPONENT, "Home app");
+ return logStartAllowedAndReturnCode(BAL_ALLOW_ALLOWLISTED_COMPONENT,
+ /*background*/ false, callingUid, realCallingUid, intent,
+ "Home app");
}
// IME should always be allowed to start activity, like IME settings.
final WindowState imeWindow =
mService.mRootWindowContainer.getCurrentInputMethodWindow();
if (imeWindow != null && callingAppId == imeWindow.mOwnerUid) {
- return logStartAllowedAndReturnCode(/*background*/ false, callingUid,
- BAL_ALLOW_ALLOWLISTED_COMPONENT, "Active ime");
+ return logStartAllowedAndReturnCode(BAL_ALLOW_ALLOWLISTED_COMPONENT,
+ /*background*/ false, callingUid, realCallingUid, intent,
+ "Active ime");
}
}
@@ -211,8 +214,8 @@ public class BackgroundActivityStartController {
&& callingUidHasAnyVisibleWindow)
|| isCallingUidPersistentSystemProcess;
if (useCallingUidState && allowCallingUidStartActivity) {
- return logStartAllowedAndReturnCode(/*background*/ false,
- BAL_ALLOW_VISIBLE_WINDOW,
+ return logStartAllowedAndReturnCode(BAL_ALLOW_VISIBLE_WINDOW,
+ /*background*/ false, callingUid, realCallingUid, intent,
"callingUidHasAnyVisibleWindow = "
+ callingUid
+ ", isCallingUidPersistentSystemProcess = "
@@ -247,8 +250,8 @@ public class BackgroundActivityStartController {
Process.getAppUidForSdkSandboxUid(UserHandle.getAppId(realCallingUid));
if (mService.hasActiveVisibleWindow(realCallingSdkSandboxUidToAppUid)) {
- return logStartAllowedAndReturnCode(/*background*/ false, realCallingUid,
- BAL_ALLOW_SDK_SANDBOX,
+ return logStartAllowedAndReturnCode(BAL_ALLOW_SDK_SANDBOX,
+ /*background*/ false, callingUid, realCallingUid, intent,
"uid in SDK sandbox has visible (non-toast) window");
}
}
@@ -267,25 +270,24 @@ public class BackgroundActivityStartController {
-1,
true)
== PackageManager.PERMISSION_GRANTED) {
- return logStartAllowedAndReturnCode(/*background*/ false, callingUid,
- BAL_ALLOW_PENDING_INTENT,
+ return logStartAllowedAndReturnCode(BAL_ALLOW_PENDING_INTENT,
+ /*background*/ false, callingUid, realCallingUid, intent,
"realCallingUid has BAL permission. realCallingUid: " + realCallingUid);
}
// don't abort if the realCallingUid has a visible window
// TODO(b/171459802): We should check appSwitchAllowed also
if (realCallingUidHasAnyVisibleWindow) {
- return logStartAllowedAndReturnCode(/*background*/ false,
- callingUid, BAL_ALLOW_PENDING_INTENT,
+ return logStartAllowedAndReturnCode(BAL_ALLOW_PENDING_INTENT,
+ /*background*/ false, callingUid, realCallingUid, intent,
"realCallingUid has visible (non-toast) window. realCallingUid: "
+ realCallingUid);
}
// if the realCallingUid is a persistent system process, abort if the IntentSender
// wasn't allowed to start an activity
if (isRealCallingUidPersistentSystemProcess && allowBackgroundActivityStart) {
- return logStartAllowedAndReturnCode(/*background*/ false,
- callingUid,
- BAL_ALLOW_PENDING_INTENT,
+ return logStartAllowedAndReturnCode(BAL_ALLOW_PENDING_INTENT,
+ /*background*/ false, callingUid, realCallingUid, intent,
"realCallingUid is persistent system process AND intent "
+ "sender allowed (allowBackgroundActivityStart = true). "
+ "realCallingUid: " + realCallingUid);
@@ -293,8 +295,9 @@ public class BackgroundActivityStartController {
// don't abort if the realCallingUid is an associated companion app
if (mService.isAssociatedCompanionApp(
UserHandle.getUserId(realCallingUid), realCallingUid)) {
- return logStartAllowedAndReturnCode(/*background*/ false, callingUid,
- BAL_ALLOW_PENDING_INTENT, "realCallingUid is a companion app. "
+ return logStartAllowedAndReturnCode(BAL_ALLOW_PENDING_INTENT,
+ /*background*/ false, callingUid, realCallingUid, intent,
+ "realCallingUid is a companion app. "
+ "realCallingUid: " + realCallingUid);
}
}
@@ -302,25 +305,28 @@ public class BackgroundActivityStartController {
// don't abort if the callingUid has START_ACTIVITIES_FROM_BACKGROUND permission
if (ActivityTaskManagerService.checkPermission(START_ACTIVITIES_FROM_BACKGROUND,
callingPid, callingUid) == PERMISSION_GRANTED) {
- return logStartAllowedAndReturnCode(/*background*/ true, callingUid,
- BAL_ALLOW_BAL_PERMISSION,
+ return logStartAllowedAndReturnCode(BAL_ALLOW_BAL_PERMISSION,
+ /*background*/ true, callingUid, realCallingUid, intent,
"START_ACTIVITIES_FROM_BACKGROUND permission granted");
}
// don't abort if the caller has the same uid as the recents component
if (mSupervisor.mRecentTasks.isCallerRecents(callingUid)) {
- return logStartAllowedAndReturnCode(/*background*/ true, callingUid,
- BAL_ALLOW_ALLOWLISTED_COMPONENT, "Recents Component");
+ return logStartAllowedAndReturnCode(BAL_ALLOW_ALLOWLISTED_COMPONENT,
+ /*background*/ true, callingUid, realCallingUid,
+ intent, "Recents Component");
}
// don't abort if the callingUid is the device owner
if (mService.isDeviceOwner(callingUid)) {
- return logStartAllowedAndReturnCode(/*background*/ true, callingUid,
- BAL_ALLOW_ALLOWLISTED_COMPONENT, "Device Owner");
+ return logStartAllowedAndReturnCode(BAL_ALLOW_ALLOWLISTED_COMPONENT,
+ /*background*/ true, callingUid, realCallingUid,
+ intent, "Device Owner");
}
// don't abort if the callingUid has companion device
final int callingUserId = UserHandle.getUserId(callingUid);
if (mService.isAssociatedCompanionApp(callingUserId, callingUid)) {
- return logStartAllowedAndReturnCode(/*background*/ true, callingUid,
- BAL_ALLOW_ALLOWLISTED_COMPONENT, "Companion App");
+ return logStartAllowedAndReturnCode(BAL_ALLOW_ALLOWLISTED_COMPONENT,
+ /*background*/ true, callingUid, realCallingUid,
+ intent, "Companion App");
}
// don't abort if the callingUid has SYSTEM_ALERT_WINDOW permission
if (mService.hasSystemAlertWindowPermission(callingUid, callingPid, callingPackage)) {
@@ -329,8 +335,9 @@ public class BackgroundActivityStartController {
"Background activity start for "
+ callingPackage
+ " allowed because SYSTEM_ALERT_WINDOW permission is granted.");
- return logStartAllowedAndReturnCode(/*background*/ true, callingUid,
- BAL_ALLOW_SAW_PERMISSION, "SYSTEM_ALERT_WINDOW permission is granted");
+ return logStartAllowedAndReturnCode(BAL_ALLOW_SAW_PERMISSION,
+ /*background*/ true, callingUid, realCallingUid,
+ intent, "SYSTEM_ALERT_WINDOW permission is granted");
}
}
// If we don't have callerApp at this point, no caller was provided to startActivity().
@@ -348,7 +355,8 @@ public class BackgroundActivityStartController {
@BalCode int balAllowedForCaller = callerApp
.areBackgroundActivityStartsAllowed(appSwitchState);
if (balAllowedForCaller != BAL_BLOCK) {
- return logStartAllowedAndReturnCode(/*background*/ true, balAllowedForCaller,
+ return logStartAllowedAndReturnCode(balAllowedForCaller,
+ /*background*/ true, callingUid, realCallingUid, intent,
"callerApp process (pid = " + callerApp.getPid()
+ ", uid = " + callerAppUid + ") is allowed");
}
@@ -361,7 +369,8 @@ public class BackgroundActivityStartController {
int balAllowedForUid = proc.areBackgroundActivityStartsAllowed(appSwitchState);
if (proc != callerApp
&& balAllowedForUid != BAL_BLOCK) {
- return logStartAllowedAndReturnCode(/*background*/ true, balAllowedForUid,
+ return logStartAllowedAndReturnCode(balAllowedForUid,
+ /*background*/ true, callingUid, realCallingUid, intent,
"process" + proc.getPid()
+ " from uid " + callerAppUid + " is allowed");
}
@@ -427,31 +436,48 @@ public class BackgroundActivityStartController {
return BAL_BLOCK;
}
- private int logStartAllowedAndReturnCode(boolean background, int callingUid, int code,
- String msg) {
- if (DEBUG_ACTIVITY_STARTS) {
- return logStartAllowedAndReturnCode(background, code,
- msg, "callingUid: " + callingUid);
- }
- return code;
+ static @BalCode int logStartAllowedAndReturnCode(@BalCode int code, boolean background,
+ int callingUid, int realCallingUid, Intent intent, int pid, String msg) {
+ return logStartAllowedAndReturnCode(code, background, callingUid, realCallingUid, intent,
+ DEBUG_ACTIVITY_STARTS ? ("[Process(" + pid + ")]" + msg) : "");
}
- private int logStartAllowedAndReturnCode(boolean background, int code,
- String... msg) {
+ static @BalCode int logStartAllowedAndReturnCode(@BalCode int code, boolean background,
+ int callingUid, int realCallingUid, Intent intent, String msg) {
+ statsLogBalAllowed(code, callingUid, realCallingUid, intent);
if (DEBUG_ACTIVITY_STARTS) {
StringBuilder builder = new StringBuilder();
if (background) {
builder.append("Background ");
}
- builder.append("Activity start allowed: ");
- for (int i = 0; i < msg.length; i++) {
- builder.append(msg[i]);
- builder.append(". ");
- }
+ builder.append("Activity start allowed: " + msg + ". callingUid: " + callingUid + ". ");
builder.append("BAL Code: ");
builder.append(code);
Slog.d(TAG, builder.toString());
}
return code;
}
+
+ private static void statsLogBalAllowed(
+ @BalCode int code, int callingUid, int realCallingUid, Intent intent) {
+ if (code == BAL_ALLOW_PENDING_INTENT
+ && (callingUid == Process.SYSTEM_UID || realCallingUid == Process.SYSTEM_UID)) {
+ String activityName =
+ intent != null ? intent.getComponent().flattenToShortString() : "";
+ FrameworkStatsLog.write(FrameworkStatsLog.BAL_ALLOWED,
+ activityName,
+ code,
+ callingUid,
+ realCallingUid);
+ }
+ if (code == BAL_ALLOW_BAL_PERMISSION || code == BAL_ALLOW_FOREGROUND
+ || code == BAL_ALLOW_SAW_PERMISSION) {
+ // We don't need to know which activity in this case.
+ FrameworkStatsLog.write(FrameworkStatsLog.BAL_ALLOWED,
+ /*activityName*/ "",
+ code,
+ callingUid,
+ realCallingUid);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java b/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java
index 020e9c582ebe..cc47528f9950 100644
--- a/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java
+++ b/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java
@@ -93,12 +93,10 @@ class BackgroundLaunchProcessController {
// let app to be able to start background activity even it's in grace period.
if (lastActivityLaunchTime > lastStopAppSwitchesTime
|| lastActivityFinishTime > lastStopAppSwitchesTime) {
- if (DEBUG_ACTIVITY_STARTS) {
- Slog.d(TAG, "[Process(" + pid
- + ")] Activity start allowed: within "
- + ACTIVITY_BG_START_GRACE_PERIOD_MS + "ms grace period");
- }
- return BAL_ALLOW_GRACE_PERIOD;
+ return BackgroundActivityStartController.logStartAllowedAndReturnCode(
+ BAL_ALLOW_GRACE_PERIOD, /*background*/ true, uid, uid, /*intent*/ null,
+ pid, "Activity start allowed: within "
+ + ACTIVITY_BG_START_GRACE_PERIOD_MS + "ms grace period");
}
if (DEBUG_ACTIVITY_STARTS) {
Slog.d(TAG, "[Process(" + pid + ")] Activity start within "
@@ -110,37 +108,29 @@ class BackgroundLaunchProcessController {
}
// Allow if the proc is instrumenting with background activity starts privs.
if (hasBackgroundActivityStartPrivileges) {
- if (DEBUG_ACTIVITY_STARTS) {
- Slog.d(TAG, "[Process(" + pid
- + ")] Activity start allowed: process instrumenting with background "
+ return BackgroundActivityStartController.logStartAllowedAndReturnCode(
+ BAL_ALLOW_BAL_PERMISSION, /*background*/ true, uid, uid, /*intent*/ null,
+ pid, "Activity start allowed: process instrumenting with background "
+ "activity starts privileges");
- }
- return BAL_ALLOW_BAL_PERMISSION;
}
// Allow if the caller has an activity in any foreground task.
if (hasActivityInVisibleTask
&& (appSwitchState == APP_SWITCH_ALLOW || appSwitchState == APP_SWITCH_FG_ONLY)) {
- if (DEBUG_ACTIVITY_STARTS) {
- Slog.d(TAG, "[Process(" + pid
- + ")] Activity start allowed: process has activity in foreground task");
- }
- return BAL_ALLOW_FOREGROUND;
+ return BackgroundActivityStartController.logStartAllowedAndReturnCode(
+ BAL_ALLOW_FOREGROUND, /*background*/ false, uid, uid, /*intent*/ null,
+ pid, "Activity start allowed: process has activity in foreground task");
}
// Allow if the caller is bound by a UID that's currently foreground.
if (isBoundByForegroundUid()) {
- if (DEBUG_ACTIVITY_STARTS) {
- Slog.d(TAG, "[Process(" + pid
- + ")] Activity start allowed: process bound by foreground uid");
- }
- return BAL_ALLOW_FOREGROUND;
+ return BackgroundActivityStartController.logStartAllowedAndReturnCode(
+ BAL_ALLOW_FOREGROUND, /*background*/ false, uid, uid, /*intent*/ null,
+ pid, "Activity start allowed: process bound by foreground uid");
}
// Allow if the flag was explicitly set.
if (isBackgroundStartAllowedByToken(uid, packageName, isCheckingForFgsStart)) {
- if (DEBUG_ACTIVITY_STARTS) {
- Slog.d(TAG, "[Process(" + pid
- + ")] Activity start allowed: process allowed by token");
- }
- return BAL_ALLOW_BAL_PERMISSION;
+ return BackgroundActivityStartController.logStartAllowedAndReturnCode(
+ BAL_ALLOW_BAL_PERMISSION, /*background*/ true, uid, uid, /*intent*/ null,
+ pid, "Activity start allowed: process allowed by token");
}
return BAL_BLOCK;
}
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 1d859bf0198a..0a6cb37a7fa9 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -16,7 +16,9 @@
package com.android.server.wm;
+import static android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND;
import static android.app.Activity.RESULT_CANCELED;
+import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP;
import static android.app.ActivityManager.PROCESS_STATE_TOP;
import static android.app.ActivityManager.START_ABORTED;
import static android.app.ActivityManager.START_CANCELED;
@@ -42,6 +44,7 @@ import static android.content.pm.ActivityInfo.FLAG_ALLOW_UNTRUSTED_ACTIVITY_EMBE
import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.Process.SYSTEM_UID;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.clearInvocations;
@@ -49,6 +52,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
@@ -73,6 +77,7 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyObject;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.notNull;
@@ -103,6 +108,8 @@ import android.window.TaskFragmentOrganizerToken;
import androidx.test.filters.SmallTest;
+import com.android.internal.util.FrameworkStatsLog;
+import com.android.server.am.PendingIntentRecord;
import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.wm.LaunchParamsController.LaunchParamsModifier;
import com.android.server.wm.utils.MockTracker;
@@ -110,6 +117,8 @@ import com.android.server.wm.utils.MockTracker;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
import java.util.Arrays;
import java.util.HashSet;
@@ -729,6 +738,63 @@ public class ActivityStarterTests extends WindowTestsBase {
isCallingUidDeviceOwner, false /* isPinnedSingleInstance */);
}
+ /**
+ * This test ensures proper logging for BAL_ALLOW_PERMISSION.
+ */
+ @Test
+ public void testBackgroundActivityStartsAllowed_logging() {
+ doReturn(false).when(mAtm).isBackgroundActivityStartsEnabled();
+ MockitoSession mockingSession = mockitoSession()
+ .mockStatic(ActivityTaskManagerService.class)
+ .mockStatic(FrameworkStatsLog.class)
+ .strictness(Strictness.LENIENT)
+ .startMocking();
+ doReturn(PERMISSION_GRANTED).when(() -> ActivityTaskManagerService.checkPermission(
+ eq(START_ACTIVITIES_FROM_BACKGROUND),
+ anyInt(), anyInt()));
+ runAndVerifyBackgroundActivityStartsSubtest(
+ "allowed_notAborted", false,
+ UNIMPORTANT_UID, false, PROCESS_STATE_BOUND_TOP,
+ UNIMPORTANT_UID2, false, PROCESS_STATE_BOUND_TOP,
+ false, true, false, false, false);
+ verify(() -> FrameworkStatsLog.write(FrameworkStatsLog.BAL_ALLOWED,
+ "", // activity name
+ BackgroundActivityStartController.BAL_ALLOW_BAL_PERMISSION,
+ UNIMPORTANT_UID,
+ UNIMPORTANT_UID2));
+ mockingSession.finishMocking();
+ }
+
+ /**
+ * This test ensures proper logging for BAL_ALLOW_PENDING_INTENT.
+ */
+ @Test
+ public void testBackgroundActivityStartsAllowed_loggingPendingIntentAllowed() {
+ doReturn(false).when(mAtm).isBackgroundActivityStartsEnabled();
+ MockitoSession mockingSession = mockitoSession()
+ .mockStatic(ActivityTaskManagerService.class)
+ .mockStatic(FrameworkStatsLog.class)
+ .mockStatic(PendingIntentRecord.class)
+ .strictness(Strictness.LENIENT)
+ .startMocking();
+ doReturn(PERMISSION_GRANTED).when(() -> ActivityTaskManagerService.checkPermission(
+ eq(START_ACTIVITIES_FROM_BACKGROUND),
+ anyInt(), anyInt()));
+ doReturn(true).when(
+ () -> PendingIntentRecord.isPendingIntentBalAllowedByCaller(anyObject()));
+ runAndVerifyBackgroundActivityStartsSubtest(
+ "allowed_notAborted", false,
+ UNIMPORTANT_UID, false, PROCESS_STATE_BOUND_TOP,
+ Process.SYSTEM_UID, true, PROCESS_STATE_BOUND_TOP,
+ false, true, false, false, false);
+ verify(() -> FrameworkStatsLog.write(FrameworkStatsLog.BAL_ALLOWED,
+ DEFAULT_COMPONENT_PACKAGE_NAME + "/" + DEFAULT_COMPONENT_PACKAGE_NAME,
+ BackgroundActivityStartController.BAL_ALLOW_PENDING_INTENT,
+ UNIMPORTANT_UID,
+ Process.SYSTEM_UID));
+ mockingSession.finishMocking();
+ }
+
private void runAndVerifyBackgroundActivityStartsSubtest(String name, boolean shouldHaveAborted,
int callingUid, boolean callingUidHasVisibleWindow, int callingUidProcState,
int realCallingUid, boolean realCallingUidHasVisibleWindow, int realCallingUidProcState,