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 static java.lang.Math.min;
|
||||||
|
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.content.ComponentName;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.content.pm.ResolveInfo;
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.DeadObjectException;
|
import android.os.DeadObjectException;
|
||||||
@ -89,24 +86,12 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
|
|
||||||
/* package */ class MediaSessionImpl {
|
/* 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 =
|
private static final String WRONG_THREAD_ERROR_MESSAGE =
|
||||||
"Player callback method is called from a wrong thread. "
|
"Player callback method is called from a wrong thread. "
|
||||||
+ "See javadoc of MediaSession for details.";
|
+ "See javadoc of MediaSession for details.";
|
||||||
|
|
||||||
private static final long DEFAULT_SESSION_POSITION_UPDATE_DELAY_MS = 3_000;
|
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";
|
public static final String TAG = "MSImplBase";
|
||||||
|
|
||||||
private static final SessionResult RESULT_WHEN_CLOSED = new SessionResult(RESULT_INFO_SKIPPED);
|
private static final SessionResult RESULT_WHEN_CLOSED = new SessionResult(RESULT_INFO_SKIPPED);
|
||||||
@ -198,21 +183,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
sessionStub,
|
sessionStub,
|
||||||
tokenExtras);
|
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 =
|
sessionLegacyStub =
|
||||||
new MediaSessionLegacyStub(
|
new MediaSessionLegacyStub(/* session= */ thisRef, sessionUri, applicationHandler);
|
||||||
/* session= */ thisRef, sessionUri, serviceComponentName, applicationHandler);
|
|
||||||
|
|
||||||
PlayerWrapper playerWrapper = new PlayerWrapper(player);
|
PlayerWrapper playerWrapper = new PlayerWrapper(player);
|
||||||
this.playerWrapper = playerWrapper;
|
this.playerWrapper = playerWrapper;
|
||||||
@ -818,20 +790,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
sessionStub.getConnectedControllersManager().removeController(controller);
|
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() {
|
private void verifyApplicationThread() {
|
||||||
if (Looper.myLooper() != applicationHandler.getLooper()) {
|
if (Looper.myLooper() != applicationHandler.getLooper()) {
|
||||||
throw new IllegalStateException(WRONG_THREAD_ERROR_MESSAGE);
|
throw new IllegalStateException(WRONG_THREAD_ERROR_MESSAGE);
|
||||||
|
@ -136,11 +136,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
|
|||||||
private int sessionFlags;
|
private int sessionFlags;
|
||||||
|
|
||||||
@SuppressWarnings("PendingIntentMutability") // We can't use SaferPendingIntent
|
@SuppressWarnings("PendingIntentMutability") // We can't use SaferPendingIntent
|
||||||
public MediaSessionLegacyStub(
|
public MediaSessionLegacyStub(MediaSessionImpl session, Uri sessionUri, Handler handler) {
|
||||||
MediaSessionImpl session,
|
|
||||||
Uri sessionUri,
|
|
||||||
@Nullable ComponentName serviceComponentName,
|
|
||||||
Handler handler) {
|
|
||||||
sessionImpl = session;
|
sessionImpl = session;
|
||||||
Context context = sessionImpl.getContext();
|
Context context = sessionImpl.getContext();
|
||||||
appPackageName = context.getPackageName();
|
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
|
// Assume an app that intentionally puts a `MediaButtonReceiver` into the manifest has
|
||||||
// implemented some kind of resumption of the last recently played media item.
|
// implemented some kind of resumption of the last recently played media item.
|
||||||
canResumePlaybackOnStart = receiverComponentName != null;
|
canResumePlaybackOnStart = receiverComponentName != null;
|
||||||
|
boolean isReceiverComponentAService = false;
|
||||||
if (receiverComponentName == null) {
|
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);
|
Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON, sessionUri);
|
||||||
PendingIntent mediaButtonIntent;
|
PendingIntent mediaButtonIntent;
|
||||||
@ -181,7 +184,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
|
|||||||
} else {
|
} else {
|
||||||
intent.setComponent(receiverComponentName);
|
intent.setComponent(receiverComponentName);
|
||||||
mediaButtonIntent =
|
mediaButtonIntent =
|
||||||
Objects.equals(serviceComponentName, receiverComponentName)
|
isReceiverComponentAService
|
||||||
? (Util.SDK_INT >= 26
|
? (Util.SDK_INT >= 26
|
||||||
? PendingIntent.getForegroundService(
|
? PendingIntent.getForegroundService(
|
||||||
context, /* requestCode= */ 0, intent, PENDING_INTENT_FLAG_MUTABLE)
|
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();
|
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
|
// TODO(b/193193462): Replace this with androidx.media.session.MediaButtonReceiver
|
||||||
private final class MediaButtonReceiver extends BroadcastReceiver {
|
private final class MediaButtonReceiver extends BroadcastReceiver {
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user