Add interface version of MediaControllerStub

PiperOrigin-RevId: 463930162
This commit is contained in:
bachinger 2022-07-28 21:45:49 +00:00 committed by tonihei
parent 65a2a3a0a0
commit c8089ead42
11 changed files with 125 additions and 19 deletions

View File

@ -29,7 +29,6 @@ import androidx.media3.session.IMediaSession;
oneway interface IMediaController { oneway interface IMediaController {
// Id < 3000 is reserved to avoid potential collision with media2 1.x. // Id < 3000 is reserved to avoid potential collision with media2 1.x.
void onConnected(int seq, in Bundle connectionResult) = 3000; void onConnected(int seq, in Bundle connectionResult) = 3000;
void onSessionResult(int seq, in Bundle sessionResult) = 3001; void onSessionResult(int seq, in Bundle sessionResult) = 3001;
void onLibraryResult(int seq, in Bundle libraryResult) = 3002; void onLibraryResult(int seq, in Bundle libraryResult) = 3002;

View File

@ -35,7 +35,9 @@ import java.lang.annotation.Target;
*/ */
/* package */ class ConnectionRequest implements Bundleable { /* package */ class ConnectionRequest implements Bundleable {
public final int version; public final int libraryVersion;
public final int controllerInterfaceVersion;
public final String packageName; public final String packageName;
@ -44,11 +46,22 @@ import java.lang.annotation.Target;
public final Bundle connectionHints; public final Bundle connectionHints;
public ConnectionRequest(String packageName, int pid, Bundle connectionHints) { public ConnectionRequest(String packageName, int pid, Bundle connectionHints) {
this(MediaLibraryInfo.VERSION_INT, packageName, pid, new Bundle(connectionHints)); this(
MediaLibraryInfo.VERSION_INT,
MediaControllerStub.VERSION_INT,
packageName,
pid,
new Bundle(connectionHints));
} }
private ConnectionRequest(int version, String packageName, int pid, Bundle connectionHints) { private ConnectionRequest(
this.version = version; int libraryVersion,
int controllerInterfaceVersion,
String packageName,
int pid,
Bundle connectionHints) {
this.libraryVersion = libraryVersion;
this.controllerInterfaceVersion = controllerInterfaceVersion;
this.packageName = packageName; this.packageName = packageName;
this.pid = pid; this.pid = pid;
this.connectionHints = connectionHints; this.connectionHints = connectionHints;
@ -59,34 +72,50 @@ import java.lang.annotation.Target;
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE) @Target(TYPE_USE)
@IntDef({FIELD_VERSION, FIELD_PACKAGE_NAME, FIELD_PID, FIELD_CONNECTION_HINTS}) @IntDef({
FIELD_LIBRARY_VERSION,
FIELD_PACKAGE_NAME,
FIELD_PID,
FIELD_CONNECTION_HINTS,
FIELD_CONTROLLER_INTERFACE_VERSION
})
private @interface FieldNumber {} private @interface FieldNumber {}
private static final int FIELD_VERSION = 0; private static final int FIELD_LIBRARY_VERSION = 0;
private static final int FIELD_PACKAGE_NAME = 1; private static final int FIELD_PACKAGE_NAME = 1;
private static final int FIELD_PID = 2; private static final int FIELD_PID = 2;
private static final int FIELD_CONNECTION_HINTS = 3; private static final int FIELD_CONNECTION_HINTS = 3;
private static final int FIELD_CONTROLLER_INTERFACE_VERSION = 4;
// Next id: 5
@Override @Override
public Bundle toBundle() { public Bundle toBundle() {
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putInt(keyForField(FIELD_VERSION), version); bundle.putInt(keyForField(FIELD_LIBRARY_VERSION), libraryVersion);
bundle.putString(keyForField(FIELD_PACKAGE_NAME), packageName); bundle.putString(keyForField(FIELD_PACKAGE_NAME), packageName);
bundle.putInt(keyForField(FIELD_PID), pid); bundle.putInt(keyForField(FIELD_PID), pid);
bundle.putBundle(keyForField(FIELD_CONNECTION_HINTS), connectionHints); bundle.putBundle(keyForField(FIELD_CONNECTION_HINTS), connectionHints);
bundle.putInt(keyForField(FIELD_CONTROLLER_INTERFACE_VERSION), controllerInterfaceVersion);
return bundle; return bundle;
} }
/** Object that can restore {@link ConnectionRequest} from a {@link Bundle}. */ /** Object that can restore {@link ConnectionRequest} from a {@link Bundle}. */
public static final Creator<ConnectionRequest> CREATOR = public static final Creator<ConnectionRequest> CREATOR =
bundle -> { bundle -> {
int version = bundle.getInt(keyForField(FIELD_VERSION), /* defaultValue= */ 0); int libraryVersion =
bundle.getInt(keyForField(FIELD_LIBRARY_VERSION), /* defaultValue= */ 0);
int controllerInterfaceVersion =
bundle.getInt(keyForField(FIELD_CONTROLLER_INTERFACE_VERSION), /* defaultValue= */ 0);
String packageName = checkNotNull(bundle.getString(keyForField(FIELD_PACKAGE_NAME))); String packageName = checkNotNull(bundle.getString(keyForField(FIELD_PACKAGE_NAME)));
int pid = bundle.getInt(keyForField(FIELD_PID), /* defaultValue= */ 0); int pid = bundle.getInt(keyForField(FIELD_PID), /* defaultValue= */ 0);
checkArgument(pid != 0); checkArgument(pid != 0);
@Nullable Bundle connectionHints = bundle.getBundle(keyForField(FIELD_CONNECTION_HINTS)); @Nullable Bundle connectionHints = bundle.getBundle(keyForField(FIELD_CONNECTION_HINTS));
return new ConnectionRequest( return new ConnectionRequest(
version, packageName, pid, connectionHints == null ? Bundle.EMPTY : connectionHints); libraryVersion,
controllerInterfaceVersion,
packageName,
pid,
connectionHints == null ? Bundle.EMPTY : connectionHints);
}; };
private static String keyForField(@FieldNumber int field) { private static String keyForField(@FieldNumber int field) {

View File

@ -35,6 +35,9 @@ import org.checkerframework.checker.nullness.qual.NonNull;
private static final String TAG = "MediaControllerStub"; private static final String TAG = "MediaControllerStub";
/** The version of the IMediaController interface. */
public static final int VERSION_INT = 1;
private final WeakReference<MediaControllerImplBase> controller; private final WeakReference<MediaControllerImplBase> controller;
public MediaControllerStub(MediaControllerImplBase controller) { public MediaControllerStub(MediaControllerImplBase controller) {

View File

@ -321,6 +321,7 @@ import java.util.concurrent.atomic.AtomicReference;
return new ControllerInfo( return new ControllerInfo(
remoteUserInfo, remoteUserInfo,
ControllerInfo.LEGACY_CONTROLLER_VERSION, ControllerInfo.LEGACY_CONTROLLER_VERSION,
ControllerInfo.LEGACY_CONTROLLER_INTERFACE_VERSION,
getMediaSessionManager().isTrustedForMediaControl(remoteUserInfo), getMediaSessionManager().isTrustedForMediaControl(remoteUserInfo),
new BrowserLegacyCb(remoteUserInfo), new BrowserLegacyCb(remoteUserInfo),
/* connectionHints= */ Bundle.EMPTY); /* connectionHints= */ Bundle.EMPTY);

View File

@ -325,9 +325,12 @@ public class MediaSession {
/** The {@linkplain #getControllerVersion() controller version} of legacy controllers. */ /** The {@linkplain #getControllerVersion() controller version} of legacy controllers. */
public static final int LEGACY_CONTROLLER_VERSION = 0; public static final int LEGACY_CONTROLLER_VERSION = 0;
/** The {@linkplain #getInterfaceVersion()} interface version} of legacy controllers. */
@UnstableApi public static final int LEGACY_CONTROLLER_INTERFACE_VERSION = 0;
private final RemoteUserInfo remoteUserInfo; private final RemoteUserInfo remoteUserInfo;
private final int controllerVersion; private final int libraryVersion;
private final int interfaceVersion;
private final boolean isTrusted; private final boolean isTrusted;
@Nullable private final ControllerCb controllerCb; @Nullable private final ControllerCb controllerCb;
private final Bundle connectionHints; private final Bundle connectionHints;
@ -344,12 +347,14 @@ public class MediaSession {
*/ */
/* package */ ControllerInfo( /* package */ ControllerInfo(
RemoteUserInfo remoteUserInfo, RemoteUserInfo remoteUserInfo,
int controllerVersion, int libraryVersion,
int interfaceVersion,
boolean trusted, boolean trusted,
@Nullable ControllerCb cb, @Nullable ControllerCb cb,
Bundle connectionHints) { Bundle connectionHints) {
this.remoteUserInfo = remoteUserInfo; this.remoteUserInfo = remoteUserInfo;
this.controllerVersion = controllerVersion; this.libraryVersion = libraryVersion;
this.interfaceVersion = interfaceVersion;
isTrusted = trusted; isTrusted = trusted;
controllerCb = cb; controllerCb = cb;
this.connectionHints = connectionHints; this.connectionHints = connectionHints;
@ -366,7 +371,13 @@ public class MediaSession {
* than {@code 1000000} if the controller is a legacy controller. * than {@code 1000000} if the controller is a legacy controller.
*/ */
public int getControllerVersion() { public int getControllerVersion() {
return controllerVersion; return libraryVersion;
}
/** Returns the interface version of the controller, or 0 if it's a legacy controller. */
@UnstableApi
public int getInterfaceVersion() {
return interfaceVersion;
} }
/** /**
@ -459,6 +470,7 @@ public class MediaSession {
return new ControllerInfo( return new ControllerInfo(
legacyRemoteUserInfo, legacyRemoteUserInfo,
ControllerInfo.LEGACY_CONTROLLER_VERSION, ControllerInfo.LEGACY_CONTROLLER_VERSION,
ControllerInfo.LEGACY_CONTROLLER_INTERFACE_VERSION,
/* trusted= */ false, /* trusted= */ false,
/* cb= */ null, /* cb= */ null,
/* connectionHints= */ Bundle.EMPTY); /* connectionHints= */ Bundle.EMPTY);
@ -780,11 +792,19 @@ public class MediaSession {
/* package */ void handleControllerConnectionFromService( /* package */ void handleControllerConnectionFromService(
IMediaController controller, IMediaController controller,
int controllerVersion, int controllerVersion,
int controllerInterfaceVersion,
String packageName, String packageName,
int pid, int pid,
int uid, int uid,
Bundle connectionHints) { Bundle connectionHints) {
impl.connectFromService(controller, controllerVersion, packageName, pid, uid, connectionHints); impl.connectFromService(
controller,
controllerVersion,
controllerInterfaceVersion,
packageName,
pid,
uid,
connectionHints);
} }
/* package */ IBinder getLegacyBrowserServiceBinder() { /* package */ IBinder getLegacyBrowserServiceBinder() {

View File

@ -476,12 +476,19 @@ import org.checkerframework.checker.initialization.qual.Initialized;
public void connectFromService( public void connectFromService(
IMediaController caller, IMediaController caller,
int controllerVersion, int controllerVersion,
int controllerInterfaceVersion,
String packageName, String packageName,
int pid, int pid,
int uid, int uid,
Bundle connectionHints) { Bundle connectionHints) {
sessionStub.connect( sessionStub.connect(
caller, controllerVersion, packageName, pid, uid, checkStateNotNull(connectionHints)); caller,
controllerVersion,
controllerInterfaceVersion,
packageName,
pid,
uid,
checkStateNotNull(connectionHints));
} }
public MediaSessionCompat getSessionCompat() { public MediaSessionCompat getSessionCompat() {

View File

@ -650,6 +650,7 @@ import org.checkerframework.checker.initialization.qual.Initialized;
new ControllerInfo( new ControllerInfo(
remoteUserInfo, remoteUserInfo,
ControllerInfo.LEGACY_CONTROLLER_VERSION, ControllerInfo.LEGACY_CONTROLLER_VERSION,
ControllerInfo.LEGACY_CONTROLLER_INTERFACE_VERSION,
sessionManager.isTrustedForMediaControl(remoteUserInfo), sessionManager.isTrustedForMediaControl(remoteUserInfo),
controllerCb, controllerCb,
/* connectionHints= */ Bundle.EMPTY); /* connectionHints= */ Bundle.EMPTY);

View File

@ -516,7 +516,8 @@ public abstract class MediaSessionService extends Service {
ControllerInfo controllerInfo = ControllerInfo controllerInfo =
new ControllerInfo( new ControllerInfo(
remoteUserInfo, remoteUserInfo,
/* controllerVersion= */ request.version, request.libraryVersion,
request.controllerInterfaceVersion,
isTrusted, isTrusted,
/* cb= */ null, /* cb= */ null,
request.connectionHints); request.connectionHints);
@ -533,7 +534,8 @@ public abstract class MediaSessionService extends Service {
session.handleControllerConnectionFromService( session.handleControllerConnectionFromService(
caller, caller,
request.version, request.libraryVersion,
request.controllerInterfaceVersion,
request.packageName, request.packageName,
pid, pid,
uid, uid,

View File

@ -96,6 +96,7 @@ import java.util.concurrent.atomic.AtomicReference;
return new ControllerInfo( return new ControllerInfo(
info, info,
ControllerInfo.LEGACY_CONTROLLER_VERSION, ControllerInfo.LEGACY_CONTROLLER_VERSION,
ControllerInfo.LEGACY_CONTROLLER_INTERFACE_VERSION,
manager.isTrustedForMediaControl(info), manager.isTrustedForMediaControl(info),
/* cb= */ null, /* cb= */ null,
/* connectionHints= */ Bundle.EMPTY); /* connectionHints= */ Bundle.EMPTY);

View File

@ -369,6 +369,7 @@ import java.util.concurrent.ExecutionException;
public void connect( public void connect(
IMediaController caller, IMediaController caller,
int controllerVersion, int controllerVersion,
int controllerInterfaceVersion,
String callingPackage, String callingPackage,
int pid, int pid,
int uid, int uid,
@ -379,6 +380,7 @@ import java.util.concurrent.ExecutionException;
new ControllerInfo( new ControllerInfo(
remoteUserInfo, remoteUserInfo,
controllerVersion, controllerVersion,
controllerInterfaceVersion,
sessionManager.isTrustedForMediaControl(remoteUserInfo), sessionManager.isTrustedForMediaControl(remoteUserInfo),
new Controller2Cb(caller), new Controller2Cb(caller),
connectionHints); connectionHints);
@ -529,7 +531,14 @@ import java.util.concurrent.ExecutionException;
// If it's the case, use PID from the ConnectionRequest. // If it's the case, use PID from the ConnectionRequest.
int pid = (callingPid != 0) ? callingPid : request.pid; int pid = (callingPid != 0) ? callingPid : request.pid;
try { try {
connect(caller, request.version, request.packageName, pid, uid, request.connectionHints); connect(
caller,
request.libraryVersion,
request.controllerInterfaceVersion,
request.packageName,
pid,
uid,
request.connectionHints);
} finally { } finally {
Binder.restoreCallingIdentity(token); Binder.restoreCallingIdentity(token);
} }

View File

@ -30,6 +30,7 @@ import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import android.text.TextUtils; import android.text.TextUtils;
import androidx.media3.common.MediaItem; import androidx.media3.common.MediaItem;
import androidx.media3.common.MediaLibraryInfo;
import androidx.media3.common.Player; import androidx.media3.common.Player;
import androidx.media3.common.Rating; import androidx.media3.common.Rating;
import androidx.media3.common.StarRating; import androidx.media3.common.StarRating;
@ -50,6 +51,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
@ -94,6 +96,38 @@ public class MediaSessionCallbackTest {
executorService.shutdownNow(); executorService.shutdownNow();
} }
@Test
public void onConnect_correctControllerVersions() throws Exception {
CountDownLatch latch = new CountDownLatch(1);
final AtomicInteger controllerVersion = new AtomicInteger();
final AtomicInteger controllerInterfaceVersion = new AtomicInteger();
MediaSession.Callback callback =
new MediaSession.Callback() {
@Override
public MediaSession.ConnectionResult onConnect(
MediaSession session, ControllerInfo controller) {
controllerVersion.set(controller.getControllerVersion());
controllerInterfaceVersion.set(controller.getInterfaceVersion());
latch.countDown();
return MediaSession.ConnectionResult.accept(
new SessionCommands.Builder().addAllSessionCommands().build(),
new Player.Commands.Builder().addAllCommands().build());
}
};
MediaSession session =
sessionTestRule.ensureReleaseAfterTest(
new MediaSession.Builder(context, player)
.setCallback(callback)
.setId("testOnConnect_correctControllerVersions")
.build());
controllerTestRule.createRemoteController(session.getToken());
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(controllerVersion.get()).isEqualTo(MediaLibraryInfo.VERSION_INT);
assertThat(controllerInterfaceVersion.get()).isEqualTo(MediaControllerStub.VERSION_INT);
}
@Test @Test
public void onPostConnect_afterConnected() throws Exception { public void onPostConnect_afterConnected() throws Exception {
CountDownLatch latch = new CountDownLatch(1); CountDownLatch latch = new CountDownLatch(1);