Loading core/api/system-current.txt +2 −0 Original line number Diff line number Diff line Loading @@ -806,10 +806,12 @@ package android.app { method @Nullable public android.content.IntentFilter getDeliveryGroupMatchingFilter(); method @Nullable public String getDeliveryGroupMatchingKey(); method public int getDeliveryGroupPolicy(); method public boolean isDeferUntilActive(); method public boolean isPendingIntentBackgroundActivityLaunchAllowed(); method public static android.app.BroadcastOptions makeBasic(); method @RequiresPermission(android.Manifest.permission.ACCESS_BROADCAST_RESPONSE_STATS) public void recordResponseEventWhileInBackground(@IntRange(from=0) long); method @RequiresPermission(android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND) public void setBackgroundActivityStartsAllowed(boolean); method @NonNull public android.app.BroadcastOptions setDeferUntilActive(boolean); method @NonNull public android.app.BroadcastOptions setDeliveryGroupMatchingFilter(@NonNull android.content.IntentFilter); method @NonNull public android.app.BroadcastOptions setDeliveryGroupMatchingKey(@NonNull String, @NonNull String); method @NonNull public android.app.BroadcastOptions setDeliveryGroupPolicy(int); core/java/android/app/BroadcastOptions.java +46 −0 Original line number Diff line number Diff line Loading @@ -63,6 +63,7 @@ public class BroadcastOptions extends ComponentOptions { private long mRequireCompatChangeId = CHANGE_INVALID; private boolean mRequireCompatChangeEnabled = true; private boolean mIsAlarmBroadcast = false; private boolean mIsDeferUntilActive = false; private long mIdForResponseEvent; private @Nullable IntentFilter mRemoveMatchingFilter; private @DeliveryGroupPolicy int mDeliveryGroupPolicy; Loading Loading @@ -200,6 +201,12 @@ public class BroadcastOptions extends ComponentOptions { private static final String KEY_REMOVE_MATCHING_FILTER = "android:broadcast.removeMatchingFilter"; /** * Corresponds to {@link #setDeferUntilActive(boolean)}. */ private static final String KEY_DEFER_UNTIL_ACTIVE = "android:broadcast.deferuntilactive"; /** * Corresponds to {@link #setDeliveryGroupPolicy(int)}. */ Loading Loading @@ -320,6 +327,7 @@ public class BroadcastOptions extends ComponentOptions { BundleMerger.class); mDeliveryGroupMatchingFilter = opts.getParcelable(KEY_DELIVERY_GROUP_MATCHING_FILTER, IntentFilter.class); mIsDeferUntilActive = opts.getBoolean(KEY_DEFER_UNTIL_ACTIVE, false); } /** Loading Loading @@ -699,6 +707,41 @@ public class BroadcastOptions extends ComponentOptions { return mIdForResponseEvent; } /** * Sets whether the broadcast should not run until the process is in an active process state * (ie, a process exists for the app and the app is not in a cached process state). * * Whether an app's process state is considered active is independent of its standby bucket. * * A broadcast that is deferred until the process is active will not execute until the process * is brought to an active state by some other action, like a job, alarm, or service binding. As * a result, the broadcast may be delayed indefinitely. This deferral only applies to runtime * registered receivers of a broadcast. Any manifest receivers will run immediately, similar to * how a manifest receiver would start a new process in order to run a broadcast receiver. * * Ordered broadcasts, alarm broadcasts, interactive broadcasts, and manifest broadcasts are * never deferred. * * Unordered broadcasts and unordered broadcasts with completion callbacks may be * deferred. Completion callbacks for broadcasts deferred until active are * best-effort. Completion callbacks will run when all eligible processes have finished * executing the broadcast. Processes in inactive process states that defer the broadcast are * not considered eligible and may not execute the broadcast prior to the completion callback. * * @hide */ @SystemApi public @NonNull BroadcastOptions setDeferUntilActive(boolean shouldDefer) { mIsDeferUntilActive = shouldDefer; return this; } /** @hide */ @SystemApi public boolean isDeferUntilActive() { return mIsDeferUntilActive; } /** * When enqueuing this broadcast, remove all pending broadcasts previously * sent by this app which match the given filter. Loading Loading @@ -963,6 +1006,9 @@ public class BroadcastOptions extends ComponentOptions { if (mDeliveryGroupMatchingFilter != null) { b.putParcelable(KEY_DELIVERY_GROUP_MATCHING_FILTER, mDeliveryGroupMatchingFilter); } if (mIsDeferUntilActive) { b.putBoolean(KEY_DEFER_UNTIL_ACTIVE, mIsDeferUntilActive); } return b.isEmpty() ? null : b; } } packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +11 −1 Original line number Diff line number Diff line Loading @@ -41,6 +41,7 @@ import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.app.ActivityTaskManager; import android.app.AlarmManager; import android.app.BroadcastOptions; import android.app.PendingIntent; import android.app.StatusBarManager; import android.app.WindowConfiguration; Loading Loading @@ -391,6 +392,12 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS); private static final Bundle USER_PRESENT_INTENT_OPTIONS = BroadcastOptions.makeBasic() .setDeferUntilActive(true) .setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT) .toBundle(); /** * {@link #setKeyguardEnabled} waits on this condition when it re-enables * the keyguard. Loading Loading @@ -2319,7 +2326,10 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, Context.USER_SERVICE); mUiBgExecutor.execute(() -> { for (int profileId : um.getProfileIdsWithDisabled(currentUser.getIdentifier())) { mContext.sendBroadcastAsUser(USER_PRESENT_INTENT, UserHandle.of(profileId)); mContext.sendBroadcastAsUser(USER_PRESENT_INTENT, UserHandle.of(profileId), null, USER_PRESENT_INTENT_OPTIONS); } mLockPatternUtils.userPresent(currentUserId); }); Loading services/core/java/com/android/server/BatteryService.java +10 −5 Original line number Diff line number Diff line Loading @@ -189,15 +189,20 @@ public final class BatteryService extends SystemService { private long mLastBatteryLevelChangedSentMs; private Bundle mBatteryChangedOptions = BroadcastOptions.makeRemovingMatchingFilter( new IntentFilter(Intent.ACTION_BATTERY_CHANGED)).toBundle(); new IntentFilter(Intent.ACTION_BATTERY_CHANGED)).setDeferUntilActive(true) .toBundle(); private Bundle mPowerConnectedOptions = BroadcastOptions.makeRemovingMatchingFilter( new IntentFilter(Intent.ACTION_POWER_DISCONNECTED)).toBundle(); new IntentFilter(Intent.ACTION_POWER_DISCONNECTED)).setDeferUntilActive(true) .toBundle(); private Bundle mPowerDisconnectedOptions = BroadcastOptions.makeRemovingMatchingFilter( new IntentFilter(Intent.ACTION_POWER_CONNECTED)).toBundle(); new IntentFilter(Intent.ACTION_POWER_CONNECTED)).setDeferUntilActive(true) .toBundle(); private Bundle mBatteryLowOptions = BroadcastOptions.makeRemovingMatchingFilter( new IntentFilter(Intent.ACTION_BATTERY_OKAY)).toBundle(); new IntentFilter(Intent.ACTION_BATTERY_OKAY)).setDeferUntilActive(true) .toBundle(); private Bundle mBatteryOkayOptions = BroadcastOptions.makeRemovingMatchingFilter( new IntentFilter(Intent.ACTION_BATTERY_LOW)).toBundle(); new IntentFilter(Intent.ACTION_BATTERY_LOW)).setDeferUntilActive(true) .toBundle(); private MetricsLogger mMetricsLogger; Loading services/core/java/com/android/server/am/ActivityManagerService.java +22 −2 Original line number Diff line number Diff line Loading @@ -14108,9 +14108,17 @@ public class ActivityManagerService extends IActivityManager.Stub if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent + " ordered=" + ordered + " userid=" + userId); if ((resultTo != null) && !ordered && !mEnableModernQueue) { if ((resultTo != null) && !ordered) { if (!mEnableModernQueue) { Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!"); } if (!UserHandle.isCore(callingUid)) { String msg = "Unauthorized unordered resultTo broadcast " + intent + " sent from uid " + callingUid; Slog.w(TAG, msg); throw new SecurityException(msg); } } userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, true, ALLOW_NON_FULL, "broadcast", callerPackage); Loading Loading @@ -14190,6 +14198,18 @@ public class ActivityManagerService extends IActivityManager.Stub } } // resultTo broadcasts are always infinitely deferrable. if ((resultTo != null) && !ordered && mEnableModernQueue) { if (brOptions == null) { brOptions = BroadcastOptions.makeBasic(); } brOptions.setDeferUntilActive(true); } if (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; Loading
core/api/system-current.txt +2 −0 Original line number Diff line number Diff line Loading @@ -806,10 +806,12 @@ package android.app { method @Nullable public android.content.IntentFilter getDeliveryGroupMatchingFilter(); method @Nullable public String getDeliveryGroupMatchingKey(); method public int getDeliveryGroupPolicy(); method public boolean isDeferUntilActive(); method public boolean isPendingIntentBackgroundActivityLaunchAllowed(); method public static android.app.BroadcastOptions makeBasic(); method @RequiresPermission(android.Manifest.permission.ACCESS_BROADCAST_RESPONSE_STATS) public void recordResponseEventWhileInBackground(@IntRange(from=0) long); method @RequiresPermission(android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND) public void setBackgroundActivityStartsAllowed(boolean); method @NonNull public android.app.BroadcastOptions setDeferUntilActive(boolean); method @NonNull public android.app.BroadcastOptions setDeliveryGroupMatchingFilter(@NonNull android.content.IntentFilter); method @NonNull public android.app.BroadcastOptions setDeliveryGroupMatchingKey(@NonNull String, @NonNull String); method @NonNull public android.app.BroadcastOptions setDeliveryGroupPolicy(int);
core/java/android/app/BroadcastOptions.java +46 −0 Original line number Diff line number Diff line Loading @@ -63,6 +63,7 @@ public class BroadcastOptions extends ComponentOptions { private long mRequireCompatChangeId = CHANGE_INVALID; private boolean mRequireCompatChangeEnabled = true; private boolean mIsAlarmBroadcast = false; private boolean mIsDeferUntilActive = false; private long mIdForResponseEvent; private @Nullable IntentFilter mRemoveMatchingFilter; private @DeliveryGroupPolicy int mDeliveryGroupPolicy; Loading Loading @@ -200,6 +201,12 @@ public class BroadcastOptions extends ComponentOptions { private static final String KEY_REMOVE_MATCHING_FILTER = "android:broadcast.removeMatchingFilter"; /** * Corresponds to {@link #setDeferUntilActive(boolean)}. */ private static final String KEY_DEFER_UNTIL_ACTIVE = "android:broadcast.deferuntilactive"; /** * Corresponds to {@link #setDeliveryGroupPolicy(int)}. */ Loading Loading @@ -320,6 +327,7 @@ public class BroadcastOptions extends ComponentOptions { BundleMerger.class); mDeliveryGroupMatchingFilter = opts.getParcelable(KEY_DELIVERY_GROUP_MATCHING_FILTER, IntentFilter.class); mIsDeferUntilActive = opts.getBoolean(KEY_DEFER_UNTIL_ACTIVE, false); } /** Loading Loading @@ -699,6 +707,41 @@ public class BroadcastOptions extends ComponentOptions { return mIdForResponseEvent; } /** * Sets whether the broadcast should not run until the process is in an active process state * (ie, a process exists for the app and the app is not in a cached process state). * * Whether an app's process state is considered active is independent of its standby bucket. * * A broadcast that is deferred until the process is active will not execute until the process * is brought to an active state by some other action, like a job, alarm, or service binding. As * a result, the broadcast may be delayed indefinitely. This deferral only applies to runtime * registered receivers of a broadcast. Any manifest receivers will run immediately, similar to * how a manifest receiver would start a new process in order to run a broadcast receiver. * * Ordered broadcasts, alarm broadcasts, interactive broadcasts, and manifest broadcasts are * never deferred. * * Unordered broadcasts and unordered broadcasts with completion callbacks may be * deferred. Completion callbacks for broadcasts deferred until active are * best-effort. Completion callbacks will run when all eligible processes have finished * executing the broadcast. Processes in inactive process states that defer the broadcast are * not considered eligible and may not execute the broadcast prior to the completion callback. * * @hide */ @SystemApi public @NonNull BroadcastOptions setDeferUntilActive(boolean shouldDefer) { mIsDeferUntilActive = shouldDefer; return this; } /** @hide */ @SystemApi public boolean isDeferUntilActive() { return mIsDeferUntilActive; } /** * When enqueuing this broadcast, remove all pending broadcasts previously * sent by this app which match the given filter. Loading Loading @@ -963,6 +1006,9 @@ public class BroadcastOptions extends ComponentOptions { if (mDeliveryGroupMatchingFilter != null) { b.putParcelable(KEY_DELIVERY_GROUP_MATCHING_FILTER, mDeliveryGroupMatchingFilter); } if (mIsDeferUntilActive) { b.putBoolean(KEY_DEFER_UNTIL_ACTIVE, mIsDeferUntilActive); } return b.isEmpty() ? null : b; } }
packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +11 −1 Original line number Diff line number Diff line Loading @@ -41,6 +41,7 @@ import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.app.ActivityTaskManager; import android.app.AlarmManager; import android.app.BroadcastOptions; import android.app.PendingIntent; import android.app.StatusBarManager; import android.app.WindowConfiguration; Loading Loading @@ -391,6 +392,12 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS); private static final Bundle USER_PRESENT_INTENT_OPTIONS = BroadcastOptions.makeBasic() .setDeferUntilActive(true) .setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT) .toBundle(); /** * {@link #setKeyguardEnabled} waits on this condition when it re-enables * the keyguard. Loading Loading @@ -2319,7 +2326,10 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, Context.USER_SERVICE); mUiBgExecutor.execute(() -> { for (int profileId : um.getProfileIdsWithDisabled(currentUser.getIdentifier())) { mContext.sendBroadcastAsUser(USER_PRESENT_INTENT, UserHandle.of(profileId)); mContext.sendBroadcastAsUser(USER_PRESENT_INTENT, UserHandle.of(profileId), null, USER_PRESENT_INTENT_OPTIONS); } mLockPatternUtils.userPresent(currentUserId); }); Loading
services/core/java/com/android/server/BatteryService.java +10 −5 Original line number Diff line number Diff line Loading @@ -189,15 +189,20 @@ public final class BatteryService extends SystemService { private long mLastBatteryLevelChangedSentMs; private Bundle mBatteryChangedOptions = BroadcastOptions.makeRemovingMatchingFilter( new IntentFilter(Intent.ACTION_BATTERY_CHANGED)).toBundle(); new IntentFilter(Intent.ACTION_BATTERY_CHANGED)).setDeferUntilActive(true) .toBundle(); private Bundle mPowerConnectedOptions = BroadcastOptions.makeRemovingMatchingFilter( new IntentFilter(Intent.ACTION_POWER_DISCONNECTED)).toBundle(); new IntentFilter(Intent.ACTION_POWER_DISCONNECTED)).setDeferUntilActive(true) .toBundle(); private Bundle mPowerDisconnectedOptions = BroadcastOptions.makeRemovingMatchingFilter( new IntentFilter(Intent.ACTION_POWER_CONNECTED)).toBundle(); new IntentFilter(Intent.ACTION_POWER_CONNECTED)).setDeferUntilActive(true) .toBundle(); private Bundle mBatteryLowOptions = BroadcastOptions.makeRemovingMatchingFilter( new IntentFilter(Intent.ACTION_BATTERY_OKAY)).toBundle(); new IntentFilter(Intent.ACTION_BATTERY_OKAY)).setDeferUntilActive(true) .toBundle(); private Bundle mBatteryOkayOptions = BroadcastOptions.makeRemovingMatchingFilter( new IntentFilter(Intent.ACTION_BATTERY_LOW)).toBundle(); new IntentFilter(Intent.ACTION_BATTERY_LOW)).setDeferUntilActive(true) .toBundle(); private MetricsLogger mMetricsLogger; Loading
services/core/java/com/android/server/am/ActivityManagerService.java +22 −2 Original line number Diff line number Diff line Loading @@ -14108,9 +14108,17 @@ public class ActivityManagerService extends IActivityManager.Stub if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent + " ordered=" + ordered + " userid=" + userId); if ((resultTo != null) && !ordered && !mEnableModernQueue) { if ((resultTo != null) && !ordered) { if (!mEnableModernQueue) { Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!"); } if (!UserHandle.isCore(callingUid)) { String msg = "Unauthorized unordered resultTo broadcast " + intent + " sent from uid " + callingUid; Slog.w(TAG, msg); throw new SecurityException(msg); } } userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, true, ALLOW_NON_FULL, "broadcast", callerPackage); Loading Loading @@ -14190,6 +14198,18 @@ public class ActivityManagerService extends IActivityManager.Stub } } // resultTo broadcasts are always infinitely deferrable. if ((resultTo != null) && !ordered && mEnableModernQueue) { if (brOptions == null) { brOptions = BroadcastOptions.makeBasic(); } brOptions.setDeferUntilActive(true); } if (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;