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 @@ -21,6 +21,7 @@
import static java.lang.annotation.ElementType.TYPE_USE;

import android.annotation.SuppressLint;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.os.SystemClock;
Expand Down Expand Up @@ -336,6 +337,7 @@ private static void verifyMediaItem(MediaItem item) {
private static final String FIELD_VALUE = Util.intToStringMaxRadix(3);
private static final String FIELD_VALUE_TYPE = Util.intToStringMaxRadix(4);
private static final String FIELD_SESSION_ERROR = Util.intToStringMaxRadix(5);
private static final String FIELD_IN_PROCESS_BINDER = Util.intToStringMaxRadix(6);

// Casting V to ImmutableList<MediaItem> is safe if valueType == VALUE_TYPE_ITEM_LIST.
@SuppressWarnings("unchecked")
Expand Down Expand Up @@ -375,6 +377,17 @@ public Bundle toBundle() {
return bundle;
}

/**
* Returns a {@link Bundle} containing the entirety of this {@link #LibraryResult} object without
* bundling it, for use in local process communication only.
*/
@UnstableApi
public Bundle toBundleForLocalProcess() {
Bundle bundle = new Bundle();
bundle.putBinder(FIELD_IN_PROCESS_BINDER, new InProcessBinder());
return bundle;
}

/** Restores a {@code LibraryResult<Void>} from a {@link Bundle}. */
// fromBundle will throw if the bundle doesn't have the right value type.
@UnstableApi
Expand Down Expand Up @@ -413,6 +426,13 @@ public static LibraryResult<?> fromUnknownBundle(Bundle bundle) {
*/
private static LibraryResult<?> fromBundle(
Bundle bundle, @Nullable @ValueType Integer expectedType) {
IBinder inProcessBinder = bundle.getBinder(FIELD_IN_PROCESS_BINDER);
if (inProcessBinder instanceof LibraryResult<?>.InProcessBinder) {
LibraryResult<?> result =
((LibraryResult<?>.InProcessBinder) inProcessBinder).getLibraryResult();
checkState(expectedType == null || expectedType == result.valueType);
return result;
}
int resultCode = bundle.getInt(FIELD_RESULT_CODE, /* defaultValue= */ RESULT_SUCCESS);
long completionTimeMs =
bundle.getLong(FIELD_COMPLETION_TIME_MS, /* defaultValue= */ SystemClock.elapsedRealtime());
Expand Down Expand Up @@ -469,4 +489,10 @@ private static LibraryResult<?> fromBundle(

/** The value type isn't known because the result is carrying an error. */
private static final int VALUE_TYPE_ERROR = 4;

private final class InProcessBinder extends Binder {
public LibraryResult<V> getLibraryResult() {
return LibraryResult.this;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2829,7 +2829,12 @@ private void sendControllerResult(int seq, SessionResult result) {
return;
}
try {
iSession.onControllerResult(controllerStub, seq, result.toBundle());
iSession.onControllerResult(
controllerStub,
seq,
iSession instanceof MediaSessionStub
? result.toBundleForLocalProcess()
: result.toBundle());
} catch (RemoteException e) {
Log.w(TAG, "Error in sending");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2080,13 +2080,21 @@ public IBinder getCallbackBinder() {

@Override
public void onSessionResult(int sequenceNumber, SessionResult result) throws RemoteException {
iController.onSessionResult(sequenceNumber, result.toBundle());
iController.onSessionResult(
sequenceNumber,
iController instanceof MediaControllerStub
? result.toBundleForLocalProcess()
: result.toBundle());
}

@Override
public void onLibraryResult(int sequenceNumber, LibraryResult<?> result)
throws RemoteException {
iController.onLibraryResult(sequenceNumber, result.toBundle());
iController.onLibraryResult(
sequenceNumber,
iController instanceof MediaControllerStub
? result.toBundleForLocalProcess()
: result.toBundle());
}

@Override
Expand Down Expand Up @@ -2221,11 +2229,14 @@ public void onPeriodicSessionPositionInfoChanged(
boolean canAccessTimeline,
int controllerInterfaceVersion)
throws RemoteException {
SessionPositionInfo filteredPositionInfo =
sessionPositionInfo.filterByAvailableCommands(
canAccessCurrentMediaItem, canAccessTimeline);
iController.onPeriodicSessionPositionInfoChanged(
sequenceNumber,
sessionPositionInfo
.filterByAvailableCommands(canAccessCurrentMediaItem, canAccessTimeline)
.toBundle(controllerInterfaceVersion));
iController instanceof MediaControllerStub
? filteredPositionInfo.toBundleForLocalProcess()
: filteredPositionInfo.toBundle(controllerInterfaceVersion));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@

import static androidx.media3.common.util.Assertions.checkArgument;

import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.media3.common.C;
Expand Down Expand Up @@ -169,6 +171,8 @@ public String toString() {
@VisibleForTesting
static final String FIELD_CONTENT_BUFFERED_POSITION_MS = Util.intToStringMaxRadix(9);

private static final String FIELD_IN_PROCESS_BINDER = Util.intToStringMaxRadix(10);

/**
* Returns a copy of this session position info, filtered by the specified available commands.
*
Expand Down Expand Up @@ -234,8 +238,18 @@ public Bundle toBundle(int controllerInterfaceVersion) {
return bundle;
}

public Bundle toBundleForLocalProcess() {
Bundle bundle = new Bundle();
bundle.putBinder(FIELD_IN_PROCESS_BINDER, new InProcessBinder());
return bundle;
}

/** Restores a {@code SessionPositionInfo} from a {@link Bundle}. */
public static SessionPositionInfo fromBundle(Bundle bundle) {
IBinder inProcessBinder = bundle.getBinder(FIELD_IN_PROCESS_BINDER);
if (inProcessBinder instanceof InProcessBinder) {
return ((InProcessBinder) inProcessBinder).getSessionPositionInfo();
}
@Nullable Bundle positionInfoBundle = bundle.getBundle(FIELD_POSITION_INFO);
PositionInfo positionInfo =
positionInfoBundle == null
Expand Down Expand Up @@ -267,4 +281,10 @@ public static SessionPositionInfo fromBundle(Bundle bundle) {
contentDurationMs,
contentBufferedPositionMs);
}

private final class InProcessBinder extends Binder {
public SessionPositionInfo getSessionPositionInfo() {
return SessionPositionInfo.this;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@
import static java.lang.annotation.ElementType.TYPE_USE;

import android.annotation.SuppressLint;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.os.SystemClock;
import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
Expand Down Expand Up @@ -241,6 +243,7 @@ private SessionResult(
private static final String FIELD_EXTRAS = Util.intToStringMaxRadix(1);
private static final String FIELD_COMPLETION_TIME_MS = Util.intToStringMaxRadix(2);
private static final String FIELD_SESSION_ERROR = Util.intToStringMaxRadix(3);
private static final String FIELD_IN_PROCESS_BINDER = Util.intToStringMaxRadix(4);

@UnstableApi
public Bundle toBundle() {
Expand All @@ -254,9 +257,24 @@ public Bundle toBundle() {
return bundle;
}

/**
* Returns a {@link Bundle} containing the entirety of this {@link #SessionResult} object without
* bundling it, for use in local process communication only.
*/
@UnstableApi
public Bundle toBundleForLocalProcess() {
Bundle bundle = new Bundle();
bundle.putBinder(FIELD_IN_PROCESS_BINDER, new InProcessBinder());
return bundle;
}

/** Restores a {@code SessionResult} from a {@link Bundle}. */
@UnstableApi
public static SessionResult fromBundle(Bundle bundle) {
IBinder inProcessBinder = bundle.getBinder(FIELD_IN_PROCESS_BINDER);
if (inProcessBinder instanceof InProcessBinder) {
return ((InProcessBinder) inProcessBinder).getSessionResult();
}
int resultCode =
bundle.getInt(FIELD_RESULT_CODE, /* defaultValue= */ SessionError.ERROR_UNKNOWN);
@Nullable Bundle extras = bundle.getBundle(FIELD_EXTRAS);
Expand All @@ -274,4 +292,10 @@ public static SessionResult fromBundle(Bundle bundle) {
return new SessionResult(
resultCode, extras == null ? Bundle.EMPTY : extras, completionTimeMs, sessionError);
}

private final class InProcessBinder extends Binder {
public SessionResult getSessionResult() {
return SessionResult.this;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -145,4 +145,14 @@ public void toBundle_roundTrip_equalsWithOriginal() {
assertThat(errorLibraryResultFromBundle.completionTimeMs)
.isEqualTo(errorLibraryResult.completionTimeMs);
}

@Test
public void roundTripViaBundleForLocalProcess_yieldsSameInstance() {
LibraryResult<SessionError> errorLibraryResult =
LibraryResult.ofError(new SessionError(ERROR_NOT_SUPPORTED, "error message", new Bundle()));
LibraryResult<?> unbundledLibraryResult =
LibraryResult.fromUnknownBundle(errorLibraryResult.toBundleForLocalProcess());

assertThat(errorLibraryResult == unbundledLibraryResult).isTrue();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,14 @@ public void roundTripViaBundle_yieldsEqualInstance() {
assertThat(sessionPositionInfo).isEqualTo(testSessionPositionInfo);
}

@Test
public void roundTripViaBundleForLocalProcess_yieldsSameInstance() {
SessionPositionInfo roundTripValue =
SessionPositionInfo.fromBundle(SessionPositionInfo.DEFAULT.toBundleForLocalProcess());

assertThat(SessionPositionInfo.DEFAULT == roundTripValue).isTrue();
}

@Test
public void constructor_invalidIsPlayingAd_throwsIllegalArgumentException() {
Assert.assertThrows(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package androidx.media3.session;

import static androidx.media3.session.SessionError.ERROR_NOT_SUPPORTED;
import static androidx.media3.session.SessionError.ERROR_SESSION_AUTHENTICATION_EXPIRED;
import static androidx.media3.session.SessionError.ERROR_SESSION_CONCURRENT_STREAM_LIMIT;
import static com.google.common.truth.Truth.assertThat;
Expand Down Expand Up @@ -72,4 +73,14 @@ public void toBundle_roundTrip_resultsInEqualObjectWithSameBundle() {
assertThat(resultFromBundle.sessionError.extras.getString("errorKey")).isEqualTo("errorValue");
assertThat(resultFromBundle.extras.size()).isEqualTo(0);
}

@Test
public void roundTripViaBundleForLocalProcess_yieldsSameInstance() {
SessionResult errorSessionResult =
new SessionResult(new SessionError(ERROR_NOT_SUPPORTED, "error message", new Bundle()));
SessionResult unbundledSessionResult =
SessionResult.fromBundle(errorSessionResult.toBundleForLocalProcess());

assertThat(errorSessionResult == unbundledSessionResult).isTrue();
}
}