微信扫码,给个关注吧

第一次接触蓝牙,先从蓝牙的开启流程入手吧,借此顺便熟悉一下蓝牙的代码架构。

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 incoming pairing, transition to pending state */

if (newState == BluetoothDevice.BOND_BONDING) {

sendIntent(dev, newState, 0);

transitionTo(mPendingCommandState);

} else if (newState == BluetoothDevice.BOND_NONE) {

/* if the link key was deleted by the stack */

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操作。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐