1 /* 2 * Copyright 2017 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.btservice; 18 19 import static android.Manifest.permission.BLUETOOTH_SCAN; 20 21 import static org.mockito.ArgumentMatchers.any; 22 import static org.mockito.Mockito.*; 23 24 import android.app.AlarmManager; 25 import android.app.admin.DevicePolicyManager; 26 import android.bluetooth.BluetoothAdapter; 27 import android.bluetooth.BluetoothDevice; 28 import android.bluetooth.IBluetoothCallback; 29 import android.content.AttributionSource; 30 import android.content.Context; 31 import android.content.pm.ApplicationInfo; 32 import android.content.pm.PackageManager; 33 import android.content.pm.PermissionInfo; 34 import android.content.res.Resources; 35 import android.media.AudioManager; 36 import android.os.AsyncTask; 37 import android.os.Binder; 38 import android.os.Bundle; 39 import android.os.Handler; 40 import android.os.Looper; 41 import android.os.PowerManager; 42 import android.os.Process; 43 import android.os.SystemProperties; 44 import android.os.UserHandle; 45 import android.os.UserManager; 46 import android.permission.PermissionCheckerManager; 47 import android.test.mock.MockContentResolver; 48 import android.util.Log; 49 50 import androidx.test.InstrumentationRegistry; 51 import androidx.test.filters.MediumTest; 52 import androidx.test.runner.AndroidJUnit4; 53 54 import com.android.bluetooth.R; 55 import com.android.bluetooth.TestUtils; 56 import com.android.bluetooth.Utils; 57 58 import libcore.util.HexEncoding; 59 60 import org.junit.After; 61 import org.junit.Assert; 62 import org.junit.Before; 63 import org.junit.BeforeClass; 64 import org.junit.Ignore; 65 import org.junit.Test; 66 import org.junit.runner.RunWith; 67 import org.mockito.Mock; 68 import org.mockito.MockitoAnnotations; 69 70 import java.security.InvalidKeyException; 71 import java.security.NoSuchAlgorithmException; 72 import java.util.Arrays; 73 import java.util.HashMap; 74 75 import javax.crypto.Mac; 76 import javax.crypto.spec.SecretKeySpec; 77 78 @MediumTest 79 @RunWith(AndroidJUnit4.class) 80 public class AdapterServiceTest { 81 private static final String TAG = AdapterServiceTest.class.getSimpleName(); 82 83 private AdapterService mAdapterService; 84 private AdapterService.AdapterServiceBinder mServiceBinder; 85 86 private @Mock Context mMockContext; 87 private @Mock ApplicationInfo mMockApplicationInfo; 88 private @Mock AlarmManager mMockAlarmManager; 89 private @Mock Resources mMockResources; 90 private @Mock UserManager mMockUserManager; 91 private @Mock DevicePolicyManager mMockDevicePolicyManager; 92 private @Mock ProfileService mMockGattService; 93 private @Mock ProfileService mMockService; 94 private @Mock ProfileService mMockService2; 95 private @Mock IBluetoothCallback mIBluetoothCallback; 96 private @Mock Binder mBinder; 97 private @Mock AudioManager mAudioManager; 98 private @Mock android.app.Application mApplication; 99 100 private static final int CONTEXT_SWITCH_MS = 100; 101 private static final int PROFILE_SERVICE_TOGGLE_TIME_MS = 200; 102 private static final int GATT_START_TIME_MS = 500; 103 private static final int ONE_SECOND_MS = 1000; 104 private static final int NATIVE_INIT_MS = 8000; 105 private static final int NATIVE_DISABLE_MS = 1000; 106 107 private final AttributionSource mAttributionSource = new AttributionSource.Builder( 108 Process.myUid()).build(); 109 110 private PowerManager mPowerManager; 111 private PermissionCheckerManager mPermissionCheckerManager; 112 private PackageManager mMockPackageManager; 113 private MockContentResolver mMockContentResolver; 114 private HashMap<String, HashMap<String, String>> mAdapterConfig; 115 116 @BeforeClass setupClass()117 public static void setupClass() { 118 // Bring native layer up and down to make sure config files are properly loaded 119 if (Looper.myLooper() == null) { 120 Looper.prepare(); 121 } 122 Assert.assertNotNull(Looper.myLooper()); 123 AdapterService adapterService = new AdapterService(); 124 adapterService.initNative(false /* is_restricted */, false /* is_common_criteria_mode */, 125 0 /* config_compare_result */, new String[0], false); 126 adapterService.cleanupNative(); 127 HashMap<String, HashMap<String, String>> adapterConfig = TestUtils.readAdapterConfig(); 128 Assert.assertNotNull(adapterConfig); 129 Assert.assertNotNull("metrics salt is null: " + adapterConfig.toString(), 130 getMetricsSalt(adapterConfig)); 131 } 132 133 @Before setUp()134 public void setUp() throws PackageManager.NameNotFoundException { 135 if (Looper.myLooper() == null) { 136 Looper.prepare(); 137 } 138 Assert.assertNotNull(Looper.myLooper()); 139 140 // Dispatch all async work through instrumentation so we can wait until 141 // it's drained below 142 AsyncTask.setDefaultExecutor((r) -> { 143 InstrumentationRegistry.getInstrumentation().runOnMainSync(r); 144 }); 145 146 InstrumentationRegistry.getInstrumentation().runOnMainSync( 147 () -> mAdapterService = new AdapterService()); 148 mServiceBinder = new AdapterService.AdapterServiceBinder(mAdapterService); 149 mMockPackageManager = mock(PackageManager.class); 150 when(mMockPackageManager.getPermissionInfo(any(), anyInt())) 151 .thenReturn(new PermissionInfo()); 152 153 mMockContentResolver = new MockContentResolver(mMockContext); 154 MockitoAnnotations.initMocks(this); 155 mPowerManager = (PowerManager) InstrumentationRegistry.getTargetContext() 156 .getSystemService(Context.POWER_SERVICE); 157 mPermissionCheckerManager = InstrumentationRegistry.getTargetContext() 158 .getSystemService(PermissionCheckerManager.class); 159 160 when(mMockContext.getApplicationInfo()).thenReturn(mMockApplicationInfo); 161 when(mMockContext.getContentResolver()).thenReturn(mMockContentResolver); 162 when(mMockContext.getApplicationContext()).thenReturn(mMockContext); 163 when(mMockContext.createContextAsUser(UserHandle.SYSTEM, /* flags= */ 0)).thenReturn( 164 mMockContext); 165 when(mMockContext.getResources()).thenReturn(mMockResources); 166 when(mMockContext.getUserId()).thenReturn(Process.BLUETOOTH_UID); 167 when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager); 168 when(mMockContext.getSystemService(Context.USER_SERVICE)).thenReturn(mMockUserManager); 169 when(mMockContext.getSystemService(Context.DEVICE_POLICY_SERVICE)).thenReturn( 170 mMockDevicePolicyManager); 171 when(mMockContext.getSystemService(Context.POWER_SERVICE)).thenReturn(mPowerManager); 172 when(mMockContext.getSystemServiceName(PermissionCheckerManager.class)) 173 .thenReturn(Context.PERMISSION_CHECKER_SERVICE); 174 when(mMockContext.getSystemService(PermissionCheckerManager.class)) 175 .thenReturn(mPermissionCheckerManager); 176 when(mMockContext.getSystemService(Context.ALARM_SERVICE)).thenReturn(mMockAlarmManager); 177 when(mMockContext.getSystemService(Context.AUDIO_SERVICE)).thenReturn(mAudioManager); 178 when(mMockContext.getAttributionSource()).thenReturn(mAttributionSource); 179 doAnswer(invocation -> { 180 Object[] args = invocation.getArguments(); 181 return InstrumentationRegistry.getTargetContext().getDatabasePath((String) args[0]); 182 }).when(mMockContext).getDatabasePath(anyString()); 183 184 when(mMockResources.getBoolean(R.bool.profile_supported_gatt)).thenReturn(true); 185 when(mMockResources.getBoolean(R.bool.profile_supported_pbap)).thenReturn(true); 186 when(mMockResources.getBoolean(R.bool.profile_supported_pan)).thenReturn(true); 187 188 when(mMockDevicePolicyManager.isCommonCriteriaModeEnabled(any())).thenReturn(false); 189 190 when(mIBluetoothCallback.asBinder()).thenReturn(mBinder); 191 192 doReturn(Process.BLUETOOTH_UID).when(mMockPackageManager) 193 .getPackageUidAsUser(any(), anyInt(), anyInt()); 194 195 when(mMockGattService.getName()).thenReturn("GattService"); 196 when(mMockService.getName()).thenReturn("Service1"); 197 when(mMockService2.getName()).thenReturn("Service2"); 198 199 // Attach a context to the service for permission checks. 200 mAdapterService.attach(mMockContext, null, null, null, mApplication, null); 201 mAdapterService.onCreate(); 202 203 // Wait for any async events to drain 204 InstrumentationRegistry.getInstrumentation().waitForIdleSync(); 205 206 mServiceBinder.registerCallback(mIBluetoothCallback, mAttributionSource); 207 208 Config.init(mMockContext); 209 210 mAdapterConfig = TestUtils.readAdapterConfig(); 211 Assert.assertNotNull(mAdapterConfig); 212 } 213 214 @After tearDown()215 public void tearDown() { 216 mServiceBinder.unregisterCallback(mIBluetoothCallback, mAttributionSource); 217 mAdapterService.cleanup(); 218 Config.init(InstrumentationRegistry.getTargetContext()); 219 } 220 verifyStateChange(int prevState, int currState, int callNumber, int timeoutMs)221 private void verifyStateChange(int prevState, int currState, int callNumber, int timeoutMs) { 222 try { 223 verify(mIBluetoothCallback, timeout(timeoutMs) 224 .times(callNumber)).onBluetoothStateChange(prevState, currState); 225 } catch (Exception e) { 226 // the mocked onBluetoothStateChange doesn't throw exceptions 227 } 228 } 229 doEnable(int invocationNumber, boolean onlyGatt)230 private void doEnable(int invocationNumber, boolean onlyGatt) { 231 Assert.assertFalse(mAdapterService.getState() == BluetoothAdapter.STATE_ON); 232 233 final int startServiceCalls = 2 * (onlyGatt ? 1 : 3); // Start and stop GATT + 2 234 235 mAdapterService.enable(false); 236 237 verifyStateChange(BluetoothAdapter.STATE_OFF, BluetoothAdapter.STATE_BLE_TURNING_ON, 238 invocationNumber + 1, CONTEXT_SWITCH_MS); 239 240 // Start GATT 241 verify(mMockContext, timeout(GATT_START_TIME_MS).times( 242 startServiceCalls * invocationNumber + 1)).startService(any()); 243 mAdapterService.addProfile(mMockGattService); 244 mAdapterService.onProfileServiceStateChanged(mMockGattService, BluetoothAdapter.STATE_ON); 245 246 verifyStateChange(BluetoothAdapter.STATE_BLE_TURNING_ON, BluetoothAdapter.STATE_BLE_ON, 247 invocationNumber + 1, NATIVE_INIT_MS); 248 249 mServiceBinder.onLeServiceUp(mAttributionSource); 250 251 verifyStateChange(BluetoothAdapter.STATE_BLE_ON, BluetoothAdapter.STATE_TURNING_ON, 252 invocationNumber + 1, CONTEXT_SWITCH_MS); 253 254 if (!onlyGatt) { 255 // Start Mock PBAP and PAN services 256 verify(mMockContext, timeout(ONE_SECOND_MS).times( 257 startServiceCalls * invocationNumber + 3)).startService(any()); 258 mAdapterService.addProfile(mMockService); 259 mAdapterService.addProfile(mMockService2); 260 mAdapterService.onProfileServiceStateChanged(mMockService, BluetoothAdapter.STATE_ON); 261 mAdapterService.onProfileServiceStateChanged(mMockService2, BluetoothAdapter.STATE_ON); 262 } 263 264 verifyStateChange(BluetoothAdapter.STATE_TURNING_ON, BluetoothAdapter.STATE_ON, 265 invocationNumber + 1, PROFILE_SERVICE_TOGGLE_TIME_MS); 266 267 verify(mMockContext, timeout(CONTEXT_SWITCH_MS).times(2 * invocationNumber + 2)) 268 .sendBroadcast(any(), eq(BLUETOOTH_SCAN), 269 any(Bundle.class)); 270 final int scanMode = mServiceBinder.getScanMode(mAttributionSource); 271 Assert.assertTrue(scanMode == BluetoothAdapter.SCAN_MODE_CONNECTABLE 272 || scanMode == BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE); 273 Assert.assertTrue(mAdapterService.getState() == BluetoothAdapter.STATE_ON); 274 } 275 doDisable(int invocationNumber, boolean onlyGatt)276 private void doDisable(int invocationNumber, boolean onlyGatt) { 277 Assert.assertTrue(mAdapterService.getState() == BluetoothAdapter.STATE_ON); 278 279 final int startServiceCalls = 2 * (onlyGatt ? 1 : 3); // Start and stop GATT + 2 280 281 mAdapterService.disable(); 282 283 verifyStateChange(BluetoothAdapter.STATE_ON, BluetoothAdapter.STATE_TURNING_OFF, 284 invocationNumber + 1, CONTEXT_SWITCH_MS); 285 286 if (!onlyGatt) { 287 // Stop PBAP and PAN 288 verify(mMockContext, timeout(ONE_SECOND_MS).times( 289 startServiceCalls * invocationNumber + 5)).startService(any()); 290 mAdapterService.onProfileServiceStateChanged(mMockService, BluetoothAdapter.STATE_OFF); 291 mAdapterService.onProfileServiceStateChanged(mMockService2, BluetoothAdapter.STATE_OFF); 292 } 293 294 verifyStateChange(BluetoothAdapter.STATE_TURNING_OFF, BluetoothAdapter.STATE_BLE_ON, 295 invocationNumber + 1, PROFILE_SERVICE_TOGGLE_TIME_MS); 296 297 mServiceBinder.onBrEdrDown(mAttributionSource); 298 299 verifyStateChange(BluetoothAdapter.STATE_BLE_ON, BluetoothAdapter.STATE_BLE_TURNING_OFF, 300 invocationNumber + 1, CONTEXT_SWITCH_MS); 301 302 // Stop GATT 303 verify(mMockContext, timeout(ONE_SECOND_MS).times( 304 startServiceCalls * invocationNumber + startServiceCalls)).startService(any()); 305 mAdapterService.onProfileServiceStateChanged(mMockGattService, BluetoothAdapter.STATE_OFF); 306 307 verifyStateChange(BluetoothAdapter.STATE_BLE_TURNING_OFF, BluetoothAdapter.STATE_OFF, 308 invocationNumber + 1, NATIVE_DISABLE_MS); 309 310 Assert.assertFalse(mAdapterService.getState() == BluetoothAdapter.STATE_ON); 311 } 312 313 /** 314 * Test: Turn Bluetooth on. 315 * Check whether the AdapterService gets started. 316 */ 317 @Test testEnable()318 public void testEnable() { 319 doEnable(0, false); 320 } 321 322 /** 323 * Test: Turn Bluetooth on/off. 324 * Check whether the AdapterService gets started and stopped. 325 */ 326 @Test testEnableDisable()327 public void testEnableDisable() { 328 doEnable(0, false); 329 doDisable(0, false); 330 } 331 332 /** 333 * Test: Turn Bluetooth on/off with only GATT supported. 334 * Check whether the AdapterService gets started and stopped. 335 */ 336 @Test testEnableDisableOnlyGatt()337 public void testEnableDisableOnlyGatt() { 338 Context mockContext = mock(Context.class); 339 Resources mockResources = mock(Resources.class); 340 341 when(mockContext.getApplicationInfo()).thenReturn(mMockApplicationInfo); 342 when(mockContext.getContentResolver()).thenReturn(mMockContentResolver); 343 when(mockContext.getApplicationContext()).thenReturn(mockContext); 344 when(mockContext.getResources()).thenReturn(mockResources); 345 when(mockContext.getUserId()).thenReturn(Process.BLUETOOTH_UID); 346 when(mockContext.getPackageManager()).thenReturn(mMockPackageManager); 347 when(mockContext.getSystemService(Context.USER_SERVICE)).thenReturn(mMockUserManager); 348 when(mockContext.getSystemService(Context.POWER_SERVICE)).thenReturn(mPowerManager); 349 when(mockContext.getSystemService(Context.ALARM_SERVICE)).thenReturn(mMockAlarmManager); 350 351 when(mockResources.getBoolean(R.bool.profile_supported_gatt)).thenReturn(true); 352 353 Config.init(mockContext); 354 doEnable(0, true); 355 doDisable(0, true); 356 } 357 358 /** 359 * Test: Don't start GATT 360 * Check whether the AdapterService quits gracefully 361 */ 362 @Test testGattStartTimeout()363 public void testGattStartTimeout() { 364 Assert.assertFalse(mAdapterService.getState() == BluetoothAdapter.STATE_ON); 365 366 mAdapterService.enable(false); 367 368 verifyStateChange(BluetoothAdapter.STATE_OFF, BluetoothAdapter.STATE_BLE_TURNING_ON, 1, 369 CONTEXT_SWITCH_MS); 370 371 // Start GATT 372 verify(mMockContext, timeout(GATT_START_TIME_MS).times(1)).startService(any()); 373 mAdapterService.addProfile(mMockGattService); 374 375 verifyStateChange(BluetoothAdapter.STATE_BLE_TURNING_ON, 376 BluetoothAdapter.STATE_BLE_TURNING_OFF, 1, 377 AdapterState.BLE_START_TIMEOUT_DELAY + CONTEXT_SWITCH_MS); 378 379 // Stop GATT 380 verify(mMockContext, timeout(AdapterState.BLE_STOP_TIMEOUT_DELAY + CONTEXT_SWITCH_MS) 381 .times(2)).startService(any()); 382 383 verifyStateChange(BluetoothAdapter.STATE_BLE_TURNING_OFF, BluetoothAdapter.STATE_OFF, 1, 384 NATIVE_DISABLE_MS); 385 386 Assert.assertFalse(mAdapterService.getState() == BluetoothAdapter.STATE_ON); 387 } 388 389 /** 390 * Test: Don't stop GATT 391 * Check whether the AdapterService quits gracefully 392 */ 393 @Test testGattStopTimeout()394 public void testGattStopTimeout() { 395 doEnable(0, false); 396 Assert.assertTrue(mAdapterService.getState() == BluetoothAdapter.STATE_ON); 397 398 mAdapterService.disable(); 399 400 verifyStateChange(BluetoothAdapter.STATE_ON, BluetoothAdapter.STATE_TURNING_OFF, 1, 401 CONTEXT_SWITCH_MS); 402 403 // Stop PBAP and PAN 404 verify(mMockContext, timeout(ONE_SECOND_MS).times(5)).startService(any()); 405 mAdapterService.onProfileServiceStateChanged(mMockService, BluetoothAdapter.STATE_OFF); 406 mAdapterService.onProfileServiceStateChanged(mMockService2, BluetoothAdapter.STATE_OFF); 407 408 verifyStateChange(BluetoothAdapter.STATE_TURNING_OFF, BluetoothAdapter.STATE_BLE_ON, 1, 409 CONTEXT_SWITCH_MS); 410 411 mServiceBinder.onBrEdrDown(mAttributionSource); 412 413 verifyStateChange(BluetoothAdapter.STATE_BLE_ON, BluetoothAdapter.STATE_BLE_TURNING_OFF, 1, 414 CONTEXT_SWITCH_MS); 415 416 // Stop GATT 417 verify(mMockContext, timeout(ONE_SECOND_MS).times(6)).startService(any()); 418 419 verifyStateChange(BluetoothAdapter.STATE_BLE_TURNING_OFF, BluetoothAdapter.STATE_OFF, 1, 420 AdapterState.BLE_STOP_TIMEOUT_DELAY + NATIVE_DISABLE_MS); 421 422 Assert.assertFalse(mAdapterService.getState() == BluetoothAdapter.STATE_ON); 423 } 424 425 /** 426 * Test: Don't start a classic profile 427 * Check whether the AdapterService quits gracefully 428 */ 429 @Test testProfileStartTimeout()430 public void testProfileStartTimeout() { 431 Assert.assertFalse(mAdapterService.getState() == BluetoothAdapter.STATE_ON); 432 433 mAdapterService.enable(false); 434 435 verifyStateChange(BluetoothAdapter.STATE_OFF, BluetoothAdapter.STATE_BLE_TURNING_ON, 1, 436 CONTEXT_SWITCH_MS); 437 438 // Start GATT 439 verify(mMockContext, timeout(GATT_START_TIME_MS).times(1)).startService(any()); 440 mAdapterService.addProfile(mMockGattService); 441 mAdapterService.onProfileServiceStateChanged(mMockGattService, BluetoothAdapter.STATE_ON); 442 443 verifyStateChange(BluetoothAdapter.STATE_BLE_TURNING_ON, BluetoothAdapter.STATE_BLE_ON, 1, 444 NATIVE_INIT_MS); 445 446 mServiceBinder.onLeServiceUp(mAttributionSource); 447 448 verifyStateChange(BluetoothAdapter.STATE_BLE_ON, BluetoothAdapter.STATE_TURNING_ON, 1, 449 CONTEXT_SWITCH_MS); 450 451 // Register Mock PBAP and PAN services, only start one 452 verify(mMockContext, timeout(ONE_SECOND_MS).times(3)).startService(any()); 453 mAdapterService.addProfile(mMockService); 454 mAdapterService.addProfile(mMockService2); 455 mAdapterService.onProfileServiceStateChanged(mMockService, BluetoothAdapter.STATE_ON); 456 457 verifyStateChange(BluetoothAdapter.STATE_TURNING_ON, BluetoothAdapter.STATE_TURNING_OFF, 1, 458 AdapterState.BREDR_START_TIMEOUT_DELAY + CONTEXT_SWITCH_MS); 459 460 // Stop PBAP and PAN 461 verify(mMockContext, timeout(ONE_SECOND_MS).times(5)).startService(any()); 462 mAdapterService.onProfileServiceStateChanged(mMockService, BluetoothAdapter.STATE_OFF); 463 464 verifyStateChange(BluetoothAdapter.STATE_TURNING_OFF, BluetoothAdapter.STATE_BLE_ON, 1, 465 CONTEXT_SWITCH_MS); 466 } 467 468 /** 469 * Test: Don't stop a classic profile 470 * Check whether the AdapterService quits gracefully 471 */ 472 @Test testProfileStopTimeout()473 public void testProfileStopTimeout() { 474 doEnable(0, false); 475 476 Assert.assertTrue(mAdapterService.getState() == BluetoothAdapter.STATE_ON); 477 478 mAdapterService.disable(); 479 480 verifyStateChange(BluetoothAdapter.STATE_ON, BluetoothAdapter.STATE_TURNING_OFF, 1, 481 CONTEXT_SWITCH_MS); 482 483 // Stop PBAP and PAN 484 verify(mMockContext, timeout(ONE_SECOND_MS).times(5)).startService(any()); 485 mAdapterService.onProfileServiceStateChanged(mMockService, BluetoothAdapter.STATE_OFF); 486 487 verifyStateChange(BluetoothAdapter.STATE_TURNING_OFF, 488 BluetoothAdapter.STATE_BLE_TURNING_OFF, 1, 489 AdapterState.BREDR_STOP_TIMEOUT_DELAY + CONTEXT_SWITCH_MS); 490 491 // Stop GATT 492 verify(mMockContext, timeout(ONE_SECOND_MS).times(6)).startService(any()); 493 mAdapterService.onProfileServiceStateChanged(mMockGattService, BluetoothAdapter.STATE_OFF); 494 495 verifyStateChange(BluetoothAdapter.STATE_BLE_TURNING_OFF, BluetoothAdapter.STATE_OFF, 1, 496 AdapterState.BLE_STOP_TIMEOUT_DELAY + NATIVE_DISABLE_MS); 497 498 Assert.assertFalse(mAdapterService.getState() == BluetoothAdapter.STATE_ON); 499 } 500 501 /** 502 * Test: Toggle snoop logging setting 503 * Check whether the AdapterService restarts fully 504 */ 505 @Test testSnoopLoggingChange()506 public void testSnoopLoggingChange() { 507 String snoopSetting = 508 SystemProperties.get(AdapterService.BLUETOOTH_BTSNOOP_LOG_MODE_PROPERTY, ""); 509 SystemProperties.set(AdapterService.BLUETOOTH_BTSNOOP_LOG_MODE_PROPERTY, "false"); 510 doEnable(0, false); 511 512 Assert.assertTrue(mAdapterService.getState() == BluetoothAdapter.STATE_ON); 513 514 Assert.assertFalse( 515 SystemProperties.get(AdapterService.BLUETOOTH_BTSNOOP_LOG_MODE_PROPERTY, 516 "true").equals("true")); 517 518 SystemProperties.set(AdapterService.BLUETOOTH_BTSNOOP_LOG_MODE_PROPERTY, "true"); 519 520 mAdapterService.disable(); 521 522 verifyStateChange(BluetoothAdapter.STATE_ON, BluetoothAdapter.STATE_TURNING_OFF, 1, 523 CONTEXT_SWITCH_MS); 524 525 // Stop PBAP and PAN 526 verify(mMockContext, timeout(ONE_SECOND_MS).times(5)).startService(any()); 527 mAdapterService.onProfileServiceStateChanged(mMockService, BluetoothAdapter.STATE_OFF); 528 mAdapterService.onProfileServiceStateChanged(mMockService2, BluetoothAdapter.STATE_OFF); 529 530 verifyStateChange(BluetoothAdapter.STATE_TURNING_OFF, BluetoothAdapter.STATE_BLE_ON, 1, 531 CONTEXT_SWITCH_MS); 532 533 // Don't call onBrEdrDown(). The Adapter should turn itself off. 534 535 verifyStateChange(BluetoothAdapter.STATE_BLE_ON, BluetoothAdapter.STATE_BLE_TURNING_OFF, 1, 536 CONTEXT_SWITCH_MS); 537 538 // Stop GATT 539 verify(mMockContext, timeout(ONE_SECOND_MS).times(6)).startService(any()); 540 mAdapterService.onProfileServiceStateChanged(mMockGattService, BluetoothAdapter.STATE_OFF); 541 542 verifyStateChange(BluetoothAdapter.STATE_BLE_TURNING_OFF, BluetoothAdapter.STATE_OFF, 1, 543 NATIVE_DISABLE_MS); 544 545 Assert.assertFalse(mAdapterService.getState() == BluetoothAdapter.STATE_ON); 546 547 // Restore earlier setting 548 SystemProperties.set(AdapterService.BLUETOOTH_BTSNOOP_LOG_MODE_PROPERTY, snoopSetting); 549 } 550 551 552 /** 553 * Test: Obfuscate a null Bluetooth 554 * Check if returned value from {@link AdapterService#obfuscateAddress(BluetoothDevice)} is 555 * an empty array when device address is null 556 */ 557 @Test testObfuscateBluetoothAddress_NullAddress()558 public void testObfuscateBluetoothAddress_NullAddress() { 559 Assert.assertArrayEquals(mAdapterService.obfuscateAddress(null), new byte[0]); 560 } 561 562 /** 563 * Test: Obfuscate Bluetooth address when Bluetooth is disabled 564 * Check whether the returned value meets expectation 565 */ 566 @Test testObfuscateBluetoothAddress_BluetoothDisabled()567 public void testObfuscateBluetoothAddress_BluetoothDisabled() { 568 Assert.assertFalse(mAdapterService.getState() == BluetoothAdapter.STATE_ON); 569 byte[] metricsSalt = getMetricsSalt(mAdapterConfig); 570 Assert.assertNotNull(metricsSalt); 571 BluetoothDevice device = TestUtils.getTestDevice(BluetoothAdapter.getDefaultAdapter(), 0); 572 byte[] obfuscatedAddress = mAdapterService.obfuscateAddress(device); 573 Assert.assertTrue(obfuscatedAddress.length > 0); 574 Assert.assertFalse(isByteArrayAllZero(obfuscatedAddress)); 575 Assert.assertArrayEquals(obfuscateInJava(metricsSalt, device), obfuscatedAddress); 576 } 577 578 /** 579 * Test: Obfuscate Bluetooth address when Bluetooth is enabled 580 * Check whether the returned value meets expectation 581 */ 582 @Test testObfuscateBluetoothAddress_BluetoothEnabled()583 public void testObfuscateBluetoothAddress_BluetoothEnabled() { 584 Assert.assertFalse(mAdapterService.getState() == BluetoothAdapter.STATE_ON); 585 doEnable(0, false); 586 Assert.assertTrue(mAdapterService.getState() == BluetoothAdapter.STATE_ON); 587 byte[] metricsSalt = getMetricsSalt(mAdapterConfig); 588 Assert.assertNotNull(metricsSalt); 589 BluetoothDevice device = TestUtils.getTestDevice(BluetoothAdapter.getDefaultAdapter(), 0); 590 byte[] obfuscatedAddress = mAdapterService.obfuscateAddress(device); 591 Assert.assertTrue(obfuscatedAddress.length > 0); 592 Assert.assertFalse(isByteArrayAllZero(obfuscatedAddress)); 593 Assert.assertArrayEquals(obfuscateInJava(metricsSalt, device), obfuscatedAddress); 594 } 595 596 /** 597 * Test: Check if obfuscated Bluetooth address stays the same after toggling Bluetooth 598 */ 599 @Test testObfuscateBluetoothAddress_PersistentBetweenToggle()600 public void testObfuscateBluetoothAddress_PersistentBetweenToggle() { 601 Assert.assertFalse(mAdapterService.getState() == BluetoothAdapter.STATE_ON); 602 byte[] metricsSalt = getMetricsSalt(mAdapterConfig); 603 Assert.assertNotNull(metricsSalt); 604 BluetoothDevice device = TestUtils.getTestDevice(BluetoothAdapter.getDefaultAdapter(), 0); 605 byte[] obfuscatedAddress1 = mAdapterService.obfuscateAddress(device); 606 Assert.assertTrue(obfuscatedAddress1.length > 0); 607 Assert.assertFalse(isByteArrayAllZero(obfuscatedAddress1)); 608 Assert.assertArrayEquals(obfuscateInJava(metricsSalt, device), 609 obfuscatedAddress1); 610 // Enable 611 doEnable(0, false); 612 Assert.assertTrue(mAdapterService.getState() == BluetoothAdapter.STATE_ON); 613 byte[] obfuscatedAddress3 = mAdapterService.obfuscateAddress(device); 614 Assert.assertTrue(obfuscatedAddress3.length > 0); 615 Assert.assertFalse(isByteArrayAllZero(obfuscatedAddress3)); 616 Assert.assertArrayEquals(obfuscatedAddress3, 617 obfuscatedAddress1); 618 // Disable 619 doDisable(0, false); 620 Assert.assertFalse(mAdapterService.getState() == BluetoothAdapter.STATE_ON); 621 byte[] obfuscatedAddress4 = mAdapterService.obfuscateAddress(device); 622 Assert.assertTrue(obfuscatedAddress4.length > 0); 623 Assert.assertFalse(isByteArrayAllZero(obfuscatedAddress4)); 624 Assert.assertArrayEquals(obfuscatedAddress4, 625 obfuscatedAddress1); 626 } 627 628 /** 629 * Test: Check if obfuscated Bluetooth address stays the same after re-initializing 630 * {@link AdapterService} 631 */ 632 @Test testObfuscateBluetoothAddress_PersistentBetweenAdapterServiceInitialization()633 public void testObfuscateBluetoothAddress_PersistentBetweenAdapterServiceInitialization() throws 634 PackageManager.NameNotFoundException { 635 byte[] metricsSalt = getMetricsSalt(mAdapterConfig); 636 Assert.assertNotNull(metricsSalt); 637 Assert.assertFalse(mAdapterService.getState() == BluetoothAdapter.STATE_ON); 638 BluetoothDevice device = TestUtils.getTestDevice(BluetoothAdapter.getDefaultAdapter(), 0); 639 byte[] obfuscatedAddress1 = mAdapterService.obfuscateAddress(device); 640 Assert.assertTrue(obfuscatedAddress1.length > 0); 641 Assert.assertFalse(isByteArrayAllZero(obfuscatedAddress1)); 642 Assert.assertArrayEquals(obfuscateInJava(metricsSalt, device), 643 obfuscatedAddress1); 644 tearDown(); 645 setUp(); 646 Assert.assertFalse(mAdapterService.getState() == BluetoothAdapter.STATE_ON); 647 byte[] obfuscatedAddress2 = mAdapterService.obfuscateAddress(device); 648 Assert.assertTrue(obfuscatedAddress2.length > 0); 649 Assert.assertFalse(isByteArrayAllZero(obfuscatedAddress2)); 650 Assert.assertArrayEquals(obfuscatedAddress2, 651 obfuscatedAddress1); 652 } 653 654 /** 655 * Test: Verify that obfuscated Bluetooth address changes after factory reset 656 * 657 * There are 4 types of factory reset that we are talking about: 658 * 1. Factory reset all user data from Settings -> Will restart phone 659 * 2. Factory reset WiFi and Bluetooth from Settings -> Will only restart WiFi and BT 660 * 3. Call BluetoothAdapter.factoryReset() -> Will disable Bluetooth and reset config in 661 * memory and disk 662 * 4. Call AdapterService.factoryReset() -> Will only reset config in memory 663 * 664 * We can only use No. 4 here 665 */ 666 @Ignore("AdapterService.factoryReset() does not reload config into memory and hence old salt" 667 + " is still used until next time Bluetooth library is initialized. However Bluetooth" 668 + " cannot be used until Bluetooth process restart any way. Thus it is almost" 669 + " guaranteed that user has to re-enable Bluetooth and hence re-generate new salt" 670 + " after factory reset") 671 @Test testObfuscateBluetoothAddress_FactoryReset()672 public void testObfuscateBluetoothAddress_FactoryReset() { 673 Assert.assertFalse(mAdapterService.getState() == BluetoothAdapter.STATE_ON); 674 BluetoothDevice device = TestUtils.getTestDevice(BluetoothAdapter.getDefaultAdapter(), 0); 675 byte[] obfuscatedAddress1 = mAdapterService.obfuscateAddress(device); 676 Assert.assertTrue(obfuscatedAddress1.length > 0); 677 Assert.assertFalse(isByteArrayAllZero(obfuscatedAddress1)); 678 mServiceBinder.factoryReset(mAttributionSource); 679 byte[] obfuscatedAddress2 = mAdapterService.obfuscateAddress(device); 680 Assert.assertTrue(obfuscatedAddress2.length > 0); 681 Assert.assertFalse(isByteArrayAllZero(obfuscatedAddress2)); 682 Assert.assertFalse(Arrays.equals(obfuscatedAddress2, 683 obfuscatedAddress1)); 684 doEnable(0, false); 685 byte[] obfuscatedAddress3 = mAdapterService.obfuscateAddress(device); 686 Assert.assertTrue(obfuscatedAddress3.length > 0); 687 Assert.assertFalse(isByteArrayAllZero(obfuscatedAddress3)); 688 Assert.assertArrayEquals(obfuscatedAddress3, 689 obfuscatedAddress2); 690 mServiceBinder.factoryReset(mAttributionSource); 691 byte[] obfuscatedAddress4 = mAdapterService.obfuscateAddress(device); 692 Assert.assertTrue(obfuscatedAddress4.length > 0); 693 Assert.assertFalse(isByteArrayAllZero(obfuscatedAddress4)); 694 Assert.assertFalse(Arrays.equals(obfuscatedAddress4, 695 obfuscatedAddress3)); 696 } 697 698 /** 699 * Test: Verify that obfuscated Bluetooth address changes after factory reset and reloading 700 * native layer 701 */ 702 @Test testObfuscateBluetoothAddress_FactoryResetAndReloadNativeLayer()703 public void testObfuscateBluetoothAddress_FactoryResetAndReloadNativeLayer() throws 704 PackageManager.NameNotFoundException { 705 byte[] metricsSalt1 = getMetricsSalt(mAdapterConfig); 706 Assert.assertNotNull(metricsSalt1); 707 Assert.assertFalse(mAdapterService.getState() == BluetoothAdapter.STATE_ON); 708 BluetoothDevice device = TestUtils.getTestDevice(BluetoothAdapter.getDefaultAdapter(), 0); 709 byte[] obfuscatedAddress1 = mAdapterService.obfuscateAddress(device); 710 Assert.assertTrue(obfuscatedAddress1.length > 0); 711 Assert.assertFalse(isByteArrayAllZero(obfuscatedAddress1)); 712 Assert.assertArrayEquals(obfuscateInJava(metricsSalt1, device), 713 obfuscatedAddress1); 714 mServiceBinder.factoryReset(mAttributionSource); 715 tearDown(); 716 setUp(); 717 // Cannot verify metrics salt since it is not written to disk until native cleanup 718 byte[] obfuscatedAddress2 = mAdapterService.obfuscateAddress(device); 719 Assert.assertTrue(obfuscatedAddress2.length > 0); 720 Assert.assertFalse(isByteArrayAllZero(obfuscatedAddress2)); 721 Assert.assertFalse(Arrays.equals(obfuscatedAddress2, 722 obfuscatedAddress1)); 723 } 724 getMetricsSalt(HashMap<String, HashMap<String, String>> adapterConfig)725 private static byte[] getMetricsSalt(HashMap<String, HashMap<String, String>> adapterConfig) { 726 HashMap<String, String> metricsSection = adapterConfig.get("Metrics"); 727 if (metricsSection == null) { 728 Log.e(TAG, "Metrics section is null: " + adapterConfig.toString()); 729 return null; 730 } 731 String saltString = metricsSection.get("Salt256Bit"); 732 if (saltString == null) { 733 Log.e(TAG, "Salt256Bit is null: " + metricsSection.toString()); 734 return null; 735 } 736 byte[] metricsSalt = HexEncoding.decode(saltString, false /* allowSingleChar */); 737 if (metricsSalt.length != 32) { 738 Log.e(TAG, "Salt length is not 32 bit, but is " + metricsSalt.length); 739 return null; 740 } 741 return metricsSalt; 742 } 743 obfuscateInJava(byte[] key, BluetoothDevice device)744 private static byte[] obfuscateInJava(byte[] key, BluetoothDevice device) { 745 String algorithm = "HmacSHA256"; 746 try { 747 Mac hmac256 = Mac.getInstance(algorithm); 748 hmac256.init(new SecretKeySpec(key, algorithm)); 749 return hmac256.doFinal(Utils.getByteAddress(device)); 750 } catch (NoSuchAlgorithmException | IllegalStateException | InvalidKeyException exp) { 751 exp.printStackTrace(); 752 return null; 753 } 754 } 755 isByteArrayAllZero(byte[] byteArray)756 private static boolean isByteArrayAllZero(byte[] byteArray) { 757 for (byte i : byteArray) { 758 if (i != 0) { 759 return false; 760 } 761 } 762 return true; 763 } 764 765 /** 766 * Test: Get id for null address 767 * Check if returned value from {@link AdapterService#getMetricId(BluetoothDevice)} is 768 * 0 when device address is null 769 */ 770 @Test testGetMetricId_NullAddress()771 public void testGetMetricId_NullAddress() { 772 Assert.assertEquals(mAdapterService.getMetricId(null), 0); 773 } 774 775 /** 776 * Test: Get id when Bluetooth is disabled 777 * Check whether the returned value meets expectation 778 */ 779 @Test testGetMetricId_BluetoothDisabled()780 public void testGetMetricId_BluetoothDisabled() { 781 Assert.assertFalse(mAdapterService.getState() == BluetoothAdapter.STATE_ON); 782 BluetoothDevice device = TestUtils.getTestDevice(BluetoothAdapter.getDefaultAdapter(), 0); 783 int id = mAdapterService.getMetricId(device); 784 Assert.assertTrue(id > 0); 785 } 786 787 /** 788 * Test: Get id when Bluetooth is enabled 789 * Check whether the returned value meets expectation 790 */ 791 @Test testGetMetricId_BluetoothEnabled()792 public void testGetMetricId_BluetoothEnabled() { 793 Assert.assertFalse(mAdapterService.getState() == BluetoothAdapter.STATE_ON); 794 doEnable(0, false); 795 Assert.assertTrue(mAdapterService.getState() == BluetoothAdapter.STATE_ON); 796 BluetoothDevice device = TestUtils.getTestDevice(BluetoothAdapter.getDefaultAdapter(), 0); 797 int id = mAdapterService.getMetricId(device); 798 Assert.assertTrue(id > 0); 799 } 800 801 /** 802 * Test: Check if id gotten stays the same after toggling Bluetooth 803 */ 804 @Test testGetMetricId_PersistentBetweenToggle()805 public void testGetMetricId_PersistentBetweenToggle() { 806 Assert.assertFalse(mAdapterService.getState() == BluetoothAdapter.STATE_ON); 807 BluetoothDevice device = TestUtils.getTestDevice(BluetoothAdapter.getDefaultAdapter(), 0); 808 int id1 = mAdapterService.getMetricId(device); 809 Assert.assertTrue(id1 > 0); 810 811 // Enable 812 doEnable(0, false); 813 Assert.assertTrue(mAdapterService.getState() == BluetoothAdapter.STATE_ON); 814 int id2 = mAdapterService.getMetricId(device); 815 Assert.assertEquals(id2, id1); 816 817 // Disable 818 doDisable(0, false); 819 Assert.assertFalse(mAdapterService.getState() == BluetoothAdapter.STATE_ON); 820 int id3 = mAdapterService.getMetricId(device); 821 Assert.assertEquals(id3, id1); 822 } 823 824 /** 825 * Test: Check if id gotten stays the same after re-initializing 826 * {@link AdapterService} 827 */ 828 @Test testgetMetricId_PersistentBetweenAdapterServiceInitialization()829 public void testgetMetricId_PersistentBetweenAdapterServiceInitialization() throws 830 PackageManager.NameNotFoundException { 831 Assert.assertFalse(mAdapterService.getState() == BluetoothAdapter.STATE_ON); 832 BluetoothDevice device = TestUtils.getTestDevice(BluetoothAdapter.getDefaultAdapter(), 0); 833 int id1 = mAdapterService.getMetricId(device); 834 Assert.assertTrue(id1 > 0); 835 tearDown(); 836 setUp(); 837 Assert.assertFalse(mAdapterService.getState() == BluetoothAdapter.STATE_ON); 838 int id2 = mAdapterService.getMetricId(device); 839 Assert.assertEquals(id2, id1); 840 } 841 } 842