Loading android/app/src/com/android/bluetooth/btservice/AdapterProperties.java +0 −7 Original line number Diff line number Diff line Loading @@ -744,10 +744,6 @@ class AdapterProperties { intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); mService.sendBroadcast(intent, AdapterService.BLUETOOTH_PERM); debugLog("Scan Mode:" + mScanMode); if (mBluetoothDisabling) { mBluetoothDisabling = false; mService.startBluetoothDisable(); } break; case AbstractionLayer.BT_PROPERTY_UUIDS: mUuids = Utils.byteArrayToUuid(val); Loading Loading @@ -842,8 +838,6 @@ class AdapterProperties { } } private boolean mBluetoothDisabling = false; void onBleDisable() { // Sequence BLE_ON to STATE_OFF - that is _complete_ OFF state. // When BT disable is invoked, set the scan_mode to NONE Loading @@ -862,7 +856,6 @@ class AdapterProperties { //Set flag to indicate we are disabling. When property change of scan mode done //continue with disable sequence debugLog("onBluetoothDisable()"); mBluetoothDisabling = true; if (getState() == BluetoothAdapter.STATE_TURNING_OFF) { // Turn off any Device Search/Inquiry mService.cancelDiscovery(); Loading android/app/src/com/android/bluetooth/btservice/AdapterService.java +58 −20 Original line number Diff line number Diff line Loading @@ -270,9 +270,11 @@ public class AdapterService extends Service { } mRunningProfiles.add(profile); if (GattService.class.getSimpleName().equals(profile.getName())) { mAdapterStateMachine.sendMessage(AdapterState.BLE_STARTED); enableNativeWithGuestFlag(); } else if (mRegisteredProfiles.size() == Config.getSupportedProfiles().length && mRegisteredProfiles.size() == mRunningProfiles.size()) { updateUuids(); setBluetoothClassFromConfig(); mAdapterStateMachine.sendMessage(AdapterState.BREDR_STARTED); } break; Loading @@ -291,6 +293,7 @@ public class AdapterService extends Service { .equals(mRunningProfiles.get(0).getName())))) { mAdapterStateMachine.sendMessage(AdapterState.BREDR_STOPPED); } else if (mRunningProfiles.size() == 0) { disableNative(); mAdapterStateMachine.sendMessage(AdapterState.BLE_STOPPED); } break; Loading Loading @@ -369,8 +372,8 @@ public class AdapterService extends Service { mRemoteDevices.init(); mBinder = new AdapterServiceBinder(this); mAdapterProperties = new AdapterProperties(this); mAdapterStateMachine = AdapterState.make(this, mAdapterProperties); mJniCallbacks = new JniCallbacks(mAdapterStateMachine, mAdapterProperties); mAdapterStateMachine = AdapterState.make(this); mJniCallbacks = new JniCallbacks(this, mAdapterProperties); initNative(); mNativeAvailable = true; mCallbacks = new RemoteCallbackList<IBluetoothCallback>(); Loading Loading @@ -473,7 +476,7 @@ public class AdapterService extends Service { } }; void bleOnProcessStart() { void bringUpBle() { debugLog("bleOnProcessStart()"); if (getResources().getBoolean( Loading Loading @@ -508,6 +511,20 @@ public class AdapterService extends Service { setProfileServiceState(GattService.class, BluetoothAdapter.STATE_ON); } void bringDownBle() { stopGattProfileService(); } void stateChangeCallback(int status) { if (status == AbstractionLayer.BT_STATE_OFF) { debugLog("stateChangeCallback: disableNative() completed"); } else if (status == AbstractionLayer.BT_STATE_ON) { mAdapterStateMachine.sendMessage(AdapterState.BLE_STARTED); } else { Log.e(TAG, "Incorrect status " + status + " in stateChangeCallback"); } } /** * Sets the Bluetooth CoD value of the local adapter if there exists a config value for it. */ Loading @@ -534,31 +551,42 @@ public class AdapterService extends Service { return result; } void startCoreServices() { void startProfileServices() { debugLog("startCoreServices()"); Class[] supportedProfileServices = Config.getSupportedProfiles(); if (supportedProfileServices.length == 1 && GattService.class.getSimpleName() .equals(supportedProfileServices[0].getSimpleName())) { updateUuids(); setBluetoothClassFromConfig(); mAdapterStateMachine.sendMessage(AdapterState.BREDR_STARTED); } else { setAllProfileServiceStates(supportedProfileServices, BluetoothAdapter.STATE_ON); } void startBluetoothDisable() { mAdapterStateMachine.sendMessage(AdapterState.BEGIN_DISABLE); } void stopProfileServices() { mAdapterProperties.onBluetoothDisable(); Class[] supportedProfileServices = Config.getSupportedProfiles(); if (mRunningProfiles.size() == 0) { if (supportedProfileServices.length == 1 && (mRunningProfiles.size() == 1 && GattService.class.getSimpleName().equals(mRunningProfiles.get(0).getName()))) { debugLog("stopProfileServices() - No profiles services to stop or already stopped."); return; } mAdapterStateMachine.sendMessage(AdapterState.BREDR_STOPPED); } else { setAllProfileServiceStates(supportedProfileServices, BluetoothAdapter.STATE_OFF); } } boolean stopGattProfileService() { private void stopGattProfileService() { mAdapterProperties.onBleDisable(); if (mRunningProfiles.size() == 0) { debugLog("stopGattProfileService() - No profiles services to stop."); mAdapterStateMachine.sendMessage(AdapterState.BLE_STOPPED); } setProfileServiceState(GattService.class, BluetoothAdapter.STATE_OFF); return true; } void updateAdapterState(int prevState, int newState) { mAdapterProperties.setState(newState); if (mCallbacks != null) { int n = mCallbacks.beginBroadcast(); debugLog("updateAdapterState() - Broadcasting state " + BluetoothAdapter.nameForState( Loading Loading @@ -1576,7 +1604,7 @@ public class AdapterService extends Service { enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); debugLog("disable() called with mRunningProfiles.size() = " + mRunningProfiles.size()); mAdapterStateMachine.sendMessage(AdapterState.BLE_TURN_OFF); mAdapterStateMachine.sendMessage(AdapterState.USER_TURN_OFF); return true; } Loading Loading @@ -2185,12 +2213,12 @@ public class AdapterService extends Service { return mAdapterProperties.getTotalNumOfTrackableAdvertisements(); } public void onLeServiceUp() { void onLeServiceUp() { mAdapterStateMachine.sendMessage(AdapterState.USER_TURN_ON); } public void onBrEdrDown() { mAdapterStateMachine.sendMessage(AdapterState.USER_TURN_OFF); void onBrEdrDown() { mAdapterStateMachine.sendMessage(AdapterState.BLE_TURN_OFF); } private static int convertScanModeToHal(int mode) { Loading Loading @@ -2384,6 +2412,9 @@ public class AdapterService extends Service { + device.getName()); } writer.println(); mAdapterStateMachine.dump(fd, writer, args); StringBuilder sb = new StringBuilder(); for (ProfileService profile : mRegisteredProfiles) { profile.dump(sb); Loading Loading @@ -2447,7 +2478,14 @@ public class AdapterService extends Service { } }; private static native void classInitNative(); private void enableNativeWithGuestFlag() { boolean isGuest = UserManager.get(this).isGuestUser(); if (!enableNative(isGuest)) { Log.e(TAG, "enableNative() returned false"); } } static native void classInitNative(); native boolean initNative(); Loading android/app/src/com/android/bluetooth/btservice/AdapterState.java +227 −402 File changed.Preview size limit exceeded, changes collapsed. Show changes android/app/src/com/android/bluetooth/btservice/JniCallbacks.java +5 −5 Original line number Diff line number Diff line Loading @@ -20,11 +20,11 @@ final class JniCallbacks { private RemoteDevices mRemoteDevices; private AdapterProperties mAdapterProperties; private AdapterState mAdapterStateMachine; private AdapterService mAdapterService; private BondStateMachine mBondStateMachine; JniCallbacks(AdapterState adapterStateMachine, AdapterProperties adapterProperties) { mAdapterStateMachine = adapterStateMachine; JniCallbacks(AdapterService adapterService, AdapterProperties adapterProperties) { mAdapterService = adapterService; mAdapterProperties = adapterProperties; } Loading @@ -36,7 +36,7 @@ final class JniCallbacks { void cleanup() { mRemoteDevices = null; mAdapterProperties = null; mAdapterStateMachine = null; mAdapterService = null; mBondStateMachine = null; } Loading Loading @@ -70,7 +70,7 @@ final class JniCallbacks { } void stateChangeCallback(int status) { mAdapterStateMachine.stateChangeCallback(status); mAdapterService.stateChangeCallback(status); } void discoveryStateChangeCallback(int state) { Loading android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceTest.java +206 −25 Original line number Diff line number Diff line Loading @@ -71,6 +71,10 @@ public class AdapterServiceTest { private static final int ONE_SECOND_MS = 1000; private static final int NATIVE_INIT_MS = 8000; private PowerManager mPowerManager; private PackageManager mMockPackageManager; private MockContentResolver mMockContentResolver; @Before public void setUp() throws PackageManager.NameNotFoundException { if (Looper.myLooper() == null) { Loading @@ -84,10 +88,10 @@ public class AdapterServiceTest { mAdapterService = new AdapterService(); } }); PackageManager mMockPackageManager = mock(PackageManager.class); MockContentResolver mMockContentResolver = new MockContentResolver(mMockContext); mMockPackageManager = mock(PackageManager.class); mMockContentResolver = new MockContentResolver(mMockContext); MockitoAnnotations.initMocks(this); PowerManager powerManager = (PowerManager) InstrumentationRegistry.getTargetContext() mPowerManager = (PowerManager) InstrumentationRegistry.getTargetContext() .getSystemService(Context.POWER_SERVICE); when(mMockContext.getApplicationInfo()).thenReturn(mMockApplicationInfo); Loading @@ -97,7 +101,7 @@ public class AdapterServiceTest { when(mMockContext.getUserId()).thenReturn(Process.BLUETOOTH_UID); when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager); when(mMockContext.getSystemService(Context.USER_SERVICE)).thenReturn(mMockUserManager); when(mMockContext.getSystemService(Context.POWER_SERVICE)).thenReturn(powerManager); when(mMockContext.getSystemService(Context.POWER_SERVICE)).thenReturn(mPowerManager); when(mMockContext.getSystemService(Context.ALARM_SERVICE)).thenReturn(mMockAlarmManager); when(mMockResources.getBoolean(R.bool.profile_supported_gatt)).thenReturn(true); Loading Loading @@ -138,17 +142,19 @@ public class AdapterServiceTest { } } private void doEnable(int invocationNumber) { private void doEnable(int invocationNumber, boolean onlyGatt) { Assert.assertFalse(mAdapterService.isEnabled()); final int startServiceCalls = 2 * (onlyGatt ? 1 : 3); // Start and stop GATT + 2 mAdapterService.enable(); verifyStateChange(BluetoothAdapter.STATE_OFF, BluetoothAdapter.STATE_BLE_TURNING_ON, invocationNumber + 1, CONTEXT_SWITCH_MS); // Start GATT verify(mMockContext, timeout(CONTEXT_SWITCH_MS).times(6 * invocationNumber + 1)).startService(any()); verify(mMockContext, timeout(CONTEXT_SWITCH_MS).times( startServiceCalls * invocationNumber + 1)).startService(any()); mAdapterService.addProfile(mMockGattService); mAdapterService.onProfileServiceStateChanged(mMockGattService, BluetoothAdapter.STATE_ON); Loading @@ -160,13 +166,15 @@ public class AdapterServiceTest { verifyStateChange(BluetoothAdapter.STATE_BLE_ON, BluetoothAdapter.STATE_TURNING_ON, invocationNumber + 1, CONTEXT_SWITCH_MS); if (!onlyGatt) { // Start Mock PBAP and PAN services verify(mMockContext, timeout(ONE_SECOND_MS).times(6 * invocationNumber + 3)).startService( any()); verify(mMockContext, timeout(ONE_SECOND_MS).times( startServiceCalls * invocationNumber + 3)).startService(any()); mAdapterService.addProfile(mMockService); mAdapterService.addProfile(mMockService2); mAdapterService.onProfileServiceStateChanged(mMockService, BluetoothAdapter.STATE_ON); mAdapterService.onProfileServiceStateChanged(mMockService2, BluetoothAdapter.STATE_ON); } verifyStateChange(BluetoothAdapter.STATE_TURNING_ON, BluetoothAdapter.STATE_ON, invocationNumber + 1, CONTEXT_SWITCH_MS); Loading @@ -174,19 +182,23 @@ public class AdapterServiceTest { Assert.assertTrue(mAdapterService.isEnabled()); } private void doDisable(int invocationNumber) { private void doDisable(int invocationNumber, boolean onlyGatt) { Assert.assertTrue(mAdapterService.isEnabled()); final int startServiceCalls = 2 * (onlyGatt ? 1 : 3); // Start and stop GATT + 2 mAdapterService.disable(); verifyStateChange(BluetoothAdapter.STATE_ON, BluetoothAdapter.STATE_TURNING_OFF, invocationNumber + 1, CONTEXT_SWITCH_MS); if (!onlyGatt) { // Stop PBAP and PAN verify(mMockContext, timeout(ONE_SECOND_MS).times(6 * invocationNumber + 5)).startService( any()); verify(mMockContext, timeout(ONE_SECOND_MS).times( startServiceCalls * invocationNumber + 5)).startService(any()); mAdapterService.onProfileServiceStateChanged(mMockService, BluetoothAdapter.STATE_OFF); mAdapterService.onProfileServiceStateChanged(mMockService2, BluetoothAdapter.STATE_OFF); } verifyStateChange(BluetoothAdapter.STATE_TURNING_OFF, BluetoothAdapter.STATE_BLE_ON, invocationNumber + 1, CONTEXT_SWITCH_MS); Loading @@ -197,8 +209,8 @@ public class AdapterServiceTest { invocationNumber + 1, CONTEXT_SWITCH_MS); // Stop GATT verify(mMockContext, timeout(ONE_SECOND_MS).times(6 * invocationNumber + 6)).startService( any()); verify(mMockContext, timeout(ONE_SECOND_MS).times( startServiceCalls * invocationNumber + startServiceCalls)).startService(any()); mAdapterService.onProfileServiceStateChanged(mMockGattService, BluetoothAdapter.STATE_OFF); verifyStateChange(BluetoothAdapter.STATE_BLE_TURNING_OFF, BluetoothAdapter.STATE_OFF, Loading @@ -213,7 +225,7 @@ public class AdapterServiceTest { */ @Test public void testEnable() { doEnable(0); doEnable(0, false); } /** Loading @@ -222,7 +234,176 @@ public class AdapterServiceTest { */ @Test public void testEnableDisable() { doEnable(0); doDisable(0); doEnable(0, false); doDisable(0, false); } /** * Test: Turn Bluetooth on/off with only GATT supported. * Check whether the AdapterService gets started and stopped. */ @Test public void testEnableDisableOnlyGatt() { Context mockContext = mock(Context.class); Resources mockResources = mock(Resources.class); when(mockContext.getApplicationInfo()).thenReturn(mMockApplicationInfo); when(mockContext.getContentResolver()).thenReturn(mMockContentResolver); when(mockContext.getApplicationContext()).thenReturn(mockContext); when(mockContext.getResources()).thenReturn(mockResources); when(mockContext.getUserId()).thenReturn(Process.BLUETOOTH_UID); when(mockContext.getPackageManager()).thenReturn(mMockPackageManager); when(mockContext.getSystemService(Context.USER_SERVICE)).thenReturn(mMockUserManager); when(mockContext.getSystemService(Context.POWER_SERVICE)).thenReturn(mPowerManager); when(mockContext.getSystemService(Context.ALARM_SERVICE)).thenReturn(mMockAlarmManager); when(mockResources.getBoolean(R.bool.profile_supported_gatt)).thenReturn(true); Config.init(mockContext); doEnable(0, true); doDisable(0, true); } /** * Test: Don't start GATT * Check whether the AdapterService quits gracefully */ @Test public void testGattStartTimeout() { Assert.assertFalse(mAdapterService.isEnabled()); mAdapterService.enable(); verifyStateChange(BluetoothAdapter.STATE_OFF, BluetoothAdapter.STATE_BLE_TURNING_ON, 1, CONTEXT_SWITCH_MS); // Start GATT verify(mMockContext, timeout(CONTEXT_SWITCH_MS).times(1)).startService(any()); mAdapterService.addProfile(mMockGattService); verifyStateChange(BluetoothAdapter.STATE_BLE_TURNING_ON, BluetoothAdapter.STATE_BLE_TURNING_OFF, 1, AdapterState.BLE_START_TIMEOUT_DELAY + CONTEXT_SWITCH_MS); // Stop GATT verify(mMockContext, timeout(AdapterState.BLE_STOP_TIMEOUT_DELAY + CONTEXT_SWITCH_MS) .times(2)).startService(any()); verifyStateChange(BluetoothAdapter.STATE_BLE_TURNING_OFF, BluetoothAdapter.STATE_OFF, 1, CONTEXT_SWITCH_MS); Assert.assertFalse(mAdapterService.isEnabled()); } /** * Test: Don't stop GATT * Check whether the AdapterService quits gracefully */ @Test public void testGattStopTimeout() { doEnable(0, false); Assert.assertTrue(mAdapterService.isEnabled()); mAdapterService.disable(); verifyStateChange(BluetoothAdapter.STATE_ON, BluetoothAdapter.STATE_TURNING_OFF, 1, CONTEXT_SWITCH_MS); // Stop PBAP and PAN verify(mMockContext, timeout(ONE_SECOND_MS).times(5)).startService(any()); mAdapterService.onProfileServiceStateChanged(mMockService, BluetoothAdapter.STATE_OFF); mAdapterService.onProfileServiceStateChanged(mMockService2, BluetoothAdapter.STATE_OFF); verifyStateChange(BluetoothAdapter.STATE_TURNING_OFF, BluetoothAdapter.STATE_BLE_ON, 1, CONTEXT_SWITCH_MS); mAdapterService.onBrEdrDown(); verifyStateChange(BluetoothAdapter.STATE_BLE_ON, BluetoothAdapter.STATE_BLE_TURNING_OFF, 1, CONTEXT_SWITCH_MS); // Stop GATT verify(mMockContext, timeout(ONE_SECOND_MS).times(6)).startService(any()); verifyStateChange(BluetoothAdapter.STATE_BLE_TURNING_OFF, BluetoothAdapter.STATE_OFF, 1, AdapterState.BLE_STOP_TIMEOUT_DELAY + CONTEXT_SWITCH_MS); Assert.assertFalse(mAdapterService.isEnabled()); } /** * Test: Don't start a classic profile * Check whether the AdapterService quits gracefully */ @Test public void testProfileStartTimeout() { Assert.assertFalse(mAdapterService.isEnabled()); mAdapterService.enable(); verifyStateChange(BluetoothAdapter.STATE_OFF, BluetoothAdapter.STATE_BLE_TURNING_ON, 1, CONTEXT_SWITCH_MS); // Start GATT verify(mMockContext, timeout(CONTEXT_SWITCH_MS).times(1)).startService(any()); mAdapterService.addProfile(mMockGattService); mAdapterService.onProfileServiceStateChanged(mMockGattService, BluetoothAdapter.STATE_ON); verifyStateChange(BluetoothAdapter.STATE_BLE_TURNING_ON, BluetoothAdapter.STATE_BLE_ON, 1, NATIVE_INIT_MS); mAdapterService.onLeServiceUp(); verifyStateChange(BluetoothAdapter.STATE_BLE_ON, BluetoothAdapter.STATE_TURNING_ON, 1, CONTEXT_SWITCH_MS); // Register Mock PBAP and PAN services, only start one verify(mMockContext, timeout(ONE_SECOND_MS).times(3)).startService(any()); mAdapterService.addProfile(mMockService); mAdapterService.addProfile(mMockService2); mAdapterService.onProfileServiceStateChanged(mMockService, BluetoothAdapter.STATE_ON); verifyStateChange(BluetoothAdapter.STATE_TURNING_ON, BluetoothAdapter.STATE_TURNING_OFF, 1, AdapterState.BREDR_START_TIMEOUT_DELAY + CONTEXT_SWITCH_MS); // Stop PBAP and PAN verify(mMockContext, timeout(ONE_SECOND_MS).times(5)).startService(any()); mAdapterService.onProfileServiceStateChanged(mMockService, BluetoothAdapter.STATE_OFF); verifyStateChange(BluetoothAdapter.STATE_TURNING_OFF, BluetoothAdapter.STATE_BLE_ON, 1, CONTEXT_SWITCH_MS); } /** * Test: Don't stop a classic profile * Check whether the AdapterService quits gracefully */ @Test public void testProfileStopTimeout() { doEnable(0, false); Assert.assertTrue(mAdapterService.isEnabled()); mAdapterService.disable(); verifyStateChange(BluetoothAdapter.STATE_ON, BluetoothAdapter.STATE_TURNING_OFF, 1, CONTEXT_SWITCH_MS); // Stop PBAP and PAN verify(mMockContext, timeout(ONE_SECOND_MS).times(5)).startService(any()); mAdapterService.onProfileServiceStateChanged(mMockService, BluetoothAdapter.STATE_OFF); verifyStateChange(BluetoothAdapter.STATE_TURNING_OFF, BluetoothAdapter.STATE_BLE_TURNING_OFF, 1, AdapterState.BREDR_STOP_TIMEOUT_DELAY + CONTEXT_SWITCH_MS); // Stop GATT verify(mMockContext, timeout(ONE_SECOND_MS).times(6)).startService(any()); mAdapterService.onProfileServiceStateChanged(mMockGattService, BluetoothAdapter.STATE_OFF); verifyStateChange(BluetoothAdapter.STATE_BLE_TURNING_OFF, BluetoothAdapter.STATE_OFF, 1, AdapterState.BLE_STOP_TIMEOUT_DELAY + CONTEXT_SWITCH_MS); Assert.assertFalse(mAdapterService.isEnabled()); } } Loading
android/app/src/com/android/bluetooth/btservice/AdapterProperties.java +0 −7 Original line number Diff line number Diff line Loading @@ -744,10 +744,6 @@ class AdapterProperties { intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); mService.sendBroadcast(intent, AdapterService.BLUETOOTH_PERM); debugLog("Scan Mode:" + mScanMode); if (mBluetoothDisabling) { mBluetoothDisabling = false; mService.startBluetoothDisable(); } break; case AbstractionLayer.BT_PROPERTY_UUIDS: mUuids = Utils.byteArrayToUuid(val); Loading Loading @@ -842,8 +838,6 @@ class AdapterProperties { } } private boolean mBluetoothDisabling = false; void onBleDisable() { // Sequence BLE_ON to STATE_OFF - that is _complete_ OFF state. // When BT disable is invoked, set the scan_mode to NONE Loading @@ -862,7 +856,6 @@ class AdapterProperties { //Set flag to indicate we are disabling. When property change of scan mode done //continue with disable sequence debugLog("onBluetoothDisable()"); mBluetoothDisabling = true; if (getState() == BluetoothAdapter.STATE_TURNING_OFF) { // Turn off any Device Search/Inquiry mService.cancelDiscovery(); Loading
android/app/src/com/android/bluetooth/btservice/AdapterService.java +58 −20 Original line number Diff line number Diff line Loading @@ -270,9 +270,11 @@ public class AdapterService extends Service { } mRunningProfiles.add(profile); if (GattService.class.getSimpleName().equals(profile.getName())) { mAdapterStateMachine.sendMessage(AdapterState.BLE_STARTED); enableNativeWithGuestFlag(); } else if (mRegisteredProfiles.size() == Config.getSupportedProfiles().length && mRegisteredProfiles.size() == mRunningProfiles.size()) { updateUuids(); setBluetoothClassFromConfig(); mAdapterStateMachine.sendMessage(AdapterState.BREDR_STARTED); } break; Loading @@ -291,6 +293,7 @@ public class AdapterService extends Service { .equals(mRunningProfiles.get(0).getName())))) { mAdapterStateMachine.sendMessage(AdapterState.BREDR_STOPPED); } else if (mRunningProfiles.size() == 0) { disableNative(); mAdapterStateMachine.sendMessage(AdapterState.BLE_STOPPED); } break; Loading Loading @@ -369,8 +372,8 @@ public class AdapterService extends Service { mRemoteDevices.init(); mBinder = new AdapterServiceBinder(this); mAdapterProperties = new AdapterProperties(this); mAdapterStateMachine = AdapterState.make(this, mAdapterProperties); mJniCallbacks = new JniCallbacks(mAdapterStateMachine, mAdapterProperties); mAdapterStateMachine = AdapterState.make(this); mJniCallbacks = new JniCallbacks(this, mAdapterProperties); initNative(); mNativeAvailable = true; mCallbacks = new RemoteCallbackList<IBluetoothCallback>(); Loading Loading @@ -473,7 +476,7 @@ public class AdapterService extends Service { } }; void bleOnProcessStart() { void bringUpBle() { debugLog("bleOnProcessStart()"); if (getResources().getBoolean( Loading Loading @@ -508,6 +511,20 @@ public class AdapterService extends Service { setProfileServiceState(GattService.class, BluetoothAdapter.STATE_ON); } void bringDownBle() { stopGattProfileService(); } void stateChangeCallback(int status) { if (status == AbstractionLayer.BT_STATE_OFF) { debugLog("stateChangeCallback: disableNative() completed"); } else if (status == AbstractionLayer.BT_STATE_ON) { mAdapterStateMachine.sendMessage(AdapterState.BLE_STARTED); } else { Log.e(TAG, "Incorrect status " + status + " in stateChangeCallback"); } } /** * Sets the Bluetooth CoD value of the local adapter if there exists a config value for it. */ Loading @@ -534,31 +551,42 @@ public class AdapterService extends Service { return result; } void startCoreServices() { void startProfileServices() { debugLog("startCoreServices()"); Class[] supportedProfileServices = Config.getSupportedProfiles(); if (supportedProfileServices.length == 1 && GattService.class.getSimpleName() .equals(supportedProfileServices[0].getSimpleName())) { updateUuids(); setBluetoothClassFromConfig(); mAdapterStateMachine.sendMessage(AdapterState.BREDR_STARTED); } else { setAllProfileServiceStates(supportedProfileServices, BluetoothAdapter.STATE_ON); } void startBluetoothDisable() { mAdapterStateMachine.sendMessage(AdapterState.BEGIN_DISABLE); } void stopProfileServices() { mAdapterProperties.onBluetoothDisable(); Class[] supportedProfileServices = Config.getSupportedProfiles(); if (mRunningProfiles.size() == 0) { if (supportedProfileServices.length == 1 && (mRunningProfiles.size() == 1 && GattService.class.getSimpleName().equals(mRunningProfiles.get(0).getName()))) { debugLog("stopProfileServices() - No profiles services to stop or already stopped."); return; } mAdapterStateMachine.sendMessage(AdapterState.BREDR_STOPPED); } else { setAllProfileServiceStates(supportedProfileServices, BluetoothAdapter.STATE_OFF); } } boolean stopGattProfileService() { private void stopGattProfileService() { mAdapterProperties.onBleDisable(); if (mRunningProfiles.size() == 0) { debugLog("stopGattProfileService() - No profiles services to stop."); mAdapterStateMachine.sendMessage(AdapterState.BLE_STOPPED); } setProfileServiceState(GattService.class, BluetoothAdapter.STATE_OFF); return true; } void updateAdapterState(int prevState, int newState) { mAdapterProperties.setState(newState); if (mCallbacks != null) { int n = mCallbacks.beginBroadcast(); debugLog("updateAdapterState() - Broadcasting state " + BluetoothAdapter.nameForState( Loading Loading @@ -1576,7 +1604,7 @@ public class AdapterService extends Service { enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); debugLog("disable() called with mRunningProfiles.size() = " + mRunningProfiles.size()); mAdapterStateMachine.sendMessage(AdapterState.BLE_TURN_OFF); mAdapterStateMachine.sendMessage(AdapterState.USER_TURN_OFF); return true; } Loading Loading @@ -2185,12 +2213,12 @@ public class AdapterService extends Service { return mAdapterProperties.getTotalNumOfTrackableAdvertisements(); } public void onLeServiceUp() { void onLeServiceUp() { mAdapterStateMachine.sendMessage(AdapterState.USER_TURN_ON); } public void onBrEdrDown() { mAdapterStateMachine.sendMessage(AdapterState.USER_TURN_OFF); void onBrEdrDown() { mAdapterStateMachine.sendMessage(AdapterState.BLE_TURN_OFF); } private static int convertScanModeToHal(int mode) { Loading Loading @@ -2384,6 +2412,9 @@ public class AdapterService extends Service { + device.getName()); } writer.println(); mAdapterStateMachine.dump(fd, writer, args); StringBuilder sb = new StringBuilder(); for (ProfileService profile : mRegisteredProfiles) { profile.dump(sb); Loading Loading @@ -2447,7 +2478,14 @@ public class AdapterService extends Service { } }; private static native void classInitNative(); private void enableNativeWithGuestFlag() { boolean isGuest = UserManager.get(this).isGuestUser(); if (!enableNative(isGuest)) { Log.e(TAG, "enableNative() returned false"); } } static native void classInitNative(); native boolean initNative(); Loading
android/app/src/com/android/bluetooth/btservice/AdapterState.java +227 −402 File changed.Preview size limit exceeded, changes collapsed. Show changes
android/app/src/com/android/bluetooth/btservice/JniCallbacks.java +5 −5 Original line number Diff line number Diff line Loading @@ -20,11 +20,11 @@ final class JniCallbacks { private RemoteDevices mRemoteDevices; private AdapterProperties mAdapterProperties; private AdapterState mAdapterStateMachine; private AdapterService mAdapterService; private BondStateMachine mBondStateMachine; JniCallbacks(AdapterState adapterStateMachine, AdapterProperties adapterProperties) { mAdapterStateMachine = adapterStateMachine; JniCallbacks(AdapterService adapterService, AdapterProperties adapterProperties) { mAdapterService = adapterService; mAdapterProperties = adapterProperties; } Loading @@ -36,7 +36,7 @@ final class JniCallbacks { void cleanup() { mRemoteDevices = null; mAdapterProperties = null; mAdapterStateMachine = null; mAdapterService = null; mBondStateMachine = null; } Loading Loading @@ -70,7 +70,7 @@ final class JniCallbacks { } void stateChangeCallback(int status) { mAdapterStateMachine.stateChangeCallback(status); mAdapterService.stateChangeCallback(status); } void discoveryStateChangeCallback(int state) { Loading
android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceTest.java +206 −25 Original line number Diff line number Diff line Loading @@ -71,6 +71,10 @@ public class AdapterServiceTest { private static final int ONE_SECOND_MS = 1000; private static final int NATIVE_INIT_MS = 8000; private PowerManager mPowerManager; private PackageManager mMockPackageManager; private MockContentResolver mMockContentResolver; @Before public void setUp() throws PackageManager.NameNotFoundException { if (Looper.myLooper() == null) { Loading @@ -84,10 +88,10 @@ public class AdapterServiceTest { mAdapterService = new AdapterService(); } }); PackageManager mMockPackageManager = mock(PackageManager.class); MockContentResolver mMockContentResolver = new MockContentResolver(mMockContext); mMockPackageManager = mock(PackageManager.class); mMockContentResolver = new MockContentResolver(mMockContext); MockitoAnnotations.initMocks(this); PowerManager powerManager = (PowerManager) InstrumentationRegistry.getTargetContext() mPowerManager = (PowerManager) InstrumentationRegistry.getTargetContext() .getSystemService(Context.POWER_SERVICE); when(mMockContext.getApplicationInfo()).thenReturn(mMockApplicationInfo); Loading @@ -97,7 +101,7 @@ public class AdapterServiceTest { when(mMockContext.getUserId()).thenReturn(Process.BLUETOOTH_UID); when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager); when(mMockContext.getSystemService(Context.USER_SERVICE)).thenReturn(mMockUserManager); when(mMockContext.getSystemService(Context.POWER_SERVICE)).thenReturn(powerManager); when(mMockContext.getSystemService(Context.POWER_SERVICE)).thenReturn(mPowerManager); when(mMockContext.getSystemService(Context.ALARM_SERVICE)).thenReturn(mMockAlarmManager); when(mMockResources.getBoolean(R.bool.profile_supported_gatt)).thenReturn(true); Loading Loading @@ -138,17 +142,19 @@ public class AdapterServiceTest { } } private void doEnable(int invocationNumber) { private void doEnable(int invocationNumber, boolean onlyGatt) { Assert.assertFalse(mAdapterService.isEnabled()); final int startServiceCalls = 2 * (onlyGatt ? 1 : 3); // Start and stop GATT + 2 mAdapterService.enable(); verifyStateChange(BluetoothAdapter.STATE_OFF, BluetoothAdapter.STATE_BLE_TURNING_ON, invocationNumber + 1, CONTEXT_SWITCH_MS); // Start GATT verify(mMockContext, timeout(CONTEXT_SWITCH_MS).times(6 * invocationNumber + 1)).startService(any()); verify(mMockContext, timeout(CONTEXT_SWITCH_MS).times( startServiceCalls * invocationNumber + 1)).startService(any()); mAdapterService.addProfile(mMockGattService); mAdapterService.onProfileServiceStateChanged(mMockGattService, BluetoothAdapter.STATE_ON); Loading @@ -160,13 +166,15 @@ public class AdapterServiceTest { verifyStateChange(BluetoothAdapter.STATE_BLE_ON, BluetoothAdapter.STATE_TURNING_ON, invocationNumber + 1, CONTEXT_SWITCH_MS); if (!onlyGatt) { // Start Mock PBAP and PAN services verify(mMockContext, timeout(ONE_SECOND_MS).times(6 * invocationNumber + 3)).startService( any()); verify(mMockContext, timeout(ONE_SECOND_MS).times( startServiceCalls * invocationNumber + 3)).startService(any()); mAdapterService.addProfile(mMockService); mAdapterService.addProfile(mMockService2); mAdapterService.onProfileServiceStateChanged(mMockService, BluetoothAdapter.STATE_ON); mAdapterService.onProfileServiceStateChanged(mMockService2, BluetoothAdapter.STATE_ON); } verifyStateChange(BluetoothAdapter.STATE_TURNING_ON, BluetoothAdapter.STATE_ON, invocationNumber + 1, CONTEXT_SWITCH_MS); Loading @@ -174,19 +182,23 @@ public class AdapterServiceTest { Assert.assertTrue(mAdapterService.isEnabled()); } private void doDisable(int invocationNumber) { private void doDisable(int invocationNumber, boolean onlyGatt) { Assert.assertTrue(mAdapterService.isEnabled()); final int startServiceCalls = 2 * (onlyGatt ? 1 : 3); // Start and stop GATT + 2 mAdapterService.disable(); verifyStateChange(BluetoothAdapter.STATE_ON, BluetoothAdapter.STATE_TURNING_OFF, invocationNumber + 1, CONTEXT_SWITCH_MS); if (!onlyGatt) { // Stop PBAP and PAN verify(mMockContext, timeout(ONE_SECOND_MS).times(6 * invocationNumber + 5)).startService( any()); verify(mMockContext, timeout(ONE_SECOND_MS).times( startServiceCalls * invocationNumber + 5)).startService(any()); mAdapterService.onProfileServiceStateChanged(mMockService, BluetoothAdapter.STATE_OFF); mAdapterService.onProfileServiceStateChanged(mMockService2, BluetoothAdapter.STATE_OFF); } verifyStateChange(BluetoothAdapter.STATE_TURNING_OFF, BluetoothAdapter.STATE_BLE_ON, invocationNumber + 1, CONTEXT_SWITCH_MS); Loading @@ -197,8 +209,8 @@ public class AdapterServiceTest { invocationNumber + 1, CONTEXT_SWITCH_MS); // Stop GATT verify(mMockContext, timeout(ONE_SECOND_MS).times(6 * invocationNumber + 6)).startService( any()); verify(mMockContext, timeout(ONE_SECOND_MS).times( startServiceCalls * invocationNumber + startServiceCalls)).startService(any()); mAdapterService.onProfileServiceStateChanged(mMockGattService, BluetoothAdapter.STATE_OFF); verifyStateChange(BluetoothAdapter.STATE_BLE_TURNING_OFF, BluetoothAdapter.STATE_OFF, Loading @@ -213,7 +225,7 @@ public class AdapterServiceTest { */ @Test public void testEnable() { doEnable(0); doEnable(0, false); } /** Loading @@ -222,7 +234,176 @@ public class AdapterServiceTest { */ @Test public void testEnableDisable() { doEnable(0); doDisable(0); doEnable(0, false); doDisable(0, false); } /** * Test: Turn Bluetooth on/off with only GATT supported. * Check whether the AdapterService gets started and stopped. */ @Test public void testEnableDisableOnlyGatt() { Context mockContext = mock(Context.class); Resources mockResources = mock(Resources.class); when(mockContext.getApplicationInfo()).thenReturn(mMockApplicationInfo); when(mockContext.getContentResolver()).thenReturn(mMockContentResolver); when(mockContext.getApplicationContext()).thenReturn(mockContext); when(mockContext.getResources()).thenReturn(mockResources); when(mockContext.getUserId()).thenReturn(Process.BLUETOOTH_UID); when(mockContext.getPackageManager()).thenReturn(mMockPackageManager); when(mockContext.getSystemService(Context.USER_SERVICE)).thenReturn(mMockUserManager); when(mockContext.getSystemService(Context.POWER_SERVICE)).thenReturn(mPowerManager); when(mockContext.getSystemService(Context.ALARM_SERVICE)).thenReturn(mMockAlarmManager); when(mockResources.getBoolean(R.bool.profile_supported_gatt)).thenReturn(true); Config.init(mockContext); doEnable(0, true); doDisable(0, true); } /** * Test: Don't start GATT * Check whether the AdapterService quits gracefully */ @Test public void testGattStartTimeout() { Assert.assertFalse(mAdapterService.isEnabled()); mAdapterService.enable(); verifyStateChange(BluetoothAdapter.STATE_OFF, BluetoothAdapter.STATE_BLE_TURNING_ON, 1, CONTEXT_SWITCH_MS); // Start GATT verify(mMockContext, timeout(CONTEXT_SWITCH_MS).times(1)).startService(any()); mAdapterService.addProfile(mMockGattService); verifyStateChange(BluetoothAdapter.STATE_BLE_TURNING_ON, BluetoothAdapter.STATE_BLE_TURNING_OFF, 1, AdapterState.BLE_START_TIMEOUT_DELAY + CONTEXT_SWITCH_MS); // Stop GATT verify(mMockContext, timeout(AdapterState.BLE_STOP_TIMEOUT_DELAY + CONTEXT_SWITCH_MS) .times(2)).startService(any()); verifyStateChange(BluetoothAdapter.STATE_BLE_TURNING_OFF, BluetoothAdapter.STATE_OFF, 1, CONTEXT_SWITCH_MS); Assert.assertFalse(mAdapterService.isEnabled()); } /** * Test: Don't stop GATT * Check whether the AdapterService quits gracefully */ @Test public void testGattStopTimeout() { doEnable(0, false); Assert.assertTrue(mAdapterService.isEnabled()); mAdapterService.disable(); verifyStateChange(BluetoothAdapter.STATE_ON, BluetoothAdapter.STATE_TURNING_OFF, 1, CONTEXT_SWITCH_MS); // Stop PBAP and PAN verify(mMockContext, timeout(ONE_SECOND_MS).times(5)).startService(any()); mAdapterService.onProfileServiceStateChanged(mMockService, BluetoothAdapter.STATE_OFF); mAdapterService.onProfileServiceStateChanged(mMockService2, BluetoothAdapter.STATE_OFF); verifyStateChange(BluetoothAdapter.STATE_TURNING_OFF, BluetoothAdapter.STATE_BLE_ON, 1, CONTEXT_SWITCH_MS); mAdapterService.onBrEdrDown(); verifyStateChange(BluetoothAdapter.STATE_BLE_ON, BluetoothAdapter.STATE_BLE_TURNING_OFF, 1, CONTEXT_SWITCH_MS); // Stop GATT verify(mMockContext, timeout(ONE_SECOND_MS).times(6)).startService(any()); verifyStateChange(BluetoothAdapter.STATE_BLE_TURNING_OFF, BluetoothAdapter.STATE_OFF, 1, AdapterState.BLE_STOP_TIMEOUT_DELAY + CONTEXT_SWITCH_MS); Assert.assertFalse(mAdapterService.isEnabled()); } /** * Test: Don't start a classic profile * Check whether the AdapterService quits gracefully */ @Test public void testProfileStartTimeout() { Assert.assertFalse(mAdapterService.isEnabled()); mAdapterService.enable(); verifyStateChange(BluetoothAdapter.STATE_OFF, BluetoothAdapter.STATE_BLE_TURNING_ON, 1, CONTEXT_SWITCH_MS); // Start GATT verify(mMockContext, timeout(CONTEXT_SWITCH_MS).times(1)).startService(any()); mAdapterService.addProfile(mMockGattService); mAdapterService.onProfileServiceStateChanged(mMockGattService, BluetoothAdapter.STATE_ON); verifyStateChange(BluetoothAdapter.STATE_BLE_TURNING_ON, BluetoothAdapter.STATE_BLE_ON, 1, NATIVE_INIT_MS); mAdapterService.onLeServiceUp(); verifyStateChange(BluetoothAdapter.STATE_BLE_ON, BluetoothAdapter.STATE_TURNING_ON, 1, CONTEXT_SWITCH_MS); // Register Mock PBAP and PAN services, only start one verify(mMockContext, timeout(ONE_SECOND_MS).times(3)).startService(any()); mAdapterService.addProfile(mMockService); mAdapterService.addProfile(mMockService2); mAdapterService.onProfileServiceStateChanged(mMockService, BluetoothAdapter.STATE_ON); verifyStateChange(BluetoothAdapter.STATE_TURNING_ON, BluetoothAdapter.STATE_TURNING_OFF, 1, AdapterState.BREDR_START_TIMEOUT_DELAY + CONTEXT_SWITCH_MS); // Stop PBAP and PAN verify(mMockContext, timeout(ONE_SECOND_MS).times(5)).startService(any()); mAdapterService.onProfileServiceStateChanged(mMockService, BluetoothAdapter.STATE_OFF); verifyStateChange(BluetoothAdapter.STATE_TURNING_OFF, BluetoothAdapter.STATE_BLE_ON, 1, CONTEXT_SWITCH_MS); } /** * Test: Don't stop a classic profile * Check whether the AdapterService quits gracefully */ @Test public void testProfileStopTimeout() { doEnable(0, false); Assert.assertTrue(mAdapterService.isEnabled()); mAdapterService.disable(); verifyStateChange(BluetoothAdapter.STATE_ON, BluetoothAdapter.STATE_TURNING_OFF, 1, CONTEXT_SWITCH_MS); // Stop PBAP and PAN verify(mMockContext, timeout(ONE_SECOND_MS).times(5)).startService(any()); mAdapterService.onProfileServiceStateChanged(mMockService, BluetoothAdapter.STATE_OFF); verifyStateChange(BluetoothAdapter.STATE_TURNING_OFF, BluetoothAdapter.STATE_BLE_TURNING_OFF, 1, AdapterState.BREDR_STOP_TIMEOUT_DELAY + CONTEXT_SWITCH_MS); // Stop GATT verify(mMockContext, timeout(ONE_SECOND_MS).times(6)).startService(any()); mAdapterService.onProfileServiceStateChanged(mMockGattService, BluetoothAdapter.STATE_OFF); verifyStateChange(BluetoothAdapter.STATE_BLE_TURNING_OFF, BluetoothAdapter.STATE_OFF, 1, AdapterState.BLE_STOP_TIMEOUT_DELAY + CONTEXT_SWITCH_MS); Assert.assertFalse(mAdapterService.isEnabled()); } }