1. 程式人生 > >第十四篇 ANDROID的 BLUETOOTH 實現機制與架構

第十四篇 ANDROID的 BLUETOOTH 實現機制與架構

        從ANDROID3.0開始,BLUETOOTH  API提供了Bluetooth profile協議的支援。目前ANDROID4.0的藍芽API提供了五種藍芽無線介面規範(Bluetooth profile)的支援,用來在裝置之間通過藍芽實現特定功能:包括 Headset和Hands-Freeprofile(實現藍芽耳機功能),A2dpprofile(第二代藍芽聲音裝置協議,用來在藍芽裝置之間實現高質量的聲音傳輸),InputDeviceprofile(實現藍芽輸入裝置功能),Bluetooth  Panprofile(實現藍芽個人區域網功能),Bluetooth Healthprofile(實現藍芽健康裝置規範,用來與支援藍芽健康裝置規範的裝置進行藍芽通訊)。另外還有Bluetooth Pbapprofile(實現藍芽電話本功能),但介面和其它profile實現不一致。

        ANDROID對 Bluetooth profile API的實現主要採用了中介模式、代理模式及狀態模式等。

        應用通過一個統一的類BluetoothAdapter(藍芽本地介面卡類)與這些藍芽裝置協議對應的BLUETOOTH  API進行互動。

       BluetoothAdapter是所有藍芽物件互動和執行藍芽操作的入口:包括呼叫BLUETOOTH profile API,發現其它藍芽裝置、查詢配對成功的裝置、使用已知的MAC地址例項化藍芽裝置、建立一個BluetoothServerSocket物件來監聽其它藍芽裝置以及根據地址例項化藍芽裝置等操作。

       應用為了使用藍芽功能,JELLY_BEAN_MR1以下的版本使用如下方式獲得BluetoothAdapter單例物件。

     BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter();

        JELLY_BEAN_MR2以後的版本,使用如下方式來呼叫藍芽API。

     BluetoothManager bluetoothManager =
                (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
     BluetoothAdapter mAdpter=bluetoothManager.getAdapter(); 


     幾乎所有的藍芽物件和所有的藍芽服務都維護一個BluetoothAdapter單例物件,BluetoothAdapter單例物件通過BluetoothAdapter類提供的getDefaultAdapter函式獲得。BluetoothAdapter物件可以說是整個系統互動的中介,是中介設計模式的採用。

      而幾個藍芽裝置協議的實現藉助幾個ANDROID服務來實現,並通過代理物件對外提供BLUETOOTH  API。Headset對應的代理物件為BluetoothHeadset,A2dp對應的代理物件為BluetoothA2dp,InputDeviceprofile對應的代理物件為BluetoothInputDevice,Bluetooth  Pan對應的代理物件為BluetoothPan,Bluetooth  Health對應的代理物件為BluetoothHealth。

      通過BluetoothAdapter類提供的getProfileProxy函式根據不同的profile引數例項化對應的代理物件,getProfileProxy函式還傳給代理物件一個實現BluetoothProfile.ServiceListener介面的監聽物件。

       代理物件例項化時與代理的服務進行繫結,與服務進行繫結成功後呼叫對應監聽物件的onServiceConnected回撥函式,並通過回撥函式把代理物件傳給應用,應用通過代理物件通過BINDER訪問藍芽裝置服務。

       Headset對應藍芽服務為BluetoothHeadsetService及BluetoothHandsfree物件,A2dpprofile對應的藍芽服務為BluetoothA2dpService,而InputDeviceprofile、Bluetooth Healthprofile及Bluetooth  Panprofile都由BluetoothService服務來實現。Bluetooth Pbap profile對應的服務是BluetoothPbapService。

       BluetoothAdapter物件相關類圖如下:

      

圖中幾個藍芽服務BluetoothHeadsetService、BluetoothA2dpService、BluetoothService、BluetoothPbapService及BluetoothDeviceProfileState、BluetoothHandsfree、BluetoothEventLoop物件都維護一個BluetoothAdapter物件(使用BluetoothAdapter類提供的getDefaultAdapter函式獲得),並通過BluetoothAdapter物件提供的getProfileProxy函式根據profile型別獲得要訪問的代理物件,還通過BluetoothAdapter物件訪問其它藍芽物件。

       圖中幾個代理物件都是BluetoothProfile介面的實現,並都維護一個ServiceListener監聽物件。BluetoothHeadset物件通過IBluetoothHeadset對BluetoothHeadsetService服務進行BINDER呼叫,BluetoothA2dp物件通過IBluetoothA2dp對BluetoothA2dpService服務進行BINDER呼叫,而BluetoothInputDevice、BluetoothPan、BluetoothHealth物件通過IBluetooth呼叫BluetoothService的API。

        代理物件本身及BluetoothAudioGateway物件也可以通過BluetoothAdapter物件訪問其它藍芽物件來獲得藍芽裝置資訊和狀態。

        BluetoothAdapter物件提供的介面除了getProfileProxy外主要有以下幾個:

        getRemoteDevice() 獲得遠端裝置,返回一個BluetoothDevice物件;

        getBondedDevices() 獲得已配對裝置,返回繫結(配對)到本地藍芽的BluetoothDevice物件集合;

        getState()   獲得本地藍芽的當前狀態,包括STATE_ON、STATE_OFF、STATE_TURNING_ON、STATE_TURNING_OFF四種狀態,由BluetoothAdapterStateMachine狀態機進行維護

        isEnabled()  返回當前藍芽是否可用狀態,和getState()==STATE_ON對應。

        enable()    開啟本地藍芽

        disable()    關閉本地藍芽

        getUuids() 返回本地藍芽支援的UUIDs陣列

        isDiscovering()  本地藍芽當前正處於藍芽裝置發現過程

        cancelDiscovery() 取消當前藍芽裝置發現過程

       另外還提供建立RfcommSocket監聽通道的API。

       BluetoothAdapter物件通過六個API來建立RfcommSocket資料連線監聽通道(三個使用固定埠三個使用隨機埠)及一個SCO監聽通道(面向連線方式,主要用於話音傳輸)。三個建立使用固定埠的監聽通道API:一個用來建立需要認證和加密的使用固定socket埠的API(需要BLUETOOTH_ADMIN許可權許可);一個用來建立不加密不認證的透明固定埠的RFCOMMSocket API;一個用來建立加密不認證的固定埠的RFCOMMSocket API。三個建立使用隨機埠的監聽RfcommSocket通道API(一個建立加密認證通道、一個建立透明通道、一個建立加密無認證通道),隨機埠的產生由BluetoothAdapter的內部物件RfcommChannelPicker負責產生。

       對於藍芽服務端,可以呼叫BluetoothAdapter物件的這些API來建立一個BluetoothServerSocket物件,初始化一個服務端RfcommSocket監聽通道,並呼叫BluetoothServerSocket物件的accept函式接收對方連線(實際呼叫剛例項化的監聽RfcommSocket的accept函式)。當成功與對方建立連線後,BluetoothServerSocket物件的accept函式返回一個新RfcommSocket通道,用來作為裝置之間的資料傳輸的通訊通道。

       每個RfcommSocket通道對應一個BluetoothSocket物件。BluetoothServerSocket物件例項化時根據BluetoothServerSocket例項化函式傳進來的通道socket型別、是否需要認證對方裝置、連線是否加密、遠端socket埠等引數來例項化一個BluetoothSocket物件,socket埠引數為空時使用產生的隨機埠。例項化BluetoothSocket物件時使用的socket埠值為1到30之間的數,但10、11、12、19四個保留埠留給其它Profile使用。

       在BluetoothSocket物件的例項化函式中還例項化了一個BluetoothInputStream物件和BluetoothOutputStream物件,用作交換資料使用。

       BluetoothSocket物件還可以由藍芽客戶端裝置來例項化,即由BluetoothDevice物件來例項化。每個BluetoothDevice物件對應一個遠端藍芽裝置。BluetoothDevice物件使用BluetoothSocket物件向藍芽服務端請求連線。通過BluetoothSocket物件還可以查詢遠端藍芽裝置的資訊如裝置名、MAC地址、繫結狀態、藍芽型別等。

       BluetoothDevice物件提供了四個建立RfcommSocket的函式(兩個用於建立安全連線,兩個用於建立透明連線,而兩個安全連線和兩個透明連線中一個通過SDP裝置發現功能產生的隨機socket埠,一個使用固定socket埠) 及一個建立SCO socket(用於話音傳輸)的函式 createScoSocket。createScoSocket及建立透明固定socket埠的API的使用需要BLUETOOTH_ADMIN許可權許可。裝置發現功能的實現由SdpHelper物件來實現。

       下圖是BluetoothService相關類圖:

     

BluetoothService服務採用三個ProfileHandler物件提供相關Profile API的服務。BluetoothPanProfileHandler用於Bluetooth PanProfile,BluetoothInputProfileHandler用於Bluetooth InputDeviceProfile,BluetoothHealthProfileHandler用於Bluetooth HealthProfile。

       三個ProfileHandler物件通過父物件BluetoothService與其它藍芽物件互動。三個ProfileHandler物件本身都有一個以BluetoothDevice物件為key的HashMap以維護已連線裝置狀態。

       BluetoothPanProfileHandl物件還通過ConnectivityManager、INetworkManagementService、BluetoothTetheringDataTracker三個物件和介面與資料連線服務互動實現藍芽連線共享功能。資料連線服務機制見博主的另一篇博文《第十一篇 ANDROID 系統網路連線和管理機制》。

       BluetoothHealthProfileHandler使用BluetoothHealthAppConfiguration物件指示一個登記用來與醫療藍芽裝置通訊和接收健康藍芽裝置發來的資料的物件,也稱為sink角色,與sink通訊的健康藍芽裝置稱為Source。

       應用通過呼叫BluetoothHealth代理物件的registerSinkAppConfiguration函式在BluetoothHealthProfileHandler物件中登記一個BluetoothHealthAppConfiguration物件。

       應用使用BluetoothHealth代理物件的connectChannelToSource或connectChannelToSink函式實現sink與Source的連線。

       BluetoothHealthProfileHandler使用IBluetoothHealthCallback回撥介面通過BluetoothHealth代理物件嚮應用傳送事件通知。

       BluetoothService服務還包括幾個狀態機物件,採用了狀態設計模式。

       一個BluetoothAdapterStateMachine狀態機,處理和維護本地藍芽的狀態事件,包括BluetoothOn、Switching、HotOffWarmUp、PowerOff、PerProcessState等幾個狀態物件,初始狀態為PowerOff。BluetoothAdapterStateMachine狀態機還通過IBluetoothStateChangeCallback介面向BluetoothAdapter物件通知本地藍芽的狀態。

       在PowerOff狀態接收到BluetoothService服務發來的USER_TURN_ON訊息時(由應用呼叫BluetoothAdapter物件的enable函式觸發)完成本地藍芽模組和韌體的載入,還啟動一個BluetoothEventLoop物件,通過JNI啟動一個執行緒接收本地藍芽模組bluez產生的藍芽訊號。

       兩個BluetoothProfileState狀態機,其中一個維護A2dp Profile連線狀態的管理,另外一個維護Health Profile連線狀態的管理。

       還有一個以藍芽裝置地址為key的BluetoothDeviceProfileState狀態機HashMap集合。為每個已配對遠端裝置提供一個相關的BluetoothDeviceProfileState狀態機,用來跟蹤所有的藍芽Profile的輸入輸出連線。

        InputDevice profile的連線狀態的管理由BluetoothInputProfileHandler物件提供的一個狀態機物件進行維護。

                                                 版權所有,轉載時請尊重原創顯要處註明連結,謝謝!

上一篇

下一篇