BTIF: Bluetooth Interface
BTU : Bluetooth Upper Layer
BTM: Bluetooth Manager
BTE: Bluetooth embedded system
BTA :Blueetooth application layer
CO: call out\CI: call in
HF : Handsfree Profile
HH: HID Host Profile
HL: Health Device Profile
AV:audio\vidio
ag: audio gateway
ar: audio/video registration
gattc: GATT client
BLE: Bluetooth Low Energyjava
再把左邊的部分展開來看:
再把它攤開來看:
代碼分佈:
frameworks/base/core/Java/Android/Bluetooth:
frameworks/base/services/java/com/android/server/BluetoothManagerService.java:
裏面提供java層使用的一些類和一些aidl文件,供其餘進程調用。打開和關閉藍牙的公共接口也在這裏面。
packages/apps/Bluetooth:對應Bluetooth.apk,做爲系統的藍牙的核心進程而存在,com.android.bluetooth,調用framework的打開藍牙接口後會啓動該進程。其內部實現了多種上層藍牙模式:opp,hfp,a2dp,hdp,hid等,並經過JNI調用與hal層完成聯繫。
/hardware/libhardware/include/hardware/bluetooth.h: hal層接口頭文件
external/bluetooth/bluedroid:bluedroid官方協議棧
packages/apps/Settings/src/com/android/settings/Bluetooth: setting中藍牙部分,界面相關
bluedroid藍牙的調用方式:從apk到framework,framework再經過binder調用bluetooth應用,在經過應用層利用jni調用hal層實現藍牙的各類請求。android
Core Specification(核心規範),用於規定藍牙設備必須實現的通用功能和協議層次。它由軟件和硬件模塊組成,兩個模塊之間的信息和數據經過主機控制接口(HCI)的解釋才能進行傳遞。app
Profiles(藍牙應用規範),它從應用場景的角度爲藍牙技術的使用制定了不一樣的規範。這也是和大衆平常生活接觸最多的一部分。藍牙支持不少Profiles,下文將介紹幾種使用最普遍的藍牙應用規範異步
OPP:文件傳輸規範
hfp:和電話相關,接聽、掛斷電話,以及鏈接sco通路
a2dp:藍牙立體聲規範,其中包含avrcp規範,avrcp規範實現了聽歌時暫停、上下歌曲選擇等控制模式。目前藍牙耳機通常都支持這兩種規範。
hid:人機交互規範,藍牙鼠標鍵盤等
phap:電話號碼簿訪問協議
hdp:藍牙醫療相關規範ide
文件路徑:
frameworks/base/core/java/android/bluetooth/BluetoothAdapter.java
frameworks/base/services/java/com/android/server/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
hardware/libhardware/include/hardware/bluetooth.h
external/bluetooth/bluedroid/btif/src/bluetooth.c函數
先從framework提供的公共接口開始:
打開藍牙使用BluetoothAdapter.java提供的方法getDefaultAdapter(),該方法中先獲取BluetoothManagerService.java提供的binder對象,而且用該對象建立BluetoothAdapter實例。
獲取到BluetoothAdapter實例用,調用enable方法,BluetoothAdapter的enable方法會調用BluetoothManagerService.java的enable,直接看BluetoothManagerService.java,在其中enable方法會啓動一個service,這個service就是AdapterService。在啓動這個service以後,先不看這個service的具體動做,繼續看BluetoothManagerService會作什麼。
在啓動這個AdapterService以後,先不看這個AdapterService的具體動做,繼續看BluetoothManagerService中的執行流程。在啓動AdapterService,會回調mConnection的onServiceConnected()方法,在該方法中發送MESSAGE_BLUETOOTH_SERVICE_CONNECTED 消息,在處理該消息時,作了下面三件事:
一、獲得AdapterService返回的IBluetooth.aidl接口的實現類。
mBluetooth = IBluetooth.Stub.asInterface(service)
2.調用IBluetooth.aidl提供的接口註冊AdapterService的回調方法。
這樣,不只BluetoothManagerService能夠經過aidl調用AdapterService中的方法,也實現了AdapterService能夠回調BluetoothManagerService中的方法。回調方法以下所示,記住這個回調方法,後面會講到。
mBluetooth.registerCallback(mBluetoothCallback)
三、第三件事就是調用IBluetooth.aidl提供的enable方法。下面就進入到AdapterService.java中。編碼
下面就進入了package/apps下:
首先看onBind方法,返回了一個對象mBinder。執行其中的enable方法,
調用mAdapterStateMachine的sendMessage方法,發送USER_TURN_ON消息。。AdapterState.java是一個狀態機,有如下幾種狀態:
mOffState:關閉
mPendingCommandState:活動,打開中
mOnState:打開
初始狀態是mOffState。spa
發送消息後,在OffState狀態下處理消息,首先切換狀態到mPendingCommandState,而後調用adapterService.processStart()方法。
繼續回到adapterService。執行以下代碼,啓動手機支持的全部profile,
手機支持的全部profile以下:
挨個啓動上面全部的服務。每一個服務啓動以後都會調用adapterService中的notifyProfileServiceStateChanged方法。該方法中發送MESSAGE_PROFILE_SERVICE_STATE_CHANGED消息。消息處理以下:
若是全部服務都起來以後,給狀態機AdapterState發送消息AdapterState.STARTED。
根據以上流程,如今狀態機在mPendingCommandState狀態,在該狀態下處理STARTED消息。代碼以下:
終於看到native方法。
對應的native方法在com_android_bluetooth_btservice_AdapterService.cpp中。調用了sBluetoothInterface結構體中的enable方法。該結構體的定義在bluetooth.h中,具體實如今bluetooth.c中。後面的代碼這裏不作具體分析。
.net
回調主要使用
HAL_CBACK(bt_hal_cbacks, device_found_cb, num_properties, properties); HAL_CBACK就是一宏定義,就是調用結構體中對應的方法。
這裏重點看一下一個bt_callbacks_t結構體,定義在bluetooth.h中,以下
初始化在bluetooth.c中,初始化的流程。code
回到AdapterService.java,在服務啓動時調用了initNative方法。看下jni中的initNative方法:
仍是sBluetoothInterface結構體,繼續看bluetooth.c文件,能夠看到init方法中將地址sBluetoothCallbacks賦值給bt_callbacks_t,也就是,回調結構體的地址指向了sBluetoothCallbacks,看下sBluetoothCallbacks的定義。任然在jni中定義。這樣在啓動AdapterService時將回調地址傳入了hal層。
最後,在驅動層完成藍牙打開以後,會執行如下兩個回調方法:
adapter_properties_callback:返回手機藍牙設備的地址、名稱、UUID等。
adapter_state_change_callback:更新AdapterProperties中藍牙狀態,發送廣播通知藍牙狀態變化。
具體分析下adapter_state_change_callback。對應的jni方法爲:adapter_state_change_callback,方法執行如下方法。
callbackEnv->CallVoidMethod(sJniCallbacksObj, method_stateChangeCallback, (jint)status);
也就是回調java層代碼:JniCallback.java文件中stateChangeCallback方法。這時跳轉到AdapterState.java中,執行stateChangeCallback()方法;發送了ENABLED_READY消息。根據以上分析,這時狀態機還處於PendingCommandState,在該狀態下處理ENABLED_READY消息,
作下面兩個動做:狀態切換到mOnState;更新adapterProperties中的藍牙狀態信息;通知藍牙狀態變爲打開。具體看下notifyAdapterStateChange方法。主要是調用了adapterService類的方法。
adapterService.updateAdapterState(oldState, newState);
來到adapterService類。
能夠看到,看是執行該服務中註冊的回調方法。應該還能記得,以前在打開藍牙操做初期,在BluetoothManagerService中註冊了回調方法。所以又跳轉到framework中,執行回調方法。在該回調方法中,發送廣播通知藍牙狀態變化。
藍牙打開的流程到這裏,藍牙打開從framework公共接口開始調用enable方法,執行到bluetooth.apk中,在該應用中經過jni註冊回調方法和調用hal層打開藍牙方法,在驅動層完成藍牙上電等操做後,經過hal-jni回調到應用層中,應用經過aidl回調通知framework藍牙狀態變化,framework發送廣播通知你們藍牙打開。
packages/apps/Bluetooth/src/com/android/bluetooth/btservice/RemoteDevices.java
packages/apps/Settings/src/com/android/settings/Bluetooth/*
BluetoothSettings.java中的startScanning命令,開始搜索。
若是a2dp沒有在播放,就調用BluetoothAdapter.java中的startDiscovery()方法。
而後又回到AdapterService中,調用startDiscovery方法。在該方法中直接進入到jni層。
在jni層的函數中執行以下語句,依然是該結構體。
int ret = sBluetoothInterface->start_discovery();
具體的底層搜索方法暫不往下追蹤。驅動層完成搜索以後,返回狀態,根據返回的消息進行處理。回調消息分以下幾種:包括搜索結果返回消息、搜索完成消息、搜索取消等。
BTA_DM_INQ_RES_EVT
BTA_DM_INQ_CMPL_EVT
BTA_DM_DISC_RES_EVT
BTA_DM_DISC_BLE_RES_EVT
BTA_DM_DISC_CMPL_EVT
BTA_DM_DI_DISC_CMPL_EVT
BTA_DM_SEARCH_CANCEL_CMPL_EVT
當收到搜索結果放回消息以後,會執行如下回調方法。
其中後面兩個參數:設備屬性個數和設備屬性。其中設備屬性包括:地址、名稱、信號強度等屬性。根據上面所講的回調方法初始化,直接找到jni層的對應回調方法,能夠看到會前後調用如下兩個方法。
其中devicePropertyChangedCallback方法更新RemoteDevice類中的變量值。
deviceFoundCallback方法發送BluetoothDevice.ACTION_FOUND廣播,通知setting中要更新界面顯示該設備。
packages/apps/Settings/src/com/android/settings/Bluetooth/*
packages/apps/Bluetooth/src/com/android/bluetooth/btservice/ BondStateMachine.java
packages/apps/Settings/src/com/android/settings/Bluetooth/BluetoothEventManager.java
packages/apps/Settings/src/com/android/settings/Bluetooth/CachedBluetoothDevice.java
在setting中點擊設備以後開始進行配對。調用BluetoothDevice的createBond方法,走到AdapterService.java中的createBond方法。驅動BondStateMachine中的狀態從StableState到
PendingCommandState。而後調用jni層createBondNative方法。又來到hal層接口sBluetoothInterface:
sBluetoothInterface->create_bond((bt_bdaddr_t *)addr);
一樣,在底層完成配對以後進行回調:
找到對應的回調方法,JniCallback.java中的
void bondStateChangeCallback(int status, byte[] address, int newState) {
mBondStateMachine.bondStateChangeCallback(status, address, newState);
}
只有opp的彈框是bluetooth裏,其餘都是setting中彈框。
點擊用藍牙分享文件後,會調用BluetoothOppLauncherActivity.java,其中會判斷當前藍牙是否打開,若是沒打開則進入BluetoothOppBtEnableActivity.java打開藍牙,若是已經打開,則直接進入BluetoothDevicePicker.java選擇傳輸文件設備選擇。
藍牙開啓後會啓動BluetoothMapService.java
在BluetoothMapService.java調用了BluetoothMapMasInstance.java的startRfcommSocketListener()方法,監聽rfcomm端的鏈接請求,若是有鏈接請求,調用BluetoothMapService 的 onConnect()方法,在該方法裏發送廣播到setting中,setting彈框,用戶確認後發送廣播ACTION_CONNECTION_ACCESS_REPLY通知BluetoothMapService,BluetoothMapService收到廣播後調用onConnectHandler方法,調用startObexServerSession方法,啓動Obex傳輸通道。
手機側主動改變狀態。註冊了一個RemoteControllerWeak(RemoteController),當手機端的播放器暫停、快進、快退、切歌等操做後,會調用遠程控制接口更新播放狀態、歌曲信息。mTrackChangedNT、mPlayStatusChangedNT、mPlayPosChangedNT三個變量的值決定是否會通知對端進行同步;這三個值有jni回調改變,即對端回調改變。
對端主動改變狀態:1)快進、快退底層有回調handlePassthroughCmd,來通知avrcp實時更新進度條,並同步給對端。部分車載會上報快進、快退的keycode給手機端,播放器利用RemoteController更新狀態。2)播放、暫停,對端上報keycode,播放器RemoteController控制avrcp中狀態切換
相似map,鏈接後彈框都是廣播給setting彈框
以前的audiopath比較複雜,要到DSP裏面去硬解碼。如今比較簡單了,從驅動角度看,收到AF寫下來的PCM數據後,經協議棧SBC編碼後經HCI接口寫入到藍牙芯片,而後就發出去了。 SBC編碼是針對藍牙設備的一種音頻編碼方式,壓縮率中等,可是cpu消耗低。電話對應HFP profile,音樂對應Profile。電話使用的是同步鏈路SCO,音樂時異步鏈路ACL,使用A2DP profile。另外還有其它profile,傳問題,獲取電話本,短信同步等。 使用A2DP時,先是進行音樂的解碼,而後再把解碼後的PCM進行SBC編碼。A2DP支持下行audio編碼採樣率範圍爲8k-48k。在高通的大多數方案裏面,SBC編碼是在DSP裏作的。 HFP,有兩個角色AG和HF,正常狀況下手機做爲AG,耳機做爲HF。可是手機代碼中也有HF部分的代碼 手機藍牙芯片是三合一的,包括BT,FM和WLAN,使用一根天線。藍牙耳機和藍牙模塊之間經過AT命令進行通訊,分爲master和slave,誰先連對方誰就是master。藍牙功耗待機1mA左右,傳文件要100多mA,聽音樂60左右,打電話30。