Android源码个个击破之6.0蓝牙广播开启源码

由于公司想节约成本,将蓝牙盒子的功能由android来实现,但是发现android广播包的数据的拼组顺序与蓝牙盒子的不一致。所以需要看看源码是如何组包的,是否可以去修改。


  1. 开启广播的源码

  》》注册客户端

image.png

  AdvertiseCallbackWrapper是BluetoothAdvertiser的内部类

 image.png  

    |

    上面的mBluetoothGatt其实就是GattService的BluetoothGattBinder对象,但是注意广播的数据advertiseData并没有往下传递。

    image.png

      |

      Binder又调用了外部类GattService的方法

        image.png

          然后调用了Native的方法,调用到这里突然发现TMD的广播包数据没有传递过来。所以往回看,搜索广播包存储的变量mAdertisment.

      》》客户端注册成功,真正的开启广播

         

         image.png

        先调用binder的方法startMultiAdvertising

        image.png

        然后binder再调用service里的方法

        image.png

         可以看到广播的数据被封进了AdvertiseClient对象

             service然后再调用AdvertiseManager的方法

         image.png    

        |

            image.png

            |

            调用AdvertiseNative方法,注意这个类是AdvertiseManager的内部类

            image.png

            先看单个广播的方法startSingleAdvertising:

              image.png

             第一步,先使能广播 。

             第二步,设置广播的数据 。

             image.png

       看看JNI方法,注意是JNI,不是C。

        image.png

          注意上面的JNI方法env->GetByteArrayElements和ReleaseByteArrayElements,获取数组然后又释放了数组。所以主要看sGattIf->client->set_adv_data这个方法

          搜索到这个方法的定义的h文件:

         image.png

            那么sGattIf是什么,client又是什么?这个方法的实现在哪里呢?

            追溯sGattIf

            image.png

          追溯btIf

          image.png    

         |

        image.png

        |

         image.png

            这个方法是在classInitNative方法里被调用的

            image.png

          那么classInitNative肯定有个地方被用,我们找找,注意这是jni类的方法,那么它肯定是要被上层代码所调用的 :

         image.png

            |

            image.png

            |

            image.png

            可以发现classInitNative正好是GattService的本地方法,并且在GattService类加载时就调用了。观察GattService和com_android_bluetooth_btservice_AdapterService.cpp两个类,

    发现它们也是在同一个应用下。所以上面方法调用推理是没有毛病的。

            所以我们接着上面的源码说起

            image.png

            上面引用调用十分复杂:

static void classInitNative(JNIEnv* env, jclass clazz) {
        int err;
        hw_module_t* module;
   
        char value[PROPERTY_VALUE_MAX];
        //从配置文件里获取key = "bluetooth.mock_stack"的值
        property_get("bluetooth.mock_stack", value, "");
    
        //得到module的ID
        const char *id = (strcmp(value, "1")? BT_STACK_MODULE_ID : BT_STACK_TEST_MODULE_ID);
    
        //给module赋值
        err = hw_get_module(id, (hw_module_t const**)&module);
    
        if (err == 0) {
                hw_device_t* abstraction;
                err = module->methods->open(module, id, &abstraction);
                if (err == 0) {
                        bluetooth_module_t* btStack = (bluetooth_module_t *)abstraction;
                        sBluetoothInterface = btStack->get_bluetooth_interface();
                    } else {
                       ALOGE("Error while opening Bluetooth library");
                    }
            } else {
                ALOGE("No Bluetooth Library found");
            }
    }

      上面的hw_get_module已经在和硬件打交道了

        image.png

         上面方法的调用就不去具体深究了,下面看看看     sBluetoothInterface这个变量的类型

          image.png

          它是bt_interface_t的指针类型,bt_interface_t的定义:

  /** Represents the standard Bluetooth DM interface. */
typedef struct {
            /** set to sizeof(bt_interface_t) */
            size_t size;
            /**
              * Opens the interface and provides the callback routines
              * to the implemenation of this interface.
              */
            int (*init)(bt_callbacks_t* callbacks );
        
            /** Enable Bluetooth. */
            int (*enable)(void);
        
            /** Disable Bluetooth. */
            int (*disable)(void);
        
            /** Closes the interface. */
            void (*cleanup)(void);
        
            /** Get all Bluetooth Adapter properties at init */
            int (*get_adapter_properties)(void);
        
            /** Get Bluetooth Adapter property of 'type' */
            int (*get_adapter_property)(bt_property_type_t type);
        
            /** Set Bluetooth Adapter property of 'type' */
            /* Based on the type, val shall be one of
     * bt_bdaddr_t or bt_bdname_t or bt_scanmode_t etc
     */
            int (*set_adapter_property)(const bt_property_t *property);
        
            /** Get all Remote Device properties */
            int (*get_remote_device_properties)(bt_bdaddr_t *remote_addr);
        
            /** Get Remote Device property of 'type' */
            int (*get_remote_device_property)(bt_bdaddr_t *remote_addr,
                                                      bt_property_type_t type);
        
            /** Set Remote Device property of 'type' */
            int (*set_remote_device_property)(bt_bdaddr_t *remote_addr,
                                                      const bt_property_t *property);
        
            /** Get Remote Device's service record  for the given UUID */
            int (*get_remote_service_record)(bt_bdaddr_t *remote_addr,
                                                     bt_uuid_t *uuid);
        
            /** Start SDP to get remote services */
            int (*get_remote_services)(bt_bdaddr_t *remote_addr);
        
            /** Start Discovery */
            int (*start_discovery)(void);
        
            /** Cancel Discovery */
            int (*cancel_discovery)(void);
        
            /** Create Bluetooth Bonding */
            int (*create_bond)(const bt_bdaddr_t *bd_addr, int transport);
        
            /** Remove Bond */
            int (*remove_bond)(const bt_bdaddr_t *bd_addr);
        
            /** Cancel Bond */
            int (*cancel_bond)(const bt_bdaddr_t *bd_addr);
        
            /**
              * Get the connection status for a given remote device.
              * return value of 0 means the device is not connected,
              * non-zero return status indicates an active connection.
              */
            int (*get_connection_state)(const bt_bdaddr_t *bd_addr);
        
            /** BT Legacy PinKey Reply */
            /** If accept==FALSE, then pin_len and pin_code shall be 0x0 */
            int (*pin_reply)(const bt_bdaddr_t *bd_addr, uint8_t accept,
                                     uint8_t pin_len, bt_pin_code_t *pin_code);
        
            /** BT SSP Reply - Just Works, Numeric Comparison and Passkey
              * passkey shall be zero for BT_SSP_VARIANT_PASSKEY_COMPARISON &
              * BT_SSP_VARIANT_CONSENT
              * For BT_SSP_VARIANT_PASSKEY_ENTRY, if accept==FALSE, then passkey
              * shall be zero */
            int (*ssp_reply)(const bt_bdaddr_t *bd_addr, bt_ssp_variant_t variant,
                                     uint8_t accept, uint32_t passkey);
        
            /** Get Bluetooth profile interface */
            const void* (*get_profile_interface) (const char *profile_id);
        
            /** Bluetooth Test Mode APIs - Bluetooth must be enabled for these APIs */
            /* Configure DUT Mode - Use this mode to enter/exit DUT mode */
            int (*dut_mode_configure)(uint8_t enable);
        
            /* Send any test HCI (vendor-specific) command to the controller. Must be in DUT Mode */
            int (*dut_mode_send)(uint16_t opcode, uint8_t *buf, uint8_t len);
            /** BLE Test Mode APIs */
            /* opcode MUST be one of: LE_Receiver_Test, LE_Transmitter_Test, LE_Test_End */
            int (*le_test_mode)(uint16_t opcode, uint8_t *buf, uint8_t len);
        
            /* enable or disable bluetooth HCI snoop log */
            int (*config_hci_snoop_log)(uint8_t enable);
        
            /** Sets the OS call-out functions that bluedroid needs for alarms and wake locks.
               * This should be called immediately after a successful |init|.
               */
            int (*set_os_callouts)(bt_os_callouts_t *callouts);
        
            /** Read Energy info details - return value indicates BT_STATUS_SUCCESS or BT_STATUS_NOT_READY
               * Success indicates that the VSC command was sent to controller
               */
            int (*read_energy_info)();
        
            /**
              * Native support for dumpsys function
              * Function is synchronous and |fd| is owned by caller.
              */
            void (*dump)(int fd);
        
            /**
              * Clear /data/misc/bt_config.conf and erase all stored connections
              */
            int (*config_clear)(void);
        
        } bt_interface_t;

        可以知道bt_interface_t是个结构体类型

        其实吧,源码看到这儿我又走偏了,我们主要是分析set_adv_data是由那个类实现的

        搜索这个方法的调用是很绕的

        image.png

         只能搜索一个bt_gatt_client.h文件,那么继续搜索bt_gatt_client.h文件

        image.png

            继续搜索bt_gatt.h文件

         image.png

           然后一个一个文件点进去搜索set_adv_data方法,发现只有/system/bt/btif/src/btif_gatt_client.c这个类里包涵这个方法,但是名字不是完全一模一样。

           image.png

            image.png

            那么这个模块是怎么和外部模块建立关联的?用的什么机制?

            搜索btgattClientInterface这个变量

            image.png

               |    

            image.png

            搜索btif_gatt_get_interface方法

           image.png

                  

            image.png

            看看调用的方法:

             image.png

               

    

             

        

猜你喜欢

转载自blog.51cto.com/4259297/2176538