summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--media/java/android/media/MediaRoute2Info.java181
-rw-r--r--media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java8
-rw-r--r--media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2Test.java96
-rw-r--r--media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java19
4 files changed, 284 insertions, 20 deletions
diff --git a/media/java/android/media/MediaRoute2Info.java b/media/java/android/media/MediaRoute2Info.java
index 7008d32fd574..d919d78a8c08 100644
--- a/media/java/android/media/MediaRoute2Info.java
+++ b/media/java/android/media/MediaRoute2Info.java
@@ -16,13 +16,17 @@
package android.media;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.net.Uri;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@@ -46,6 +50,34 @@ public final class MediaRoute2Info implements Parcelable {
}
};
+ /** @hide */
+ @IntDef({CONNECTION_STATE_DISCONNECTED, CONNECTION_STATE_CONNECTING,
+ CONNECTION_STATE_CONNECTED})
+ @Retention(RetentionPolicy.SOURCE)
+ private @interface ConnectionState {}
+
+ /**
+ * The default connection state indicating the route is disconnected.
+ *
+ * @see #getConnectionState
+ */
+ public static final int CONNECTION_STATE_DISCONNECTED = 0;
+
+ /**
+ * A connection state indicating the route is in the process of connecting and is not yet
+ * ready for use.
+ *
+ * @see #getConnectionState
+ */
+ public static final int CONNECTION_STATE_CONNECTING = 1;
+
+ /**
+ * A connection state indicating the route is connected.
+ *
+ * @see #getConnectionState
+ */
+ public static final int CONNECTION_STATE_CONNECTED = 2;
+
/**
* Playback information indicating the playback volume is fixed, i.e. it cannot be
* controlled from this object. An example of fixed playback volume is a remote player,
@@ -61,6 +93,46 @@ public final class MediaRoute2Info implements Parcelable {
*/
public static final int PLAYBACK_VOLUME_VARIABLE = 1;
+ /** @hide */
+ @IntDef({
+ DEVICE_TYPE_UNKNOWN, DEVICE_TYPE_TV,
+ DEVICE_TYPE_SPEAKER, DEVICE_TYPE_BLUETOOTH})
+ @Retention(RetentionPolicy.SOURCE)
+ private @interface DeviceType {}
+
+ /**
+ * The default receiver device type of the route indicating the type is unknown.
+ *
+ * @see #getDeviceType
+ * @hide
+ */
+ public static final int DEVICE_TYPE_UNKNOWN = 0;
+
+ /**
+ * A receiver device type of the route indicating the presentation of the media is happening
+ * on a TV.
+ *
+ * @see #getDeviceType
+ */
+ public static final int DEVICE_TYPE_TV = 1;
+
+ /**
+ * A receiver device type of the route indicating the presentation of the media is happening
+ * on a speaker.
+ *
+ * @see #getDeviceType
+ */
+ public static final int DEVICE_TYPE_SPEAKER = 2;
+
+ /**
+ * A receiver device type of the route indicating the presentation of the media is happening
+ * on a bluetooth device such as a bluetooth speaker.
+ *
+ * @see #getDeviceType
+ * @hide
+ */
+ public static final int DEVICE_TYPE_BLUETOOTH = 3;
+
@NonNull
final String mId;
@Nullable
@@ -70,12 +142,17 @@ public final class MediaRoute2Info implements Parcelable {
@Nullable
final CharSequence mDescription;
@Nullable
+ final @ConnectionState int mConnectionState;
+ @Nullable
+ final Uri mIconUri;
+ @Nullable
final String mClientPackageName;
@NonNull
final List<String> mSupportedCategories;
final int mVolume;
final int mVolumeMax;
final int mVolumeHandling;
+ final @DeviceType int mDeviceType;
@Nullable
final Bundle mExtras;
@@ -86,11 +163,14 @@ public final class MediaRoute2Info implements Parcelable {
mProviderId = builder.mProviderId;
mName = builder.mName;
mDescription = builder.mDescription;
+ mConnectionState = builder.mConnectionState;
+ mIconUri = builder.mIconUri;
mClientPackageName = builder.mClientPackageName;
mSupportedCategories = builder.mSupportedCategories;
mVolume = builder.mVolume;
mVolumeMax = builder.mVolumeMax;
mVolumeHandling = builder.mVolumeHandling;
+ mDeviceType = builder.mDeviceType;
mExtras = builder.mExtras;
mUniqueId = createUniqueId();
}
@@ -100,11 +180,14 @@ public final class MediaRoute2Info implements Parcelable {
mProviderId = in.readString();
mName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
mDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+ mConnectionState = in.readInt();
+ mIconUri = in.readParcelable(null);
mClientPackageName = in.readString();
mSupportedCategories = in.createStringArrayList();
mVolume = in.readInt();
mVolumeMax = in.readInt();
mVolumeHandling = in.readInt();
+ mDeviceType = in.readInt();
mExtras = in.readBundle();
mUniqueId = createUniqueId();
}
@@ -145,18 +228,22 @@ public final class MediaRoute2Info implements Parcelable {
&& Objects.equals(mProviderId, other.mProviderId)
&& Objects.equals(mName, other.mName)
&& Objects.equals(mDescription, other.mDescription)
+ && (mConnectionState == other.mConnectionState)
+ && Objects.equals(mIconUri, other.mIconUri)
&& Objects.equals(mClientPackageName, other.mClientPackageName)
&& Objects.equals(mSupportedCategories, other.mSupportedCategories)
&& (mVolume == other.mVolume)
&& (mVolumeMax == other.mVolumeMax)
&& (mVolumeHandling == other.mVolumeHandling)
+ && (mDeviceType == other.mDeviceType)
//TODO: This will be evaluated as false in most cases. Try not to.
&& Objects.equals(mExtras, other.mExtras);
}
@Override
public int hashCode() {
- return Objects.hash(mId, mName, mDescription, mSupportedCategories);
+ return Objects.hash(mId, mName, mDescription, mConnectionState, mIconUri,
+ mSupportedCategories, mVolume, mVolumeMax, mVolumeHandling, mDeviceType);
}
/**
@@ -204,6 +291,29 @@ public final class MediaRoute2Info implements Parcelable {
}
/**
+ * Gets the connection state of the route.
+ *
+ * @return The connection state of this route: {@link #CONNECTION_STATE_DISCONNECTED},
+ * {@link #CONNECTION_STATE_CONNECTING}, or {@link #CONNECTION_STATE_CONNECTED}.
+ */
+ @ConnectionState
+ public int getConnectionState() {
+ return mConnectionState;
+ }
+
+ /**
+ * Gets the URI of the icon representing this route.
+ * <p>
+ * This icon will be used in picker UIs if available.
+ *
+ * @return The URI of the icon representing this route, or null if none.
+ */
+ @Nullable
+ public Uri getIconUri() {
+ return mIconUri;
+ }
+
+ /**
* Gets the package name of the client that uses the route.
* Returns null if no clients use this.
* @hide
@@ -221,6 +331,18 @@ public final class MediaRoute2Info implements Parcelable {
return mSupportedCategories;
}
+ //TODO: once device types are confirmed, reflect those into the comment.
+ /**
+ * Gets the type of the receiver device associated with this route.
+ *
+ * @return The type of the receiver device associated with this route:
+ * {@link #DEVICE_TYPE_TV} or {@link #DEVICE_TYPE_SPEAKER}.
+ */
+ @DeviceType
+ public int getDeviceType() {
+ return mDeviceType;
+ }
+
/**
* Gets the current volume of the route. This may be invalid if the route is not selected.
*/
@@ -293,11 +415,14 @@ public final class MediaRoute2Info implements Parcelable {
dest.writeString(mProviderId);
TextUtils.writeToParcel(mName, dest, flags);
TextUtils.writeToParcel(mDescription, dest, flags);
+ dest.writeInt(mConnectionState);
+ dest.writeParcelable(mIconUri, flags);
dest.writeString(mClientPackageName);
dest.writeStringList(mSupportedCategories);
dest.writeInt(mVolume);
dest.writeInt(mVolumeMax);
dest.writeInt(mVolumeHandling);
+ dest.writeInt(mDeviceType);
dest.writeBundle(mExtras);
}
@@ -308,9 +433,12 @@ public final class MediaRoute2Info implements Parcelable {
.append("id=").append(getId())
.append(", name=").append(getName())
.append(", description=").append(getDescription())
+ .append(", connectionState=").append(getConnectionState())
+ .append(", iconUri=").append(getIconUri())
.append(", volume=").append(getVolume())
.append(", volumeMax=").append(getVolumeMax())
.append(", volumeHandling=").append(getVolumeHandling())
+ .append(", deviceType=").append(getDeviceType())
.append(", providerId=").append(getProviderId())
.append(" }");
return result.toString();
@@ -324,11 +452,16 @@ public final class MediaRoute2Info implements Parcelable {
String mProviderId;
CharSequence mName;
CharSequence mDescription;
+ @ConnectionState
+ int mConnectionState;
+ Uri mIconUri;
String mClientPackageName;
List<String> mSupportedCategories;
int mVolume;
int mVolumeMax;
int mVolumeHandling = PLAYBACK_VOLUME_FIXED;
+ @DeviceType
+ int mDeviceType = DEVICE_TYPE_UNKNOWN;
Bundle mExtras;
public Builder(@NonNull String id, @NonNull CharSequence name) {
@@ -348,11 +481,14 @@ public final class MediaRoute2Info implements Parcelable {
}
setName(routeInfo.mName);
mDescription = routeInfo.mDescription;
+ mConnectionState = routeInfo.mConnectionState;
+ mIconUri = routeInfo.mIconUri;
setClientPackageName(routeInfo.mClientPackageName);
setSupportedCategories(routeInfo.mSupportedCategories);
setVolume(routeInfo.mVolume);
setVolumeMax(routeInfo.mVolumeMax);
setVolumeHandling(routeInfo.mVolumeHandling);
+ setDeviceType(routeInfo.mDeviceType);
if (routeInfo.mExtras != null) {
mExtras = new Bundle(routeInfo.mExtras);
}
@@ -403,6 +539,39 @@ public final class MediaRoute2Info implements Parcelable {
}
/**
+ * Sets the route's connection state.
+ *
+ * {@link #CONNECTION_STATE_DISCONNECTED},
+ * {@link #CONNECTION_STATE_CONNECTING}, or
+ * {@link #CONNECTION_STATE_CONNECTED}.
+ */
+ @NonNull
+ public Builder setConnectionState(@ConnectionState int connectionState) {
+ mConnectionState = connectionState;
+ return this;
+ }
+
+ /**
+ * Sets the URI of the icon representing this route.
+ * <p>
+ * This icon will be used in picker UIs if available.
+ * </p><p>
+ * The URI must be one of the following formats:
+ * <ul>
+ * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li>
+ * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE})
+ * </li>
+ * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})</li>
+ * </ul>
+ * </p>
+ */
+ @NonNull
+ public Builder setIconUri(@Nullable Uri iconUri) {
+ mIconUri = iconUri;
+ return this;
+ }
+
+ /**
* Sets the package name of the app using the route.
*/
@NonNull
@@ -470,6 +639,16 @@ public final class MediaRoute2Info implements Parcelable {
mVolumeHandling = volumeHandling;
return this;
}
+
+ /**
+ * Sets the route's device type.
+ */
+ @NonNull
+ public Builder setDeviceType(@DeviceType int deviceType) {
+ mDeviceType = deviceType;
+ return this;
+ }
+
/**
* Sets a bundle of extras for the route.
*/
diff --git a/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java b/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java
index df6345fb7db0..524be8c014c2 100644
--- a/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java
+++ b/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java
@@ -16,6 +16,9 @@
package com.android.mediarouteprovider.example;
+import static android.media.MediaRoute2Info.DEVICE_TYPE_SPEAKER;
+import static android.media.MediaRoute2Info.DEVICE_TYPE_TV;
+
import android.content.Intent;
import android.media.MediaRoute2Info;
import android.media.MediaRoute2ProviderInfo;
@@ -57,9 +60,11 @@ public class SampleMediaRoute2ProviderService extends MediaRoute2ProviderService
private void initializeRoutes() {
MediaRoute2Info route1 = new MediaRoute2Info.Builder(ROUTE_ID1, ROUTE_NAME1)
.addSupportedCategory(CATEGORY_SAMPLE)
+ .setDeviceType(DEVICE_TYPE_TV)
.build();
MediaRoute2Info route2 = new MediaRoute2Info.Builder(ROUTE_ID2, ROUTE_NAME2)
.addSupportedCategory(CATEGORY_SAMPLE)
+ .setDeviceType(DEVICE_TYPE_SPEAKER)
.build();
MediaRoute2Info routeSpecial =
new MediaRoute2Info.Builder(ROUTE_ID_SPECIAL_CATEGORY, ROUTE_NAME_SPECIAL_CATEGORY)
@@ -123,7 +128,8 @@ public class SampleMediaRoute2ProviderService extends MediaRoute2ProviderService
@Override
public void onControlRequest(String routeId, Intent request) {
- if (ACTION_REMOVE_ROUTE.equals(request.getAction())) {
+ String action = request.getAction();
+ if (ACTION_REMOVE_ROUTE.equals(action)) {
MediaRoute2Info route = mRoutes.get(routeId);
if (route != null) {
mRoutes.remove(routeId);
diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2Test.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2Test.java
index 326628587837..6f1a070d6f7c 100644
--- a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2Test.java
+++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2Test.java
@@ -16,19 +16,31 @@
package com.android.mediaroutertest;
+import static android.media.MediaRoute2Info.CONNECTION_STATE_CONNECTED;
+import static android.media.MediaRoute2Info.CONNECTION_STATE_CONNECTING;
+import static android.media.MediaRoute2Info.DEVICE_TYPE_SPEAKER;
+import static android.media.MediaRoute2Info.DEVICE_TYPE_TV;
+import static android.media.MediaRoute2Info.PLAYBACK_VOLUME_FIXED;
+import static android.media.MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE;
+
import static com.android.mediaroutertest.MediaRouterManagerTest.CATEGORIES_ALL;
import static com.android.mediaroutertest.MediaRouterManagerTest.CATEGORIES_SPECIAL;
+import static com.android.mediaroutertest.MediaRouterManagerTest.CATEGORY_SAMPLE;
+import static com.android.mediaroutertest.MediaRouterManagerTest.CATEGORY_SPECIAL;
import static com.android.mediaroutertest.MediaRouterManagerTest.ROUTE_ID_SPECIAL_CATEGORY;
import static com.android.mediaroutertest.MediaRouterManagerTest.ROUTE_ID_VARIABLE_VOLUME;
import static com.android.mediaroutertest.MediaRouterManagerTest.SYSTEM_PROVIDER_ID;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import android.content.Context;
import android.media.MediaRoute2Info;
import android.media.MediaRouter2;
+import android.net.Uri;
+import android.os.Parcel;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
@@ -88,6 +100,90 @@ public class MediaRouter2Test {
}
@Test
+ public void testRouteInfoEquality() {
+ MediaRoute2Info routeInfo = new MediaRoute2Info.Builder("id", "name")
+ .setDescription("description")
+ .setClientPackageName("com.android.mediaroutertest")
+ .setConnectionState(CONNECTION_STATE_CONNECTING)
+ .setIconUri(new Uri.Builder().path("icon").build())
+ .setVolume(5)
+ .setVolumeMax(20)
+ .addSupportedCategory(CATEGORY_SAMPLE)
+ .setVolumeHandling(PLAYBACK_VOLUME_VARIABLE)
+ .setDeviceType(DEVICE_TYPE_SPEAKER)
+ .build();
+
+ MediaRoute2Info routeInfoRebuilt = new MediaRoute2Info.Builder(routeInfo).build();
+ assertEquals(routeInfo, routeInfoRebuilt);
+
+ Parcel parcel = Parcel.obtain();
+ parcel.writeParcelable(routeInfo, 0);
+ parcel.setDataPosition(0);
+ MediaRoute2Info routeInfoFromParcel = parcel.readParcelable(null);
+
+ assertEquals(routeInfo, routeInfoFromParcel);
+ }
+
+ @Test
+ public void testRouteInfoInequality() {
+ MediaRoute2Info route = new MediaRoute2Info.Builder("id", "name")
+ .setDescription("description")
+ .setClientPackageName("com.android.mediaroutertest")
+ .setConnectionState(CONNECTION_STATE_CONNECTING)
+ .setIconUri(new Uri.Builder().path("icon").build())
+ .addSupportedCategory(CATEGORY_SAMPLE)
+ .setVolume(5)
+ .setVolumeMax(20)
+ .setVolumeHandling(PLAYBACK_VOLUME_VARIABLE)
+ .setDeviceType(DEVICE_TYPE_SPEAKER)
+ .build();
+
+ MediaRoute2Info routeId = new MediaRoute2Info.Builder(route)
+ .setId("another id").build();
+ assertNotEquals(route, routeId);
+
+ MediaRoute2Info routeName = new MediaRoute2Info.Builder(route)
+ .setName("another name").build();
+ assertNotEquals(route, routeName);
+
+ MediaRoute2Info routeDescription = new MediaRoute2Info.Builder(route)
+ .setDescription("another description").build();
+ assertNotEquals(route, routeDescription);
+
+ MediaRoute2Info routeConnectionState = new MediaRoute2Info.Builder(route)
+ .setConnectionState(CONNECTION_STATE_CONNECTED).build();
+ assertNotEquals(route, routeConnectionState);
+
+ MediaRoute2Info routeIcon = new MediaRoute2Info.Builder(route)
+ .setIconUri(new Uri.Builder().path("new icon").build()).build();
+ assertNotEquals(route, routeIcon);
+
+ MediaRoute2Info routeClient = new MediaRoute2Info.Builder(route)
+ .setClientPackageName("another.client.package").build();
+ assertNotEquals(route, routeClient);
+
+ MediaRoute2Info routeCategory = new MediaRoute2Info.Builder(route)
+ .addSupportedCategory(CATEGORY_SPECIAL).build();
+ assertNotEquals(route, routeCategory);
+
+ MediaRoute2Info routeVolume = new MediaRoute2Info.Builder(route)
+ .setVolume(10).build();
+ assertNotEquals(route, routeVolume);
+
+ MediaRoute2Info routeVolumeMax = new MediaRoute2Info.Builder(route)
+ .setVolumeMax(30).build();
+ assertNotEquals(route, routeVolumeMax);
+
+ MediaRoute2Info routeVolumeHandling = new MediaRoute2Info.Builder(route)
+ .setVolumeHandling(PLAYBACK_VOLUME_FIXED).build();
+ assertNotEquals(route, routeVolumeHandling);
+
+ MediaRoute2Info routeDeviceType = new MediaRoute2Info.Builder(route)
+ .setVolume(DEVICE_TYPE_TV).build();
+ assertNotEquals(route, routeDeviceType);
+ }
+
+ @Test
public void testControlVolumeWithRouter() throws Exception {
Map<String, MediaRoute2Info> routes = waitAndGetRoutes(CATEGORIES_ALL);
diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
index 2772aa46911c..c5d8a96c7e08 100644
--- a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
+++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
@@ -20,7 +20,6 @@ import static android.media.MediaRoute2Info.PLAYBACK_VOLUME_FIXED;
import static android.media.MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
@@ -124,21 +123,7 @@ public class MediaRouterManagerTest {
clearCallbacks();
}
- //TODO: Move to a separate file
- @Test
- public void testMediaRoute2Info() {
- MediaRoute2Info routeInfo1 = new MediaRoute2Info.Builder("id", "name")
- .build();
- MediaRoute2Info routeInfo2 = new MediaRoute2Info.Builder(routeInfo1).build();
-
- MediaRoute2Info routeInfo3 = new MediaRoute2Info.Builder(routeInfo1)
- .setClientPackageName(mPackageName).build();
-
- assertEquals(routeInfo1, routeInfo2);
- assertNotEquals(routeInfo1, routeInfo3);
- }
-
- /**
+ /**
* Tests if routes are added correctly when a new callback is registered.
*/
@Test
@@ -177,8 +162,6 @@ public class MediaRouterManagerTest {
}
});
- //TODO: Figure out a more proper way to test.
- // (Control requests shouldn't be used in this way.)
mRouter2.sendControlRequest(routes.get(ROUTE_ID2), new Intent(ACTION_REMOVE_ROUTE));
assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
}