在權(quán)限允許的情況下,通過enable()函數(shù)可以打開Android設(shè)備的本地藍牙。調(diào)用該函數(shù)需要權(quán)限Manifest.permission.BLUETOOTH_ADMIN。它是BluetoothAdapter的函數(shù),那就先從這開始分析:
private final IBluetoothManager mManagerService;
@RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public boolean enable() {
if (isEnabled()) {
// 藍牙已經(jīng)可用,直接返回true
return true;
}
try {
return mManagerService.enable(ActivityThread.currentPackageName());
} catch (RemoteException e) {Log.e(TAG, "", e);}
return false;
}
BluetoothAdapter的enable()函數(shù)很簡單,通過aidl的方式,調(diào)用遠程服務(wù)BluetoothManagerService的enable(packageName)函數(shù):
public boolean enable(String packageName) throws RemoteException {
final int callingUid = Binder.getCallingUid();
final boolean callerSystem = UserHandle.getAppId(callingUid) ==Process.SYSTEM_UID;
// 如果藍牙被禁用,直接返回false
if (isBluetoothDisallowed()) {
return false;
}
if (!callerSystem) {
if (!checkIfCallerIsForegroundUser()) {
return false;
}
// 檢測是否擁有BLUETOOTH_ADMIN權(quán)限
mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,"Need BLUETOOTH ADMIN permission");
if (!isEnabled() && mPermissionReviewRequired
&& startConsentUiIfNeeded(packageName, callingUid,
BluetoothAdapter.ACTION_REQUEST_ENABLE)) {
return false;
}
}
synchronized(mReceiver) {
mQuietEnableExternal = false;
mEnableExternal = true;
// 通過BluetoothHandler去處理enable的消息
sendEnableMsg(false, packageName);
}
return true;
}
在函數(shù)中先是檢查各種權(quán)限,權(quán)限都通過之后,向BluetoothHandler發(fā)送消息,交給它去完成接下來的開啟任務(wù),到這意味著開啟任務(wù)已經(jīng)開始,該函數(shù)的任務(wù)已經(jīng)結(jié)束返回true。因此這里返回true并不代表藍牙功能開啟成功,僅僅表示這項工作通過了層層檢測,步上了正軌。繼續(xù)看sendEnableMsg()函數(shù)
private void sendEnableMsg(boolean quietMode, String packageName) {
mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE,
quietMode ? 1 : 0, 0));
}
接著看BluetoothHandler的handleMessage()函數(shù),這個函數(shù)很長,有450行代碼,這里只看MESSAGE_ENABLE分支:
private IBluetooth mBluetooth;
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_ENABLE:
mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);
mEnable = true;
try {
// 通過讀寫鎖來保證線程安全
mBluetoothLock.readLock().lock();
if (mBluetooth != null) {
// 獲取當(dāng)前藍牙狀態(tài),如果當(dāng)前處于STATE_BLE_ON狀態(tài),那就切換到USER_TURN_ON狀態(tài),并返回
int state = mBluetooth.getState();
if (state == BluetoothAdapter.STATE_BLE_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) {
// 執(zhí)行enable()的函數(shù)
handleEnable(mQuietEnable);
} else {
//
// 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).
//
// 遠程服務(wù)已連接,并且當(dāng)前不是STATE_BLE_ON狀態(tài),那么需要重啟藍牙服務(wù)。
// 需要等待本地藍牙功能關(guān)閉,然后重啟藍牙服務(wù)
waitForOnOff(false, true);
Message restartMsg = mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE);
mHandler.sendMessageDelayed(restartMsg, 2 * SERVICE_RESTART_TIME_MS);
}
break;
}
重點看handleEnable(bool)函數(shù):
private void handleEnable(boolean quietMode) {
mQuietEnable = quietMode;
try {
mBluetoothLock.writeLock().lock();
if ((mBluetooth == null) && (!mBinding)) {
// 沒有綁定服務(wù),發(fā)起服務(wù)綁定,并設(shè)置綁定超時時間為3s
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) {
try {
if (!mQuietEnable) {
// 調(diào)用enable函數(shù),開啟藍牙
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();
}
}
核心代碼就是mBluetooth.enable() ,其余的忽略。通過AIDL調(diào)用的是遠程服務(wù)AdapterService中的enable()函數(shù)。
接著看AdapterService:
private AdapterState mAdapterStateMachine;
public boolean enable() {
return enable(false);
}
public synchronized boolean enable(boolean quietMode) {
// 檢測權(quán)限
enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
if (mUserManager.hasUserRestriction(UserManager.DISALLOW_BLUETOOTH, UserHandle.SYSTEM)) {
// 藍牙不允許使用
return false;
}
mQuietmode = quietMode;
mAdapterStateMachine.sendMessage(AdapterState.BLE_TURN_ON);
return true;
}
核心代碼是mAdapterStateMachine.sendMessage(AdapterState.BLE_TURN_ON);,那么mAdapterStateMachine又是什么對象呢,從命名上可以看出它是個狀態(tài)機,因此這里是往狀態(tài)機AdapterState中發(fā)送了一條BLE_TURN_ON的消息。接著看狀態(tài)機AdapterState:
/**
* This state machine handles Bluetooth Adapter State.
* Stable States:
* {@link OffState}: Initial State
* {@link BleOnState} : Bluetooth Low Energy, Including GATT, is on
* {@link OnState} : Bluetooth is on (All supported profiles)
*
* Transition States:
* {@link TurningBleOnState} : OffState to BleOnState
* {@link TurningBleOffState} : BleOnState to OffState
* {@link TurningOnState} : BleOnState to OnState
* {@link TurningOffState} : OnState to BleOnState
*
* +------ Off <-----+
* | |
* v |
* TurningBleOn TO---> TurningBleOff
* | ^ ^
* | | |
* +-----> ----+ |
* BleOn |
* +------ <---+ O
* v | T
* TurningOn TO----> TurningOff
* | ^
* | |
* +-----> On ------+
*
*/
final class AdapterState extends StateMachine {
private AdapterService mAdapterService;
private TurningOnState mTurningOnState = new TurningOnState();
private TurningBleOnState mTurningBleOnState = new TurningBleOnState();
private TurningOffState mTurningOffState = new TurningOffState();
private TurningBleOffState mTurningBleOffState = new TurningBleOffState();
private OnState mOnState = new OnState();
private OffState mOffState = new OffState();
private BleOnState mBleOnState = new BleOnState();
private AdapterState(AdapterService service) {
super(TAG);
addState(mOnState);
addState(mBleOnState);
addState(mOffState);
addState(mTurningOnState);
addState(mTurningOffState);
addState(mTurningBleOnState);
addState(mTurningBleOffState);
mAdapterService = service;
setInitialState(mOffState);
}
public static AdapterState make(AdapterService service) {
AdapterState as = new AdapterState(service);
as.start();
return as;
}
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:
return false;
}
return true;
}
}
}
從源碼注釋上可以清楚了解到狀態(tài)機擁有的所有狀態(tài),狀態(tài)機的使用以及原理之前分析過,這里再看一下:
-
addState(state),藍牙狀態(tài)機總共有7中狀態(tài),都沒有父狀態(tài); -
setInitialState(state),藍牙初始狀態(tài)是offState; - 在
State的processMessage()函數(shù)中處理消息。
AdapterService中向狀態(tài)機發(fā)送了BLE_TURN_ON消息,此時狀態(tài)機的狀態(tài)是OffState。在OffState類的processMessage()函數(shù)中對BLE_TURN_ON消息的處理是:調(diào)用transitionTo(mTurningBleOnState),將狀態(tài)切換到TurningBleOnState。那么TurningBleOnState()將會執(zhí)行enter()方法,接著看看在enter()函數(shù)里做了什么事情:
private class TurningBleOnState extends BaseAdapterState {
@Override
public void enter() {
super.enter();
sendMessageDelayed(BLE_START_TIMEOUT, BLE_START_TIMEOUT_DELAY);
mAdapterService.bringUpBle();
}
}
先設(shè)置了4s超時時間,然后調(diào)用AdapterService的bringUpBle()函數(shù)。
那么接著回到AdapterService類中,看一下bringUpBle()函數(shù):
// 刪減了無關(guān)代碼
void bringUpBle() {
// 重置藍牙設(shè)備
mRemoteDevices.reset();
// 初始化藍牙相關(guān)屬性
mAdapterProperties.init(mRemoteDevices);
// 啟動藍牙綁定狀態(tài)機
mBondStateMachine = BondStateMachine.make(this, mAdapterProperties, mRemoteDevices);
// 初始化JNI回調(diào)類
mJniCallbacks.init(mBondStateMachine, mRemoteDevices);
try {
// 標(biāo)記重置藍牙Ble掃描的電池統(tǒng)計
mBatteryStats.noteResetBleScan();
} catch (RemoteException e) {
}
// 啟動Gatt協(xié)議服務(wù)
setProfileServiceState(GattService.class, BluetoothAdapter.STATE_ON);
}
在這個函數(shù)里頭,首先做了一系列初始化工作,然后啟動Gatt協(xié)議服務(wù),接著看setProfileServiceState()函數(shù):
private void setProfileServiceState(Class service, int state) {
Intent intent = new Intent(this, service);
intent.putExtra(EXTRA_ACTION, ACTION_SERVICE_STATE_CHANGED);
intent.putExtra(BluetoothAdapter.EXTRA_STATE, state);
startService(intent);
}
代碼很簡單,就是啟動GattService,告知GattService執(zhí)行ACTION_SERVICE_STATE_CHANGED相關(guān)操作。
在GattService父類ProfileService的onStartCommand()函數(shù)看到了對ACTION_SERVICE_STATE_CHANGEDaction的處理:
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
String action = intent.getStringExtra(AdapterService.EXTRA_ACTION);
if (AdapterService.ACTION_SERVICE_STATE_CHANGED.equals(action)) {
int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,BluetoothAdapter.ERROR);
if (state == BluetoothAdapter.STATE_OFF) {
doStop();
} else if (state == BluetoothAdapter.STATE_ON) {
doStart();
}
}
return PROFILE_SERVICE_MODE;
}
private void doStart() {
// 省略了其他代碼
mAdapterService.onProfileServiceStateChanged(this, BluetoothAdapter.STATE_ON);
}
在doStart()中調(diào)用start()方法啟動了一系列Manager,做了一些預(yù)處理,最后調(diào)用AdapterService的onProfileServiceStateChanged()方法。
private final AdapterServiceHandler mHandler = new AdapterServiceHandler();
public void onProfileServiceStateChanged(ProfileService profile, int state) {
// 只處理藍牙打開與關(guān)閉狀態(tài)
if (state != BluetoothAdapter.STATE_ON && state != BluetoothAdapter.STATE_OFF) {
throw new IllegalArgumentException(BluetoothAdapter.nameForState(state));
}
Message m = mHandler.obtainMessage(MESSAGE_PROFILE_SERVICE_STATE_CHANGED);
m.obj = profile;
m.arg1 = state;
mHandler.sendMessage(m);
}
向AdapterServiceHandler發(fā)送一條MESSAGE_PROFILE_SERVICE_STATE_CHANGED的消息,接著看AdapterServiceHandler的handlerMessage()方法。
class AdapterServiceHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_PROFILE_SERVICE_STATE_CHANGED:
processProfileServiceStateChanged((ProfileService) msg.obj, msg.arg1);
break;
}
}
private void processProfileServiceStateChanged(ProfileService profile, int state) {
switch (state) {
case BluetoothAdapter.STATE_ON:
mRunningProfiles.add(profile);
if (GattService.class.getSimpleName().equals(profile.getName())) {
//
enableNativeWithGuestFlag();
} else if (mRegisteredProfiles.size() == Config.getSupportedProfiles().length
&& mRegisteredProfiles.size() == mRunningProfiles.size()) {
mAdapterProperties.onBluetoothReady();
updateUuids();
setBluetoothClassFromConfig();
mAdapterStateMachine.sendMessage(AdapterState.BREDR_STARTED);
}
break;
}
}
}
}
這里的ProfileService指的就是GattService,因此進入enableNativeWithGuestFlag()函數(shù):
private void enableNativeWithGuestFlag() {
boolean isGuest = UserManager.get(this).isGuestUser();
if (!enableNative(isGuest)) {
Log.e(TAG, "enableNative() returned false");
}
}
native boolean enableNative(boolean startRestricted);
最終調(diào)用JNI的enableNative(),在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;
}
通過sBluetoothInterface->enable()方法去調(diào)用藍牙的底層驅(qū)動來實現(xiàn)藍牙的打開操作。那么sBluetoothInterface又是什么呢???它對應(yīng)的是bluetooth.cc,在bluetooth.cc中可以看到:
EXPORT_SYMBOL bt_interface_t bluetoothInterface = {
sizeof(bluetoothInterface),
init,
enable,
disable,
cleanup,
get_adapter_properties,
get_adapter_property,
set_adapter_property,
get_remote_device_properties,
get_remote_device_property,
set_remote_device_property,
get_remote_service_record,
get_remote_services,
start_discovery,
cancel_discovery,
create_bond,
create_bond_out_of_band,
remove_bond,
cancel_bond,
get_connection_state,
pin_reply,
ssp_reply,
get_profile_interface,
dut_mode_configure,
dut_mode_send,
le_test_mode,
set_os_callouts,
read_energy_info,
dump,
dumpMetrics,
config_clear,
interop_database_clear,
interop_database_add,
get_avrcp_service,
};
可以理解為導(dǎo)出對應(yīng)的內(nèi)核方法供其他模塊使用?;氐秸},看一下enable()方法:
static int enable(bool start_restricted) {
restricted_mode = start_restricted;
// 接口未就緒,返回未就緒的狀態(tài)碼
if (!interface_ready()) return BT_STATUS_NOT_READY;
stack_manager_get_interface()->start_up_stack_async();
return BT_STATUS_SUCCESS;
}
接著執(zhí)行stack_manager_get_interface()的start_up_stack_async(),stack_manager_get_interface()函數(shù)指的是stack_manager.cc,接著看:
static void start_up_stack_async(void) {
thread_post(management_thread, event_start_up_stack, NULL);
}
這里通過thread_post異步去執(zhí)行event_start_up_stack函數(shù):
// start_up過程是一個同步過程
static void event_start_up_stack(UNUSED_ATTR void* context) {
// 確保棧已經(jīng)初始化
ensure_stack_is_initialized();
// 加載配置文件
module_start_up(get_module(BTIF_CONFIG_MODULE));
// 執(zhí)行enable
bte_main_enable();
// 上一步的enable失敗
if (future_await(local_hack_future) != FUTURE_SUCCESS) {
stack_is_running = true;
event_shut_down_stack(NULL);
return;
}
stack_is_running = true;
// enable成功
btif_thread_post(event_signal_stack_up, NULL);
}
bte_main_enable()是在bte_main.cc中執(zhí)行的,具體的實現(xiàn)就不再深入。接下來讓我們看看成功的結(jié)果是如何返回到Java層的。
bte_main_enable()執(zhí)行成功之后,會在event_signal_stack_up()函數(shù)中執(zhí)行回掉,將BT_STATE_ON狀態(tài)通過HAL_CBACK函數(shù)回傳給adapter_state_changed_cb ()函數(shù) 。
static void event_signal_stack_up(UNUSED_ATTR void* context) {
// Notify BTIF connect queue that we've brought up the stack. It's
// now time to dispatch all the pending profile connect requests.
btif_queue_connect_next();
HAL_CBACK(bt_hal_cbacks, adapter_state_changed_cb, BT_STATE_ON);
}
函數(shù)adapter_state_changed_cb()對應(yīng)的是com_android_bluetooth_btservice_AdapterService.cpp中的adapter_state_change_callback()函數(shù)
static void adapter_state_change_callback(bt_state_t status) {
CallbackEnv sCallbackEnv(__func__);
if (!sCallbackEnv.valid()) return;
sCallbackEnv->CallVoidMethod(sJniCallbacksObj, method_stateChangeCallback, (jint)status);
}
這里有一個疑惑,stack_manager.cc中調(diào)用的adapter_state_changed_cb()函數(shù)是如何對應(yīng)到com_android_bluetooth_btservice_AdapterService.cpp中的adapter_state_change_callback()函數(shù)的????在bluetooth.h中看到了結(jié)構(gòu)體bt_callbacks_t中聲明:
typedef struct {
adapter_state_changed_callback adapter_state_changed_cb;
} bt_callbacks_t;
在com_android_bluetooth_btservice_AdapterService.cpp中創(chuàng)建了bt_callbacks_t對象。由于c/c++基礎(chǔ)不好,所以這部分很多都是個人的猜測。
static bt_callbacks_t sBluetoothCallbacks = {
adapter_state_change_callback
};
JNI層通過CallVoidMethod(xx, method_stateChangeCallback, BT_STATE_ON)去調(diào)用Java層AdapterService.java中的stateChangeCallback()函數(shù):
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");
}
}
返回的狀態(tài)是BT_STATE_ON,所以接著給狀態(tài)機AdapterState發(fā)送消息BLE_STARTED。
private class TurningBleOnState extends BaseAdapterState {
@Override
public boolean processMessage(Message msg) {
switch (msg.what) {
case BLE_STARTED:
transitionTo(mBleOnState);
break;
}
return true;
}
}
狀態(tài)機接收到該消息之后,將狀態(tài)切換成BleOnState。進入新的狀態(tài)之后,告知AdapterService更新到新的狀態(tài)。
@Override
public void enter() {
int currState = getStateValue();
mAdapterService.updateAdapterState(mPrevState, currState);
mPrevState = currState;
}
接著看AdapterService中是如何處理新狀態(tài)STATE_BLE_ON的:
void updateAdapterState(int prevState, int newState) {
mAdapterProperties.setState(newState);
if (mCallbacks != null) {
int n = mCallbacks.beginBroadcast();
for (int i = 0; i < n; i++) {
try {
mCallbacks.getBroadcastItem(i).onBluetoothStateChange(prevState, newState);
} catch (RemoteException e) {
debugLog("updateAdapterState() - Callback #" + i + " failed (" + e + ")");
}
}
mCallbacks.finishBroadcast();
}
}
AdapterService接收到新狀態(tài)之后,通過AIDL回調(diào)給BluetoothManagerService,接著看BluetoothManagerService是如何處理回調(diào)的:
private final IBluetoothCallback mBluetoothCallback = new IBluetoothCallback.Stub() {
@Override
public void onBluetoothStateChange(int prevState, int newState) throws RemoteException {
Message msg =
mHandler.obtainMessage(MESSAGE_BLUETOOTH_STATE_CHANGE, prevState, newState);
mHandler.sendMessage(msg);
}
};
跟調(diào)用enable()的時候一樣,同樣是交給BluetoothHandler去處理:
// 省略了很多非核心代碼
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_BLUETOOTH_STATE_CHANGE: {
int prevState = msg.arg1;
int newState = msg.arg2;
mState = newState;
bluetoothStateChangeHandler(prevState, newState);
}
}
private void bluetoothStateChangeHandler(int prevState, int newState) {
if (newState == BluetoothAdapter.STATE_BLE_ON || newState == BluetoothAdapter.STATE_OFF) {
boolean intermediate_off = (prevState == BluetoothAdapter.STATE_TURNING_OFF
&& newState == BluetoothAdapter.STATE_BLE_ON);
if (!intermediate_off) {
if (mBluetoothGatt != null || !mContext.getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
continueFromBleOnState();
}
sendBleStateChanged(prevState, newState);
}
}
private void continueFromBleOnState() {
try {
mBluetoothLock.readLock().lock();
if (isBluetoothPersistedStateOnBluetooth() || !isBleAppPresent()) {
// mBluetooth指的是AdapterService
mBluetooth.onLeServiceUp();
persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
}
} catch (RemoteException e) {
Slog.e(TAG, "Unable to call onServiceUp", e);
} finally {
mBluetoothLock.readLock().unlock();
}
}
BluetoothHandler獲取到STATE_BLE_ON的狀態(tài)信息之后,會繼續(xù)通過AIDL讓AdapterService將狀態(tài)切換成OnState
@Override
public void onLeServiceUp() {
AdapterService service = getService();
if (service == null) {
return;
}
service.onLeServiceUp();
}
void onLeServiceUp() {
mAdapterStateMachine.sendMessage(AdapterState.USER_TURN_ON);
}
接著又回到狀態(tài)機中切換狀態(tài),實現(xiàn)的代碼很簡單跟之前的狀態(tài)切換類似,這就不再分析,最終BluetoothHandler會通過AIDL回調(diào)給BluetoothAdapter,最后會執(zhí)行BluetoothStateChangeCallback的onBluetoothStateChange(boolean on)函數(shù),但是這個回調(diào)接口被@hide了,因此我們無法監(jiān)聽此回調(diào)。
整個enable()過程就分析到這了,可能很多都沒有分析到位,或者存在錯誤,后期再優(yōu)化。