首先介紹下幾個重要的類:
在Android 4.3中引入了一個新的類BluetoothManager,它是一個high level manager,被用於”to obtain an instance of an BluetoothAdapter and conduct overall Bluetooth Management“。
LocalBluetoothManager.java 提供了藍牙API上的簡單調用接口,本機藍牙設備管理,開啓關閉,搜索等等)。
BluetoothEnabler.java 界面的點擊和狀態文字的顯示。
流程爲:Settings的BluetoothEnabler類(對應於UI上看到的Bluetooth開關),得到代表local device的BluetoothAdapter。
看源碼:
可以看出BluetoothEnabler在構造裏會先調用 LocalBluetoothManager.getInstance(context),在getInstance裏會調用init()函數,BluetoothAdapter.getDefaultAdapter()獲得藍牙設備的句柄,如果當前沒有藍牙設備則返回null。 源碼中manager可以對本地藍牙進行管理,並且manager湖區得到mLocalAdapter(本地藍牙適配器)。同時設置藍牙適配器的事件過濾mIntentFilter。
即:BluetoothEnabler->LocalBluetoothManager->BluetoothAdapter;
這裏的BluetoothAdapter:framework封裝的類,提供本地藍牙設備的配置,包括開啓藍牙,搜索周圍藍牙設備,設置本地藍牙可見性。
enable藍牙:
1、開啓藍牙的service
從界面上看藍牙開關就是設置settings裏那個switch開關,widget開關當然也可以,起點不同而已,後續的流程是一樣的。先來看systemServer.java的代碼,藍牙服務開啓的地方,最後一個else分支是我們關心的,前兩個是模擬器的一個測試模式的。
- if (SystemProperties.get("ro.kernel.qemu").equals("1")) {
- Slog.i(TAG, "No Bluetooh Service (emulator)");
- } else if (factoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
- Slog.i(TAG, "No Bluetooth Service (factory test)");
- } else {
- Slog.i(TAG, "Bluetooth Manager Service");
- bluetooth = new BluetoothManagerService(context);
- ServiceManager.addService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE, bluetooth);
- }
暫且看下bluetoothManagerService的構造方法,代碼有點多,我們只看兩個地方, loadStoredNameAndAddress()是讀取藍牙打開默認名稱的地方,isBluetoothPersistedStateOn()是判斷是否已打開藍牙的,如果已打開,後續操作要執行開啓藍牙的動作,前面那幾行註冊廣播其中就有這個作用。
- BluetoothManagerService(Context context) {
- ...一些變量聲明初始化...
- IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
- filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
- filter.addAction(Intent.ACTION_USER_SWITCHED);
- registerForAirplaneMode(filter);
- mContext.registerReceiver(mReceiver, filter);
- loadStoredNameAndAddress();
- if (isBluetoothPersistedStateOn()) {
- mEnableExternal = true;
- }
- }
回到界面開關那個看得着的地方,界面上開關就是BluetoothEnabler.java這個類了。
2、Enable藍牙
當我們開啓藍牙的按鈕的時候會觸發一個事件:
看下代碼
- public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
- // Show toast message if Bluetooth is not allowed in airplane mode
- if (isChecked &&
- !WirelessSettings.isRadioAllowed(mContext, Settings.Global.RADIO_BLUETOOTH)) {
- Toast.makeText(mContext, R.string.wifi_in_airplane_mode, Toast.LENGTH_SHORT).show();
- // Reset switch to off
- buttonView.setChecked(false);
- }
- if (mLocalAdapter != null) {
- mLocalAdapter.setBluetoothEnabled(isChecked);
- }
- mSwitch.setEnabled(false);
- }
這裏在判斷是飛行模式不知道爲什麼沒有return,如果是飛行模式會有提示toast彈出,既然這樣源碼爲什麼還要執行下面打開流程呢,也許是個bug?不細究這個了,繼續看setBluetoothEnabled()方法做什麼了,很明顯mLocalAdapter(LocalBluetoothAdapter )只是個過渡,裏面的 mAdapter(BluetoothAdapter)纔是真正的主角,即開始開啓enable,代碼如下:
- public void setBluetoothEnabled(boolean enabled) {
- boolean success = enabled ? mAdapter.enable() : mAdapter.disable();
- if (success) {
- setBluetoothStateInt(enabled
- ? BluetoothAdapter.STATE_TURNING_ON
- : BluetoothAdapter.STATE_TURNING_OFF);
- } else {
- .........
- }
- }
- public static synchronized BluetoothAdapter getDefaultAdapter() {
- if (sAdapter == null) {
- IBinder b = ServiceManager.getService(BLUETOOTH_MANAGER_SERVICE);
- if (b != null) {
- IBluetoothManager managerService = IBluetoothManager.Stub.asInterface(b);
- sAdapter = new BluetoothAdapter(managerService);
- } else {
- Log.e(TAG, "Bluetooth binder is null");
- }
- }
- return sAdapter;
接着來說,此時我們更關心mAdapter.enable()的後續操作。
其中在這期間還做了些事情,AdapterService維護着一個狀態機。
1、AdapterService維護着一個狀態機AdapterState,所有工作都是通過驅動狀態機來完成的。AdapterState收到AdapterService發過來的USER_TURN_ON消息,就會調用AdapterService::processStart()來啓動Profie Services的初始化和Bluetooth hardware enable process。此時Bluetooth Adapter的狀態是BluetoothAdapter.STATE_TURNING_ON。
2、每一個profile都有一個service。每個profile service啓動完成後,都會通知AdapterService。當AdapterService::processProfileServiceSta
3、狀態機AdapterState::PendingCommandState::processMessage()收到AdapterState.STARTED消息後就立刻調用AdapterService::enableNative()。
4、AdapterService::enableNative()就是用來enable Bluetooth的Bluetooth JNI接口。enableNative()會調用Bluetooth HAL的enable()。
5、Bluedroid用btif_enable_bluetooth()來實現了Bluetooth HAL的enable()。
6、當Bluedroid真正完成了enable Bluetooth hardware,就通過btif_enable_bluetooth_evt()中的HAL_CBACK調用Bluetooth JNI的adapter_state_change_callback(),這樣就把BT_STATE_ON消息傳遞給了狀態機AdapterState。
7、AdapterState會把Bluetooth Adapter的狀態轉換到BluetoothAdapter.STATE_ON,並通過AdapterState::notifyAdapterStateChange
8、AdapterService::updateAdapterState()會通過callback函數通知BluetoothManagerService,Adapter狀態改變了。
9、BluetoothManagerService確認狀態發生了改變就會發出一個BluetoothAdapter.ACTION_STATE_CHANGE的intent。
10、Settings的BluetoothEnabler收到這個intent之後,就會去更新UI上Bluetooth開關的狀態。
流程圖如下:
繼續分析的話:
那就是去AdapterService裏看看,裏面一共有三個enable(),跳轉關係不復雜,我們直接看最後一個關鍵的。
- public synchronized boolean enable(boolean quietMode) {
- enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH ADMIN permission");
- if (DBG)debugLog("Enable called with quiet mode status = " + mQuietmode);
- mQuietmode = quietMode;
- Message m =
- mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_ON);
- mAdapterStateMachine.sendMessage(m);
- return true;
- }
處理在同文件下面的代碼裏
- case STARTED: {
- if (DBG) Log.d(TAG,"CURRENT_STATE=PENDING, MESSAGE = STARTED, isTurningOn=" + isTurningOn + ", isTurningOff=" + isTurningOff);
- //Remove start timeout
- removeMessages(START_TIMEOUT);
- //Enable
- boolean ret = mAdapterService.enableNative();
- if (!ret) {
- Log.e(TAG, "Error while turning Bluetooth On");
- notifyAdapterStateChange(BluetoothAdapter.STATE_OFF);
- transitionTo(mOffState);
- } else {
- sendMessageDelayed(ENABLE_TIMEOUT, ENABLE_TIMEOUT_DELAY);
- }
看到那個enableNative()函數調用了吧,又要用到JNI了,稍微回頭看下前面的代碼,我們先從應用界面開關BluetoothEnabler走到framework的BluetoothAdapter,又回到package的adapterService,現在又要去JNI的C++代碼了,往常一般是packages -->framework-->下面一層,這次順序有些顛倒了,不過這不能影響我們跟蹤代碼,最後
還是要到下面去的。一起往下看吧。
根據android JNI的函數命名慣例很容易找到enableNative對應的C++函數在packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterService.cpp裏面
- static jboolean enableNative(JNIEnv* env, jobject obj) {
- ALOGV("%s:",__FUNCTION__);
- jboolean result = JNI_FALSE;
- if (!sBluetoothInterface) return result;
- int ret = sBluetoothInterface->enable();
- result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
- return result;
- }
代碼瞬間簡潔了不少,看來更多的故事還在下面,sBluetoothInterface這是什麼,直接關係到下一步去哪的問題,看下變量聲明,原來是
Const bt_interface_t *sBluetoothInterface = NULL; 再去找在哪初始化,搜索external目錄可以找到/external/bluetooth/bluedroid/btif/src/bluetooth.c
- static const bt_interface_t bluetoothInterface = {
- sizeof(bt_interface_t),
- init,
- enable,
- disable,
- .............
- start_discovery,
- cancel_discovery,
- create_bond,
- remove_bond,
- cancel_bond,
- ...............
- };
- static int enable( void )
- {
- ALOGI("enable");
- /* sanity check */
- if (interface_ready() == FALSE)
- return BT_STATUS_NOT_READY;
- return btif_enable_bluetooth();
- }
- bt_status_t btif_enable_bluetooth(void)
- {
- BTIF_TRACE_DEBUG0("BTIF ENABLE BLUETOOTH");
- if (btif_core_state != BTIF_CORE_STATE_DISABLED)
- {
- ALOGD("not disabled\n");
- return BT_STATUS_DONE;
- }
- btif_core_state = BTIF_CORE_STATE_ENABLING;
- /* Create the GKI tasks and run them */
- bte_main_enable(btif_local_bd_addr.address);
- return BT_STATUS_SUCCESS;
- }
- void bte_main_enable(uint8_t *local_addr)
- {
- APPL_TRACE_DEBUG1("%s", __FUNCTION__);
- ........................
- #if (defined (BT_CLEAN_TURN_ON_DISABLED) && BT_CLEAN_TURN_ON_DISABLED == TRUE)
- APPL_TRACE_DEBUG1("%s Not Turninig Off the BT before Turninig ON", __FUNCTION__);
- #else
- /* toggle chip power to ensure we will reset chip in case
- a previous stack shutdown wasn't completed gracefully */
- bt_hc_if->set_power(BT_HC_CHIP_PWR_OFF);
- #endif
- bt_hc_if->set_power(BT_HC_CHIP_PWR_ON);
- bt_hc_if->preload(NULL);
- }
- .............................
- }
路徑在這裏/external/bluetooth/bluedroid/hci/src/bt_hci_bdroid.c,看看set_power裏面有什麼,快到頭了
- static void set_power(bt_hc_chip_power_state_t state)
- {
- int pwr_state;
- BTHCDBG("set_power %d", state);
- /* Calling vendor-specific part */
- pwr_state = (state == BT_HC_CHIP_PWR_ON) ? BT_VND_PWR_ON : BT_VND_PWR_OFF;
- if (bt_vnd_if)
- bt_vnd_if->op(BT_VND_OP_POWER_CTRL, &pwr_state);
- else
- ALOGE("vendor lib is missing!");
- }
- /* Entry point of DLib --
- * Vendor library needs to implement the body of bt_vendor_interface_t
- * structure and uses the below name as the variable name. HCI library
- * will use this symbol name to get address of the object through the
- * dlsym call.
- */
- extern const bt_vendor_interface_t BLUETOOTH_VENDOR_LIB_INTERFACE;
- bt_vendor_interface_t *bt_vnd_if=NULL;
google定義好了接口,具體實現要看vendor廠商來做了,這後面怎麼實現就看各家芯片商怎麼寫了,肯定各有不同,而且這一部分代碼一般是不會公開,當然授權購買後除外了。所以在4.2的源碼中我們只跟到這裏了,那後面會做什麼呢,加載驅動和上電這兩項肯定要有了,打開藍牙沒這兩步怎麼行,類似下面的字符串
- static const char* BT_DRIVER_MODULE_PATH = "/system/lib/modules/mbt8xxx.ko";
- static const char* BT_DRIVER_MODULE_NAME = "bt8xxx";
- static const char* BT_DRIVER_MODULE_INIT_ARG = " init_cfg=";
- static const char* BT_DRIVER_MODULE_INIT_CFG_PATH = "bt_init_cfg.conf";
在有類似下面的動作,insmod加載驅動,rfkill控制上下電,具體廠商具體做法也不同。
- ret = insmod(BT_DRIVER_MODULE_PATH, arg_buf);
- ret = system("/system/bin/rfkill block all");