[Android P] 蓝牙mac地址的读取与修改

1、蓝牙mac地址格式

蓝牙设备地址(BD_ADDR)是一个48bit的唯一标识符,由LAP(24位地址低端部分)、UAP(8位地址高端部分)和NAP(16位无意义地址部分)组成,其格式如下所示:

          LSB                                                       MSB
          |0000 0001 0000 0000 0000 0000|0001 0010|0111 1011 0011 0101|
          |<----------(24bit)---------->|<( 8bit)>|<----+(16bit)+---->|
          |             LAP             |   UAP   |        NAP        |

NAP和UAP是蓝牙设备生产厂商的唯一标识码,由SIG分配给各个厂商;LAP则由厂商自行分配。

其中,bit40为组播地址标志位,其值为0:unicast(单播),其值为1:multicast(组播);bit41为地址类型标志位,其值为0:universal addr,其值为1:local addr。

2、读取蓝牙mac地址

在函数BluetoothAddress::GetLocalAddress()中展示了数种方式读取蓝牙BD_ADDR。
首先函数fetch_vendor_addr(local_addr)读取存储在vendor下bt_nv.bin文件中的蓝牙地址:

vendor/qcom/proprietary/bluetooth/hidl_transport/bt/1.0/default/bluetooth_address.cpp
bool fetch_vendor_addr(uint8_t * addr ){
  cmd_result = (nv_persist_stat_enum_type)bt_nv_cmd(NV_READ_F,NV_BD_ADDR_I, &my_nv_item); 
}

vendor/qcom/proprietary/bt/hci_qcomm_init/bt_nv.cpp
int bt_nv_cmd(nv_persist_func_enum_type nvReadWriteFunc, nv_persist_items_enum_type
nvitem,nv_persist_item_type *my_nv_item, int bIsRandom){
 numitems = bt_nv_read(params_temp)
 switch(nvReadWriteFunc){
   case NV_READ_F:                        //read from file
   ......
   if(nvitem == NV_BD_ADDR_I){
     memcpy((*my_nv_item).bd_addr, params_temp[item].pCmdBuffer, NV_BD_ADDR_SIZE );
   ......
 }
 
#define PERSISTENCE_PATH "/vendor/factory"
#define BT_NV_FILE_NAME "bt_nv.bin"
int bt_nv_read (nv_persist_params *params_read) {
 snprintf(filename, NAME_MAX, "%s/%s",PERSISTENCE_PATH,BT_NV_FILE_NAME);}

其次是从system property中获取本地蓝牙地址路径:

static constexpr char PROPERTY_BT_BDADDR_PATH[] = "ro.vendor.bt.bdaddr_path";
static constexpr char PROPERTY_BT_BDADDR_PATH[] = "ro.bt.bdaddr_path";
property_get(PROPERTY_BT_BDADDR_PATH, property, NULL)
const uint8_t zero_bdaddr[kBytes] = { 0, 0, 0, 0, 0, 0 };
if ((StringToBytes(property, local_addr)) && (memcmp(local_addr, zero_bdaddr, kBytes) != 0)) {
  valid_bda = true;
  le2bd(local_addr);
  ALOGD("%s: Got Factory BDA %s", __func__, property)
}

若以上两种方法均不能获得BD_ADDR,则尝试从factory property中获取:

static constexpr char FACTORY_BDADDR_PROPERTY[] = "ro.boot.btmacaddr";
static constexpr char FACTORY_BDADDR_PROPERTY[] = "ro.vendor.bt.boot.macaddr";if (!valid_bda && property_get(FACTORY_BDADDR_PROPERTY, property, NULL) &&
StringToBytes(property, local_addr)) {
  valid_bda = true;
  le2bd(local_addr); 
}

再者,若从factory property中也无法获取到BD_ADDR,可以从之前保存的BDA中查找:

static constexpr char PERSIST_BDADDR_PROPERTY[] = "persist.service.bdroid.bdaddr";
static constexpr char PERSIST_BDADDR_PROPERTY[] = "persist.vendor.service.bdroid.bdaddr";

if (!valid_bda && property_get(PERSIST_BDADDR_PROPERTY, property, NULL) &&
StringToBytes(property, local_addr)) {
  valid_bda = true;
  le2bd(local_addr);
}

以上方法均无法获取到固定地址时,则生成随机地址,其形式为0x22:22:xx:xx:xx:xx,然后将之保存在property之中,每次重新开关机后会生成新的随机地址:

  /* No autogen BDA. Generate one now. */
  local_addr[0] = 0x22;
  local_addr[1] = 0x22;
  local_addr[2] = (uint8_t)rand();
  local_addr[3] = (uint8_t)rand();
  local_addr[4] = (uint8_t)rand();
  local_addr[5] = (uint8_t)rand();
  
  /* Convert to ascii, and store as a persistent property */
  BytesToString(local_addr, bdstr);
  
  if (property_set(PERSIST_BDADDR_PROPERTY, (char*)bdstr) < 0) {
    ALOGE("%s: Failed to set random BDA in prop %s",__func__,PERSIST_BDADDR_PROPERTY);
    valid_bda = false;
  }
   else {
    valid_bda = true;
    le2bd(local_addr);
  }

3、修改蓝牙mac地址

  • 使用bluedroid中提供的btnvtool修改蓝牙地址,具体过程如下:
#adb shell
#btnvtool -p                    // display bt address
#btnvtool -b aa:bb:cc:dd:ee:ff  // change bt address to be aa:bb:cc:dd:ee:ff
  • 使用高通QXDM工具修改蓝牙地址,在nv工具中ID:00447对应的BT地址中可以直接修改。

你可能感兴趣的:([Android P] 蓝牙mac地址的读取与修改)