From 691b392b246522fb664cdb1ce196e16c3449926c Mon Sep 17 00:00:00 2001 From: olly Date: Wed, 15 Jun 2022 15:00:47 +0000 Subject: [PATCH] Don't export broadcast receivers that don't require it Issue: google/ExoPlayer#10287 PiperOrigin-RevId: 455131138 --- .../common/util/NetworkTypeObserver.java | 2 +- .../androidx/media3/common/util/Util.java | 50 +++++++++++++++++++ .../exoplayer/AudioBecomingNoisyManager.java | 5 +- .../media3/exoplayer/StreamVolumeManager.java | 2 +- .../exoplayer/audio/AudioCapabilities.java | 4 +- .../audio/AudioCapabilitiesReceiver.java | 6 +-- .../exoplayer/scheduler/Requirements.java | 8 +-- .../scheduler/RequirementsWatcher.java | 2 +- 8 files changed, 64 insertions(+), 15 deletions(-) diff --git a/libraries/common/src/main/java/androidx/media3/common/util/NetworkTypeObserver.java b/libraries/common/src/main/java/androidx/media3/common/util/NetworkTypeObserver.java index c6421efd61..4e97ab796c 100644 --- a/libraries/common/src/main/java/androidx/media3/common/util/NetworkTypeObserver.java +++ b/libraries/common/src/main/java/androidx/media3/common/util/NetworkTypeObserver.java @@ -94,7 +94,7 @@ public final class NetworkTypeObserver { networkType = C.NETWORK_TYPE_UNKNOWN; IntentFilter filter = new IntentFilter(); filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); - context.registerReceiver(/* receiver= */ new Receiver(), filter); + Util.registerReceiverNotExported(context, new Receiver(), filter); } /** diff --git a/libraries/common/src/main/java/androidx/media3/common/util/Util.java b/libraries/common/src/main/java/androidx/media3/common/util/Util.java index bb0c2205ee..02fab9ce93 100644 --- a/libraries/common/src/main/java/androidx/media3/common/util/Util.java +++ b/libraries/common/src/main/java/androidx/media3/common/util/Util.java @@ -34,9 +34,11 @@ import android.Manifest.permission; import android.annotation.SuppressLint; import android.app.Activity; import android.app.UiModeManager; +import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; @@ -189,6 +191,54 @@ public final class Util { return outputStream.toByteArray(); } + /** + * Registers a {@link BroadcastReceiver} that's not intended to receive broadcasts from other + * apps. This will be enforced by specifying {@link Context#RECEIVER_NOT_EXPORTED} if {@link + * #SDK_INT} is 33 or above. + * + * @param context The context on which {@link Context#registerReceiver} will be called. + * @param receiver The {@link BroadcastReceiver} to register. This value may be null. + * @param filter Selects the Intent broadcasts to be received. + * @return The first sticky intent found that matches {@code filter}, or null if there are none. + */ + @UnstableApi + @Nullable + public static Intent registerReceiverNotExported( + Context context, @Nullable BroadcastReceiver receiver, IntentFilter filter) { + if (SDK_INT < 33) { + return context.registerReceiver(receiver, filter); + } else { + return context.registerReceiver(receiver, filter, Context.RECEIVER_NOT_EXPORTED); + } + } + + /** + * Registers a {@link BroadcastReceiver} that's not intended to receive broadcasts from other + * apps. This will be enforced by specifying {@link Context#RECEIVER_NOT_EXPORTED} if {@link + * #SDK_INT} is 33 or above. + * + * @param context The context on which {@link Context#registerReceiver} will be called. + * @param receiver The {@link BroadcastReceiver} to register. This value may be null. + * @param filter Selects the Intent broadcasts to be received. + * @param handler Handler identifying the thread that will receive the Intent. + * @return The first sticky intent found that matches {@code filter}, or null if there are none. + */ + @UnstableApi + @Nullable + public static Intent registerReceiverNotExported( + Context context, BroadcastReceiver receiver, IntentFilter filter, Handler handler) { + if (SDK_INT < 33) { + return context.registerReceiver(receiver, filter, /* broadcastPermission= */ null, handler); + } else { + return context.registerReceiver( + receiver, + filter, + /* broadcastPermission= */ null, + handler, + Context.RECEIVER_NOT_EXPORTED); + } + } + /** * Calls {@link Context#startForegroundService(Intent)} if {@link #SDK_INT} is 26 or higher, or * {@link Context#startService(Intent)} otherwise. diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/AudioBecomingNoisyManager.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/AudioBecomingNoisyManager.java index 04fd1482bd..625c6090b6 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/AudioBecomingNoisyManager.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/AudioBecomingNoisyManager.java @@ -21,6 +21,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.media.AudioManager; import android.os.Handler; +import androidx.media3.common.util.Util; /* package */ final class AudioBecomingNoisyManager { @@ -46,8 +47,8 @@ import android.os.Handler; */ public void setEnabled(boolean enabled) { if (enabled && !receiverRegistered) { - context.registerReceiver( - receiver, new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY)); + Util.registerReceiverNotExported( + context, receiver, new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY)); receiverRegistered = true; } else if (!enabled && receiverRegistered) { context.unregisterReceiver(receiver); diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/StreamVolumeManager.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/StreamVolumeManager.java index c5a8230154..1fc7dc4828 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/StreamVolumeManager.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/StreamVolumeManager.java @@ -75,7 +75,7 @@ import androidx.media3.common.util.Util; VolumeChangeReceiver receiver = new VolumeChangeReceiver(); IntentFilter filter = new IntentFilter(VOLUME_CHANGED_ACTION); try { - applicationContext.registerReceiver(receiver, filter); + Util.registerReceiverNotExported(applicationContext, receiver, filter); this.receiver = receiver; } catch (RuntimeException e) { Log.w(TAG, "Error registering stream volume receiver", e); diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/AudioCapabilities.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/AudioCapabilities.java index 9888db45a6..6cb10f0731 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/AudioCapabilities.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/AudioCapabilities.java @@ -88,8 +88,8 @@ public final class AudioCapabilities { @SuppressWarnings("InlinedApi") public static AudioCapabilities getCapabilities(Context context) { Intent intent = - context.registerReceiver( - /* receiver= */ null, new IntentFilter(AudioManager.ACTION_HDMI_AUDIO_PLUG)); + Util.registerReceiverNotExported( + context, /* receiver= */ null, new IntentFilter(AudioManager.ACTION_HDMI_AUDIO_PLUG)); return getCapabilities(context, intent); } diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/AudioCapabilitiesReceiver.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/AudioCapabilitiesReceiver.java index 241e914ff0..1cfef2accc 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/AudioCapabilitiesReceiver.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/AudioCapabilitiesReceiver.java @@ -90,12 +90,10 @@ public final class AudioCapabilitiesReceiver { if (externalSurroundSoundSettingObserver != null) { externalSurroundSoundSettingObserver.register(); } - Intent stickyIntent = null; + @Nullable Intent stickyIntent = null; if (receiver != null) { IntentFilter intentFilter = new IntentFilter(AudioManager.ACTION_HDMI_AUDIO_PLUG); - stickyIntent = - context.registerReceiver( - receiver, intentFilter, /* broadcastPermission= */ null, handler); + stickyIntent = Util.registerReceiverNotExported(context, receiver, intentFilter, handler); } audioCapabilities = AudioCapabilities.getCapabilities(context, stickyIntent); return audioCapabilities; diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/scheduler/Requirements.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/scheduler/Requirements.java index 53ad113710..ab87aa361c 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/scheduler/Requirements.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/scheduler/Requirements.java @@ -184,8 +184,8 @@ public final class Requirements implements Parcelable { private boolean isDeviceCharging(Context context) { @Nullable Intent batteryStatus = - context.registerReceiver( - /* receiver= */ null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); + Util.registerReceiverNotExported( + context, /* receiver= */ null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); if (batteryStatus == null) { return false; } @@ -203,8 +203,8 @@ public final class Requirements implements Parcelable { } private boolean isStorageNotLow(Context context) { - return context.registerReceiver( - /* receiver= */ null, new IntentFilter(Intent.ACTION_DEVICE_STORAGE_LOW)) + return Util.registerReceiverNotExported( + context, /* receiver= */ null, new IntentFilter(Intent.ACTION_DEVICE_STORAGE_LOW)) == null; } diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/scheduler/RequirementsWatcher.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/scheduler/RequirementsWatcher.java index c7ae614e05..541224221c 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/scheduler/RequirementsWatcher.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/scheduler/RequirementsWatcher.java @@ -111,7 +111,7 @@ public final class RequirementsWatcher { filter.addAction(Intent.ACTION_DEVICE_STORAGE_OK); } receiver = new DeviceStatusChangeReceiver(); - context.registerReceiver(receiver, filter, null, handler); + Util.registerReceiverNotExported(context, receiver, filter, handler); return notMetRequirements; }