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.bluetooth.BluetoothAdapter.STATE_BLE_ON; 20 import static android.bluetooth.BluetoothAdapter.STATE_BLE_TURNING_OFF; 21 import static android.bluetooth.BluetoothAdapter.STATE_BLE_TURNING_ON; 22 import static android.bluetooth.BluetoothAdapter.STATE_OFF; 23 import static android.bluetooth.BluetoothAdapter.STATE_ON; 24 import static android.bluetooth.BluetoothAdapter.STATE_TURNING_OFF; 25 import static android.bluetooth.BluetoothAdapter.STATE_TURNING_ON; 26 27 import static com.google.common.truth.Truth.assertThat; 28 import static com.google.common.truth.Truth.assertWithMessage; 29 30 import static org.mockito.ArgumentMatchers.any; 31 import static org.mockito.Mockito.*; 32 33 import android.app.AlarmManager; 34 import android.app.AppOpsManager; 35 import android.app.admin.DevicePolicyManager; 36 import android.bluetooth.BluetoothAdapter; 37 import android.bluetooth.BluetoothDevice; 38 import android.bluetooth.BluetoothManager; 39 import android.bluetooth.BluetoothProfile; 40 import android.bluetooth.IBluetoothCallback; 41 import android.companion.CompanionDeviceManager; 42 import android.content.Context; 43 import android.content.pm.ApplicationInfo; 44 import android.content.pm.PackageManager; 45 import android.content.pm.PermissionInfo; 46 import android.content.res.Resources; 47 import android.hardware.display.DisplayManager; 48 import android.media.AudioManager; 49 import android.os.BatteryStatsManager; 50 import android.os.Binder; 51 import android.os.Bundle; 52 import android.os.Handler; 53 import android.os.Looper; 54 import android.os.Message; 55 import android.os.PowerManager; 56 import android.os.Process; 57 import android.os.RemoteException; 58 import android.os.UserHandle; 59 import android.os.UserManager; 60 import android.os.test.TestLooper; 61 import android.permission.PermissionCheckerManager; 62 import android.permission.PermissionManager; 63 import android.platform.test.annotations.DisableFlags; 64 import android.platform.test.annotations.EnableFlags; 65 import android.platform.test.flag.junit.FlagsParameterization; 66 import android.platform.test.flag.junit.SetFlagsRule; 67 import android.provider.Settings; 68 import android.sysprop.BluetoothProperties; 69 import android.test.mock.MockContentProvider; 70 import android.test.mock.MockContentResolver; 71 import android.util.Log; 72 73 import androidx.test.InstrumentationRegistry; 74 import androidx.test.filters.MediumTest; 75 76 import com.android.bluetooth.TestUtils; 77 import com.android.bluetooth.Utils; 78 import com.android.bluetooth.btservice.bluetoothkeystore.BluetoothKeystoreNativeInterface; 79 import com.android.bluetooth.flags.Flags; 80 import com.android.bluetooth.gatt.AdvertiseManagerNativeInterface; 81 import com.android.bluetooth.gatt.DistanceMeasurementNativeInterface; 82 import com.android.bluetooth.gatt.GattNativeInterface; 83 import com.android.bluetooth.le_scan.PeriodicScanNativeInterface; 84 import com.android.bluetooth.le_scan.ScanNativeInterface; 85 import com.android.bluetooth.sdp.SdpManagerNativeInterface; 86 import com.android.internal.app.IBatteryStats; 87 88 import libcore.util.HexEncoding; 89 90 import org.junit.After; 91 import org.junit.Before; 92 import org.junit.Rule; 93 import org.junit.Test; 94 import org.junit.runner.RunWith; 95 import org.mockito.Mock; 96 import org.mockito.junit.MockitoJUnit; 97 import org.mockito.junit.MockitoRule; 98 99 import platform.test.runner.parameterized.ParameterizedAndroidJunit4; 100 import platform.test.runner.parameterized.Parameters; 101 102 import java.io.FileDescriptor; 103 import java.io.PrintWriter; 104 import java.security.InvalidKeyException; 105 import java.security.NoSuchAlgorithmException; 106 import java.util.List; 107 import java.util.Map; 108 109 import javax.crypto.Mac; 110 import javax.crypto.spec.SecretKeySpec; 111 112 @MediumTest 113 @RunWith(ParameterizedAndroidJunit4.class) 114 public class AdapterServiceTest { 115 private static final String TAG = AdapterServiceTest.class.getSimpleName(); 116 private static final String TEST_BT_ADDR_1 = "00:11:22:33:44:55"; 117 private static final String TEST_BT_ADDR_2 = "00:11:22:33:44:66"; 118 119 private static final int MESSAGE_PROFILE_SERVICE_STATE_CHANGED = 1; 120 private static final int MESSAGE_PROFILE_SERVICE_REGISTERED = 2; 121 private static final int MESSAGE_PROFILE_SERVICE_UNREGISTERED = 3; 122 123 private MockAdapterService mAdapterService; 124 125 static class MockAdapterService extends AdapterService { 126 127 int mSetProfileServiceStateCounter = 0; 128 MockAdapterService(Looper looper)129 MockAdapterService(Looper looper) { 130 super(looper); 131 } 132 133 @Override setProfileServiceState(int profileId, int state)134 void setProfileServiceState(int profileId, int state) { 135 mSetProfileServiceStateCounter++; 136 } 137 } 138 139 @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); 140 141 private @Mock Context mMockContext; 142 private @Mock ApplicationInfo mMockApplicationInfo; 143 private @Mock Resources mMockResources; 144 private @Mock ProfileService mMockGattService; 145 private @Mock ProfileService mMockService; 146 private @Mock ProfileService mMockService2; 147 private @Mock IBluetoothCallback mIBluetoothCallback; 148 private @Mock Binder mBinder; 149 private @Mock android.app.Application mApplication; 150 private @Mock MetricsLogger mMockMetricsLogger; 151 private @Mock AdapterNativeInterface mNativeInterface; 152 private @Mock BluetoothKeystoreNativeInterface mKeystoreNativeInterface; 153 private @Mock BluetoothQualityReportNativeInterface mQualityNativeInterface; 154 private @Mock SdpManagerNativeInterface mSdpNativeInterface; 155 private @Mock AdvertiseManagerNativeInterface mAdvertiseNativeInterface; 156 private @Mock DistanceMeasurementNativeInterface mDistanceNativeInterface; 157 private @Mock GattNativeInterface mGattNativeInterface; 158 private @Mock PeriodicScanNativeInterface mPeriodicNativeInterface; 159 private @Mock ScanNativeInterface mScanNativeInterface; 160 private @Mock JniCallbacks mJniCallbacks; 161 162 @Rule public final SetFlagsRule mSetFlagsRule; 163 164 // SystemService that are not mocked 165 private BluetoothManager mBluetoothManager; 166 private CompanionDeviceManager mCompanionDeviceManager; 167 private DisplayManager mDisplayManager; 168 private PowerManager mPowerManager; 169 private PermissionCheckerManager mPermissionCheckerManager; 170 private PermissionManager mPermissionManager; 171 // BatteryStatsManager is final and cannot be mocked with regular mockito, so just mock the 172 // underlying binder calls. 173 final BatteryStatsManager mBatteryStatsManager = 174 new BatteryStatsManager(mock(IBatteryStats.class)); 175 176 private static final int CONTEXT_SWITCH_MS = 100; 177 178 private PackageManager mMockPackageManager; 179 private MockContentResolver mMockContentResolver; 180 private int mForegroundUserId; 181 private TestLooper mLooper; 182 configureEnabledProfiles()183 static void configureEnabledProfiles() { 184 Log.e(TAG, "configureEnabledProfiles"); 185 186 for (int profileId = 0; profileId <= BluetoothProfile.MAX_PROFILE_ID; profileId++) { 187 boolean enabled = 188 profileId == BluetoothProfile.PAN 189 || profileId == BluetoothProfile.PBAP 190 || profileId == BluetoothProfile.GATT; 191 192 Config.setProfileEnabled(profileId, enabled); 193 } 194 } 195 mockGetSystemService(String serviceName, Class<T> serviceClass, T mockService)196 <T> void mockGetSystemService(String serviceName, Class<T> serviceClass, T mockService) { 197 TestUtils.mockGetSystemService(mMockContext, serviceName, serviceClass, mockService); 198 } 199 mockGetSystemService(String serviceName, Class<T> serviceClass)200 <T> T mockGetSystemService(String serviceName, Class<T> serviceClass) { 201 return TestUtils.mockGetSystemService(mMockContext, serviceName, serviceClass); 202 } 203 204 @Parameters(name = "{0}") getParams()205 public static List<FlagsParameterization> getParams() { 206 return FlagsParameterization.allCombinationsOf(Flags.FLAG_EXPLICIT_KILL_FROM_SYSTEM_SERVER); 207 } 208 AdapterServiceTest(FlagsParameterization flags)209 public AdapterServiceTest(FlagsParameterization flags) { 210 mSetFlagsRule = new SetFlagsRule(flags); 211 } 212 213 @Before setUp()214 public void setUp() throws PackageManager.NameNotFoundException { 215 Log.e(TAG, "setUp()"); 216 217 mLooper = new TestLooper(); 218 Handler handler = new Handler(mLooper.getLooper()); 219 220 doReturn(mJniCallbacks).when(mNativeInterface).getCallbacks(); 221 222 AdapterNativeInterface.setInstance(mNativeInterface); 223 BluetoothKeystoreNativeInterface.setInstance(mKeystoreNativeInterface); 224 BluetoothQualityReportNativeInterface.setInstance(mQualityNativeInterface); 225 SdpManagerNativeInterface.setInstance(mSdpNativeInterface); 226 AdvertiseManagerNativeInterface.setInstance(mAdvertiseNativeInterface); 227 DistanceMeasurementNativeInterface.setInstance(mDistanceNativeInterface); 228 GattNativeInterface.setInstance(mGattNativeInterface); 229 PeriodicScanNativeInterface.setInstance(mPeriodicNativeInterface); 230 ScanNativeInterface.setInstance(mScanNativeInterface); 231 232 // Post the creation of AdapterService since it rely on Looper.myLooper() 233 handler.post(() -> mAdapterService = new MockAdapterService(mLooper.getLooper())); 234 assertThat(mLooper.dispatchAll()).isEqualTo(1); 235 assertThat(mAdapterService).isNotNull(); 236 237 mMockPackageManager = mock(PackageManager.class); 238 when(mMockPackageManager.getPermissionInfo(any(), anyInt())) 239 .thenReturn(new PermissionInfo()); 240 241 Context targetContext = InstrumentationRegistry.getTargetContext(); 242 243 mMockContentResolver = new MockContentResolver(targetContext); 244 mMockContentResolver.addProvider( 245 Settings.AUTHORITY, 246 new MockContentProvider() { 247 @Override 248 public Bundle call(String method, String request, Bundle args) { 249 return Bundle.EMPTY; 250 } 251 }); 252 253 mBluetoothManager = targetContext.getSystemService(BluetoothManager.class); 254 mCompanionDeviceManager = targetContext.getSystemService(CompanionDeviceManager.class); 255 mDisplayManager = targetContext.getSystemService(DisplayManager.class); 256 mPermissionCheckerManager = targetContext.getSystemService(PermissionCheckerManager.class); 257 mPermissionManager = targetContext.getSystemService(PermissionManager.class); 258 mPowerManager = targetContext.getSystemService(PowerManager.class); 259 260 when(mMockContext.getCacheDir()).thenReturn(targetContext.getCacheDir()); 261 when(mMockContext.getUser()).thenReturn(targetContext.getUser()); 262 when(mMockContext.getPackageName()).thenReturn(targetContext.getPackageName()); 263 when(mMockContext.getApplicationInfo()).thenReturn(mMockApplicationInfo); 264 when(mMockContext.getContentResolver()).thenReturn(mMockContentResolver); 265 when(mMockContext.getApplicationContext()).thenReturn(mMockContext); 266 when(mMockContext.createContextAsUser(UserHandle.SYSTEM, /* flags= */ 0)) 267 .thenReturn(mMockContext); 268 when(mMockContext.getResources()).thenReturn(mMockResources); 269 when(mMockContext.getUserId()).thenReturn(Process.BLUETOOTH_UID); 270 when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager); 271 272 mockGetSystemService(Context.ALARM_SERVICE, AlarmManager.class); 273 mockGetSystemService(Context.APP_OPS_SERVICE, AppOpsManager.class); 274 mockGetSystemService(Context.AUDIO_SERVICE, AudioManager.class); 275 DevicePolicyManager dpm = 276 mockGetSystemService(Context.DEVICE_POLICY_SERVICE, DevicePolicyManager.class); 277 doReturn(false).when(dpm).isCommonCriteriaModeEnabled(any()); 278 mockGetSystemService(Context.USER_SERVICE, UserManager.class); 279 280 mockGetSystemService( 281 Context.BATTERY_STATS_SERVICE, BatteryStatsManager.class, mBatteryStatsManager); 282 mockGetSystemService(Context.BLUETOOTH_SERVICE, BluetoothManager.class, mBluetoothManager); 283 mockGetSystemService( 284 Context.COMPANION_DEVICE_SERVICE, 285 CompanionDeviceManager.class, 286 mCompanionDeviceManager); 287 mockGetSystemService(Context.DISPLAY_SERVICE, DisplayManager.class, mDisplayManager); 288 mockGetSystemService( 289 Context.PERMISSION_CHECKER_SERVICE, 290 PermissionCheckerManager.class, 291 mPermissionCheckerManager); 292 mockGetSystemService( 293 Context.PERMISSION_SERVICE, PermissionManager.class, mPermissionManager); 294 mockGetSystemService(Context.POWER_SERVICE, PowerManager.class, mPowerManager); 295 296 when(mMockContext.getSharedPreferences(anyString(), anyInt())) 297 .thenReturn( 298 targetContext.getSharedPreferences( 299 "AdapterServiceTestPrefs", Context.MODE_PRIVATE)); 300 301 doAnswer( 302 invocation -> { 303 Object[] args = invocation.getArguments(); 304 return targetContext.getDatabasePath((String) args[0]); 305 }) 306 .when(mMockContext) 307 .getDatabasePath(anyString()); 308 309 // Sets the foreground user id to match that of the tests (restored in tearDown) 310 mForegroundUserId = Utils.getForegroundUserId(); 311 int callingUid = Binder.getCallingUid(); 312 UserHandle callingUser = UserHandle.getUserHandleForUid(callingUid); 313 Utils.setForegroundUserId(callingUser.getIdentifier()); 314 315 when(mIBluetoothCallback.asBinder()).thenReturn(mBinder); 316 317 doReturn(Process.BLUETOOTH_UID) 318 .when(mMockPackageManager) 319 .getPackageUidAsUser(any(), anyInt(), anyInt()); 320 321 when(mMockGattService.getName()).thenReturn("GattService"); 322 when(mMockService.getName()).thenReturn("Service1"); 323 when(mMockService2.getName()).thenReturn("Service2"); 324 325 when(mMockMetricsLogger.init(any())).thenReturn(true); 326 when(mMockMetricsLogger.close()).thenReturn(true); 327 328 configureEnabledProfiles(); 329 Config.init(mMockContext); 330 331 mAdapterService.setMetricsLogger(mMockMetricsLogger); 332 333 // Attach a context to the service for permission checks. 334 mAdapterService.attach(mMockContext, null, null, null, mApplication, null); 335 mAdapterService.onCreate(); 336 337 mLooper.dispatchAll(); 338 339 mAdapterService.registerRemoteCallback(mIBluetoothCallback); 340 } 341 342 @After tearDown()343 public void tearDown() { 344 Log.e(TAG, "tearDown()"); 345 346 // Restores the foregroundUserId to the ID prior to the test setup 347 Utils.setForegroundUserId(mForegroundUserId); 348 349 assertThat(mLooper.nextMessage()).isNull(); 350 mAdapterService.cleanup(); 351 mAdapterService.unregisterRemoteCallback(mIBluetoothCallback); 352 AdapterNativeInterface.setInstance(null); 353 BluetoothKeystoreNativeInterface.setInstance(null); 354 BluetoothQualityReportNativeInterface.setInstance(null); 355 SdpManagerNativeInterface.setInstance(null); 356 AdvertiseManagerNativeInterface.setInstance(null); 357 DistanceMeasurementNativeInterface.setInstance(null); 358 GattNativeInterface.setInstance(null); 359 PeriodicScanNativeInterface.setInstance(null); 360 ScanNativeInterface.setInstance(null); 361 } 362 syncHandler(int... what)363 private void syncHandler(int... what) { 364 TestUtils.syncHandler(mLooper, what); 365 } 366 dropNextMessage(int what)367 private void dropNextMessage(int what) { 368 Message msg = mLooper.nextMessage(); 369 assertThat(msg).isNotNull(); 370 assertWithMessage("Not the expected Message:\n" + msg).that(msg.what).isEqualTo(what); 371 Log.d(TAG, "Message dropped on purpose: " + msg); 372 } 373 verifyStateChange(int prevState, int currState)374 private void verifyStateChange(int prevState, int currState) { 375 try { 376 verify(mIBluetoothCallback).onBluetoothStateChange(prevState, currState); 377 } catch (RemoteException e) { 378 // the mocked onBluetoothStateChange doesn't throw RemoteException 379 } 380 } 381 verifyStateChange(int prevState, int currState, int timeoutMs)382 private void verifyStateChange(int prevState, int currState, int timeoutMs) { 383 try { 384 verify(mIBluetoothCallback, timeout(timeoutMs)) 385 .onBluetoothStateChange(prevState, currState); 386 } catch (RemoteException e) { 387 // the mocked onBluetoothStateChange doesn't throw RemoteException 388 } 389 } 390 verifyStateChange(IBluetoothCallback cb, int prevState, int currState)391 private static void verifyStateChange(IBluetoothCallback cb, int prevState, int currState) { 392 try { 393 verify(cb).onBluetoothStateChange(prevState, currState); 394 } catch (RemoteException e) { 395 // the mocked onBluetoothStateChange doesn't throw RemoteException 396 } 397 } 398 offToBleOn( TestLooper looper, ProfileService gattService, AdapterService adapter, Context ctx, IBluetoothCallback callback, AdapterNativeInterface nativeInterface)399 static void offToBleOn( 400 TestLooper looper, 401 ProfileService gattService, 402 AdapterService adapter, 403 Context ctx, 404 IBluetoothCallback callback, 405 AdapterNativeInterface nativeInterface) { 406 adapter.enable(false); 407 if (Flags.fastBindToApp()) { 408 TestUtils.syncHandler(looper, 0); // when fastBindToApp is enable init need to be run 409 } 410 TestUtils.syncHandler(looper, AdapterState.BLE_TURN_ON); 411 verifyStateChange(callback, STATE_OFF, STATE_BLE_TURNING_ON); 412 413 if (!Flags.scanManagerRefactor()) { 414 TestUtils.syncHandler(looper, MESSAGE_PROFILE_SERVICE_REGISTERED); 415 416 TestUtils.syncHandler(looper, MESSAGE_PROFILE_SERVICE_STATE_CHANGED); 417 } 418 419 verify(nativeInterface).enable(); 420 adapter.stateChangeCallback(AbstractionLayer.BT_STATE_ON); 421 TestUtils.syncHandler(looper, AdapterState.BLE_STARTED); 422 verifyStateChange(callback, STATE_BLE_TURNING_ON, STATE_BLE_ON); 423 assertThat(adapter.getState()).isEqualTo(STATE_BLE_ON); 424 } 425 onToBleOn( TestLooper looper, MockAdapterService adapter, Context ctx, IBluetoothCallback callback, boolean onlyGatt, List<ProfileService> services)426 static void onToBleOn( 427 TestLooper looper, 428 MockAdapterService adapter, 429 Context ctx, 430 IBluetoothCallback callback, 431 boolean onlyGatt, 432 List<ProfileService> services) { 433 adapter.disable(); 434 TestUtils.syncHandler(looper, AdapterState.USER_TURN_OFF); 435 verifyStateChange(callback, STATE_ON, STATE_TURNING_OFF); 436 437 if (!onlyGatt) { 438 // Stop PBAP and PAN services 439 assertThat(adapter.mSetProfileServiceStateCounter).isEqualTo(4); 440 441 for (ProfileService service : services) { 442 adapter.onProfileServiceStateChanged(service, STATE_OFF); 443 TestUtils.syncHandler(looper, MESSAGE_PROFILE_SERVICE_STATE_CHANGED); 444 } 445 } 446 447 TestUtils.syncHandler(looper, AdapterState.BREDR_STOPPED); 448 verifyStateChange(callback, STATE_TURNING_OFF, STATE_BLE_ON); 449 450 assertThat(adapter.getState()).isEqualTo(STATE_BLE_ON); 451 } 452 doEnable(boolean onlyGatt)453 void doEnable(boolean onlyGatt) { 454 doEnable( 455 mLooper, 456 mMockGattService, 457 mAdapterService, 458 mMockContext, 459 onlyGatt, 460 List.of(mMockService, mMockService2), 461 mNativeInterface); 462 } 463 464 // Method is re-used in other AdapterService*Test doEnable( TestLooper looper, ProfileService gattService, MockAdapterService adapter, Context ctx, boolean onlyGatt, List<ProfileService> services, AdapterNativeInterface nativeInterface)465 static void doEnable( 466 TestLooper looper, 467 ProfileService gattService, 468 MockAdapterService adapter, 469 Context ctx, 470 boolean onlyGatt, 471 List<ProfileService> services, 472 AdapterNativeInterface nativeInterface) { 473 Log.e(TAG, "doEnable() start"); 474 475 IBluetoothCallback callback = mock(IBluetoothCallback.class); 476 Binder binder = mock(Binder.class); 477 doReturn(binder).when(callback).asBinder(); 478 adapter.registerRemoteCallback(callback); 479 480 assertThat(adapter.getState()).isEqualTo(STATE_OFF); 481 482 offToBleOn(looper, gattService, adapter, ctx, callback, nativeInterface); 483 484 adapter.startBrEdr(); 485 TestUtils.syncHandler(looper, AdapterState.USER_TURN_ON); 486 verifyStateChange(callback, STATE_BLE_ON, STATE_TURNING_ON); 487 488 if (!onlyGatt) { 489 // Start Mock PBAP and PAN services 490 assertThat(adapter.mSetProfileServiceStateCounter).isEqualTo(2); 491 492 for (ProfileService service : services) { 493 adapter.addProfile(service); 494 TestUtils.syncHandler(looper, MESSAGE_PROFILE_SERVICE_REGISTERED); 495 } 496 // Keep in 2 separate loop to first add the services and then eventually trigger the 497 // ON transition during the callback 498 for (ProfileService service : services) { 499 adapter.onProfileServiceStateChanged(service, STATE_ON); 500 TestUtils.syncHandler(looper, MESSAGE_PROFILE_SERVICE_STATE_CHANGED); 501 } 502 } 503 TestUtils.syncHandler(looper, AdapterState.BREDR_STARTED); 504 verifyStateChange(callback, STATE_TURNING_ON, STATE_ON); 505 506 assertThat(adapter.getState()).isEqualTo(STATE_ON); 507 adapter.unregisterRemoteCallback(callback); 508 Log.e(TAG, "doEnable() complete success"); 509 } 510 doDisable(boolean onlyGatt)511 void doDisable(boolean onlyGatt) { 512 doDisable( 513 mLooper, 514 mAdapterService, 515 mMockContext, 516 onlyGatt, 517 List.of(mMockService, mMockService2), 518 mNativeInterface); 519 } 520 doDisable( TestLooper looper, MockAdapterService adapter, Context ctx, boolean onlyGatt, List<ProfileService> services, AdapterNativeInterface nativeInterface)521 private static void doDisable( 522 TestLooper looper, 523 MockAdapterService adapter, 524 Context ctx, 525 boolean onlyGatt, 526 List<ProfileService> services, 527 AdapterNativeInterface nativeInterface) { 528 Log.e(TAG, "doDisable() start"); 529 IBluetoothCallback callback = mock(IBluetoothCallback.class); 530 Binder binder = mock(Binder.class); 531 doReturn(binder).when(callback).asBinder(); 532 adapter.registerRemoteCallback(callback); 533 534 assertThat(adapter.getState()).isEqualTo(STATE_ON); 535 536 onToBleOn(looper, adapter, ctx, callback, onlyGatt, services); 537 538 adapter.stopBle(); 539 TestUtils.syncHandler(looper, AdapterState.BLE_TURN_OFF); 540 verifyStateChange(callback, STATE_BLE_ON, STATE_BLE_TURNING_OFF); 541 542 TestUtils.syncHandler(looper, MESSAGE_PROFILE_SERVICE_STATE_CHANGED); 543 TestUtils.syncHandler(looper, MESSAGE_PROFILE_SERVICE_UNREGISTERED); 544 545 verify(nativeInterface).disable(); 546 adapter.stateChangeCallback(AbstractionLayer.BT_STATE_OFF); 547 TestUtils.syncHandler(looper, AdapterState.BLE_STOPPED); 548 if (Flags.explicitKillFromSystemServer()) { 549 // When reaching the OFF state, the cleanup is called that will destroy the state 550 // machine of the adapterService. Destroying state machine send a -1 event on the 551 // handler 552 TestUtils.syncHandler(looper, -1); 553 } 554 verifyStateChange(callback, STATE_BLE_TURNING_OFF, STATE_OFF); 555 556 assertThat(adapter.getState()).isEqualTo(STATE_OFF); 557 adapter.unregisterRemoteCallback(callback); 558 Log.e(TAG, "doDisable() complete success"); 559 } 560 561 /** Test: Turn Bluetooth on. Check whether the AdapterService gets started. */ 562 @Test testEnable()563 public void testEnable() { 564 doEnable(false); 565 } 566 567 @Test enable_isCorrectScanMode()568 public void enable_isCorrectScanMode() { 569 doEnable(false); 570 571 final int expectedScanMode = BluetoothAdapter.SCAN_MODE_CONNECTABLE; 572 573 int type = AbstractionLayer.BT_PROPERTY_ADAPTER_SCAN_MODE; 574 byte[] val = Utils.intToByteArray(AdapterService.convertScanModeToHal(expectedScanMode)); 575 576 verify(mNativeInterface).setAdapterProperty(eq(type), eq(val)); 577 // Intercept native call and simulate its callback 578 mAdapterService.mAdapterProperties.adapterPropertyChangedCallback( 579 new int[] {type}, new byte[][] {val}); 580 assertThat(mAdapterService.getScanMode()).isEqualTo(BluetoothAdapter.SCAN_MODE_CONNECTABLE); 581 } 582 583 /** Test: Turn Bluetooth on/off. Check whether the AdapterService gets started and stopped. */ 584 @Test testEnableDisable()585 public void testEnableDisable() { 586 doEnable(false); 587 doDisable(false); 588 } 589 590 /** 591 * Test: Turn Bluetooth on/off with only GATT supported. Check whether the AdapterService gets 592 * started and stopped. 593 */ 594 @Test testEnableDisableOnlyGatt()595 public void testEnableDisableOnlyGatt() { 596 Context mockContext = mock(Context.class); 597 Resources mockResources = mock(Resources.class); 598 599 when(mockContext.getApplicationInfo()).thenReturn(mMockApplicationInfo); 600 when(mockContext.getContentResolver()).thenReturn(mMockContentResolver); 601 when(mockContext.getApplicationContext()).thenReturn(mockContext); 602 when(mockContext.getResources()).thenReturn(mockResources); 603 when(mockContext.getUserId()).thenReturn(Process.BLUETOOTH_UID); 604 when(mockContext.getPackageManager()).thenReturn(mMockPackageManager); 605 606 // Config is set to PBAP, PAN and GATT by default. Turn off PAN and PBAP. 607 Config.setProfileEnabled(BluetoothProfile.PAN, false); 608 Config.setProfileEnabled(BluetoothProfile.PBAP, false); 609 610 Config.init(mockContext); 611 doEnable(true); 612 doDisable(true); 613 } 614 615 /** Test: Don't start GATT Check whether the AdapterService quits gracefully */ 616 @Test testGattStartTimeout()617 public void testGattStartTimeout() { 618 assertThat(mAdapterService.getState()).isEqualTo(STATE_OFF); 619 620 mAdapterService.enable(false); 621 if (Flags.fastBindToApp()) { 622 syncHandler(0); // when fastBindToApp is enable init need to be run 623 } 624 syncHandler(AdapterState.BLE_TURN_ON); 625 verifyStateChange(STATE_OFF, STATE_BLE_TURNING_ON); 626 assertThat(mAdapterService.getBluetoothGatt()).isNotNull(); 627 syncHandler(MESSAGE_PROFILE_SERVICE_REGISTERED); 628 629 // Fetch next message and never process it to simulate a timeout. 630 dropNextMessage(MESSAGE_PROFILE_SERVICE_STATE_CHANGED); 631 632 mLooper.moveTimeForward(120_000); // Skip time so the timeout fires 633 syncHandler(AdapterState.BLE_START_TIMEOUT); 634 assertThat(mAdapterService.getBluetoothGatt()).isNull(); 635 636 syncHandler(AdapterState.BLE_STOPPED); 637 if (Flags.explicitKillFromSystemServer()) { 638 // When reaching the OFF state, the cleanup is called that will destroy the state 639 // machine of the adapterService. Destroying state machine send a -1 event on the 640 // handler 641 syncHandler(-1); 642 } 643 syncHandler(MESSAGE_PROFILE_SERVICE_STATE_CHANGED); 644 syncHandler(MESSAGE_PROFILE_SERVICE_UNREGISTERED); 645 646 verifyStateChange(STATE_BLE_TURNING_OFF, STATE_OFF); 647 assertThat(mAdapterService.getState()).isEqualTo(STATE_OFF); 648 } 649 650 /** Test: Don't stop GATT Check whether the AdapterService quits gracefully */ 651 @Test testGattStopTimeout()652 public void testGattStopTimeout() { 653 doEnable(false); 654 655 onToBleOn( 656 mLooper, 657 mAdapterService, 658 mMockContext, 659 mIBluetoothCallback, 660 false, 661 List.of(mMockService, mMockService2)); 662 663 mAdapterService.stopBle(); 664 syncHandler(AdapterState.BLE_TURN_OFF); 665 verifyStateChange(STATE_BLE_ON, STATE_BLE_TURNING_OFF, CONTEXT_SWITCH_MS); 666 assertThat(mAdapterService.getBluetoothGatt()).isNull(); 667 668 // Fetch Gatt message and never process it to simulate a timeout. 669 dropNextMessage(MESSAGE_PROFILE_SERVICE_STATE_CHANGED); 670 dropNextMessage(MESSAGE_PROFILE_SERVICE_UNREGISTERED); 671 672 mLooper.moveTimeForward(120_000); // Skip time so the timeout fires 673 syncHandler(AdapterState.BLE_STOP_TIMEOUT); 674 if (Flags.explicitKillFromSystemServer()) { 675 // When reaching the OFF state, the cleanup is called that will destroy the state 676 // machine of the adapterService. Destroying state machine send a -1 event on the 677 // handler 678 syncHandler(-1); 679 } 680 verifyStateChange(STATE_BLE_TURNING_OFF, STATE_OFF); 681 682 assertThat(mAdapterService.getState()).isEqualTo(STATE_OFF); 683 } 684 685 @Test 686 @DisableFlags(Flags.FLAG_SCAN_MANAGER_REFACTOR) startBleOnly_whenScanManagerRefactorFlagIsOff_onlyStartGattProfile()687 public void startBleOnly_whenScanManagerRefactorFlagIsOff_onlyStartGattProfile() { 688 mAdapterService.bringUpBle(); 689 690 assertThat(mAdapterService.getBluetoothGatt()).isNotNull(); 691 assertThat(mAdapterService.getBluetoothScan()).isNull(); 692 693 dropNextMessage(MESSAGE_PROFILE_SERVICE_REGISTERED); 694 dropNextMessage(MESSAGE_PROFILE_SERVICE_STATE_CHANGED); 695 } 696 697 @Test 698 @EnableFlags(Flags.FLAG_SCAN_MANAGER_REFACTOR) startBleOnly_whenScanManagerRefactorFlagIsOn_onlyStartScanController()699 public void startBleOnly_whenScanManagerRefactorFlagIsOn_onlyStartScanController() { 700 mAdapterService.bringUpBle(); 701 702 assertThat(mAdapterService.getBluetoothGatt()).isNull(); 703 assertThat(mAdapterService.getBluetoothScan()).isNotNull(); 704 } 705 706 @Test 707 @EnableFlags(Flags.FLAG_SCAN_MANAGER_REFACTOR) startBleOnly_whenScanManagerRefactorFlagIsOn_startAndStopScanController()708 public void startBleOnly_whenScanManagerRefactorFlagIsOn_startAndStopScanController() { 709 assertThat(mAdapterService.getBluetoothScan()).isNull(); 710 assertThat(mAdapterService.getBluetoothGatt()).isNull(); 711 712 IBluetoothCallback callback = mock(IBluetoothCallback.class); 713 Binder binder = mock(Binder.class); 714 doReturn(binder).when(callback).asBinder(); 715 mAdapterService.registerRemoteCallback(callback); 716 717 offToBleOn( 718 mLooper, 719 mMockGattService, 720 mAdapterService, 721 mMockContext, 722 mIBluetoothCallback, 723 mNativeInterface); 724 725 assertThat(mAdapterService.getBluetoothScan()).isNotNull(); 726 assertThat(mAdapterService.getBluetoothGatt()).isNull(); 727 728 mAdapterService.stopBle(); 729 syncHandler(AdapterState.BLE_TURN_OFF); 730 verifyStateChange(callback, STATE_BLE_ON, STATE_BLE_TURNING_OFF); 731 732 verify(mNativeInterface).disable(); 733 mAdapterService.stateChangeCallback(AbstractionLayer.BT_STATE_OFF); 734 syncHandler(AdapterState.BLE_STOPPED); 735 if (Flags.explicitKillFromSystemServer()) { 736 // When reaching the OFF state, the cleanup is called that will destroy the state 737 // machine of the adapterService. Destroying state machine send a -1 event on the 738 // handler 739 syncHandler(-1); 740 } 741 verifyStateChange(callback, STATE_BLE_TURNING_OFF, STATE_OFF); 742 743 assertThat(mAdapterService.getState()).isEqualTo(STATE_OFF); 744 mAdapterService.unregisterRemoteCallback(callback); 745 746 assertThat(mAdapterService.getBluetoothScan()).isNull(); 747 assertThat(mAdapterService.getBluetoothGatt()).isNull(); 748 } 749 750 @Test 751 @EnableFlags(Flags.FLAG_SCAN_MANAGER_REFACTOR) startBrDr_whenScanManagerRefactorFlagIsOn_startAndStopScanController()752 public void startBrDr_whenScanManagerRefactorFlagIsOn_startAndStopScanController() { 753 assertThat(mAdapterService.getBluetoothScan()).isNull(); 754 assertThat(mAdapterService.getBluetoothGatt()).isNull(); 755 756 IBluetoothCallback callback = mock(IBluetoothCallback.class); 757 Binder binder = mock(Binder.class); 758 doReturn(binder).when(callback).asBinder(); 759 mAdapterService.registerRemoteCallback(callback); 760 761 assertThat(mAdapterService.getState()).isEqualTo(STATE_OFF); 762 763 offToBleOn( 764 mLooper, 765 mMockGattService, 766 mAdapterService, 767 mMockContext, 768 mIBluetoothCallback, 769 mNativeInterface); 770 771 assertThat(mAdapterService.getBluetoothScan()).isNotNull(); 772 assertThat(mAdapterService.getBluetoothGatt()).isNull(); 773 774 mAdapterService.startBrEdr(); 775 TestUtils.syncHandler(mLooper, AdapterState.USER_TURN_ON); 776 verifyStateChange(callback, STATE_BLE_ON, STATE_TURNING_ON); 777 778 // Start Mock PBAP, PAN, and GATT services 779 assertThat(mAdapterService.mSetProfileServiceStateCounter).isEqualTo(3); 780 List<ProfileService> services = List.of(mMockService, mMockService2, mMockGattService); 781 782 for (ProfileService service : services) { 783 mAdapterService.addProfile(service); 784 TestUtils.syncHandler(mLooper, MESSAGE_PROFILE_SERVICE_REGISTERED); 785 } 786 787 for (ProfileService service : services) { 788 mAdapterService.onProfileServiceStateChanged(service, STATE_ON); 789 TestUtils.syncHandler(mLooper, MESSAGE_PROFILE_SERVICE_STATE_CHANGED); 790 } 791 792 TestUtils.syncHandler(mLooper, AdapterState.BREDR_STARTED); 793 verifyStateChange(callback, STATE_TURNING_ON, STATE_ON); 794 795 assertThat(mAdapterService.getState()).isEqualTo(STATE_ON); 796 797 mAdapterService.disable(); 798 TestUtils.syncHandler(mLooper, AdapterState.USER_TURN_OFF); 799 verifyStateChange(callback, STATE_ON, STATE_TURNING_OFF); 800 801 // Stop PBAP, PAN, and GATT services 802 assertThat(mAdapterService.mSetProfileServiceStateCounter).isEqualTo(6); 803 804 for (ProfileService service : services) { 805 mAdapterService.onProfileServiceStateChanged(service, STATE_OFF); 806 TestUtils.syncHandler(mLooper, MESSAGE_PROFILE_SERVICE_STATE_CHANGED); 807 } 808 809 TestUtils.syncHandler(mLooper, AdapterState.BREDR_STOPPED); 810 verifyStateChange(callback, STATE_TURNING_OFF, STATE_BLE_ON); 811 812 assertThat(mAdapterService.getState()).isEqualTo(STATE_BLE_ON); 813 814 mAdapterService.unregisterRemoteCallback(callback); 815 } 816 817 /** Test: Don't start a classic profile Check whether the AdapterService quits gracefully */ 818 @Test testProfileStartTimeout()819 public void testProfileStartTimeout() { 820 assertThat(mAdapterService.getState()).isEqualTo(STATE_OFF); 821 822 offToBleOn( 823 mLooper, 824 mMockGattService, 825 mAdapterService, 826 mMockContext, 827 mIBluetoothCallback, 828 mNativeInterface); 829 830 mAdapterService.startBrEdr(); 831 syncHandler(AdapterState.USER_TURN_ON); 832 verifyStateChange(STATE_BLE_ON, STATE_TURNING_ON); 833 assertThat(mAdapterService.mSetProfileServiceStateCounter).isEqualTo(2); 834 835 mAdapterService.addProfile(mMockService); 836 syncHandler(MESSAGE_PROFILE_SERVICE_REGISTERED); 837 mAdapterService.addProfile(mMockService2); 838 syncHandler(MESSAGE_PROFILE_SERVICE_REGISTERED); 839 mAdapterService.onProfileServiceStateChanged(mMockService, STATE_ON); 840 syncHandler(MESSAGE_PROFILE_SERVICE_STATE_CHANGED); 841 842 // Skip onProfileServiceStateChanged for mMockService2 to be in the test situation 843 844 mLooper.moveTimeForward(120_000); // Skip time so the timeout fires 845 syncHandler(AdapterState.BREDR_START_TIMEOUT); 846 847 verifyStateChange(STATE_TURNING_ON, STATE_TURNING_OFF); 848 assertThat(mAdapterService.mSetProfileServiceStateCounter).isEqualTo(4); 849 850 mAdapterService.onProfileServiceStateChanged(mMockService, STATE_OFF); 851 syncHandler(MESSAGE_PROFILE_SERVICE_STATE_CHANGED); 852 syncHandler(AdapterState.BREDR_STOPPED); 853 verifyStateChange(STATE_TURNING_OFF, STATE_BLE_ON); 854 855 // Ensure GATT is still running 856 assertThat(mAdapterService.getBluetoothGatt()).isNotNull(); 857 } 858 859 /** Test: Don't stop a classic profile Check whether the AdapterService quits gracefully */ 860 @Test testProfileStopTimeout()861 public void testProfileStopTimeout() { 862 doEnable(false); 863 864 mAdapterService.disable(); 865 syncHandler(AdapterState.USER_TURN_OFF); 866 verifyStateChange(STATE_ON, STATE_TURNING_OFF); 867 assertThat(mAdapterService.mSetProfileServiceStateCounter).isEqualTo(4); 868 869 mAdapterService.onProfileServiceStateChanged(mMockService, STATE_OFF); 870 syncHandler(MESSAGE_PROFILE_SERVICE_STATE_CHANGED); 871 872 // Skip onProfileServiceStateChanged for mMockService2 to be in the test situation 873 874 mLooper.moveTimeForward(120_000); // Skip time so the timeout fires 875 syncHandler(AdapterState.BREDR_STOP_TIMEOUT); 876 verifyStateChange(STATE_TURNING_OFF, STATE_BLE_TURNING_OFF); 877 878 syncHandler(MESSAGE_PROFILE_SERVICE_STATE_CHANGED); 879 syncHandler(MESSAGE_PROFILE_SERVICE_UNREGISTERED); 880 881 // TODO(b/280518177): The only timeout to fire here should be the BREDR 882 mLooper.moveTimeForward(120_000); // Skip time so the timeout fires 883 syncHandler(AdapterState.BLE_STOP_TIMEOUT); 884 if (Flags.explicitKillFromSystemServer()) { 885 // When reaching the OFF state, the cleanup is called that will destroy the state 886 // machine of the adapterService. Destroying state machine send a -1 event on the 887 // handler 888 syncHandler(-1); 889 } 890 verifyStateChange(STATE_BLE_TURNING_OFF, STATE_OFF); 891 892 assertThat(mAdapterService.getState()).isEqualTo(STATE_OFF); 893 } 894 895 /** Test: Toggle snoop logging setting Check whether the AdapterService restarts fully */ 896 @Test testSnoopLoggingChange()897 public void testSnoopLoggingChange() { 898 BluetoothProperties.snoop_log_mode_values snoopSetting = 899 BluetoothProperties.snoop_log_mode() 900 .orElse(BluetoothProperties.snoop_log_mode_values.EMPTY); 901 BluetoothProperties.snoop_log_mode(BluetoothProperties.snoop_log_mode_values.DISABLED); 902 doEnable(false); 903 904 assertThat( 905 BluetoothProperties.snoop_log_mode() 906 .orElse(BluetoothProperties.snoop_log_mode_values.EMPTY)) 907 .isNotEqualTo(BluetoothProperties.snoop_log_mode_values.FULL); 908 909 BluetoothProperties.snoop_log_mode(BluetoothProperties.snoop_log_mode_values.FULL); 910 911 onToBleOn( 912 mLooper, 913 mAdapterService, 914 mMockContext, 915 mIBluetoothCallback, 916 false, 917 List.of(mMockService, mMockService2)); 918 919 // Do not call stopBle(). The Adapter should turn itself off. 920 syncHandler(AdapterState.BLE_TURN_OFF); 921 verifyStateChange(STATE_BLE_ON, STATE_BLE_TURNING_OFF, CONTEXT_SWITCH_MS); 922 923 syncHandler(MESSAGE_PROFILE_SERVICE_STATE_CHANGED); // stop GATT 924 syncHandler(MESSAGE_PROFILE_SERVICE_UNREGISTERED); 925 926 verify(mNativeInterface).disable(); 927 928 mAdapterService.stateChangeCallback(AbstractionLayer.BT_STATE_OFF); 929 syncHandler(AdapterState.BLE_STOPPED); 930 if (Flags.explicitKillFromSystemServer()) { 931 // When reaching the OFF state, the cleanup is called that will destroy the state 932 // machine of the adapterService. Destroying state machine send a -1 event on the 933 // handler 934 syncHandler(-1); 935 } 936 937 verifyStateChange(STATE_BLE_TURNING_OFF, STATE_OFF); 938 assertThat(mAdapterService.getState()).isEqualTo(STATE_OFF); 939 940 // Restore earlier setting 941 BluetoothProperties.snoop_log_mode(snoopSetting); 942 } 943 944 /** 945 * Test: Obfuscate a null Bluetooth Check if returned value from {@link 946 * AdapterService#obfuscateAddress(BluetoothDevice)} is an empty array when device address is 947 * null 948 */ 949 @Test testObfuscateBluetoothAddress_NullAddress()950 public void testObfuscateBluetoothAddress_NullAddress() { 951 assertThat(mAdapterService.obfuscateAddress(null)).isEmpty(); 952 } 953 954 @Test testAddressConsolidation()955 public void testAddressConsolidation() { 956 // Create device properties 957 RemoteDevices remoteDevices = mAdapterService.getRemoteDevices(); 958 remoteDevices.addDeviceProperties(Utils.getBytesFromAddress((TEST_BT_ADDR_1))); 959 String identityAddress = mAdapterService.getIdentityAddress(TEST_BT_ADDR_1); 960 if (!Flags.identityAddressNullIfUnknown()) { 961 assertThat(identityAddress).isEqualTo(TEST_BT_ADDR_1); 962 } 963 964 // Trigger address consolidate callback 965 remoteDevices.addressConsolidateCallback( 966 Utils.getBytesFromAddress(TEST_BT_ADDR_1), 967 Utils.getBytesFromAddress(TEST_BT_ADDR_2)); 968 969 // Verify we can get correct identity address 970 identityAddress = mAdapterService.getIdentityAddress(TEST_BT_ADDR_1); 971 assertThat(identityAddress).isEqualTo(TEST_BT_ADDR_2); 972 } 973 974 @Test 975 @EnableFlags(Flags.FLAG_IDENTITY_ADDRESS_NULL_IF_UNKNOWN) testIdentityAddressNullIfUnknown()976 public void testIdentityAddressNullIfUnknown() { 977 BluetoothDevice device = TestUtils.getTestDevice(BluetoothAdapter.getDefaultAdapter(), 0); 978 979 assertThat(mAdapterService.getByteIdentityAddress(device)).isNull(); 980 assertThat(mAdapterService.getIdentityAddress(device.getAddress())).isNull(); 981 } 982 getMetricsSalt(Map<String, Map<String, String>> adapterConfig)983 public static byte[] getMetricsSalt(Map<String, Map<String, String>> adapterConfig) { 984 Map<String, String> metricsSection = adapterConfig.get("Metrics"); 985 if (metricsSection == null) { 986 Log.e(TAG, "Metrics section is null: " + adapterConfig.toString()); 987 return null; 988 } 989 String saltString = metricsSection.get("Salt256Bit"); 990 if (saltString == null) { 991 Log.e(TAG, "Salt256Bit is null: " + metricsSection.toString()); 992 return null; 993 } 994 byte[] metricsSalt = HexEncoding.decode(saltString, false /* allowSingleChar */); 995 if (metricsSalt.length != 32) { 996 Log.e(TAG, "Salt length is not 32 bit, but is " + metricsSalt.length); 997 return null; 998 } 999 return metricsSalt; 1000 } 1001 obfuscateInJava(byte[] key, BluetoothDevice device)1002 public static byte[] obfuscateInJava(byte[] key, BluetoothDevice device) { 1003 String algorithm = "HmacSHA256"; 1004 try { 1005 Mac hmac256 = Mac.getInstance(algorithm); 1006 hmac256.init(new SecretKeySpec(key, algorithm)); 1007 return hmac256.doFinal(Utils.getByteAddress(device)); 1008 } catch (NoSuchAlgorithmException | IllegalStateException | InvalidKeyException exp) { 1009 exp.printStackTrace(); 1010 return null; 1011 } 1012 } 1013 isByteArrayAllZero(byte[] byteArray)1014 public static boolean isByteArrayAllZero(byte[] byteArray) { 1015 for (byte i : byteArray) { 1016 if (i != 0) { 1017 return false; 1018 } 1019 } 1020 return true; 1021 } 1022 1023 /** 1024 * Test: Get id for null address Check if returned value from {@link 1025 * AdapterService#getMetricId(BluetoothDevice)} is 0 when device address is null 1026 */ 1027 @Test testGetMetricId_NullAddress()1028 public void testGetMetricId_NullAddress() { 1029 assertThat(mAdapterService.getMetricId(null)).isEqualTo(0); 1030 } 1031 1032 @Test testDump_doesNotCrash()1033 public void testDump_doesNotCrash() { 1034 FileDescriptor fd = new FileDescriptor(); 1035 PrintWriter writer = mock(PrintWriter.class); 1036 1037 mAdapterService.dump(fd, writer, new String[] {}); 1038 mAdapterService.dump(fd, writer, new String[] {"set-test-mode", "enabled"}); 1039 doReturn(new byte[0]).when(mNativeInterface).dumpMetrics(); 1040 mAdapterService.dump(fd, writer, new String[] {"--proto-bin"}); 1041 mAdapterService.dump(fd, writer, new String[] {"random", "arguments"}); 1042 } 1043 } 1044