diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 4713a31359764..762fb0459b412 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -1299,7 +1299,7 @@ class ContextImpl extends Context { @Override public void sendBroadcastMultiplePermissions(Intent intent, String[] receiverPermissions, - String[] excludedPermissions, String[] excludedPackages) { + String[] excludedPermissions, String[] excludedPackages, BroadcastOptions options) { warnIfCallingFromSystemProcess(); String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); try { @@ -1307,7 +1307,8 @@ class ContextImpl extends Context { ActivityManager.getService().broadcastIntentWithFeature( mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType, null, Activity.RESULT_OK, null, null, receiverPermissions, excludedPermissions, - excludedPackages, AppOpsManager.OP_NONE, null, false, false, getUserId()); + excludedPackages, AppOpsManager.OP_NONE, + options == null ? null : options.toBundle(), false, false, getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 36f7ff53eb768..fc7532303ab14 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -2399,7 +2399,6 @@ public abstract class Context { sendBroadcastMultiplePermissions(intent, receiverPermissions, excludedPermissions, null); } - /** * Like {@link #sendBroadcastMultiplePermissions(Intent, String[], String[])}, but also allows * specification of a list of excluded packages. @@ -2409,6 +2408,19 @@ public abstract class Context { public void sendBroadcastMultiplePermissions(@NonNull Intent intent, @NonNull String[] receiverPermissions, @Nullable String[] excludedPermissions, @Nullable String[] excludedPackages) { + sendBroadcastMultiplePermissions(intent, receiverPermissions, excludedPermissions, + excludedPackages, null); + } + + /** + * Like {@link #sendBroadcastMultiplePermissions(Intent, String[], String[], String[])}, but + * also allows specification of options generated from {@link android.app.BroadcastOptions}. + * + * @hide + */ + public void sendBroadcastMultiplePermissions(@NonNull Intent intent, + @NonNull String[] receiverPermissions, @Nullable String[] excludedPermissions, + @Nullable String[] excludedPackages, @Nullable BroadcastOptions options) { throw new RuntimeException("Not implemented. Must override in a subclass."); } diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java index 1775bf7d13909..21de5cf1511a7 100644 --- a/core/java/android/content/ContextWrapper.java +++ b/core/java/android/content/ContextWrapper.java @@ -24,6 +24,7 @@ import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.annotation.TestApi; import android.annotation.UiContext; +import android.app.BroadcastOptions; import android.app.IApplicationThread; import android.app.IServiceConnection; import android.app.compat.CompatChanges; @@ -519,9 +520,9 @@ public class ContextWrapper extends Context { @Override public void sendBroadcastMultiplePermissions(@NonNull Intent intent, @NonNull String[] receiverPermissions, @Nullable String[] excludedPermissions, - @Nullable String[] excludedPackages) { + @Nullable String[] excludedPackages, @Nullable BroadcastOptions options) { mBase.sendBroadcastMultiplePermissions(intent, receiverPermissions, excludedPermissions, - excludedPackages); + excludedPackages, options); } /** @hide */ diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index bffa3dd797545..e76b628691bb1 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -28,6 +28,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; import android.app.AppOpsManager; +import android.app.BroadcastOptions; import android.app.compat.CompatChanges; import android.compat.annotation.ChangeId; import android.compat.annotation.EnabledSince; @@ -3533,28 +3534,36 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { // - Sanitized ServiceState sent to all other apps with READ_PHONE_STATE // - Sanitized ServiceState sent to all other apps with READ_PRIVILEGED_PHONE_STATE but not // READ_PHONE_STATE + BroadcastOptions options = createServiceStateBroadcastOptions(subId, phoneId); if (LocationAccessPolicy.isLocationModeEnabled(mContext, mContext.getUserId())) { Intent fullIntent = createServiceStateIntent(state, subId, phoneId, false); mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions( fullIntent, new String[]{Manifest.permission.READ_PHONE_STATE, - Manifest.permission.ACCESS_FINE_LOCATION}); + Manifest.permission.ACCESS_FINE_LOCATION}, + options); mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions( fullIntent, new String[]{Manifest.permission.READ_PRIVILEGED_PHONE_STATE, Manifest.permission.ACCESS_FINE_LOCATION}, - new String[]{Manifest.permission.READ_PHONE_STATE}); + new String[]{Manifest.permission.READ_PHONE_STATE}, + null, + options); Intent sanitizedIntent = createServiceStateIntent(state, subId, phoneId, true); mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions( sanitizedIntent, new String[]{Manifest.permission.READ_PHONE_STATE}, - new String[]{Manifest.permission.ACCESS_FINE_LOCATION}); + new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, + null, + options); mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions( sanitizedIntent, new String[]{Manifest.permission.READ_PRIVILEGED_PHONE_STATE}, new String[]{Manifest.permission.READ_PHONE_STATE, - Manifest.permission.ACCESS_FINE_LOCATION}); + Manifest.permission.ACCESS_FINE_LOCATION}, + null, + options); } else { String[] locationBypassPackages = Binder.withCleanCallingIdentity(() -> LocationAccessPolicy.getLocationBypassPackages(mContext)); @@ -3563,11 +3572,14 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { fullIntent.setPackage(locationBypassPackage); mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions( fullIntent, - new String[]{Manifest.permission.READ_PHONE_STATE}); + new String[]{Manifest.permission.READ_PHONE_STATE}, + options); mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions( fullIntent, new String[]{Manifest.permission.READ_PRIVILEGED_PHONE_STATE}, - new String[]{Manifest.permission.READ_PHONE_STATE}); + new String[]{Manifest.permission.READ_PHONE_STATE}, + null, + options); } Intent sanitizedIntent = createServiceStateIntent(state, subId, phoneId, true); @@ -3575,12 +3587,14 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { sanitizedIntent, new String[]{Manifest.permission.READ_PHONE_STATE}, new String[]{/* no excluded permissions */}, - locationBypassPackages); + locationBypassPackages, + options); mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions( sanitizedIntent, new String[]{Manifest.permission.READ_PRIVILEGED_PHONE_STATE}, new String[]{Manifest.permission.READ_PHONE_STATE}, - locationBypassPackages); + locationBypassPackages, + options); } } @@ -3602,6 +3616,15 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { return intent; } + private BroadcastOptions createServiceStateBroadcastOptions(int subId, int phoneId) { + return new BroadcastOptions() + .setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT) + // Use a combination of subId and phoneId as the key so that older broadcasts + // with same subId and phoneId will get discarded. + .setDeliveryGroupMatchingKey(Intent.ACTION_SERVICE_STATE, subId + "-" + phoneId) + .setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE); + } + private void broadcastSignalStrengthChanged(SignalStrength signalStrength, int phoneId, int subId) { final long ident = Binder.clearCallingIdentity();