這應該只會是惟一的一篇從頭至尾的調用關係都分析一遍的文章,目的是爲了幫助初學者從上往下一層一層分析代碼,對大量的代碼再也不懼怕。若是是對閱讀Android代碼很熟悉的人能夠略過這一篇。java
Android的藍牙Enable是由BluetoothAdapter提供的。只須要調用BluetoothAdapter.enable()便可啓動藍牙。下面我就分析這一個過程。因爲Android的java層的代碼過多,我只順序的看下去。android
一、打開BluetoothAdapter.java,找到其中的enable方法,代碼以下:app
[java] view plaincopy函數
public boolean enable() { 學習
if (isEnabled() == true){ ui
if (DBG) Log.d(TAG, "enable(): BT is already enabled..!"); spa
return true; .net
} debug
try { 代理
return mManagerService.enable();
} catch (RemoteException e) {Log.e(TAG, "", e);}
return false;
}
發現關鍵的一句就是mManagerService.enable();這個mManagerService是什麼呢?其實就是btAdapter的一個proxy。能夠在getDefaultAdapter()裏面看到以下代碼
[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;
}
BluetoothAdapter(IBluetoothManager managerService) {
if (managerService == null) {
throw new IllegalArgumentException("bluetooth manager service is null");
}
try {
mService = managerService.registerAdapter(mManagerCallback); //這實際上是一步重要的操做,初始化了咱們的mService
} catch (RemoteException e) {Log.e(TAG, "", e);}
mManagerService = managerService;
mServiceRecordHandler = null;
}
它是經過ServiceManager獲取了一個系統服務,而後轉換爲了IBluetoothManager接口,讓mManagerService做爲 了bluetooth_manager服務的代理。這裏基本就能想到,這個bluetooth_manager服務多是Bluetooth.apk裏面 的btAdapter。可是咱們仍是得找找究竟是怎麼來的。
二、在frameworks/base/services/java/com/android/server/SystemServer.java裏面能夠看到這樣一句:
[java] view plaincopy
bluetooth = new BluetoothManagerService(context);
ServiceManager.addService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE, bluetooth);
哦,原來是用的一個BluetoothManagerService的東西註冊的服務,並非Bluetooth.apk裏面的。去看看是個什麼玩意兒。
三、打開BluetoothManagerService.java,能夠看到,這個東西就是BluetoothAdapter裏面的mManagerService的proxy了。下面看裏面的enable方法:
[java] view plaincopy
public boolean enable() {
//前面省略權限相關的東西
synchronized(mReceiver) {
mQuietEnableExternal = false;
mEnableExternal = true;
// waive WRITE_SECURE_SETTINGS permission check
long callingIdentity = Binder.clearCallingIdentity();
persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
Binder.restoreCallingIdentity(callingIdentity);
sendEnableMsg(false);
}
return true;
}
看到這裏的關鍵就是sendEnableMsg(),繼續tag進去看看究竟。
[java] view plaincopy
private void sendEnableMsg(boolean quietMode) {
mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE,
quietMode ? 1 : 0, 0));
}
額,又是Handler模式,這個玩意兒在Android系統裏面用得太多了。。遇到這種東西的時候,就進入到mHandler這個對象裏面的handleMessage去看switch---case就對了。
[java] view plaincopy
case MESSAGE_ENABLE:
mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);
mEnable = true;
handleEnable(msg.arg1 == 1);
break;
OK,去handleEnable裏面去看吧,這裏傳送的參數是0。這個handleEnable有點太長了,我就截取重要部分了
[java] view plaincopy
if ((mBluetooth == null) && (!mBinding)) {
//Start bind timeout and bind
Intent i = new Intent(IBluetooth.class.getName());
if (!mContext.bindService(i, mConnection,Context.BIND_AUTO_CREATE,
UserHandle.USER_CURRENT)) {
}
} else if (mBluetooth != null) {
="white-space:pre"> </span>//若是已經綁定了服務,就作其餘事……其實咱們通常調用,都是會進入這裏的。
}
//Enable bluetooth
try {
if (!mQuietEnable) {
if(!mBluetooth.enable()) {
Log.e(TAG,"IBluetooth.enable() returned false");
}
}
else {
if(!mBluetooth.enableNoAutoConnect()) {
Log.e(TAG,"IBluetooth.enableNoAutoConnect() returned false");
}
}
} catch (RemoteException e) {
Log.e(TAG,"Unable to call enable()",e);
}
好吧,轉那麼大的一圈,結果就是調用了mBluetooth.enable();並且蛋疼的是在BluetoothAdapter裏面原本就有 一個mService,而且mService就是registerAdapter()返回的mBluetooth!!不過親愛的朋友得注意了,咱們 BluetoothAdapter的mService的賦值是在這裏的bindService以前的,並且其餘的API的實現,都實際上是直接用的 mService,因此其實bindService是在BluetoothManagerService.java的另一個 MESSAGE_GET_NAME_AND_ADDRESS中調用的。真心蛋疼,這裏我我的以爲寫得很很差。
這個mBluetooth就是Bluetooth.apk裏面的AdapterService了。去看看代碼吧。
4.打開/packages/app/Bluetooth/src/com/android/bluetooth/btservice/AdapterService.java,找到關鍵代碼
[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;
}
額,用了StateMachine,直接搜索UER_TURN_ON找到processMessage吧(StateMachine就是狀態機,在不一樣的狀態下,收到相同的Event,作不一樣的事情)
[cpp] view plaincopy
notifyAdapterStateChange(BluetoothAdapter.STATE_TURNING_ON); //更新AdapterService裏的狀態爲TURNING_ON
mPendingCommandState.setTurningOn(true); //設置在等待狀態下的TurningOn爲打開狀態
transitionTo(mPendingCommandState); //轉移到Pending(等待)狀態
sendMessageDelayed(START_TIMEOUT, START_TIMEOUT_DELAY); //這個傢伙是設置超時的
mAdapterService.processStart(); //真正Enable藍牙的地方
繼續看processStart
[cpp] view plaincopy
void processStart() {
..................
if (!mProfilesStarted && supportedProfileServices.length >0) {
//Startup all profile services
setProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_ON);<span style="white-space:pre"> </span>//這種狀況下也會Call到else裏面的同樣的代碼
}else {
if (DBG) {debugLog("processStart(): Profile Services alreay started");}
mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.STARTED));
}
}
Android就是這麼煩,又進入了STARTED的狀態,此次是在Pending狀態下去看
[cpp] view plaincopy
//Remove start timeout
removeMessages(START_TIMEOUT); //去除超時的定時器
//Enable
boolean ret = mAdapterService.enableNative(); //。。。原來這裏纔是真正的enableNative
if (!ret) { //若是失敗了
notifyAdapterStateChange(BluetoothAdapter.STATE_OFF); //讓AdapterService進入失敗狀態
transitionTo(mOffState);
} else {
sendMessageDelayed(ENABLE_TIMEOUT, ENABLE_TIMEOUT_DELAY);
}
好了,這樣就從java層進入到Native層了。對於之後分析藍牙,我就直接分析Bluetooth.apk裏面的東西了,就不會涉及到任何其餘的java代碼了。
5.在Bluetooth APP裏面打開jni/com_android_bluetooth_btservice_AdapterService.cpp,找到裏面的enableNative();
[cpp] view plaincopy
jboolean result = JNI_FALSE;
if (!sBluetoothInterface) return result;
int ret = sBluetoothInterface->enable();
result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
return result;
嗯,直接調用了sBluetoothInterface裏面的enable();sBluetoothInterface的初始化在classInitNative(),這個函數大概作了如下的事情:
一、註冊java的回調函數(就是當下層已經打開藍牙了,而後要通知上層,藍牙已經打開了,java層就能夠發送藍牙打開的Broadcast了。)
二、初始化藍牙模塊的HAL接口。
三、獲得sBluetoothInterface
你須要對應着/external/bluetooth/bluedroid/btif/src/bluetooth.c看,就比較容易理解了。
五、接下來終於進入Bluedroid了,找到/external/bluetooth/bluedroid/btif/src /bluetooth.c裏面的enable函數,發現調用的btif_enable_bluetooth(),用tag進去看,發現原來整個分析的關鍵 點
[cpp] view plaincopy
bte_main_enable(btif_local_bd_addr.address);
這個函數有點長啊,在bluedroid/main/bte_main.c裏面,咱們就關心bt_hc_if->set_power就是了。前面有作一些初始化Bluedroid的動做
bt_hc_if是由bt_hc_get_interface()返回的。繼續tag進去看。
發如今bluedroid/hci/src/bt_hci_bdroid.c裏面的,有個set_power()
這個過程以下:
[cpp] view plaincopy
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->op(BT_VND_OP_POWER_CTRL, &pwr_state);bt_vnd_if在init_vnd_if()函數裏面賦值,發現實際上是一個libbt-vendor.so的 interface。好吧,能夠絕望了,這個是Vendor的library。
我解釋一下什麼是VND(Vendor)
Vendor就是芯片供應商的意思,在他們作好一塊藍牙芯片後,須要提供一些硬件相關的動做,好比上下電,設置波特率之類的。可是這些操做通常 不會對沒有許可的開放。Bluedroid提供了一個統一的接口bt_vendor_interface_t,供應商只須要實現這個接口定義的藍牙相關的 操做就能夠交給bluedroid去作剩下的事情了。
咱們繼續分析,既然原生的Android代碼可以編譯出來可用的Android系統,那麼裏面確定也有廠家提供的開放的libbt-vendor.so,咱們進入/hardware/裏面去執行如下命令
[cpp] view plaincopy
$ find . -name Android.mk | xargs grep "libbt"
返回結果:
[cpp] view plaincopy
$ find . -name Android.mk | xargs grep libbt
./qcom/bt/Android.mk:include $(call all-named-subdir-makefiles,libbt-vendor)
./qcom/bt/libbt-vendor/Android.mk:LOCAL_MODULE := libbt-vendor
哈哈,原來Nexus4用的高通提供的藍牙芯片,那咱們能夠繼續進去看咯。
打開./qcom/bt/libbt-vendor/bt_vendor_qcom.c,找到op函數,找到關鍵點
[cpp] view plaincopy
case BT_VND_OP_POWER_CTRL:
{
nState = *(int *) param;
retval = hw_config(nState);
if(nState == BT_VND_PWR_ON
&& retval == 0
&& is_hw_ready() == TRUE){
retval = 0;
}
else {
retval = -1;
}
}
break;
額,調用的hw_config(nState),進入看
[cpp] view plaincopy
int hw_config(int nState)
{
ALOGI("Starting hciattach daemon");
char *szState[] = {"true", "false"};
char *szReqSt = NULL;
if(nState == BT_VND_PWR_OFF)
szReqSt = szState[1];
else
szReqSt = szState[0];
ALOGI("try to set %s", szReqSt);
if (property_set("bluetooth.hciattach", szReqSt) < 0){
ALOGE("Property Setting fail");
return -1;
}
return 0;
}
看到這裏,我又蛋疼了。怎麼跟Android的前幾個版本實現同樣了。我到如今都不知道這個hciattach屬性是在哪裏定義的,估計可能根本沒有使用 這個東西,由於bluez的hciattach.c我沒有找到。因此爲了避免妨礙咱們學習,我又找到了Broadcom的Vendor實現
在/device/common/libbt/src/bt_vendor_brcm.c裏面的。一樣的方式找到了upio.c裏面的upio_set_bluetooth_power()
[cpp] view plaincopy
int upio_set_bluetooth_power(int on)
{
int sz;
int fd = -1;
int ret = -1;
char buffer = '0';
switch(on)
{
case UPIO_BT_POWER_OFF:
buffer = '0';
break;
case UPIO_BT_POWER_ON:
buffer = '1';
break;
}
if (is_emulator_context())
{
/* if new value is same as current, return -1 */
if (bt_emul_enable == on)
return ret;
UPIODBG("set_bluetooth_power [emul] %d", on);
bt_emul_enable = on;
return 0;
}
/* check if we have rfkill interface */
if (is_rfkill_disabled())
return 0;
if (rfkill_id == -1)
{
if (init_rfkill())
return ret;
}
fd = open(rfkill_state_path, O_WRONLY);
if (fd < 0)
{
ALOGE("set_bluetooth_power : open(%s) for write failed: %s (%d)",
rfkill_state_path, strerror(errno), errno);
return ret;
}
sz = write(fd, &buffer, 1);
if (sz < 0) {
ALOGE("set_bluetooth_power : write(%s) failed: %s (%d)",
rfkill_state_path, strerror(errno),errno);
}
else
ret = 0;
if (fd >= 0)
close(fd);
return ret;
}
好吧,原來就是在rfkill_state_path(/sys/class/rfkill/rfkill[x]/state)虛擬設備裏寫入了1。對於驅動的代碼,我就不繼續看了。畢竟目前我也沒深刻到那一塊去。
rfkill是Linux下的一個標準的無線控制的虛擬設備,Linux也提供了rfkill的命令去查看以及控制全部的註冊的無線設備。它們會在/dev/(PC的Linux)或者/sys/class(通常是Android)下生成相應的虛擬設備。
到這裏,整個藍牙的Enable過程就分析完了。。
整個過程十分累,從應用到下層。可是其實關鍵步驟就那麼幾步,從JNI那一塊開始入手的看,仍是比較好分析的。只要咱們願意深刻下去看,對於Bluedroid和藍牙的理解必定會更上一層。