mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Remove static MediaSessionImpl.serviceComponentName
An app must only have a single service in the manifest that is either exposing `MediaLibraryService.SERVICE_INTERFACE` or `MediaSessionService.SERVICE_INTERFACE`. Hence the component name found by querying the package manager for a service never returns a different result when queried again. The static `MediaSessionImpl.serviceComponentName` can hence be removed and the package manager queried again when a second session instance is created. #minor-release PiperOrigin-RevId: 531210456
This commit is contained in:
parent
674885cfa5
commit
1ca9e0024b
@ -24,11 +24,8 @@ import static androidx.media3.session.SessionResult.RESULT_INFO_SKIPPED;
|
||||
import static java.lang.Math.min;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.DeadObjectException;
|
||||
@ -89,24 +86,12 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
|
||||
/* package */ class MediaSessionImpl {
|
||||
|
||||
// Create a static lock for synchronize methods below.
|
||||
// We'd better not use MediaSessionImplBase.class for synchronized(), which indirectly exposes
|
||||
// lock object to the outside of the class.
|
||||
private static final Object STATIC_LOCK = new Object();
|
||||
|
||||
private static final String WRONG_THREAD_ERROR_MESSAGE =
|
||||
"Player callback method is called from a wrong thread. "
|
||||
+ "See javadoc of MediaSession for details.";
|
||||
|
||||
private static final long DEFAULT_SESSION_POSITION_UPDATE_DELAY_MS = 3_000;
|
||||
|
||||
@GuardedBy("STATIC_LOCK")
|
||||
private static boolean componentNamesInitialized = false;
|
||||
|
||||
@GuardedBy("STATIC_LOCK")
|
||||
@Nullable
|
||||
private static ComponentName serviceComponentName;
|
||||
|
||||
public static final String TAG = "MSImplBase";
|
||||
|
||||
private static final SessionResult RESULT_WHEN_CLOSED = new SessionResult(RESULT_INFO_SKIPPED);
|
||||
@ -198,21 +183,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
sessionStub,
|
||||
tokenExtras);
|
||||
|
||||
synchronized (STATIC_LOCK) {
|
||||
if (!componentNamesInitialized) {
|
||||
MediaSessionImpl.serviceComponentName =
|
||||
getServiceComponentByAction(context, MediaLibraryService.SERVICE_INTERFACE);
|
||||
if (MediaSessionImpl.serviceComponentName == null) {
|
||||
MediaSessionImpl.serviceComponentName =
|
||||
getServiceComponentByAction(context, MediaSessionService.SERVICE_INTERFACE);
|
||||
}
|
||||
componentNamesInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
sessionLegacyStub =
|
||||
new MediaSessionLegacyStub(
|
||||
/* session= */ thisRef, sessionUri, serviceComponentName, applicationHandler);
|
||||
new MediaSessionLegacyStub(/* session= */ thisRef, sessionUri, applicationHandler);
|
||||
|
||||
PlayerWrapper playerWrapper = new PlayerWrapper(player);
|
||||
this.playerWrapper = playerWrapper;
|
||||
@ -818,20 +790,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
sessionStub.getConnectedControllersManager().removeController(controller);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@SuppressWarnings("QueryPermissionsNeeded") // Needs to be provided in the app manifest.
|
||||
private static ComponentName getServiceComponentByAction(Context context, String action) {
|
||||
PackageManager pm = context.getPackageManager();
|
||||
Intent queryIntent = new Intent(action);
|
||||
queryIntent.setPackage(context.getPackageName());
|
||||
List<ResolveInfo> resolveInfos = pm.queryIntentServices(queryIntent, /* flags= */ 0);
|
||||
if (resolveInfos == null || resolveInfos.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
ResolveInfo resolveInfo = resolveInfos.get(0);
|
||||
return new ComponentName(resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name);
|
||||
}
|
||||
|
||||
private void verifyApplicationThread() {
|
||||
if (Looper.myLooper() != applicationHandler.getLooper()) {
|
||||
throw new IllegalStateException(WRONG_THREAD_ERROR_MESSAGE);
|
||||
|
@ -136,11 +136,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
|
||||
private int sessionFlags;
|
||||
|
||||
@SuppressWarnings("PendingIntentMutability") // We can't use SaferPendingIntent
|
||||
public MediaSessionLegacyStub(
|
||||
MediaSessionImpl session,
|
||||
Uri sessionUri,
|
||||
@Nullable ComponentName serviceComponentName,
|
||||
Handler handler) {
|
||||
public MediaSessionLegacyStub(MediaSessionImpl session, Uri sessionUri, Handler handler) {
|
||||
sessionImpl = session;
|
||||
Context context = sessionImpl.getContext();
|
||||
appPackageName = context.getPackageName();
|
||||
@ -159,8 +155,15 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
|
||||
// Assume an app that intentionally puts a `MediaButtonReceiver` into the manifest has
|
||||
// implemented some kind of resumption of the last recently played media item.
|
||||
canResumePlaybackOnStart = receiverComponentName != null;
|
||||
boolean isReceiverComponentAService = false;
|
||||
if (receiverComponentName == null) {
|
||||
receiverComponentName = serviceComponentName;
|
||||
receiverComponentName =
|
||||
getServiceComponentByAction(context, MediaLibraryService.SERVICE_INTERFACE);
|
||||
if (receiverComponentName == null) {
|
||||
receiverComponentName =
|
||||
getServiceComponentByAction(context, MediaSessionService.SERVICE_INTERFACE);
|
||||
}
|
||||
isReceiverComponentAService = receiverComponentName != null;
|
||||
}
|
||||
Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON, sessionUri);
|
||||
PendingIntent mediaButtonIntent;
|
||||
@ -181,7 +184,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
|
||||
} else {
|
||||
intent.setComponent(receiverComponentName);
|
||||
mediaButtonIntent =
|
||||
Objects.equals(serviceComponentName, receiverComponentName)
|
||||
isReceiverComponentAService
|
||||
? (Util.SDK_INT >= 26
|
||||
? PendingIntent.getForegroundService(
|
||||
context, /* requestCode= */ 0, intent, PENDING_INTENT_FLAG_MUTABLE)
|
||||
@ -1434,6 +1437,20 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
|
||||
return "Failed to load bitmap: " + throwable.getMessage();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@SuppressWarnings("QueryPermissionsNeeded") // Needs to be provided in the app manifest.
|
||||
private static ComponentName getServiceComponentByAction(Context context, String action) {
|
||||
PackageManager pm = context.getPackageManager();
|
||||
Intent queryIntent = new Intent(action);
|
||||
queryIntent.setPackage(context.getPackageName());
|
||||
List<ResolveInfo> resolveInfos = pm.queryIntentServices(queryIntent, /* flags= */ 0);
|
||||
if (resolveInfos == null || resolveInfos.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
ResolveInfo resolveInfo = resolveInfos.get(0);
|
||||
return new ComponentName(resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name);
|
||||
}
|
||||
|
||||
// TODO(b/193193462): Replace this with androidx.media.session.MediaButtonReceiver
|
||||
private final class MediaButtonReceiver extends BroadcastReceiver {
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user