1 /* 2 * Copyright 2021 HIMSA II K/S - www.himsa.com. 3 * Represented by EHIMA - www.ehima.com 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package com.android.bluetooth.mcp; 19 20 import static org.mockito.Mockito.*; 21 22 import android.bluetooth.BluetoothAdapter; 23 import android.bluetooth.BluetoothDevice; 24 import android.bluetooth.BluetoothGatt; 25 import android.bluetooth.BluetoothGattCharacteristic; 26 import android.bluetooth.BluetoothGattDescriptor; 27 import android.bluetooth.BluetoothGattService; 28 import android.bluetooth.BluetoothLeBroadcastMetadata; 29 import android.os.Looper; 30 import android.platform.test.flag.junit.SetFlagsRule; 31 32 import androidx.test.filters.MediumTest; 33 import androidx.test.runner.AndroidJUnit4; 34 35 import com.android.bluetooth.TestUtils; 36 import com.android.bluetooth.btservice.AdapterService; 37 import com.android.bluetooth.le_audio.LeAudioService; 38 39 import org.junit.After; 40 import org.junit.Assert; 41 import org.junit.Before; 42 import org.junit.Rule; 43 import org.junit.Test; 44 import org.junit.runner.RunWith; 45 import org.mockito.ArgumentCaptor; 46 import org.mockito.Captor; 47 import org.mockito.Mock; 48 import org.mockito.junit.MockitoJUnit; 49 import org.mockito.junit.MockitoRule; 50 51 import java.nio.ByteBuffer; 52 import java.nio.ByteOrder; 53 import java.util.ArrayList; 54 import java.util.HashMap; 55 import java.util.List; 56 import java.util.Map; 57 import java.util.UUID; 58 59 @MediumTest 60 @RunWith(AndroidJUnit4.class) 61 public class MediaControlGattServiceTest { 62 private BluetoothAdapter mAdapter; 63 private BluetoothDevice mCurrentDevice; 64 65 private static final UUID UUID_GMCS = UUID.fromString("00001849-0000-1000-8000-00805f9b34fb"); 66 private static final UUID UUID_CCCD = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"); 67 public static final int TEST_CCID = 1; 68 69 @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); 70 71 private MediaControlGattService mMcpService; 72 73 @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); 74 75 @Mock private AdapterService mAdapterService; 76 @Mock private MediaControlGattService.BluetoothGattServerProxy mMockGattServer; 77 @Mock private McpService mMockMcpService; 78 @Mock private LeAudioService mMockLeAudioService; 79 @Mock private MediaControlServiceCallbacks mMockMcsCallbacks; 80 81 @Captor private ArgumentCaptor<BluetoothGattService> mGattServiceCaptor; 82 83 @Before setUp()84 public void setUp() throws Exception { 85 if (Looper.myLooper() == null) { 86 Looper.prepare(); 87 } 88 89 TestUtils.setAdapterService(mAdapterService); 90 mAdapter = BluetoothAdapter.getDefaultAdapter(); 91 92 doReturn(true).when(mMockGattServer).addService(any(BluetoothGattService.class)); 93 doReturn(new BluetoothDevice[0]).when(mAdapterService).getBondedDevices(); 94 95 mMcpService = new MediaControlGattService(mMockMcpService, mMockMcsCallbacks, TEST_CCID); 96 mMcpService.setBluetoothGattServerForTesting(mMockGattServer); 97 mMcpService.setServiceManagerForTesting(mMockMcpService); 98 mMcpService.setLeAudioServiceForTesting(mMockLeAudioService); 99 100 when(mMockMcpService.getDeviceAuthorization(any(BluetoothDevice.class))) 101 .thenReturn(BluetoothDevice.ACCESS_ALLOWED); 102 } 103 104 @After tearDown()105 public void tearDown() throws Exception { 106 mMcpService = null; 107 reset(mMockGattServer); 108 reset(mMockMcpService); 109 reset(mMockMcsCallbacks); 110 reset(mMockLeAudioService); 111 TestUtils.clearAdapterService(mAdapterService); 112 } 113 prepareConnectedDevice()114 private void prepareConnectedDevice() { 115 if (mCurrentDevice == null) { 116 mCurrentDevice = TestUtils.getTestDevice(mAdapter, 0); 117 List<BluetoothDevice> devices = new ArrayList<BluetoothDevice>(); 118 devices.add(mCurrentDevice); 119 doReturn(devices).when(mMockGattServer).getConnectedDevices(); 120 doReturn(true).when(mMockGattServer).isDeviceConnected(eq(mCurrentDevice)); 121 } 122 } 123 prepareConnectedDevicesCccVal( BluetoothGattCharacteristic characteristic, byte[] value)124 private void prepareConnectedDevicesCccVal( 125 BluetoothGattCharacteristic characteristic, byte[] value) { 126 prepareConnectedDevice(); 127 mMcpService.setCcc(mCurrentDevice, characteristic.getUuid(), 0, value, true); 128 } 129 130 @Test testInit()131 public void testInit() { 132 long mMandatoryFeatures = ServiceFeature.ALL_MANDATORY_SERVICE_FEATURES; 133 134 doReturn(mMandatoryFeatures).when(mMockMcsCallbacks).onGetFeatureFlags(); 135 Assert.assertTrue(mMcpService.init(UUID_GMCS)); 136 Assert.assertEquals(mMcpService.getServiceUuid(), UUID_GMCS); 137 Assert.assertEquals(mMcpService.getContentControlId(), TEST_CCID); 138 139 doReturn(true).when(mMockGattServer).removeService(any(BluetoothGattService.class)); 140 mMcpService.destroy(); 141 verify(mMockMcsCallbacks).onServiceInstanceUnregistered(eq(ServiceStatus.OK)); 142 } 143 144 @Test testFailingInit()145 public void testFailingInit() { 146 long mMandatoryFeatures = 0; 147 148 doReturn(mMandatoryFeatures).when(mMockMcsCallbacks).onGetFeatureFlags(); 149 Assert.assertFalse(mMcpService.init(UUID_GMCS)); 150 } 151 initAllFeaturesGattService()152 private BluetoothGattService initAllFeaturesGattService() { 153 long features = 154 ServiceFeature.ALL_MANDATORY_SERVICE_FEATURES 155 | ServiceFeature.PLAYER_ICON_OBJ_ID 156 | ServiceFeature.PLAYER_ICON_URL 157 | ServiceFeature.PLAYBACK_SPEED 158 | ServiceFeature.SEEKING_SPEED 159 | ServiceFeature.CURRENT_TRACK_SEGMENT_OBJ_ID 160 | ServiceFeature.CURRENT_TRACK_OBJ_ID 161 | ServiceFeature.NEXT_TRACK_OBJ_ID 162 | ServiceFeature.CURRENT_GROUP_OBJ_ID 163 | ServiceFeature.PARENT_GROUP_OBJ_ID 164 | ServiceFeature.PLAYING_ORDER 165 | ServiceFeature.PLAYING_ORDER_SUPPORTED 166 | ServiceFeature.MEDIA_CONTROL_POINT 167 | ServiceFeature.MEDIA_CONTROL_POINT_OPCODES_SUPPORTED 168 | ServiceFeature.SEARCH_RESULT_OBJ_ID 169 | ServiceFeature.SEARCH_CONTROL_POINT 170 // Notifications 171 | ServiceFeature.PLAYER_NAME_NOTIFY 172 | ServiceFeature.TRACK_TITLE_NOTIFY 173 | ServiceFeature.TRACK_DURATION_NOTIFY 174 | ServiceFeature.TRACK_POSITION_NOTIFY 175 | ServiceFeature.PLAYBACK_SPEED_NOTIFY 176 | ServiceFeature.SEEKING_SPEED_NOTIFY 177 | ServiceFeature.CURRENT_TRACK_OBJ_ID_NOTIFY 178 | ServiceFeature.NEXT_TRACK_OBJ_ID_NOTIFY 179 | ServiceFeature.CURRENT_GROUP_OBJ_ID_NOTIFY 180 | ServiceFeature.PARENT_GROUP_OBJ_ID_NOTIFY 181 | ServiceFeature.PLAYING_ORDER_NOTIFY 182 | ServiceFeature.MEDIA_CONTROL_POINT_OPCODES_SUPPORTED_NOTIFY; 183 184 doReturn(features).when(mMockMcsCallbacks).onGetFeatureFlags(); 185 Assert.assertTrue(mMcpService.init(UUID_GMCS)); 186 187 verify(mMockGattServer).addService(mGattServiceCaptor.capture()); 188 189 // Capture GATT Service definition for verification 190 BluetoothGattService service = mGattServiceCaptor.getValue(); 191 Assert.assertNotNull(service); 192 193 // Call back the low level GATT callback and expect proper higher level callback to be 194 // called 195 mMcpService.mServerCallback.onServiceAdded(BluetoothGatt.GATT_SUCCESS, service); 196 verify(mMockMcsCallbacks) 197 .onServiceInstanceRegistered( 198 any(ServiceStatus.class), any(MediaControlGattServiceInterface.class)); 199 200 return service; 201 } 202 203 @Test testGattServerFullInitialState()204 public void testGattServerFullInitialState() { 205 BluetoothGattService service = initAllFeaturesGattService(); 206 207 // Check initial state of all mandatory characteristics 208 BluetoothGattCharacteristic characteristic = 209 service.getCharacteristic(MediaControlGattService.UUID_PLAYER_NAME); 210 Assert.assertNotNull(characteristic); 211 Assert.assertEquals( 212 characteristic.getProperties(), 213 BluetoothGattCharacteristic.PROPERTY_READ 214 | BluetoothGattCharacteristic.PROPERTY_NOTIFY); 215 Assert.assertEquals("", characteristic.getStringValue(0)); 216 217 characteristic = service.getCharacteristic(MediaControlGattService.UUID_TRACK_TITLE); 218 Assert.assertNotNull(characteristic); 219 Assert.assertEquals( 220 characteristic.getProperties(), 221 BluetoothGattCharacteristic.PROPERTY_READ 222 | BluetoothGattCharacteristic.PROPERTY_NOTIFY); 223 Assert.assertEquals("", characteristic.getStringValue(0)); 224 225 characteristic = service.getCharacteristic(MediaControlGattService.UUID_TRACK_DURATION); 226 Assert.assertNotNull(characteristic); 227 Assert.assertEquals( 228 characteristic.getProperties(), 229 BluetoothGattCharacteristic.PROPERTY_READ 230 | BluetoothGattCharacteristic.PROPERTY_NOTIFY); 231 Assert.assertEquals( 232 0xFFFFFFFF, 233 characteristic 234 .getIntValue(BluetoothGattCharacteristic.FORMAT_SINT32, 0) 235 .intValue()); 236 237 characteristic = service.getCharacteristic(MediaControlGattService.UUID_TRACK_POSITION); 238 Assert.assertNotNull(characteristic); 239 Assert.assertEquals( 240 characteristic.getProperties(), 241 BluetoothGattCharacteristic.PROPERTY_READ 242 | BluetoothGattCharacteristic.PROPERTY_WRITE 243 | BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE 244 | BluetoothGattCharacteristic.PROPERTY_NOTIFY); 245 Assert.assertEquals( 246 0xFFFFFFFF, 247 characteristic 248 .getIntValue(BluetoothGattCharacteristic.FORMAT_SINT32, 0) 249 .intValue()); 250 251 characteristic = service.getCharacteristic(MediaControlGattService.UUID_MEDIA_STATE); 252 Assert.assertNotNull(characteristic); 253 Assert.assertEquals( 254 characteristic.getProperties(), 255 BluetoothGattCharacteristic.PROPERTY_READ 256 | BluetoothGattCharacteristic.PROPERTY_NOTIFY); 257 Assert.assertEquals( 258 MediaState.INACTIVE.getValue(), 259 characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0).intValue()); 260 261 characteristic = service.getCharacteristic(MediaControlGattService.UUID_CONTENT_CONTROL_ID); 262 Assert.assertNotNull(characteristic); 263 Assert.assertEquals( 264 characteristic.getProperties(), BluetoothGattCharacteristic.PROPERTY_READ); 265 Assert.assertEquals( 266 TEST_CCID, 267 characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0).intValue()); 268 269 // Check initial state of all optional characteristics 270 characteristic = service.getCharacteristic(MediaControlGattService.UUID_PLAYER_ICON_OBJ_ID); 271 Assert.assertNotNull(characteristic); 272 Assert.assertEquals( 273 characteristic.getProperties(), BluetoothGattCharacteristic.PROPERTY_READ); 274 Assert.assertTrue(characteristic.getValue().length == 0); 275 276 characteristic = service.getCharacteristic(MediaControlGattService.UUID_PLAYER_ICON_URL); 277 Assert.assertNotNull(characteristic); 278 Assert.assertEquals( 279 characteristic.getProperties(), BluetoothGattCharacteristic.PROPERTY_READ); 280 Assert.assertEquals("", characteristic.getStringValue(0)); 281 282 characteristic = service.getCharacteristic(MediaControlGattService.UUID_TRACK_CHANGED); 283 Assert.assertNotNull(characteristic); 284 Assert.assertEquals( 285 characteristic.getProperties(), BluetoothGattCharacteristic.PROPERTY_NOTIFY); 286 287 characteristic = service.getCharacteristic(MediaControlGattService.UUID_PLAYBACK_SPEED); 288 Assert.assertNotNull(characteristic); 289 Assert.assertEquals( 290 characteristic.getProperties(), 291 BluetoothGattCharacteristic.PROPERTY_READ 292 | BluetoothGattCharacteristic.PROPERTY_WRITE 293 | BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE 294 | BluetoothGattCharacteristic.PROPERTY_NOTIFY); 295 Assert.assertEquals( 296 0, 297 characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_SINT8, 0).intValue()); 298 299 characteristic = service.getCharacteristic(MediaControlGattService.UUID_SEEKING_SPEED); 300 Assert.assertNotNull(characteristic); 301 Assert.assertEquals( 302 characteristic.getProperties(), 303 BluetoothGattCharacteristic.PROPERTY_READ 304 | BluetoothGattCharacteristic.PROPERTY_NOTIFY); 305 Assert.assertEquals( 306 0, 307 characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_SINT8, 0).intValue()); 308 309 characteristic = 310 service.getCharacteristic( 311 MediaControlGattService.UUID_CURRENT_TRACK_SEGMENT_OBJ_ID); 312 Assert.assertNotNull(characteristic); 313 Assert.assertEquals( 314 characteristic.getProperties(), BluetoothGattCharacteristic.PROPERTY_READ); 315 Assert.assertTrue(characteristic.getValue().length == 0); 316 317 characteristic = 318 service.getCharacteristic(MediaControlGattService.UUID_CURRENT_TRACK_OBJ_ID); 319 Assert.assertNotNull(characteristic); 320 Assert.assertEquals( 321 characteristic.getProperties(), 322 BluetoothGattCharacteristic.PROPERTY_READ 323 | BluetoothGattCharacteristic.PROPERTY_WRITE 324 | BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE 325 | BluetoothGattCharacteristic.PROPERTY_NOTIFY); 326 Assert.assertTrue(characteristic.getValue().length == 0); 327 328 characteristic = service.getCharacteristic(MediaControlGattService.UUID_NEXT_TRACK_OBJ_ID); 329 Assert.assertNotNull(characteristic); 330 Assert.assertEquals( 331 characteristic.getProperties(), 332 BluetoothGattCharacteristic.PROPERTY_READ 333 | BluetoothGattCharacteristic.PROPERTY_WRITE 334 | BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE 335 | BluetoothGattCharacteristic.PROPERTY_NOTIFY); 336 Assert.assertTrue(characteristic.getValue().length == 0); 337 338 characteristic = 339 service.getCharacteristic(MediaControlGattService.UUID_CURRENT_GROUP_OBJ_ID); 340 Assert.assertNotNull(characteristic); 341 Assert.assertEquals( 342 characteristic.getProperties(), 343 BluetoothGattCharacteristic.PROPERTY_READ 344 | BluetoothGattCharacteristic.PROPERTY_WRITE 345 | BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE 346 | BluetoothGattCharacteristic.PROPERTY_NOTIFY); 347 Assert.assertTrue(characteristic.getValue().length == 0); 348 349 characteristic = 350 service.getCharacteristic(MediaControlGattService.UUID_PARENT_GROUP_OBJ_ID); 351 Assert.assertNotNull(characteristic); 352 Assert.assertEquals( 353 characteristic.getProperties(), 354 BluetoothGattCharacteristic.PROPERTY_READ 355 | BluetoothGattCharacteristic.PROPERTY_NOTIFY); 356 Assert.assertTrue(characteristic.getValue().length == 0); 357 358 characteristic = service.getCharacteristic(MediaControlGattService.UUID_PLAYING_ORDER); 359 Assert.assertNotNull(characteristic); 360 Assert.assertEquals( 361 characteristic.getProperties(), 362 BluetoothGattCharacteristic.PROPERTY_READ 363 | BluetoothGattCharacteristic.PROPERTY_WRITE 364 | BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE 365 | BluetoothGattCharacteristic.PROPERTY_NOTIFY); 366 Assert.assertEquals( 367 PlayingOrder.SINGLE_ONCE.getValue(), 368 characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0).intValue()); 369 370 characteristic = 371 service.getCharacteristic(MediaControlGattService.UUID_PLAYING_ORDER_SUPPORTED); 372 Assert.assertNotNull(characteristic); 373 Assert.assertEquals( 374 characteristic.getProperties(), BluetoothGattCharacteristic.PROPERTY_READ); 375 Assert.assertEquals( 376 SupportedPlayingOrder.SINGLE_ONCE, 377 characteristic 378 .getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, 0) 379 .intValue()); 380 381 characteristic = 382 service.getCharacteristic(MediaControlGattService.UUID_MEDIA_CONTROL_POINT); 383 Assert.assertNotNull(characteristic); 384 Assert.assertEquals( 385 characteristic.getProperties(), 386 BluetoothGattCharacteristic.PROPERTY_NOTIFY 387 | BluetoothGattCharacteristic.PROPERTY_WRITE 388 | BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE); 389 390 characteristic = 391 service.getCharacteristic( 392 MediaControlGattService.UUID_MEDIA_CONTROL_POINT_OPCODES_SUPPORTED); 393 Assert.assertNotNull(characteristic); 394 Assert.assertEquals( 395 characteristic.getProperties(), 396 BluetoothGattCharacteristic.PROPERTY_READ 397 | BluetoothGattCharacteristic.PROPERTY_NOTIFY); 398 Assert.assertEquals( 399 MediaControlGattService.INITIAL_SUPPORTED_OPCODES, 400 characteristic 401 .getIntValue(BluetoothGattCharacteristic.FORMAT_UINT32, 0) 402 .intValue()); 403 404 characteristic = 405 service.getCharacteristic(MediaControlGattService.UUID_SEARCH_RESULT_OBJ_ID); 406 Assert.assertNotNull(characteristic); 407 Assert.assertEquals( 408 characteristic.getProperties(), 409 BluetoothGattCharacteristic.PROPERTY_READ 410 | BluetoothGattCharacteristic.PROPERTY_NOTIFY); 411 Assert.assertTrue(characteristic.getValue().length == 0); 412 413 characteristic = 414 service.getCharacteristic(MediaControlGattService.UUID_SEARCH_CONTROL_POINT); 415 Assert.assertNotNull(characteristic); 416 Assert.assertEquals( 417 characteristic.getProperties(), 418 BluetoothGattCharacteristic.PROPERTY_NOTIFY 419 | BluetoothGattCharacteristic.PROPERTY_WRITE 420 | BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE); 421 } 422 423 @Test testUpdatePlayerState()424 public void testUpdatePlayerState() { 425 BluetoothGattService service = initAllFeaturesGattService(); 426 Map<PlayerStateField, Object> state_map = new HashMap<>(); 427 float playback_speed = 0.5f; 428 PlayingOrder playing_order = PlayingOrder.IN_ORDER_REPEAT; 429 long track_position = 100; 430 String player_name = "TestPlayerName"; 431 String icon_url = "www.testiconurl.com"; 432 Long icon_obj_id = 7L; 433 Integer playing_order_supported = 434 SupportedPlayingOrder.IN_ORDER_REPEAT 435 | SupportedPlayingOrder.SINGLE_ONCE 436 | SupportedPlayingOrder.SINGLE_REPEAT 437 | SupportedPlayingOrder.IN_ORDER_ONCE 438 | SupportedPlayingOrder.IN_ORDER_REPEAT 439 | SupportedPlayingOrder.OLDEST_ONCE 440 | SupportedPlayingOrder.OLDEST_REPEAT 441 | SupportedPlayingOrder.NEWEST_ONCE 442 | SupportedPlayingOrder.NEWEST_REPEAT 443 | SupportedPlayingOrder.SHUFFLE_ONCE 444 | SupportedPlayingOrder.SHUFFLE_REPEAT; 445 Integer opcodes_supported = 446 Request.SupportedOpcodes.NONE 447 | Request.SupportedOpcodes.PLAY 448 | Request.SupportedOpcodes.PAUSE 449 | Request.SupportedOpcodes.FAST_REWIND 450 | Request.SupportedOpcodes.FAST_FORWARD 451 | Request.SupportedOpcodes.STOP 452 | Request.SupportedOpcodes.MOVE_RELATIVE 453 | Request.SupportedOpcodes.PREVIOUS_SEGMENT 454 | Request.SupportedOpcodes.NEXT_SEGMENT 455 | Request.SupportedOpcodes.FIRST_SEGMENT 456 | Request.SupportedOpcodes.LAST_SEGMENT 457 | Request.SupportedOpcodes.GOTO_SEGMENT 458 | Request.SupportedOpcodes.PREVIOUS_TRACK 459 | Request.SupportedOpcodes.NEXT_TRACK 460 | Request.SupportedOpcodes.FIRST_TRACK 461 | Request.SupportedOpcodes.LAST_TRACK 462 | Request.SupportedOpcodes.GOTO_TRACK 463 | Request.SupportedOpcodes.PREVIOUS_GROUP 464 | Request.SupportedOpcodes.NEXT_GROUP 465 | Request.SupportedOpcodes.FIRST_GROUP 466 | Request.SupportedOpcodes.LAST_GROUP; 467 String track_title = "Test Song"; 468 long track_duration = 1000; 469 MediaState playback_state = MediaState.SEEKING; 470 float seeking_speed = 2.0f; 471 472 state_map.put(PlayerStateField.PLAYBACK_SPEED, playback_speed); 473 state_map.put(PlayerStateField.PLAYING_ORDER, playing_order); 474 state_map.put(PlayerStateField.TRACK_POSITION, track_position); 475 state_map.put(PlayerStateField.PLAYER_NAME, player_name); 476 state_map.put(PlayerStateField.ICON_URL, icon_url); 477 state_map.put(PlayerStateField.ICON_OBJ_ID, icon_obj_id); 478 state_map.put(PlayerStateField.PLAYING_ORDER_SUPPORTED, playing_order_supported); 479 state_map.put(PlayerStateField.OPCODES_SUPPORTED, opcodes_supported); 480 state_map.put(PlayerStateField.TRACK_TITLE, track_title); 481 state_map.put(PlayerStateField.TRACK_DURATION, track_duration); 482 state_map.put(PlayerStateField.PLAYBACK_STATE, playback_state); 483 state_map.put(PlayerStateField.SEEKING_SPEED, seeking_speed); 484 mMcpService.updatePlayerState(state_map); 485 486 BluetoothGattCharacteristic characteristic = 487 service.getCharacteristic(MediaControlGattService.UUID_PLAYBACK_SPEED); 488 Assert.assertNotNull(characteristic); 489 Assert.assertEquals( 490 playback_speed, mMcpService.getPlaybackSpeedChar().floatValue(), 0.001f); 491 492 characteristic = service.getCharacteristic(MediaControlGattService.UUID_PLAYING_ORDER); 493 Assert.assertNotNull(characteristic); 494 Assert.assertEquals( 495 playing_order.getValue(), 496 characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0).intValue()); 497 498 characteristic = service.getCharacteristic(MediaControlGattService.UUID_TRACK_POSITION); 499 Assert.assertNotNull(characteristic); 500 // Set value as ms, kept in characteristic as 0.01s 501 Assert.assertEquals( 502 track_position / 10, 503 characteristic 504 .getIntValue(BluetoothGattCharacteristic.FORMAT_SINT32, 0) 505 .intValue()); 506 507 characteristic = service.getCharacteristic(MediaControlGattService.UUID_PLAYER_NAME); 508 Assert.assertNotNull(characteristic); 509 Assert.assertEquals(player_name, characteristic.getStringValue(0)); 510 511 characteristic = service.getCharacteristic(MediaControlGattService.UUID_PLAYER_ICON_URL); 512 Assert.assertNotNull(characteristic); 513 Assert.assertEquals(icon_url, characteristic.getStringValue(0)); 514 515 characteristic = service.getCharacteristic(MediaControlGattService.UUID_PLAYER_ICON_OBJ_ID); 516 Assert.assertNotNull(characteristic); 517 Assert.assertEquals( 518 icon_obj_id.longValue(), mMcpService.byteArray2ObjId(characteristic.getValue())); 519 520 characteristic = 521 service.getCharacteristic(MediaControlGattService.UUID_PLAYING_ORDER_SUPPORTED); 522 Assert.assertNotNull(characteristic); 523 Assert.assertEquals( 524 playing_order_supported.intValue(), 525 characteristic 526 .getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, 0) 527 .intValue()); 528 529 characteristic = 530 service.getCharacteristic( 531 MediaControlGattService.UUID_MEDIA_CONTROL_POINT_OPCODES_SUPPORTED); 532 Assert.assertNotNull(characteristic); 533 Assert.assertEquals( 534 opcodes_supported.intValue(), 535 characteristic 536 .getIntValue(BluetoothGattCharacteristic.FORMAT_UINT32, 0) 537 .intValue()); 538 539 characteristic = service.getCharacteristic(MediaControlGattService.UUID_TRACK_TITLE); 540 Assert.assertNotNull(characteristic); 541 Assert.assertEquals(track_title, characteristic.getStringValue(0)); 542 543 characteristic = service.getCharacteristic(MediaControlGattService.UUID_TRACK_DURATION); 544 Assert.assertNotNull(characteristic); 545 // Set value as ms, kept in characteristic as 0.01s 546 Assert.assertEquals( 547 track_duration / 10, 548 characteristic 549 .getIntValue(BluetoothGattCharacteristic.FORMAT_SINT32, 0) 550 .intValue()); 551 552 characteristic = service.getCharacteristic(MediaControlGattService.UUID_MEDIA_STATE); 553 Assert.assertNotNull(characteristic); 554 Assert.assertEquals( 555 playback_state.getValue(), 556 characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0).intValue()); 557 558 characteristic = service.getCharacteristic(MediaControlGattService.UUID_SEEKING_SPEED); 559 Assert.assertNotNull(characteristic); 560 Assert.assertEquals(seeking_speed, mMcpService.getSeekingSpeedChar().floatValue(), 0.001f); 561 } 562 verifyWriteObjIdsValid( BluetoothGattCharacteristic characteristic, long value, int id)563 private void verifyWriteObjIdsValid( 564 BluetoothGattCharacteristic characteristic, long value, int id) { 565 mMcpService.mServerCallback.onCharacteristicWriteRequest( 566 mCurrentDevice, 567 1, 568 characteristic, 569 false, 570 true, 571 0, 572 mMcpService.objId2ByteArray(value)); 573 574 verify(mMockMcsCallbacks).onSetObjectIdRequest(eq(id), eq(value)); 575 576 verify(mMockGattServer) 577 .sendResponse( 578 eq(mCurrentDevice), 579 eq(1), 580 eq(BluetoothGatt.GATT_SUCCESS), 581 eq(0), 582 eq(mMcpService.objId2ByteArray(value))); 583 } 584 585 @Test testWriteCallbacksValid()586 public void testWriteCallbacksValid() { 587 BluetoothGattService service = initAllFeaturesGattService(); 588 int track_position = 100; 589 byte playback_speed = 64; 590 long current_track_obj_id = 7; 591 long next_track_obj_id = 77; 592 long current_group_obj_id = 777; 593 PlayingOrder playing_order = PlayingOrder.IN_ORDER_REPEAT; 594 Integer playing_order_supported = SupportedPlayingOrder.IN_ORDER_REPEAT; 595 596 BluetoothGattCharacteristic characteristic = 597 service.getCharacteristic(MediaControlGattService.UUID_TRACK_POSITION); 598 599 ByteBuffer bb = ByteBuffer.allocate(Integer.BYTES).order(ByteOrder.LITTLE_ENDIAN); 600 bb.putInt((int) track_position); 601 602 prepareConnectedDevice(); 603 mMcpService.mServerCallback.onCharacteristicWriteRequest( 604 mCurrentDevice, 1, characteristic, false, true, 0, bb.array()); 605 606 verify(mMockMcsCallbacks).onTrackPositionSetRequest(eq(track_position * 10L)); 607 608 verify(mMockGattServer) 609 .sendResponse( 610 eq(mCurrentDevice), 611 eq(1), 612 eq(BluetoothGatt.GATT_SUCCESS), 613 eq(0), 614 eq(bb.array())); 615 616 characteristic = service.getCharacteristic(MediaControlGattService.UUID_PLAYBACK_SPEED); 617 618 bb = ByteBuffer.allocate(Byte.BYTES); 619 bb.put(playback_speed); 620 621 mMcpService.mServerCallback.onCharacteristicWriteRequest( 622 mCurrentDevice, 1, characteristic, false, true, 0, bb.array()); 623 624 verify(mMockMcsCallbacks) 625 .onPlaybackSpeedSetRequest(eq((float) Math.pow(2, playback_speed / 64.0))); 626 627 verify(mMockGattServer) 628 .sendResponse( 629 eq(mCurrentDevice), 630 eq(1), 631 eq(BluetoothGatt.GATT_SUCCESS), 632 eq(0), 633 eq(bb.array())); 634 635 characteristic = 636 service.getCharacteristic(MediaControlGattService.UUID_CURRENT_TRACK_OBJ_ID); 637 verifyWriteObjIdsValid( 638 characteristic, current_track_obj_id, ObjectIds.CURRENT_TRACK_OBJ_ID); 639 640 characteristic = service.getCharacteristic(MediaControlGattService.UUID_NEXT_TRACK_OBJ_ID); 641 verifyWriteObjIdsValid(characteristic, next_track_obj_id, ObjectIds.NEXT_TRACK_OBJ_ID); 642 643 characteristic = 644 service.getCharacteristic(MediaControlGattService.UUID_CURRENT_GROUP_OBJ_ID); 645 verifyWriteObjIdsValid( 646 characteristic, current_group_obj_id, ObjectIds.CURRENT_GROUP_OBJ_ID); 647 648 characteristic = 649 service.getCharacteristic(MediaControlGattService.UUID_PLAYING_ORDER_SUPPORTED); 650 characteristic.setValue( 651 playing_order_supported, BluetoothGattCharacteristic.FORMAT_UINT16, 0); 652 characteristic = service.getCharacteristic(MediaControlGattService.UUID_PLAYING_ORDER); 653 bb = ByteBuffer.allocate(Byte.BYTES); 654 bb.put((byte) playing_order.getValue()); 655 656 mMcpService.mServerCallback.onCharacteristicWriteRequest( 657 mCurrentDevice, 1, characteristic, false, true, 0, bb.array()); 658 659 verify(mMockMcsCallbacks).onPlayingOrderSetRequest(eq(playing_order.getValue())); 660 661 verify(mMockGattServer) 662 .sendResponse( 663 eq(mCurrentDevice), 664 eq(1), 665 eq(BluetoothGatt.GATT_SUCCESS), 666 eq(0), 667 eq(bb.array())); 668 } 669 verifyWriteObjIdsInvalid( BluetoothGattCharacteristic characteristic, byte diffByte)670 private void verifyWriteObjIdsInvalid( 671 BluetoothGattCharacteristic characteristic, byte diffByte) { 672 byte[] value = new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, diffByte}; 673 mMcpService.mServerCallback.onCharacteristicWriteRequest( 674 mCurrentDevice, 1, characteristic, false, true, 0, value); 675 676 verify(mMockGattServer) 677 .sendResponse( 678 eq(mCurrentDevice), 679 eq(1), 680 eq(BluetoothGatt.GATT_INVALID_ATTRIBUTE_LENGTH), 681 eq(0), 682 eq(value)); 683 } 684 685 @Test testWriteCallbacksInvalid()686 public void testWriteCallbacksInvalid() { 687 BluetoothGattService service = initAllFeaturesGattService(); 688 int track_position = 100; 689 byte playback_speed = 64; 690 PlayingOrder playing_order = PlayingOrder.IN_ORDER_REPEAT; 691 byte diff_byte = 0x00; 692 693 BluetoothGattCharacteristic characteristic = 694 service.getCharacteristic(MediaControlGattService.UUID_TRACK_POSITION); 695 696 ByteBuffer bb = ByteBuffer.allocate(Integer.BYTES + 1).order(ByteOrder.LITTLE_ENDIAN); 697 bb.putInt((int) track_position); 698 bb.put((byte) 0); 699 700 prepareConnectedDevice(); 701 mMcpService.mServerCallback.onCharacteristicWriteRequest( 702 mCurrentDevice, 1, characteristic, false, true, 0, bb.array()); 703 704 verify(mMockGattServer) 705 .sendResponse( 706 eq(mCurrentDevice), 707 eq(1), 708 eq(BluetoothGatt.GATT_INVALID_ATTRIBUTE_LENGTH), 709 eq(0), 710 eq(bb.array())); 711 712 characteristic = service.getCharacteristic(MediaControlGattService.UUID_PLAYBACK_SPEED); 713 714 bb = ByteBuffer.allocate(Byte.BYTES + 1); 715 bb.put(playback_speed); 716 bb.put((byte) 0); 717 718 mMcpService.mServerCallback.onCharacteristicWriteRequest( 719 mCurrentDevice, 1, characteristic, false, true, 0, bb.array()); 720 721 verify(mMockGattServer) 722 .sendResponse( 723 eq(mCurrentDevice), 724 eq(1), 725 eq(BluetoothGatt.GATT_INVALID_ATTRIBUTE_LENGTH), 726 eq(0), 727 eq(bb.array())); 728 729 characteristic = 730 service.getCharacteristic(MediaControlGattService.UUID_CURRENT_TRACK_OBJ_ID); 731 verifyWriteObjIdsInvalid(characteristic, diff_byte++); 732 733 characteristic = service.getCharacteristic(MediaControlGattService.UUID_NEXT_TRACK_OBJ_ID); 734 verifyWriteObjIdsInvalid(characteristic, diff_byte++); 735 736 characteristic = 737 service.getCharacteristic(MediaControlGattService.UUID_CURRENT_GROUP_OBJ_ID); 738 verifyWriteObjIdsInvalid(characteristic, diff_byte++); 739 740 characteristic = service.getCharacteristic(MediaControlGattService.UUID_PLAYING_ORDER); 741 bb = ByteBuffer.allocate(Byte.BYTES + 1); 742 bb.put((byte) playing_order.getValue()); 743 bb.put((byte) 0); 744 745 mMcpService.mServerCallback.onCharacteristicWriteRequest( 746 mCurrentDevice, 1, characteristic, false, true, 0, bb.array()); 747 748 verify(mMockGattServer) 749 .sendResponse( 750 eq(mCurrentDevice), 751 eq(1), 752 eq(BluetoothGatt.GATT_INVALID_ATTRIBUTE_LENGTH), 753 eq(0), 754 eq(bb.array())); 755 } 756 testNotify(boolean registerForNotification)757 private void testNotify(boolean registerForNotification) { 758 BluetoothGattService service = initAllFeaturesGattService(); 759 String player_name = "TestPlayerName"; 760 String track_title = "Test Song"; 761 long track_duration = 1000; 762 long track_position = 100; 763 float playback_speed = 0.5f; 764 float seeking_speed = 2.0f; 765 Long obj_id = 7L; 766 PlayingOrder playing_order = PlayingOrder.IN_ORDER_REPEAT; 767 int playing_order_supported = SupportedPlayingOrder.IN_ORDER_REPEAT; 768 int playback_state = MediaState.SEEKING.getValue(); 769 Integer opcodes_supported = 770 Request.SupportedOpcodes.NONE 771 | Request.SupportedOpcodes.PLAY 772 | Request.SupportedOpcodes.PAUSE 773 | Request.SupportedOpcodes.FAST_REWIND 774 | Request.SupportedOpcodes.FAST_FORWARD 775 | Request.SupportedOpcodes.STOP 776 | Request.SupportedOpcodes.MOVE_RELATIVE 777 | Request.SupportedOpcodes.PREVIOUS_SEGMENT 778 | Request.SupportedOpcodes.NEXT_SEGMENT 779 | Request.SupportedOpcodes.FIRST_SEGMENT 780 | Request.SupportedOpcodes.LAST_SEGMENT 781 | Request.SupportedOpcodes.GOTO_SEGMENT 782 | Request.SupportedOpcodes.PREVIOUS_TRACK 783 | Request.SupportedOpcodes.NEXT_TRACK 784 | Request.SupportedOpcodes.FIRST_TRACK 785 | Request.SupportedOpcodes.LAST_TRACK 786 | Request.SupportedOpcodes.GOTO_TRACK 787 | Request.SupportedOpcodes.PREVIOUS_GROUP 788 | Request.SupportedOpcodes.NEXT_GROUP 789 | Request.SupportedOpcodes.FIRST_GROUP 790 | Request.SupportedOpcodes.LAST_GROUP; 791 byte[] ccc_val = 792 registerForNotification 793 ? BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE.clone() 794 : BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE.clone(); 795 int times_cnt = registerForNotification ? 1 : 0; 796 int media_control_request_opcode = Request.Opcodes.MOVE_RELATIVE; 797 798 BluetoothGattCharacteristic characteristic = 799 service.getCharacteristic(MediaControlGattService.UUID_PLAYER_NAME); 800 prepareConnectedDevicesCccVal(characteristic, ccc_val); 801 mMcpService.updatePlayerNameChar(player_name, true); 802 verify(mMockGattServer, times(times_cnt)) 803 .notifyCharacteristicChanged(eq(mCurrentDevice), eq(characteristic), eq(false)); 804 805 characteristic = service.getCharacteristic(MediaControlGattService.UUID_TRACK_TITLE); 806 prepareConnectedDevicesCccVal(characteristic, ccc_val); 807 mMcpService.updateTrackTitleChar(track_title, true); 808 verify(mMockGattServer, times(times_cnt)) 809 .notifyCharacteristicChanged(eq(mCurrentDevice), eq(characteristic), eq(false)); 810 811 characteristic = service.getCharacteristic(MediaControlGattService.UUID_TRACK_DURATION); 812 prepareConnectedDevicesCccVal(characteristic, ccc_val); 813 mMcpService.updateTrackDurationChar(track_duration, true); 814 verify(mMockGattServer, times(times_cnt)) 815 .notifyCharacteristicChanged(eq(mCurrentDevice), eq(characteristic), eq(false)); 816 817 characteristic = service.getCharacteristic(MediaControlGattService.UUID_MEDIA_STATE); 818 prepareConnectedDevicesCccVal(characteristic, ccc_val); 819 mMcpService.updateMediaStateChar(playback_state); 820 verify(mMockGattServer, times(times_cnt)) 821 .notifyCharacteristicChanged(eq(mCurrentDevice), eq(characteristic), eq(false)); 822 823 characteristic = service.getCharacteristic(MediaControlGattService.UUID_TRACK_POSITION); 824 prepareConnectedDevicesCccVal(characteristic, ccc_val); 825 mMcpService.updateTrackPositionChar(track_position, false); 826 verify(mMockGattServer, times(times_cnt)) 827 .notifyCharacteristicChanged(eq(mCurrentDevice), eq(characteristic), eq(false)); 828 829 characteristic = service.getCharacteristic(MediaControlGattService.UUID_PLAYBACK_SPEED); 830 prepareConnectedDevicesCccVal(characteristic, ccc_val); 831 mMcpService.updatePlaybackSpeedChar(playback_speed, true); 832 verify(mMockGattServer, times(times_cnt)) 833 .notifyCharacteristicChanged(eq(mCurrentDevice), eq(characteristic), eq(false)); 834 835 characteristic = service.getCharacteristic(MediaControlGattService.UUID_SEEKING_SPEED); 836 prepareConnectedDevicesCccVal(characteristic, ccc_val); 837 mMcpService.updateSeekingSpeedChar(seeking_speed, true); 838 verify(mMockGattServer, times(times_cnt)) 839 .notifyCharacteristicChanged(eq(mCurrentDevice), eq(characteristic), eq(false)); 840 841 characteristic = 842 service.getCharacteristic(MediaControlGattService.UUID_CURRENT_TRACK_OBJ_ID); 843 prepareConnectedDevicesCccVal(characteristic, ccc_val); 844 mMcpService.updateObjectID(ObjectIds.CURRENT_TRACK_OBJ_ID, obj_id); 845 verify(mMockGattServer, times(times_cnt)) 846 .notifyCharacteristicChanged(eq(mCurrentDevice), eq(characteristic), eq(false)); 847 848 characteristic = service.getCharacteristic(MediaControlGattService.UUID_NEXT_TRACK_OBJ_ID); 849 prepareConnectedDevicesCccVal(characteristic, ccc_val); 850 mMcpService.updateObjectID(ObjectIds.NEXT_TRACK_OBJ_ID, obj_id); 851 verify(mMockGattServer, times(times_cnt)) 852 .notifyCharacteristicChanged(eq(mCurrentDevice), eq(characteristic), eq(false)); 853 854 characteristic = 855 service.getCharacteristic(MediaControlGattService.UUID_CURRENT_GROUP_OBJ_ID); 856 prepareConnectedDevicesCccVal(characteristic, ccc_val); 857 mMcpService.updateObjectID(ObjectIds.CURRENT_GROUP_OBJ_ID, obj_id); 858 verify(mMockGattServer, times(times_cnt)) 859 .notifyCharacteristicChanged(eq(mCurrentDevice), eq(characteristic), eq(false)); 860 861 characteristic = 862 service.getCharacteristic(MediaControlGattService.UUID_PARENT_GROUP_OBJ_ID); 863 prepareConnectedDevicesCccVal(characteristic, ccc_val); 864 mMcpService.updateObjectID(ObjectIds.PARENT_GROUP_OBJ_ID, obj_id); 865 verify(mMockGattServer, times(times_cnt)) 866 .notifyCharacteristicChanged(eq(mCurrentDevice), eq(characteristic), eq(false)); 867 868 characteristic = service.getCharacteristic(MediaControlGattService.UUID_PLAYING_ORDER); 869 prepareConnectedDevicesCccVal(characteristic, ccc_val); 870 mMcpService.updatePlayingOrderSupportedChar(playing_order_supported); 871 mMcpService.updatePlayingOrderChar(playing_order, true); 872 verify(mMockGattServer, times(times_cnt)) 873 .notifyCharacteristicChanged(eq(mCurrentDevice), eq(characteristic), eq(false)); 874 875 characteristic = 876 service.getCharacteristic(MediaControlGattService.UUID_MEDIA_CONTROL_POINT); 877 prepareConnectedDevicesCccVal(characteristic, ccc_val); 878 mMcpService.setMediaControlRequestResult( 879 new Request(media_control_request_opcode, 0), Request.Results.SUCCESS); 880 verify(mMockGattServer, times(times_cnt)) 881 .notifyCharacteristicChanged(eq(mCurrentDevice), eq(characteristic), eq(false)); 882 883 characteristic = 884 service.getCharacteristic( 885 MediaControlGattService.UUID_MEDIA_CONTROL_POINT_OPCODES_SUPPORTED); 886 prepareConnectedDevicesCccVal(characteristic, ccc_val); 887 mMcpService.updateSupportedOpcodesChar(opcodes_supported, true); 888 verify(mMockGattServer, times(times_cnt)) 889 .notifyCharacteristicChanged(eq(mCurrentDevice), eq(characteristic), eq(false)); 890 891 characteristic = 892 service.getCharacteristic(MediaControlGattService.UUID_SEARCH_RESULT_OBJ_ID); 893 prepareConnectedDevicesCccVal(characteristic, ccc_val); 894 mMcpService.updateObjectID(ObjectIds.SEARCH_RESULT_OBJ_ID, obj_id); 895 verify(mMockGattServer, times(times_cnt)) 896 .notifyCharacteristicChanged(eq(mCurrentDevice), eq(characteristic), eq(false)); 897 898 characteristic = 899 service.getCharacteristic(MediaControlGattService.UUID_SEARCH_CONTROL_POINT); 900 prepareConnectedDevicesCccVal(characteristic, ccc_val); 901 mMcpService.setSearchRequestResult(null, SearchRequest.Results.SUCCESS, obj_id); 902 verify(mMockGattServer, times(times_cnt)) 903 .notifyCharacteristicChanged(eq(mCurrentDevice), eq(characteristic), eq(false)); 904 } 905 906 @Test testNotifyRegistered()907 public void testNotifyRegistered() { 908 testNotify(true); 909 } 910 911 @Test testNotifyNotRegistered()912 public void testNotifyNotRegistered() { 913 testNotify(false); 914 } 915 verifyMediaControlPointRequest( int opcode, Integer value, int expectedGattResult, int invocation_count)916 private void verifyMediaControlPointRequest( 917 int opcode, Integer value, int expectedGattResult, int invocation_count) { 918 ByteBuffer bb; 919 920 if (expectedGattResult == BluetoothGatt.GATT_INVALID_ATTRIBUTE_LENGTH) { 921 bb = ByteBuffer.allocate(6).order(ByteOrder.LITTLE_ENDIAN); 922 } else { 923 bb = 924 ByteBuffer.allocate(value != null ? (Integer.BYTES + Byte.BYTES) : Byte.BYTES) 925 .order(ByteOrder.LITTLE_ENDIAN); 926 } 927 bb.put((byte) opcode); 928 if (value != null) { 929 bb.putInt(value); 930 } 931 932 Assert.assertEquals( 933 expectedGattResult, 934 mMcpService.handleMediaControlPointRequest(mCurrentDevice, bb.array())); 935 936 if (expectedGattResult == BluetoothGatt.GATT_SUCCESS) { 937 // Verify if callback comes to profile 938 verify(mMockMcsCallbacks, times(invocation_count++)) 939 .onMediaControlRequest(any(Request.class)); 940 } 941 } 942 verifyMediaControlPointRequests(int expectedGattResult)943 private void verifyMediaControlPointRequests(int expectedGattResult) { 944 BluetoothGattService service = initAllFeaturesGattService(); 945 int invocation_count = 1; 946 Integer opcodes_supported = 947 Request.SupportedOpcodes.PLAY 948 | Request.SupportedOpcodes.PAUSE 949 | Request.SupportedOpcodes.FAST_REWIND 950 | Request.SupportedOpcodes.FAST_FORWARD 951 | Request.SupportedOpcodes.STOP 952 | Request.SupportedOpcodes.MOVE_RELATIVE 953 | Request.SupportedOpcodes.PREVIOUS_SEGMENT 954 | Request.SupportedOpcodes.NEXT_SEGMENT 955 | Request.SupportedOpcodes.FIRST_SEGMENT 956 | Request.SupportedOpcodes.LAST_SEGMENT 957 | Request.SupportedOpcodes.GOTO_SEGMENT 958 | Request.SupportedOpcodes.PREVIOUS_TRACK 959 | Request.SupportedOpcodes.NEXT_TRACK 960 | Request.SupportedOpcodes.FIRST_TRACK 961 | Request.SupportedOpcodes.LAST_TRACK 962 | Request.SupportedOpcodes.GOTO_TRACK 963 | Request.SupportedOpcodes.PREVIOUS_GROUP 964 | Request.SupportedOpcodes.NEXT_GROUP 965 | Request.SupportedOpcodes.FIRST_GROUP 966 | Request.SupportedOpcodes.LAST_GROUP 967 | Request.SupportedOpcodes.GOTO_GROUP; 968 969 BluetoothGattCharacteristic characteristic = 970 service.getCharacteristic( 971 MediaControlGattService.UUID_MEDIA_CONTROL_POINT_OPCODES_SUPPORTED); 972 prepareConnectedDevicesCccVal( 973 characteristic, BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE.clone()); 974 mMcpService.updateSupportedOpcodesChar(opcodes_supported, true); 975 verify(mMockGattServer, times(0)) 976 .notifyCharacteristicChanged(eq(mCurrentDevice), eq(characteristic), eq(false)); 977 978 verifyMediaControlPointRequest( 979 Request.Opcodes.PLAY, null, expectedGattResult, invocation_count++); 980 verifyMediaControlPointRequest( 981 Request.Opcodes.PAUSE, null, expectedGattResult, invocation_count++); 982 verifyMediaControlPointRequest( 983 Request.Opcodes.FAST_REWIND, null, expectedGattResult, invocation_count++); 984 verifyMediaControlPointRequest( 985 Request.Opcodes.FAST_FORWARD, null, expectedGattResult, invocation_count++); 986 verifyMediaControlPointRequest( 987 Request.Opcodes.STOP, null, expectedGattResult, invocation_count++); 988 verifyMediaControlPointRequest( 989 Request.Opcodes.MOVE_RELATIVE, 100, expectedGattResult, invocation_count++); 990 verifyMediaControlPointRequest( 991 Request.Opcodes.PREVIOUS_SEGMENT, null, expectedGattResult, invocation_count++); 992 verifyMediaControlPointRequest( 993 Request.Opcodes.NEXT_SEGMENT, null, expectedGattResult, invocation_count++); 994 verifyMediaControlPointRequest( 995 Request.Opcodes.FIRST_SEGMENT, null, expectedGattResult, invocation_count++); 996 verifyMediaControlPointRequest( 997 Request.Opcodes.LAST_SEGMENT, null, expectedGattResult, invocation_count++); 998 verifyMediaControlPointRequest( 999 Request.Opcodes.GOTO_SEGMENT, 10, expectedGattResult, invocation_count++); 1000 verifyMediaControlPointRequest( 1001 Request.Opcodes.PREVIOUS_TRACK, null, expectedGattResult, invocation_count++); 1002 verifyMediaControlPointRequest( 1003 Request.Opcodes.NEXT_TRACK, null, expectedGattResult, invocation_count++); 1004 verifyMediaControlPointRequest( 1005 Request.Opcodes.FIRST_TRACK, null, expectedGattResult, invocation_count++); 1006 verifyMediaControlPointRequest( 1007 Request.Opcodes.LAST_TRACK, null, expectedGattResult, invocation_count++); 1008 verifyMediaControlPointRequest( 1009 Request.Opcodes.GOTO_TRACK, 7, expectedGattResult, invocation_count++); 1010 verifyMediaControlPointRequest( 1011 Request.Opcodes.PREVIOUS_GROUP, null, expectedGattResult, invocation_count++); 1012 verifyMediaControlPointRequest( 1013 Request.Opcodes.NEXT_GROUP, null, expectedGattResult, invocation_count++); 1014 verifyMediaControlPointRequest( 1015 Request.Opcodes.FIRST_GROUP, null, expectedGattResult, invocation_count++); 1016 verifyMediaControlPointRequest( 1017 Request.Opcodes.LAST_GROUP, null, expectedGattResult, invocation_count++); 1018 verifyMediaControlPointRequest( 1019 Request.Opcodes.GOTO_GROUP, 10, expectedGattResult, invocation_count++); 1020 } 1021 1022 @Test testMediaControlPointRequestValid()1023 public void testMediaControlPointRequestValid() { 1024 verifyMediaControlPointRequests(BluetoothGatt.GATT_SUCCESS); 1025 } 1026 1027 @Test testMediaControlPointRequestInvalidLength()1028 public void testMediaControlPointRequestInvalidLength() { 1029 verifyMediaControlPointRequests(BluetoothGatt.GATT_INVALID_ATTRIBUTE_LENGTH); 1030 } 1031 1032 @Test testMediaControlPointRequestInvalid()1033 public void testMediaControlPointRequestInvalid() { 1034 Assert.assertFalse(mMcpService.isOpcodeSupported(Request.Opcodes.PLAY)); 1035 } 1036 1037 @Test testMediaControlPointeRequest_OpcodePlayCallLeAudioServiceSetActiveDevice()1038 public void testMediaControlPointeRequest_OpcodePlayCallLeAudioServiceSetActiveDevice() { 1039 initAllFeaturesGattService(); 1040 prepareConnectedDevice(); 1041 mMcpService.updateSupportedOpcodesChar(Request.SupportedOpcodes.PLAY, true); 1042 verifyMediaControlPointRequest(Request.Opcodes.PLAY, null, BluetoothGatt.GATT_SUCCESS, 1); 1043 1044 final List<BluetoothLeBroadcastMetadata> metadataList = mock(List.class); 1045 when(mMockLeAudioService.getAllBroadcastMetadata()).thenReturn(metadataList); 1046 verify(mMockMcsCallbacks).onMediaControlRequest(any(Request.class)); 1047 } 1048 1049 @Test testPlaybackSpeedWrite()1050 public void testPlaybackSpeedWrite() { 1051 BluetoothGattService service = initAllFeaturesGattService(); 1052 byte playback_speed = -64; 1053 1054 BluetoothGattCharacteristic characteristic = 1055 service.getCharacteristic(MediaControlGattService.UUID_PLAYBACK_SPEED); 1056 prepareConnectedDevicesCccVal( 1057 characteristic, BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE.clone()); 1058 1059 ByteBuffer bb = ByteBuffer.allocate(Byte.BYTES); 1060 bb.put(playback_speed); 1061 1062 mMcpService.mServerCallback.onCharacteristicWriteRequest( 1063 mCurrentDevice, 1, characteristic, false, true, 0, bb.array()); 1064 1065 verify(mMockMcsCallbacks) 1066 .onPlaybackSpeedSetRequest(eq((float) Math.pow(2, playback_speed / 64.0))); 1067 1068 // Fake characteristic write - this is done by player status update 1069 characteristic.setValue(playback_speed, BluetoothGattCharacteristic.FORMAT_SINT8, 0); 1070 1071 // Second set of the same value - does not bother player only sends notification 1072 mMcpService.mServerCallback.onCharacteristicWriteRequest( 1073 mCurrentDevice, 1, characteristic, false, true, 0, bb.array()); 1074 1075 verify(mMockGattServer) 1076 .notifyCharacteristicChanged(eq(mCurrentDevice), eq(characteristic), eq(false)); 1077 } 1078 1079 @Test testUpdateSupportedOpcodesChar()1080 public void testUpdateSupportedOpcodesChar() { 1081 BluetoothGattService service = initAllFeaturesGattService(); 1082 Integer opcodes_supported = 1083 Request.SupportedOpcodes.PLAY 1084 | Request.SupportedOpcodes.PAUSE 1085 | Request.SupportedOpcodes.FAST_REWIND 1086 | Request.SupportedOpcodes.FAST_FORWARD 1087 | Request.SupportedOpcodes.STOP 1088 | Request.SupportedOpcodes.MOVE_RELATIVE 1089 | Request.SupportedOpcodes.PREVIOUS_SEGMENT 1090 | Request.SupportedOpcodes.NEXT_SEGMENT 1091 | Request.SupportedOpcodes.FIRST_SEGMENT 1092 | Request.SupportedOpcodes.LAST_SEGMENT 1093 | Request.SupportedOpcodes.GOTO_SEGMENT 1094 | Request.SupportedOpcodes.PREVIOUS_TRACK 1095 | Request.SupportedOpcodes.NEXT_TRACK 1096 | Request.SupportedOpcodes.FIRST_TRACK 1097 | Request.SupportedOpcodes.LAST_TRACK 1098 | Request.SupportedOpcodes.GOTO_TRACK 1099 | Request.SupportedOpcodes.PREVIOUS_GROUP 1100 | Request.SupportedOpcodes.NEXT_GROUP 1101 | Request.SupportedOpcodes.FIRST_GROUP 1102 | Request.SupportedOpcodes.LAST_GROUP 1103 | Request.SupportedOpcodes.GOTO_GROUP; 1104 1105 BluetoothGattCharacteristic characteristic = 1106 service.getCharacteristic( 1107 MediaControlGattService.UUID_MEDIA_CONTROL_POINT_OPCODES_SUPPORTED); 1108 prepareConnectedDevicesCccVal( 1109 characteristic, BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE.clone()); 1110 1111 mMcpService.updateSupportedOpcodesChar(opcodes_supported, true); 1112 verify(mMockGattServer) 1113 .notifyCharacteristicChanged(eq(mCurrentDevice), eq(characteristic), eq(false)); 1114 1115 // Verify if there will be no new notification triggered when nothing changes 1116 mMcpService.updateSupportedOpcodesChar(opcodes_supported, true); 1117 verify(mMockGattServer) 1118 .notifyCharacteristicChanged(eq(mCurrentDevice), eq(characteristic), eq(false)); 1119 1120 opcodes_supported = 0; 1121 mMcpService.updateSupportedOpcodesChar(opcodes_supported, true); 1122 verify(mMockGattServer, times(2)) 1123 .notifyCharacteristicChanged(eq(mCurrentDevice), eq(characteristic), eq(false)); 1124 } 1125 1126 @Test testPlayingOrderSupportedChar()1127 public void testPlayingOrderSupportedChar() { 1128 BluetoothGattService service = initAllFeaturesGattService(); 1129 int playing_order_supported = 1130 SupportedPlayingOrder.IN_ORDER_REPEAT | SupportedPlayingOrder.NEWEST_ONCE; 1131 PlayingOrder playing_order = PlayingOrder.IN_ORDER_REPEAT; 1132 ByteBuffer bb = ByteBuffer.allocate(Byte.BYTES); 1133 1134 BluetoothGattCharacteristic characteristic = 1135 service.getCharacteristic(MediaControlGattService.UUID_PLAYING_ORDER); 1136 prepareConnectedDevicesCccVal( 1137 characteristic, BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE.clone()); 1138 1139 mMcpService.updatePlayingOrderSupportedChar(playing_order_supported); 1140 1141 bb.put((byte) playing_order.getValue()); 1142 mMcpService.mServerCallback.onCharacteristicWriteRequest( 1143 mCurrentDevice, 1, characteristic, false, true, 0, bb.array()); 1144 verify(mMockMcsCallbacks).onPlayingOrderSetRequest(anyInt()); 1145 1146 // Not supported playing order should be ignored 1147 playing_order = PlayingOrder.SHUFFLE_ONCE; 1148 bb.put(0, (byte) playing_order.getValue()); 1149 mMcpService.mServerCallback.onCharacteristicWriteRequest( 1150 mCurrentDevice, 1, characteristic, false, true, 0, bb.array()); 1151 verify(mMockMcsCallbacks).onPlayingOrderSetRequest(anyInt()); 1152 1153 playing_order = PlayingOrder.NEWEST_ONCE; 1154 bb.put(0, (byte) playing_order.getValue()); 1155 mMcpService.mServerCallback.onCharacteristicWriteRequest( 1156 mCurrentDevice, 1, characteristic, false, true, 0, bb.array()); 1157 verify(mMockMcsCallbacks, times(2)).onPlayingOrderSetRequest(anyInt()); 1158 } 1159 1160 @Test testCharacteristicReadRejectedUnauthorized()1161 public void testCharacteristicReadRejectedUnauthorized() { 1162 BluetoothGattService service = initAllFeaturesGattService(); 1163 1164 BluetoothGattCharacteristic characteristic = 1165 service.getCharacteristic(MediaControlGattService.UUID_TRACK_POSITION); 1166 1167 prepareConnectedDevice(); 1168 doReturn(BluetoothDevice.ACCESS_REJECTED) 1169 .when(mMockMcpService) 1170 .getDeviceAuthorization(any(BluetoothDevice.class)); 1171 1172 mMcpService.mServerCallback.onCharacteristicReadRequest( 1173 mCurrentDevice, 1, 0, characteristic); 1174 1175 verify(mMockGattServer) 1176 .sendResponse( 1177 eq(mCurrentDevice), 1178 eq(1), 1179 eq(BluetoothGatt.GATT_INSUFFICIENT_AUTHORIZATION), 1180 eq(0), 1181 any()); 1182 } 1183 1184 @Test testCharacteristicNotifyOnAuthorization()1185 public void testCharacteristicNotifyOnAuthorization() { 1186 BluetoothGattService service = initAllFeaturesGattService(); 1187 prepareConnectedDevice(); 1188 1189 // Leave it as unauthorized yet 1190 doReturn(BluetoothDevice.ACCESS_REJECTED) 1191 .when(mMockMcpService) 1192 .getDeviceAuthorization(any(BluetoothDevice.class)); 1193 1194 BluetoothGattCharacteristic characteristic = 1195 service.getCharacteristic(MediaControlGattService.UUID_PLAYING_ORDER_SUPPORTED); 1196 prepareConnectedDevicesCccVal( 1197 characteristic, BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE.clone()); 1198 1199 // Assume no update on some of the characteristics 1200 BluetoothGattCharacteristic characteristic2 = 1201 service.getCharacteristic(MediaControlGattService.UUID_MEDIA_STATE); 1202 prepareConnectedDevicesCccVal( 1203 characteristic2, BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE.clone()); 1204 characteristic2.setValue((byte[]) null); 1205 1206 BluetoothGattCharacteristic characteristic3 = 1207 service.getCharacteristic(MediaControlGattService.UUID_TRACK_CHANGED); 1208 prepareConnectedDevicesCccVal( 1209 characteristic3, BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE.clone()); 1210 characteristic3.setValue((byte[]) null); 1211 1212 // Call it once but expect no notification for the unauthorized device 1213 int playing_order_supported = 1214 SupportedPlayingOrder.IN_ORDER_REPEAT | SupportedPlayingOrder.NEWEST_ONCE; 1215 mMcpService.updatePlayingOrderSupportedChar(playing_order_supported); 1216 verify(mMockGattServer, times(0)) 1217 .notifyCharacteristicChanged(eq(mCurrentDevice), any(), eq(false)); 1218 1219 // Expect a single notification for the just authorized device 1220 doReturn(BluetoothDevice.ACCESS_ALLOWED) 1221 .when(mMockMcpService) 1222 .getDeviceAuthorization(any(BluetoothDevice.class)); 1223 mMcpService.onDeviceAuthorizationSet(mCurrentDevice); 1224 verify(mMockGattServer, times(0)) 1225 .notifyCharacteristicChanged(eq(mCurrentDevice), eq(characteristic2), eq(false)); 1226 verify(mMockGattServer, times(0)) 1227 .notifyCharacteristicChanged(eq(mCurrentDevice), eq(characteristic3), eq(false)); 1228 verify(mMockGattServer) 1229 .notifyCharacteristicChanged(eq(mCurrentDevice), eq(characteristic), eq(false)); 1230 } 1231 1232 @Test testCharacteristicReadUnknownUnauthorized()1233 public void testCharacteristicReadUnknownUnauthorized() { 1234 BluetoothGattService service = initAllFeaturesGattService(); 1235 1236 BluetoothGattCharacteristic characteristic = 1237 service.getCharacteristic(MediaControlGattService.UUID_TRACK_POSITION); 1238 1239 prepareConnectedDevice(); 1240 doReturn(BluetoothDevice.ACCESS_UNKNOWN) 1241 .when(mMockMcpService) 1242 .getDeviceAuthorization(any(BluetoothDevice.class)); 1243 1244 mMcpService.mServerCallback.onCharacteristicReadRequest( 1245 mCurrentDevice, 1, 0, characteristic); 1246 verify(mMockMcpService, times(0)).onDeviceUnauthorized(eq(mCurrentDevice)); 1247 verify(mMockGattServer, times(0)) 1248 .sendResponse( 1249 eq(mCurrentDevice), 1250 eq(1), 1251 eq(BluetoothGatt.GATT_INSUFFICIENT_AUTHORIZATION), 1252 eq(0), 1253 any()); 1254 } 1255 1256 @Test testCharacteristicWriteRejectedUnauthorized()1257 public void testCharacteristicWriteRejectedUnauthorized() { 1258 BluetoothGattService service = initAllFeaturesGattService(); 1259 int track_position = 100; 1260 1261 BluetoothGattCharacteristic characteristic = 1262 service.getCharacteristic(MediaControlGattService.UUID_TRACK_POSITION); 1263 1264 ByteBuffer bb = ByteBuffer.allocate(Integer.BYTES + 1).order(ByteOrder.LITTLE_ENDIAN); 1265 bb.putInt((int) track_position); 1266 bb.put((byte) 0); 1267 1268 prepareConnectedDevice(); 1269 doReturn(BluetoothDevice.ACCESS_REJECTED) 1270 .when(mMockMcpService) 1271 .getDeviceAuthorization(any(BluetoothDevice.class)); 1272 1273 mMcpService.mServerCallback.onCharacteristicWriteRequest( 1274 mCurrentDevice, 1, characteristic, false, true, 0, bb.array()); 1275 1276 verify(mMockGattServer) 1277 .sendResponse( 1278 eq(mCurrentDevice), 1279 eq(1), 1280 eq(BluetoothGatt.GATT_INSUFFICIENT_AUTHORIZATION), 1281 eq(0), 1282 any()); 1283 } 1284 1285 @Test testCharacteristicWriteUnknownUnauthorized()1286 public void testCharacteristicWriteUnknownUnauthorized() { 1287 BluetoothGattService service = initAllFeaturesGattService(); 1288 int track_position = 100; 1289 1290 BluetoothGattCharacteristic characteristic = 1291 service.getCharacteristic(MediaControlGattService.UUID_TRACK_POSITION); 1292 1293 ByteBuffer bb = ByteBuffer.allocate(Integer.BYTES + 1).order(ByteOrder.LITTLE_ENDIAN); 1294 bb.putInt((int) track_position); 1295 bb.put((byte) 0); 1296 1297 prepareConnectedDevice(); 1298 doReturn(BluetoothDevice.ACCESS_UNKNOWN) 1299 .when(mMockMcpService) 1300 .getDeviceAuthorization(any(BluetoothDevice.class)); 1301 1302 mMcpService.mServerCallback.onCharacteristicWriteRequest( 1303 mCurrentDevice, 1, characteristic, false, true, 0, bb.array()); 1304 verify(mMockMcpService).onDeviceUnauthorized(eq(mCurrentDevice)); 1305 } 1306 1307 @Test testDescriptorReadRejectedUnauthorized()1308 public void testDescriptorReadRejectedUnauthorized() { 1309 BluetoothGattService service = initAllFeaturesGattService(); 1310 1311 BluetoothGattDescriptor descriptor = 1312 service.getCharacteristic(MediaControlGattService.UUID_TRACK_POSITION) 1313 .getDescriptor(UUID_CCCD); 1314 Assert.assertNotNull(descriptor); 1315 1316 prepareConnectedDevice(); 1317 doReturn(BluetoothDevice.ACCESS_REJECTED) 1318 .when(mMockMcpService) 1319 .getDeviceAuthorization(any(BluetoothDevice.class)); 1320 1321 mMcpService.mServerCallback.onDescriptorReadRequest(mCurrentDevice, 1, 0, descriptor); 1322 1323 verify(mMockGattServer) 1324 .sendResponse( 1325 eq(mCurrentDevice), 1326 eq(1), 1327 eq(BluetoothGatt.GATT_INSUFFICIENT_AUTHORIZATION), 1328 eq(0), 1329 any()); 1330 } 1331 1332 @Test testDescriptorReadUnknownUnauthorized()1333 public void testDescriptorReadUnknownUnauthorized() { 1334 BluetoothGattService service = initAllFeaturesGattService(); 1335 1336 BluetoothGattDescriptor descriptor = 1337 service.getCharacteristic(MediaControlGattService.UUID_TRACK_POSITION) 1338 .getDescriptor(UUID_CCCD); 1339 Assert.assertNotNull(descriptor); 1340 1341 prepareConnectedDevice(); 1342 doReturn(BluetoothDevice.ACCESS_UNKNOWN) 1343 .when(mMockMcpService) 1344 .getDeviceAuthorization(any(BluetoothDevice.class)); 1345 1346 mMcpService.mServerCallback.onDescriptorReadRequest(mCurrentDevice, 1, 0, descriptor); 1347 verify(mMockMcpService, times(0)).onDeviceUnauthorized(eq(mCurrentDevice)); 1348 verify(mMockGattServer, times(0)) 1349 .sendResponse( 1350 eq(mCurrentDevice), 1351 eq(1), 1352 eq(BluetoothGatt.GATT_INSUFFICIENT_AUTHORIZATION), 1353 eq(0), 1354 any()); 1355 } 1356 1357 @Test testDescriptorWriteRejectedUnauthorized()1358 public void testDescriptorWriteRejectedUnauthorized() { 1359 BluetoothGattService service = initAllFeaturesGattService(); 1360 1361 BluetoothGattDescriptor descriptor = 1362 service.getCharacteristic(MediaControlGattService.UUID_TRACK_POSITION) 1363 .getDescriptor(UUID_CCCD); 1364 Assert.assertNotNull(descriptor); 1365 1366 prepareConnectedDevice(); 1367 doReturn(BluetoothDevice.ACCESS_REJECTED) 1368 .when(mMockMcpService) 1369 .getDeviceAuthorization(any(BluetoothDevice.class)); 1370 1371 ByteBuffer bb = ByteBuffer.allocate(2).order(ByteOrder.LITTLE_ENDIAN); 1372 bb.put((byte) 0); 1373 bb.put((byte) 1); 1374 1375 mMcpService.mServerCallback.onDescriptorWriteRequest( 1376 mCurrentDevice, 1, descriptor, false, true, 0, bb.array()); 1377 1378 verify(mMockGattServer) 1379 .sendResponse( 1380 eq(mCurrentDevice), 1381 eq(1), 1382 eq(BluetoothGatt.GATT_INSUFFICIENT_AUTHORIZATION), 1383 eq(0), 1384 any()); 1385 } 1386 1387 @Test testDescriptorWriteUnknownUnauthorized()1388 public void testDescriptorWriteUnknownUnauthorized() { 1389 BluetoothGattService service = initAllFeaturesGattService(); 1390 1391 BluetoothGattDescriptor descriptor = 1392 service.getCharacteristic(MediaControlGattService.UUID_TRACK_POSITION) 1393 .getDescriptor(UUID_CCCD); 1394 Assert.assertNotNull(descriptor); 1395 1396 prepareConnectedDevice(); 1397 doReturn(BluetoothDevice.ACCESS_UNKNOWN) 1398 .when(mMockMcpService) 1399 .getDeviceAuthorization(any(BluetoothDevice.class)); 1400 1401 ByteBuffer bb = ByteBuffer.allocate(2).order(ByteOrder.LITTLE_ENDIAN); 1402 bb.put((byte) 0); 1403 bb.put((byte) 1); 1404 1405 mMcpService.mServerCallback.onDescriptorWriteRequest( 1406 mCurrentDevice, 1, descriptor, false, true, 0, bb.array()); 1407 verify(mMockMcpService, times(0)).onDeviceUnauthorized(eq(mCurrentDevice)); 1408 verify(mMockGattServer, times(0)) 1409 .sendResponse( 1410 eq(mCurrentDevice), 1411 eq(1), 1412 eq(BluetoothGatt.GATT_INSUFFICIENT_AUTHORIZATION), 1413 eq(0), 1414 any()); 1415 } 1416 1417 @Test testUpdatePlayerNameFromNull()1418 public void testUpdatePlayerNameFromNull() { 1419 BluetoothGattService service = initAllFeaturesGattService(); 1420 1421 BluetoothGattCharacteristic characteristic = 1422 service.getCharacteristic(MediaControlGattService.UUID_PLAYER_NAME); 1423 Assert.assertNotNull(characteristic); 1424 byte[] nullname = null; 1425 characteristic.setValue(nullname); 1426 1427 prepareConnectedDevice(); 1428 doReturn(BluetoothDevice.ACCESS_ALLOWED) 1429 .when(mMockMcpService) 1430 .getDeviceAuthorization(any(BluetoothDevice.class)); 1431 1432 Map<PlayerStateField, Object> state_map = new HashMap<>(); 1433 String player_name = "TestPlayerName"; 1434 state_map.put(PlayerStateField.PLAYER_NAME, player_name); 1435 mMcpService.updatePlayerState(state_map); 1436 } 1437 1438 @Test testUpdatePlayerStateFromNullStateChar()1439 public void testUpdatePlayerStateFromNullStateChar() { 1440 BluetoothGattService service = initAllFeaturesGattService(); 1441 1442 BluetoothGattCharacteristic characteristic = 1443 service.getCharacteristic(MediaControlGattService.UUID_MEDIA_STATE); 1444 Assert.assertNotNull(characteristic); 1445 byte[] nullBytes = null; 1446 characteristic.setValue(nullBytes); 1447 1448 prepareConnectedDevice(); 1449 doReturn(BluetoothDevice.ACCESS_ALLOWED) 1450 .when(mMockMcpService) 1451 .getDeviceAuthorization(any(BluetoothDevice.class)); 1452 1453 Map<PlayerStateField, Object> state_map = new HashMap<>(); 1454 MediaState playback_state = MediaState.SEEKING; 1455 state_map.put(PlayerStateField.PLAYBACK_STATE, playback_state); 1456 mMcpService.updatePlayerState(state_map); 1457 } 1458 1459 @Test testDumpDoesNotCrash()1460 public void testDumpDoesNotCrash() { 1461 mMcpService.dump(new StringBuilder()); 1462 initAllFeaturesGattService(); 1463 mMcpService.dump(new StringBuilder()); 1464 } 1465 } 1466