一、前言
本文側(cè)重點(diǎn):Android中藍(lán)牙代碼結(jié)構(gòu)分析尿招。
代碼來(lái)源于Android P踊餐,本文相關(guān)代碼:
client:
frameworks/base/core/java/android/bluetooth/*
system/bt/binder/android/bluetooth/**.aidl
servie:
framework/base/services/core/java/com/android/server/BluetoothService.java
framework/base/services/core/java/com/android/server/BluetoothManagerService.java
bluetooth:
package/app/bluetooth
(上面是aosp源碼提供的藍(lán)牙實(shí)現(xiàn)乱豆。而芯片廠商提供的代碼一般這部分是沒(méi)有源碼的伶棒,比如mtkbluetooth.apk直接替換此apk。但aosp提供的源碼供我們學(xué)習(xí)還是可以的项戴。)
settingslib:
vendor/mediatek/proprietary/packages/apps/SettingsLib/src/com/android/settingslib/bluetooth/
(SettingsLib原生frameworks/base/packages/SettingsLib也有形帮,上面是MTK定制,主要區(qū)別是對(duì)協(xié)議的修改添加一些支持等)
上面四個(gè)部分是藍(lán)牙核心的地方周叮。對(duì)于系統(tǒng)的應(yīng)用從AndroidP開(kāi)始辩撑。AOSP已經(jīng)原生支持對(duì)藍(lán)牙的各種接口了。只要芯片廠商對(duì)接好系統(tǒng)藍(lán)牙接口我們就可以依賴原生接口開(kāi)發(fā)自己想要的應(yīng)用app仿耽,下面是功能應(yīng)用的表格:
功能 | 依賴項(xiàng) |
---|---|
Diar | 通話相關(guān)合冀,來(lái)去電走Android原生telecom流程。聯(lián)系人/通話記錄依賴原生contactsprovider |
music | 音樂(lè)相關(guān)项贺,走原生Mediasession |
settings | 藍(lán)牙設(shè)置相關(guān)君躺,用settingsLib控制,開(kāi)關(guān)連接等 |
其他 | 其他應(yīng)用依賴于Android自身支持的協(xié)議(profile)比如GATT低功耗藍(lán)牙开缎,OPP文件傳輸棕叫,等等 |
注:
1、本文以分析整體為主奕删。讀者需要對(duì)framework中service/client結(jié)構(gòu)熟悉(此文有介紹這種結(jié)構(gòu):PackageManagerService服務(wù)框架詳解)俺泣。另外建議閱讀時(shí)去翻翻對(duì)應(yīng)路徑下的源碼,便于理解。
2伏钠、本文以整體框架講解的思想來(lái)闡述侮邀。特殊流程會(huì)源碼講解,講解時(shí)只列出源碼關(guān)鍵代碼行贝润。大部分只總結(jié)它的作用。需要讀者自行去結(jié)合源碼理解铝宵。
二打掘、功能簡(jiǎn)單介紹
首先藍(lán)牙服務(wù)和AMS、PMS等系統(tǒng)眾多服務(wù)一樣鹏秋,也是service/client結(jié)構(gòu)尊蚁。不理解S/C結(jié)構(gòu)的同學(xué)可以直接理解為普通的API調(diào)用,直接調(diào)用最終在BluetoothManagerService.java代碼里侣夷,方法名大部分都一樣横朋。
2.1、四部分(client百拓、service琴锭、bluetooth、settinglib)
藍(lán)牙的代碼主要分為標(biāo)題的四個(gè)部分
2.1.1衙传、client
客戶端主要代碼是BluetoothAdapter决帖,我們平時(shí)開(kāi)發(fā)時(shí)都是通過(guò)操作BluetoothAdapter的公開(kāi)api來(lái)實(shí)現(xiàn)我們的功能。
除開(kāi)BluetoothAdapter起到核心作用之外在com.android.bluetooth下還默認(rèn)提供一些默認(rèn)協(xié)議API級(jí)的支持蓖捶。這些協(xié)議都是一個(gè)獨(dú)立的profile實(shí)現(xiàn)地回。這些profile使我們可以控制藍(lán)牙工作于我們想要的場(chǎng)景下。通常這部分三方apk使用較多俊鱼。
名稱 | 簡(jiǎn)單介紹 |
---|---|
A2dp | 音頻 |
Gatt | 低功耗 |
Headset | 藍(lán)牙耳機(jī) |
Health | 健康 |
Socket | 面向連接刻像,套接字,基于RFCOMM |
2.2.2并闲、service
代碼:BluetoothManagerService.java
service管理:
BluetoothManagerService里主要是framework層實(shí)現(xiàn)藍(lán)牙功能的地方细睡。我們從BluetoothAdapter調(diào)用方法都會(huì)調(diào)用到BluetoothManagerService里,而BluetoothManagerService里的大部分實(shí)現(xiàn)又是通過(guò)綁定bluetooth apk里的service(AdapterService)來(lái)實(shí)現(xiàn)帝火。這樣BluetoothManagerService既起到了統(tǒng)一framework藍(lán)牙實(shí)現(xiàn)的地方纹冤,又讓Bluetooth apk可以有豐富的profile具體功能實(shí)現(xiàn)。
Profile理解:
一個(gè)藍(lán)牙硬件模塊根據(jù)藍(lán)牙規(guī)范(比如藍(lán)牙4.0)购公。會(huì)默認(rèn)實(shí)現(xiàn)很多自帶的協(xié)議萌京。由于制定協(xié)議的人多個(gè)組等其他原因。藍(lán)牙規(guī)范是有很多個(gè)細(xì)分的協(xié)議協(xié)同工作宏浩≈校可以理解為一種通信規(guī)范。一個(gè)標(biāo)準(zhǔn)的藍(lán)牙模塊肯定得把藍(lán)牙規(guī)范里的協(xié)議都實(shí)現(xiàn)比庄。而Profile的存在的意義就是求妹。不管你標(biāo)準(zhǔn)有多少個(gè)協(xié)議乏盐,我只要我想要的功能,別的我不管制恍。比如A2dp音頻協(xié)議父能。我只需要藍(lán)牙工作于A2dp就可以了。當(dāng)然A2dp可能是基于其中某幾個(gè)協(xié)議上的協(xié)議净神。但是別的協(xié)議它沒(méi)有何吝。用JavaScript的思想來(lái)理解Profile,它就是一個(gè)切面鹃唯。
2.2.3爱榕、bluetooth
bluetooth是藍(lán)牙協(xié)議具體實(shí)現(xiàn)的地方。比如BluetoothAdapter#enable打開(kāi)藍(lán)牙的時(shí)候坡慌,跟蹤代碼最后的調(diào)用就會(huì)跟蹤到bluetooth apk里黔酥。而打開(kāi)操作就在bluetooth中的AdapterService。這個(gè)是service就是藍(lán)牙功能的服務(wù)洪橘。在BluetoothManagerService中會(huì)綁定AdapterService跪者,拿到服務(wù)后,就間接提供給client中的BluetoothAdapter API使用熄求。下面用連個(gè)截圖來(lái)展示它的豐富的實(shí)現(xiàn)
bluetooth apk由于是具體的實(shí)現(xiàn)坑夯,所以它會(huì)實(shí)現(xiàn)所有的協(xié)議。
除開(kāi)client中提供的profile抡四,還有settingslib中系統(tǒng)藍(lán)牙操作功能實(shí)現(xiàn)的Profile柜蜈。這些豐富的profile會(huì)在下一小節(jié)列出。
2.2.4指巡、settingslib
settingsLib和其他三個(gè)部分是相對(duì)而言比較獨(dú)立的一個(gè)部分淑履。因?yàn)樗皇欠庋b操作。以便settings可以更方便的控制管理
settingslib主要是服務(wù)系統(tǒng)app:settings使用藻雪,編譯時(shí)一般也是編譯settings的時(shí)候一起編譯settingslib秘噪。
只有系統(tǒng)級(jí)權(quán)限(集成到系統(tǒng)中,system/app勉耀、framework等)才可以調(diào)用settingslib指煎,普通三方應(yīng)用開(kāi)發(fā)者無(wú)法使用
settingslib中藍(lán)牙代碼相當(dāng)于也是操作BluetoothAdapter,BluetoothAdapter間接調(diào)用BluetoothManagerService來(lái)實(shí)現(xiàn)功能.
在SettingsLib\src\com\android\settingslib\bluetooth中我們還能看到像com.android.bluetooth路徑下那些協(xié)議之外的一些協(xié)議
名稱 | 簡(jiǎn)單介紹 | 名稱 | 簡(jiǎn)單介紹 |
---|---|---|---|
A2dp | 音頻 | Headset | 藍(lán)牙耳機(jī) |
HearingAid | 助聽(tīng)器 | Hfp | 免提 |
Hid | 人機(jī)接口設(shè)備 | Map | 信息訪問(wèn) |
Opp | 對(duì)象推送 | Pan | 個(gè)人局域網(wǎng) |
Pbap | 電話薄 | Sap | 會(huì)話通知 |
看到這些協(xié)議便斥,settingslib服務(wù)于系統(tǒng)就很好理解了至壤。一個(gè)手機(jī)連上藍(lán)牙。那么手機(jī)設(shè)置支持藍(lán)牙相關(guān)的操作也就是這些協(xié)議支持的功能
三枢纠、詳解四大部分(client像街、service、bluetooth、settinglib)
文章第二段對(duì)Android藍(lán)牙框架代碼已經(jīng)有了一個(gè)簡(jiǎn)單的介紹镰绎。就是這四個(gè)部分代碼支撐著藍(lán)牙的各種功能脓斩。接下來(lái)將詳細(xì)介紹四個(gè)部分比較核心的內(nèi)容。
3.1畴栖、BluetoothAdapter詳細(xì)介紹(client)
BluetoothAdapter部分主要是api使用随静,所以這部分以表格方式列出信息方便查閱
第一個(gè)表是BluetoothAdapter定義的一些狀態(tài)和通知:
作用類型 | 關(guān)鍵字 | 介紹 |
---|---|---|
開(kāi)關(guān)通知 | ACTION_STATE_CHANGED | 上次狀態(tài)和當(dāng)前狀態(tài) |
開(kāi)關(guān)狀態(tài)定義 | AdapterState | 描述當(dāng)前藍(lán)牙狀態(tài) |
請(qǐng)求掃描 | ACTION_REQUEST_DISCOVERABLE | 請(qǐng)求掃描,默認(rèn)120秒吗讶,可帶時(shí)間參數(shù) activity#resulet |
請(qǐng)求掃描 | ACTION_REQUEST_BLE_SCAN_ALWAYS_AVAILABLE | 一直允許掃描 activity#resulet |
請(qǐng)求打開(kāi)/關(guān)閉 | ACTION_REQUEST_ENABLE燎猛、ACTION_REQUEST_DISABLE | 請(qǐng)求打開(kāi)/關(guān)閉activity#resulet |
掃描狀態(tài)通知 | ACTION_SCAN_MODE_CHANGED | 上次狀態(tài)和當(dāng)前狀態(tài) |
掃描狀態(tài)定義 | ScanMode | 描述掃描狀態(tài) |
掃描開(kāi)始/結(jié)束通知 | ACTION_DISCOVERY_STARTED、ACTION_DISCOVERY_FINISHED | |
名字改變通知 | ACTION_LOCAL_NAME_CHANGED | 帶名字參數(shù) |
連接狀態(tài)通知 | ACTION_CONNECTION_STATE_CHANGED | 帶當(dāng)前和上次狀態(tài) |
LE下?tīng)顟B(tài)通知 | ACTION_BLE_STATE_CHANGED | 藍(lán)牙只在低功耗模式時(shí)狀態(tài)變化 |
mac地址變化 | ACTION_BLUETOOTH_ADDRESS_CHANGED | 帶參數(shù) |
連接類型 | ACTION_BLE_ACL_CONNECTED | |
斷開(kāi)連接類型 | ACTION_BLE_ACL_CONNECTED |
上面這些豐富的廣播通知是在bluetooth apk里的實(shí)現(xiàn)的关翎。bluetooth中的btservice中收到狀態(tài)的時(shí)候直接發(fā)出廣播
第二個(gè)表是BluetoothAdapter.java內(nèi)部方法(方法只是提及,不包括所有鸠信,類似或者不重要的省略):
方法 | 作用 | 方法 | 作用 |
---|---|---|---|
getDefaultAdapter | 拿對(duì)象 | getRemoteDevice | 遠(yuǎn)端設(shè)備 |
getBluetoothLeAdvertiser | LE廣播數(shù)據(jù) | getPeriodicAdvertisingManager | LE注冊(cè)管理 |
getBluetoothLeScanner | 掃描 | isEnabled | 開(kāi) |
getState | 狀態(tài) | getLeState | LE狀態(tài) |
enable | 打開(kāi) | getAddress | 地址 |
setName | 名字 | factoryReset | 出廠設(shè)置 |
getUuids | uuid | getBluetoothClass | 遠(yuǎn)端設(shè)備信息判斷設(shè)備類型是否提供某個(gè)service等 |
setScanMode | 掃描模式 | setDiscoverableTimeout | 超時(shí)時(shí)間 |
cancelDiscovery | 取消 | isDiscovering | 是否掃描 |
isLe*** | LE設(shè)備功能支持判斷 | getMaxConnectedAudioDevices | 最大audio設(shè)備數(shù) |
requestControllerActivityEnergyInfo | 獲取藍(lán)牙信息比如電量 | getBondedDevices | 已配對(duì)設(shè)備 |
getSupportedProfiles | 支持的協(xié)議 | getConnectionState | 連接狀態(tài) |
getProfileConnectionState | 協(xié)議連接狀態(tài) | listen*** | 創(chuàng)建service監(jiān)聽(tīng)例如開(kāi)氣socket服務(wù) |
getProfileProxy | 客戶端拿到服務(wù)比如pbap | closeProfileProxy | 關(guān)閉連接 |
enableNoAutoConnect | 打開(kāi) | checkBluetoothAddress | 有效地址判斷 |
getBluetoothManager | 獲得bluetoothmanagerservice | getBluetoothService | 獲得藍(lán)牙服務(wù) |
startLeScan | LE開(kāi)始掃描 | stopLeScan | 停止le掃描 |
BluetoothAdapter小結(jié)
1纵寝、BluetoothAdapter的重要信息上面基本都列出來(lái)了。除了常規(guī)的開(kāi)關(guān)監(jiān)聽(tīng)等操作外星立。還有很多掃描連接狀態(tài)等得廣播通知發(fā)送出來(lái)爽茴。
2、我們的apk客戶端想要和某個(gè)profile服務(wù)綁定時(shí)绰垂,通過(guò)getProfileProxy來(lái)拿到服務(wù)和監(jiān)聽(tīng)
3室奏、低功耗LE設(shè)備也提供了一些操作方法
3.2、BluetoothManagerService詳細(xì)介紹(service)
BluetoothManagerService功能實(shí)現(xiàn)比較分散劲装,下面以講解比較重要的幾個(gè)代碼流程邏輯為主胧沫。
BluetoothManagerService這部分主要是功能的詳細(xì)實(shí)現(xiàn)。而BluetoothManagerService和其他系統(tǒng)service不太一樣占业。它這里的實(shí)現(xiàn)也只是表面封裝一下绒怨。具體的實(shí)現(xiàn)是通過(guò)綁定bluetooth apk里的AdapterService,然后通過(guò)AdapterService來(lái)實(shí)現(xiàn)谦疾。下面我們看下怎么調(diào)用到AdapterService的南蹂。
3.2.1、系統(tǒng)api調(diào)用流程
BluetoothManagerService調(diào)用到package/app/bluetooth
BluetoothAdapter->BluetoothManagerService->AdapterService(bluetooth apk)上面client部分列出的方法大部分都是這個(gè)操作流程念恍,走到bluetooth里的具體實(shí)現(xiàn)六剥。
查看BluetoothAdapter調(diào)用邏輯,和其他系統(tǒng)api一樣峰伙,藍(lán)牙也是S/C結(jié)構(gòu)疗疟。那么具體實(shí)現(xiàn)就都會(huì)集中到BluetoothManagerService。查看BluetoothManagerService代碼我們很容發(fā)現(xiàn)里面的詳細(xì)實(shí)現(xiàn)主要有兩個(gè)間接調(diào)用mManagerService和mBluetooth 瞳氓。我們跟一下這兩個(gè)對(duì)象秃嗜。
BluetoothManagerService.java代碼片段:
IBluetoothManager mManagerService = IBluetoothManager.Stub.asInterface(ServiceManager.getService(BLUETOOTH_MANAGER_SERVICE));
private void handleEnable(boolean quietMode) {
...
Intent i = new Intent(IBluetooth.class.getName());
if (!doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
UserHandle.CURRENT)) {
...
}
private class BluetoothServiceConnection implements ServiceConnection {
public void onServiceConnected(ComponentName componentName, IBinder service) {
...
msg.obj = service;
mHandler.sendMessage(msg);
}
mBluetooth = IBluetooth.Stub.asInterface(Binder.allowBlocking(service));
mManagerService很好理解就是綁定到了我們的BluetoothManagerService服務(wù)。
mManagerService在打開(kāi)藍(lán)牙的時(shí)候會(huì)間接調(diào)用到handleEnable方法,handleEnable的dobind會(huì)綁定BluetoothService,回調(diào)到BluetoothServiceConnection方法中把service賦值給mBluetooth锅锨,這樣我們就可以拿到Bluetooth app里的service(AdapterService)進(jìn)行操作了叽赊。
3.2.2、BluetoothAdapter和Bluetooth apk其他協(xié)議綁定調(diào)用
這個(gè)流程和BluetoothManagerService沒(méi)什么關(guān)系,但是和3.2.1極其相似,所以放在這里講恨搓。
普通三方apk可以通過(guò)BluetoothAdapter#getProfileProxy來(lái)拿到協(xié)議翰绊,并通過(guò)協(xié)議進(jìn)行具體操作。操作實(shí)際也會(huì)操作到Bluetooth apk里惕味。我們以settingslib連接使用profile來(lái)講解。整體流程大致如下:
settingslib->settingslib#setBluetoothStateOn->bluetoothadater#getProfileProxy->bluetooth apk profile service
1、settinglib中LocalBluetoothAdapter打開(kāi)藍(lán)牙
首先除了默認(rèn)的BluetoothAdapter#enable可以打開(kāi)外葛家,settinglib中LocalBluetoothAdapter#enable也可以打開(kāi),打開(kāi)時(shí)代碼會(huì)走到LocalBluetoothProfileManager#setBluetoothStateOn泌类。我們以HidProfile為代表來(lái)講
// Called from LocalBluetoothAdapter when state changes to ON
void setBluetoothStateOn() {
if (mHidProfile == null) {
mHidProfile = new HidProfile(mContext, mLocalAdapter, mDeviceManager, this);
addProfile(mHidProfile, HidProfile.NAME,
BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED);
}
2癞谒、HidProfile拿到bluetooth apk中的HidProfile服務(wù)
public class HidProfile implements LocalBluetoothProfile {
public void onServiceConnected(int profile, BluetoothProfile proxy) {
if (V) Log.d(TAG,"Bluetooth service connected");
mService = (BluetoothHidHost) proxy;
....
HidProfile(Context context, LocalBluetoothAdapter adapter,
CachedBluetoothDeviceManager deviceManager,
LocalBluetoothProfileManager profileManager) {
...
adapter.getProfileProxy(context, new HidHostServiceListener(),
BluetoothProfile.HID_HOST);
}
這里的HidProfile代碼在settinglib中,創(chuàng)建時(shí)核心的調(diào)用到了adapter.getProfileProxy刃榨。這里就是framework層通過(guò)BluetoothAdapter拿到bluetooth apk中的profile service核心邏輯
BluetoothAdapter#getProfileProxy
public boolean getProfileProxy(Context context, BluetoothProfile.ServiceListener listener,
int profile) {
....
if (profile == BluetoothProfile.HEADSET) {
BluetoothHeadset headset = new BluetoothHeadset(context, listener);
return true;
}
....
else if (profile == BluetoothProfile.HID_HOST) {
BluetoothHidHost iDev = new BluetoothHidHost(context, listener);
return true;
}
這里又會(huì)新創(chuàng)建一個(gè)HID的profile對(duì)象BluetoothHidHost弹砚。(這里容易和settingslib中的HidProfile混淆,這個(gè)HID還好名字有區(qū)別枢希,別的profile名字極其類似桌吃。)BluetoothHidHost在路徑frameworks\base\core\java\android\bluetooth
private final ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
if (DBG) Log.d(TAG, "Proxy object connected");
mService = IBluetoothHealth.Stub.asInterface(Binder.allowBlocking(service));
if (mServiceListener != null) {
mServiceListener.onServiceConnected(BluetoothProfile.HEALTH, BluetoothHealth.this);
}
}
...
BluetoothHidHost(Context context, ServiceListener l) {
...
doBind();
}
boolean doBind() {
Intent intent = new Intent(IBluetoothHidHost.class.getName());
ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
intent.setComponent(comp);
if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
mContext.getUser())) {
Log.e(TAG, "Could not bind to Bluetooth HID Service with " + intent);
return false;
}
return true;
}
dobind時(shí),就和上面講解的API調(diào)用流程比較類似苞轿,綁定服務(wù)茅诱,并把bluetooth apk里的service,回調(diào)給mConnection搬卒。這樣BluetoothHidHost就綁定了bluetooth apk里的HIDProfile service 并獲得代理對(duì)象让簿。在mConnection中,又通過(guò)剛才HidProfile 傳入的listenner回調(diào)傳回service秀睛,讓HidProfile 也擁有了Bluetooth apk中的這個(gè)service尔当。
3、流程概述
<1>蹂安、1,2流程下來(lái)椭迎。settinglib中打開(kāi)時(shí)就會(huì)創(chuàng)建支持的profile,這些profile創(chuàng)建的時(shí)候田盈,都大同小異的讓BluetoothAdapter也創(chuàng)一個(gè)名字類似的profile畜号,讓兩個(gè)profile都拿到bluetooth apk中對(duì)應(yīng)協(xié)議的service。當(dāng)profile拿到service了允瞧,有了bluetooth apk具體的實(shí)現(xiàn)了简软,就能調(diào)用到具體的功能上了蛮拔。
<2>、注意這里的service和協(xié)議的service/client中的service要區(qū)分開(kāi)痹升。client也是在要bluetooth apk運(yùn)行一個(gè)服務(wù)來(lái)供系統(tǒng)使用建炫。
<3>、三方應(yīng)用可以BluetoothAdapter#getProfileProxy來(lái)拿到profile操作疼蛾。一般profile實(shí)現(xiàn)的方法也不多肛跌,只能調(diào)用一些簡(jiǎn)單的方法。有哪些公開(kāi)api直接打開(kāi)某個(gè)profile就能看到
BluetoothManagerService小結(jié)
由于service的特性察郁,就是各個(gè)功能的具體實(shí)現(xiàn)衍慎。所以對(duì)于service的分析一般都是流程為主。BluetoothManagerService的功能和系統(tǒng)其他服務(wù)比相對(duì)比較簡(jiǎn)單皮钠∥壤Γ基本就是綁定bluetoothapk 的service,具體的實(shí)現(xiàn)還是都在Bluetooth apk里麦轰。
3.3乔夯、bluetooth apk
這部分代碼芯片廠商一般有自己的私有定制,未開(kāi)放源碼原朝,學(xué)習(xí)這部分參考AOSP源碼package/app/bluetooth
Bluetooth apk里就是我們藍(lán)牙功能具體的實(shí)現(xiàn)了驯嘱。常規(guī)打開(kāi)關(guān)閉功能在AdapterService入口實(shí)現(xiàn)镶苞。這些方法最后跟蹤都會(huì)跟蹤到native方法上喳坠。由于方法流程很多,這里以打開(kāi)流程來(lái)舉例介紹
3.3.1茂蚓、AdapterService#enable
enable就是打開(kāi)的入口壕鹉,我們跟一下打開(kāi)流程
1、狀態(tài)機(jī)開(kāi)始工作
private AdapterState mAdapterStateMachine;
public synchronized boolean enable(boolean quietMode) {
...
mAdapterStateMachine.sendMessage(AdapterState.BLE_TURN_ON);
}
AdapterState.java代碼片段
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);
}
打開(kāi)的工作交給了AdapterState聋涨。AdapterState 是一個(gè)狀態(tài)機(jī)晾浴,狀態(tài)機(jī)改變狀態(tài)時(shí)就會(huì)執(zhí)行類的一些行為。Android的狀態(tài)機(jī)制一般用于復(fù)雜狀態(tài)+復(fù)雜操作牍白。這里你可以簡(jiǎn)單理解為狀態(tài)切一下就會(huì)去執(zhí)行對(duì)應(yīng)操作脊凰。
構(gòu)造函數(shù)默認(rèn)是mOffState,收到BLE_TURN_ON消息茂腥。那么第一個(gè)地方就是OffState的processMessage處理BLE_TURN_ON狸涌,消息也是再直接傳遞到TurningBleOnState
private class OffState extends BaseAdapterState {
...
@Override
public boolean processMessage(Message msg) {
switch (msg.what) {
case BLE_TURN_ON:
transitionTo(mTurningBleOnState);
break;
}
}
2、把打開(kāi)消息傳給GattService
private class TurningBleOnState extends BaseAdapterState {
...
@Override
public void enter() {
super.enter();
sendMessageDelayed(BLE_START_TIMEOUT, BLE_START_TIMEOUT_DELAY);
mAdapterService.bringUpBle();
}
...
@Override
public boolean processMessage(Message msg) {
switch (msg.what) {
case BLE_STARTED:
transitionTo(mBleOnState);
break;
void bringUpBle() {
...
//Start Gatt service
setProfileServiceState(GattService.class, BluetoothAdapter.STATE_ON);
}
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;
3最岗、GattService打開(kāi)藍(lán)牙
private void processProfileServiceStateChanged(ProfileService profile, int state) {
switch (state) {
case BluetoothAdapter.STATE_ON:
...
if (GattService.class.getSimpleName().equals(profile.getName())) {
enableNativeWithGuestFlag();
}
private void enableNativeWithGuestFlag() {
boolean isGuest = UserManager.get(this).isGuestUser();
if (!enableNative(isGuest)) {
Log.e(TAG, "enableNative() returned false");
}
}
這樣就調(diào)用到了底層實(shí)現(xiàn)的native方法
3.3.2帕胆、其他協(xié)議啟動(dòng)
上面3.3.1講解BluetoothAdapter#enable時(shí),BluetoothManagerService代碼從BluetoothManagerService調(diào)用到bluetooh apk的Adapterservice最后一步BluetoothServiceConnection 回調(diào)MESSAGE_BLUETOOTH_SERVICE_CONNECTED信息般渡,代碼從這里接著開(kāi)始懒豹。
1芙盘、framwork調(diào)用到bluetooth apk里
private class BluetoothHandler extends Handler {
...
@Override
public void handleMessage(Message msg) {
case MESSAGE_BLUETOOTH_SERVICE_CONNECTED: {
IBinder service = (IBinder) msg.obj;
try {
mBluetoothLock.writeLock().lock();
if (msg.arg1 == SERVICE_IBLUETOOTHGATT) {
mBluetoothGatt = IBluetoothGatt.Stub.asInterface(Binder.allowBlocking(service));
continueFromBleOnState();
break;
}
private void continueFromBleOnState() {
...
mBluetooth.onLeServiceUp();
}
BluetoothManagerService#enable講解最后這里拿到了service。同時(shí)也是這里的continueFromBleOnState脸秽,開(kāi)起了bluetooth apk里其他所有支持的profile的service儒老。
2、Adapterservice#startProfileServices
接著又是狀態(tài)機(jī)一頓切換豹储,切換流程和上面狀態(tài)機(jī)一樣贷盲,這里簡(jiǎn)略
void onLeServiceUp() {
mAdapterStateMachine.sendMessage(AdapterState.USER_TURN_ON);
}
private class TurningOnState extends BaseAdapterState {
@Override
public void enter() {
...
mAdapterService.startProfileServices();
}
void startProfileServices() {
Class[] supportedProfileServices = Config.getSupportedProfiles();
...
setAllProfileServiceStates(supportedProfileServices, BluetoothAdapter.STATE_ON);
}
}
private void setAllProfileServiceStates(Class[] services, int state) {
for (Class service : services) {
if (GattService.class.getSimpleName().equals(service.getSimpleName())) {
continue;
}
setProfileServiceState(service, state);
}
}
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);
}
Config.getSupportedProfiles拿到的是配置文件中列出來(lái)支持的所有協(xié)議。然后全部把profile的狀態(tài)置為STATE_ON
最后一個(gè)for循環(huán)遍歷startService開(kāi)起所有支持的服務(wù)
bluetooth apk小結(jié)
1剥扣、bluetooth apk是藍(lán)牙功能實(shí)現(xiàn)的地方巩剖。
2、bluetooth apk里的代碼主要靠adapterservice工作運(yùn)行钠怯。
3佳魔、adapterservice提供了底層so庫(kù)的入口。也提供了供framework使用的方法晦炊。
4鞠鲜、adapterservice藍(lán)牙操作相關(guān)主要靠AdapterState狀態(tài)機(jī)來(lái)切換
3.4、SettingsLib
1断国、SettingsLib和bluetoothAdapter類似以API運(yùn)用為主贤姆,這部分以表格方式
2、首先SettingsLib包含了很多功能稳衬,它的目的是封裝一些操作霞捡。專注服務(wù)于settings app。本文只對(duì)settingslib中bluetooth部分分析薄疚。本文開(kāi)頭部分簡(jiǎn)單介紹settingsLib的時(shí)候?qū)β窂较碌膒rofile進(jìn)行了表格統(tǒng)計(jì)碧信,并說(shuō)明了他們的功能。settingslib中的bletooth代碼除了這部分協(xié)議,剩下幾個(gè)LocalManager對(duì)藍(lán)牙的操作封裝處理街夭。這個(gè)Manager我們也先以表格的形式簡(jiǎn)單統(tǒng)計(jì)說(shuō)明砰碴。
名稱 | 簡(jiǎn)單介紹 |
---|---|
LocalBluetoothAdapter | 絕大部分都是對(duì)BluetoothAdapter間接調(diào)用 |
CachedBluetoothDeviceManager | 管理已配對(duì)設(shè)備列表 |
BluetoothEventManager | 接收藍(lán)牙相關(guān)廣播和藍(lán)牙的一些回調(diào),并根據(jù)UI操作執(zhí)行到對(duì)應(yīng)的事件 |
LocalBluetoothProfileManager | 對(duì)外提供可用profile的訪問(wèn) |
LocalBluetoothManager | 統(tǒng)一管理CachedBluetoothDeviceManager板丽、LocalBluetoothProfileManager呈枉、BluetoothEventManager創(chuàng)建和獲取 |
有了前面三個(gè)部分的講解,settingslib的代碼看起來(lái)就很簡(jiǎn)單了埃碱。接下來(lái)分開(kāi)解析
3.4.1猖辫、LocalBluetoothAdapter裝飾者
LocalBluetoothAdapter用的是裝飾者模式,代理了BluetoothAdapter的一些方法乃正,并擴(kuò)展了極少功能住册。通篇LocalBluetoothAdapter的代碼除了代理外就把藍(lán)牙打開(kāi)狀態(tài)傳給了LocalBluetoothProfileManager
public boolean enable() {
return mAdapter.enable();
}
synchronized void setBluetoothStateInt(int state) {
mState = state;
if (state == BluetoothAdapter.STATE_ON) {
...
if (mProfileManager != null) {
mProfileManager.setBluetoothStateOn();
}
}
}
3.4.2、CachedBluetoothDeviceManager配對(duì)設(shè)備
CachedBluetoothDeviceManager管理已連接設(shè)備瓮具,里邊用兩個(gè)ArrayList一個(gè)Map來(lái)存儲(chǔ)荧飞。助聽(tīng)器設(shè)備單獨(dú)用了一個(gè)list存儲(chǔ)凡人。
對(duì)象 | 作用 |
---|---|
List<CachedBluetoothDevice> mCachedDevices | 已配對(duì)設(shè)備 |
List<CachedBluetoothDevice> mHearingAidDevicesNotAddedInCache | 助聽(tīng)器列表供UI顯示 |
final Map<Long, CachedBluetoothDevice> mCachedDevicesMapForHearingAids | 助聽(tīng)器是兩個(gè)設(shè)備時(shí),另一個(gè)設(shè)備存在這個(gè)list里 |
下面是CachedBluetoothDeviceManager提供的方法列表
方法 | 作用 |
---|---|
getCachedDevicesCopy | 拷貝已配對(duì)設(shè)備List |
onDeviceDisappeared | 設(shè)備消失 |
onDeviceNameUpdated | 設(shè)備名稱更新 |
findDevice | 存儲(chǔ)的兩個(gè)list中查找 |
addDevice | 添加設(shè)備到對(duì)應(yīng)list/map |
isPairAddedInCache | 是否在配對(duì)列表中 |
getHearingAidPairDeviceSummary | 已配對(duì)助聽(tīng)描述 |
addDeviceNotaddedInMap | 添加到map |
updateHearingAidsDevices | 助聽(tīng)設(shè)備刷新?tīng)顟B(tài)后更新列表 |
getName | 有名字返回名字叹阔,沒(méi)有名字返回mac地址 |
clearNonBondedDevices | 從三個(gè)列表中移除沒(méi)有綁定過(guò)狀態(tài)的設(shè)備 |
onScanningStateChanged | 開(kāi)始掃描更新排序狀態(tài) |
onBtClassChanged | 藍(lán)牙設(shè)備描述變化 |
onUuidChanged | uuid變化 |
onBluetoothStateChanged | 藍(lán)牙開(kāi)關(guān)挠轴,關(guān)閉需清空列表,打卡需刷新信息 |
onActiveDeviceChanged | profile是否存活 |
onHiSyncIdChanged | 助聽(tīng)設(shè)備類型變化 |
getHearingAidOtherDevice | 獲得助聽(tīng)設(shè)備 |
hearingAidSwitchDisplayDevice | 助聽(tīng)設(shè)備一對(duì)耳幢,選擇哪個(gè)顯示到UI列表 |
onProfileConnectionStateChanged | 協(xié)議監(jiān)聽(tīng)刷新助聽(tīng)設(shè)備列表 |
onDeviceUnpaired | 取消配對(duì)岸晦,更新列表 |
dispatchAudioModeChanged | audio狀態(tài)變化 |
3.4.3、BluetoothEventManager處理Event變化
BluetoothEventManager接收藍(lán)牙相關(guān)廣播和藍(lán)牙的一些回調(diào)睛藻,并根據(jù)UI操作執(zhí)行到對(duì)應(yīng)的事件启上。
BluetoothEventManager設(shè)計(jì)思想也很簡(jiǎn)單,就是監(jiān)聽(tīng)所有需要關(guān)心的藍(lán)牙廣播店印。收到狀態(tài)后把傳給CallBack或者其他Manager
1冈在、構(gòu)造函數(shù)監(jiān)聽(tīng)廣播
BluetoothEventManager(LocalBluetoothAdapter adapter,
CachedBluetoothDeviceManager deviceManager, Context context) {
...
// 藍(lán)牙開(kāi)關(guān)
addHandler(BluetoothAdapter.ACTION_STATE_CHANGED, new AdapterStateChangedHandler());
// 藍(lán)牙連接
addHandler(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED,
new ConnectionStateChangedHandler());
// 藍(lán)牙發(fā)現(xiàn)廣播
addHandler(BluetoothAdapter.ACTION_DISCOVERY_STARTED, new ScanningStateChangedHandler(true));
addHandler(BluetoothAdapter.ACTION_DISCOVERY_FINISHED, new ScanningStateChangedHandler(false));
addHandler(BluetoothDevice.ACTION_FOUND, new DeviceFoundHandler());
addHandler(BluetoothDevice.ACTION_DISAPPEARED, new DeviceDisappearedHandler());
addHandler(BluetoothDevice.ACTION_NAME_CHANGED, new NameChangedHandler());
addHandler(BluetoothDevice.ACTION_ALIAS_CHANGED, new NameChangedHandler());
//配對(duì)
addHandler(BluetoothDevice.ACTION_BOND_STATE_CHANGED, new BondStateChangedHandler());
// 遠(yuǎn)端設(shè)備描述信息
addHandler(BluetoothDevice.ACTION_CLASS_CHANGED, new ClassChangedHandler());
addHandler(BluetoothDevice.ACTION_UUID, new UuidChangedHandler());
addHandler(BluetoothDevice.ACTION_BATTERY_LEVEL_CHANGED, new BatteryLevelChangedHandler());
// 藍(lán)牙底座設(shè)備狀態(tài),比如車載電源充電狀態(tài)
addHandler(Intent.ACTION_DOCK_EVENT, new DockEventHandler());
//藍(lán)牙協(xié)議開(kāi)始活動(dòng)廣播
addHandler(BluetoothA2dp.ACTION_ACTIVE_DEVICE_CHANGED,
new ActiveDeviceChangedHandler());
addHandler(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED,
new ActiveDeviceChangedHandler());
addHandler(BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED,
new ActiveDeviceChangedHandler());
// 音頻策略按摘,聯(lián)系人
addHandler(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED,
new AudioModeChangedHandler());
addHandler(TelephonyManager.ACTION_PHONE_STATE_CHANGED,
new AudioModeChangedHandler());
...
}
2包券、回調(diào)給監(jiān)聽(tīng)
廣播來(lái)了,就遍歷回調(diào)Callback炫贤,給manager設(shè)置狀態(tài)溅固。以StateChanged舉例:
private class AdapterStateChangedHandler implements Handler {
public void onReceive(Context context, Intent intent,
BluetoothDevice device) {
int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
BluetoothAdapter.ERROR);
// Reregister Profile Broadcast Receiver as part of TURN OFF
if (state == BluetoothAdapter.STATE_OFF)
{
context.unregisterReceiver(mProfileBroadcastReceiver);
registerProfileIntentReceiver();
}
// update local profiles and get paired devices
mLocalAdapter.setBluetoothStateInt(state);
// send callback to update UI and possibly start scanning
synchronized (mCallbacks) {
for (BluetoothCallback callback : mCallbacks) {
callback.onBluetoothStateChanged(state);
}
}
// Inform CachedDeviceManager that the adapter state has changed
mDeviceManager.onBluetoothStateChanged(state);
}
}
**3、BluetoothCallback **
親切的BluetoothCallback 兰珍,我們監(jiān)聽(tīng)都是從這兒來(lái)監(jiān)聽(tīng)
public interface BluetoothCallback {
void onBluetoothStateChanged(int bluetoothState);
void onScanningStateChanged(boolean started);
void onDeviceAdded(CachedBluetoothDevice cachedDevice);
void onDeviceDeleted(CachedBluetoothDevice cachedDevice);
void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState);
void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state);
void onActiveDeviceChanged(CachedBluetoothDevice activeDevice, int bluetoothProfile);
void onAudioModeChanged();
default void onProfileConnectionStateChanged(CachedBluetoothDevice cachedDevice,
int state, int bluetoothProfile) {
}
}
3.4.4侍郭、LocalBluetoothProfileManager
LocalBluetoothProfileManager是統(tǒng)一管理settings支持的profile的地方,提供profile的訪問(wèn)和狀態(tài)變化監(jiān)聽(tīng)俩垃。profile創(chuàng)建和綁定的流程在BluetoothManagerService部分已經(jīng)分析励幼。這些profile也是文章開(kāi)頭部分列出settinglib中的profile汰寓。用了Map<String, LocalBluetoothProfile>mProfileNameMap 來(lái)存儲(chǔ)口柳。
private A2dpProfile mA2dpProfile;
private A2dpSinkProfile mA2dpSinkProfile;
private HeadsetProfile mHeadsetProfile;
private HfpClientProfile mHfpClientProfile;
private MapProfile mMapProfile;
private MapClientProfile mMapClientProfile;
private HidProfile mHidProfile;
private HidDeviceProfile mHidDeviceProfile;
private OppProfile mOppProfile;
private PanProfile mPanProfile;
private PbapClientProfile mPbapClientProfile;
private PbapServerProfile mPbapProfile;
private final boolean mUsePbapPce;
private final boolean mUseMapClient;
private HearingAidProfile mHearingAidProfile;
創(chuàng)建的代碼都在打開(kāi)藍(lán)牙的時(shí)候調(diào)用setBluetoothStateOn
void setBluetoothStateOn() {
if (mHidProfile == null) {
mHidProfile = new HidProfile(mContext, mLocalAdapter, mDeviceManager, this);
addProfile(mHidProfile, HidProfile.NAME,
BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED);
}
if (mPanProfile == null) {
mPanProfile = new PanProfile(mContext, mLocalAdapter);
addPanProfile(mPanProfile, PanProfile.NAME,
BluetoothPan.ACTION_CONNECTION_STATE_CHANGED);
}
if (mHidDeviceProfile == null) {
mHidDeviceProfile = new HidDeviceProfile(mContext, mLocalAdapter, mDeviceManager, this);
addProfile(mHidDeviceProfile, HidDeviceProfile.NAME,
BluetoothHidDevice.ACTION_CONNECTION_STATE_CHANGED);
}
....
//等等其他profile創(chuàng)建
3.4.5、LocalBluetoothManager
LocalBluetoothManager是這個(gè)manager里最簡(jiǎn)單的了就是創(chuàng)建著幾個(gè)manager有滑,方便對(duì)外獲取manager跃闹。
private LocalBluetoothManager(LocalBluetoothAdapter adapter, Context context) {
mContext = context;
mLocalAdapter = adapter;
mCachedDeviceManager = new CachedBluetoothDeviceManager(context, this);
mEventManager = new BluetoothEventManager(mLocalAdapter,
mCachedDeviceManager, context);
mProfileManager = new LocalBluetoothProfileManager(context,
mLocalAdapter, mCachedDeviceManager, mEventManager);
mEventManager.readPairedDevices();
}
SettingsLib小結(jié)
1、SettingsLib主要供settings使用毛好,封裝一些操作望艺。
2、四個(gè)部分(代理Adapter肌访、管理配對(duì)設(shè)備找默、管理profile、監(jiān)聽(tīng)藍(lán)牙狀態(tài))
四吼驶、寫在最后
1惩激、通篇文章下來(lái)店煞,我們可以看到Android藍(lán)牙的架構(gòu)并不復(fù)雜。client提供對(duì)外接口风钻,service通過(guò)綁定Bluetooth中Adapterservice對(duì)接上具體實(shí)現(xiàn)顷蟀。最后settingslib封裝一些操作供settings使用更便捷。層次分明骡技。不像其他系統(tǒng)service和別的系統(tǒng)service有很多相互作用操作鸣个。
2、框架層的講解為的是幫助大家對(duì)Android藍(lán)牙整體的理解布朦。往細(xì)了講囤萤,service、Bluetooth是趴、settings里邊還有很多細(xì)節(jié)代碼可以扣阁将。每個(gè)profile還有很具體的用法用例。
3右遭、源碼真香
Read the fucking source code!