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 @@ -24,6 +24,7 @@

import androidx.mediarouter.media.MediaControlIntent;
import androidx.mediarouter.media.MediaRouteSelector;
import androidx.mediarouter.media.MediaRouter;

import com.google.android.gms.cast.CastMediaControlIntent;
import com.google.android.gms.cast.framework.CastOptions;
Expand Down Expand Up @@ -64,13 +65,38 @@ public CastContextImpl(IObjectWrapper context, CastOptions options, IMediaRouter
String defaultCategory = CastMediaControlIntent.categoryForCast(receiverApplicationId);

this.defaultSessionProvider = this.sessionProviders.get(defaultCategory);
if (this.defaultSessionProvider == null) {
// The provider map can be keyed by the full control category, which carries extra
// namespace/flag suffixes (e.g. ".../CC1AD845///ALLOW_IPV6"), rather than the bare
// categoryForCast(appId). Fall back to matching by category prefix.
for (Map.Entry<String, ISessionProvider> entry : this.sessionProviders.entrySet()) {
if (entry.getKey() != null && entry.getKey().startsWith(defaultCategory)) {
this.defaultSessionProvider = entry.getValue();
break;
}
}
}

// TODO: This should incorporate passed options
this.mergedSelector = new MediaRouteSelector.Builder()
.addControlCategory(MediaControlIntent.CATEGORY_LIVE_VIDEO)
.addControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)
.addControlCategory(defaultCategory)
.build();

// Observe route selection so that choosing a Cast route actually starts a session.
// This goes through the app's MediaRouterProxy (IMediaRouter), which runs androidx
// MediaRouter in the app process; touching MediaRouter directly from the dynamite would
// fail with a Resources$NotFoundException. On selection the app invokes
// MediaRouterCallbackImpl.onRouteSelected(), which starts the session.
try {
this.router.registerMediaRouterCallbackImpl(this.mergedSelector.asBundle(),
new MediaRouterCallbackImpl(this));
this.router.addCallback(this.mergedSelector.asBundle(),
MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY);
} catch (RemoteException e) {
Log.w(TAG, "Failed to register media router callback: " + e.getMessage());
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,18 @@ public void onRouteRemoved(String routeId, Bundle extras) {
@Override
public void onRouteSelected(String routeId, Bundle extras) throws RemoteException {
CastDevice castDevice = CastDevice.getFromBundle(extras);

SessionImpl session = (SessionImpl) ObjectWrapper.unwrap(this.castContext.defaultSessionProvider.getSession(null));
Bundle routeInfoExtras = this.castContext.getRouter().getRouteInfoExtrasById(routeId);
if (routeInfoExtras != null) {
session.start(this.castContext, castDevice, routeId, routeInfoExtras);
if (this.castContext.defaultSessionProvider == null) {
Log.w(TAG, "No session provider for selected route " + routeId + "; cannot start session");
return;
}
Object session = ObjectWrapper.unwrap(this.castContext.defaultSessionProvider.getSession(null));
if (!(session instanceof SessionImpl)) {
Log.w(TAG, "Session provider did not yield a SessionImpl for route " + routeId);
return;
}
Bundle routeInfoExtras = this.castContext.getRouter().getRouteInfoExtrasById(routeId);
((SessionImpl) session).start(this.castContext, castDevice, routeId,
routeInfoExtras != null ? routeInfoExtras : extras);
}
@Override
public void unknown(String routeId, Bundle extras) {
Expand Down