4.2的藍(lán)牙打開流程這一部分還是有些變化的,從界面上看藍(lán)牙開關(guān)就是設(shè)置settings里那個(gè)switch開關(guān),widget開關(guān)當(dāng)然也可以,起點(diǎn)不同而已,后續(xù)的流程是一樣的。先來看systemServer.java的代碼,藍(lán)牙服務(wù)開啟的地方,最后一個(gè)else分支是我們關(guān)心的,前兩個(gè)是模擬器的一個(gè)測(cè)試模式的。
?
[java] ?view plaincopy ? 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的構(gòu)造方法,代碼有點(diǎn)多,我們只看兩個(gè)地方,?loadStoredNameAndAddress()是讀取藍(lán)牙打開默認(rèn)名稱的地方,isBluetoothPersistedStateOn()是判斷是否已打開藍(lán)牙的,如果已打開,后續(xù)操作要執(zhí)行開啟藍(lán)牙的動(dòng)作,前面那幾行注冊(cè)廣播其中就有這個(gè)作用。
?
[java] ?view plaincopy ? 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;?? ????????}?? ????}?? ?
? ? ? ? 回到界面開關(guān)那個(gè)看得著的地方,界面上開關(guān)就是BluetoothEnabler.java這個(gè)類了,而setBluetoothEnabled()則是具體開關(guān)動(dòng)作??聪麓a
?
[java] ?view plaincopy ? public?void?onCheckedChanged(CompoundButton?buttonView,?boolean?isChecked)?{?? ??????? ???????if?(isChecked?&&?? ???????????????!WirelessSettings.isRadioAllowed(mContext,?Settings.Global.RADIO_BLUETOOTH))?{?? ???????????Toast.makeText(mContext,?R.string.wifi_in_airplane_mode,?Toast.LENGTH_SHORT).show();?? ??????????? ???????????buttonView.setChecked(false);???????????? ???????}?? ?? ???????if?(mLocalAdapter?!=?null)?{?? ???????????mLocalAdapter.setBluetoothEnabled(isChecked);?? ???????}?? ???????mSwitch.setEnabled(false);?? ???}?? 這里在判斷是飛行模式不知道為什么沒有return,如果是飛行模式會(huì)有提示toast彈出,既然這樣源碼為什么還要執(zhí)行下面打開流程呢,也許是個(gè)bug?不細(xì)究這個(gè)了,繼續(xù)看setBluetoothEnabled()方法做什么了,很明顯mLocalAdapter(LocalBluetoothAdapter )只是個(gè)過渡,里面的?mAdapter(BluetoothAdapter)才是真正的主角,代碼如下:
?
[java] ?view plaincopy ? 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?{?? ???????.........?? ????}?? }?? ? ? ? ? 在BluetoothAdapter.java里可以看到一個(gè)單例模式的應(yīng)用,主要提供給其它程序調(diào)用藍(lán)牙的一些方法用的,外部程序想調(diào)用藍(lán)牙的方法就要先用這個(gè)
拿到BluetoothAdapter對(duì)象,代碼也簡單看下吧,里面是典型的binder應(yīng)用。
?
[java] ?view plaincopy ? 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;?? ? ? ? ? 此時(shí)我們更關(guān)心mAdapter.enable()的后續(xù)操作,外部其它應(yīng)用到getDefaultAdapter()也是調(diào)用enable(),注意,到了BluetoothAdapter我們已經(jīng)在framework層了,順著BluetoothAdapter.java的enable()調(diào)用先回到BluetoothManagerService.java的enable(),再進(jìn)一步來到BluetoothManagerService.java中的handleEnable()
方法,后面要跳轉(zhuǎn)到新類了,貼出來一起看下,這部分好像不同版本還有些出入,不過核心的啟動(dòng)service是一樣的,不影響理解。
?
[java] ?view plaincopy ? ?private?void?handleEnable(boolean?persist,?boolean?quietMode)?{?? ?synchronized(mConnection)?{?? ????if?((mBluetooth?==?null)?&&?(!mBinding))?{?? ???????? ????????Message?timeoutMsg=mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);?? ????????mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS);?? ????????mConnection.setGetNameAddressOnly(false);?? ????????Intent?i?=?new?Intent(IBluetooth.class.getName());?? ????????if?(!mContext.bindService(i,?mConnection,Context.BIND_AUTO_CREATE,?? ??????????????????????????????????UserHandle.USER_CURRENT))?{?? ????????????mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);?? ????????????Log.e(TAG,?"Fail?to?bind?to:?"?+?IBluetooth.class.getName());?? ????????}?else?{?? ????????????mBinding?=?true;?? ????????}?? ????}??? ? ? ? ?下面跑到哪個(gè)service里去了呢,在log信息里可以看到"ActivityManager: Start proc com.android.bluetooth for service com.android.bluetooth/.btservice.AdapterService:"
?
這樣的信息,那就是去AdapterService里看看,里面一共有三個(gè)enable(),跳轉(zhuǎn)關(guān)系不復(fù)雜,我們直接看最后一個(gè)關(guān)鍵的。
?
[java] ?view plaincopy ? 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;?? ?}?? ?狀態(tài)機(jī)來了,狀態(tài)轉(zhuǎn)換圖,從一個(gè)狀態(tài)接受命令跳到另一個(gè)狀態(tài),因?yàn)槲覀兪窃陂_啟藍(lán)牙,所以先去的AdapterState.java內(nèi)部類offstate.java里面找,在這個(gè)分支USER_TURN_ON看到mAdapterService.processStart();在這里面可以看到藍(lán)牙遍歷下所支持的profile,最后又發(fā)出個(gè)帶AdapterState.STARTED標(biāo)識(shí)的消息
處理在同文件下面的代碼里
?
[java] ?view plaincopy ? case?STARTED:???{?? ??if?(DBG)?Log.d(TAG,"CURRENT_STATE=PENDING,?MESSAGE?=?STARTED,?isTurningOn="?+?isTurningOn?+?",?isTurningOff="?+?isTurningOff);?? ?? ??removeMessages(START_TIMEOUT);?? ?? ?? ??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);?? ??}??? 看到那個(gè)enableNative()函數(shù)調(diào)用了吧,又要用到JNI了,稍微回頭看下前面的代碼,我們先從應(yīng)用界面開關(guān)BluetoothEnabler走到framework的BluetoothAdapter,又回到package的adapterService,現(xiàn)在又要去JNI的C++代碼了,往常一般是packages -->framework-->下面一層,這次順序有些顛倒了,不過這不能影響我們跟蹤代碼,最后
?
還是要到下面去的。一起往下看吧。
? ? ? ? 根據(jù)android JNI的函數(shù)命名慣例很容易找到enableNative對(duì)應(yīng)的C++函數(shù)在packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterService.cpp里面
?
[java] ?view plaincopy ? 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這是什么,直接關(guān)系到下一步去哪的問題,看下變量聲明,原來是
Const bt_interface_t *sBluetoothInterface = NULL; 再去找在哪初始化,搜索external目錄可以找到/external/bluetooth/bluedroid/btif/src/bluetooth.c
?
[cpp] ?view plaincopy ? ????static?const?bt_interface_t?bluetoothInterface?=?{?? ????sizeof(bt_interface_t),?? ????init,?? ????enable,?? ????disable,?? ????.............?? ????start_discovery,?? ????cancel_discovery,?? ????create_bond,?? ????remove_bond,?? ????cancel_bond,?? ???...............?? };?? 原來在這里,說下怎么找到,直接跳轉(zhuǎn)是不成了,看這個(gè)文件夾下的mk文件,那里面有l(wèi)ibhardware目錄是編譯的時(shí)候要用到,這個(gè)多半在hardware目錄里,在這里面很快可以看到bluetooth.h,那里面有最我們要找的結(jié)構(gòu)體定義,頭文件找到了,再找同名C文件就快了,好了繼續(xù)吧看下enable()里是怎么實(shí)現(xiàn)的
?
?
[cpp] ?view plaincopy ? static?int?enable(?void?)?? {?? ????ALOGI("enable");?? ?? ???? ????if?(interface_ready()?==?FALSE)?? ????????return?BT_STATUS_NOT_READY;?? ?? ????return?btif_enable_bluetooth();?? }?? 又是一個(gè)新函數(shù),直接跳轉(zhuǎn),比起剛才的尋覓這太幸福了
[cpp] ?view plaincopy ? 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;?? ?? ???? ????bte_main_enable(btif_local_bd_addr.address);?? ?? ????return?BT_STATUS_SUCCESS;?? }?? 忘了寫路徑了 好在可以直接跳轉(zhuǎn),下面是/external/bluetooth/bluedroid/main/bte_main.c,有點(diǎn)長,暫時(shí)只關(guān)心set_power那部分就好了,
[cpp] ?view plaincopy ? 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?? ???????? ????????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里面有什么,快到頭了
?
[cpp] ?view plaincopy ? static?void?set_power(bt_hc_chip_power_state_t?state)?? {?? ????int?pwr_state;?? ?? ????BTHCDBG("set_power?%d",?state);?? ?? ???? ????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!");?? }?? ? ? ? ? 這下又有新東西了bt_vnd_if,這個(gè)是什么,bt_vendor_interface_t *bt_vnd_if=NULL;和剛才的bt_interface_t 一樣,我們希望可以找到它的初始化,那樣就可以繼續(xù)跟蹤了,不過看到下面的代碼和注釋,在源碼中我們要絕望了。路徑:/external/bluetooth/bluedroid/hci/include/bt_vendor_lib.h
?
?
[cpp] ?view plaincopy ? extern?const?bt_vendor_interface_t?BLUETOOTH_VENDOR_LIB_INTERFACE;?? ?? bt_vendor_interface_t?*bt_vnd_if=NULL;?? ?google定義好了接口,具體實(shí)現(xiàn)要看vendor廠商來做了,這后面怎么實(shí)現(xiàn)就看各家芯片商怎么寫了,肯定各有不同,而且這一部分代碼一般是不會(huì)公開,當(dāng)然授權(quán)購買后除外了。所以在4.2的源碼中我們只跟到這里了,那后面會(huì)做什么呢,加載驅(qū)動(dòng)和上電這兩項(xiàng)肯定要有了,打開藍(lán)牙沒這兩步怎么行,類似下面的字符串
?
?
[cpp] ?view plaincopy ? 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";?? 在有類似下面的動(dòng)作,insmod加載驅(qū)動(dòng),rfkill控制上下電,具體廠商具體做法也不同。
?
[cpp] ?view plaincopy ? ret?=?insmod(BT_DRIVER_MODULE_PATH,?arg_buf);?? ret?=?system("/system/bin/rfkill?block?all");?? ? ? ? ?寫到這,關(guān)于4.2源碼的藍(lán)牙打開流程就算結(jié)束了,比起4.1之前的代碼感覺沒有以前的直觀,對(duì)于vendor那部分的代碼大家只能看各自廠商的代碼了,一般藍(lán)牙開啟后才會(huì)上電,這樣也比較符合邏輯和節(jié)省電量,是否上電可以連上手機(jī)用adb shell看sys/class/rfkill目錄下的state狀態(tài)值,有些廠商會(huì)把藍(lán)牙和wifi的上電算在一起,這個(gè)也是要注意的,小心誤判。最后呢,這次文章寫得有點(diǎn)倉促,寫錯(cuò)的或遺漏地方希望朋友指出來,非常感謝。
轉(zhuǎn)載于:https://www.cnblogs.com/Free-Thinker/p/4539973.html
總結(jié)
以上是生活随笔 為你收集整理的android -- 蓝牙 bluetooth (二) 打开蓝牙 的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔 推薦給好友。