1 /* 2 * Copyright (C) 2021 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 17 package com.android.bluetooth.mcp; 18 19 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; 20 21 import static org.mockito.Mockito.*; 22 23 import android.bluetooth.BluetoothAdapter; 24 import android.bluetooth.BluetoothDevice; 25 import android.bluetooth.BluetoothUuid; 26 import android.content.pm.ApplicationInfo; 27 import android.content.pm.PackageManager; 28 import android.media.session.PlaybackState; 29 import android.os.ParcelUuid; 30 31 import androidx.test.filters.MediumTest; 32 import androidx.test.runner.AndroidJUnit4; 33 34 import com.android.bluetooth.TestUtils; 35 import com.android.bluetooth.audio_util.MediaData; 36 import com.android.bluetooth.audio_util.MediaPlayerList; 37 import com.android.bluetooth.audio_util.MediaPlayerWrapper; 38 import com.android.bluetooth.audio_util.Metadata; 39 import com.android.bluetooth.btservice.AdapterService; 40 41 import org.junit.After; 42 import org.junit.Assert; 43 import org.junit.Before; 44 import org.junit.Rule; 45 import org.junit.Test; 46 import org.junit.runner.RunWith; 47 import org.mockito.ArgumentCaptor; 48 import org.mockito.Captor; 49 import org.mockito.Mock; 50 import org.mockito.junit.MockitoJUnit; 51 import org.mockito.junit.MockitoRule; 52 53 import java.util.HashMap; 54 import java.util.UUID; 55 56 @MediumTest 57 @RunWith(AndroidJUnit4.class) 58 public class MediaControlProfileTest { 59 private final String mFlagDexmarker = System.getProperty("dexmaker.share_classloader", "false"); 60 61 private BluetoothAdapter mAdapter; 62 private MediaControlProfile mMediaControlProfile; 63 64 private String packageName = "TestPackage"; 65 66 private String name = "TestPlayer"; 67 private CharSequence charSequence = "TestPlayer"; 68 private MediaControlServiceCallbacks mMcpServiceCallbacks; 69 70 @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); 71 72 @Mock private AdapterService mAdapterService; 73 @Mock private MediaData mMockMediaData; 74 @Mock private MediaPlayerList mMockMediaPlayerList; 75 @Mock private Metadata mMockMetadata; 76 @Mock private MediaPlayerWrapper mMockMediaPlayerWrapper; 77 @Mock private PackageManager mMockPackageManager; 78 @Mock private ApplicationInfo mMockApplicationInfo; 79 @Mock private MediaControlGattServiceInterface mMockGMcsService; 80 @Mock private McpService mMockMcpService; 81 82 @Captor private ArgumentCaptor<HashMap> stateMapCaptor; 83 @Captor private ArgumentCaptor<Long> positionCaptor; 84 @Captor private ArgumentCaptor<MediaControlProfile.ListCallback> listCallbackCaptor; 85 86 @Before setUp()87 public void setUp() throws Exception { 88 if (!mFlagDexmarker.equals("true")) { 89 System.setProperty("dexmaker.share_classloader", "true"); 90 } 91 92 MediaControlProfile.ListCallback listCallback; 93 94 TestUtils.setAdapterService(mAdapterService); 95 mAdapter = BluetoothAdapter.getDefaultAdapter(); 96 97 mMockMediaData.metadata = mMockMetadata; 98 99 mMockMediaData.state = null; 100 mMockMetadata.duration = Long.toString(0); 101 mMockMetadata.title = null; 102 doReturn(mMockMediaPlayerWrapper).when(mMockMediaPlayerList).getActivePlayer(); 103 doReturn(mMockMcpService).when(mMockMcpService).getApplicationContext(); 104 doReturn(mMockPackageManager).when(mMockMcpService).getPackageManager(); 105 doReturn(getInstrumentation().getTargetContext().getMainThreadHandler()) 106 .when(mMockMcpService) 107 .getMainThreadHandler(); 108 doReturn(packageName).when(mMockMcpService).getPackageName(); 109 doReturn(name).when(mMockMediaPlayerWrapper).getPackageName(); 110 doReturn(charSequence).when(mMockApplicationInfo).loadLabel(any(PackageManager.class)); 111 doReturn(mMockApplicationInfo) 112 .when(mMockPackageManager) 113 .getApplicationInfo(anyString(), anyInt()); 114 115 mMediaControlProfile = new MediaControlProfile(mMockMcpService, mMockMediaPlayerList); 116 117 // this is equivalent of what usually happens inside init class 118 mMediaControlProfile.injectGattServiceForTesting(packageName, mMockGMcsService); 119 mMediaControlProfile.onServiceInstanceRegistered(ServiceStatus.OK, mMockGMcsService); 120 mMcpServiceCallbacks = mMediaControlProfile; 121 122 // Make sure callbacks are not called before it's fully initialized 123 verify(mMockMediaPlayerList, times(0)).init(any()); 124 mMediaControlProfile.init(); 125 verify(mMockMediaPlayerList).init(listCallbackCaptor.capture()); 126 127 listCallback = listCallbackCaptor.getValue(); 128 listCallback.run(mMockMediaData); 129 // Give some time to verify if post function finishes on update player state method call 130 // TODO: Is there a possibility to get rid of this timeout? 131 verify(mMockGMcsService, timeout(100).times(1)).updatePlayerState(any(HashMap.class)); 132 } 133 134 @After tearDown()135 public void tearDown() throws Exception { 136 TestUtils.clearAdapterService(mAdapterService); 137 138 if (mMediaControlProfile == null) { 139 return; 140 } 141 142 mMediaControlProfile.cleanup(); 143 mMediaControlProfile = null; 144 reset(mMockMediaPlayerList); 145 146 if (!mFlagDexmarker.equals("true")) { 147 System.setProperty("dexmaker.share_classloader", mFlagDexmarker); 148 } 149 } 150 151 @Test testGetCurrentTrackDuration()152 public void testGetCurrentTrackDuration() { 153 long duration = 10; 154 155 // Some duration 156 mMockMetadata.duration = Long.toString(duration); 157 Assert.assertEquals(duration, mMediaControlProfile.getCurrentTrackDuration()); 158 159 // No metadata equals no track duration 160 mMockMediaData.metadata = null; 161 Assert.assertEquals( 162 MediaControlGattServiceInterface.TRACK_DURATION_UNAVAILABLE, 163 mMediaControlProfile.getCurrentTrackDuration()); 164 } 165 166 @Test testPlayerState2McsState()167 public void testPlayerState2McsState() { 168 Assert.assertEquals( 169 mMediaControlProfile.playerState2McsState(PlaybackState.STATE_PLAYING), 170 MediaState.PLAYING); 171 Assert.assertEquals( 172 mMediaControlProfile.playerState2McsState(PlaybackState.STATE_NONE), 173 MediaState.INACTIVE); 174 Assert.assertEquals( 175 mMediaControlProfile.playerState2McsState(PlaybackState.STATE_STOPPED), 176 MediaState.PAUSED); 177 Assert.assertEquals( 178 mMediaControlProfile.playerState2McsState(PlaybackState.STATE_PAUSED), 179 MediaState.PAUSED); 180 Assert.assertEquals( 181 mMediaControlProfile.playerState2McsState(PlaybackState.STATE_PLAYING), 182 MediaState.PLAYING); 183 Assert.assertEquals( 184 mMediaControlProfile.playerState2McsState(PlaybackState.STATE_FAST_FORWARDING), 185 MediaState.SEEKING); 186 Assert.assertEquals( 187 mMediaControlProfile.playerState2McsState(PlaybackState.STATE_REWINDING), 188 MediaState.SEEKING); 189 Assert.assertEquals( 190 mMediaControlProfile.playerState2McsState(PlaybackState.STATE_BUFFERING), 191 MediaState.PAUSED); 192 Assert.assertEquals( 193 mMediaControlProfile.playerState2McsState(PlaybackState.STATE_ERROR), 194 MediaState.INACTIVE); 195 Assert.assertEquals( 196 mMediaControlProfile.playerState2McsState(PlaybackState.STATE_CONNECTING), 197 MediaState.INACTIVE); 198 Assert.assertEquals( 199 mMediaControlProfile.playerState2McsState(PlaybackState.STATE_SKIPPING_TO_PREVIOUS), 200 MediaState.PAUSED); 201 Assert.assertEquals( 202 mMediaControlProfile.playerState2McsState(PlaybackState.STATE_SKIPPING_TO_NEXT), 203 MediaState.PAUSED); 204 Assert.assertEquals( 205 mMediaControlProfile.playerState2McsState( 206 PlaybackState.STATE_SKIPPING_TO_QUEUE_ITEM), 207 MediaState.PAUSED); 208 } 209 210 @Test testGetLatestTrackPosition()211 public void testGetLatestTrackPosition() { 212 int state = PlaybackState.STATE_PLAYING; 213 long position = 10; 214 float playback_speed = 1.5f; 215 216 Assert.assertEquals( 217 mMcpServiceCallbacks.onGetCurrentTrackPosition(), 218 MediaControlGattServiceInterface.TRACK_POSITION_UNAVAILABLE); 219 220 PlaybackState.Builder bob = new PlaybackState.Builder(mMockMediaData.state); 221 bob.setState(state, position, playback_speed); 222 mMockMediaData.state = bob.build(); 223 doReturn(mMockMediaData.state).when(mMockMediaPlayerWrapper).getPlaybackState(); 224 225 Assert.assertNotEquals( 226 mMcpServiceCallbacks.onGetCurrentTrackPosition(), 227 MediaControlGattServiceInterface.TRACK_POSITION_UNAVAILABLE); 228 } 229 230 @Test testOnCurrentPlayerStateUpdate()231 public void testOnCurrentPlayerStateUpdate() { 232 HashMap stateMap; 233 int state = PlaybackState.STATE_PLAYING; 234 long position = 10; 235 float playback_speed = 1.5f; 236 long update_time = 77; 237 long duration = 10; 238 String title = "TestTrackTitle"; 239 240 mMockMetadata.duration = Long.toString(duration); 241 mMockMetadata.title = title; 242 243 PlaybackState.Builder bob = new PlaybackState.Builder(mMockMediaData.state); 244 bob.setState(state, position, playback_speed, update_time); 245 mMockMediaData.state = bob.build(); 246 247 mMediaControlProfile.onCurrentPlayerStateUpdated(true, true); 248 // First time called from ListCallback. Give some time to verify if post function 249 // finishes on update player state method call 250 // TODO: Is there a possibility to get rid of this timeout? 251 verify(mMockGMcsService, timeout(100).times(2)).updatePlayerState(stateMapCaptor.capture()); 252 stateMap = stateMapCaptor.getValue(); 253 254 Assert.assertTrue(stateMap.containsKey(PlayerStateField.PLAYER_NAME)); 255 256 // state changed 257 Assert.assertTrue(stateMap.containsKey(PlayerStateField.PLAYBACK_STATE)); 258 Assert.assertTrue(stateMap.containsKey(PlayerStateField.OPCODES_SUPPORTED)); 259 Assert.assertTrue(stateMap.containsKey(PlayerStateField.SEEKING_SPEED)); 260 Assert.assertTrue(stateMap.containsKey(PlayerStateField.PLAYBACK_SPEED)); 261 Assert.assertTrue(stateMap.containsKey(PlayerStateField.TRACK_POSITION)); 262 263 // metadata changed 264 Assert.assertTrue(stateMap.containsKey(PlayerStateField.TRACK_DURATION)); 265 Assert.assertTrue(stateMap.containsKey(PlayerStateField.TRACK_TITLE)); 266 } 267 testHandleTrackPositionSetRequest(long position, long duration, int times)268 private void testHandleTrackPositionSetRequest(long position, long duration, int times) { 269 mMcpServiceCallbacks.onTrackPositionSetRequest(position); 270 verify(mMockMediaPlayerWrapper, timeout(100).times(times)).seekTo(positionCaptor.capture()); 271 272 // position cannot be negative and bigger than track duration 273 if (position < 0) Assert.assertEquals(positionCaptor.getValue().longValue(), 0); 274 else if (position > duration) { 275 Assert.assertEquals(positionCaptor.getValue().longValue(), duration); 276 } else { 277 Assert.assertEquals(positionCaptor.getValue().longValue(), position); 278 } 279 } 280 281 @Test testHandleTrackPositionsSetRequest()282 public void testHandleTrackPositionsSetRequest() { 283 long duration = 50; 284 long actions = PlaybackState.ACTION_SEEK_TO; 285 int times = 1; 286 287 mMockMetadata.duration = Long.toString(duration); 288 289 PlaybackState.Builder bob = new PlaybackState.Builder(mMockMediaData.state); 290 bob.setActions(actions); 291 mMockMediaData.state = bob.build(); 292 293 testHandleTrackPositionSetRequest(-duration, duration, times++); 294 testHandleTrackPositionSetRequest(duration + duration, duration, times++); 295 testHandleTrackPositionSetRequest(duration / 2, duration, times++); 296 297 actions = 0; 298 bob.setActions(actions); 299 mMockMediaData.state = bob.build(); 300 301 mMcpServiceCallbacks.onTrackPositionSetRequest(duration); 302 // First time called from ListCallback. Give some time to verify if post function 303 // finishes on update player state method call 304 // TODO: Is there a possibility to get rid of this timeout? 305 verify(mMockGMcsService, timeout(100).times(2)).updatePlayerState(any(HashMap.class)); 306 } 307 308 @Test testHandlePlaybackSpeedSetRequest()309 public void testHandlePlaybackSpeedSetRequest() { 310 float speed = 1.5f; 311 int times = 1; 312 313 mMcpServiceCallbacks.onPlaybackSpeedSetRequest(speed); 314 verify(mMockMediaPlayerWrapper, timeout(100).times(times)).setPlaybackSpeed(anyFloat()); 315 316 // Playback speed wouldn't be set if no active player 317 doReturn(null).when(mMockMediaPlayerList).getActivePlayer(); 318 mMcpServiceCallbacks.onPlaybackSpeedSetRequest(speed); 319 verify(mMockMediaPlayerWrapper, timeout(100).times(times)).setPlaybackSpeed(anyFloat()); 320 } 321 322 @Test testHandleMediaControlRequest()323 public void testHandleMediaControlRequest() { 324 long actions = 325 PlaybackState.ACTION_PLAY 326 | PlaybackState.ACTION_PAUSE 327 | PlaybackState.ACTION_STOP 328 | PlaybackState.ACTION_SKIP_TO_PREVIOUS 329 | PlaybackState.ACTION_SKIP_TO_NEXT 330 | PlaybackState.ACTION_REWIND 331 | PlaybackState.ACTION_FAST_FORWARD 332 | PlaybackState.ACTION_SEEK_TO; 333 long duration = 10; 334 335 PlaybackState.Builder bob = new PlaybackState.Builder(mMockMediaData.state); 336 bob.setActions(actions); 337 mMockMediaData.state = bob.build(); 338 339 Request request = new Request(Request.Opcodes.PLAY, 0); 340 mMcpServiceCallbacks.onMediaControlRequest(request); 341 verify(mMockMediaPlayerWrapper, timeout(100)).playCurrent(); 342 request = new Request(Request.Opcodes.PAUSE, 0); 343 mMcpServiceCallbacks.onMediaControlRequest(request); 344 verify(mMockMediaPlayerWrapper, timeout(100)).pauseCurrent(); 345 request = new Request(Request.Opcodes.STOP, 0); 346 mMcpServiceCallbacks.onMediaControlRequest(request); 347 verify(mMockMediaPlayerWrapper, timeout(100)).seekTo(0); 348 verify(mMockMediaPlayerWrapper).stopCurrent(); 349 request = new Request(Request.Opcodes.PREVIOUS_TRACK, 0); 350 mMcpServiceCallbacks.onMediaControlRequest(request); 351 verify(mMockMediaPlayerWrapper, timeout(100)).skipToPrevious(); 352 request = new Request(Request.Opcodes.NEXT_TRACK, 0); 353 mMcpServiceCallbacks.onMediaControlRequest(request); 354 verify(mMockMediaPlayerWrapper, timeout(100)).skipToNext(); 355 request = new Request(Request.Opcodes.FAST_REWIND, 0); 356 mMcpServiceCallbacks.onMediaControlRequest(request); 357 verify(mMockMediaPlayerWrapper, timeout(100)).rewind(); 358 request = new Request(Request.Opcodes.FAST_FORWARD, 0); 359 mMcpServiceCallbacks.onMediaControlRequest(request); 360 verify(mMockMediaPlayerWrapper, timeout(100)).fastForward(); 361 362 mMockMetadata.duration = Long.toString(duration); 363 Assert.assertEquals(duration, mMediaControlProfile.getCurrentTrackDuration()); 364 request = new Request(Request.Opcodes.MOVE_RELATIVE, 100); 365 mMcpServiceCallbacks.onMediaControlRequest(request); 366 verify(mMockMediaPlayerWrapper, timeout(100)).seekTo(duration); 367 368 // Verify toggle-style play/pause control support 369 clearInvocations(mMockMediaPlayerWrapper); 370 actions = PlaybackState.ACTION_PLAY_PAUSE; 371 bob = new PlaybackState.Builder(mMockMediaData.state); 372 bob.setActions(actions); 373 mMockMediaData.state = bob.build(); 374 375 request = new Request(Request.Opcodes.PLAY, 0); 376 mMcpServiceCallbacks.onMediaControlRequest(request); 377 verify(mMockMediaPlayerWrapper, timeout(100)).playCurrent(); 378 request = new Request(Request.Opcodes.PAUSE, 0); 379 mMcpServiceCallbacks.onMediaControlRequest(request); 380 verify(mMockMediaPlayerWrapper, timeout(100)).pauseCurrent(); 381 } 382 383 @Test testAvrcpCompatibleActionSet()384 public void testAvrcpCompatibleActionSet() { 385 long actions = PlaybackState.ACTION_SET_RATING; 386 PlaybackState.Builder bob = new PlaybackState.Builder(mMockMediaData.state); 387 bob.setActions(actions); 388 mMockMediaData.state = bob.build(); 389 390 // Same base feature set as the player item features defined in `avrcp/get_foder_items.cc` 391 final long baseFeatures = 392 PlaybackState.ACTION_PLAY 393 | PlaybackState.ACTION_STOP 394 | PlaybackState.ACTION_PAUSE 395 | PlaybackState.ACTION_REWIND 396 | PlaybackState.ACTION_FAST_FORWARD 397 | PlaybackState.ACTION_SKIP_TO_NEXT 398 | PlaybackState.ACTION_SKIP_TO_PREVIOUS; 399 Assert.assertEquals( 400 actions | baseFeatures, mMediaControlProfile.getCurrentPlayerSupportedActions()); 401 } 402 403 @Test testPlayerActions2McsSupportedOpcodes()404 public void testPlayerActions2McsSupportedOpcodes() { 405 long actions = 406 PlaybackState.ACTION_PLAY 407 | PlaybackState.ACTION_PAUSE 408 | PlaybackState.ACTION_STOP 409 | PlaybackState.ACTION_SKIP_TO_PREVIOUS 410 | PlaybackState.ACTION_SKIP_TO_NEXT 411 | PlaybackState.ACTION_REWIND 412 | PlaybackState.ACTION_FAST_FORWARD 413 | PlaybackState.ACTION_SEEK_TO; 414 int opcodes_supported = 415 Request.SupportedOpcodes.STOP 416 | Request.SupportedOpcodes.PAUSE 417 | Request.SupportedOpcodes.PLAY 418 | Request.SupportedOpcodes.FAST_REWIND 419 | Request.SupportedOpcodes.PREVIOUS_TRACK 420 | Request.SupportedOpcodes.NEXT_TRACK 421 | Request.SupportedOpcodes.FAST_FORWARD 422 | Request.SupportedOpcodes.MOVE_RELATIVE; 423 424 Assert.assertEquals( 425 mMediaControlProfile.playerActions2McsSupportedOpcodes(actions), opcodes_supported); 426 427 // Verify toggle-style play/pause control support 428 actions = PlaybackState.ACTION_PLAY_PAUSE; 429 opcodes_supported = Request.SupportedOpcodes.PAUSE | Request.SupportedOpcodes.PLAY; 430 431 Assert.assertEquals( 432 mMediaControlProfile.playerActions2McsSupportedOpcodes(actions), opcodes_supported); 433 } 434 435 @Test testProcessPendingPlayerStateRequest()436 public void testProcessPendingPlayerStateRequest() { 437 HashMap stateMap; 438 int state = PlaybackState.STATE_PLAYING; 439 long position = 10; 440 float playback_speed = 1.5f; 441 442 PlaybackState.Builder bob = new PlaybackState.Builder(mMockMediaData.state); 443 bob.setState(state, position, playback_speed); 444 mMockMediaData.state = bob.build(); 445 doReturn(mMockMediaData.state).when(mMockMediaPlayerWrapper).getPlaybackState(); 446 447 PlayerStateField[] state_fields = 448 new PlayerStateField[] { 449 PlayerStateField.PLAYBACK_STATE, 450 PlayerStateField.TRACK_DURATION, 451 PlayerStateField.PLAYBACK_SPEED, 452 PlayerStateField.SEEKING_SPEED, 453 PlayerStateField.PLAYING_ORDER, 454 PlayerStateField.TRACK_POSITION, 455 PlayerStateField.PLAYER_NAME, 456 PlayerStateField.PLAYING_ORDER_SUPPORTED, 457 PlayerStateField.OPCODES_SUPPORTED 458 }; 459 460 mMcpServiceCallbacks.onPlayerStateRequest(state_fields); 461 // First time called from ListCallback. Give some time to verify if post function 462 // finishes on update player state method call 463 // TODO: Is there a possibility to get rid of this timeout? 464 verify(mMockGMcsService, timeout(100).times(2)).updatePlayerState(stateMapCaptor.capture()); 465 stateMap = stateMapCaptor.getValue(); 466 467 Assert.assertTrue(stateMap.containsKey(PlayerStateField.PLAYBACK_STATE)); 468 Assert.assertTrue(stateMap.containsKey(PlayerStateField.TRACK_DURATION)); 469 Assert.assertTrue(stateMap.containsKey(PlayerStateField.PLAYBACK_SPEED)); 470 Assert.assertTrue(stateMap.containsKey(PlayerStateField.SEEKING_SPEED)); 471 Assert.assertTrue(stateMap.containsKey(PlayerStateField.PLAYING_ORDER)); 472 Assert.assertTrue(stateMap.containsKey(PlayerStateField.TRACK_POSITION)); 473 Assert.assertTrue(stateMap.containsKey(PlayerStateField.PLAYER_NAME)); 474 Assert.assertTrue(stateMap.containsKey(PlayerStateField.PLAYING_ORDER_SUPPORTED)); 475 Assert.assertTrue(stateMap.containsKey(PlayerStateField.OPCODES_SUPPORTED)); 476 } 477 testGetCurrentPlayerPlayingOrder( PlayingOrder expected_value, boolean is_shuffle_set, boolean is_repeat_set)478 private void testGetCurrentPlayerPlayingOrder( 479 PlayingOrder expected_value, boolean is_shuffle_set, boolean is_repeat_set) { 480 doReturn(is_shuffle_set).when(mMockMediaPlayerWrapper).isShuffleSet(); 481 doReturn(is_repeat_set).when(mMockMediaPlayerWrapper).isRepeatSet(); 482 Assert.assertEquals(expected_value, mMediaControlProfile.getCurrentPlayerPlayingOrder()); 483 } 484 485 @Test testGetCurrentPlayerPlayingOrders()486 public void testGetCurrentPlayerPlayingOrders() { 487 testGetCurrentPlayerPlayingOrder(PlayingOrder.SHUFFLE_REPEAT, true, true); 488 testGetCurrentPlayerPlayingOrder(PlayingOrder.SHUFFLE_ONCE, true, false); 489 testGetCurrentPlayerPlayingOrder(PlayingOrder.IN_ORDER_REPEAT, false, true); 490 testGetCurrentPlayerPlayingOrder(PlayingOrder.IN_ORDER_ONCE, false, false); 491 } 492 testGetSupportedPlayingOrder(boolean is_shuffle_set, boolean is_repeat_set)493 private void testGetSupportedPlayingOrder(boolean is_shuffle_set, boolean is_repeat_set) { 494 int expected_value = SupportedPlayingOrder.IN_ORDER_ONCE; 495 496 if (is_repeat_set) expected_value |= SupportedPlayingOrder.IN_ORDER_REPEAT; 497 if (is_shuffle_set) { 498 if (is_repeat_set) expected_value |= SupportedPlayingOrder.SHUFFLE_REPEAT; 499 else expected_value |= SupportedPlayingOrder.SHUFFLE_ONCE; 500 } 501 502 doReturn(is_shuffle_set).when(mMockMediaPlayerWrapper).isShuffleSupported(); 503 doReturn(is_repeat_set).when(mMockMediaPlayerWrapper).isRepeatSupported(); 504 Assert.assertEquals( 505 expected_value, mMediaControlProfile.getSupportedPlayingOrder().intValue()); 506 } 507 508 @Test testGetSupportedPlayingOrders()509 public void testGetSupportedPlayingOrders() { 510 testGetSupportedPlayingOrder(true, true); 511 testGetSupportedPlayingOrder(true, false); 512 testGetSupportedPlayingOrder(false, true); 513 testGetSupportedPlayingOrder(false, false); 514 } 515 516 @Test testGmcsSetGetNotificationSubscriptionDoesNotCrash()517 public void testGmcsSetGetNotificationSubscriptionDoesNotCrash() { 518 final ParcelUuid charUuid1 = new ParcelUuid(UUID.randomUUID()); 519 final int ccid1 = BluetoothDevice.METADATA_GMCS_CCCD; 520 521 doReturn(ccid1).when(mMockGMcsService).getContentControlId(); 522 doReturn(BluetoothUuid.GENERIC_MEDIA_CONTROL.getUuid()) 523 .when(mMockGMcsService) 524 .getServiceUuid(); 525 526 // BluetoothDevice class is not mockable 527 BluetoothDevice bluetoothDevice = TestUtils.getTestDevice(mAdapter, 0); 528 mMediaControlProfile.setNotificationSubscription(ccid1, bluetoothDevice, charUuid1, true); 529 Assert.assertNotNull( 530 mMediaControlProfile.getNotificationSubscriptions(ccid1, bluetoothDevice)); 531 } 532 533 @Test testDumpDoesNotCrash()534 public void testDumpDoesNotCrash() { 535 mMediaControlProfile.dump(new StringBuilder()); 536 } 537 } 538