Skip to content

Commit 01ef27a

Browse files
committed
Asynchronously connect to media3 controllers
1 parent ec6ac47 commit 01ef27a

File tree

4 files changed

+84
-67
lines changed

4 files changed

+84
-67
lines changed

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

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424

2525
import android.content.Context;
2626
import android.os.Bundle;
27-
import android.os.Handler;
2827
import android.os.Looper;
2928
import androidx.annotation.IntRange;
3029
import androidx.annotation.Nullable;
@@ -208,18 +207,17 @@ public ListenableFuture<MediaBrowser> buildAsync() {
208207
if (token.isLegacySession() && bitmapLoader == null) {
209208
bitmapLoader = new CacheBitmapLoader(new DataSourceBitmapLoader(context));
210209
}
211-
MediaBrowser browser =
212-
new MediaBrowser(
213-
context,
214-
token,
215-
connectionHints,
216-
listener,
217-
applicationLooper,
218-
holder,
219-
bitmapLoader,
220-
maxCommandsForMediaItems,
221-
platformSessionCallbackAggregationTimeoutMs);
222-
postOrRun(new Handler(applicationLooper), () -> holder.setController(browser));
210+
new MediaBrowser(
211+
context,
212+
token,
213+
connectionHints,
214+
listener,
215+
applicationLooper,
216+
holder,
217+
bitmapLoader,
218+
maxCommandsForMediaItems,
219+
platformSessionCallbackAggregationTimeoutMs,
220+
holder::setController);
223221
return holder;
224222
}
225223
}
@@ -289,7 +287,8 @@ default void onSearchResultChanged(
289287
ConnectionCallback connectionCallback,
290288
@Nullable BitmapLoader bitmapLoader,
291289
int maxCommandsForMediaItems,
292-
long platformSessionCallbackAggregationTimeoutMs) {
290+
long platformSessionCallbackAggregationTimeoutMs,
291+
Consumer<MediaBrowser> onConnectedAsyncCallback) {
293292
super(
294293
context,
295294
token,
@@ -299,7 +298,8 @@ default void onSearchResultChanged(
299298
connectionCallback,
300299
bitmapLoader,
301300
maxCommandsForMediaItems,
302-
platformSessionCallbackAggregationTimeoutMs);
301+
platformSessionCallbackAggregationTimeoutMs,
302+
controller -> onConnectedAsyncCallback.accept((MediaBrowser) controller));
303303
}
304304

305305
@Override

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

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -377,18 +377,17 @@ public ListenableFuture<MediaController> buildAsync() {
377377
if (token.isLegacySession() && bitmapLoader == null) {
378378
bitmapLoader = new CacheBitmapLoader(new DataSourceBitmapLoader(context));
379379
}
380-
MediaController controller =
381-
new MediaController(
382-
context,
383-
token,
384-
connectionHints,
385-
listener,
386-
applicationLooper,
387-
holder,
388-
bitmapLoader,
389-
maxCommandsForMediaItems,
390-
platformSessionCallbackAggregationTimeoutMs);
391-
postOrRun(new Handler(applicationLooper), () -> holder.setController(controller));
380+
new MediaController(
381+
context,
382+
token,
383+
connectionHints,
384+
listener,
385+
applicationLooper,
386+
holder,
387+
bitmapLoader,
388+
maxCommandsForMediaItems,
389+
platformSessionCallbackAggregationTimeoutMs,
390+
holder::setController);
392391
return holder;
393392
}
394393
}
@@ -603,7 +602,8 @@ default void onError(MediaController controller, SessionError sessionError) {}
603602
ConnectionCallback connectionCallback,
604603
@Nullable BitmapLoader bitmapLoader,
605604
int maxCommandsForMediaItems,
606-
long platformSessionCallbackAggregationTimeoutMs) {
605+
long platformSessionCallbackAggregationTimeoutMs,
606+
Consumer<MediaController> onConnectedAsyncCallback) {
607607
checkNotNull(context, "context must not be null");
608608
checkNotNull(token, "token must not be null");
609609
Log.i(
@@ -634,7 +634,7 @@ default void onError(MediaController controller, SessionError sessionError) {}
634634
applicationLooper,
635635
bitmapLoader,
636636
platformSessionCallbackAggregationTimeoutMs);
637-
impl.connect();
637+
impl.connect(() -> postOrRun(applicationHandler, () -> onConnectedAsyncCallback.accept(this)));
638638
}
639639

640640
/* package */ @UnderInitialization
@@ -2227,7 +2227,7 @@ private void verifyApplicationThread() {
22272227

22282228
/* package */ interface MediaControllerImpl {
22292229

2230-
void connect(@UnderInitialization MediaControllerImpl this);
2230+
void connect(@UnderInitialization MediaControllerImpl this, Runnable callback);
22312231

22322232
Bundle getConnectionHints();
22332233

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

Lines changed: 52 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,10 @@
7777
import androidx.media3.common.Tracks;
7878
import androidx.media3.common.VideoSize;
7979
import androidx.media3.common.text.CueGroup;
80+
import androidx.media3.common.util.BackgroundExecutor;
8081
import androidx.media3.common.util.BundleCollectionUtil;
8182
import androidx.media3.common.util.Clock;
83+
import androidx.media3.common.util.Consumer;
8284
import androidx.media3.common.util.ListenerSet;
8385
import androidx.media3.common.util.Log;
8486
import androidx.media3.common.util.Size;
@@ -209,18 +211,21 @@ public MediaControllerImplBase(
209211
}
210212

211213
@Override
212-
public void connect(@UnderInitialization MediaControllerImplBase this) {
213-
boolean connectionRequested;
214+
public void connect(@UnderInitialization MediaControllerImplBase this, Runnable callback) {
215+
Consumer<Boolean> onConnectionRequested =
216+
connectionRequested -> {
217+
if (!connectionRequested) {
218+
getInstance().runOnApplicationLooper(getInstance()::release);
219+
}
220+
callback.run();
221+
};
214222
if (this.token.getType() == SessionToken.TYPE_SESSION) {
215223
// Session
216224
serviceConnection = null;
217-
connectionRequested = requestConnectToSession(connectionHints);
225+
requestConnectToSession(connectionHints, onConnectionRequested);
218226
} else {
219227
serviceConnection = new SessionServiceConnection(connectionHints);
220-
connectionRequested = requestConnectToService();
221-
}
222-
if (!connectionRequested) {
223-
getInstance().runOnApplicationLooper(getInstance()::release);
228+
requestConnectToService(onConnectionRequested);
224229
}
225230
}
226231

@@ -2618,7 +2623,7 @@ private void notifyPlayerInfoListenersWithReasons(
26182623
listeners.flushEvents();
26192624
}
26202625

2621-
private boolean requestConnectToService() {
2626+
private void requestConnectToService(Consumer<Boolean> onConnectionRequested) {
26222627
int flags =
26232628
SDK_INT >= 29
26242629
? Context.BIND_AUTO_CREATE | Context.BIND_INCLUDE_CAPABILITIES
@@ -2642,34 +2647,45 @@ private boolean requestConnectToService() {
26422647
// If a service wants to keep running, it should be either foreground service or
26432648
// bound service. But there had been request for the feature for system apps
26442649
// and using bindService() will be better fit with it.
2645-
try {
2646-
if (context.bindService(intent, serviceConnection, flags)) {
2647-
return true;
2648-
}
2649-
Log.w(TAG, "bind to " + token + " failed");
2650-
} catch (SecurityException e) {
2651-
Log.w(TAG, "bind to " + token + " not allowed", e);
2652-
}
2653-
return false;
2654-
}
2655-
2656-
private boolean requestConnectToSession(Bundle connectionHints) {
2657-
IMediaSession iSession =
2658-
IMediaSession.Stub.asInterface((IBinder) checkStateNotNull(token.getBinder()));
2659-
int seq = sequencedFutureManager.obtainNextSequenceNumber();
2660-
ConnectionRequest request =
2661-
new ConnectionRequest(
2662-
context.getPackageName(),
2663-
Process.myPid(),
2664-
connectionHints,
2665-
instance.getMaxCommandsForMediaItems());
2666-
try {
2667-
iSession.connect(controllerStub, seq, request.toBundle());
2668-
} catch (RemoteException e) {
2669-
Log.w(TAG, "Failed to call connection request.", e);
2670-
return false;
2671-
}
2672-
return true;
2650+
BackgroundExecutor.get()
2651+
.execute(
2652+
() -> {
2653+
try {
2654+
if (context.bindService(intent, serviceConnection, flags)) {
2655+
onConnectionRequested.accept(true);
2656+
return;
2657+
}
2658+
Log.w(TAG, "bind to " + token + " failed");
2659+
} catch (SecurityException e) {
2660+
Log.w(TAG, "bind to " + token + " not allowed", e);
2661+
}
2662+
onConnectionRequested.accept(false);
2663+
});
2664+
}
2665+
2666+
private void requestConnectToSession(
2667+
Bundle connectionHints, Consumer<Boolean> onConnectionRequested) {
2668+
BackgroundExecutor.get()
2669+
.execute(
2670+
() -> {
2671+
IMediaSession iSession =
2672+
IMediaSession.Stub.asInterface((IBinder) checkStateNotNull(token.getBinder()));
2673+
int seq = sequencedFutureManager.obtainNextSequenceNumber();
2674+
ConnectionRequest request =
2675+
new ConnectionRequest(
2676+
context.getPackageName(),
2677+
Process.myPid(),
2678+
connectionHints,
2679+
instance.getMaxCommandsForMediaItems());
2680+
try {
2681+
iSession.connect(controllerStub, seq, request.toBundle());
2682+
} catch (RemoteException e) {
2683+
Log.w(TAG, "Failed to call connection request.", e);
2684+
onConnectionRequested.accept(false);
2685+
return;
2686+
}
2687+
onConnectionRequested.accept(true);
2688+
});
26732689
}
26742690

26752691
private void clearSurfacesAndCallbacks() {

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,12 +155,13 @@ public MediaControllerImplLegacy(
155155
}
156156

157157
@Override
158-
public void connect(@UnderInitialization MediaControllerImplLegacy this) {
158+
public void connect(@UnderInitialization MediaControllerImplLegacy this, Runnable callback) {
159159
if (this.token.getType() == SessionToken.TYPE_SESSION) {
160160
connectToSession((MediaSessionCompat.Token) checkStateNotNull(this.token.getBinder()));
161161
} else {
162162
connectToService();
163163
}
164+
callback.run();
164165
}
165166

166167
@Override

0 commit comments

Comments
 (0)