藍芽系列之BlueDroid與MTK程式碼分佈
目錄:
0 應用層設計相關
一、application Framework
二、Bluetooth server層:服務層 包括兩部分--Bluetooth System service(部分)和Bluetooth profile;
2.1 mtk 封裝的庫(JNI和中間協議)
三、JNI
四、HAL
五、BT stack---- 實現(中間協議+核心協議)。
六、Vendor extension---也就是HCI驅動層的使用者空間介面
七 system\bluetoothBluetooth (mtk removed it )
八 核心層
九 驅動層
================================================================
0 應用層設計相關
kitkat_ibd\packages\apps\Settings\src\com\android\settings\bluetooth -----android 4.4 |
谷歌原生的profile管理介面。包括opp、hfp、hdp、a2dp、pan,gatt等等, 這裡自稱為面向應用的profile介面。 |
一、application Framework
這個層的程式碼主要是利用android.bluetoothAPIS和 bluetooth hardware進行互動。
Android原生的BTFramework程式碼位於framework/base/core/java/android.bluetooth/下。 |
這個目錄裡的程式碼更像一個橋樑,裡面有供java層使用一些類,也有對應的aidl檔案聯絡C、C++部分的程式碼,包括opp、hfp、hdp、a2dp、pan,gatt等等 |
MTK廠商客製化的修改程式碼位於 \mediatek\frameworks-ext\base\core\java\android\bluetooth |
重寫了原生部分的BT |
兩者什麼關係?增加了自己的相關profile server橋接介面(與Bluetooth的server層 profile對應的):如下:
LOCAL_SRC_FILES += \
../../mediatek/frameworks-ext/base/core/java/android/bluetooth/IBluetoothBipi.aidl \
../../mediatek/frameworks-ext/base/core/java/android/bluetooth/IBluetoothBipr.aidl\
../../mediatek/frameworks-ext/base/core/java/android/bluetooth/IBluetoothBpp.aidl \
../../mediatek/frameworks-ext/base/core/java/android/bluetooth/IBluetoothDun.aidl \
../../mediatek/frameworks-ext/base/core/java/android/bluetooth/IBluetoothFtpCtrl.aidl\
../../mediatek/frameworks-ext/base/core/java/android/bluetooth/IBluetoothFtpServer.aidl \
../../mediatek/frameworks-ext/base/core/java/android/bluetooth/IBluetoothFtpServerCallback.aidl\
../../mediatek/frameworks-ext/base/core/java/android/bluetooth/IBluetoothProfileManager.aidl\
../../mediatek/frameworks-ext/base/core/java/android/bluetooth/IBluetoothSimap.aidl\
../../mediatek/frameworks-ext/base/core/java/android/bluetooth/IBluetoothSimapCallback.aidl\
../../mediatek/frameworks-ext/base/core/java/com/mediatek/bluetooth/service/IBluetoothPrxm.aidl\
../../mediatek/frameworks-ext/base/core/java/com/mediatek/bluetooth/service/IBluetoothPrxr.aidl\
../../mediatek/frameworks-ext/base/core/java/android/net/INetworkManagementIpv6EventObserver.aidl
如何編譯?
通過\frameworks\base的Android,.mk包含include$(LOCAL_PATH)/../../mediatek/frameworks-ext/base/config.mk完成把:mtk客製化增加的framework和原生的BTFramework的整合->生成:framework.jar。
下面僅僅是原生的例子:
比如A2DP的連線:framework/base/core/java/android/bluetooth/BluetoothA2dp.java中的connect(Bluetoothevice)方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public boolean connect(BluetoothDevice device) { if (DBG) log("connect(" + device + ")"); if (mService != null && isEnabled() && isValidDevice(device)) { try { return mService.connect(device); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return false; } } if (mService == null) Log.w(TAG, "Proxy not attached to service"); return false; } |
通過Binder IPC通訊機制,呼叫到packages/apps/Bluetooth/src/com.android.bluetooth.a2dp/A2dpService.java下一個內部私有類
A2dpService是一個繼承於ProfileService的類,而類ProfileService是繼承於Service類的。
private static class BluetoothA2dpBinder extendsIBluetoothA2dp.Stub{}的connect(BluetoothDevice)方法。
1 2 3 4 5 |
public boolean connect(BluetoothDevice device) { A2dpService service = getService(); if (service == null) return false; return service.connect(device); } |
然後呼叫到A2dpService的connect(BluetoothDevice)方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public boolean connect(BluetoothDevice device) { enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); if (getPriority(device) == BluetoothProfile.PRIORITY_OFF) { return false; } int connectionState = mStateMachine.getConnectionState(device); if (connectionState == BluetoothProfile.STATE_CONNECTED || connectionState == BluetoothProfile.STATE_CONNECTING) { return false; } mStateMachine.sendMessage(A2dpStateMachine.CONNECT, device); return true; } |
這個過程就是Bluetooth Application Framework與Bluetooth Process的呼叫過程。
二、Bluetooth server層:服務層包括兩部分--Bluetooth System service(部分)和Bluetoothprofile;
1.Bluetooth System service:
\mediatek\frameworks-ext\base\core\java\android\server |
編譯到framework.jar:mtk自增加的profilemanager server部分 |
2.Bluetooth profile API介面(也就是各個profile的server層):
---這裡自稱為server層的profile介面。
----實現了關於藍芽java應用profile的API程式碼,包括opp、hfp、hdp、a2dp、pan,gatt等等,而且也有部分server性質的程式碼(不同的profile,有不同的設計)
由兩部分組成:
packages/apps/Bluetooth |
android原生提供的profile:a2dp,gatt,hdp,hfp,hid,map,opp,pan,pbap |
生成bluetooth.apk |
\mediatek\packages\apps\bluetooth\profiles |
mtk增加的profile: |
MtkBt.apk: 程序名:com.mediatek.bluetooth “如果刪除,則連線不上,提示parei,connet錯誤等資訊。 因為很多pofile都連線不上。” |
mtk增加的profile:
include$(MY_MODULE_PATH)/profiles/prxm/Android.mk
include$(MY_MODULE_PATH)/profiles/prxr/Android.mk
include$(MY_MODULE_PATH)/profiles/simap/Android.mk
include$(MY_MODULE_PATH)/profiles/ftp/Android.mk
include$(MY_MODULE_PATH)/profiles/bpp/Android.mk
include$(MY_MODULE_PATH)/profiles/bip/Android.mk
include$(MY_MODULE_PATH)/profiles/dun/Android.mk
src_list +=profiles/prxm profiles/prxr profiles/simap profiles/ftp profiles/bppprofiles/bip profiles/dun
Bluetooth System service位於packages/apps/Bluetooth目錄下,它打包成一個android app包,並且在android framework 層實現BTservice和各種profile。BT app會通過JNI呼叫到HAL層。
A2dpService.java
的connect方法會發送一個StateMachine.sendMessage(A2dpStateMachine.CONNECT,device)的message,這個message會被A2dpStateMachine.java物件的processMessage(Message)方法接收到:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
case CONNECT: BluetoothDevice device = (BluetoothDevice) message.obj; broadcastConnectionState(device, BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_DISCONNECTED); if (!connectA2dpNative(getByteAddress(device)) ) { broadcastConnectionState(device, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTING); break; } synchronized (A2dpStateMachine.this) { mTargetDevice = device; transitionTo(mPending); } // TODO(BT) remove CONNECT_TIMEOUT when the stack // sends back events consistently sendMessageDelayed(CONNECT_TIMEOUT, 30000); break; |
最重要的一句:connectA2dpNative(getByteAddress(device);
即會通過JNI呼叫到Native:
Com_android_bluetooth_a2dp.cpp(kitkat_ibd\packages\apps\bluetooth\jni): {"connectA2dpNative"
server層就呼叫到JNI層----》
////////////////////////////////////////////////////////////////////////////
mtk封裝的庫(JNI和中間協議)
////////////////////////////////////////////////////////////////////
\build\target\product\common.mk定義:
ifeq ($(strip$(MTK_BT_SUPPORT)), yes)
PRODUCT_PROPERTY_OVERRIDES += \
ro.btstack=blueangel
PRODUCT_PACKAGES += MtkBt \
btconfig.xml \
auto_pair_blacklist.conf \
libbtcusttable \
libbtcust \
libmtkbtextadp \
libextpbap \
libextavrcp \
libextopp \
libextsys \
libextftp \
libmtkbtextadpa2dp \
libmtka2dp \
libextbip \
libextbpp \
libexthid \
libextsimap \
libextjsr82 \
libbtsession \
libmtkbtextpan \
libextmap \
libmtkbtextspp \
libexttestmode \
libpppbtdun \
libextopp_jni \
libexthid_jni \
libextpan_jni \
libextftp_jni \
libextbpp_jni \
libextbip_jni \
libextpbap_jni \
libextavrcp_jni \
libextsimap_jni \
libextdun_jni \
libextmap_jni \
libextsys_jni \
libextadvanced_jni \
btlogmask \
btconfig \
libbtpcm \
libbtsniff \
mtkbt \
bluetooth.blueangel \
audio.a2dp.blueangel
Endif
\vendor\mediatek\huaqin82_we_iba_jb5\artifacts\out\target\product\huaqin82_we_iba_jb5\system\lib
三、JNI
與android.bluetooth有關的JNI程式碼位於:分為兩部分:
android原生的和mtk增加的:
\packages\apps\Bluetooth\jni, |
原生的BT JNI程式碼: com_android_bluetooth_btservice_AdapterService.cpp: 控制本地藍芽晶片,載入藍芽hal層:BT_STACK_MODULE_ID定義在bluetooth。c。 com_android_bluetooth_hfp.cpp \ com_android_bluetooth_a2dp.cpp \ com_android_bluetooth_avrcp.cpp \ com_android_bluetooth_hid.cpp \ com_android_bluetooth_hdp.cpp \ com_android_bluetooth_pan.cpp \ com_android_bluetooth_gatt.cpp |
生成:libbluetooth_jni.so 實現: 本地裝置的hal控制; 調起各種中間協議; |
\mediatek\frameworks-ext\base\core\jni |
mtk平臺的BT jni程式碼所在路徑 |
kitkat不使用 |
JNI的程式碼會呼叫到HAL層,並且在確信一些BT操作被觸發時,會從HAL獲取一些回撥。比如當BT裝置被發現時。
再回到A2dp連線的例子中來,BT System Service通過JNI會呼叫到com_android_bluetooth_a2dp.cpp中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
static jboolean connectA2dpNative(JNIEnv *env, jobject object, jbyteArray address) { jbyte *addr; bt_bdaddr_t * btAddr; bt_status_t status; ALOGI("%s: sBluetoothA2dpInterface: %p", __FUNCTION__, sBluetoothA2dpInterface); if (!sBluetoothA2dpInterface) return JNI_FALSE; addr = env->GetByteArrayElements(address, NULL); btAddr = (bt_bdaddr_t *) addr; if (!addr) { jniThrowIOException(env, EINVAL); return JNI_FALSE; } if ((status = sBluetoothA2dpInterface->connect((bt_bdaddr_t *)addr)) != BT_STATUS_SUCCESS) { ALOGE("Failed HF connection, status: %d", status); } env->ReleaseByteArrayElements(address, addr, 0); return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; } |
重點程式碼是:status= sBluetoothA2dpInterface->connect((bt_bdaddr_t *)addr);
這個sBluetoothA2dpInterface結構體物件是在initNative(JNIEnv *env, jobject object)方法時得到的。
1 2 3 4 5 |
if ( (sBluetoothA2dpInterface = (btav_interface_t *) btInf->get_profile_interface(BT_PROFILE_ADVANCED_AUDIO_ID)) == NULL) { ALOGE("Failed to get Bluetooth A2DP Interface"); return; } |
四、HAL
4.1硬體抽象層定義android.bluetooth APIs和BTprocess呼叫的標準介面(所有的廠家都是按照這種介面定義來編寫自己的底層協議棧),並且你必須實現這些介面來讓你的BT hardware功能執行正常。BT HAL的的標頭檔案位於hardware/libhardware/include/hardware/bluetooth.h和hardware/libhardware/include/hardware/bt_*.h檔案中。
JNI中sBluetoothA2dpInterface是一個btav_interface_t結構體,位於