1. 程式人生 > >藍芽系列之BlueDroid與MTK程式碼分佈

藍芽系列之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進行互動。

也就是通過BinderIPC機制呼叫bluetooth程序;

Android原生的BTFramework程式碼位於framework/base/core/java/android.bluetooth/下。

這個目錄裡的程式碼更像一個橋樑,裡面有供java層使用一些類,也有對應的aidl檔案聯絡CC++部分的程式碼,包括opp、hfp、hdp、a2dp、pan,gatt等等

MTK廠商客製化的修改程式碼位於

\mediatek\frameworks-ext\base\core\java\android\bluetooth

重寫了原生部分的BT

程式碼,而且各種profile API:是橋接application和server之間的介面:BluetoothFtp.java /BluetoothHealth.ajva /BluetoothHid.java…….

兩者什麼關係?增加了自己的相關profile server橋接介面(與Bluetoothserver 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);

}

然後呼叫到A2dpServiceconnect(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 FrameworkBluetooth Process的呼叫過程。

二、Bluetooth server層:服務層包括兩部分--Bluetooth System service(部分)Bluetoothprofile

1.Bluetooth System service

\mediatek\frameworks-ext\base\core\java\android\server

編譯到framework.jarmtk自增加的profilemanager server部分

2.Bluetooth profile API介面(也就是各個profileserver層):

---裡自稱為server層的profile介面。

----實現了關於藍芽java應用profile的API程式碼,包括opp、hfp、hdp、a2dp、pan,gatt等等,而且也有部分server性質的程式碼(不同的profile,有不同的設計)

由兩部分組成:

packages/apps/Bluetooth

android原生提供的profilea2dp,gatt,hdp,hfp,hid,map,opp,pan,pbap

生成bluetooth.apk

\mediatek\packages\apps\bluetooth\profiles

mtk增加的profile

MtkBt.apk

程序名:com.mediatek.bluetooth

“如果刪除,則連線不上,提示pareiconnet錯誤等資訊。

因為很多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和各種profileBT 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 APIsBTprocess呼叫的標準介面(所有的廠家都是按照這種介面定義來編寫自己的底層協議棧,並且你必須實現這些介面來讓你的BT hardware功能執行正常。BT HAL的的標頭檔案位於hardware/libhardware/include/hardware/bluetooth.hhardware/libhardware/include/hardware/bt_*.h檔案中。

JNIsBluetoothA2dpInterface是一個btav_interface_t結構體,位於