diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index fe05cb9523830..0eed1909944f3 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -444,6 +444,14 @@ public class ActivityManagerService extends IActivityManager.Stub private static final String SYSTEM_PROPERTY_DEVICE_PROVISIONED = "persist.sys.device_provisioned"; + /** + * Enabling this flag enforces the requirement for context registered receivers to use one of + * {@link Context#RECEIVER_EXPORTED} or {@link Context#RECEIVER_NOT_EXPORTED} for unprotected + * broadcasts + */ + private static final boolean ENFORCE_DYNAMIC_RECEIVER_EXPLICIT_EXPORT = + SystemProperties.getBoolean("fw.enforce_dynamic_receiver_explicit_export", false); + static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityManagerService" : TAG_AM; static final String TAG_BACKUP = TAG + POSTFIX_BACKUP; private static final String TAG_BROADCAST = TAG + POSTFIX_BROADCAST; @@ -12646,28 +12654,43 @@ public class ActivityManagerService extends IActivityManager.Stub // an error so the consumer can know to explicitly set the value for their flag. // If the caller is registering for a sticky broadcast with a null receiver, we won't // require a flag - if (!onlyProtectedBroadcasts && receiver != null && ( - CompatChanges.isChangeEnabled( - DYNAMIC_RECEIVER_EXPLICIT_EXPORT_REQUIRED, callingUid) - && (flags & (Context.RECEIVER_EXPORTED | Context.RECEIVER_NOT_EXPORTED)) - == 0)) { - Slog.e(TAG, - callerPackage + ": Targeting T+ (version " + Build.VERSION_CODES.TIRAMISU - + " and above) requires that one of RECEIVER_EXPORTED or " - + "RECEIVER_NOT_EXPORTED be specified when registering a receiver"); - } else if (((flags & Context.RECEIVER_EXPORTED) != 0) && ( + final boolean explicitExportStateDefined = + (flags & (Context.RECEIVER_EXPORTED | Context.RECEIVER_NOT_EXPORTED)) != 0; + if (((flags & Context.RECEIVER_EXPORTED) != 0) && ( (flags & Context.RECEIVER_NOT_EXPORTED) != 0)) { throw new IllegalArgumentException( "Receiver can't specify both RECEIVER_EXPORTED and RECEIVER_NOT_EXPORTED" + "flag"); } + if (CompatChanges.isChangeEnabled(DYNAMIC_RECEIVER_EXPLICIT_EXPORT_REQUIRED, + callingUid) + && !explicitExportStateDefined) { + if (ENFORCE_DYNAMIC_RECEIVER_EXPLICIT_EXPORT) { + throw new SecurityException( + callerPackage + ": Targeting T+ (version " + + Build.VERSION_CODES.TIRAMISU + + " and above) requires that one of RECEIVER_EXPORTED or " + + "RECEIVER_NOT_EXPORTED be specified when registering a " + + "receiver"); + } else { + Slog.wtf(TAG, + callerPackage + ": Targeting T+ (version " + + Build.VERSION_CODES.TIRAMISU + + " and above) requires that one of RECEIVER_EXPORTED or " + + "RECEIVER_NOT_EXPORTED be specified when registering a " + + "receiver"); + // Assume default behavior-- flag check is not enforced + flags |= Context.RECEIVER_EXPORTED; + } + } else if (!CompatChanges.isChangeEnabled(DYNAMIC_RECEIVER_EXPLICIT_EXPORT_REQUIRED, + callingUid)) { + // Change is not enabled, thus not targeting T+. Assume exported. + flags |= Context.RECEIVER_EXPORTED; + } } // Dynamic receivers are exported by default for versions prior to T - final boolean exported = - ((flags & Context.RECEIVER_EXPORTED) != 0 - || (!CompatChanges.isChangeEnabled( - DYNAMIC_RECEIVER_EXPLICIT_EXPORT_REQUIRED, callingUid))); + final boolean exported = (flags & Context.RECEIVER_EXPORTED) != 0; ArrayList allSticky = null; if (stickyIntents != null) { diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java index 8638c7da4da22..fd6f0994ecfb5 100644 --- a/services/core/java/com/android/server/am/BroadcastQueue.java +++ b/services/core/java/com/android/server/am/BroadcastQueue.java @@ -792,7 +792,7 @@ public final class BroadcastQueue { + " due to receiver " + filter.receiverList.app + " (uid " + filter.receiverList.uid + ")" + " not specifying RECEIVER_EXPORTED"); - // skip = true; + skip = true; } if (skip) {