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 {
// Id < 3000 is reserved to avoid potential collision with media2 1.x.
void onConnected(int seq, in Bundle connectionResult) = 3000;
void onSessionResult(int seq, in Bundle sessionResult) = 3001;
void onLibraryResult(int seq, in Bundle libraryResult) = 3002;

View File

@ -35,7 +35,9 @@ import java.lang.annotation.Target;
*/
/* package */ class ConnectionRequest implements Bundleable {
public final int version;
public final int libraryVersion;
public final int controllerInterfaceVersion;
public final String packageName;
@ -44,11 +46,22 @@ import java.lang.annotation.Target;
public final 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) {
this.version = version;
private ConnectionRequest(
int libraryVersion,
int controllerInterfaceVersion,
String packageName,
int pid,
Bundle connectionHints) {
this.libraryVersion = libraryVersion;
this.controllerInterfaceVersion = controllerInterfaceVersion;
this.packageName = packageName;
this.pid = pid;
this.connectionHints = connectionHints;
@ -59,34 +72,50 @@ import java.lang.annotation.Target;
@Documented
@Retention(RetentionPolicy.SOURCE)
@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 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_PID = 2;
private static final int FIELD_CONNECTION_HINTS = 3;
private static final int FIELD_CONTROLLER_INTERFACE_VERSION = 4;
// Next id: 5
@Override
public Bundle toBundle() {
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.putInt(keyForField(FIELD_PID), pid);
bundle.putBundle(keyForField(FIELD_CONNECTION_HINTS), connectionHints);
bundle.putInt(keyForField(FIELD_CONTROLLER_INTERFACE_VERSION), controllerInterfaceVersion);
return bundle;
}
/** Object that can restore {@link ConnectionRequest} from a {@link Bundle}. */
public static final Creator<ConnectionRequest> CREATOR =
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)));
int pid = bundle.getInt(keyForField(FIELD_PID), /* defaultValue= */ 0);
checkArgument(pid != 0);
@Nullable Bundle connectionHints = bundle.getBundle(keyForField(FIELD_CONNECTION_HINTS));
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) {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -30,6 +30,7 @@ import android.content.Context;
import android.os.Bundle;
import android.text.TextUtils;
import androidx.media3.common.MediaItem;
import androidx.media3.common.MediaLibraryInfo;
import androidx.media3.common.Player;
import androidx.media3.common.Rating;
import androidx.media3.common.StarRating;
@ -50,6 +51,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import org.junit.After;
import org.junit.Before;
@ -94,6 +96,38 @@ public class MediaSessionCallbackTest {
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
public void onPostConnect_afterConnected() throws Exception {
CountDownLatch latch = new CountDownLatch(1);