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