MediaRouter2: Sync routes when first RouteCallback is registered

Bug: 149526397
Test: Passed CTS and mediaroutertest
      Also checked logs that DEFAULT_ROUTE is not added.
Change-Id: Icc0a5f2ea8f93fd7baba132a9bd4a1f9d798bba9
This commit is contained in:
Hyundo Moon
2020-06-04 18:12:29 +09:00
parent 5c8f3b20d5
commit bc63327359
3 changed files with 125 additions and 29 deletions

View File

@@ -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);

View File

@@ -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 (shouldReleaseSession && stub != null) {
try {
mMediaRouterService.releaseSessionWithRouter2(stub, getId());
} catch (RemoteException ex) {
Log.e(TAG, "Unable to release session", ex);
if (!mNonSystemRoutingControllers.remove(getId(), this)) {
Log.w(TAG, "releaseInternal: Ignoring unknown controller.");
return false;
}
}
if (shouldNotifyStop) {
mHandler.sendMessage(obtainMessage(MediaRouter2::notifyStop, MediaRouter2.this,
RoutingController.this));
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 (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;
}
@@ -1414,6 +1496,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,

View File

@@ -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);
}
}