第一次接触蓝牙,先从蓝牙的开启流程入手吧,借此顺便熟悉一下蓝牙的代码架构。
1、UI/packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothSwitchPreferenceController.java
public void onClick(View v) {
// send users to scanning settings if they click on the link in the summary text
new SubSettingLauncher(mContext)
.setDestination(ScanningSettings.class.getName())
.setSourceMetricsCategory(MetricsProto.MetricsEvent.BLUETOOTH_FRAGMENT)
.launch();
}
/packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothEnabler.java
public boolean onSwitchToggled(boolean isChecked) {
if (maybeEnforceRestrictions()) {
triggerParentPreferenceCallback(isChecked);
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
mSwitchController.setChecked(false);
triggerParentPreferenceCallback(false);
return false;
}
mMetricsFeatureProvider.action(mContext, mMetricsEvent, isChecked);
if (mLocalAdapter != null) {
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) {
mSwitchController.setChecked(false);
mSwitchController.setEnabled(true);
mSwitchController.updateTitle(false);
triggerParentPreferenceCallback(false);
return false;
}
}
mSwitchController.setEnabled(false);
triggerParentPreferenceCallback(isChecked);
return true;
}
2、framework
/frameworks/base/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java
public boolean setBluetoothEnabled(boolean enabled) {
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;
}
/frameworks/base/core/java/android/bluetooth/BluetoothAdapter.java
@RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public boolean enable() {
if (isEnabled()) {
if (DBG) {
Log.d(TAG, "enable(): BT already enabled!");
}
return true;
}
try {
return mManagerService.enable(ActivityThread.currentPackageName());
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
return false;
}
这个方法中的关键代码是“return mManagerService.enable();” mManagerService 对象是由IBluetoothManager 接口代码实现的,IBluetoothManager实际定义的是AIDL文件,对应的类就是 BluetoothManagerService 类,在路径 frameworks/base/core/java/android/bluetooth/BluetoothManagerService 下面 。
/frameworks/base/services/core/java/com/android/server/BluetoothManagerService.java
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 && 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;
mEnableExternal = true;
// waive WRITE_SECURE_SETTINGS permission check
sendEnableMsg(false,
BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName);
}
if (DBG) {
Slog.d(TAG, "enable returning");
}
return true;
}
方法中先判断是否是系统app操作蓝牙,检查是否有操作蓝牙的权限等,然后关键的代码是“sendEnableMsg(false)”,handler最后调用handleEnable方法处理该消息。
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();
}
}
这里通过AIDL的方式,调用Bluetooth App 中的AdapterService 。先绑定服务,然后注册Ibluetooth回调函数,之后调用enable方法方法开启蓝牙。所以之后就从Framworks 跳到 Bluetooth APP 中继续分析。
3、Bluetooth APP/packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterService.java
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 = " + quietMode);
mQuietmode = quietMode;
mAdapterStateMachine.sendMessage(AdapterState.BLE_TURN_ON);
return true;
}
private class OffState extends BaseAdapterState {
@Override
int getStateValue() {
return BluetoothAdapter.STATE_OFF;
}
@Override
public boolean processMessage(Message msg) {
switch (msg.what) {
case BLE_TURN_ON:
transitionTo(mTurningBleOnState);
break;
default:
infoLog("Unhandled message - " + messageString(msg.what));
return false;
}
return true;
}
}
private class TurningBleOnState extends BaseAdapterState {
@Override
int getStateValue() {
return BluetoothAdapter.STATE_BLE_TURNING_ON;
}
@Override
public void enter() {
super.enter();
sendMessageDelayed(BLE_START_TIMEOUT, BLE_START_TIMEOUT_DELAY);
mAdapterService.bringUpBle();
}
@Override
public void exit() {
removeMessages(BLE_START_TIMEOUT);
super.exit();
}
@Override
public boolean processMessage(Message msg) {
switch (msg.what) {
case BLE_STARTED:
transitionTo(mBleOnState);
break;
case BLE_START_TIMEOUT:
errorLog(messageString(msg.what));
transitionTo(mTurningBleOffState);
break;
default:
infoLog("Unhandled message - " + messageString(msg.what));
return false;
}
return true;
}
}
/packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterService.java
void bringUpBle() {
debugLog("bleOnProcessStart()");
if (getResources().getBoolean(
R.bool.config_bluetooth_reload_supported_profiles_when_enabled)) {
Config.init(getApplicationContext());
}
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) {
Log.w(TAG, "RemoteException trying to send a reset to BatteryStats");
}
StatsLog.write_non_chained(StatsLog.BLE_SCAN_STATE_CHANGED, -1, null,
StatsLog.BLE_SCAN_STATE_CHANGED__STATE__RESET, false, false, false);
//Start Gatt service
setProfileServiceState(GattService.class, BluetoothAdapter.STATE_ON);
}
/packages/apps/Bluetooth/src/com/android/bluetooth/btservice/BondStateMachine.java
private BondStateMachine(AdapterService service, AdapterProperties prop,
RemoteDevices remoteDevices) {
super("BondStateMachine:");
addState(mStableState);
addState(mPendingCommandState);
mRemoteDevices = remoteDevices;
mAdapterService = service;
mAdapterProperties = prop;
mAdapter = BluetoothAdapter.getDefaultAdapter();
setInitialState(mStableState);
}
private class StableState extends State {
@Override
public void enter() {
infoLog("StableState(): Entering Off State");
}
@Override
public boolean processMessage(Message msg) {
BluetoothDevice dev = (BluetoothDevice) msg.obj;
switch (msg.what) {
case CREATE_BOND:
OobData oobData = null;
if (msg.getData() != null) {
oobData = msg.getData().getParcelable(OOBDATA);
}
createBond(dev, msg.arg1, oobData, true);
break;
case REMOVE_BOND:
removeBond(dev, true);
break;
case BONDING_STATE_CHANGE:
int newState = msg.arg1;
if (newState == BluetoothDevice.BOND_BONDING) {
sendIntent(dev, newState, 0);
transitionTo(mPendingCommandState);
} else if (newState == BluetoothDevice.BOND_NONE) {
sendIntent(dev, newState, 0);
} else {
Log.e(TAG, "In stable state, received invalid newState: "
+ state2str(newState));
}
break;
case CANCEL_BOND:
default:
Log.e(TAG, "Received unhandled state: " + msg.what);
return false;
}
return true;
}
}
通过调用adapterService.enableNative()方法,开始调用JNI方法,进入C/C++层。adapterService.enableNative对应的cpp文件为
/packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterService.cpp
static jboolean enableNative(JNIEnv* env, jobject obj, jboolean isGuest) {
ALOGV("%s", __func__);
if (!sBluetoothInterface) return JNI_FALSE;
int ret = sBluetoothInterface->enable(isGuest == JNI_TRUE ? 1 : 0);
return (ret == BT_STATUS_SUCCESS || ret == BT_STATUS_DONE) ? JNI_TRUE
: JNI_FALSE;
}
通过调用“int ret = sBluetoothInterface->enable()”来驱动底层打开蓝牙开关。接下来就是C里面对打开蓝牙的实现。
4、蓝牙协议栈/system/bt/btif/src/bluetooth.cc
static int enable(bool start_restricted) {
LOG_INFO(LOG_TAG, "%s: start restricted = %d", __func__, start_restricted);
restricted_mode = start_restricted;
if (!interface_ready()) return BT_STATUS_NOT_READY;
stack_manager_get_interface()->start_up_stack_async();
return BT_STATUS_SUCCESS;
}
enable方法会调用start_up_stack_async方法,start_up_stack_async的实现在stack_manager.c 文件中:
/system/bt/btif/src/stack_manager.cc
static void start_up_stack_async(void) {
thread_post(management_thread, event_start_up_stack, NULL);
}
通过thread_post异步event_start_up_stack,来启动蓝牙栈
static void event_start_up_stack(UNUSED_ATTR void* context) {
if (stack_is_running) {
LOG_INFO(LOG_TAG, "%s stack already brought up", __func__);
return;
}
ensure_stack_is_initialized();
LOG_INFO(LOG_TAG, "%s is bringing up the stack", __func__);
future_t* local_hack_future = future_new();
hack_future = local_hack_future;
// Include this for now to put btif config into a shutdown-able state
module_start_up(get_module(BTIF_CONFIG_MODULE));
bte_main_enable();
if (future_await(local_hack_future) != FUTURE_SUCCESS) {
LOG_ERROR(LOG_TAG, "%s failed to start up the stack", __func__);
stack_is_running = true; // So stack shutdown actually happens
event_shut_down_stack(NULL);
return;
}
stack_is_running = true;
LOG_INFO(LOG_TAG, "%s finished", __func__);
btif_thread_post(event_signal_stack_up, NULL);
}
bte_main_enable()方法中进行btsnoop_module和hci_module的启动以及启动BTU操作。
作者:二十岁了还没有去过星巴克