Home | History | Annotate | Download | only in cts
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package android.media.cts;
     17 
     18 import android.media.cts.R;
     19 
     20 import android.app.PendingIntent;
     21 import android.content.Context;
     22 import android.content.Intent;
     23 import android.graphics.Bitmap;
     24 import android.graphics.Canvas;
     25 import android.graphics.drawable.Drawable;
     26 import android.media.AudioManager;
     27 import android.media.MediaRouter;
     28 import android.media.MediaRouter.RouteGroup;
     29 import android.media.MediaRouter.RouteCategory;
     30 import android.media.MediaRouter.RouteInfo;
     31 import android.media.MediaRouter.UserRouteInfo;
     32 import android.media.RemoteControlClient;
     33 import android.platform.test.annotations.AppModeFull;
     34 import android.test.InstrumentationTestCase;
     35 
     36 import java.util.List;
     37 import java.util.ArrayList;
     38 
     39 /**
     40  * Test {@link android.media.MediaRouter}.
     41  */
     42 @AppModeFull(reason = "TODO: evaluate and port to instant")
     43 public class MediaRouterTest extends InstrumentationTestCase {
     44 
     45     private static final int TEST_ROUTE_NAME_RESOURCE_ID = R.string.test_user_route_name;
     46     private static final int TEST_CATEGORY_NAME_RESOURCE_ID = R.string.test_route_category_name;
     47     private static final int TEST_ICON_RESOURCE_ID = R.drawable.single_face;
     48     private static final int TEST_MAX_VOLUME = 100;
     49     private static final int TEST_VOLUME = 17;
     50     private static final int TEST_VOLUME_DIRECTION = -2;
     51     private static final int TEST_PLAYBACK_STREAM = AudioManager.STREAM_ALARM;
     52     private static final int TEST_VOLUME_HANDLING = RouteInfo.PLAYBACK_VOLUME_VARIABLE;
     53     private static final int TEST_PLAYBACK_TYPE = RouteInfo.PLAYBACK_TYPE_LOCAL;
     54     private static final CharSequence TEST_ROUTE_DESCRIPTION = "test_user_route_description";
     55     private static final CharSequence TEST_STATUS = "test_user_route_status";
     56     private static final CharSequence TEST_GROUPABLE_CATEGORY_NAME = "test_groupable_category_name";
     57 
     58     private MediaRouter mMediaRouter;
     59     private RouteCategory mTestCategory;
     60     private RouteCategory mTestGroupableCategory;
     61     private CharSequence mTestRouteName;
     62     private Drawable mTestIconDrawable;
     63     private Context mContext;
     64 
     65     @Override
     66     protected void setUp() throws Exception {
     67         super.setUp();
     68         mContext = getInstrumentation().getContext();
     69         mMediaRouter = (MediaRouter) mContext.getSystemService(Context.MEDIA_ROUTER_SERVICE);
     70         mTestCategory = mMediaRouter.createRouteCategory(TEST_CATEGORY_NAME_RESOURCE_ID, false);
     71         mTestGroupableCategory = mMediaRouter.createRouteCategory(TEST_GROUPABLE_CATEGORY_NAME,
     72                 true);
     73         mTestRouteName = mContext.getText(TEST_ROUTE_NAME_RESOURCE_ID);
     74         mTestIconDrawable = mContext.getDrawable(TEST_ICON_RESOURCE_ID);
     75     }
     76 
     77     protected void tearDown() throws Exception {
     78         mMediaRouter.clearUserRoutes();
     79         super.tearDown();
     80     }
     81 
     82     /**
     83      * Test {@link MediaRouter#selectRoute(int, RouteInfo)}.
     84      */
     85     public void testSelectRoute() {
     86         RouteInfo prevSelectedRoute = mMediaRouter.getSelectedRoute(
     87                 MediaRouter.ROUTE_TYPE_LIVE_AUDIO | MediaRouter.ROUTE_TYPE_LIVE_VIDEO
     88                 | MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY);
     89         assertNotNull(prevSelectedRoute);
     90 
     91         UserRouteInfo userRoute = mMediaRouter.createUserRoute(mTestCategory);
     92         mMediaRouter.addUserRoute(userRoute);
     93         mMediaRouter.selectRoute(userRoute.getSupportedTypes(), userRoute);
     94 
     95         RouteInfo nowSelectedRoute = mMediaRouter.getSelectedRoute(MediaRouter.ROUTE_TYPE_USER);
     96         assertEquals(userRoute, nowSelectedRoute);
     97         assertEquals(mTestCategory, nowSelectedRoute.getCategory());
     98 
     99         mMediaRouter.selectRoute(prevSelectedRoute.getSupportedTypes(), prevSelectedRoute);
    100     }
    101 
    102     /**
    103      * Test {@link MediaRouter#getRouteCount()}.
    104      */
    105     public void testGetRouteCount() {
    106         final int count = mMediaRouter.getRouteCount();
    107         assertTrue("By default, a media router has at least one route.", count > 0);
    108 
    109         UserRouteInfo userRoute0 = mMediaRouter.createUserRoute(mTestCategory);
    110         mMediaRouter.addUserRoute(userRoute0);
    111         assertEquals(count + 1, mMediaRouter.getRouteCount());
    112 
    113         mMediaRouter.removeUserRoute(userRoute0);
    114         assertEquals(count, mMediaRouter.getRouteCount());
    115 
    116         UserRouteInfo userRoute1 = mMediaRouter.createUserRoute(mTestCategory);
    117         mMediaRouter.addUserRoute(userRoute0);
    118         mMediaRouter.addUserRoute(userRoute1);
    119         assertEquals(count + 2, mMediaRouter.getRouteCount());
    120 
    121         mMediaRouter.clearUserRoutes();
    122         assertEquals(count, mMediaRouter.getRouteCount());
    123     }
    124 
    125     /**
    126      * Test {@link MediaRouter#getRouteAt(int)}.
    127      */
    128     public void testGetRouteAt() throws Exception {
    129         UserRouteInfo userRoute0 = mMediaRouter.createUserRoute(mTestCategory);
    130         UserRouteInfo userRoute1 = mMediaRouter.createUserRoute(mTestCategory);
    131         mMediaRouter.addUserRoute(userRoute0);
    132         mMediaRouter.addUserRoute(userRoute1);
    133 
    134         int count = mMediaRouter.getRouteCount();
    135         assertEquals(userRoute0, mMediaRouter.getRouteAt(count - 2));
    136         assertEquals(userRoute1, mMediaRouter.getRouteAt(count - 1));
    137     }
    138 
    139     /**
    140      * Test {@link MediaRouter.UserRouteInfo} with the default route.
    141      */
    142     public void testDefaultRouteInfo() {
    143         RouteInfo route = mMediaRouter.getDefaultRoute();
    144 
    145         assertNotNull(route.getCategory());
    146         assertNotNull(route.getName());
    147         assertNotNull(route.getName(mContext));
    148         assertTrue(route.isEnabled());
    149         assertFalse(route.isConnecting());
    150         assertEquals(RouteInfo.DEVICE_TYPE_UNKNOWN, route.getDeviceType());
    151         assertEquals(RouteInfo.PLAYBACK_TYPE_LOCAL, route.getPlaybackType());
    152         assertNull(route.getDescription());
    153         assertNull(route.getStatus());
    154         assertNull(route.getIconDrawable());
    155         assertNull(route.getGroup());
    156 
    157         Object tag = new Object();
    158         route.setTag(tag);
    159         assertEquals(tag, route.getTag());
    160         assertEquals(AudioManager.STREAM_MUSIC, route.getPlaybackStream());
    161 
    162         int curVolume = route.getVolume();
    163         int maxVolume = route.getVolumeMax();
    164         assertTrue(curVolume <= maxVolume);
    165     }
    166 
    167     /**
    168      * Test {@link MediaRouter.UserRouteInfo}.
    169      */
    170     public void testUserRouteInfo() {
    171         UserRouteInfo userRoute = mMediaRouter.createUserRoute(mTestCategory);
    172         assertTrue(userRoute.isEnabled());
    173         assertFalse(userRoute.isConnecting());
    174         assertEquals(mTestCategory, userRoute.getCategory());
    175         assertEquals(RouteInfo.DEVICE_TYPE_UNKNOWN, userRoute.getDeviceType());
    176         assertEquals(RouteInfo.PLAYBACK_TYPE_REMOTE, userRoute.getPlaybackType());
    177 
    178         // Test setName by CharSequence object.
    179         userRoute.setName(mTestRouteName);
    180         assertEquals(mTestRouteName, userRoute.getName());
    181 
    182         userRoute.setName(null);
    183         assertNull(userRoute.getName());
    184 
    185         // Test setName by resource ID.
    186         // The getName() method tries to find the resource in application resources which was stored
    187         // when the media router is first initialized. In contrast, getName(Context) method tries to
    188         // find the resource in a given context's resources. So if we call getName(Context) with a
    189         // context which has the same resources, two methods will return the same value.
    190         userRoute.setName(TEST_ROUTE_NAME_RESOURCE_ID);
    191         assertEquals(mTestRouteName, userRoute.getName());
    192         assertEquals(mTestRouteName, userRoute.getName(mContext));
    193 
    194         userRoute.setDescription(TEST_ROUTE_DESCRIPTION);
    195         assertEquals(TEST_ROUTE_DESCRIPTION, userRoute.getDescription());
    196 
    197         userRoute.setStatus(TEST_STATUS);
    198         assertEquals(TEST_STATUS, userRoute.getStatus());
    199 
    200         Object tag = new Object();
    201         userRoute.setTag(tag);
    202         assertEquals(tag, userRoute.getTag());
    203 
    204         userRoute.setPlaybackStream(TEST_PLAYBACK_STREAM);
    205         assertEquals(TEST_PLAYBACK_STREAM, userRoute.getPlaybackStream());
    206 
    207         userRoute.setIconDrawable(mTestIconDrawable);
    208         assertEquals(mTestIconDrawable, userRoute.getIconDrawable());
    209 
    210         userRoute.setIconDrawable(null);
    211         assertNull(userRoute.getIconDrawable());
    212 
    213         userRoute.setIconResource(TEST_ICON_RESOURCE_ID);
    214         assertTrue(getBitmap(mTestIconDrawable).sameAs(getBitmap(userRoute.getIconDrawable())));
    215 
    216         userRoute.setVolumeMax(TEST_MAX_VOLUME);
    217         assertEquals(TEST_MAX_VOLUME, userRoute.getVolumeMax());
    218 
    219         userRoute.setVolume(TEST_VOLUME);
    220         assertEquals(TEST_VOLUME, userRoute.getVolume());
    221 
    222         Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON);
    223         PendingIntent mediaButtonIntent = PendingIntent.getBroadcast(
    224                 mContext, 0, intent, PendingIntent.FLAG_ONE_SHOT);
    225         RemoteControlClient rcc = new RemoteControlClient(mediaButtonIntent);
    226         userRoute.setRemoteControlClient(rcc);
    227         assertEquals(rcc, userRoute.getRemoteControlClient());
    228 
    229         userRoute.setVolumeHandling(TEST_VOLUME_HANDLING);
    230         assertEquals(TEST_VOLUME_HANDLING, userRoute.getVolumeHandling());
    231 
    232         userRoute.setPlaybackType(TEST_PLAYBACK_TYPE);
    233         assertEquals(TEST_PLAYBACK_TYPE, userRoute.getPlaybackType());
    234     }
    235 
    236     /**
    237      * Test {@link MediaRouter.RouteGroup}.
    238      */
    239     public void testRouteGroup() {
    240         // Create a route with a groupable category.
    241         // A route does not belong to any group until it is added to a media router or to a group.
    242         UserRouteInfo userRoute0 = mMediaRouter.createUserRoute(mTestGroupableCategory);
    243         assertNull(userRoute0.getGroup());
    244 
    245         // Call addUserRoute(UserRouteInfo).
    246         // For the route whose category is groupable, this method does not directly add the route in
    247         // the media router. Instead, it creates a RouteGroup, adds the group in the media router,
    248         // and puts the route inside that group.
    249         mMediaRouter.addUserRoute(userRoute0);
    250         RouteGroup routeGroup = userRoute0.getGroup();
    251         assertNotNull(routeGroup);
    252         assertEquals(1, routeGroup.getRouteCount());
    253         assertEquals(userRoute0, routeGroup.getRouteAt(0));
    254 
    255         // Create another two routes with the same category.
    256         UserRouteInfo userRoute1 = mMediaRouter.createUserRoute(mTestGroupableCategory);
    257         UserRouteInfo userRoute2 = mMediaRouter.createUserRoute(mTestGroupableCategory);
    258 
    259         // Add userRoute2 at the end of the group.
    260         routeGroup.addRoute(userRoute2);
    261         assertSame(routeGroup, userRoute2.getGroup());
    262         assertEquals(2, routeGroup.getRouteCount());
    263         assertEquals(userRoute0, routeGroup.getRouteAt(0));
    264         assertEquals(userRoute2, routeGroup.getRouteAt(1));
    265 
    266         // To place routes in order, add userRoute1 to the group between userRoute0 and userRoute2.
    267         routeGroup.addRoute(userRoute1, 1);
    268         assertSame(routeGroup, userRoute1.getGroup());
    269         assertEquals(3, routeGroup.getRouteCount());
    270         assertEquals(userRoute0, routeGroup.getRouteAt(0));
    271         assertEquals(userRoute1, routeGroup.getRouteAt(1));
    272         assertEquals(userRoute2, routeGroup.getRouteAt(2));
    273 
    274         // Remove userRoute0.
    275         routeGroup.removeRoute(userRoute0);
    276         assertNull(userRoute0.getGroup());
    277         assertEquals(2, routeGroup.getRouteCount());
    278         assertEquals(userRoute1, routeGroup.getRouteAt(0));
    279         assertEquals(userRoute2, routeGroup.getRouteAt(1));
    280 
    281         // Remove userRoute1 which is the first route in the group now.
    282         routeGroup.removeRoute(0);
    283         assertNull(userRoute1.getGroup());
    284         assertEquals(1, routeGroup.getRouteCount());
    285         assertEquals(userRoute2, routeGroup.getRouteAt(0));
    286 
    287         // Routes in different categories cannot be added to the same group.
    288         UserRouteInfo userRouteInAnotherCategory = mMediaRouter.createUserRoute(mTestCategory);
    289         try {
    290             // This will throw an IllegalArgumentException.
    291             routeGroup.addRoute(userRouteInAnotherCategory);
    292             fail();
    293         } catch (IllegalArgumentException exception) {
    294             // Expected
    295         }
    296 
    297         // Set an icon for the group.
    298         routeGroup.setIconDrawable(mTestIconDrawable);
    299         assertEquals(mTestIconDrawable, routeGroup.getIconDrawable());
    300 
    301         routeGroup.setIconDrawable(null);
    302         assertNull(routeGroup.getIconDrawable());
    303 
    304         routeGroup.setIconResource(TEST_ICON_RESOURCE_ID);
    305         assertTrue(getBitmap(mTestIconDrawable).sameAs(getBitmap(routeGroup.getIconDrawable())));
    306     }
    307 
    308     /**
    309      * Test {@link MediaRouter.RouteCategory}.
    310      */
    311     public void testRouteCategory() {
    312         // Test getName() for category whose name is set with resource ID.
    313         RouteCategory routeCategory = mMediaRouter.createRouteCategory(
    314                 TEST_CATEGORY_NAME_RESOURCE_ID, false);
    315 
    316         // The getName() method tries to find the resource in application resources which was stored
    317         // when the media router is first initialized. In contrast, getName(Context) method tries to
    318         // find the resource in a given context's resources. So if we call getName(Context) with a
    319         // context which has the same resources, two methods will return the same value.
    320         CharSequence categoryName = mContext.getText(
    321                 TEST_CATEGORY_NAME_RESOURCE_ID);
    322         assertEquals(categoryName, routeCategory.getName());
    323         assertEquals(categoryName, routeCategory.getName(mContext));
    324 
    325         assertFalse(routeCategory.isGroupable());
    326         assertEquals(MediaRouter.ROUTE_TYPE_USER, routeCategory.getSupportedTypes());
    327 
    328         final int count = mMediaRouter.getCategoryCount();
    329         assertTrue("By default, a media router has at least one route category.", count > 0);
    330 
    331         UserRouteInfo userRoute = mMediaRouter.createUserRoute(routeCategory);
    332         mMediaRouter.addUserRoute(userRoute);
    333         assertEquals(count + 1, mMediaRouter.getCategoryCount());
    334         assertEquals(routeCategory, mMediaRouter.getCategoryAt(count));
    335 
    336         List<RouteInfo> routesInCategory = new ArrayList<RouteInfo>();
    337         routeCategory.getRoutes(routesInCategory);
    338         assertEquals(1, routesInCategory.size());
    339 
    340         RouteInfo route = routesInCategory.get(0);
    341         assertEquals(userRoute, route);
    342 
    343         // Test getName() for category whose name is set with CharSequence object.
    344         RouteCategory newRouteCategory = mMediaRouter.createRouteCategory(categoryName, false);
    345         assertEquals(categoryName, newRouteCategory.getName());
    346     }
    347 
    348     public void testCallback() {
    349         MediaRouterCallback callback = new MediaRouterCallback();
    350         MediaRouter.Callback mrc = (MediaRouter.Callback) callback;
    351         MediaRouter.SimpleCallback mrsc = (MediaRouter.SimpleCallback) callback;
    352 
    353         final int allRouteTypes = MediaRouter.ROUTE_TYPE_LIVE_AUDIO
    354                 | MediaRouter.ROUTE_TYPE_LIVE_VIDEO | MediaRouter.ROUTE_TYPE_USER;
    355         mMediaRouter.addCallback(allRouteTypes, callback);
    356 
    357         // Test onRouteAdded().
    358         callback.reset();
    359         UserRouteInfo userRoute = mMediaRouter.createUserRoute(mTestCategory);
    360         mMediaRouter.addUserRoute(userRoute);
    361         assertTrue(callback.mOnRouteAddedCalled);
    362         assertEquals(userRoute, callback.mAddedRoute);
    363         // Call the callback methods directly so they are marked as tested
    364         mrc.onRouteAdded(mMediaRouter, callback.mAddedRoute);
    365         mrsc.onRouteAdded(mMediaRouter, callback.mAddedRoute);
    366 
    367         RouteInfo prevSelectedRoute = mMediaRouter.getSelectedRoute(allRouteTypes);
    368 
    369         // Test onRouteSelected() and onRouteUnselected().
    370         callback.reset();
    371         mMediaRouter.selectRoute(MediaRouter.ROUTE_TYPE_USER, userRoute);
    372         assertTrue(callback.mOnRouteUnselectedCalled);
    373         assertEquals(prevSelectedRoute, callback.mUnselectedRoute);
    374         assertTrue(callback.mOnRouteSelectedCalled);
    375         assertEquals(userRoute, callback.mSelectedRoute);
    376         // Call the callback methods directly so they are marked as tested
    377         mrc.onRouteUnselected(mMediaRouter, MediaRouter.ROUTE_TYPE_USER, callback.mUnselectedRoute);
    378         mrc.onRouteSelected(mMediaRouter, MediaRouter.ROUTE_TYPE_USER, callback.mSelectedRoute);
    379         mrsc.onRouteUnselected(mMediaRouter, MediaRouter.ROUTE_TYPE_USER,
    380                 callback.mUnselectedRoute);
    381         mrsc.onRouteSelected(mMediaRouter, MediaRouter.ROUTE_TYPE_USER, callback.mSelectedRoute);
    382 
    383         // Test onRouteChanged().
    384         // It is called when the route's name, description, status or tag is updated.
    385         callback.reset();
    386         userRoute.setName(mTestRouteName);
    387         assertTrue(callback.mOnRouteChangedCalled);
    388         assertEquals(userRoute, callback.mChangedRoute);
    389         // Call the callback methods directly so they are marked as tested
    390         mrc.onRouteChanged(mMediaRouter, callback.mChangedRoute);
    391         mrsc.onRouteChanged(mMediaRouter, callback.mChangedRoute);
    392 
    393         callback.reset();
    394         userRoute.setDescription(TEST_ROUTE_DESCRIPTION);
    395         assertTrue(callback.mOnRouteChangedCalled);
    396         assertEquals(userRoute, callback.mChangedRoute);
    397         // Call the callback methods directly so they are marked as tested
    398         mrc.onRouteChanged(mMediaRouter, callback.mChangedRoute);
    399         mrsc.onRouteChanged(mMediaRouter, callback.mChangedRoute);
    400 
    401         callback.reset();
    402         userRoute.setStatus(TEST_STATUS);
    403         assertTrue(callback.mOnRouteChangedCalled);
    404         assertEquals(userRoute, callback.mChangedRoute);
    405         // Call the callback methods directly so they are marked as tested
    406         mrc.onRouteChanged(mMediaRouter, callback.mChangedRoute);
    407         mrsc.onRouteChanged(mMediaRouter, callback.mChangedRoute);
    408 
    409         callback.reset();
    410         Object tag = new Object();
    411         userRoute.setTag(tag);
    412         assertTrue(callback.mOnRouteChangedCalled);
    413         assertEquals(userRoute, callback.mChangedRoute);
    414         // Call the callback methods directly so they are marked as tested
    415         mrc.onRouteChanged(mMediaRouter, callback.mChangedRoute);
    416         mrsc.onRouteChanged(mMediaRouter, callback.mChangedRoute);
    417 
    418         // Test onRouteVolumeChanged().
    419         userRoute.setVolumeMax(TEST_MAX_VOLUME);
    420         callback.reset();
    421         userRoute.setVolume(TEST_VOLUME);
    422         assertTrue(callback.mOnRouteVolumeChangedCalled);
    423         assertEquals(userRoute, callback.mVolumeChangedRoute);
    424         // Call the callback methods directly so they are marked as tested
    425         mrc.onRouteVolumeChanged(mMediaRouter, callback.mVolumeChangedRoute);
    426         mrsc.onRouteVolumeChanged(mMediaRouter, callback.mVolumeChangedRoute);
    427 
    428         // Test onRouteRemoved().
    429         callback.reset();
    430         mMediaRouter.removeUserRoute(userRoute);
    431         assertTrue(callback.mOnRouteRemovedCalled);
    432         assertEquals(userRoute, callback.mRemovedRoute);
    433         // Call the callback methods directly so they are marked as tested
    434         mrc.onRouteRemoved(mMediaRouter, callback.mRemovedRoute);
    435         mrsc.onRouteRemoved(mMediaRouter, callback.mRemovedRoute);
    436 
    437         // Test onRouteGrouped() and onRouteUngrouped().
    438         mMediaRouter.clearUserRoutes();
    439         UserRouteInfo groupableRoute0 = mMediaRouter.createUserRoute(mTestGroupableCategory);
    440         UserRouteInfo groupableRoute1 = mMediaRouter.createUserRoute(mTestGroupableCategory);
    441 
    442         // Adding a route of groupable category in the media router does not directly add the route.
    443         // Instead, it creates a RouteGroup, adds the group as a route in the media router, and puts
    444         // the route inside that group. Therefore onRouteAdded() is called for the group, and
    445         // onRouteGrouped() is called for the route.
    446         callback.reset();
    447         mMediaRouter.addUserRoute(groupableRoute0);
    448 
    449         RouteGroup group = groupableRoute0.getGroup();
    450         assertTrue(callback.mOnRouteAddedCalled);
    451         assertEquals(group, callback.mAddedRoute);
    452 
    453         assertTrue(callback.mOnRouteGroupedCalled);
    454         assertEquals(groupableRoute0, callback.mGroupedRoute);
    455         assertEquals(group, callback.mGroup);
    456         assertEquals(0, callback.mRouteIndexInGroup);
    457         // Call the callback methods directly so they are marked as tested
    458         mrc.onRouteGrouped(mMediaRouter, callback.mGroupedRoute, callback.mGroup,
    459                 callback.mRouteIndexInGroup);
    460         mrsc.onRouteGrouped(mMediaRouter, callback.mGroupedRoute, callback.mGroup,
    461                 callback.mRouteIndexInGroup);
    462 
    463         // Add another route to the group.
    464         callback.reset();
    465         group.addRoute(groupableRoute1);
    466         assertTrue(callback.mOnRouteGroupedCalled);
    467         assertEquals(groupableRoute1, callback.mGroupedRoute);
    468         assertEquals(1, callback.mRouteIndexInGroup);
    469         // Call the callback methods directly so they are marked as tested
    470         mrc.onRouteGrouped(mMediaRouter, callback.mGroupedRoute, callback.mGroup,
    471                 callback.mRouteIndexInGroup);
    472         mrsc.onRouteGrouped(mMediaRouter, callback.mGroupedRoute, callback.mGroup,
    473                 callback.mRouteIndexInGroup);
    474 
    475         // Since removing a route from the group changes the group's name, onRouteChanged() is
    476         // called.
    477         callback.reset();
    478         group.removeRoute(groupableRoute1);
    479         assertTrue(callback.mOnRouteUngroupedCalled);
    480         assertEquals(groupableRoute1, callback.mUngroupedRoute);
    481         assertTrue(callback.mOnRouteChangedCalled);
    482         assertEquals(group, callback.mChangedRoute);
    483         // Call the callback methods directly so they are marked as tested
    484         mrc.onRouteUngrouped(mMediaRouter, callback.mUngroupedRoute, callback.mGroup);
    485         mrc.onRouteChanged(mMediaRouter, callback.mChangedRoute);
    486         mrsc.onRouteUngrouped(mMediaRouter, callback.mUngroupedRoute, callback.mGroup);
    487         mrsc.onRouteChanged(mMediaRouter, callback.mChangedRoute);
    488 
    489         // When a group has no routes, the group is removed from the media router.
    490         callback.reset();
    491         group.removeRoute(0);
    492         assertTrue(callback.mOnRouteUngroupedCalled);
    493         assertEquals(groupableRoute0, callback.mUngroupedRoute);
    494         assertTrue(callback.mOnRouteRemovedCalled);
    495         assertEquals(group, callback.mRemovedRoute);
    496         // Call the callback methods directly so they are marked as tested
    497         mrc.onRouteUngrouped(mMediaRouter, callback.mUngroupedRoute, callback.mGroup);
    498         mrc.onRouteRemoved(mMediaRouter, callback.mRemovedRoute);
    499         mrsc.onRouteUngrouped(mMediaRouter, callback.mUngroupedRoute, callback.mGroup);
    500         mrsc.onRouteRemoved(mMediaRouter, callback.mRemovedRoute);
    501 
    502         // In this case, onRouteChanged() is not called.
    503         assertFalse(callback.mOnRouteChangedCalled);
    504 
    505         // Try removing the callback.
    506         mMediaRouter.removeCallback(callback);
    507         callback.reset();
    508         mMediaRouter.addUserRoute(groupableRoute0);
    509         assertFalse(callback.mOnRouteAddedCalled);
    510 
    511         mMediaRouter.selectRoute(prevSelectedRoute.getSupportedTypes(), prevSelectedRoute);
    512     }
    513 
    514     /**
    515      * Test {@link MediaRouter#addCallback(int, MediaRouter.Callback, int)}.
    516      */
    517     public void testAddCallbackWithFlags() {
    518         MediaRouterCallback callback = new MediaRouterCallback();
    519         mMediaRouter.addCallback(MediaRouter.ROUTE_TYPE_USER, callback);
    520 
    521         RouteInfo prevSelectedRoute = mMediaRouter.getSelectedRoute(
    522                 MediaRouter.ROUTE_TYPE_LIVE_AUDIO | MediaRouter.ROUTE_TYPE_LIVE_VIDEO
    523                 | MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY);
    524 
    525         // Currently mCallback is set for the type MediaRouter.ROUTE_TYPE_USER.
    526         // Changes on prevSelectedRoute will not invoke mCallback since the types do not match.
    527         callback.reset();
    528         Object tag0 = new Object();
    529         prevSelectedRoute.setTag(tag0);
    530         assertFalse(callback.mOnRouteChangedCalled);
    531 
    532         // Remove mCallback and add it again with flag MediaRouter.CALLBACK_FLAG_UNFILTERED_EVENTS.
    533         // This flag will make the callback be invoked even when the types do not match.
    534         mMediaRouter.removeCallback(callback);
    535         mMediaRouter.addCallback(MediaRouter.ROUTE_TYPE_USER, callback,
    536                 MediaRouter.CALLBACK_FLAG_UNFILTERED_EVENTS);
    537 
    538         callback.reset();
    539         Object tag1 = new Object();
    540         prevSelectedRoute.setTag(tag1);
    541         assertTrue(callback.mOnRouteChangedCalled);
    542     }
    543 
    544     /**
    545      * Test {@link MediaRouter.VolumeCallback)}.
    546      */
    547     public void testVolumeCallback() {
    548         UserRouteInfo userRoute = mMediaRouter.createUserRoute(mTestCategory);
    549         userRoute.setVolumeHandling(RouteInfo.PLAYBACK_VOLUME_VARIABLE);
    550         MediaRouterVolumeCallback callback = new MediaRouterVolumeCallback();
    551         MediaRouter.VolumeCallback mrvc = (MediaRouter.VolumeCallback) callback;
    552         userRoute.setVolumeCallback(callback);
    553 
    554         userRoute.requestSetVolume(TEST_VOLUME);
    555         assertTrue(callback.mOnVolumeSetRequestCalled);
    556         assertEquals(userRoute, callback.mRouteInfo);
    557         assertEquals(TEST_VOLUME, callback.mVolume);
    558         // Call the callback method directly so it is marked as tested
    559         mrvc.onVolumeSetRequest(callback.mRouteInfo, callback.mVolume);
    560 
    561         callback.reset();
    562         userRoute.requestUpdateVolume(TEST_VOLUME_DIRECTION);
    563         assertTrue(callback.mOnVolumeUpdateRequestCalled);
    564         assertEquals(userRoute, callback.mRouteInfo);
    565         assertEquals(TEST_VOLUME_DIRECTION, callback.mDirection);
    566         // Call the callback method directly so it is marked as tested
    567         mrvc.onVolumeUpdateRequest(callback.mRouteInfo, callback.mDirection);
    568     }
    569 
    570     private Bitmap getBitmap(Drawable drawable) {
    571         int width = drawable.getIntrinsicWidth();
    572         int height = drawable.getIntrinsicHeight();
    573 
    574         Bitmap result = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    575         Canvas canvas = new Canvas(result);
    576 
    577         drawable.setBounds(0, 0, width, height);
    578         drawable.draw(canvas);
    579 
    580         return result;
    581     }
    582 
    583     private class MediaRouterVolumeCallback extends MediaRouter.VolumeCallback {
    584         private boolean mOnVolumeUpdateRequestCalled;
    585         private boolean mOnVolumeSetRequestCalled;
    586         private RouteInfo mRouteInfo;
    587         private int mDirection;
    588         private int mVolume;
    589 
    590         public void reset() {
    591             mOnVolumeUpdateRequestCalled = false;
    592             mOnVolumeSetRequestCalled = false;
    593             mRouteInfo = null;
    594             mDirection = 0;
    595             mVolume = 0;
    596         }
    597 
    598         @Override
    599         public void onVolumeUpdateRequest(RouteInfo info, int direction) {
    600             mOnVolumeUpdateRequestCalled = true;
    601             mRouteInfo = info;
    602             mDirection = direction;
    603         }
    604 
    605         @Override
    606         public void onVolumeSetRequest(RouteInfo info, int volume) {
    607             mOnVolumeSetRequestCalled = true;
    608             mRouteInfo = info;
    609             mVolume = volume;
    610         }
    611     }
    612 
    613     private class MediaRouterCallback extends MediaRouter.SimpleCallback {
    614         private boolean mOnRouteSelectedCalled;
    615         private boolean mOnRouteUnselectedCalled;
    616         private boolean mOnRouteAddedCalled;
    617         private boolean mOnRouteRemovedCalled;
    618         private boolean mOnRouteChangedCalled;
    619         private boolean mOnRouteGroupedCalled;
    620         private boolean mOnRouteUngroupedCalled;
    621         private boolean mOnRouteVolumeChangedCalled;
    622 
    623         private RouteInfo mSelectedRoute;
    624         private RouteInfo mUnselectedRoute;
    625         private RouteInfo mAddedRoute;
    626         private RouteInfo mRemovedRoute;
    627         private RouteInfo mChangedRoute;
    628         private RouteInfo mGroupedRoute;
    629         private RouteInfo mUngroupedRoute;
    630         private RouteInfo mVolumeChangedRoute;
    631         private RouteGroup mGroup;
    632         private int mRouteIndexInGroup = -1;
    633 
    634         public void reset() {
    635             mOnRouteSelectedCalled = false;
    636             mOnRouteUnselectedCalled = false;
    637             mOnRouteAddedCalled = false;
    638             mOnRouteRemovedCalled = false;
    639             mOnRouteChangedCalled = false;
    640             mOnRouteGroupedCalled = false;
    641             mOnRouteUngroupedCalled = false;
    642             mOnRouteVolumeChangedCalled = false;
    643 
    644             mSelectedRoute = null;
    645             mUnselectedRoute = null;
    646             mAddedRoute = null;
    647             mRemovedRoute = null;
    648             mChangedRoute = null;
    649             mGroupedRoute = null;
    650             mUngroupedRoute = null;
    651             mVolumeChangedRoute = null;
    652             mGroup = null;
    653             mRouteIndexInGroup = -1;
    654         }
    655 
    656         @Override
    657         public void onRouteSelected(MediaRouter router, int type, RouteInfo info) {
    658             mOnRouteSelectedCalled = true;
    659             mSelectedRoute = info;
    660         }
    661 
    662         @Override
    663         public void onRouteUnselected(MediaRouter router, int type, RouteInfo info) {
    664             mOnRouteUnselectedCalled = true;
    665             mUnselectedRoute = info;
    666         }
    667 
    668         @Override
    669         public void onRouteAdded(MediaRouter router, RouteInfo info) {
    670             mOnRouteAddedCalled = true;
    671             mAddedRoute = info;
    672         }
    673 
    674         @Override
    675         public void onRouteRemoved(MediaRouter router, RouteInfo info) {
    676             mOnRouteRemovedCalled = true;
    677             mRemovedRoute = info;
    678         }
    679 
    680         @Override
    681         public void onRouteChanged(MediaRouter router, RouteInfo info) {
    682             mOnRouteChangedCalled = true;
    683             mChangedRoute = info;
    684         }
    685 
    686         @Override
    687         public void onRouteGrouped(MediaRouter router, RouteInfo info, RouteGroup group,
    688                 int index) {
    689             mOnRouteGroupedCalled = true;
    690             mGroupedRoute = info;
    691             mGroup = group;
    692             mRouteIndexInGroup = index;
    693         }
    694 
    695         @Override
    696         public void onRouteUngrouped(MediaRouter router, RouteInfo info, RouteGroup group) {
    697             mOnRouteUngroupedCalled = true;
    698             mUngroupedRoute = info;
    699             mGroup = group;
    700         }
    701 
    702         @Override
    703         public void onRouteVolumeChanged(MediaRouter router, RouteInfo info) {
    704             mOnRouteVolumeChangedCalled = true;
    705             mVolumeChangedRoute = info;
    706         }
    707     }
    708 }
    709