diff options
8 files changed, 75 insertions, 6 deletions
diff --git a/api/current.txt b/api/current.txt index e3e87607ad7c..5ac58d043660 100644 --- a/api/current.txt +++ b/api/current.txt @@ -26737,6 +26737,7 @@ package android.media { method public int getVolume(); method public int getVolumeHandling(); method public int getVolumeMax(); + method public boolean isSystemRoute(); method public void writeToParcel(@NonNull android.os.Parcel, int); field public static final int CONNECTION_STATE_CONNECTED = 2; // 0x2 field public static final int CONNECTION_STATE_CONNECTING = 1; // 0x1 diff --git a/media/java/android/media/MediaRoute2Info.java b/media/java/android/media/MediaRoute2Info.java index dace09147568..0e88c75e6d25 100644 --- a/media/java/android/media/MediaRoute2Info.java +++ b/media/java/android/media/MediaRoute2Info.java @@ -198,6 +198,7 @@ public final class MediaRoute2Info implements Parcelable { final List<String> mFeatures; @DeviceType final int mDeviceType; + final boolean mIsSystem; final Uri mIconUri; final CharSequence mDescription; @ConnectionState @@ -214,6 +215,7 @@ public final class MediaRoute2Info implements Parcelable { mName = builder.mName; mFeatures = builder.mFeatures; mDeviceType = builder.mDeviceType; + mIsSystem = builder.mIsSystem; mIconUri = builder.mIconUri; mDescription = builder.mDescription; mConnectionState = builder.mConnectionState; @@ -230,6 +232,7 @@ public final class MediaRoute2Info implements Parcelable { mName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); mFeatures = in.createStringArrayList(); mDeviceType = in.readInt(); + mIsSystem = in.readBoolean(); mIconUri = in.readParcelable(null); mDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); mConnectionState = in.readInt(); @@ -288,6 +291,17 @@ public final class MediaRoute2Info implements Parcelable { } /** + * Returns whether the route is a system route or not. + * <p> + * System routes are media routes directly controlled by the system + * such as phone speaker, wired headset, and Bluetooth devices. + * </p> + */ + public boolean isSystemRoute() { + return mIsSystem; + } + + /** * Gets the URI of the icon representing this route. * <p> * This icon will be used in picker UIs if available. @@ -425,6 +439,7 @@ public final class MediaRoute2Info implements Parcelable { && Objects.equals(mName, other.mName) && Objects.equals(mFeatures, other.mFeatures) && (mDeviceType == other.mDeviceType) + && (mIsSystem == other.mIsSystem) && Objects.equals(mIconUri, other.mIconUri) && Objects.equals(mDescription, other.mDescription) && (mConnectionState == other.mConnectionState) @@ -438,7 +453,7 @@ public final class MediaRoute2Info implements Parcelable { @Override public int hashCode() { // Note: mExtras is not included. - return Objects.hash(mId, mName, mFeatures, mDeviceType, mIconUri, mDescription, + return Objects.hash(mId, mName, mFeatures, mDeviceType, mIsSystem, mIconUri, mDescription, mConnectionState, mClientPackageName, mVolumeHandling, mVolumeMax, mVolume, mProviderId); } @@ -475,6 +490,7 @@ public final class MediaRoute2Info implements Parcelable { TextUtils.writeToParcel(mName, dest, flags); dest.writeStringList(mFeatures); dest.writeInt(mDeviceType); + dest.writeBoolean(mIsSystem); dest.writeParcelable(mIconUri, flags); TextUtils.writeToParcel(mDescription, dest, flags); dest.writeInt(mConnectionState); @@ -496,6 +512,7 @@ public final class MediaRoute2Info implements Parcelable { @DeviceType int mDeviceType = DEVICE_TYPE_UNKNOWN; + boolean mIsSystem; Uri mIconUri; CharSequence mDescription; @ConnectionState @@ -542,6 +559,7 @@ public final class MediaRoute2Info implements Parcelable { mName = routeInfo.mName; mFeatures = new ArrayList<>(routeInfo.mFeatures); mDeviceType = routeInfo.mDeviceType; + mIsSystem = routeInfo.mIsSystem; mIconUri = routeInfo.mIconUri; mDescription = routeInfo.mDescription; mConnectionState = routeInfo.mConnectionState; @@ -610,6 +628,16 @@ public final class MediaRoute2Info implements Parcelable { } /** + * Sets whether the route is a system route or not. + * @hide + */ + @NonNull + public Builder setSystemRoute(boolean isSystem) { + mIsSystem = isSystem; + return this; + } + + /** * Sets the URI of the icon representing this route. * <p> * This icon will be used in picker UIs if available. diff --git a/media/java/android/media/MediaRoute2ProviderInfo.java b/media/java/android/media/MediaRoute2ProviderInfo.java index c9a2ec7ed095..afe002edfbcd 100644 --- a/media/java/android/media/MediaRoute2ProviderInfo.java +++ b/media/java/android/media/MediaRoute2ProviderInfo.java @@ -180,6 +180,23 @@ public final class MediaRoute2ProviderInfo implements Parcelable { } /** + * Sets whether the provider provides system routes or not + */ + @NonNull + public Builder setSystemRouteProvider(boolean isSystem) { + int count = mRoutes.size(); + for (int i = 0; i < count; i++) { + MediaRoute2Info route = mRoutes.valueAt(i); + if (route.isSystemRoute() != isSystem) { + mRoutes.setValueAt(i, new MediaRoute2Info.Builder(route) + .setSystemRoute(isSystem) + .build()); + } + } + return this; + } + + /** * Adds a route to the provider */ @NonNull diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java index 7b9a44f71473..f751a22c4900 100644 --- a/media/java/android/media/MediaRouter2.java +++ b/media/java/android/media/MediaRouter2.java @@ -230,7 +230,11 @@ public class MediaRouter2 { /** * Gets the unmodifiable list of {@link MediaRoute2Info routes} currently * known to the media router. + * <p> + * {@link MediaRoute2Info#isSystemRoute() System routes} such as phone speaker, + * Bluetooth devices are always included in the list. * Please note that the list can be changed before callbacks are invoked. + * </p> * * @return the list of routes that contains at least one of the route features in discovery * preferences registered by the application @@ -243,7 +247,8 @@ public class MediaRouter2 { List<MediaRoute2Info> filteredRoutes = new ArrayList<>(); for (MediaRoute2Info route : mRoutes.values()) { - if (route.hasAnyFeatures(mDiscoveryPreference.getPreferredFeatures())) { + if (route.isSystemRoute() + || route.hasAnyFeatures(mDiscoveryPreference.getPreferredFeatures())) { filteredRoutes.add(route); } } @@ -307,12 +312,18 @@ public class MediaRouter2 { * with the given route. * * @param route the route you want to create a controller with. + * @throws IllegalArgumentException if the given route is + * {@link MediaRoute2Info#isSystemRoute() system route} * * @see RoutingControllerCallback#onControllerCreated * @see RoutingControllerCallback#onControllerCreationFailed */ public void requestCreateController(@NonNull MediaRoute2Info route) { Objects.requireNonNull(route, "route must not be null"); + if (route.isSystemRoute()) { + throw new IllegalArgumentException("Can't create a route controller with " + + "a system route. Use getSystemController()."); + } // TODO: Check the given route exists final int requestId; diff --git a/media/java/android/media/MediaRouter2Manager.java b/media/java/android/media/MediaRouter2Manager.java index 61e2f77b7d2e..662eeb1418f1 100644 --- a/media/java/android/media/MediaRouter2Manager.java +++ b/media/java/android/media/MediaRouter2Manager.java @@ -161,14 +161,15 @@ public class MediaRouter2Manager { public List<MediaRoute2Info> getAvailableRoutes(@NonNull String packageName) { Objects.requireNonNull(packageName, "packageName must not be null"); + List<MediaRoute2Info> routes = new ArrayList<>(); + List<String> preferredFeatures = mPreferredFeaturesMap.get(packageName); if (preferredFeatures == null) { - return Collections.emptyList(); + preferredFeatures = Collections.emptyList(); } - List<MediaRoute2Info> routes = new ArrayList<>(); synchronized (mRoutesLock) { for (MediaRoute2Info route : mRoutes.values()) { - if (route.hasAnyFeatures(preferredFeatures)) { + if (route.isSystemRoute() || route.hasAnyFeatures(preferredFeatures)) { routes.add(route); } } diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java index 4a2044af0431..16259ab45792 100644 --- a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java +++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java @@ -196,7 +196,14 @@ public class MediaRouterManagerTest { public void testRouteFeatures() throws Exception { Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(FEATURES_SPECIAL); - assertEquals(1, routes.size()); + int routeCount = 0; + for (MediaRoute2Info route : routes.values()) { + if (!route.isSystemRoute()) { + routeCount++; + } + } + + assertEquals(1, routeCount); assertNotNull(routes.get(ROUTE_ID_SPECIAL_FEATURE)); } diff --git a/services/core/java/com/android/server/media/MediaRoute2Provider.java b/services/core/java/com/android/server/media/MediaRoute2Provider.java index 1cd8aad3f0c5..5123362d84ba 100644 --- a/services/core/java/com/android/server/media/MediaRoute2Provider.java +++ b/services/core/java/com/android/server/media/MediaRoute2Provider.java @@ -36,6 +36,7 @@ abstract class MediaRoute2Provider { final Object mLock = new Object(); Callback mCallback; + boolean mIsSystemRouteProvider; private volatile MediaRoute2ProviderInfo mProviderInfo; @GuardedBy("mLock") @@ -85,6 +86,7 @@ abstract class MediaRoute2Provider { } else { mProviderInfo = new MediaRoute2ProviderInfo.Builder(providerInfo) .setUniqueId(mUniqueId) + .setSystemRouteProvider(mIsSystemRouteProvider) .build(); } } diff --git a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java index 558eb8d05783..924a9b71c8ec 100644 --- a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java +++ b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java @@ -83,6 +83,8 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { super(sComponentName); setCallback(callback); + mIsSystemRouteProvider = true; + mContext = context; mHandler = new Handler(Looper.getMainLooper()); |