Skip to content

Commit 4ee6158

Browse files
committed
Make frequently called controller callbacks local binder aware
Especially MediaBrowser will profit from this, as List<MediaItem> no longer has to be bundled if the caller is in the same process.
1 parent 03e9a6b commit 4ee6158

File tree

8 files changed

+121
-6
lines changed

8 files changed

+121
-6
lines changed

libraries/session/src/main/java/androidx/media3/session/LibraryResult.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import static java.lang.annotation.ElementType.TYPE_USE;
2222

2323
import android.annotation.SuppressLint;
24+
import android.os.Binder;
2425
import android.os.Bundle;
2526
import android.os.IBinder;
2627
import android.os.SystemClock;
@@ -336,6 +337,7 @@ private static void verifyMediaItem(MediaItem item) {
336337
private static final String FIELD_VALUE = Util.intToStringMaxRadix(3);
337338
private static final String FIELD_VALUE_TYPE = Util.intToStringMaxRadix(4);
338339
private static final String FIELD_SESSION_ERROR = Util.intToStringMaxRadix(5);
340+
private static final String FIELD_IN_PROCESS_BINDER = Util.intToStringMaxRadix(6);
339341

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

380+
/**
381+
* Returns a {@link Bundle} containing the entirety of this {@link #LibraryResult} object without
382+
* bundling it, for use in local process communication only.
383+
*/
384+
@UnstableApi
385+
public Bundle toBundleForLocalProcess() {
386+
Bundle bundle = new Bundle();
387+
bundle.putBinder(FIELD_IN_PROCESS_BINDER, new InProcessBinder());
388+
return bundle;
389+
}
390+
378391
/** Restores a {@code LibraryResult<Void>} from a {@link Bundle}. */
379392
// fromBundle will throw if the bundle doesn't have the right value type.
380393
@UnstableApi
@@ -413,6 +426,13 @@ public static LibraryResult<?> fromUnknownBundle(Bundle bundle) {
413426
*/
414427
private static LibraryResult<?> fromBundle(
415428
Bundle bundle, @Nullable @ValueType Integer expectedType) {
429+
IBinder inProcessBinder = bundle.getBinder(FIELD_IN_PROCESS_BINDER);
430+
if (inProcessBinder instanceof LibraryResult<?>.InProcessBinder) {
431+
LibraryResult<?> result =
432+
((LibraryResult<?>.InProcessBinder) inProcessBinder).getLibraryResult();
433+
checkState(expectedType == null || expectedType == result.valueType);
434+
return result;
435+
}
416436
int resultCode = bundle.getInt(FIELD_RESULT_CODE, /* defaultValue= */ RESULT_SUCCESS);
417437
long completionTimeMs =
418438
bundle.getLong(FIELD_COMPLETION_TIME_MS, /* defaultValue= */ SystemClock.elapsedRealtime());
@@ -469,4 +489,10 @@ private static LibraryResult<?> fromBundle(
469489

470490
/** The value type isn't known because the result is carrying an error. */
471491
private static final int VALUE_TYPE_ERROR = 4;
492+
493+
private final class InProcessBinder extends Binder {
494+
public LibraryResult<V> getLibraryResult() {
495+
return LibraryResult.this;
496+
}
497+
}
472498
}

libraries/session/src/main/java/androidx/media3/session/MediaControllerImplBase.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2829,7 +2829,12 @@ private void sendControllerResult(int seq, SessionResult result) {
28292829
return;
28302830
}
28312831
try {
2832-
iSession.onControllerResult(controllerStub, seq, result.toBundle());
2832+
iSession.onControllerResult(
2833+
controllerStub,
2834+
seq,
2835+
iSession instanceof MediaSessionStub
2836+
? result.toBundleForLocalProcess()
2837+
: result.toBundle());
28332838
} catch (RemoteException e) {
28342839
Log.w(TAG, "Error in sending");
28352840
}

libraries/session/src/main/java/androidx/media3/session/MediaSessionStub.java

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2080,13 +2080,21 @@ public IBinder getCallbackBinder() {
20802080

20812081
@Override
20822082
public void onSessionResult(int sequenceNumber, SessionResult result) throws RemoteException {
2083-
iController.onSessionResult(sequenceNumber, result.toBundle());
2083+
iController.onSessionResult(
2084+
sequenceNumber,
2085+
iController instanceof MediaControllerStub
2086+
? result.toBundleForLocalProcess()
2087+
: result.toBundle());
20842088
}
20852089

20862090
@Override
20872091
public void onLibraryResult(int sequenceNumber, LibraryResult<?> result)
20882092
throws RemoteException {
2089-
iController.onLibraryResult(sequenceNumber, result.toBundle());
2093+
iController.onLibraryResult(
2094+
sequenceNumber,
2095+
iController instanceof MediaControllerStub
2096+
? result.toBundleForLocalProcess()
2097+
: result.toBundle());
20902098
}
20912099

20922100
@Override
@@ -2221,11 +2229,14 @@ public void onPeriodicSessionPositionInfoChanged(
22212229
boolean canAccessTimeline,
22222230
int controllerInterfaceVersion)
22232231
throws RemoteException {
2232+
SessionPositionInfo filteredPositionInfo =
2233+
sessionPositionInfo.filterByAvailableCommands(
2234+
canAccessCurrentMediaItem, canAccessTimeline);
22242235
iController.onPeriodicSessionPositionInfoChanged(
22252236
sequenceNumber,
2226-
sessionPositionInfo
2227-
.filterByAvailableCommands(canAccessCurrentMediaItem, canAccessTimeline)
2228-
.toBundle(controllerInterfaceVersion));
2237+
iController instanceof MediaControllerStub
2238+
? filteredPositionInfo.toBundleForLocalProcess()
2239+
: filteredPositionInfo.toBundle(controllerInterfaceVersion));
22292240
}
22302241

22312242
@Override

libraries/session/src/main/java/androidx/media3/session/SessionPositionInfo.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717

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

20+
import android.os.Binder;
2021
import android.os.Bundle;
22+
import android.os.IBinder;
2123
import androidx.annotation.Nullable;
2224
import androidx.annotation.VisibleForTesting;
2325
import androidx.media3.common.C;
@@ -169,6 +171,8 @@ public String toString() {
169171
@VisibleForTesting
170172
static final String FIELD_CONTENT_BUFFERED_POSITION_MS = Util.intToStringMaxRadix(9);
171173

174+
private static final String FIELD_IN_PROCESS_BINDER = Util.intToStringMaxRadix(10);
175+
172176
/**
173177
* Returns a copy of this session position info, filtered by the specified available commands.
174178
*
@@ -234,8 +238,18 @@ public Bundle toBundle(int controllerInterfaceVersion) {
234238
return bundle;
235239
}
236240

241+
public Bundle toBundleForLocalProcess() {
242+
Bundle bundle = new Bundle();
243+
bundle.putBinder(FIELD_IN_PROCESS_BINDER, new InProcessBinder());
244+
return bundle;
245+
}
246+
237247
/** Restores a {@code SessionPositionInfo} from a {@link Bundle}. */
238248
public static SessionPositionInfo fromBundle(Bundle bundle) {
249+
IBinder inProcessBinder = bundle.getBinder(FIELD_IN_PROCESS_BINDER);
250+
if (inProcessBinder instanceof InProcessBinder) {
251+
return ((InProcessBinder) inProcessBinder).getSessionPositionInfo();
252+
}
239253
@Nullable Bundle positionInfoBundle = bundle.getBundle(FIELD_POSITION_INFO);
240254
PositionInfo positionInfo =
241255
positionInfoBundle == null
@@ -267,4 +281,10 @@ public static SessionPositionInfo fromBundle(Bundle bundle) {
267281
contentDurationMs,
268282
contentBufferedPositionMs);
269283
}
284+
285+
private final class InProcessBinder extends Binder {
286+
public SessionPositionInfo getSessionPositionInfo() {
287+
return SessionPositionInfo.this;
288+
}
289+
}
270290
}

libraries/session/src/main/java/androidx/media3/session/SessionResult.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@
1919
import static java.lang.annotation.ElementType.TYPE_USE;
2020

2121
import android.annotation.SuppressLint;
22+
import android.os.Binder;
2223
import android.os.Bundle;
24+
import android.os.IBinder;
2325
import android.os.SystemClock;
2426
import androidx.annotation.IntDef;
2527
import androidx.annotation.Nullable;
@@ -241,6 +243,7 @@ private SessionResult(
241243
private static final String FIELD_EXTRAS = Util.intToStringMaxRadix(1);
242244
private static final String FIELD_COMPLETION_TIME_MS = Util.intToStringMaxRadix(2);
243245
private static final String FIELD_SESSION_ERROR = Util.intToStringMaxRadix(3);
246+
private static final String FIELD_IN_PROCESS_BINDER = Util.intToStringMaxRadix(4);
244247

245248
@UnstableApi
246249
public Bundle toBundle() {
@@ -254,9 +257,24 @@ public Bundle toBundle() {
254257
return bundle;
255258
}
256259

260+
/**
261+
* Returns a {@link Bundle} containing the entirety of this {@link #SessionResult} object without
262+
* bundling it, for use in local process communication only.
263+
*/
264+
@UnstableApi
265+
public Bundle toBundleForLocalProcess() {
266+
Bundle bundle = new Bundle();
267+
bundle.putBinder(FIELD_IN_PROCESS_BINDER, new InProcessBinder());
268+
return bundle;
269+
}
270+
257271
/** Restores a {@code SessionResult} from a {@link Bundle}. */
258272
@UnstableApi
259273
public static SessionResult fromBundle(Bundle bundle) {
274+
IBinder inProcessBinder = bundle.getBinder(FIELD_IN_PROCESS_BINDER);
275+
if (inProcessBinder instanceof InProcessBinder) {
276+
return ((InProcessBinder) inProcessBinder).getSessionResult();
277+
}
260278
int resultCode =
261279
bundle.getInt(FIELD_RESULT_CODE, /* defaultValue= */ SessionError.ERROR_UNKNOWN);
262280
@Nullable Bundle extras = bundle.getBundle(FIELD_EXTRAS);
@@ -274,4 +292,10 @@ public static SessionResult fromBundle(Bundle bundle) {
274292
return new SessionResult(
275293
resultCode, extras == null ? Bundle.EMPTY : extras, completionTimeMs, sessionError);
276294
}
295+
296+
private final class InProcessBinder extends Binder {
297+
public SessionResult getSessionResult() {
298+
return SessionResult.this;
299+
}
300+
}
277301
}

libraries/session/src/test/java/androidx/media3/session/LibraryResultTest.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,4 +145,14 @@ public void toBundle_roundTrip_equalsWithOriginal() {
145145
assertThat(errorLibraryResultFromBundle.completionTimeMs)
146146
.isEqualTo(errorLibraryResult.completionTimeMs);
147147
}
148+
149+
@Test
150+
public void roundTripViaBundleForLocalProcess_yieldsSameInstance() {
151+
LibraryResult<SessionError> errorLibraryResult =
152+
LibraryResult.ofError(new SessionError(ERROR_NOT_SUPPORTED, "error message", new Bundle()));
153+
LibraryResult<?> unbundledLibraryResult =
154+
LibraryResult.fromUnknownBundle(errorLibraryResult.toBundleForLocalProcess());
155+
156+
assertThat(errorLibraryResult == unbundledLibraryResult).isTrue();
157+
}
148158
}

libraries/session/src/test/java/androidx/media3/session/SessionPositionInfoTest.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,14 @@ public void roundTripViaBundle_yieldsEqualInstance() {
6060
assertThat(sessionPositionInfo).isEqualTo(testSessionPositionInfo);
6161
}
6262

63+
@Test
64+
public void roundTripViaBundleForLocalProcess_yieldsSameInstance() {
65+
SessionPositionInfo roundTripValue =
66+
SessionPositionInfo.fromBundle(SessionPositionInfo.DEFAULT.toBundleForLocalProcess());
67+
68+
assertThat(SessionPositionInfo.DEFAULT == roundTripValue).isTrue();
69+
}
70+
6371
@Test
6472
public void constructor_invalidIsPlayingAd_throwsIllegalArgumentException() {
6573
Assert.assertThrows(

libraries/session/src/test/java/androidx/media3/session/SessionResultTest.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package androidx.media3.session;
1717

18+
import static androidx.media3.session.SessionError.ERROR_NOT_SUPPORTED;
1819
import static androidx.media3.session.SessionError.ERROR_SESSION_AUTHENTICATION_EXPIRED;
1920
import static androidx.media3.session.SessionError.ERROR_SESSION_CONCURRENT_STREAM_LIMIT;
2021
import static com.google.common.truth.Truth.assertThat;
@@ -72,4 +73,14 @@ public void toBundle_roundTrip_resultsInEqualObjectWithSameBundle() {
7273
assertThat(resultFromBundle.sessionError.extras.getString("errorKey")).isEqualTo("errorValue");
7374
assertThat(resultFromBundle.extras.size()).isEqualTo(0);
7475
}
76+
77+
@Test
78+
public void roundTripViaBundleForLocalProcess_yieldsSameInstance() {
79+
SessionResult errorSessionResult =
80+
new SessionResult(new SessionError(ERROR_NOT_SUPPORTED, "error message", new Bundle()));
81+
SessionResult unbundledSessionResult =
82+
SessionResult.fromBundle(errorSessionResult.toBundleForLocalProcess());
83+
84+
assertThat(errorSessionResult == unbundledSessionResult).isTrue();
85+
}
7586
}

0 commit comments

Comments
 (0)