php律師網(wǎng)站源碼推廣計劃方案模板
轉(zhuǎn)自:http://blog.csdn.net/baimy1985/article/details/8922508
?
4.2的藍(lán)牙打開流程這一部分還是有些變化的,從界面上看藍(lán)牙開關(guān)就是設(shè)置settings里那個switch開關(guān),widget開關(guān)當(dāng)然也可以,起點(diǎn)不同而已,后續(xù)的流程是一樣的。先來看systemServer.java的代碼,藍(lán)牙服務(wù)開啟的地方,最后一個else分支是我們關(guān)心的,前兩個是模擬器的一個測試模式的。
- 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);??
- ???????????}?????
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)多,我們只看兩個地方,?loadStoredNameAndAddress()是讀取藍(lán)牙打開默認(rèn)名稱的地方,isBluetoothPersistedStateOn()是判斷是否已打開藍(lán)牙的,如果已打開,后續(xù)操作要執(zhí)行開啟藍(lán)牙的動作,前面那幾行注冊廣播其中就有這個作用。
- 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;??
- ????????}??
- ????}??
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)那個看得著的地方,界面上開關(guān)就是BluetoothEnabler.java這個類了,而setBluetoothEnabled()則是具體開關(guān)動作??聪麓a
- 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);??
- ???}??
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彈出,既然這樣源碼為什么還要執(zhí)行下面打開流程呢,也許是個bug?不細(xì)究這個了,繼續(xù)看setBluetoothEnabled()方法做什么了,很明顯mLocalAdapter(LocalBluetoothAdapter )只是個過渡,里面的?mAdapter(BluetoothAdapter)才是真正的主角,代碼如下:
- 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 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里可以看到一個單例模式的應(yīng)用,主要提供給其它程序調(diào)用藍(lán)牙的一些方法用的,外部程序想調(diào)用藍(lán)牙的方法就要先用這個
拿到BluetoothAdapter對象,代碼也簡單看下吧,里面是典型的binder應(yīng)用。
- 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;??
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;
}
? ? ? ? 此時我們更關(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)到新類了,貼出來一起看下,這部分好像不同版本還有些出入,不過核心的啟動service是一樣的,不影響理解。
- ?private?void?handleEnable(boolean?persist,?boolean?quietMode)?{??
- ?synchronized(mConnection)?{??
- ????if?((mBluetooth?==?null)?&&?(!mBinding))?{??
- ????????//Start?bind?timeout?and?bind ??
- ????????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;??
- ????????}??
- ????}???
private void handleEnable(boolean persist, boolean quietMode) {
synchronized(mConnection) {
if ((mBluetooth == null) && (!mBinding)) {
//Start bind timeout and bind
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;
}
}?
? ? ? ?下面跑到哪個service里去了呢,在log信息里可以看到"ActivityManager: Start proc com.android.bluetooth for service com.android.bluetooth/.btservice.AdapterService:"
這樣的信息,那就是去AdapterService里看看,里面一共有三個enable(),跳轉(zhuǎn)關(guān)系不復(fù)雜,我們直接看最后一個關(guān)鍵的。
- 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;??
- ?}??
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)換圖,從一個狀態(tài)接受命令跳到另一個狀態(tài),因?yàn)槲覀兪窃陂_啟藍(lán)牙,所以先去的AdapterState.java內(nèi)部類offstate.java里面找,在這個分支USER_TURN_ON看到mAdapterService.processStart();在這里面可以看到藍(lán)牙遍歷下所支持的profile,最后又發(fā)出個帶AdapterState.STARTED標(biāo)識的消息
處理在同文件下面的代碼里
- 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);??
- ??}???
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()函數(shù)調(diào)用了吧,又要用到JNI了,稍微回頭看下前面的代碼,我們先從應(yīng)用界面開關(guān)BluetoothEnabler走到framework的BluetoothAdapter,又回到package的adapterService,現(xiàn)在又要去JNI的C++代碼了,往常一般是packages -->framework-->下面一層,這次順序有些顛倒了,不過這不能影響我們跟蹤代碼,最后
還是要到下面去的。一起往下看吧。
? ? ? ? 根據(jù)android JNI的函數(shù)命名慣例很容易找到enableNative對應(yīng)的C++函數(shù)在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;??
- }??
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
- ????static?const?bt_interface_t?bluetoothInterface?=?{??
- ????sizeof(bt_interface_t),??
- ????init,??
- ????enable,??
- ????disable,??
- ????.............??
- ????start_discovery,??
- ????cancel_discovery,??
- ????create_bond,??
- ????remove_bond,??
- ????cancel_bond,??
- ???...............??
- };??
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)是不成了,看這個文件夾下的mk文件,那里面有l(wèi)ibhardware目錄是編譯的時候要用到,這個多半在hardware目錄里,在這里面很快可以看到bluetooth.h,那里面有最我們要找的結(jié)構(gòu)體定義,頭文件找到了,再找同名C文件就快了,好了繼續(xù)吧看下enable()里是怎么實(shí)現(xiàn)的
- static?int?enable(?void?)??
- {??
- ????ALOGI("enable");??
- ??
- ????/*?sanity?check?*/??
- ????if?(interface_ready()?==?FALSE)??
- ????????return?BT_STATUS_NOT_READY;??
- ??
- ????return?btif_enable_bluetooth();??
- }??
static int enable( void )
{
ALOGI("enable");
/* sanity check */
if (interface_ready() == FALSE)
return BT_STATUS_NOT_READY;
return btif_enable_bluetooth();
}
又是一個新函數(shù),直接跳轉(zhuǎn),比起剛才的尋覓這太幸福了
- 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;??
- }??
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;
}
忘了寫路徑了 好在可以直接跳轉(zhuǎn),下面是/external/bluetooth/bluedroid/main/bte_main.c,有點(diǎn)長,暫時只關(guān)心set_power那部分就好了,
- 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);??
- ????}??
- ??
- ?????.............................??
- }??
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!");??
- }??
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!");
}
? ? ? ? 這下又有新東西了bt_vnd_if,這個是什么,bt_vendor_interface_t *bt_vnd_if=NULL;和剛才的bt_interface_t 一樣,我們希望可以找到它的初始化,那樣就可以繼續(xù)跟蹤了,不過看到下面的代碼和注釋,在源碼中我們要絕望了。路徑:/external/bluetooth/bluedroid/hci/include/bt_vendor_lib.h
- /*?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;??
/* 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定義好了接口,具體實(shí)現(xiàn)要看vendor廠商來做了,這后面怎么實(shí)現(xiàn)就看各家芯片商怎么寫了,肯定各有不同,而且這一部分代碼一般是不會公開,當(dāng)然授權(quán)購買后除外了。所以在4.2的源碼中我們只跟到這里了,那后面會做什么呢,加載驅(qū)動和上電這兩項(xiàng)肯定要有了,打開藍(lán)牙沒這兩步怎么行,類似下面的字符串
- 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";??
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加載驅(qū)動,rfkill控制上下電,具體廠商具體做法也不同。
- ret?=?insmod(BT_DRIVER_MODULE_PATH,?arg_buf);??
- ret?=?system("/system/bin/rfkill?block?all");??
ret = insmod(BT_DRIVER_MODULE_PATH, arg_buf);
ret = system("/system/bin/rfkill block all");
? ? ? ?寫到這,關(guān)于4.2源碼的藍(lán)牙打開流程就算結(jié)束了,比起4.1之前的代碼感覺沒有以前的直觀,對于vendor那部分的代碼大家只能看各自廠商的代碼了,一般藍(lán)牙開啟后才會上電,這樣也比較符合邏輯和節(jié)省電量,是否上電可以連上手機(jī)用adb shell看sys/class/rfkill目錄下的state狀態(tài)值,有些廠商會把藍(lán)牙和wifi的上電算在一起,這個也是要注意的,小心誤判。最后呢,這次文章寫得有點(diǎn)倉促,寫錯的或遺漏地方希望朋友指出來,非常感謝。
?