1 /* 2 * Copyright 2018 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.hearingaid; 18 19 import static org.mockito.Mockito.*; 20 21 import android.bluetooth.BluetoothAdapter; 22 import android.bluetooth.BluetoothDevice; 23 import android.bluetooth.BluetoothHearingAid; 24 import android.bluetooth.BluetoothProfile; 25 import android.bluetooth.BluetoothUuid; 26 import android.content.BroadcastReceiver; 27 import android.content.Context; 28 import android.content.Intent; 29 import android.content.IntentFilter; 30 import android.media.AudioManager; 31 import android.os.Looper; 32 import android.os.ParcelUuid; 33 import android.support.test.InstrumentationRegistry; 34 import android.support.test.filters.MediumTest; 35 import android.support.test.rule.ServiceTestRule; 36 import android.support.test.runner.AndroidJUnit4; 37 38 import com.android.bluetooth.R; 39 import com.android.bluetooth.TestUtils; 40 import com.android.bluetooth.btservice.AdapterService; 41 42 import org.junit.After; 43 import org.junit.Assert; 44 import org.junit.Assume; 45 import org.junit.Before; 46 import org.junit.Rule; 47 import org.junit.Test; 48 import org.junit.runner.RunWith; 49 import org.mockito.Mock; 50 import org.mockito.MockitoAnnotations; 51 52 import java.util.HashMap; 53 import java.util.List; 54 import java.util.concurrent.LinkedBlockingQueue; 55 import java.util.concurrent.TimeoutException; 56 57 @MediumTest 58 @RunWith(AndroidJUnit4.class) 59 public class HearingAidServiceTest { 60 private BluetoothAdapter mAdapter; 61 private Context mTargetContext; 62 private HearingAidService mService; 63 private BluetoothDevice mLeftDevice; 64 private BluetoothDevice mRightDevice; 65 private BluetoothDevice mSingleDevice; 66 private HashMap<BluetoothDevice, LinkedBlockingQueue<Intent>> mDeviceQueueMap; 67 private static final int TIMEOUT_MS = 1000; 68 69 private BroadcastReceiver mHearingAidIntentReceiver; 70 71 @Mock private AdapterService mAdapterService; 72 @Mock private HearingAidNativeInterface mNativeInterface; 73 @Mock private AudioManager mAudioManager; 74 75 @Rule public final ServiceTestRule mServiceRule = new ServiceTestRule(); 76 77 @Before 78 public void setUp() throws Exception { 79 mTargetContext = InstrumentationRegistry.getTargetContext(); 80 Assume.assumeTrue("Ignore test when HearingAidService is not enabled", 81 mTargetContext.getResources().getBoolean(R.bool.profile_supported_hearing_aid)); 82 // Set up mocks and test assets 83 MockitoAnnotations.initMocks(this); 84 85 if (Looper.myLooper() == null) { 86 Looper.prepare(); 87 } 88 89 TestUtils.setAdapterService(mAdapterService); 90 91 mAdapter = BluetoothAdapter.getDefaultAdapter(); 92 93 startService(); 94 mService.mHearingAidNativeInterface = mNativeInterface; 95 mService.mAudioManager = mAudioManager; 96 97 // Override the timeout value to speed up the test 98 HearingAidStateMachine.sConnectTimeoutMs = TIMEOUT_MS; // 1s 99 100 // Set up the Connection State Changed receiver 101 IntentFilter filter = new IntentFilter(); 102 filter.addAction(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED); 103 mHearingAidIntentReceiver = new HearingAidIntentReceiver(); 104 mTargetContext.registerReceiver(mHearingAidIntentReceiver, filter); 105 106 // Get a device for testing 107 mLeftDevice = TestUtils.getTestDevice(mAdapter, 0); 108 mRightDevice = TestUtils.getTestDevice(mAdapter, 1); 109 mSingleDevice = TestUtils.getTestDevice(mAdapter, 2); 110 mDeviceQueueMap = new HashMap<>(); 111 mDeviceQueueMap.put(mLeftDevice, new LinkedBlockingQueue<>()); 112 mDeviceQueueMap.put(mRightDevice, new LinkedBlockingQueue<>()); 113 mDeviceQueueMap.put(mSingleDevice, new LinkedBlockingQueue<>()); 114 mService.setPriority(mLeftDevice, BluetoothProfile.PRIORITY_UNDEFINED); 115 mService.setPriority(mRightDevice, BluetoothProfile.PRIORITY_UNDEFINED); 116 mService.setPriority(mSingleDevice, BluetoothProfile.PRIORITY_UNDEFINED); 117 doReturn(BluetoothDevice.BOND_BONDED).when(mAdapterService) 118 .getBondState(any(BluetoothDevice.class)); 119 doReturn(new ParcelUuid[]{BluetoothUuid.HearingAid}).when(mAdapterService) 120 .getRemoteUuids(any(BluetoothDevice.class)); 121 } 122 123 @After 124 public void tearDown() throws Exception { 125 if (!mTargetContext.getResources().getBoolean(R.bool.profile_supported_hearing_aid)) { 126 return; 127 } 128 stopService(); 129 mTargetContext.unregisterReceiver(mHearingAidIntentReceiver); 130 mDeviceQueueMap.clear(); 131 TestUtils.clearAdapterService(mAdapterService); 132 reset(mAudioManager); 133 } 134 135 private void startService() throws TimeoutException { 136 TestUtils.startService(mServiceRule, HearingAidService.class); 137 mService = HearingAidService.getHearingAidService(); 138 Assert.assertNotNull(mService); 139 } 140 141 private void stopService() throws TimeoutException { 142 TestUtils.stopService(mServiceRule, HearingAidService.class); 143 mService = HearingAidService.getHearingAidService(); 144 Assert.assertNull(mService); 145 } 146 147 private class HearingAidIntentReceiver extends BroadcastReceiver { 148 @Override 149 public void onReceive(Context context, Intent intent) { 150 if (BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED.equals(intent.getAction())) { 151 try { 152 BluetoothDevice device = intent.getParcelableExtra( 153 BluetoothDevice.EXTRA_DEVICE); 154 Assert.assertNotNull(device); 155 LinkedBlockingQueue<Intent> queue = mDeviceQueueMap.get(device); 156 Assert.assertNotNull(queue); 157 queue.put(intent); 158 } catch (InterruptedException e) { 159 Assert.fail("Cannot add Intent to the Connection State queue: " 160 + e.getMessage()); 161 } 162 } 163 } 164 } 165 166 private void verifyConnectionStateIntent(int timeoutMs, BluetoothDevice device, 167 int newState, int prevState) { 168 Intent intent = TestUtils.waitForIntent(timeoutMs, mDeviceQueueMap.get(device)); 169 Assert.assertNotNull(intent); 170 Assert.assertEquals(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED, 171 intent.getAction()); 172 Assert.assertEquals(device, intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)); 173 Assert.assertEquals(newState, intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); 174 Assert.assertEquals(prevState, intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, 175 -1)); 176 } 177 178 private void verifyNoConnectionStateIntent(int timeoutMs, BluetoothDevice device) { 179 Intent intent = TestUtils.waitForNoIntent(timeoutMs, mDeviceQueueMap.get(device)); 180 Assert.assertNull(intent); 181 } 182 183 /** 184 * Test getting HearingAid Service: getHearingAidService() 185 */ 186 @Test 187 public void testGetHearingAidService() { 188 Assert.assertEquals(mService, HearingAidService.getHearingAidService()); 189 } 190 191 /** 192 * Test stop HearingAid Service 193 */ 194 @Test 195 public void testStopHearingAidService() { 196 // Prepare: connect 197 connectDevice(mLeftDevice); 198 // HearingAid Service is already running: test stop(). Note: must be done on the main thread 199 InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { 200 public void run() { 201 Assert.assertTrue(mService.stop()); 202 } 203 }); 204 // Try to restart the service. Note: must be done on the main thread 205 InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { 206 public void run() { 207 Assert.assertTrue(mService.start()); 208 } 209 }); 210 } 211 212 /** 213 * Test get/set priority for BluetoothDevice 214 */ 215 @Test 216 public void testGetSetPriority() { 217 Assert.assertEquals("Initial device priority", 218 BluetoothProfile.PRIORITY_UNDEFINED, 219 mService.getPriority(mLeftDevice)); 220 221 Assert.assertTrue(mService.setPriority(mLeftDevice, BluetoothProfile.PRIORITY_OFF)); 222 Assert.assertEquals("Setting device priority to PRIORITY_OFF", 223 BluetoothProfile.PRIORITY_OFF, 224 mService.getPriority(mLeftDevice)); 225 226 Assert.assertTrue(mService.setPriority(mLeftDevice, BluetoothProfile.PRIORITY_ON)); 227 Assert.assertEquals("Setting device priority to PRIORITY_ON", 228 BluetoothProfile.PRIORITY_ON, 229 mService.getPriority(mLeftDevice)); 230 231 Assert.assertTrue(mService.setPriority(mLeftDevice, 232 BluetoothProfile.PRIORITY_AUTO_CONNECT)); 233 Assert.assertEquals("Setting device priority to PRIORITY_AUTO_CONNECT", 234 BluetoothProfile.PRIORITY_AUTO_CONNECT, 235 mService.getPriority(mLeftDevice)); 236 } 237 238 /** 239 * Test okToConnect method using various test cases 240 */ 241 @Test 242 public void testOkToConnect() { 243 int badPriorityValue = 1024; 244 int badBondState = 42; 245 testOkToConnectCase(mSingleDevice, 246 BluetoothDevice.BOND_NONE, BluetoothProfile.PRIORITY_UNDEFINED, false); 247 testOkToConnectCase(mSingleDevice, 248 BluetoothDevice.BOND_NONE, BluetoothProfile.PRIORITY_OFF, false); 249 testOkToConnectCase(mSingleDevice, 250 BluetoothDevice.BOND_NONE, BluetoothProfile.PRIORITY_ON, false); 251 testOkToConnectCase(mSingleDevice, 252 BluetoothDevice.BOND_NONE, BluetoothProfile.PRIORITY_AUTO_CONNECT, false); 253 testOkToConnectCase(mSingleDevice, 254 BluetoothDevice.BOND_NONE, badPriorityValue, false); 255 testOkToConnectCase(mSingleDevice, 256 BluetoothDevice.BOND_BONDING, BluetoothProfile.PRIORITY_UNDEFINED, true); 257 testOkToConnectCase(mSingleDevice, 258 BluetoothDevice.BOND_BONDING, BluetoothProfile.PRIORITY_OFF, false); 259 testOkToConnectCase(mSingleDevice, 260 BluetoothDevice.BOND_BONDING, BluetoothProfile.PRIORITY_ON, true); 261 testOkToConnectCase(mSingleDevice, 262 BluetoothDevice.BOND_BONDING, BluetoothProfile.PRIORITY_AUTO_CONNECT, true); 263 testOkToConnectCase(mSingleDevice, 264 BluetoothDevice.BOND_BONDING, badPriorityValue, false); 265 testOkToConnectCase(mSingleDevice, 266 BluetoothDevice.BOND_BONDED, BluetoothProfile.PRIORITY_UNDEFINED, true); 267 testOkToConnectCase(mSingleDevice, 268 BluetoothDevice.BOND_BONDED, BluetoothProfile.PRIORITY_OFF, false); 269 testOkToConnectCase(mSingleDevice, 270 BluetoothDevice.BOND_BONDED, BluetoothProfile.PRIORITY_ON, true); 271 testOkToConnectCase(mSingleDevice, 272 BluetoothDevice.BOND_BONDED, BluetoothProfile.PRIORITY_AUTO_CONNECT, true); 273 testOkToConnectCase(mSingleDevice, 274 BluetoothDevice.BOND_BONDED, badPriorityValue, false); 275 testOkToConnectCase(mSingleDevice, 276 badBondState, BluetoothProfile.PRIORITY_UNDEFINED, false); 277 testOkToConnectCase(mSingleDevice, 278 badBondState, BluetoothProfile.PRIORITY_OFF, false); 279 testOkToConnectCase(mSingleDevice, 280 badBondState, BluetoothProfile.PRIORITY_ON, false); 281 testOkToConnectCase(mSingleDevice, 282 badBondState, BluetoothProfile.PRIORITY_AUTO_CONNECT, false); 283 testOkToConnectCase(mSingleDevice, 284 badBondState, badPriorityValue, false); 285 // Restore prirority to undefined for this test device 286 Assert.assertTrue(mService.setPriority(mSingleDevice, BluetoothProfile.PRIORITY_UNDEFINED)); 287 } 288 289 /** 290 * Test that an outgoing connection to device that does not have Hearing Aid UUID is rejected 291 */ 292 @Test 293 public void testOutgoingConnectMissingHearingAidUuid() { 294 // Update the device priority so okToConnect() returns true 295 mService.setPriority(mLeftDevice, BluetoothProfile.PRIORITY_ON); 296 mService.setPriority(mRightDevice, BluetoothProfile.PRIORITY_OFF); 297 mService.setPriority(mSingleDevice, BluetoothProfile.PRIORITY_OFF); 298 doReturn(true).when(mNativeInterface).connectHearingAid(any(BluetoothDevice.class)); 299 doReturn(true).when(mNativeInterface).disconnectHearingAid(any(BluetoothDevice.class)); 300 301 // Return No UUID 302 doReturn(new ParcelUuid[]{}).when(mAdapterService) 303 .getRemoteUuids(any(BluetoothDevice.class)); 304 305 // Send a connect request 306 Assert.assertFalse("Connect expected to fail", mService.connect(mLeftDevice)); 307 } 308 309 /** 310 * Test that an outgoing connection to device with PRIORITY_OFF is rejected 311 */ 312 @Test 313 public void testOutgoingConnectPriorityOff() { 314 doReturn(true).when(mNativeInterface).connectHearingAid(any(BluetoothDevice.class)); 315 doReturn(true).when(mNativeInterface).disconnectHearingAid(any(BluetoothDevice.class)); 316 317 // Set the device priority to PRIORITY_OFF so connect() should fail 318 mService.setPriority(mLeftDevice, BluetoothProfile.PRIORITY_OFF); 319 320 // Send a connect request 321 Assert.assertFalse("Connect expected to fail", mService.connect(mLeftDevice)); 322 } 323 324 /** 325 * Test that an outgoing connection times out 326 */ 327 @Test 328 public void testOutgoingConnectTimeout() { 329 // Update the device priority so okToConnect() returns true 330 mService.setPriority(mLeftDevice, BluetoothProfile.PRIORITY_ON); 331 mService.setPriority(mRightDevice, BluetoothProfile.PRIORITY_OFF); 332 mService.setPriority(mSingleDevice, BluetoothProfile.PRIORITY_OFF); 333 doReturn(true).when(mNativeInterface).connectHearingAid(any(BluetoothDevice.class)); 334 doReturn(true).when(mNativeInterface).disconnectHearingAid(any(BluetoothDevice.class)); 335 336 // Send a connect request 337 Assert.assertTrue("Connect failed", mService.connect(mLeftDevice)); 338 339 // Verify the connection state broadcast, and that we are in Connecting state 340 verifyConnectionStateIntent(TIMEOUT_MS, mLeftDevice, BluetoothProfile.STATE_CONNECTING, 341 BluetoothProfile.STATE_DISCONNECTED); 342 Assert.assertEquals(BluetoothProfile.STATE_CONNECTING, 343 mService.getConnectionState(mLeftDevice)); 344 345 // Verify the connection state broadcast, and that we are in Disconnected state 346 verifyConnectionStateIntent(HearingAidStateMachine.sConnectTimeoutMs * 2, mLeftDevice, 347 BluetoothProfile.STATE_DISCONNECTED, 348 BluetoothProfile.STATE_CONNECTING); 349 Assert.assertEquals(BluetoothProfile.STATE_DISCONNECTED, 350 mService.getConnectionState(mLeftDevice)); 351 } 352 353 /** 354 * Test that the Hearing Aid Service connects to left and right device at the same time. 355 */ 356 @Test 357 public void testConnectAPair_connectBothDevices() { 358 // Update hiSyncId map 359 getHiSyncIdFromNative(); 360 // Update the device priority so okToConnect() returns true 361 mService.setPriority(mLeftDevice, BluetoothProfile.PRIORITY_ON); 362 mService.setPriority(mRightDevice, BluetoothProfile.PRIORITY_ON); 363 mService.setPriority(mSingleDevice, BluetoothProfile.PRIORITY_OFF); 364 doReturn(true).when(mNativeInterface).connectHearingAid(any(BluetoothDevice.class)); 365 doReturn(true).when(mNativeInterface).disconnectHearingAid(any(BluetoothDevice.class)); 366 367 // Send a connect request 368 Assert.assertTrue("Connect failed", mService.connect(mLeftDevice)); 369 370 // Verify the connection state broadcast, and that we are in Connecting state 371 verifyConnectionStateIntent(TIMEOUT_MS, mLeftDevice, BluetoothProfile.STATE_CONNECTING, 372 BluetoothProfile.STATE_DISCONNECTED); 373 Assert.assertEquals(BluetoothProfile.STATE_CONNECTING, 374 mService.getConnectionState(mLeftDevice)); 375 verifyConnectionStateIntent(TIMEOUT_MS, mRightDevice, BluetoothProfile.STATE_CONNECTING, 376 BluetoothProfile.STATE_DISCONNECTED); 377 Assert.assertEquals(BluetoothProfile.STATE_CONNECTING, 378 mService.getConnectionState(mRightDevice)); 379 } 380 381 /** 382 * Test that the service disconnects the current pair before connecting to another pair. 383 */ 384 @Test 385 public void testConnectAnotherPair_disconnectCurrentPair() { 386 // Update hiSyncId map 387 getHiSyncIdFromNative(); 388 // Update the device priority so okToConnect() returns true 389 mService.setPriority(mLeftDevice, BluetoothProfile.PRIORITY_ON); 390 mService.setPriority(mRightDevice, BluetoothProfile.PRIORITY_ON); 391 mService.setPriority(mSingleDevice, BluetoothProfile.PRIORITY_ON); 392 doReturn(true).when(mNativeInterface).connectHearingAid(any(BluetoothDevice.class)); 393 doReturn(true).when(mNativeInterface).disconnectHearingAid(any(BluetoothDevice.class)); 394 395 // Send a connect request 396 Assert.assertTrue("Connect failed", mService.connect(mLeftDevice)); 397 398 // Verify the connection state broadcast, and that we are in Connecting state 399 verifyConnectionStateIntent(TIMEOUT_MS, mLeftDevice, BluetoothProfile.STATE_CONNECTING, 400 BluetoothProfile.STATE_DISCONNECTED); 401 verifyConnectionStateIntent(TIMEOUT_MS, mRightDevice, BluetoothProfile.STATE_CONNECTING, 402 BluetoothProfile.STATE_DISCONNECTED); 403 404 HearingAidStackEvent connCompletedEvent; 405 // Send a message to trigger connection completed 406 connCompletedEvent = new HearingAidStackEvent( 407 HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); 408 connCompletedEvent.device = mLeftDevice; 409 connCompletedEvent.valueInt1 = HearingAidStackEvent.CONNECTION_STATE_CONNECTED; 410 mService.messageFromNative(connCompletedEvent); 411 connCompletedEvent = new HearingAidStackEvent( 412 HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); 413 connCompletedEvent.device = mRightDevice; 414 connCompletedEvent.valueInt1 = HearingAidStackEvent.CONNECTION_STATE_CONNECTED; 415 mService.messageFromNative(connCompletedEvent); 416 417 // Verify the connection state broadcast, and that we are in Connected state for right side 418 verifyConnectionStateIntent(TIMEOUT_MS, mLeftDevice, BluetoothProfile.STATE_CONNECTED, 419 BluetoothProfile.STATE_CONNECTING); 420 verifyConnectionStateIntent(TIMEOUT_MS, mRightDevice, BluetoothProfile.STATE_CONNECTED, 421 BluetoothProfile.STATE_CONNECTING); 422 423 // Send a connect request for another pair 424 Assert.assertTrue("Connect failed", mService.connect(mSingleDevice)); 425 426 // Verify the connection state broadcast, and that the first pair is in Disconnecting state 427 verifyConnectionStateIntent(TIMEOUT_MS, mLeftDevice, BluetoothProfile.STATE_DISCONNECTING, 428 BluetoothProfile.STATE_CONNECTED); 429 verifyConnectionStateIntent(TIMEOUT_MS, mRightDevice, BluetoothProfile.STATE_DISCONNECTING, 430 BluetoothProfile.STATE_CONNECTED); 431 Assert.assertFalse(mService.getConnectedDevices().contains(mLeftDevice)); 432 Assert.assertFalse(mService.getConnectedDevices().contains(mRightDevice)); 433 434 // Verify the connection state broadcast, and that the second device is in Connecting state 435 verifyConnectionStateIntent(TIMEOUT_MS, mSingleDevice, BluetoothProfile.STATE_CONNECTING, 436 BluetoothProfile.STATE_DISCONNECTED); 437 Assert.assertEquals(BluetoothProfile.STATE_CONNECTING, 438 mService.getConnectionState(mSingleDevice)); 439 } 440 441 /** 442 * Test that the outgoing connect/disconnect and audio switch is successful. 443 */ 444 @Test 445 public void testAudioManagerConnectDisconnect() { 446 // Update hiSyncId map 447 getHiSyncIdFromNative(); 448 // Update the device priority so okToConnect() returns true 449 mService.setPriority(mLeftDevice, BluetoothProfile.PRIORITY_ON); 450 mService.setPriority(mRightDevice, BluetoothProfile.PRIORITY_ON); 451 mService.setPriority(mSingleDevice, BluetoothProfile.PRIORITY_OFF); 452 doReturn(true).when(mNativeInterface).connectHearingAid(any(BluetoothDevice.class)); 453 doReturn(true).when(mNativeInterface).disconnectHearingAid(any(BluetoothDevice.class)); 454 455 // Send a connect request 456 Assert.assertTrue("Connect failed", mService.connect(mLeftDevice)); 457 Assert.assertTrue("Connect failed", mService.connect(mRightDevice)); 458 459 // Verify the connection state broadcast, and that we are in Connecting state 460 verifyConnectionStateIntent(TIMEOUT_MS, mLeftDevice, BluetoothProfile.STATE_CONNECTING, 461 BluetoothProfile.STATE_DISCONNECTED); 462 Assert.assertEquals(BluetoothProfile.STATE_CONNECTING, 463 mService.getConnectionState(mLeftDevice)); 464 verifyConnectionStateIntent(TIMEOUT_MS, mRightDevice, BluetoothProfile.STATE_CONNECTING, 465 BluetoothProfile.STATE_DISCONNECTED); 466 Assert.assertEquals(BluetoothProfile.STATE_CONNECTING, 467 mService.getConnectionState(mRightDevice)); 468 469 HearingAidStackEvent connCompletedEvent; 470 // Send a message to trigger connection completed 471 connCompletedEvent = new HearingAidStackEvent( 472 HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); 473 connCompletedEvent.device = mLeftDevice; 474 connCompletedEvent.valueInt1 = HearingAidStackEvent.CONNECTION_STATE_CONNECTED; 475 mService.messageFromNative(connCompletedEvent); 476 477 // Verify the connection state broadcast, and that we are in Connected state 478 verifyConnectionStateIntent(TIMEOUT_MS, mLeftDevice, BluetoothProfile.STATE_CONNECTED, 479 BluetoothProfile.STATE_CONNECTING); 480 Assert.assertEquals(BluetoothProfile.STATE_CONNECTED, 481 mService.getConnectionState(mLeftDevice)); 482 483 // Send a message to trigger connection completed for right side 484 connCompletedEvent = new HearingAidStackEvent( 485 HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); 486 connCompletedEvent.device = mRightDevice; 487 connCompletedEvent.valueInt1 = HearingAidStackEvent.CONNECTION_STATE_CONNECTED; 488 mService.messageFromNative(connCompletedEvent); 489 490 // Verify the connection state broadcast, and that we are in Connected state for right side 491 verifyConnectionStateIntent(TIMEOUT_MS, mRightDevice, BluetoothProfile.STATE_CONNECTED, 492 BluetoothProfile.STATE_CONNECTING); 493 Assert.assertEquals(BluetoothProfile.STATE_CONNECTED, 494 mService.getConnectionState(mRightDevice)); 495 496 // Verify the list of connected devices 497 Assert.assertTrue(mService.getConnectedDevices().contains(mLeftDevice)); 498 Assert.assertTrue(mService.getConnectedDevices().contains(mRightDevice)); 499 500 // Verify the audio is routed to Hearing Aid Profile 501 verify(mAudioManager).setHearingAidDeviceConnectionState(any(BluetoothDevice.class), 502 eq(BluetoothProfile.STATE_CONNECTED)); 503 504 // Send a disconnect request 505 Assert.assertTrue("Disconnect failed", mService.disconnect(mLeftDevice)); 506 Assert.assertTrue("Disconnect failed", mService.disconnect(mRightDevice)); 507 508 // Verify the connection state broadcast, and that we are in Disconnecting state 509 verifyConnectionStateIntent(TIMEOUT_MS, mLeftDevice, BluetoothProfile.STATE_DISCONNECTING, 510 BluetoothProfile.STATE_CONNECTED); 511 Assert.assertEquals(BluetoothProfile.STATE_DISCONNECTING, 512 mService.getConnectionState(mLeftDevice)); 513 verifyConnectionStateIntent(TIMEOUT_MS, mRightDevice, BluetoothProfile.STATE_DISCONNECTING, 514 BluetoothProfile.STATE_CONNECTED); 515 Assert.assertEquals(BluetoothProfile.STATE_DISCONNECTING, 516 mService.getConnectionState(mRightDevice)); 517 518 // Send a message to trigger disconnection completed 519 connCompletedEvent = new HearingAidStackEvent( 520 HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); 521 connCompletedEvent.device = mLeftDevice; 522 connCompletedEvent.valueInt1 = HearingAidStackEvent.CONNECTION_STATE_DISCONNECTED; 523 mService.messageFromNative(connCompletedEvent); 524 525 // Verify the connection state broadcast, and that we are in Disconnected state 526 verifyConnectionStateIntent(TIMEOUT_MS, mLeftDevice, BluetoothProfile.STATE_DISCONNECTED, 527 BluetoothProfile.STATE_DISCONNECTING); 528 Assert.assertEquals(BluetoothProfile.STATE_DISCONNECTED, 529 mService.getConnectionState(mLeftDevice)); 530 531 // Send a message to trigger disconnection completed to the right device 532 connCompletedEvent = new HearingAidStackEvent( 533 HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); 534 connCompletedEvent.device = mRightDevice; 535 connCompletedEvent.valueInt1 = HearingAidStackEvent.CONNECTION_STATE_DISCONNECTED; 536 mService.messageFromNative(connCompletedEvent); 537 538 // Verify the connection state broadcast, and that we are in Disconnected state 539 verifyConnectionStateIntent(TIMEOUT_MS, mRightDevice, BluetoothProfile.STATE_DISCONNECTED, 540 BluetoothProfile.STATE_DISCONNECTING); 541 Assert.assertEquals(BluetoothProfile.STATE_DISCONNECTED, 542 mService.getConnectionState(mRightDevice)); 543 544 // Verify the list of connected devices 545 Assert.assertFalse(mService.getConnectedDevices().contains(mLeftDevice)); 546 Assert.assertFalse(mService.getConnectedDevices().contains(mRightDevice)); 547 548 // Verify the audio is not routed to Hearing Aid Profile 549 verify(mAudioManager).setHearingAidDeviceConnectionState(any(BluetoothDevice.class), 550 eq(BluetoothProfile.STATE_DISCONNECTED)); 551 } 552 553 /** 554 * Test that only CONNECTION_STATE_CONNECTED or CONNECTION_STATE_CONNECTING Hearing Aid stack 555 * events will create a state machine. 556 */ 557 @Test 558 public void testCreateStateMachineStackEvents() { 559 // Update the device priority so okToConnect() returns true 560 mService.setPriority(mLeftDevice, BluetoothProfile.PRIORITY_ON); 561 mService.setPriority(mRightDevice, BluetoothProfile.PRIORITY_OFF); 562 mService.setPriority(mSingleDevice, BluetoothProfile.PRIORITY_OFF); 563 doReturn(true).when(mNativeInterface).connectHearingAid(any(BluetoothDevice.class)); 564 doReturn(true).when(mNativeInterface).disconnectHearingAid(any(BluetoothDevice.class)); 565 566 // Hearing Aid stack event: CONNECTION_STATE_CONNECTING - state machine should be created 567 generateConnectionMessageFromNative(mLeftDevice, BluetoothProfile.STATE_CONNECTING, 568 BluetoothProfile.STATE_DISCONNECTED); 569 Assert.assertEquals(BluetoothProfile.STATE_CONNECTING, 570 mService.getConnectionState(mLeftDevice)); 571 Assert.assertTrue(mService.getDevices().contains(mLeftDevice)); 572 573 // HearingAid stack event: CONNECTION_STATE_DISCONNECTED - state machine should be removed 574 generateConnectionMessageFromNative(mLeftDevice, BluetoothProfile.STATE_DISCONNECTED, 575 BluetoothProfile.STATE_CONNECTING); 576 Assert.assertEquals(BluetoothProfile.STATE_DISCONNECTED, 577 mService.getConnectionState(mLeftDevice)); 578 Assert.assertTrue(mService.getDevices().contains(mLeftDevice)); 579 mService.bondStateChanged(mLeftDevice, BluetoothDevice.BOND_NONE); 580 Assert.assertFalse(mService.getDevices().contains(mLeftDevice)); 581 582 // stack event: CONNECTION_STATE_CONNECTED - state machine should be created 583 generateConnectionMessageFromNative(mLeftDevice, BluetoothProfile.STATE_CONNECTED, 584 BluetoothProfile.STATE_DISCONNECTED); 585 Assert.assertEquals(BluetoothProfile.STATE_CONNECTED, 586 mService.getConnectionState(mLeftDevice)); 587 Assert.assertTrue(mService.getDevices().contains(mLeftDevice)); 588 589 // stack event: CONNECTION_STATE_DISCONNECTED - state machine should be removed 590 generateConnectionMessageFromNative(mLeftDevice, BluetoothProfile.STATE_DISCONNECTED, 591 BluetoothProfile.STATE_CONNECTED); 592 Assert.assertEquals(BluetoothProfile.STATE_DISCONNECTED, 593 mService.getConnectionState(mLeftDevice)); 594 Assert.assertTrue(mService.getDevices().contains(mLeftDevice)); 595 mService.bondStateChanged(mLeftDevice, BluetoothDevice.BOND_NONE); 596 Assert.assertFalse(mService.getDevices().contains(mLeftDevice)); 597 598 // stack event: CONNECTION_STATE_DISCONNECTING - state machine should not be created 599 generateUnexpectedConnectionMessageFromNative(mLeftDevice, 600 BluetoothProfile.STATE_DISCONNECTING, 601 BluetoothProfile.STATE_DISCONNECTED); 602 Assert.assertEquals(BluetoothProfile.STATE_DISCONNECTED, 603 mService.getConnectionState(mLeftDevice)); 604 Assert.assertFalse(mService.getDevices().contains(mLeftDevice)); 605 606 // stack event: CONNECTION_STATE_DISCONNECTED - state machine should not be created 607 generateUnexpectedConnectionMessageFromNative(mLeftDevice, 608 BluetoothProfile.STATE_DISCONNECTED, 609 BluetoothProfile.STATE_DISCONNECTED); 610 Assert.assertEquals(BluetoothProfile.STATE_DISCONNECTED, 611 mService.getConnectionState(mLeftDevice)); 612 Assert.assertFalse(mService.getDevices().contains(mLeftDevice)); 613 } 614 615 /** 616 * Test that a state machine in DISCONNECTED state is removed only after the device is unbond. 617 */ 618 @Test 619 public void testDeleteStateMachineUnbondEvents() { 620 // Update the device priority so okToConnect() returns true 621 mService.setPriority(mLeftDevice, BluetoothProfile.PRIORITY_ON); 622 mService.setPriority(mRightDevice, BluetoothProfile.PRIORITY_OFF); 623 mService.setPriority(mSingleDevice, BluetoothProfile.PRIORITY_OFF); 624 doReturn(true).when(mNativeInterface).connectHearingAid(any(BluetoothDevice.class)); 625 doReturn(true).when(mNativeInterface).disconnectHearingAid(any(BluetoothDevice.class)); 626 627 // HearingAid stack event: CONNECTION_STATE_CONNECTING - state machine should be created 628 generateConnectionMessageFromNative(mLeftDevice, BluetoothProfile.STATE_CONNECTING, 629 BluetoothProfile.STATE_DISCONNECTED); 630 Assert.assertEquals(BluetoothProfile.STATE_CONNECTING, 631 mService.getConnectionState(mLeftDevice)); 632 Assert.assertTrue(mService.getDevices().contains(mLeftDevice)); 633 // Device unbond - state machine is not removed 634 mService.bondStateChanged(mLeftDevice, BluetoothDevice.BOND_NONE); 635 Assert.assertTrue(mService.getDevices().contains(mLeftDevice)); 636 637 // HearingAid stack event: CONNECTION_STATE_CONNECTED - state machine is not removed 638 mService.bondStateChanged(mLeftDevice, BluetoothDevice.BOND_BONDED); 639 generateConnectionMessageFromNative(mLeftDevice, BluetoothProfile.STATE_CONNECTED, 640 BluetoothProfile.STATE_CONNECTING); 641 Assert.assertEquals(BluetoothProfile.STATE_CONNECTED, 642 mService.getConnectionState(mLeftDevice)); 643 Assert.assertTrue(mService.getDevices().contains(mLeftDevice)); 644 // Device unbond - state machine is not removed 645 mService.bondStateChanged(mLeftDevice, BluetoothDevice.BOND_NONE); 646 Assert.assertTrue(mService.getDevices().contains(mLeftDevice)); 647 648 // HearingAid stack event: CONNECTION_STATE_DISCONNECTING - state machine is not removed 649 mService.bondStateChanged(mLeftDevice, BluetoothDevice.BOND_BONDED); 650 generateConnectionMessageFromNative(mLeftDevice, BluetoothProfile.STATE_DISCONNECTING, 651 BluetoothProfile.STATE_CONNECTED); 652 Assert.assertEquals(BluetoothProfile.STATE_DISCONNECTING, 653 mService.getConnectionState(mLeftDevice)); 654 Assert.assertTrue(mService.getDevices().contains(mLeftDevice)); 655 // Device unbond - state machine is not removed 656 mService.bondStateChanged(mLeftDevice, BluetoothDevice.BOND_NONE); 657 Assert.assertTrue(mService.getDevices().contains(mLeftDevice)); 658 659 // HearingAid stack event: CONNECTION_STATE_DISCONNECTED - state machine is not removed 660 mService.bondStateChanged(mLeftDevice, BluetoothDevice.BOND_BONDED); 661 generateConnectionMessageFromNative(mLeftDevice, BluetoothProfile.STATE_DISCONNECTED, 662 BluetoothProfile.STATE_DISCONNECTING); 663 Assert.assertEquals(BluetoothProfile.STATE_DISCONNECTED, 664 mService.getConnectionState(mLeftDevice)); 665 Assert.assertTrue(mService.getDevices().contains(mLeftDevice)); 666 // Device unbond - state machine is removed 667 mService.bondStateChanged(mLeftDevice, BluetoothDevice.BOND_NONE); 668 Assert.assertFalse(mService.getDevices().contains(mLeftDevice)); 669 } 670 671 /** 672 * Test that a CONNECTION_STATE_DISCONNECTED Hearing Aid stack event will remove the state 673 * machine only if the device is unbond. 674 */ 675 @Test 676 public void testDeleteStateMachineDisconnectEvents() { 677 // Update the device priority so okToConnect() returns true 678 mService.setPriority(mLeftDevice, BluetoothProfile.PRIORITY_ON); 679 mService.setPriority(mRightDevice, BluetoothProfile.PRIORITY_OFF); 680 mService.setPriority(mSingleDevice, BluetoothProfile.PRIORITY_OFF); 681 doReturn(true).when(mNativeInterface).connectHearingAid(any(BluetoothDevice.class)); 682 doReturn(true).when(mNativeInterface).disconnectHearingAid(any(BluetoothDevice.class)); 683 684 // HearingAid stack event: CONNECTION_STATE_CONNECTING - state machine should be created 685 generateConnectionMessageFromNative(mLeftDevice, BluetoothProfile.STATE_CONNECTING, 686 BluetoothProfile.STATE_DISCONNECTED); 687 Assert.assertEquals(BluetoothProfile.STATE_CONNECTING, 688 mService.getConnectionState(mLeftDevice)); 689 Assert.assertTrue(mService.getDevices().contains(mLeftDevice)); 690 691 // HearingAid stack event: CONNECTION_STATE_DISCONNECTED - state machine is not removed 692 generateConnectionMessageFromNative(mLeftDevice, BluetoothProfile.STATE_DISCONNECTED, 693 BluetoothProfile.STATE_CONNECTING); 694 Assert.assertEquals(BluetoothProfile.STATE_DISCONNECTED, 695 mService.getConnectionState(mLeftDevice)); 696 Assert.assertTrue(mService.getDevices().contains(mLeftDevice)); 697 698 // HearingAid stack event: CONNECTION_STATE_CONNECTING - state machine remains 699 generateConnectionMessageFromNative(mLeftDevice, BluetoothProfile.STATE_CONNECTING, 700 BluetoothProfile.STATE_DISCONNECTED); 701 Assert.assertEquals(BluetoothProfile.STATE_CONNECTING, 702 mService.getConnectionState(mLeftDevice)); 703 Assert.assertTrue(mService.getDevices().contains(mLeftDevice)); 704 705 // Device bond state marked as unbond - state machine is not removed 706 doReturn(BluetoothDevice.BOND_NONE).when(mAdapterService) 707 .getBondState(any(BluetoothDevice.class)); 708 Assert.assertTrue(mService.getDevices().contains(mLeftDevice)); 709 710 // HearingAid stack event: CONNECTION_STATE_DISCONNECTED - state machine is removed 711 generateConnectionMessageFromNative(mLeftDevice, BluetoothProfile.STATE_DISCONNECTED, 712 BluetoothProfile.STATE_CONNECTING); 713 Assert.assertEquals(BluetoothProfile.STATE_DISCONNECTED, 714 mService.getConnectionState(mLeftDevice)); 715 Assert.assertFalse(mService.getDevices().contains(mLeftDevice)); 716 } 717 718 @Test 719 public void testConnectionStateChangedActiveDevice() { 720 // Update hiSyncId map 721 getHiSyncIdFromNative(); 722 // Update the device priority so okToConnect() returns true 723 mService.setPriority(mLeftDevice, BluetoothProfile.PRIORITY_ON); 724 mService.setPriority(mRightDevice, BluetoothProfile.PRIORITY_ON); 725 mService.setPriority(mSingleDevice, BluetoothProfile.PRIORITY_OFF); 726 727 generateConnectionMessageFromNative(mRightDevice, BluetoothProfile.STATE_CONNECTED, 728 BluetoothProfile.STATE_DISCONNECTED); 729 Assert.assertTrue(mService.getActiveDevices().contains(mRightDevice)); 730 Assert.assertFalse(mService.getActiveDevices().contains(mLeftDevice)); 731 732 generateConnectionMessageFromNative(mLeftDevice, BluetoothProfile.STATE_CONNECTED, 733 BluetoothProfile.STATE_DISCONNECTED); 734 Assert.assertTrue(mService.getActiveDevices().contains(mRightDevice)); 735 Assert.assertTrue(mService.getActiveDevices().contains(mLeftDevice)); 736 737 generateConnectionMessageFromNative(mRightDevice, BluetoothProfile.STATE_DISCONNECTED, 738 BluetoothProfile.STATE_CONNECTED); 739 Assert.assertFalse(mService.getActiveDevices().contains(mRightDevice)); 740 Assert.assertTrue(mService.getActiveDevices().contains(mLeftDevice)); 741 742 generateConnectionMessageFromNative(mLeftDevice, BluetoothProfile.STATE_DISCONNECTED, 743 BluetoothProfile.STATE_CONNECTED); 744 Assert.assertFalse(mService.getActiveDevices().contains(mRightDevice)); 745 Assert.assertFalse(mService.getActiveDevices().contains(mLeftDevice)); 746 } 747 748 @Test 749 public void testConnectionStateChangedAnotherActiveDevice() { 750 // Update hiSyncId map 751 getHiSyncIdFromNative(); 752 // Update the device priority so okToConnect() returns true 753 mService.setPriority(mLeftDevice, BluetoothProfile.PRIORITY_ON); 754 mService.setPriority(mRightDevice, BluetoothProfile.PRIORITY_ON); 755 mService.setPriority(mSingleDevice, BluetoothProfile.PRIORITY_ON); 756 757 generateConnectionMessageFromNative(mRightDevice, BluetoothProfile.STATE_CONNECTED, 758 BluetoothProfile.STATE_DISCONNECTED); 759 Assert.assertTrue(mService.getActiveDevices().contains(mRightDevice)); 760 Assert.assertFalse(mService.getActiveDevices().contains(mLeftDevice)); 761 762 generateConnectionMessageFromNative(mLeftDevice, BluetoothProfile.STATE_CONNECTED, 763 BluetoothProfile.STATE_DISCONNECTED); 764 Assert.assertTrue(mService.getActiveDevices().contains(mRightDevice)); 765 Assert.assertTrue(mService.getActiveDevices().contains(mLeftDevice)); 766 767 generateConnectionMessageFromNative(mSingleDevice, BluetoothProfile.STATE_CONNECTED, 768 BluetoothProfile.STATE_DISCONNECTED); 769 Assert.assertFalse(mService.getActiveDevices().contains(mRightDevice)); 770 Assert.assertFalse(mService.getActiveDevices().contains(mLeftDevice)); 771 Assert.assertTrue(mService.getActiveDevices().contains(mSingleDevice)); 772 } 773 774 /** 775 * Verify the correctness during first time connection. 776 * Connect to left device -> Get left device hiSyncId -> Connect to right device -> 777 * Get right device hiSyncId -> Both devices should be always connected 778 */ 779 @Test 780 public void firstTimeConnection_shouldConnectToBothDevices() { 781 // Update the device priority so okToConnect() returns true 782 mService.setPriority(mLeftDevice, BluetoothProfile.PRIORITY_ON); 783 mService.setPriority(mRightDevice, BluetoothProfile.PRIORITY_ON); 784 doReturn(true).when(mNativeInterface).connectHearingAid(any(BluetoothDevice.class)); 785 doReturn(true).when(mNativeInterface).disconnectHearingAid(any(BluetoothDevice.class)); 786 // Send a connect request for left device 787 Assert.assertTrue("Connect failed", mService.connect(mLeftDevice)); 788 // Verify the connection state broadcast, and that we are in Connecting state 789 verifyConnectionStateIntent(TIMEOUT_MS, mLeftDevice, BluetoothProfile.STATE_CONNECTING, 790 BluetoothProfile.STATE_DISCONNECTED); 791 Assert.assertEquals(BluetoothProfile.STATE_CONNECTING, 792 mService.getConnectionState(mLeftDevice)); 793 794 HearingAidStackEvent connCompletedEvent; 795 // Send a message to trigger connection completed 796 connCompletedEvent = new HearingAidStackEvent( 797 HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); 798 connCompletedEvent.device = mLeftDevice; 799 connCompletedEvent.valueInt1 = HearingAidStackEvent.CONNECTION_STATE_CONNECTED; 800 mService.messageFromNative(connCompletedEvent); 801 802 // Verify the connection state broadcast, and that we are in Connected state 803 verifyConnectionStateIntent(TIMEOUT_MS, mLeftDevice, BluetoothProfile.STATE_CONNECTED, 804 BluetoothProfile.STATE_CONNECTING); 805 Assert.assertEquals(BluetoothProfile.STATE_CONNECTED, 806 mService.getConnectionState(mLeftDevice)); 807 808 // Get hiSyncId for left device 809 HearingAidStackEvent hiSyncIdEvent = new HearingAidStackEvent( 810 HearingAidStackEvent.EVENT_TYPE_DEVICE_AVAILABLE); 811 hiSyncIdEvent.device = mLeftDevice; 812 hiSyncIdEvent.valueInt1 = 0x02; 813 hiSyncIdEvent.valueLong2 = 0x0101; 814 mService.messageFromNative(hiSyncIdEvent); 815 816 // Send a connect request for right device 817 Assert.assertTrue("Connect failed", mService.connect(mRightDevice)); 818 // Verify the connection state broadcast, and that we are in Connecting state 819 verifyConnectionStateIntent(TIMEOUT_MS, mRightDevice, BluetoothProfile.STATE_CONNECTING, 820 BluetoothProfile.STATE_DISCONNECTED); 821 Assert.assertEquals(BluetoothProfile.STATE_CONNECTING, 822 mService.getConnectionState(mRightDevice)); 823 // Verify the left device is still connected 824 Assert.assertEquals(BluetoothProfile.STATE_CONNECTED, 825 mService.getConnectionState(mLeftDevice)); 826 827 // Send a message to trigger connection completed 828 connCompletedEvent = new HearingAidStackEvent( 829 HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); 830 connCompletedEvent.device = mRightDevice; 831 connCompletedEvent.valueInt1 = HearingAidStackEvent.CONNECTION_STATE_CONNECTED; 832 mService.messageFromNative(connCompletedEvent); 833 834 // Verify the connection state broadcast, and that we are in Connected state 835 verifyConnectionStateIntent(TIMEOUT_MS, mRightDevice, BluetoothProfile.STATE_CONNECTED, 836 BluetoothProfile.STATE_CONNECTING); 837 Assert.assertEquals(BluetoothProfile.STATE_CONNECTED, 838 mService.getConnectionState(mRightDevice)); 839 Assert.assertEquals(BluetoothProfile.STATE_CONNECTED, 840 mService.getConnectionState(mLeftDevice)); 841 842 // Get hiSyncId for right device 843 hiSyncIdEvent = new HearingAidStackEvent( 844 HearingAidStackEvent.EVENT_TYPE_DEVICE_AVAILABLE); 845 hiSyncIdEvent.device = mRightDevice; 846 hiSyncIdEvent.valueInt1 = 0x02; 847 hiSyncIdEvent.valueLong2 = 0x0101; 848 mService.messageFromNative(hiSyncIdEvent); 849 850 Assert.assertEquals(BluetoothProfile.STATE_CONNECTED, 851 mService.getConnectionState(mRightDevice)); 852 Assert.assertEquals(BluetoothProfile.STATE_CONNECTED, 853 mService.getConnectionState(mLeftDevice)); 854 } 855 856 /** 857 * Get the HiSyncId from native stack after connecting to left device, then connect right 858 */ 859 @Test 860 public void getHiSyncId_afterFirstDeviceConnected() { 861 // Update the device priority so okToConnect() returns true 862 mService.setPriority(mLeftDevice, BluetoothProfile.PRIORITY_ON); 863 mService.setPriority(mRightDevice, BluetoothProfile.PRIORITY_ON); 864 mService.setPriority(mSingleDevice, BluetoothProfile.PRIORITY_ON); 865 doReturn(true).when(mNativeInterface).connectHearingAid(any(BluetoothDevice.class)); 866 doReturn(true).when(mNativeInterface).disconnectHearingAid(any(BluetoothDevice.class)); 867 // Send a connect request 868 Assert.assertTrue("Connect failed", mService.connect(mLeftDevice)); 869 // Verify the connection state broadcast, and that we are in Connecting state 870 verifyConnectionStateIntent(TIMEOUT_MS, mLeftDevice, BluetoothProfile.STATE_CONNECTING, 871 BluetoothProfile.STATE_DISCONNECTED); 872 Assert.assertEquals(BluetoothProfile.STATE_CONNECTING, 873 mService.getConnectionState(mLeftDevice)); 874 Assert.assertEquals(BluetoothProfile.STATE_DISCONNECTED, 875 mService.getConnectionState(mRightDevice)); 876 877 HearingAidStackEvent connCompletedEvent; 878 // Send a message to trigger connection completed 879 connCompletedEvent = new HearingAidStackEvent( 880 HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); 881 connCompletedEvent.device = mLeftDevice; 882 connCompletedEvent.valueInt1 = HearingAidStackEvent.CONNECTION_STATE_CONNECTED; 883 mService.messageFromNative(connCompletedEvent); 884 // Verify the connection state broadcast, and that we are in Connected state 885 verifyConnectionStateIntent(TIMEOUT_MS, mLeftDevice, BluetoothProfile.STATE_CONNECTED, 886 BluetoothProfile.STATE_CONNECTING); 887 Assert.assertEquals(BluetoothProfile.STATE_CONNECTED, 888 mService.getConnectionState(mLeftDevice)); 889 890 // Get hiSyncId update from native stack 891 getHiSyncIdFromNative(); 892 // Send a connect request for right 893 Assert.assertTrue("Connect failed", mService.connect(mRightDevice)); 894 // Verify the connection state broadcast, and that we are in Connecting state 895 verifyConnectionStateIntent(TIMEOUT_MS, mRightDevice, BluetoothProfile.STATE_CONNECTING, 896 BluetoothProfile.STATE_DISCONNECTED); 897 Assert.assertEquals(BluetoothProfile.STATE_CONNECTING, 898 mService.getConnectionState(mRightDevice)); 899 // Verify the left device is still connected 900 Assert.assertEquals(BluetoothProfile.STATE_CONNECTED, 901 mService.getConnectionState(mLeftDevice)); 902 903 // Send a message to trigger connection completed 904 connCompletedEvent = new HearingAidStackEvent( 905 HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); 906 connCompletedEvent.device = mRightDevice; 907 connCompletedEvent.valueInt1 = HearingAidStackEvent.CONNECTION_STATE_CONNECTED; 908 mService.messageFromNative(connCompletedEvent); 909 910 // Verify the connection state broadcast, and that we are in Connected state 911 verifyConnectionStateIntent(TIMEOUT_MS, mRightDevice, BluetoothProfile.STATE_CONNECTED, 912 BluetoothProfile.STATE_CONNECTING); 913 Assert.assertEquals(BluetoothProfile.STATE_CONNECTED, 914 mService.getConnectionState(mRightDevice)); 915 Assert.assertEquals(BluetoothProfile.STATE_CONNECTED, 916 mService.getConnectionState(mLeftDevice)); 917 } 918 919 private void connectDevice(BluetoothDevice device) { 920 HearingAidStackEvent connCompletedEvent; 921 922 List<BluetoothDevice> prevConnectedDevices = mService.getConnectedDevices(); 923 924 // Update the device priority so okToConnect() returns true 925 mService.setPriority(device, BluetoothProfile.PRIORITY_ON); 926 doReturn(true).when(mNativeInterface).connectHearingAid(device); 927 doReturn(true).when(mNativeInterface).disconnectHearingAid(device); 928 929 // Send a connect request 930 Assert.assertTrue("Connect failed", mService.connect(device)); 931 932 // Verify the connection state broadcast, and that we are in Connecting state 933 verifyConnectionStateIntent(TIMEOUT_MS, device, BluetoothProfile.STATE_CONNECTING, 934 BluetoothProfile.STATE_DISCONNECTED); 935 Assert.assertEquals(BluetoothProfile.STATE_CONNECTING, 936 mService.getConnectionState(device)); 937 938 // Send a message to trigger connection completed 939 connCompletedEvent = new HearingAidStackEvent( 940 HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); 941 connCompletedEvent.device = device; 942 connCompletedEvent.valueInt1 = HearingAidStackEvent.CONNECTION_STATE_CONNECTED; 943 mService.messageFromNative(connCompletedEvent); 944 945 // Verify the connection state broadcast, and that we are in Connected state 946 verifyConnectionStateIntent(TIMEOUT_MS, device, BluetoothProfile.STATE_CONNECTED, 947 BluetoothProfile.STATE_CONNECTING); 948 Assert.assertEquals(BluetoothProfile.STATE_CONNECTED, 949 mService.getConnectionState(device)); 950 951 // Verify that the device is in the list of connected devices 952 Assert.assertTrue(mService.getConnectedDevices().contains(device)); 953 // Verify the list of previously connected devices 954 for (BluetoothDevice prevDevice : prevConnectedDevices) { 955 Assert.assertTrue(mService.getConnectedDevices().contains(prevDevice)); 956 } 957 } 958 959 private void generateConnectionMessageFromNative(BluetoothDevice device, int newConnectionState, 960 int oldConnectionState) { 961 HearingAidStackEvent stackEvent = 962 new HearingAidStackEvent(HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); 963 stackEvent.device = device; 964 stackEvent.valueInt1 = newConnectionState; 965 mService.messageFromNative(stackEvent); 966 // Verify the connection state broadcast 967 verifyConnectionStateIntent(TIMEOUT_MS, device, newConnectionState, oldConnectionState); 968 } 969 970 private void generateUnexpectedConnectionMessageFromNative(BluetoothDevice device, 971 int newConnectionState, int oldConnectionState) { 972 HearingAidStackEvent stackEvent = 973 new HearingAidStackEvent(HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); 974 stackEvent.device = device; 975 stackEvent.valueInt1 = newConnectionState; 976 mService.messageFromNative(stackEvent); 977 // Verify the connection state broadcast 978 verifyNoConnectionStateIntent(TIMEOUT_MS, device); 979 } 980 981 /** 982 * Helper function to test okToConnect() method 983 * 984 * @param device test device 985 * @param bondState bond state value, could be invalid 986 * @param priority value, could be invalid, coudl be invalid 987 * @param expected expected result from okToConnect() 988 */ 989 private void testOkToConnectCase(BluetoothDevice device, int bondState, int priority, 990 boolean expected) { 991 doReturn(bondState).when(mAdapterService).getBondState(device); 992 Assert.assertTrue(mService.setPriority(device, priority)); 993 Assert.assertEquals(expected, mService.okToConnect(device)); 994 } 995 996 private void getHiSyncIdFromNative() { 997 HearingAidStackEvent event = new HearingAidStackEvent( 998 HearingAidStackEvent.EVENT_TYPE_DEVICE_AVAILABLE); 999 event.device = mLeftDevice; 1000 event.valueInt1 = 0x02; 1001 event.valueLong2 = 0x0101; 1002 mService.messageFromNative(event); 1003 event.device = mRightDevice; 1004 event.valueInt1 = 0x03; 1005 mService.messageFromNative(event); 1006 event.device = mSingleDevice; 1007 event.valueInt1 = 0x00; 1008 event.valueLong2 = 0x0102; 1009 mService.messageFromNative(event); 1010 } 1011 } 1012