本文主要論述基於android 6.0的藍牙上層(Java層)通話機制;總結了藍牙通話框架,而且給出了接聽電話的詳細的流程圖;最後說明了apk的實現以及總結了藍牙/android 相關的知識點。java
1, 藍牙框架
主要代碼路徑:android
路徑1: frameworks\base\core\java\android\bluetooth\ api
藍牙相關接口,藍牙各類功能的發起點。app
路徑2:packages\apps\Bluetooth\src\com\android\bluetooth\ 框架
獨立的Bluetooth.apk,裏面包含藍牙相關的各類服務,是java層和C/C++層的橋樑。設計
路徑3: packages\apps\Bluetooth\jni\代理
調用底層C/C++實現各類藍牙功能,而且反饋給java層。視頻
在路徑2裏面還有各類相互獨立的java代碼包,每個包都包含一個協議,實現一個具體的功能:對象
btservice: 統一管理,控制其餘服務。blog
a2dp: 和藍牙耳機,音頻有關,好比聽歌等。
avrcp: 音頻/視頻經過鏈接的藍牙控制,好比放歌時控制暫停等。
gatt:低功耗BLE有關,好比藍牙按鍵。
hdp: 藍牙醫療有關
hfp和hfpclient : 藍牙通話有關,好比藍牙通話的相關操做
hid: 藍牙鍵盤鍵盤/鼠標
map: 同步藍牙短信相關
opp: 藍牙傳輸,好比傳輸文件等
pan: 我的局域網
pbap: 同步電話本,好比聯繫人/通話記錄等
sap : 藍牙通話,主要和SIM卡相關
sdp: 藍牙服務發現/獲取相關
這12個包分別實現了12中藍牙功能,大多數以服務的形式存在,運行在Bluetooth.apk中。不只如此,還具備如下特色:
1,每個服務相互獨立,互相毫無任何影響, 繼承自 ProfileService,由
AdapterService服務統一管理。
2,每個服務在路徑1中都存在對應的客戶端類,經過Binder進行跨進程通訊。
3,每個服務在路徑3中都存在對應的C/C++類,經過JNI機制互相調用。
4,每個服務的啓動,對應的Binder以及JNI機制的調用原理,方法,流程幾乎都是同樣的。
下面以藍牙通話功能爲例來解析相關接口以及代碼實現框架圖。
2 藍牙通話框架
2.1 相關類的說明
藍牙通話上層代碼主要分爲3個部分:
1,藍牙api相關代碼, 路徑4: frameworks\base\core\java\android\bluetooth\
主要有2個類
BluetoothHeadsetClient.java主要負責藍牙通話的相關動做,好比接聽等等
BluetoothHeadsetClientCall.java主要負責藍牙通話的狀態,好比是來電仍是去電等等。
2,藍牙服務端的相關代碼,路徑5:
packages\apps\Bluetooth\src\com\android\bluetooth\hfpclient\
有3個類
HeadsetClientHalConstants.java類裏面只是定義了一些int/boolean 類型的值。
HeadsetClientService.java從名字就知道它是一個服務,它的設計頗有意思,裏面還有一個BluetoothHeadsetClientBinder內部類,該內部類主要負責和
BluetoothHeadsetClient進行跨進程通訊。另外,HeadsetClientService也是
BluetoothHeadsetClientBinder和HeadsetClientStateMachine之間的橋樑。
HeadsetClientStateMachine是一個狀態機,即管理鏈接的狀態也是通話時java和C/C++之間的橋樑,經過JNI機制和com_android_bluetooth_hfpclient 裏面的方法互相調用。
3,JNI相關代碼,路徑6: packages\apps\Bluetooth\jni\
有1個文件:
com_android_bluetooth_hfpclient 藍牙通話動做,撥號/接聽/掛斷/拒接 實際的執行者。
DialerBTHfpService服務是開機以後啓動的。
2.2類圖
圖一 類圖
BluetoothHeadsetClient是一個api,由第三方apk直接調用,能夠進行撥號/接聽/拒接/掛斷操做,對應的方法依次爲dial()/acceptCall()/rejectCall()/terminateCall().
HeadsetClientService是一個服務, BluetoothHeadsetClientBinder是它的內部類, BluetoothHeadsetClientBinder是BluetoothHeadsetClient在HeadsetClientService中的代理,經過aidl進行方法的調用。
Connected(已鏈接狀態)是HeadsetClientStateMachine 的其中一種狀態,通話的相關操做都創建在已鏈接狀態之上,其它三種狀態爲Disconnected, Connecting,
AudioOn狀態。HeadsetClientService 根據不一樣的方法給狀態機發送不一樣的消息,最後經過HeadsetClientStateMachine根據JNI機制調用
com_android_bluetooth_hfpclient.cpp對應的方法,最後調用底層C/C++ 來真正的實現撥號/接聽/拒接/掛斷操做。
撥號/接聽/拒接/掛斷方法調用的流程徹底是如出一轍的,下小節給出接聽方法具體調用的完整流程圖。
2.3流程圖
圖二 接聽電話流程圖
除了dial 方法最後調用從C/C++ dialNative以外,其它的3個方法最後都是調用handleCallActionNative,只是參數不一樣而已。
撥號/接聽/拒接/掛斷都是主動完成的,那麼若是有來電,對方接通電話或者對方掛斷電話,咱們怎麼知道呢?這些都是com_android_bluetooth_hfpclient.cpp經過JNI機制調用通話狀態機的方法sendCallChangedIntent,將電話的狀態(包含在
BluetoothHeadsetClientCall.java中)經過廣播發送出來,第三方apk監聽狀態就能夠進行相應的操做了。具體的來電流程圖以下:
圖三 來電流程圖
3 藍牙通話apk說明
在本身的apk中,只須要作2件事情就能夠完成藍牙通話的幾乎全部動做,
1,根據上一小節的論述,註冊BluetoothHeadsetClientCall相關廣播,監聽來電/接通/對方掛斷的狀態,獲取藍牙電話的相關信息,好比號碼,設備信息等等。
好比,若是收到來電廣播,就能夠根據BluetoothHeadsetClientCall獲取來電的號碼等信息,而後顯示來電界面。
2,經過BluetoothAdapter 獲取而且初始化BluetoothHeadsetClient對象,而後就能夠直接調用dial()/acceptCall()/rejectCall()/terminateCall() 方法進行撥號/接聽/拒接/掛斷的操做了。
4, 小節
利用api實現藍牙通話不是很難,可是若是弄清楚具體的藍牙通話機制以及細節甚至藍牙相關功能,這就得下功夫了,關於藍牙,還能夠進一步研究的android知識點以及藍牙涉及的上層java要點以下:
1,基本藍牙功能:打開/關閉/掃描/配對/鏈接
2,藍牙功能:經過藍牙傳輸文件/藍牙鍵盤/藍牙醫療服務/藍牙同步聯繫人等等
3,android知識:跨進程通訊機制/JNI機制/反射機制/狀態機機制等等。