蓝牙关闭的流程和开启的流程差不多,下面简单分析一下流程:
1.BluetoothEnabler.java--->onSwitchToggled()
关闭和开启蓝牙的switchbar的监听状态存在与BluetoothEnable类中,当点击switchbar时,由于BluetoothEnabler implements SwitchWidgetController.OnSwitchChangeListener ,所以会调用onSwitchToggled
@Override
public boolean onSwitchToggled(boolean isChecked) {
if (maybeEnforceRestrictions()) {
return true;
}
// Show toast message if Bluetooth is not allowed in airplane mode
if (isChecked &&
!WirelessUtils.isRadioAllowed(mContext, Settings.Global.RADIO_BLUETOOTH)) {
Toast.makeText(mContext, R.string.wifi_in_airplane_mode, Toast.LENGTH_SHORT).show();
// Reset switch to off
mSwitch.setChecked(false);
return false;
}
mMetricsFeatureProvider.action(mContext, mMetricsEvent, isChecked);
if (mLocalAdapter != null) {
//isChecked未false则关闭蓝牙
boolean status = mLocalAdapter.setBluetoothEnabled(isChecked);
// If we cannot toggle it ON then reset the UI assets:
// a) The switch should be OFF but it should still be togglable (enabled = True)
// b) The switch bar should have OFF text.
if (isChecked && !status) {
mSwitch.setChecked(false);
mSwitch.setEnabled(true);
mSwitchWidget.updateTitle(false);
return false;
}
}
mSwitchWidget.setEnabled(false);
return true;
}
2.LocalBluetoothAdapter.java--->setBluetoothEnabled()
public boolean setBluetoothEnabled(boolean enabled) {
//关闭时false,所以调用到BluetoothAdapter.java-->disable()
boolean success = enabled
? mAdapter.enable()
: mAdapter.disable();
if (success) {
setBluetoothStateInt(enabled
? BluetoothAdapter.STATE_TURNING_ON
: BluetoothAdapter.STATE_TURNING_OFF);
} else {
if (Utils.V) {
Log.v(TAG, "setBluetoothEnabled call, manager didn't return " +
"success for enabled: " + enabled);
}
syncBluetoothState();
}
return success;
3.BluetoothAdapter.java-->disable()
@RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public boolean disable() {
try {
return mManagerService.disable(ActivityThread.currentPackageName(), true);
} catch (RemoteException e) {Log.e(TAG, "", e);}
return false;
}
4..BluetoothManagerService.java--->disable()
public boolean disable(String packageName, boolean persist) throws RemoteException {
final int callingUid = Binder.getCallingUid();
final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID;
if (!callerSystem) {
if (!checkIfCallerIsForegroundUser()) {
Slog.w(TAG, "disable(): not allowed for non-active and non system user");
return false;
}
mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH ADMIN permission");
if (isEnabled() && mPermissionReviewRequired && !CtaManagerFactory.getInstance().
makeCtaManager().isSystemApp(mContext, packageName)
&& startConsentUiIfNeeded(packageName, callingUid,
BluetoothAdapter.ACTION_REQUEST_DISABLE)) {
return false;
}
}
if (DBG) {
Slog.d(TAG,"disable(): mBluetooth = " + mBluetooth +
" mBinding = " + mBinding);
}
synchronized(mReceiver) {
if (persist) {
persistBluetoothSetting(BLUETOOTH_OFF);
}
mEnableExternal = false;
sendDisableMsg(packageName);
}
return true;
}
4.BluetoothManagerService.java--->sendDisableMsg()
发送MESSAGE_DISABLE消息
private void sendDisableMsg(String packageName) {
mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_DISABLE));
addActiveLog(packageName, false);
}
接收MESSAGE_DISABLE消息
case MESSAGE_DISABLE:
if (DBG) Slog.d(TAG, "MESSAGE_DISABLE: mBluetooth = " + mBluetooth);
mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);
if (mEnable && mBluetooth != null) {
waitForOnOff(true, false);
mEnable = false;
handleDisable();
waitForOnOff(false, false);
} else {
mEnable = false;
handleDisable();
}
break;
5.BluetoothManagerService.java--->handleDisable()
在这里会调用到IBluetooth的客户端代理类mBluetooth = IBluetooth.Stub.asInterface(Binder.allowBlocking(service));
调用mBluetooth.enable()
private void handleDisable() {
try {
mBluetoothLock.readLock().lock();
if (mBluetooth != null) {
if (DBG) Slog.d(TAG,"Sending off request.");
//mBluetooth = IBluetooth.Stub.asInterface(Binder.allowBlocking(service));
//是IBluetooth的客户端,服务端是AdapterService的一个内部类、
//AdapterServiceBinder extends IBluetooth.Stub,
if (!mBluetooth.disable()) {
Slog.e(TAG,"IBluetooth.disable() returned false");
}
}
} catch (RemoteException e) {
Slog.e(TAG,"Unable to call disable()",e);
} finally {
mBluetoothLock.readLock().unlock();
}
}
6.AdapterService.java--->AdapterServiceBinder --->disable()
AdapterService位于Bluetooth包下,其内部类AdapterServiceBinder extends IBluetooth.Stub
public boolean disable() {
if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
(!Utils.checkCaller())) {
Log.w(TAG, "disable() - Not allowed for non-active user and non system user");
return false;
}
AdapterService service = getService();
if (service == null) return false;
return service.disable();
}
7.AdapterService.java--->disable()
发送AdapterState.BLE_TURN_OFF信息
boolean disable() {
enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
debugLog("disable() called...");
Message m = mAdapterStateMachine.obtainMessage(AdapterState.BLE_TURN_OFF);
mAdapterStateMachine.sendMessage(m);
return true;
}
8.AdapterState.java--->OnState
接收AdapterState.BLE_TURN_OFF信息
case BLE_TURN_OFF:
notifyAdapterStateChange(BluetoothAdapter.STATE_TURNING_OFF);
mPendingCommandState.setTurningOff(true);
transitionTo(mPendingCommandState);
// Invoke onBluetoothDisable which shall trigger a
// setScanMode to SCAN_MODE_NONE
Message m = obtainMessage(SET_SCAN_MODE_TIMEOUT);
sendMessageDelayed(m, PROPERTY_OP_DELAY);
adapterProperties.onBluetoothDisable();
break;
8.AdapterService.java--->onBluetoothDisable()
void onBluetoothDisable() {
// From STATE_ON to BLE_ON
// When BT disable is invoked, set the scan_mode to NONE
// so no incoming connections are possible
//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();
setScanMode(AbstractionLayer.BT_SCAN_MODE_NONE);
}
}
boolean setScanMode(int scanMode) {
synchronized (mObject) {
//setAdapterPropertyNatives是native方法
return mService.setAdapterPropertyNative(
AbstractionLayer.BT_PROPERTY_ADAPTER_SCAN_MODE, Utils.intToByteArray(scanMode));
}
}