Java
+--------------------------------+
+-----------------+ C++/C
| BTIF |
+-----------------+
| BTA |
+-----------------+
| Bluedroid Stack |
+-----------------+ user space
+---------------------------------+
kernel space
1. BluetoothSettings.java
蓝牙配置和连接管理界面,就是咱们常见的蓝牙界面。它管理着蓝牙界面的加载,蓝牙搜索,蓝牙连接,蓝牙重命名等管理功能
2. BluetoothEnable.java
蓝牙辅助类,用来管理蓝牙的开和关以及蓝牙状态的标题显示。如打开或关闭蓝牙的switchbar的状态和文本显示。
3. DeviceListPreferenceFragment.java
BluetoothSettings类的父类,是一个抽象类,该类包含了用于保存蓝牙设备的链表以及蓝牙。同时实现BluetoothCallback接口,实现蓝牙设备的一些回调方法。
4. BluetoothCallback.java
蓝牙设备的删除、扫描状态的改变、蓝牙状态的改变等回调抽象方法。
5. CachedBluetoothDevice.java
缓存蓝牙设备,该类代表了一个远程设备,它包含了蓝牙设备的一些属性(例如蓝牙地址,名字,信号强度等)。该类还可以进行蓝牙设备的连接、配对、断开连接等功能。位于SettingsLib
6. BluetoothDevice.java
表示远程蓝牙设备。 使用{@link BluetoothDevice}可以创建与相应设备的连接或查询有关它的信息,例如名称,地址,类和绑定状态。位于frameworks中
7. BluetoothDevicePreference.java
在设置界面显示蓝牙设备的偏好类型。点击界面上的配对、连接、断开就是在这操作的。
8. BluetoothAdapter.java
表示本地设备蓝牙适配器。 {@link BluetoothAdapter}允许您执行基本的蓝牙任务,例如启动设备发现,查询绑定(配对)设备列表,使用已知MAC地址实例化{@link BluetoothDevice},以及创建{@link BluetoothServerSocket} 监听来自其他设备的连接请求,并开始扫描蓝牙LE设备。位于frameworks中
9. BluetoothEventManager.java
BluetoothEventManager从蓝牙API接收广播和回调,并将UI线程上的事件分派到设置中显示。位于SettingsLib
10.LocalBluetoothAdapter.java
蓝牙接口适配为本地的蓝牙接口适配器,为应用提供接口,同时调用BluetoothAdapter的接口,起到应用和底层的适配作用。
11. CachedBluetoothDeviceManager.java
负责管理蓝牙的缓存(已配对的设备和搜索到的设备)主要都保存在List
12. LocalBluetoothProfileManager.java
提供访问有效的蓝牙协议对象LocalBluetoothProfile。位于SettingsLib
13. BluetoothManager.java
高级管理员用于获取{@link BluetoothAdapter}的实例并进行整体蓝牙管理。
14. BluetoothManagerService.java
15. AdapterState.java
状态机处理蓝牙适配器状态
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为true则开启蓝牙
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) {
//调用到BluetoothAdapter.java-->enable()
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-->enable()
@RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public boolean enable() {
if (isEnabled()) {
if (DBG) Log.d(TAG, "enable(): BT already enabled!");
return true;
}
try {
//走到service
return mManagerService.enable(ActivityThread.currentPackageName());
} catch (RemoteException e) {Log.e(TAG, "", e);}
return false;
}
4.BluetoothManagerService.java--->enable()
public boolean enable(String packageName) throws RemoteException {
final int callingUid = Binder.getCallingUid();
final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID;
if (isBluetoothDisallowed()) {
if (DBG) {
Slog.d(TAG,"enable(): not enabling - bluetooth disallowed");
}
return false;
}
if (!callerSystem) {
if (!checkIfCallerIsForegroundUser()) {
Slog.w(TAG, "enable(): 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_ENABLE)) {
return false;
}
}
if (DBG) {
Slog.d(TAG,"enable(" + packageName + "): mBluetooth =" + mBluetooth +
" mBinding = " + mBinding + " mState = " +
BluetoothAdapter.nameForState(mState));
}
synchronized(mReceiver) {
mQuietEnableExternal = false;
if (!mEnableBLE) {
mEnableExternal = true;
} else {
mEnableBLE = false;
}
// waive WRITE_SECURE_SETTINGS permission check
sendEnableMsg(false, packageName);
}
if (DBG) Slog.d(TAG, "enable returning");
return true;
}
4.BluetoothManagerService.java--->sendEnableMsg()
private void sendEnableMsg(boolean quietMode, String packageName) {
mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE,
quietMode ? 1 : 0, 0));
addActiveLog(packageName, true);
}
case MESSAGE_ENABLE:
if (DBG) {
Slog.d(TAG, "MESSAGE_ENABLE(" + msg.arg1 + "): mBluetooth = " + mBluetooth);
}
mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);
mEnable = true;
// Use service interface to get the exact state
int state = 0;
try {
mBluetoothLock.readLock().lock();
if (mBluetooth != null) {
state = mBluetooth.getState();
if (state == BluetoothAdapter.STATE_BLE_ON) {
Slog.w(TAG, "BT Enable in BLE_ON State, going to ON");
mBluetooth.onLeServiceUp();
persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
break;
}
}
} catch (RemoteException e) {
Slog.e(TAG, "", e);
} finally {
mBluetoothLock.readLock().unlock();
}
mQuietEnable = (msg.arg1 == 1);
if (mBluetooth == null) {
handleEnable(mQuietEnable);
} else {
// M: ALPS03489521: Don't restart BT when BT is turning on
if (state == BluetoothAdapter.STATE_BLE_TURNING_ON ||
state == BluetoothAdapter.STATE_TURNING_ON ||
state == BluetoothAdapter.STATE_ON) {
break;
}
//
// We need to wait until transitioned to STATE_OFF and
// the previous Bluetooth process has exited. The
// waiting period has three components:
// (a) Wait until the local state is STATE_OFF. This
// is accomplished by "waitForOnOff(false, true)".
// (b) Wait until the STATE_OFF state is updated to
// all components.
// (c) Wait until the Bluetooth process exits, and
// ActivityManager detects it.
// The waiting for (b) and (c) is accomplished by
// delaying the MESSAGE_RESTART_BLUETOOTH_SERVICE
// message. On slower devices, that delay needs to be
// on the order of (2 * SERVICE_RESTART_TIME_MS).
//
waitForOnOff(false, true);
Message restartMsg = mHandler.obtainMessage(
MESSAGE_RESTART_BLUETOOTH_SERVICE);
mHandler.sendMessageDelayed(restartMsg,
2 * SERVICE_RESTART_TIME_MS);
}
break;
5.BluetoothManagerService.java--->handleEnable()
在这里会调用到IBluetooth的客户端代理类mBluetooth = IBluetooth.Stub.asInterface(Binder.allowBlocking(service));
调用mBluetooth.enable()
private void handleEnable(boolean quietMode) {
mQuietEnable = quietMode;
try {
mBluetoothLock.writeLock().lock();
if ((mBluetooth == null) && (!mBinding)) {
//Start bind timeout and bind
Message timeoutMsg=mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);
mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS);
Intent i = new Intent(IBluetooth.class.getName());
if (!doBind(i, mConnection,Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
UserHandle.CURRENT)) {
mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
} else {
mBinding = true;
}
} else if (mBluetooth != null) {
//Enable bluetooth
try {
if (!mQuietEnable) {
//开启蓝牙
if(!mBluetooth.enable()) {
Slog.e(TAG,"IBluetooth.enable() returned false");
}
}
else {
if(!mBluetooth.enableNoAutoConnect()) {
Slog.e(TAG,"IBluetooth.enableNoAutoConnect() returned false");
}
}
} catch (RemoteException e) {
Slog.e(TAG,"Unable to call enable()",e);
}
}
} finally {
mBluetoothLock.writeLock().unlock();
}
}
5.AdapterService.java--->AdapterServiceBinder --->enable()
AdapterService位于Bluetooth包下,其内部类AdapterServiceBinder extends IBluetooth.Stub,
public boolean enable() {
if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
(!Utils.checkCaller())) {
Log.w(TAG, "enable() - Not allowed for non-active user and non system user");
return false;
}
AdapterService service = getService();
if (service == null) return false;
return service.enable();
}
6.AdapterService.java--->enable()
发送AdapterState.BLE_TURN_ON信息
public synchronized boolean enable(boolean quietMode) {
enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
// Enforce the user restriction for disallowing Bluetooth if it was set.
if (mUserManager.hasUserRestriction(UserManager.DISALLOW_BLUETOOTH, UserHandle.SYSTEM)) {
debugLog("enable() called when Bluetooth was disallowed");
return false;
}
debugLog("enable() - Enable called with quiet mode status = " + mQuietmode);
mQuietmode = quietMode;
Message m = mAdapterStateMachine.obtainMessage(AdapterState.BLE_TURN_ON);
mAdapterStateMachine.sendMessage(m);
mBluetoothStartTime = System.currentTimeMillis();
return true;
}
7.AdapterState.java--->OffState
对BLE_TURN_ON消息进行处理
case BLE_TURN_ON:
notifyAdapterStateChange(BluetoothAdapter.STATE_BLE_TURNING_ON);
mPendingCommandState.setBleTurningOn(true);
transitionTo(mPendingCommandState);
sendMessageDelayed(BLE_START_TIMEOUT, BLE_START_TIMEOUT_DELAY);
adapterService.BleOnProcessStart();
break;
8.AdapterService.java--->BleOnProcessStart()
void BleOnProcessStart() {
debugLog("BleOnProcessStart()");
if (getResources().getBoolean(
R.bool.config_bluetooth_reload_supported_profiles_when_enabled)) {
Config.init(getApplicationContext());
}
Class[] supportedProfileServices = Config.getSupportedProfiles();
//Initialize data objects
for (int i=0; i < supportedProfileServices.length;i++) {
mProfileServicesState.put(supportedProfileServices[i].getName(),BluetoothAdapter.STATE_OFF);
}
// Reset |mRemoteDevices| whenever BLE is turned off then on
// This is to replace the fact that |mRemoteDevices| was
// reinitialized in previous code.
//
// TODO(apanicke): The reason is unclear but
// I believe it is to clear the variable every time BLE was
// turned off then on. The same effect can be achieved by
// calling cleanup but this may not be necessary at all
// We should figure out why this is needed later
mRemoteDevices.reset();
mAdapterProperties.init(mRemoteDevices);
debugLog("BleOnProcessStart() - Make Bond State Machine");
mBondStateMachine = BondStateMachine.make(this, mAdapterProperties, mRemoteDevices);
mJniCallbacks.init(mBondStateMachine,mRemoteDevices);
try {
mBatteryStats.noteResetBleScan();
} catch (RemoteException e) {
// Ignore.
}
//Start Gatt service
//在这里会启动PrfileSerice,最终调用到enableNative()
setGattProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_ON);
}