diff options
| -rw-r--r-- | media/java/android/media/IMediaRouter2.aidl | 2 | ||||
| -rw-r--r-- | media/java/android/media/MediaRouter2.java | 127 | ||||
| -rw-r--r-- | services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java | 23 |
3 files changed, 124 insertions, 28 deletions
diff --git a/media/java/android/media/IMediaRouter2.aidl b/media/java/android/media/IMediaRouter2.aidl index a8b82ba401eb..ca14052c964f 100644 --- a/media/java/android/media/IMediaRouter2.aidl +++ b/media/java/android/media/IMediaRouter2.aidl @@ -24,6 +24,8 @@ import android.os.Bundle; * @hide */ oneway interface IMediaRouter2 { + void notifyRouterRegistered(in List<MediaRoute2Info> currentRoutes, + in RoutingSessionInfo currentSystemSessionInfo); void notifyRoutesAdded(in List<MediaRoute2Info> routes); void notifyRoutesRemoved(in List<MediaRoute2Info> routes); void notifyRoutesChanged(in List<MediaRoute2Info> routes); diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java index 6634d4b4190e..20e26cd66e34 100644 --- a/media/java/android/media/MediaRouter2.java +++ b/media/java/android/media/MediaRouter2.java @@ -92,7 +92,7 @@ public final class MediaRouter2 { MediaRouter2Stub mStub; @GuardedBy("sRouterLock") - private final Map<String, RoutingController> mRoutingControllers = new ArrayMap<>(); + private final Map<String, RoutingController> mNonSystemRoutingControllers = new ArrayMap<>(); private final AtomicInteger mControllerCreationRequestCnt = new AtomicInteger(1); @@ -230,7 +230,7 @@ public final class MediaRouter2 { Log.e(TAG, "unregisterRouteCallback: Unable to set discovery request."); } } - if (mRouteCallbackRecords.size() == 0) { + if (mRouteCallbackRecords.isEmpty() && mNonSystemRoutingControllers.isEmpty()) { try { mMediaRouterService.unregisterRouter2(mStub); } catch (RemoteException ex) { @@ -470,7 +470,7 @@ public final class MediaRouter2 { List<RoutingController> result = new ArrayList<>(); result.add(0, mSystemController); synchronized (sRouterLock) { - result.addAll(mRoutingControllers.values()); + result.addAll(mNonSystemRoutingControllers.values()); } return result; } @@ -500,6 +500,77 @@ public final class MediaRouter2 { } } + void syncRoutesOnHandler(List<MediaRoute2Info> currentRoutes, + RoutingSessionInfo currentSystemSessionInfo) { + if (currentRoutes == null || currentRoutes.isEmpty() || currentSystemSessionInfo == null) { + Log.e(TAG, "syncRoutesOnHandler: Received wrong data. currentRoutes=" + currentRoutes + + ", currentSystemSessionInfo=" + currentSystemSessionInfo); + return; + } + + List<MediaRoute2Info> addedRoutes = new ArrayList<>(); + List<MediaRoute2Info> removedRoutes = new ArrayList<>(); + List<MediaRoute2Info> changedRoutes = new ArrayList<>(); + + synchronized (sRouterLock) { + List<String> currentRoutesIds = currentRoutes.stream().map(MediaRoute2Info::getId) + .collect(Collectors.toList()); + + for (String routeId : mRoutes.keySet()) { + if (!currentRoutesIds.contains(routeId)) { + // This route is removed while the callback is unregistered. + MediaRoute2Info route = mRoutes.get(routeId); + if (route.isSystemRoute() + || route.hasAnyFeatures(mDiscoveryPreference.getPreferredFeatures())) { + removedRoutes.add(mRoutes.get(routeId)); + } + } + } + + for (MediaRoute2Info route : currentRoutes) { + if (mRoutes.containsKey(route.getId())) { + if (!route.equals(mRoutes.get(route.getId()))) { + // This route is changed while the callback is unregistered. + if (route.isSystemRoute() + || route.hasAnyFeatures( + mDiscoveryPreference.getPreferredFeatures())) { + changedRoutes.add(route); + } + } + } else { + // This route is added while the callback is unregistered. + if (route.isSystemRoute() + || route.hasAnyFeatures(mDiscoveryPreference.getPreferredFeatures())) { + addedRoutes.add(route); + } + } + } + + mRoutes.clear(); + for (MediaRoute2Info route : currentRoutes) { + mRoutes.put(route.getId(), route); + } + + mShouldUpdateRoutes = true; + } + + if (addedRoutes.size() > 0) { + notifyRoutesAdded(addedRoutes); + } + if (removedRoutes.size() > 0) { + notifyRoutesRemoved(removedRoutes); + } + if (changedRoutes.size() > 0) { + notifyRoutesChanged(changedRoutes); + } + + RoutingSessionInfo oldInfo = mSystemController.getRoutingSessionInfo(); + mSystemController.setRoutingSessionInfo(currentSystemSessionInfo); + if (!oldInfo.equals(currentSystemSessionInfo)) { + notifyControllerUpdated(mSystemController); + } + } + void addRoutesOnHandler(List<MediaRoute2Info> routes) { // TODO(b/157874065): When onRoutesAdded is first called, // 1) clear mRoutes before adding the routes @@ -617,7 +688,7 @@ public final class MediaRouter2 { } else { newController = new RoutingController(sessionInfo); synchronized (sRouterLock) { - mRoutingControllers.put(newController.getId(), newController); + mNonSystemRoutingControllers.put(newController.getId(), newController); } } @@ -645,7 +716,7 @@ public final class MediaRouter2 { RoutingController matchingController; synchronized (sRouterLock) { - matchingController = mRoutingControllers.get(sessionInfo.getId()); + matchingController = mNonSystemRoutingControllers.get(sessionInfo.getId()); } if (matchingController == null) { @@ -674,7 +745,7 @@ public final class MediaRouter2 { final String uniqueSessionId = sessionInfo.getId(); RoutingController matchingController; synchronized (sRouterLock) { - matchingController = mRoutingControllers.get(uniqueSessionId); + matchingController = mNonSystemRoutingControllers.get(uniqueSessionId); } if (matchingController == null) { @@ -1232,23 +1303,34 @@ public final class MediaRouter2 { mIsReleased = true; } - MediaRouter2Stub stub; synchronized (sRouterLock) { - mRoutingControllers.remove(getId(), this); - stub = mStub; - } + if (!mNonSystemRoutingControllers.remove(getId(), this)) { + Log.w(TAG, "releaseInternal: Ignoring unknown controller."); + return false; + } - if (shouldReleaseSession && stub != null) { - try { - mMediaRouterService.releaseSessionWithRouter2(stub, getId()); - } catch (RemoteException ex) { - Log.e(TAG, "Unable to release session", ex); + if (shouldReleaseSession && mStub != null) { + try { + mMediaRouterService.releaseSessionWithRouter2(mStub, getId()); + } catch (RemoteException ex) { + Log.e(TAG, "Unable to release session", ex); + } } - } - if (shouldNotifyStop) { - mHandler.sendMessage(obtainMessage(MediaRouter2::notifyStop, MediaRouter2.this, - RoutingController.this)); + if (shouldNotifyStop) { + mHandler.sendMessage(obtainMessage(MediaRouter2::notifyStop, MediaRouter2.this, + RoutingController.this)); + } + + if (mRouteCallbackRecords.isEmpty() && mNonSystemRoutingControllers.isEmpty() + && mStub != null) { + try { + mMediaRouterService.unregisterRouter2(mStub); + } catch (RemoteException ex) { + Log.e(TAG, "releaseInternal: Unable to unregister media router.", ex); + } + mStub = null; + } } return true; } @@ -1415,6 +1497,13 @@ public final class MediaRouter2 { class MediaRouter2Stub extends IMediaRouter2.Stub { @Override + public void notifyRouterRegistered(List<MediaRoute2Info> currentRoutes, + RoutingSessionInfo currentSystemSessionInfo) { + mHandler.sendMessage(obtainMessage(MediaRouter2::syncRoutesOnHandler, + MediaRouter2.this, currentRoutes, currentSystemSessionInfo)); + } + + @Override public void notifyRoutesAdded(List<MediaRoute2Info> routes) { mHandler.sendMessage(obtainMessage(MediaRouter2::addRoutesOnHandler, MediaRouter2.this, routes)); diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java index 75a89a213052..0e997155e7af 100644 --- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java +++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java @@ -584,7 +584,7 @@ class MediaRouter2ServiceImpl { mAllRouterRecords.put(binder, routerRecord); userRecord.mHandler.sendMessage( - obtainMessage(UserHandler::notifyRoutesToRouter, + obtainMessage(UserHandler::notifyRouterRegistered, userRecord.mHandler, routerRecord)); } @@ -1769,8 +1769,8 @@ class MediaRouter2ServiceImpl { } } - private void notifyRoutesToRouter(@NonNull RouterRecord routerRecord) { - List<MediaRoute2Info> routes = new ArrayList<>(); + private void notifyRouterRegistered(@NonNull RouterRecord routerRecord) { + List<MediaRoute2Info> currentRoutes = new ArrayList<>(); MediaRoute2ProviderInfo systemProviderInfo = null; for (MediaRoute2ProviderInfo providerInfo : mLastProviderInfos) { @@ -1780,27 +1780,32 @@ class MediaRouter2ServiceImpl { systemProviderInfo = providerInfo; continue; } - routes.addAll(providerInfo.getRoutes()); + currentRoutes.addAll(providerInfo.getRoutes()); } + RoutingSessionInfo currentSystemSessionInfo; if (routerRecord.mHasModifyAudioRoutingPermission) { if (systemProviderInfo != null) { - routes.addAll(systemProviderInfo.getRoutes()); + currentRoutes.addAll(systemProviderInfo.getRoutes()); } else { // This shouldn't happen. Slog.w(TAG, "notifyRoutesToRouter: System route provider not found."); } + currentSystemSessionInfo = mSystemProvider.getSessionInfos().get(0); } else { - routes.add(mSystemProvider.getDefaultRoute()); + currentRoutes.add(mSystemProvider.getDefaultRoute()); + currentSystemSessionInfo = mSystemProvider.getDefaultSessionInfo(); } - if (routes.size() == 0) { + if (currentRoutes.size() == 0) { return; } + try { - routerRecord.mRouter.notifyRoutesAdded(routes); + routerRecord.mRouter.notifyRouterRegistered( + currentRoutes, currentSystemSessionInfo); } catch (RemoteException ex) { - Slog.w(TAG, "Failed to notify all routes. Router probably died.", ex); + Slog.w(TAG, "Failed to notify router registered. Router probably died.", ex); } } |