Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -857,6 +857,24 @@ public final void setSessionActivity(
impl.setSessionActivity(controller, activityPendingIntent);
}

/**
* Sets whether to opt out from media button (e.g. Bluetooth) playback resumption.
*
* <p>The default value is {@code false}.
*
* <p>This method will throw {@link IllegalStateException} if called when media button playback
* resumption was never opted into in the first place (by adding {@link MediaButtonReceiver} to
* the manifest).
*
* @param optOutOfMediaButtonPlaybackResumption Whether to opt out of media button playback
* resumption.
*/
@UnstableApi
public void setOptOutOfMediaButtonPlaybackResumption(
boolean optOutOfMediaButtonPlaybackResumption) {
impl.setOptOutOfMediaButtonPlaybackResumption(optOutOfMediaButtonPlaybackResumption);
}

/**
* Sets the underlying {@link Player} for this session to dispatch incoming events to.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -889,6 +889,12 @@ public MediaSession.ConnectionResult onConnectOnHandler(ControllerInfo controlle
return connectionResult;
}

public void setOptOutOfMediaButtonPlaybackResumption(
boolean optOutOfMediaButtonPlaybackResumption) {
sessionLegacyStub.setOptOutOfMediaButtonPlaybackResumption(
optOutOfMediaButtonPlaybackResumption);
}

public void onPostConnectOnHandler(ControllerInfo controller) {
if (isMediaNotificationControllerConnected && isSystemUiController(controller)) {
// Hide System UI. Apps can use the media notification controller to maintain the platform
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
import android.os.SystemClock;
import android.text.TextUtils;
import android.view.KeyEvent;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.core.util.ObjectsCompat;
Expand Down Expand Up @@ -136,6 +137,7 @@
private final MediaSessionCompat sessionCompat;
@Nullable private final MediaButtonReceiver runtimeBroadcastReceiver;
@Nullable private final ComponentName broadcastReceiverComponentName;
private boolean optOutOfMediaButtonPlaybackResumption;
@Nullable private VolumeProviderCompat volumeProviderCompat;
private final boolean playIfSuppressed;

Expand Down Expand Up @@ -191,7 +193,7 @@ public MediaSessionLegacyStub(
broadcastReceiverComponentName = queryPackageManagerForMediaButtonReceiver(context);
@Nullable ComponentName receiverComponentName = broadcastReceiverComponentName;
boolean isReceiverComponentAService = false;
if (receiverComponentName == null || SDK_INT < 31) {
if (receiverComponentName == null && SDK_INT < 26) {
// Below API 26, media button events are sent to the receiver at runtime also. We always want
// these to arrive at the service at runtime. release() then set the receiver for restart if
// available.
Expand All @@ -201,37 +203,35 @@ public MediaSessionLegacyStub(
receiverComponentName =
getServiceComponentByAction(context, MediaSessionService.SERVICE_INTERFACE);
}
isReceiverComponentAService =
receiverComponentName != null
&& !Objects.equals(receiverComponentName, broadcastReceiverComponentName);
isReceiverComponentAService = receiverComponentName != null;
}
Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON, sessionUri);
PendingIntent mediaButtonIntent;
if (receiverComponentName == null) {
final PendingIntent mediaButtonIntent;
if (receiverComponentName == null && SDK_INT < 26) {
// Neither a media button receiver from the app manifest nor a service available that could
// handle media button events. Create a runtime receiver and a pending intent for it.
runtimeBroadcastReceiver = new MediaButtonReceiver();
IntentFilter filter = new IntentFilter(Intent.ACTION_MEDIA_BUTTON);
filter.addDataScheme(castNonNull(sessionUri.getScheme()));
Util.registerReceiverNotExported(context, runtimeBroadcastReceiver, filter);
// Create a pending intent to be broadcast to the receiver.
Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON, sessionUri);
intent.setPackage(context.getPackageName());
mediaButtonIntent =
PendingIntent.getBroadcast(
context, /* requestCode= */ 0, intent, PENDING_INTENT_FLAG_MUTABLE);
// Creates a fake ComponentName for MediaSessionCompat in pre-L or without a service.
receiverComponentName = new ComponentName(context, context.getClass());
} else {
intent.setComponent(receiverComponentName);
mediaButtonIntent =
isReceiverComponentAService
? (SDK_INT >= 26
? PendingIntent.getForegroundService(
context, /* requestCode= */ 0, intent, PENDING_INTENT_FLAG_MUTABLE)
: PendingIntent.getService(
context, /* requestCode= */ 0, intent, PENDING_INTENT_FLAG_MUTABLE))
: PendingIntent.getBroadcast(
context, /* requestCode= */ 0, intent, PENDING_INTENT_FLAG_MUTABLE);
if (receiverComponentName != null && SDK_INT < 31) {
Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON, sessionUri);
intent.setComponent(receiverComponentName);
mediaButtonIntent =
isReceiverComponentAService
? PendingIntent.getService(
context, /* requestCode= */ 0, intent, PENDING_INTENT_FLAG_MUTABLE)
: PendingIntent.getBroadcast(
context, /* requestCode= */ 0, intent, PENDING_INTENT_FLAG_MUTABLE);
} else {
mediaButtonIntent = null;
}
runtimeBroadcastReceiver = null;
}

Expand All @@ -243,7 +243,6 @@ public MediaSessionLegacyStub(
new MediaSessionCompat(
context,
sessionCompatId,
SDK_INT < 31 ? receiverComponentName : null,
SDK_INT < 31 ? mediaButtonIntent : null,
/* sessionInfo= */ tokenExtras);
if (SDK_INT >= 31 && broadcastReceiverComponentName != null) {
Expand All @@ -261,6 +260,15 @@ public MediaSessionLegacyStub(
sessionCompat.setCallback(thisRef, handler);
}

public void setOptOutOfMediaButtonPlaybackResumption(
boolean optOutOfMediaButtonPlaybackResumption) {
if (broadcastReceiverComponentName == null) {
throw new IllegalStateException(
"Media button playback resumption is not enabled, cannot opt out.");
}
this.optOutOfMediaButtonPlaybackResumption = optOutOfMediaButtonPlaybackResumption;
}

/**
* Sets the available commands for the platform session.
*
Expand Down Expand Up @@ -460,22 +468,18 @@ public void start() {

@SuppressWarnings("PendingIntentMutability") // We can't use SaferPendingIntent.
public void release() {
if (SDK_INT < 31) {
if (broadcastReceiverComponentName == null) {
// No broadcast receiver available. Playback resumption not supported.
setMediaButtonReceiver(sessionCompat, /* mediaButtonReceiverIntent= */ null);
} else {
// Override the runtime receiver with the broadcast receiver for playback resumption.
Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON, sessionImpl.getUri());
intent.setComponent(broadcastReceiverComponentName);
PendingIntent mediaButtonReceiverIntent =
PendingIntent.getBroadcast(
sessionImpl.getContext(),
/* requestCode= */ 0,
intent,
PENDING_INTENT_FLAG_MUTABLE);
setMediaButtonReceiver(sessionCompat, mediaButtonReceiverIntent);
}
if ((broadcastReceiverComponentName == null && SDK_INT < 26)
|| (broadcastReceiverComponentName != null && optOutOfMediaButtonPlaybackResumption)) {
// No broadcast receiver available / opted out. Playback resumption not supported.
setMediaButtonReceiver(sessionCompat, /* mediaButtonReceiverIntent= */ null);
} else if (SDK_INT < 26) {
// Override the runtime receiver with the broadcast receiver for playback resumption.
Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON, sessionImpl.getUri());
intent.setComponent(broadcastReceiverComponentName);
PendingIntent mediaButtonReceiverIntent =
PendingIntent.getBroadcast(
sessionImpl.getContext(), /* requestCode= */ 0, intent, PENDING_INTENT_FLAG_MUTABLE);
setMediaButtonReceiver(sessionCompat, mediaButtonReceiverIntent);
}
if (runtimeBroadcastReceiver != null) {
sessionImpl.getContext().unregisterReceiver(runtimeBroadcastReceiver);
Expand Down Expand Up @@ -2080,7 +2084,7 @@ public void onReceive(Context context, Intent intent) {
@RequiresApi(31)
private static final class Api31 {
public static void setMediaButtonBroadcastReceiver(
MediaSessionCompat mediaSessionCompat, ComponentName broadcastReceiver) {
MediaSessionCompat mediaSessionCompat, @NonNull ComponentName broadcastReceiver) {
try {
((android.media.session.MediaSession) checkNotNull(mediaSessionCompat.getMediaSession()))
.setMediaButtonBroadcastReceiver(broadcastReceiver);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -325,32 +325,12 @@ public class MediaSessionCompat {
public MediaSessionCompat(
Context context,
String tag,
@Nullable ComponentName mbrComponent,
@Nullable PendingIntent mbrIntent,
@Nullable Bundle sessionInfo) {
if (TextUtils.isEmpty(tag)) {
throw new IllegalArgumentException("tag must not be null or empty");
}

if (mbrComponent == null) {
mbrComponent = MediaButtonReceiver.getMediaButtonReceiverComponent(context);
if (mbrComponent == null) {
Log.i(TAG, "Couldn't find a unique registered media button receiver in the given context.");
}
}
if (mbrComponent != null && mbrIntent == null) {
// construct a PendingIntent for the media button
Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
// the associated intent will be handled by the component being registered
mediaButtonIntent.setComponent(mbrComponent);
mbrIntent =
PendingIntent.getBroadcast(
context,
0 /* requestCode, ignored */,
mediaButtonIntent,
Build.VERSION.SDK_INT >= 31 ? PendingIntent.FLAG_MUTABLE : 0);
}

if (Build.VERSION.SDK_INT >= 29) {
impl = new MediaSessionImplApi29(context, tag, sessionInfo);
} else if (Build.VERSION.SDK_INT >= 28) {
Expand All @@ -364,7 +344,9 @@ public MediaSessionCompat(
Looper myLooper = Looper.myLooper();
Handler handler = new Handler(myLooper != null ? myLooper : Looper.getMainLooper());
setCallback(new Callback() {}, handler);
impl.setMediaButtonReceiver(mbrIntent);
if (mbrIntent != null) {
impl.setMediaButtonReceiver(mbrIntent);
}

controller = new MediaControllerCompat(context, this);
}
Expand Down Expand Up @@ -404,7 +386,7 @@ public void setSessionActivity(@Nullable PendingIntent pi) {
*
* @param mbr The {@link PendingIntent} to send the media button event to.
*/
public void setMediaButtonReceiver(PendingIntent mbr) {
public void setMediaButtonReceiver(@Nullable PendingIntent mbr) {
impl.setMediaButtonReceiver(mbr);
}

Expand Down