• ZT eoe android4.2 Bluetooth记录01-结构和代码分布


    android4.2 Bluetooth记录01-结构和代码分布

    作者:cnhua5更新于 08月21日访问(697评论(2

    android4.2中,Google更换了android蓝牙协议栈,从Bluez换成Bluedroid,我也是初涉这个方面,顺便记录一下。
    http://source.android.com/devices/bluetooth.html
    android4.2蓝牙结构

    android development对于4.3蓝牙的介绍:

    android提供BlueDroid作为默认的协议栈,BlueDroid分为两个部分:

    1、Bluetooth Embedded System(BTE),它实现了BT的核心功能。

    2、Bluetooth Application Layer (BTA),用于和android framework层交互。

    BT 系统服务通过JNI与BT stack交互,并且通过Binder IPC通信与应用交互。这个系统服务同时也提供给RD获取不同的BT profiles;下面的图标展示BT stack的一个大体的结构:

    一、application Framework

    这个层的代码主要是利用android.bluetooth APIS 和 bluetooth hardware进行交互。 也就是通过Binder IPC机制调用bluetooth 进程;

    代码位于framework/base/core/java/android.bluetooth/下。

    比如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 extends IBluetoothA2dp.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 System service

    Bluetooth System service位于packages/apps/Bluetooth下,它打包成一个android app包,并且在android framework 层实现BT service
    和各种profile。BT app会通过JNI调用到HAL层。

    A2dpService的connect方法会发送一个 StateMachine.sendMessage(A2dpStateMachine.CONNECT, device)的message,这个message会被A2dpStateMachine对象的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;

    private native boolean connectA2dpNative(byte[] address);

    三、JNI

    android.bluetooth有关的JNI代码位于packages/apps/bluetooth/jni下,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

    硬件抽象层定义android.bluetooth APIs和BT process调用的标准接口,并且你必须实现这些接口来让你的BT hardware功能运行正常。BT HAL的
    的头文件位于hardware/libhardware/include/hardware/bluetooth.h和hardware/libhardware/include/hardware/bt_*.h 文件中。

    JNI中sBluetoothA2dpInterface是一个btav_interface_t结构体,位于hardware/libhardware/include/hardware/bt_av.h中,定义为:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    typedef struct {
    
        /** set to sizeof(btav_interface_t) */
        size_t          size;
        /**
         * Register the BtAv callbacks
         */
        bt_status_t (*init)( btav_callbacks_t* callbacks );
    
        /** connect to headset */
        bt_status_t (*connect)( bt_bdaddr_t *bd_addr );
    
        /** dis-connect from headset */
        bt_status_t (*disconnect)( bt_bdaddr_t *bd_addr );
    
        /** Closes the interface. */
        void  (*cleanup)( void );
    
    } btav_interface_t;
    

    五、BT stack

    作为默认的BT stack,(4.2之前是bluez作为协议栈的)

    代码位于external/bluetooth/bluedroid下,这个stack实现了通用的BT HAL并且也可以通过扩展和改变配置来自定义。

    A2dp的连接会调用到external/bluetooth/bluedroid/btif/src/btif_av.c的connect方法。

    1
    2
    3
    4
    5
    6
    7
    static bt_status_t connect(bt_bdaddr_t *bd_addr)
    {
        BTIF_TRACE_EVENT1("%s", __FUNCTION__);
        CHECK_BTAV_INIT();
    
        return btif_queue_connect(UUID_SERVCLASS_AUDIO_SOURCE, bd_addr, connect_int);
    }
    

    六、Vendor extension

    为了追踪添加自定义拓展和一个HCI层,你可以创建一个libbt-vendor模块并且指定这些组件。

    下一篇BT enable/disable
    http://my.eoe.cn/cnhua5/archive/10667.html

  • 相关阅读:
    不要抱怨网速慢,只怪你自己不会调快网速
    2014年6月27日 几何和排列 答案
    我的世界杯生活
    javascript设计模式--备忘录模式(Memento)
    翻译:AngularJS应用的认证技术
    javascript设计模式--状态模式(State)
    一张思维导图说明jQuery的AJAX请求机制
    数据库设计中的14个技巧
    密室经典逃脱N部--考验你的智力!据说全球没几人走出去!不要看攻略!【工作之余也来休闲一下】
    关于编程,大学没有传授的10件事
  • 原文地址:https://www.cnblogs.com/jeanschen/p/3550738.html
Copyright © 2020-2023  润新知