Merge "Resolve requested deferral policy based on caller." into udc-dev am: 0177c5f293
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/21963748
Change-Id: I406dd89222ec3863b143538f434f9f8b4d3d86bc
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
index 1d93eb3..e38e21f 100644
--- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
+++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
@@ -2625,7 +2625,7 @@
final Bundle mostRecentDeliveryOptions = BroadcastOptions.makeBasic()
.setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT)
- .setDeferUntilActive(true)
+ .setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE)
.toBundle();
mIdleIntent = new Intent(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
index 1151bb7..394be6e 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
@@ -1948,7 +1948,7 @@
| Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
mTimeTickOptions = BroadcastOptions.makeBasic()
.setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT)
- .setDeferUntilActive(true)
+ .setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE)
.toBundle();
mTimeTickTrigger = new IAlarmListener.Stub() {
@Override
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index e9a7f20..d94f4f2 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -194,19 +194,19 @@
private Bundle mBatteryChangedOptions = BroadcastOptions.makeBasic()
.setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT)
- .setDeferUntilActive(true)
+ .setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE)
.toBundle();
/** Used for both connected/disconnected, so match using key */
private Bundle mPowerOptions = BroadcastOptions.makeBasic()
.setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT)
.setDeliveryGroupMatchingKey("android", Intent.ACTION_POWER_CONNECTED)
- .setDeferUntilActive(true)
+ .setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE)
.toBundle();
/** Used for both low/okay, so match using key */
private Bundle mBatteryOptions = BroadcastOptions.makeBasic()
.setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT)
.setDeliveryGroupMatchingKey("android", Intent.ACTION_BATTERY_OKAY)
- .setDeferUntilActive(true)
+ .setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE)
.toBundle();
private MetricsLogger mMetricsLogger;
diff --git a/services/core/java/com/android/server/DropBoxManagerService.java b/services/core/java/com/android/server/DropBoxManagerService.java
index 19e5cb1..a3dc21e 100644
--- a/services/core/java/com/android/server/DropBoxManagerService.java
+++ b/services/core/java/com/android/server/DropBoxManagerService.java
@@ -320,7 +320,7 @@
.setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MERGED)
.setDeliveryGroupMatchingFilter(matchingFilter)
.setDeliveryGroupExtrasMerger(extrasMerger)
- .setDeferUntilActive(true)
+ .setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE)
.toBundle();
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 2a1e860..7550196 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -14507,18 +14507,6 @@
}
}
- // resultTo broadcasts are always infinitely deferrable.
- if ((resultTo != null) && !ordered && mEnableModernQueue) {
- if (brOptions == null) {
- brOptions = BroadcastOptions.makeBasic();
- }
- brOptions.setDeferUntilActive(true);
- }
-
- if (mEnableModernQueue && ordered && brOptions != null && brOptions.isDeferUntilActive()) {
- throw new IllegalArgumentException("Ordered broadcasts can't be deferred until active");
- }
-
// Verify that protected broadcasts are only being sent by system code,
// and that system code is only sending protected broadcasts.
final boolean isProtectedBroadcast;
diff --git a/services/core/java/com/android/server/am/BroadcastConstants.java b/services/core/java/com/android/server/am/BroadcastConstants.java
index 53fcddf..33d4004 100644
--- a/services/core/java/com/android/server/am/BroadcastConstants.java
+++ b/services/core/java/com/android/server/am/BroadcastConstants.java
@@ -236,6 +236,14 @@
private static final int DEFAULT_MAX_HISTORY_SUMMARY_SIZE =
ActivityManager.isLowRamDeviceStatic() ? 256 : 1024;
+ /**
+ * For {@link BroadcastRecord}: Default to treating all broadcasts sent by
+ * the system as be {@link BroadcastOptions#DEFERRAL_POLICY_UNTIL_ACTIVE}.
+ */
+ public boolean CORE_DEFER_UNTIL_ACTIVE = DEFAULT_CORE_DEFER_UNTIL_ACTIVE;
+ private static final String KEY_CORE_DEFER_UNTIL_ACTIVE = "bcast_core_defer_until_active";
+ private static final boolean DEFAULT_CORE_DEFER_UNTIL_ACTIVE = false;
+
// Settings override tracking for this instance
private String mSettingsKey;
private SettingsObserver mSettingsObserver;
@@ -373,7 +381,12 @@
DEFAULT_MAX_HISTORY_COMPLETE_SIZE);
MAX_HISTORY_SUMMARY_SIZE = getDeviceConfigInt(KEY_MAX_HISTORY_SUMMARY_SIZE,
DEFAULT_MAX_HISTORY_SUMMARY_SIZE);
+ CORE_DEFER_UNTIL_ACTIVE = getDeviceConfigBoolean(KEY_CORE_DEFER_UNTIL_ACTIVE,
+ DEFAULT_CORE_DEFER_UNTIL_ACTIVE);
}
+
+ // TODO: migrate BroadcastRecord to accept a BroadcastConstants
+ BroadcastRecord.CORE_DEFER_UNTIL_ACTIVE = CORE_DEFER_UNTIL_ACTIVE;
}
/**
@@ -418,6 +431,8 @@
MAX_CONSECUTIVE_URGENT_DISPATCHES).println();
pw.print(KEY_MAX_CONSECUTIVE_NORMAL_DISPATCHES,
MAX_CONSECUTIVE_NORMAL_DISPATCHES).println();
+ pw.print(KEY_CORE_DEFER_UNTIL_ACTIVE,
+ CORE_DEFER_UNTIL_ACTIVE).println();
pw.decreaseIndent();
pw.println();
}
diff --git a/services/core/java/com/android/server/am/BroadcastRecord.java b/services/core/java/com/android/server/am/BroadcastRecord.java
index 59f33dd..6bd3c79 100644
--- a/services/core/java/com/android/server/am/BroadcastRecord.java
+++ b/services/core/java/com/android/server/am/BroadcastRecord.java
@@ -90,6 +90,7 @@
final boolean prioritized; // contains more than one priority tranche
final boolean deferUntilActive; // infinitely deferrable broadcast
final boolean shareIdentity; // whether the broadcaster's identity should be shared
+ final boolean urgent; // has been classified as "urgent"
final int userId; // user id this broadcast was for
final @Nullable String resolvedType; // the resolved data type
final @Nullable String[] requiredPermissions; // permissions the caller has required
@@ -146,6 +147,13 @@
private @Nullable String mCachedToString;
private @Nullable String mCachedToShortString;
+ /**
+ * When enabled, assume that {@link UserHandle#isCore(int)} apps should
+ * treat {@link BroadcastOptions#DEFERRAL_POLICY_DEFAULT} as
+ * {@link BroadcastOptions#DEFERRAL_POLICY_UNTIL_ACTIVE}.
+ */
+ static boolean CORE_DEFER_UNTIL_ACTIVE = false;
+
/** Empty immutable list of receivers */
static final List<Object> EMPTY_RECEIVERS = List.of();
@@ -400,7 +408,9 @@
receivers = (_receivers != null) ? _receivers : EMPTY_RECEIVERS;
delivery = new int[_receivers != null ? _receivers.size() : 0];
deliveryReasons = new String[delivery.length];
- deferUntilActive = options != null ? options.isDeferUntilActive() : false;
+ urgent = calculateUrgent(_intent, _options);
+ deferUntilActive = calculateDeferUntilActive(_callingUid,
+ _options, _resultTo, _serialized, urgent);
deferredUntilActive = new boolean[deferUntilActive ? delivery.length : 0];
blockedUntilTerminalCount = calculateBlockedUntilTerminalCount(receivers, _serialized);
scheduledTime = new long[delivery.length];
@@ -488,6 +498,7 @@
pushMessageOverQuota = from.pushMessageOverQuota;
interactive = from.interactive;
shareIdentity = from.shareIdentity;
+ urgent = from.urgent;
filterExtrasForReceiver = from.filterExtrasForReceiver;
}
@@ -681,15 +692,8 @@
return deferUntilActive;
}
- /**
- * Core policy determination about this broadcast's delivery prioritization
- */
boolean isUrgent() {
- // TODO: flags for controlling policy
- // TODO: migrate alarm-prioritization flag to BroadcastConstants
- return (isForeground()
- || interactive
- || alarm);
+ return urgent;
}
@NonNull String getHostingRecordTriggerType() {
@@ -849,6 +853,69 @@
}
}
+ /**
+ * Core policy determination about this broadcast's delivery prioritization
+ */
+ @VisibleForTesting
+ static boolean calculateUrgent(@NonNull Intent intent, @Nullable BroadcastOptions options) {
+ // TODO: flags for controlling policy
+ // TODO: migrate alarm-prioritization flag to BroadcastConstants
+ if ((intent.getFlags() & Intent.FLAG_RECEIVER_FOREGROUND) != 0) {
+ return true;
+ }
+ if (options != null) {
+ if (options.isInteractive()) {
+ return true;
+ }
+ if (options.isAlarmBroadcast()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Resolve the requested {@link BroadcastOptions#setDeferralPolicy(int)}
+ * against this broadcast state to determine if it should be marked as
+ * "defer until active".
+ */
+ @VisibleForTesting
+ static boolean calculateDeferUntilActive(int callingUid, @Nullable BroadcastOptions options,
+ @Nullable IIntentReceiver resultTo, boolean ordered, boolean urgent) {
+ // Ordered broadcasts can never be deferred until active
+ if (ordered) {
+ return false;
+ }
+
+ // Unordered resultTo broadcasts are always deferred until active
+ if (!ordered && resultTo != null) {
+ return true;
+ }
+
+ // Determine if a strong preference in either direction was expressed;
+ // a preference here overrides all remaining policies
+ if (options != null) {
+ switch (options.getDeferralPolicy()) {
+ case BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE:
+ return true;
+ case BroadcastOptions.DEFERRAL_POLICY_NONE:
+ return false;
+ }
+ }
+
+ // Urgent broadcasts aren't deferred until active
+ if (urgent) {
+ return false;
+ }
+
+ // Otherwise, choose a reasonable default
+ if (CORE_DEFER_UNTIL_ACTIVE && UserHandle.isCore(callingUid)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
public BroadcastRecord maybeStripForHistory() {
if (!intent.canStripForHistory()) {
return this;
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 490a33e..e403861 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -8170,7 +8170,7 @@
volumeChangedOptions.setDeliveryGroupPolicy(DELIVERY_GROUP_POLICY_MOST_RECENT);
volumeChangedOptions.setDeliveryGroupMatchingKey(
AudioManager.VOLUME_CHANGED_ACTION, String.valueOf(mStreamType));
- volumeChangedOptions.setDeferUntilActive(true);
+ volumeChangedOptions.setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE);
mVolumeChangedOptions = volumeChangedOptions.toBundle();
mStreamDevicesChanged = new Intent(AudioManager.STREAM_DEVICES_CHANGED_ACTION);
@@ -8179,7 +8179,8 @@
streamDevicesChangedOptions.setDeliveryGroupPolicy(DELIVERY_GROUP_POLICY_MOST_RECENT);
streamDevicesChangedOptions.setDeliveryGroupMatchingKey(
AudioManager.STREAM_DEVICES_CHANGED_ACTION, String.valueOf(mStreamType));
- streamDevicesChangedOptions.setDeferUntilActive(true);
+ streamDevicesChangedOptions.setDeferralPolicy(
+ BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE);
mStreamDevicesChangedOptions = streamDevicesChangedOptions.toBundle();
}
diff --git a/services/core/java/com/android/server/dreams/DreamController.java b/services/core/java/com/android/server/dreams/DreamController.java
index 3e2efdd..20ff51c 100644
--- a/services/core/java/com/android/server/dreams/DreamController.java
+++ b/services/core/java/com/android/server/dreams/DreamController.java
@@ -120,7 +120,7 @@
options.setDeliveryGroupMatchingKey(
DREAMING_DELIVERY_GROUP_NAMESPACE, DREAMING_DELIVERY_GROUP_KEY);
// This allows the broadcast delivery to be delayed to apps in the Cached state.
- options.setDeferUntilActive(true);
+ options.setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE);
return options.toBundle();
}
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index da7aaa4..d0ed9bf 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -241,7 +241,7 @@
UUID.randomUUID().toString(),
Intent.ACTION_SCREEN_ON);
// This allows the broadcast delivery to be delayed to apps in the Cached state.
- options.setDeferUntilActive(true);
+ options.setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE);
return options.toBundle();
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 6cd9f1c..a1789b2 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -3224,7 +3224,7 @@
intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Bundle options = new BroadcastOptions()
.setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT)
- .setDeferUntilActive(true)
+ .setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE)
.toBundle();
mInjector.binderWithCleanCallingIdentity(() ->
mContext.sendBroadcastAsUser(intent, new UserHandle(userHandle), null, options));
diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
index b395f42..e7e26a1 100644
--- a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
@@ -1303,7 +1303,8 @@
final BroadcastOptions actualOptions = new BroadcastOptions(actualOptionsBundle);
assertEquals(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT,
actualOptions.getDeliveryGroupPolicy());
- assertTrue(actualOptions.isDeferUntilActive());
+ assertEquals(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE,
+ actualOptions.getDeferralPolicy());
}
@Test
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastRecordTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastRecordTest.java
index 01e2768..2b6f217 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastRecordTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastRecordTest.java
@@ -25,6 +25,8 @@
import static com.android.server.am.BroadcastConstants.DEFER_BOOT_COMPLETED_BROADCAST_BACKGROUND_RESTRICTED_ONLY;
import static com.android.server.am.BroadcastConstants.DEFER_BOOT_COMPLETED_BROADCAST_NONE;
import static com.android.server.am.BroadcastRecord.calculateBlockedUntilTerminalCount;
+import static com.android.server.am.BroadcastRecord.calculateDeferUntilActive;
+import static com.android.server.am.BroadcastRecord.calculateUrgent;
import static com.android.server.am.BroadcastRecord.isReceiverEquals;
import static org.junit.Assert.assertArrayEquals;
@@ -38,6 +40,7 @@
import android.app.ActivityManagerInternal;
import android.app.BackgroundStartPrivileges;
import android.app.BroadcastOptions;
+import android.content.IIntentReceiver;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
@@ -55,6 +58,7 @@
import com.android.server.am.BroadcastDispatcher.DeferredBootCompletedBroadcastPerUser;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -86,6 +90,15 @@
private static final String[] PACKAGE_LIST = new String[] {PACKAGE1, PACKAGE2, PACKAGE3,
PACKAGE4};
+ private static final int SYSTEM_UID = android.os.Process.SYSTEM_UID;
+ private static final int APP_UID = android.os.Process.FIRST_APPLICATION_UID;
+
+ private static final BroadcastOptions OPT_DEFAULT = BroadcastOptions.makeBasic();
+ private static final BroadcastOptions OPT_NONE = BroadcastOptions.makeBasic()
+ .setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_NONE);
+ private static final BroadcastOptions OPT_UNTIL_ACTIVE = BroadcastOptions.makeBasic()
+ .setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE);
+
@Mock ActivityManagerInternal mActivityManagerInternal;
@Mock BroadcastQueue mQueue;
@Mock ProcessRecord mProcess;
@@ -213,6 +226,75 @@
}
@Test
+ public void testCalculateUrgent() {
+ final Intent intent = new Intent();
+ final Intent intentForeground = new Intent()
+ .setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+
+ assertFalse(calculateUrgent(intent, null));
+ assertTrue(calculateUrgent(intentForeground, null));
+
+ {
+ final BroadcastOptions opts = BroadcastOptions.makeBasic();
+ assertFalse(calculateUrgent(intent, opts));
+ }
+ {
+ final BroadcastOptions opts = BroadcastOptions.makeBasic();
+ opts.setInteractive(true);
+ assertTrue(calculateUrgent(intent, opts));
+ }
+ {
+ final BroadcastOptions opts = BroadcastOptions.makeBasic();
+ opts.setAlarmBroadcast(true);
+ assertTrue(calculateUrgent(intent, opts));
+ }
+ }
+
+ @Test
+ public void testCalculateDeferUntilActive_App() {
+ // Verify non-urgent behavior
+ assertFalse(calculateDeferUntilActive(APP_UID, null, null, false, false));
+ assertFalse(calculateDeferUntilActive(APP_UID, OPT_DEFAULT, null, false, false));
+ assertFalse(calculateDeferUntilActive(APP_UID, OPT_NONE, null, false, false));
+ assertTrue(calculateDeferUntilActive(APP_UID, OPT_UNTIL_ACTIVE, null, false, false));
+
+ // Verify urgent behavior
+ assertFalse(calculateDeferUntilActive(APP_UID, null, null, false, true));
+ assertFalse(calculateDeferUntilActive(APP_UID, OPT_DEFAULT, null, false, true));
+ assertFalse(calculateDeferUntilActive(APP_UID, OPT_NONE, null, false, true));
+ assertTrue(calculateDeferUntilActive(APP_UID, OPT_UNTIL_ACTIVE, null, false, true));
+ }
+
+ @Test
+ public void testCalculateDeferUntilActive_System() {
+ BroadcastRecord.CORE_DEFER_UNTIL_ACTIVE = true;
+
+ // Verify non-urgent behavior
+ assertTrue(calculateDeferUntilActive(SYSTEM_UID, null, null, false, false));
+ assertTrue(calculateDeferUntilActive(SYSTEM_UID, OPT_DEFAULT, null, false, false));
+ assertFalse(calculateDeferUntilActive(SYSTEM_UID, OPT_NONE, null, false, false));
+ assertTrue(calculateDeferUntilActive(SYSTEM_UID, OPT_UNTIL_ACTIVE, null, false, false));
+
+ // Verify urgent behavior
+ assertFalse(calculateDeferUntilActive(SYSTEM_UID, null, null, false, true));
+ assertFalse(calculateDeferUntilActive(SYSTEM_UID, OPT_DEFAULT, null, false, true));
+ assertFalse(calculateDeferUntilActive(SYSTEM_UID, OPT_NONE, null, false, true));
+ assertTrue(calculateDeferUntilActive(SYSTEM_UID, OPT_UNTIL_ACTIVE, null, false, true));
+ }
+
+ @Test
+ public void testCalculateDeferUntilActive_Overrides() {
+ final IIntentReceiver resultTo = new IIntentReceiver.Default();
+
+ // Ordered broadcasts never deferred; requested option is ignored
+ assertFalse(calculateDeferUntilActive(APP_UID, OPT_UNTIL_ACTIVE, null, true, false));
+ assertFalse(calculateDeferUntilActive(APP_UID, OPT_UNTIL_ACTIVE, resultTo, true, false));
+
+ // Unordered with result is always deferred; requested option is ignored
+ assertTrue(calculateDeferUntilActive(APP_UID, OPT_NONE, resultTo, false, false));
+ }
+
+ @Test
public void testCleanupDisabledPackageReceivers() {
final int user0 = UserHandle.USER_SYSTEM;
final int user1 = user0 + 1;