zoukankan      html  css  js  c++  java
  • android4.3 Bluetooth(le)分析之startLeScan分析

    BluetoothAdapter.java中有low enery(le)的一些方法,android提供了这些方法,但源码中并未找到这些方法的调用之处。本文档主要分析这类方法的执行流程,来了解下le到底做了些什么。

     

    本文主要就是分析下startLeScan方法(两个重载方法)。

        public boolean startLeScan(LeScanCallback callback) {
            return startLeScan(null, callback);
        }
    
        public boolean startLeScan(UUID[] serviceUuids, LeScanCallback callback) { 
            if (DBG) Log.d(TAG, "startLeScan(): " + serviceUuids);                                                                                                           
    
    
            synchronized(mLeScanClients) {     
                if (mLeScanClients.containsKey(callback)) { 
                    if (DBG) Log.e(TAG, "LE Scan has already started");                                                                                                      
                    return false;
                }
    
                try {
                    //获取BluetoothGattBinder类的实例,该类的定义在GattService.java中
                    IBluetoothGatt iGatt = mManagerService.getBluetoothGatt();                                                                                               
                    if (iGatt == null) {               
                        // BLE is not supported        
                        return false;              
                    }
    
                    UUID uuid = UUID.randomUUID(); 
                    GattCallbackWrapper wrapper = new GattCallbackWrapper(this, callback, serviceUuids);                                                     
                    //重点分析该方法。作用是为本地设备进行注册,以及启动扫描
                    //wrapper是GattCallbackWrapper类的对象。该类注册了一些Gatt协议的回调方法
                    iGatt.registerClient(new ParcelUuid(uuid), wrapper); 
                    if (wrapper.scanStarted()) {       
                        mLeScanClients.put(callback, wrapper);
                        return true;               
                    }
                } catch (RemoteException e) {      
                    Log.e(TAG,"",e);           
                }
            }
            return false;
        }

    下面来分析下iGatt.registerClient(new ParcelUuid(uuid), wrapper)方法,路径如下:(packages/apps/Bluetooth/src/com/android/bluetooth/gatt/GattService.java::BluetoothGattBinder)

            public void registerClient(ParcelUuid uuid, IBluetoothGattCallback callback) {
                GattService service = getService();
                if (service == null) return;   
                service.registerClient(uuid.getUuid(), callback);
            }

    接着会调用GattService服务的同名方法

        void registerClient(UUID uuid, IBluetoothGattCallback callback) {
            enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
    
            if (DBG) Log.d(TAG, "registerClient() - UUID=" + uuid);
            mClientMap.add(uuid, callback);
            gattClientRegisterAppNative(uuid.getLeastSignificantBits(),
                                        uuid.getMostSignificantBits());
        }

    接下来会调用jni层com_android_bluetooth_gatt.cpp文件中的gattClientRegisterAppNative方法。

    static void gattClientRegisterAppNative(JNIEnv* env, jobject object,
                                            jlong app_uuid_lsb, jlong app_uuid_msb )
    {
        bt_uuid_t uuid;
    
        if (!sGattIf) return;
        set_uuid(uuid.uu, app_uuid_msb, app_uuid_lsb);
        sGattIf->client->register_client(&uuid);
    }

    分析sGattIf->client->register_client(&uuid);语句

    (1)sGattIf是一个静态变量,定义是static const btgatt_interface_t *sGattIf = NULL;

     

    又是这种类型的变量。第一反应就是去找btgatt_interface_t结构体定义的头文件(一般在hardware目录),然后再搜索调用的c文件(一般在external/bluetooth/bluedroid,有时找到的c文件与头文件同名)。

    btgatt_interface_t结构体的定义:hardware/libhardware/include/hardware/bt_gatt.h

    /** Represents the standard Bluetooth GATT interface. */
    typedef struct {
        /** Set to sizeof(btgatt_interface_t) */
        size_t          size;
    
        /**
         * Initializes the interface and provides callback routines
         */
        bt_status_t (*init)( const btgatt_callbacks_t* callbacks );
    
        /** Closes the interface */    
        void (*cleanup)( void );
    
        /** Pointer to the GATT client interface methods.*/
        const btgatt_client_interface_t* client;
    
        /** Pointer to the GATT server interface methods.*/
        const btgatt_server_interface_t* server;
    } btgatt_interface_t;

    btgatt_interface_t结构体的对象:external/bluetooth/bluedroi/btif/src/btif_gatt.c

    static const btgatt_interface_t btgattInterface = {
        sizeof(btgattInterface),
    
        btif_gatt_init,
        btif_gatt_cleanup,
    
        &btgattClientInterface,
        &btgattServerInterface,   
    };

    回到sGattIf->client->register_client(&uuid);语句,它调用了sGattIf结构体对象中的client对象的register_client函数,那么就是btgattClientInterface对象的register_client函数。

     

    由结构体的定义可知client对象的类型是btgatt_client_interface_t结构体。同理分析可得以下结果,

    btgatt_client_interface_t结构体的定义:hardware/libhardware/include/hardware/ bt_gatt_client.h

    typedef struct {
        /** Registers a GATT client application with the stack */
        bt_status_t (*register_client)( bt_uuid_t *uuid );
    
        /** Unregister a client application from the stack */
      bt_status_t (*unregister_client)(int client_if );
      ......
    }

    btgatt_client_interface_t结构体的对象:external/bluetooth/bluedroi/btif/src/btif_gatt_client.c

    const btgatt_client_interface_t btgattClientInterface = {
        btif_gattc_register_app,
        btif_gattc_unregister_app,
        btif_gattc_scan,
      ......
    };

    因此client->register_client就是调用了btif_gattc_register_app方法[-->btif_gatt_client.c]。

    static bt_status_t btif_gattc_register_app(bt_uuid_t *uuid)
    {
        CHECK_BTGATT_INIT();
        btif_gattc_cb_t btif_cb;
        memcpy(&btif_cb.uuid, uuid, sizeof(bt_uuid_t));
        return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_REGISTER_APP,
                                     (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
    }

    分析btgattc_handle_event函数

    static void btgattc_handle_event(uint16_t event, char* p_param)
    {
        ......
        btif_gattc_cb_t* p_cb = (btif_gattc_cb_t*)p_param;
        if (!p_cb) return;
    
        switch (event)
        {
            case BTIF_GATTC_REGISTER_APP:
                btif_to_bta_uuid(&uuid, &p_cb->uuid);
                //为uuid注册回调函数
                BTA_GATTC_AppRegister(&uuid, bte_gattc_cback);
                break;
            .......
        }
    }

    分析BTA_GATTC_AppRegister函数

    -------------------------------------------------------------------------------------------------------

    void BTA_GATTC_AppRegister(tBT_UUID *p_app_uuid, tBTA_GATTC_CBACK *p_client_cb)                                                                                          
    {
        tBTA_GATTC_API_REG  *p_buf;                                                                                                                                          
    
        /* register with BTA system manager */
      GKI_sched_lock();
      //注册Gatt客户端主事件处理函数bta_gattc_hdl_event,在bta_gatt_reg结构体中定义。
        bta_sys_register(BTA_ID_GATTC, &bta_gatt_reg);
        GKI_sched_unlock();
    
        if ((p_buf = (tBTA_GATTC_API_REG *) GKI_getbuf(sizeof(tBTA_GATTC_API_REG))) != NULL)                                                                                 
        {
            p_buf->hdr.event    = BTA_GATTC_API_REG_EVT;
            if (p_app_uuid != NULL)            
                memcpy(&p_buf->app_uuid, p_app_uuid, sizeof(tBT_UUID));
            p_buf->p_cback      = p_client_cb;                                                                                                                               
    
            bta_sys_sendmsg(p_buf);    
        }
        return;
    }

    (a)通过bta_sys_register函数注册了bta_gatt_reg结构体中定义的客户端主事件处理函数bta_gattc_hdl_event;然后设置event为BTA_GATTC_API_REG_EV,触发bta_gattc_hdl_event函数。

    BOOLEAN bta_gattc_hdl_event(BT_HDR *p_msg)
    {
        tBTA_GATTC_CB *p_cb = &bta_gattc_cb;
        tBTA_GATTC_CLCB *p_clcb = NULL;
    
    #if BTA_GATT_DEBUG == TRUE
        APPL_TRACE_DEBUG1("bta_gattc_hdl_event: Event [%s]", gattc_evt_code(p_msg->event));                                                                                  
    #endif
        switch (p_msg->event)
        {
            case BTA_GATTC_API_REG_EVT:        
                bta_gattc_register(p_cb, (tBTA_GATTC_DATA *) p_msg);
                break;
            ......
      }
    }

    (b)调用bta_gattc_register函数。该函数用来注册一个客户端Gatt应用程序。

    void bta_gattc_register(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_data)
    {
        ......
        /* callback with register event */
        if (p_data->api_reg.p_cback)
        {
            (*p_data->api_reg.p_cback)(BTA_GATTC_REG_EVT,  (tBTA_GATTC *)&cb_data);
        }
    }

    调用相关event(BTA_GATTC_REG_EVT)的回调函数。

    到此,BTA_GATTC_AppRegister函数分析完毕,接下来分析BTA_GATTC_AppRegister(&uuid, bte_gattc_cback);中的参数部分。

    ps:上述的回调函数就是这里的参数:bte_gattc_cback函数。那么BTA_GATTC_REG_EVT事件就调用该函数处理了。

    -------------------------------------------------------------------------------------------------------

     

    分析回调函数bte_gattc_cback

    static void bte_gattc_cback(tBTA_GATTC_EVT event, tBTA_GATTC *p_data)
    {
        bt_status_t status = btif_transfer_context(btif_gattc_upstreams_evt,
                        (uint16_t) event, (void*)p_data, sizeof(tBTA_GATTC), NULL);
        ASSERTC(status == BT_STATUS_SUCCESS, "Context transfer failed!", status);
    }

    分析btif_gattc_upstreams_evt函数,在该函数中会处理BTA_GATTC_REG_EVT事件。

    static void btif_gattc_upstreams_evt(uint16_t event, char* p_param)
    {
        tBTA_GATTC *p_data = (tBTA_GATTC*)p_param;
        switch (event)
        {  
            case BTA_GATTC_REG_EVT:        
            {
                bt_uuid_t app_uuid;            
                bta_to_btif_uuid(&app_uuid, &p_data->reg_oper.app_uuid);
                HAL_CBACK(bt_gatt_callbacks, client->register_client_cb
                    , p_data->reg_oper.status      
                    , p_data->reg_oper.client_if   
                    , &app_uuid
                );
                break;
            }
        ......
      }
    }

    bt_gatt_callbacks对象的类型是btgatt_callbacks_t,其定义在hardware/libhardware/include/hardware/bt_gatt.h文件中。现在对bt_gatt_callbacks对象从头开始分析其来源。

     

    在GattService.java::start()方法中,调用了initializeNative方法。继而调用JNI层initializeNative方法。贴出该方法。

    static const btgatt_interface_t *sGattIf = NULL;
    static const bt_interface_t* btIf;
    ......
    static void initializeNative(JNIEnv *env, jobject object) {
        /* getBluetoothInterface 函数返回sBluetoothInterface对象,在android4.3 bt 扫描分析.docx中已说明该对象的来源*/
        if ( (btIf = getBluetoothInterface()) == NULL) {
            error("Bluetooth module is not loaded");
            return;
        }  
      ......
      //(a)
      // BT_PROFILE_GATT_ID的值是”gatt”
        if ( (sGattIf = (btgatt_interface_t *)
              btIf->get_profile_interface(BT_PROFILE_GATT_ID)) == NULL) {
            error("Failed to get Bluetooth GATT Interface");
            return;
        } 
    
      bt_status_t status;
      //(b)
      /* sGattCallbacks的定义
      static const btgatt_callbacks_t sGattCallbacks = {
          sizeof(btgatt_callbacks_t),
          &sGattClientCallbacks,
          &sGattServerCallbacks
      };*/
        if ( (status = sGattIf->init(&sGattCallbacks)) != BT_STATUS_SUCCESS) {
            error("Failed to initialize Bluetooth GATT, status: %d", status);
            sGattIf = NULL;
            return;
        }  
    
        mCallbacksObj = env->NewGlobalRef(object);
    }

    (a) 分析

    static const void* get_profile_interface (const char *profile_id)
    {
        ......
    #if BTA_GATT_INCLUDED == TRUE 
        if (is_profile(profile_id, BT_PROFILE_GATT_ID))
            return btif_gatt_get_interface();
    #endif
        return NULL;
    }

    分析btif_gatt_get_interface函数

    const btgatt_interface_t *btif_gatt_get_interface()
    {
        return &btgattInterface;
    }

    btgattInterface对象的类型是btgatt_interface_t结构体。再贴一遍该结构体的定义,如下:

    typedef struct {
        /** Set to sizeof(btgatt_interface_t) */
        size_t          size;
    
        /**
         * Initializes the interface and provides callback routines
         */
        bt_status_t (*init)( const btgatt_callbacks_t* callbacks );
    
        /** Closes the interface */    
        void (*cleanup)( void );
    
        /** Pointer to the GATT client interface methods.*/
        const btgatt_client_interface_t* client;
    
        /** Pointer to the GATT server interface methods.*/
        const btgatt_server_interface_t* server;
    } btgatt_interface_t;

    另,btgattInterface对象定义如下:

    static const btgatt_interface_t btgattInterface = {
        sizeof(btgattInterface),
    
        btif_gatt_init,
        btif_gatt_cleanup,
    
        &btgattClientInterface,
        &btgattServerInterface,
    };

    所以sGattIf 就是btgattInterface对象。

     

    (b) 接下来调用sGattIf->init函数。由上可知,即为btif_gatt_init函数。

    static bt_status_t btif_gatt_init( const btgatt_callbacks_t* callbacks )
    {
      /*bt_gatt_callbacks由参数赋值,该参数是sGattCallbacks。
      sGattCallbacks的定义
      static const btgatt_callbacks_t sGattCallbacks = {
          sizeof(btgatt_callbacks_t),
          &sGattClientCallbacks,
          &sGattServerCallbacks
      };*/
        bt_gatt_callbacks = callbacks;
    
        BTA_GATTC_Init();
        BTA_GATTS_Init();
    
        return BT_STATUS_SUCCESS;
    }

    到此为止,调用语句中bt_gatt_callbacks对象我们已经清楚了,就是sGattCallbacks对象。现在分析client->register_client_cb

    HAL_CBACK(bt_gatt_callbacks, client->register_client_cb
                    , p_data->reg_oper.status      
                    , p_data->reg_oper.client_if   
                    , &app_uuid
                );

    client对象是在btgatt_callbacks_t结构体中定义的一个变量,其初始化是在bt_gatt_callbacks对象(即sGattCallbacks对象)中。

    btgatt_callbacks_t结构体如下:

    typedef struct {
        /** Set to sizeof(btgatt_callbacks_t) */
        size_t size;
    
        /** GATT Client callbacks */   
        const btgatt_client_callbacks_t* client;
    
        /** GATT Server callbacks */   
        const btgatt_server_callbacks_t* server;
    } btgatt_callbacks_t;

    因此client对应的就是sGattCallbacks对象中的sGattClientCallbacks对象。sGattClientCallbacks对象定义如下(在JNI层的com_android_bluetooth_gatt.cpp文件中定义):

    static const btgatt_client_callbacks_t sGattClientCallbacks = {
        btgattc_register_app_cb,
        btgattc_scan_result_cb,
        ......
    };

    而sGattClientCallbacks对象的类型是btgatt_client_callbacks_t结构体,如下

    typedef struct {
        register_client_callback            register_client_cb;            
        scan_result_callback                scan_result_cb;                
        connect_callback                    open_cb;
        disconnect_callback                 close_cb;
        ......        
    } btgatt_client_callbacks_t;

    因此,client->register_client_cb就是调用了sGattClientCallbacks 对象中的btgattc_register_app_cb函数。

    void btgattc_register_app_cb(int status, int clientIf, bt_uuid_t *app_uuid)
    {
        CHECK_CALLBACK_ENV
        sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onClientRegistered, status,
            clientIf, UUID_PARAMS(app_uuid));
        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
    }

    JNI层的method_onClientRegistered 函数对应java层的onClientRegistered方法[-->GattService.java]。

        void onClientRegistered(int status, int clientIf, long uuidLsb, long uuidMsb)
                throws RemoteException {       
            UUID uuid = new UUID(uuidMsb, uuidLsb);
            if (DBG) Log.d(TAG, "onClientRegistered() - UUID=" + uuid + ", clientIf=" + clientIf);
            ClientMap.App app = mClientMap.getByUuid(uuid);
            if (app != null) {
                app.id = clientIf;
                app.linkToDeath(new ClientDeathRecipient(clientIf));
                app.callback.onClientRegistered(status, clientIf);
            }
        }

    此callback其实是GattCallbackWrapper类的对象。

    分析mClientMap对象,在registerClient方法中调用了ClientMap的父类ContextMap::add方法,将GattCallbackWrapper类对象wrapper作为callback参数添加到mClientMap对象中。

     

    接下来重新分析:

    onClientRegistered方法[--->BluetoothAdapter::GattCallbackWrapper类]

            public void onClientRegistered(int status, int clientIf) {
                if (DBG) Log.d(TAG, "onClientRegistered() - status=" + status +
                               " clientIf=" + clientIf);
                synchronized(this) {
                    if (mLeHandle == -1) {
                        if (DBG) Log.d(TAG, "onClientRegistered LE scan canceled");
                    }
    
                    if (status == BluetoothGatt.GATT_SUCCESS) {
                        mLeHandle = clientIf;
                        IBluetoothGatt iGatt = null;
                        try {
                            BluetoothAdapter adapter = mBluetoothAdapter.get();
                            if (adapter != null) {
                                iGatt = adapter.getBluetoothManager().getBluetoothGatt();
                                //调用startLeScan方法时,传递过来的参数为null,执行此处
                                if (mScanFilter == null) {
                                    iGatt.startScan(mLeHandle, false);
                                } else {
                                    ParcelUuid[] uuids = new ParcelUuid[mScanFilter.length];
                                    for(int i = 0; i != uuids.length; ++i) {
                                        uuids[i] = new ParcelUuid(mScanFilter[i]);
                                    }
                                    iGatt.startScanWithUuids(mLeHandle, false, uuids);
                                }
                            } else {
                                Log.e(TAG, "onClientRegistered, BluetoothAdapter null");
                                mLeHandle = -1;
                            }
                        } catch (RemoteException e) {
                            Log.e(TAG, "fail to start le scan: " + e);
                            mLeHandle = -1;
                        }
                ......
            }

    接下来分析startScan方法,在GattService.java中。

        void startScan(int appIf, boolean isServer) {
            ......
            if (getScanClient(appIf, isServer) == null) {
                if (DBG) Log.d(TAG, "startScan() - adding client=" + appIf);
                mScanQueue.add(new ScanClient(appIf, isServer));
            }
    
            gattClientScanNative(appIf, true);
        }

    JNI层gattClientScanNative函数

    static void gattClientScanNative(JNIEnv* env, jobject object, jint clientIf, jboolean start)
    {
        if (!sGattIf) return;
        sGattIf->client->scan(clientIf, start);
    }

    同之前分析register_client的步骤,分析的scan函数对应btif_gattc_scan函数。

    static bt_status_t btif_gattc_scan( int client_if, bool start )
    {
        CHECK_BTGATT_INIT();
        btif_gattc_cb_t btif_cb;
        btif_cb.client_if = (uint8_t) client_if;
        return btif_transfer_context(btgattc_handle_event, start ? BTIF_GATTC_SCAN_START : BTIF_GATTC_SCAN_STOP,
                                     (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
    }

    在btgattc_handle_event函数中处理BTIF_GATTC_SCAN_START事件

            case BTIF_GATTC_SCAN_START:
                btif_gattc_init_dev_cb();
                // BTA_DmBleObserve发出消息,包含BTA_DM_API_BLE_OBSERVE_EVT事件
                BTA_DmBleObserve(TRUE, 0, bte_scan_results_cb);
                break;

    调用bte_scan_results_cb函数,

    static void bte_scan_results_cb (tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data)
    {
        btif_gattc_cb_t btif_cb;
        uint8_t len;
    
        switch (event)
        {
            case BTA_DM_INQ_RES_EVT:
                ......
    
            case BTA_DM_INQ_CMPL_EVT:
                ......
        btif_transfer_context(btif_gattc_upstreams_evt, BTIF_GATT_OBSERVE_EVT,
                                     (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
    }

    在btif_gattc_upstreams_evt函数中处理BTIF_GATT_OBSERVE_EVT事件。

            case BTIF_GATT_OBSERVE_EVT:
            {
                btif_gattc_cb_t *p_btif_cb = (btif_gattc_cb_t*)p_param;
                if (!btif_gattc_find_bdaddr(p_btif_cb->bd_addr.address))
                {
                    btif_gattc_add_remote_bdaddr(p_btif_cb->bd_addr.address, p_btif_cb->addr_type);
                    btif_gattc_update_properties(p_btif_cb);
                }
                HAL_CBACK(bt_gatt_callbacks, client->scan_result_cb,
                          &p_btif_cb->bd_addr, p_btif_cb->rssi, p_btif_cb->value);
                break;
            }

    同分析register_client_cb函数,在JNI层com_android_bluetooth_gatt.cpp文件中定义,分析得scan_result_cb对应函数btgattc_scan_result_cb。

    void btgattc_scan_result_cb(bt_bdaddr_t* bda, int rssi, uint8_t* adv_data)
    {
        ......
        sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onScanResult
            , address, rssi, jb);
        ......
    }

    对应java层文件GattService类onScanResult方法。

        void onScanResult(String address, int rssi, byte[] adv_data) {
            for (ScanClient client : mScanQueue) {
                ......
                if (!client.isServer) {
                    ClientMap.App app = mClientMap.getById(client.appIf);
                    if (app != null) {
                        try {
                            app.callback.onScanResult(address, rssi, adv_data);
                        } catch (RemoteException e) {
                            Log.e(TAG, "Exception: " + e);
                            mClientMap.remove(client.appIf);
                            mScanQueue.remove(client);
                        }
                    }
                }
            ......
            }
      }

    callback为GattCallbackWrapper类的对象,因此调用GattCallbackWrapper类中的onScanResult方法。

            public void onScanResult(String address, int rssi, byte[] advData) {
                ......
                try {
                    BluetoothAdapter adapter = mBluetoothAdapter.get();
                    if (adapter == null) {
                        Log.d(TAG, "onScanResult, BluetoothAdapter null");
                        return;
                    }
                    mLeScanCb.onLeScan(adapter.getRemoteDevice(address), rssi, advData);
                } catch (Exception ex) {
                    Log.w(TAG, "Unhandled exception: " + ex);
                }
            }

    mLeScanCb对象为LeScanCallback接口的对象,不过源码中并没有类来实现该接口,故只能分析到这里了。扫描到此结束,over~~ 

    -------------------------------------------------------------------------------------------------------------

    贴出流程图,see see,5个步骤:

    1.startLeScan(JAVA-->JNI)

    -------------------------------------------------------------------------------------------------------------

    2.startLeScan(蓝牙栈)

    -------------------------------------------------------------------------------------------------------------

    3.startLeScan(JNI-->JAVA)

    -------------------------------------------------------------------------------------------------------------

    4.startLeScan(蓝牙栈)

    -------------------------------------------------------------------------------------------------------------

    5.startLeScan(JNI-->JAVA)

  • 相关阅读:
    D3制作力导向图
    page分页问题,根据页码获取对应页面的数据,接口调用
    python列表生成式、键盘输入及类型转换、字符串翻转、字母大小写、数组广播、循环语句等基础问题
    python中将已有链接的视频进行下载
    机器学习1
    python 排序算法
    LintCode 练习题
    python 装饰器的使用
    hive 学习笔记
    hive 操作
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/6418252.html
Copyright © 2011-2022 走看看