最近在作藍牙開發,研究了一下藍牙的啓動流程,總結一下java
Google在Android源碼中推出了它和博通公司一塊兒開發的BlueDroid以替代BlueZ。BlueZ的創始者,高通公司也將在基於其芯片的Android參考設計中去除BlueZ,支持BlueDroid。相比BlueZ,BlueDroid最值得稱道的地方就是其框架結構變得更爲簡潔和清晰。對咱們工程師來講這也是個不錯的福利,清晰、簡潔的架構使咱們在debug過程當中思路更清晰;android
藍牙的整體流程圖bash
從流程圖咱們能夠看出來 藍牙應用經過binder和系統藍牙Service進行通信 ,而後經過Jin與藍牙HAL層進行通信.架構
按層級劃分app
Bluetooth Service(Java層)代碼路徑框架
frameworks/base/core/java/Android/Bluetooth:
Bluetooth 應用層代碼路徑async
packages/apps/Bluetooth
Bluetooth協議層代碼ide
system/bt/
涉及的總共路徑:ui
frameworks/base/core/java/android/bluetooth/BluetoothAdapter.java frameworks/base/core/java/android/bluetooth/BluetoothManagerService.java packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterService.java packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterState.java packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterService.cpp system/bt/btif/src/btif_dm.c system/bt/btif/include/btif_common.h hardware/libhardware/include/hardware/bluetooth.h
一.將藍牙做爲sink模式 配置
sink模式通常是車機端須要設置的模式,用於連接手機以後能夠播放藍牙音樂,獲取聯繫人,和電話控制等等
packages/apps/Bluetooth/src/com/android/bluetooth/btservice/Config.java 有以下兩個參數控制是不是 sink端 boolean isA2dpSinkEnabled = SystemProperties.getBoolean("persist.service.bt.a2dp.sink", false); boolean isHfpClientEnabled = SystemProperties.getBoolean("persist.service.bt.hfp.client",false);
咱們須要在編譯源碼的時候去配置成sink模式
device/qcom/msmxxx_64/system.prop 添加以下配置 persist.service.bt.a2dp.sink=true persist.service.bt.hfp.client=true
再具體的配置信息在以下配置中進行設置具體支持那種profile
packages/apps/Bluetooth/res/values/config.xml
<resources> <bool name="profile_supported_a2dp">true</bool> <bool name="profile_supported_a2dp_sink">false</bool> <bool name="profile_supported_hdp">true</bool> <bool name="profile_supported_hs_hfp">true</bool> <bool name="profile_supported_hfpclient">false</bool> <bool name="profile_supported_hid">true</bool> <bool name="profile_supported_opp">true</bool> <bool name="profile_supported_pan">true</bool> <bool name="profile_supported_pbap">true</bool> <bool name="profile_supported_gatt">true</bool> <bool name="pbap_include_photos_in_vcard">true</bool> <bool name="pbap_use_profile_for_owner_vcard">true</bool> <bool name="profile_supported_map">true</bool> <bool name="profile_supported_avrcp_controller">false</bool> <bool name="profile_supported_sap">false</bool> <bool name="profile_supported_pbapclient">false</bool> <bool name="strict_location_check">true</bool> </resources>
固然修改上面的配置咱們能夠在以下路徑配置
vendor/qcom/opensource/bluetooth/res/values/config.xml
<resources> <bool name="profile_supported_ftp">true</bool> <bool name="profile_supported_map">false</bool> <bool name="profile_supported_sap">true</bool> <bool name="profile_supported_dun">true</bool> </resources>
若是 packages/apps/Bluetooth/res/values/config.xml 和 vendor/qcom/opensource/bluetooth/res/values/config.xml 都配置了以下配置 或者是配置的兩個Boolean 值是反向的,系統會依據 vendor/qcom/opensource/bluetooth/res/values/config.xml 配置爲最終結果,配置完成以後編譯系統,燒錄系統就能夠做爲sink端使用,也就是接收端.
二.啓動流程分析
首先咱們調用藍牙的時候使用的是Bluetooth的 BluetoothAdapter.java 類 中的enable方法
路徑以下
frameworks/base/core/java/android/bluetooth/BluetoothAdapter.java
public boolean enable() { android.util.SeempLog.record(56); if (isEnabled()) { if (DBG) Log.d(TAG, "enable(): BT already enabled!"); return true; } try { // 此處調用的是 IBluetoothManager.java的 enable return mManagerService.enable(ActivityThread.currentPackageName()); } catch (RemoteException e) {Log.e(TAG, "", e);} return false; }
咱們查看到 IBluetoothManager.java的實現類是BluetoothManagerService.java , BluetoothManagerService.java
class BluetoothManagerService extends IBluetoothManager.Stub { .....省略代碼..... public boolean enable(String packageName) throws RemoteException { final int callingUid = Binder.getCallingUid(); final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; .....省略代碼..... // 權限檢查 .....省略代碼..... synchronized(mReceiver) { mQuietEnableExternal = false; mEnableExternal = true; // waive WRITE_SECURE_SETTINGS permission check sendEnableMsg(false, packageName); } if (DBG) Slog.d(TAG, "enable returning"); return true; } .....省略代碼..... }
咱們繼續查看能夠看到調用的是 sendEnableMsg(boolean quietMode, String packageName) 方法.
private void sendEnableMsg(boolean quietMode, String packageName) { mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, quietMode ? 1 : 0, 0)); addActiveLog(packageName, true); }
在sendEnableMsg 方法中 發送了一個message消息 MESSAGE_ENABLE
case MESSAGE_ENABLE: try { if (mBluetooth != null) { int state = mBluetooth.getState(); if (state == BluetoothAdapter.STATE_BLE_ON) { //若是藍牙已經打開調用 BluetoothAdapterService.java 開啓profile mBluetooth.onLeServiceUp(); //保存藍牙的開關狀態 persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); break; } } } mQuietEnable = (msg.arg1 == 1); //若是沒有藍牙沒有打開去打開藍牙 if (mBluetooth == null) { handleEnable(mQuietEnable); } else { if(state == BluetoothAdapter.STATE_TURNING_OFF || state == BluetoothAdapter.STATE_BLE_TURNING_OFF) waitForMonitoredOnOff(false, true); //重啓藍牙 Message restartMsg = mHandler.obtainMessage( MESSAGE_RESTART_BLUETOOTH_SERVICE); mHandler.sendMessageDelayed(restartMsg, 2 * SERVICE_RESTART_TIME_MS); } break;
在 MESSAGE_ENABLE 接收的消息中會先判斷盤牙是否打開,若是已經打開 就調用mBluetooth.onLeServiceUp();去打開 Profile文件若是沒有打開就調用handleEnable(mQuietEnable);去打開藍牙. 我們這裏先不看 mBluetooth.onLeServiceUp(); 方法先查看handleEnable(mQuietEnable)
private void handleEnable(boolean quietMode) { if ((mBluetooth == null) && (!mBinding)) { //藍牙打開超時記錄 Message timeoutMsg=mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND); mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS); Intent i = new Intent(IBluetooth.class.getName()); //此處咱們查看到 mConnection 方法是連接狀態的回調 if (!doBind(i, mConnection,Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, UserHandle.CURRENT)) { mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); } else { mBinding = true; } } }
其中mConnection 是連接的回調 BluetoothServiceConnection 就是 mConnection 類
在BluetoothServiceConnection 類中會發送 MESSAGE_BLUETOOTH_SERVICE_CONNECTED 消息並傳遞了一個 AdapterService對象.
private class BluetoothServiceConnection implements ServiceConnection { public void onServiceConnected(ComponentName componentName, IBinder service) { String name = componentName.getClassName(); if (DBG) Slog.d(TAG, "BluetoothServiceConnection: " + name); Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_CONNECTED); if (name.equals("com.android.bluetooth.btservice.AdapterService")) { msg.arg1 = SERVICE_IBLUETOOTH; } msg.obj = service; mHandler.sendMessage(msg); } public void onServiceDisconnected(ComponentName componentName) { // Called if we unexpectedly disconnect. String name = componentName.getClassName(); if (DBG) Slog.d(TAG, "BluetoothServiceConnection, disconnected: " + name); Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED); if (name.equals("com.android.bluetooth.btservice.AdapterService")) { msg.arg1 = SERVICE_IBLUETOOTH; } mHandler.sendMessage(msg); } }
咱們繼續追蹤 MESSAGE_BLUETOOTH_SERVICE_CONNECTED消息
case MESSAGE_BLUETOOTH_SERVICE_CONNECTED: { IBinder service = (IBinder) msg.obj; mBinding = false; mBluetoothBinder = service; mBluetooth = IBluetooth.Stub.asInterface(service); //註冊 CallBack 重要,後面的回調要使用 try { mBluetooth.registerCallback(mBluetoothCallback); } catch (RemoteException re) { Slog.e(TAG, "Unable to register BluetoothCallback",re); } //Do enable request try { //打開藍牙請求 if (mQuietEnable == false) { if (!mBluetooth.enable()) { Slog.e(TAG,"IBluetooth.enable() returned false"); } } } break; }
MESSAGE_BLUETOOTH_SERVICE_CONNECTED消息裏面能夠查看到 mBluetooth = IBluetooth.Stub.asInterface(service);獲取的是 IBluetooth 對象 , 而AdapterService.java 內部類 AdapterServiceBinder 實現了 IBluetooth
packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterService.java
private static class AdapterServiceBinder extends IBluetooth.Stub { private AdapterService mService; public AdapterService getService() { if (mService != null && mService.isAvailable()) { return mService; } return null; } public boolean enable() { ........ AdapterService service = getService(); if (service == null) return false; return service.enable(); } }
由上面能夠看出 return service.enable();調用的是 AdapterService.java 中的方法 enable() 方法
public synchronized boolean enable(boolean quietMode) { enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); 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; }
發送的是 BLE_TURN_ON
packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterState.java 接受了這個消息
case BLE_TURN_ON: notifyAdapterStateChange(BluetoothAdapter.STATE_BLE_TURNING_ON); //將藍牙的狀態轉換成 mPendingCommandState mPendingCommandState.setBleTurningOn(true); transitionTo(mPendingCommandState); sendMessageDelayed(BLE_START_TIMEOUT, BLE_START_TIMEOUT_DELAY); adapterService.BleOnProcessStart(); break;
將了藍牙的狀態轉換成 mPendingCommandState 調用 BleOnProcessStart 方法,也能夠在supportedProfileServices 方法中去掉本身不想開啓的ProfileService.
void BleOnProcessStart() { //獲取支持的profile 文件 Class[] supportedProfileServices = Config.getSupportedProfiles(); //Initialize data objects for (int i=0; i < supportedProfileServices.length;i++) { mProfileServicesState.put(supportedProfileServices[i].getName(),BluetoothAdapter.STATE_OFF); } mRemoteDevices.cleanup(); mAdapterProperties.init(mRemoteDevices); mJniCallbacks.init(mBondStateMachine,mRemoteDevices); //Start Gatt service //調用 ProfileService setGattProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_ON); }
獲取支持的ProfileService列表.
private static final Class[] PROFILE_SERVICES = { HeadsetService.class, A2dpService.class, A2dpSinkService.class, HidService.class, HealthService.class, PanService.class, GattService.class, BluetoothMapService.class, HeadsetClientService.class, AvrcpControllerService.class, SapService.class, PbapClientService.class };
//發送 ACTION_SERVICE_STATE_CHANGED參數 每個profile 都有 遍歷開啓 profile
private void setGattProfileServiceState(Class[] services, int state) { for (int i=0; i <services.length;i++) { mProfileServicesState.put(serviceName,pendingState); Intent intent = new Intent(this,services[i]); intent.putExtra(EXTRA_ACTION,ACTION_SERVICE_STATE_CHANGED); intent.putExtra(BluetoothAdapter.EXTRA_STATE,state); startService(intent); return; } } }
public int onStartCommand(Intent intent, int flags, int startId) { if (intent == null) { Log.d(mName, "Restarting profile service..."); return PROFILE_SERVICE_MODE; } else { String action = intent.getStringExtra(AdapterService.EXTRA_ACTION); if (AdapterService.ACTION_SERVICE_STATE_CHANGED.equals(action)) { } else if (state == BluetoothAdapter.STATE_ON) { ........省略代碼...... // 開啓服務 doStart(intent); } } return PROFILE_SERVICE_MODE; }
調用doStartService以後 咱們能夠看到調用了 notifyProfileServiceStateChanged 方法。
private void doStart(Intent intent) { if (!mStartError) { // 開始調用 notifyProfileServiceStateChanged notifyProfileServiceStateChanged(BluetoothAdapter.STATE_ON); } }
繼續查看notifyProfileServiceStateChanged 方法 ,裏面又回到了AdapterServer 中的 onProfileServiceStateChanged方法
protected void notifyProfileServiceStateChanged(int state) { //Notify adapter service AdapterService adapterService = AdapterService.getAdapterService(); if (adapterService != null) { adapterService.onProfileServiceStateChanged(getClass().getName(), state); } }
發送MESSAGE_PROFILE_SERVICE_STATE_CHANGED 消息 給消息處理
public void onProfileServiceStateChanged(String serviceName, int state) { Message m = mHandler.obtainMessage(MESSAGE_PROFILE_SERVICE_STATE_CHANGED); m.obj=serviceName; m.arg1 = state; mHandler.sendMessage(m); }
在消息接收的地方查看到藍牙的 processProfileServiceStateChanged 方法被調用,在processProfileServiceStateChanged 方法中發送了 BLE_STARTED 消息,而這個消息接受的地方是開起底層ProfileService的地方。
case MESSAGE_PROFILE_SERVICE_STATE_CHANGED: { debugLog("handleMessage() - MESSAGE_PROFILE_SERVICE_STATE_CHANGED"); processProfileServiceStateChanged((String) msg.obj, msg.arg1); } break;
private void processProfileServiceStateChanged(String serviceName, int state) { if (isBleTurningOn) { if (serviceName.equals("com.android.bluetooth.gatt.GattService")) { debugLog("GattService is started"); mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.BLE_STARTED)); return; } } }
/packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterState.java BLE_STARTED消息處理任務,經過 adapterService.enableNative(isGuest) 開啓底層的profileService。
case BLE_STARTED: //開啓底層服務 if (!adapterService.enableNative(isGuest)) { errorLog("Error while turning Bluetooth on"); notifyAdapterStateChange(BluetoothAdapter.STATE_OFF); transitionTo(mOffState); } break;
調用的是 AdapterService.java 中的native方法 ,根據包名和JNI 方法的名稱咱們能夠推算出來調用的CPP的名稱是 com_android_bluetooth_btservice_AdapterService.cpp
/*package*/ native boolean enableNative(boolean startRestricted);
在以下路徑找到了 packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterService.cpp 在enableNative中查看到 int ret = sBluetoothInterface->enable(isGuest == JNI_TRUE ? 1 : 0); 調用的是 sBluetoothInterface 中的enable方法
static jboolean enableNative(JNIEnv* env, jobject obj, jboolean isGuest) { ALOGV("%s:",__FUNCTION__); jboolean result = JNI_FALSE; if (!sBluetoothInterface) return result; int ret = sBluetoothInterface->enable(isGuest == JNI_TRUE ? 1 : 0); result = (ret == BT_STATUS_SUCCESS || ret == BT_STATUS_DONE) ? JNI_TRUE : JNI_FALSE; return result; }
具體的實如今 bluetooth.c中。
/system/bt/btif/src/bluetooth.c
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; }
底層回調傳遞到上層的時候主要使用的是 btif_dm.c 中對消息的處理 BTA_DM_INQ_RES_EVT 消息
system/bt/btif/src/btif_dm.c
static void btif_dm_search_devices_evt (UINT16 event, char *p_param) { ...省略代碼..... case BTA_DM_INQ_RES_EVT: ...省略代碼..... /* Callback to notify upper layer of device */ HAL_CBACK(bt_hal_cbacks, device_found_cb, num_properties, properties); break;
/system/bt/btif/include/btif_common.h
define HAL_CBACK(P_CB, P_CBACK, ...) 方法 , HAL_CBACK就是一宏定義,就是調用結構體中對應的方法
extern bt_callbacks_t *bt_hal_cbacks; #define HAL_CBACK(P_CB, P_CBACK, ...)\ if (P_CB && P_CB->P_CBACK) { \ BTIF_TRACE_API("HAL %s->%s", #P_CB, #P_CBACK); \ P_CB->P_CBACK(__VA_ARGS__); \ } \ else { \ ASSERTC(0, "Callback is NULL", 0); \ }
bt_hal_cbacks 其實就是 藍牙AdapterService中調用了initNative方法傳入到底層的。看下jni中的initNative方法:
@Override public void onCreate() { super.onCreate(); .......... //調用底層方法 initNative(); ........ } private native boolean initNative();
調用com_android_bluetooth_btservice_AdapterService.cpp init方法 將Callback傳遞到底層
static bool initNative(JNIEnv* env, jobject obj) { ....... //調用com_android_bluetooth_btservice_AdapterService.cpp init方法 將Callback傳遞到底層 // 再調用 bluetooth.c 的 init方法 int ret = sBluetoothInterface->init(&sBluetoothCallbacks); ....... }
com_android_bluetooth_btservice_AdapterService.cpp 再調用 bluetooth.c 的 init方法
static int init(bt_callbacks_t *callbacks) { CallBack傳遞到底層 bt_hal_cbacks = callbacks; stack_manager_get_interface()->init_stack(); }
其實這裏有兩個地方有 bt_callbacks_t 咱們能夠對比看一下
1./hardware/libhardware/include/hardware/bluetooth.h
2. /packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterService.cpp
bluetooth.h 中的 bt_callbacks_t typedef struct { /** set to sizeof(bt_callbacks_t) */ size_t size; adapter_state_changed_callback adapter_state_changed_cb; adapter_properties_callback adapter_properties_cb; remote_device_properties_callback remote_device_properties_cb; device_found_callback device_found_cb; discovery_state_changed_callback discovery_state_changed_cb; pin_request_callback pin_request_cb; ssp_request_callback ssp_request_cb; bond_state_changed_callback bond_state_changed_cb; acl_state_changed_callback acl_state_changed_cb; callback_thread_event thread_evt_cb; dut_mode_recv_callback dut_mode_recv_cb; le_test_mode_callback le_test_mode_cb; energy_info_callback energy_info_cb; } bt_callbacks_t; // com_android_bluetooth_btservice_AdapterService.cpp 中的 bt_callbacks_t static bt_callbacks_t sBluetoothCallbacks = { sizeof(sBluetoothCallbacks), adapter_state_change_callback, adapter_properties_callback, remote_device_properties_callback, device_found_callback, discovery_state_changed_callback, pin_request_callback, ssp_request_callback, bond_state_changed_callback, acl_state_changed_callback, callback_thread_event, dut_mode_recv_callback, le_test_mode_recv_callback, energy_info_recv_callback };
static bt_callbacks_t sBluetoothCallbacks = { sizeof(sBluetoothCallbacks), adapter_state_change_callback, adapter_properties_callback, remote_device_properties_callback, device_found_callback, discovery_state_changed_callback, pin_request_callback, ssp_request_callback, bond_state_changed_callback, acl_state_changed_callback, callback_thread_event, dut_mode_recv_callback, le_test_mode_recv_callback, energy_info_recv_callback };
最後藍牙驅動打開以後會經過
/system/bt/btif/src/btif_core.c 中的 btif_enable_bluetooth_evt(tBTA_STATUS status) 回調給應用
void btif_enable_bluetooth_evt(tBTA_STATUS status){ // 省略代碼 HAL_CBACK(bt_hal_cbacks, adapter_properties_cb, BT_STATUS_SUCCESS, 1, &prop); }
而後回調給 adapter_properties_callback:返回手機藍牙設備的地址、名稱、UUID
adapter_state_change_callback 回調 經過 C調用 Java的代碼 callbackEnv->CallVoidMethod(sJniCallbacksObj, method_stateChangeCallback, (jint)status); 返回給應用中的也就是回調java層代碼 JniCallback.java文件中stateChangeCallback方法。這時跳轉到AdapterState.java中,執行stateChangeCallback()方法;發送了ENABLED_READY消息。根據以上分析,這時狀態機還處於PendingCommandState,在該狀態下處理ENABLED_READY消息,
case ENABLED_READY: removeMessages(ENABLE_TIMEOUT); mPendingCommandState.setBleTurningOn(false); transitionTo(mBleOnState); notifyAdapterStateChange(BluetoothAdapter.STATE_BLE_ON); break;
作下面兩個動做:狀態切換到mOnState;更新adapterProperties中的藍牙狀態信息;通知藍牙狀態變爲打開。具體看下notifyAdapterStateChange方法。主要是調用了adapterService類的方法。
private void notifyAdapterStateChange(int newState) { AdapterService adapterService = mAdapterService; AdapterProperties adapterProperties = mAdapterProperties; if ((adapterService == null) || (adapterProperties == null)) { errorLog("notifyAdapterStateChange after cleanup:" + newState); return; } int oldState = adapterProperties.getState(); adapterProperties.setState(newState); infoLog("Bluetooth adapter state changed: " + oldState + "-> " + newState); adapterService.updateAdapterState(oldState, newState); }
adapterService.updateAdapterState(oldState, newState);
來到adapterService類。
void updateAdapterState(int prevState, int newState){ if (mCallbacks !=null) { int n=mCallbacks.beginBroadcast(); debugLog("updateAdapterState() - Broadcasting state to " + n + " receivers."); 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(); } }
以前在打開藍牙操做初期,在BluetoothManagerService中註冊了回調方法,所以又跳轉到framework中,執行回調方法。藍牙打開從framework公共接口開始調用enable方法,執行到bluetooth.apk中,在該應用中經過jni註冊回調方法和調用hal層打開藍牙方法,在驅動層完成藍牙上電等操做後,經過hal-jni回調到應用層中,應用經過aidl回調通知framework藍牙狀態變化,framework發送廣播通知你們藍牙打開。