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