From 8ab64c2aa957b3fe7cd4d6c09240c4076e7d0ee1 Mon Sep 17 00:00:00 2001 From: liuxiang18 Date: Mon, 14 Oct 2024 17:31:05 +0800 Subject: [PATCH] storage:patch for KVDB storage feature bug: v/42051 rootcause: implement the KVDB storage feature Signed-off-by: liuxiang18 --- Kconfig | 14 +- service/common/bluetooth_define.h | 2 + service/common/storage_property.c | 484 +++++++++++++++++++++++++++--- service/common/storage_property.h | 38 --- 4 files changed, 461 insertions(+), 77 deletions(-) delete mode 100644 service/common/storage_property.h diff --git a/Kconfig b/Kconfig index 0e1a34fc..bf346453 100644 --- a/Kconfig +++ b/Kconfig @@ -21,9 +21,17 @@ config BLUETOOTH depends on LIBUV_EXTENSION if BLUETOOTH -config BLUETOOTH_STORAGE_PROPERTY_SUPPORT - bool "Bluetooth Storage KVDB Property support" - default n + +choice + prompt "select Bluetooth Storage Method(Unqlite, KVDB)" + default BLUETOOTH_STORAGE_UNQLITE_SUPPORT + config BLUETOOTH_STORAGE_PROPERTY_SUPPORT + bool "Bluetooth Storage KVDB Property support" + depends on KVDB + config BLUETOOTH_STORAGE_UNQLITE_SUPPORT + bool "Bluetooth Storage uv_db support" + depends on UNQLITE +endchoice config BLUETOOTH_BREDR_SUPPORT bool "BREDR support" diff --git a/service/common/bluetooth_define.h b/service/common/bluetooth_define.h index a14eb96b..8d4b43da 100644 --- a/service/common/bluetooth_define.h +++ b/service/common/bluetooth_define.h @@ -67,6 +67,7 @@ typedef enum { typedef struct { bt_address_t addr; ble_addr_type_t addr_type; + // only can add member after "addr_type" if needed, see function bt_storage_save_remote_device for reasons. char name[BT_REM_NAME_MAX_LEN + 1]; char alias[BT_REM_NAME_MAX_LEN + 1]; uint32_t class_of_device; @@ -78,6 +79,7 @@ typedef struct { typedef struct { bt_address_t addr; ble_addr_type_t addr_type; + // only can add member after "addr_type" if needed, see function bt_storage_save_le_remote_device for reasons. uint8_t smp_key[80]; bt_device_type_t device_type; } remote_device_le_properties_t; diff --git a/service/common/storage_property.c b/service/common/storage_property.c index 9eff6acd..959a99d4 100644 --- a/service/common/storage_property.c +++ b/service/common/storage_property.c @@ -26,14 +26,20 @@ #include "bluetooth_define.h" #include "service_loop.h" -#include "storage_property.h" +#include "storage.h" #include "utils/log.h" #include "uv_ext.h" -#define GET_PROP_KEY(buf, key, address) snprintf((buf), sizeof((buf)), "%s%02X:%02X:%02X:%02X:%02X:%02X", \ - (key), \ - (address)->addr[5], (address)->addr[4], (address)->addr[3], \ - (address)->addr[2], (address)->addr[1], (address)->addr[0]); +#define GEN_PROP_KEY(buf, key, address, len) snprintf((buf), (len), "%s%02X:%02X:%02X:%02X:%02X:%02X", \ + (key), \ + (address)->addr[5], (address)->addr[4], (address)->addr[3], \ + (address)->addr[2], (address)->addr[1], (address)->addr[0]) + +#define PARSE_PROP_KEY(addr_str, name, name_prefix_len, addr_str_len, addr_ptr) \ + do { \ + strlcpy((addr_str), (name) + (name_prefix_len), (addr_str_len)); \ + bt_addr_str2ba((addr_str), (addr_ptr)); \ + } while (0) #define ERROR_ADAPTERINFO_VALUE -1 @@ -43,10 +49,136 @@ #define BT_KVDB_ADAPTERINFO_SCAN "persist.bluetooth.adapterInfo.scan_mode" #define BT_KVDB_ADAPTERINFO_BOND "persist.bluetooth.adapterInfo.bondable" +#define BT_KVDB_ADAPTERINFO "persist.bluetooth.adapterInfo." +#define BT_KVDB_BTBOND "persist.bluetooth.btbonded." +#define BT_KVDB_BLEBOND "persist.bluetooth.blebonded." +#define BT_KVDB_BLEWHITELIST "persist.bluetooth.whitelist." + +typedef struct { + void* key; + uint16_t items; + uint16_t offset; + uint32_t value_length; + uint8_t value[0]; +} bt_property_value_t; + +static int storage_set_key(const char* key, void* data, size_t length) +{ + int ret; + + ret = property_set_binary(key, data, length, false); + if (ret < 0) { + BT_LOGE("key %s set error!", key); + return ret; + } + property_commit(); + return ret; +} + +static void callback_bt_load_addr(const char* name, const char* value, void* cookie) +{ + char addr_str[BT_ADDR_STR_LENGTH]; + bt_property_value_t* prop_value; + remote_device_properties_t* remote; + + prop_value = (bt_property_value_t*)cookie; + if (strncmp(name, (char*)prop_value->key, strlen(prop_value->key))) + return; + + assert(prop_value->offset < prop_value->items); + remote = (remote_device_properties_t*)prop_value->value + prop_value->offset; + + PARSE_PROP_KEY(addr_str, name, strlen((char*)prop_value->key), BT_ADDR_STR_LENGTH, &remote->addr); + prop_value->offset++; +} + +static void callback_le_load_addr(const char* name, const char* value, void* cookie) +{ + char addr_str[BT_ADDR_STR_LENGTH]; + bt_property_value_t* prop_value; + remote_device_le_properties_t* remote; + + prop_value = (bt_property_value_t*)cookie; + if (strncmp(name, (char*)prop_value->key, strlen(prop_value->key))) + return; + + assert(prop_value->offset < prop_value->items); + remote = (remote_device_le_properties_t*)prop_value->value + prop_value->offset; + + PARSE_PROP_KEY(addr_str, name, strlen((char*)prop_value->key), BT_ADDR_STR_LENGTH, &remote->addr); + prop_value->offset++; +} + +static void storage_get_key(const char* key, void* data, uint16_t value_len, void* cookie) +{ + bt_property_value_t* prop_value; + remote_device_properties_t* bt_remote; + remote_device_le_properties_t* le_remote; + bt_address_t* addr; + size_t prop_size; + char* prop_name; + int i; + + if (!key || !data) + return; + + if (!strncmp(key, BT_KVDB_ADAPTERINFO, strlen(BT_KVDB_ADAPTERINFO))) { + adapter_storage_t* adapter = (adapter_storage_t*)data; + adapter->class_of_device = property_get_int32(BT_KVDB_ADAPTERINFO_COD, ERROR_ADAPTERINFO_VALUE); + adapter->io_capability = property_get_int32(BT_KVDB_ADAPTERINFO_IOCAP, ERROR_ADAPTERINFO_VALUE); + adapter->scan_mode = property_get_int32(BT_KVDB_ADAPTERINFO_SCAN, ERROR_ADAPTERINFO_VALUE); + adapter->bondable = property_get_int32(BT_KVDB_ADAPTERINFO_BOND, ERROR_ADAPTERINFO_VALUE); + return; + } + + prop_value = (bt_property_value_t*)data; + if (prop_value->items == 0) { + ((load_storage_callback_t)cookie)(NULL, 0, 0); + return; + } + + prop_name = (char*)malloc(PROP_NAME_MAX); + if (!prop_name) { + BT_LOGE("property_name malloc failed!"); + return; + } + + if (!strncmp(key, BT_KVDB_BTBOND, strlen(BT_KVDB_BTBOND))) { + property_list(callback_bt_load_addr, data); // get addr to generate property name + for (i = 0; i < prop_value->items; i++) { + bt_remote = (remote_device_properties_t*)prop_value->value + i; + addr = &bt_remote->addr; + GEN_PROP_KEY(prop_name, key, addr, PROP_NAME_MAX); + /** + * Note: It should be ensured that "addr" is the first member of the struct remote_device_properties_t + * and "addr_type" is the second member. + * */ + prop_size = sizeof(remote_device_properties_t) - offsetof(remote_device_properties_t, addr_type); + property_get_binary(prop_name, &bt_remote->addr_type, prop_size); + } + } else { /*!BT_KVDB_BTBOND*/ + property_list(callback_le_load_addr, data); // get addr to generate property name + for (i = 0; i < prop_value->items; i++) { + le_remote = (remote_device_le_properties_t*)prop_value->value + i; + addr = &le_remote->addr; + GEN_PROP_KEY(prop_name, key, addr, PROP_NAME_MAX); + /** + * Note: It should be ensured that "addr" is the first member of the struct remote_device_le_properties_t + * and "addr_type" is the second member. + * */ + prop_size = sizeof(remote_device_le_properties_t) - offsetof(remote_device_le_properties_t, addr_type); + property_get_binary(prop_name, &le_remote->addr_type, prop_size); + } + } + ((load_storage_callback_t)cookie)(prop_value->value, value_len, prop_value->items); + free(prop_name); +} + static void adapter_properties_default(adapter_storage_t* prop) { srand(time(NULL)); - snprintf(prop->name, BT_LOC_NAME_MAX_LEN, "%s-%03X", "XIAOMI VELA", rand() % 999); + memset(prop->name, 0, sizeof(prop->name)); + snprintf(prop->name, sizeof(prop->name), "%s-%03X", "XIAOMI VELA", rand() % 999); prop->class_of_device = DEFAULT_DEVICE_OF_CLASS; prop->io_capability = DEFAULT_IO_CAPABILITY; prop->scan_mode = DEFAULT_SCAN_MODE; @@ -55,7 +187,7 @@ static void adapter_properties_default(adapter_storage_t* prop) int bt_storage_save_adapter_info(adapter_storage_t* adapter) { - property_set_buffer(BT_KVDB_ADAPTERINFO_NAME, adapter->name, sizeof(adapter->name)); + property_set_binary(BT_KVDB_ADAPTERINFO_NAME, adapter->name, sizeof(adapter->name), false); property_set_int32(BT_KVDB_ADAPTERINFO_COD, adapter->class_of_device); property_set_int32(BT_KVDB_ADAPTERINFO_IOCAP, adapter->io_capability); property_set_int32(BT_KVDB_ADAPTERINFO_SCAN, adapter->scan_mode); @@ -66,70 +198,350 @@ int bt_storage_save_adapter_info(adapter_storage_t* adapter) int bt_storage_load_adapter_info(adapter_storage_t* adapter) { - if (property_get_buffer(BT_KVDB_ADAPTERINFO_NAME, adapter->name, sizeof(adapter->name)) > 0) { - adapter->class_of_device = property_get_int32(BT_KVDB_ADAPTERINFO_COD, ERROR_ADAPTERINFO_VALUE); - adapter->io_capability = property_get_int32(BT_KVDB_ADAPTERINFO_IOCAP, ERROR_ADAPTERINFO_VALUE); - adapter->scan_mode = property_get_int32(BT_KVDB_ADAPTERINFO_SCAN, ERROR_ADAPTERINFO_VALUE); - adapter->bondable = property_get_int32(BT_KVDB_ADAPTERINFO_BOND, ERROR_ADAPTERINFO_VALUE); - } else { - adapter_properties_default(adapter); - bt_storage_save_adapter_info(adapter); + if (property_get_binary(BT_KVDB_ADAPTERINFO_NAME, adapter->name, sizeof(adapter->name)) > 0) { + storage_get_key(BT_KVDB_ADAPTERINFO, (void*)adapter, sizeof(adapter_storage_t), NULL); + if (adapter->class_of_device != ERROR_ADAPTERINFO_VALUE && adapter->io_capability != ERROR_ADAPTERINFO_VALUE + && adapter->scan_mode != ERROR_ADAPTERINFO_VALUE && adapter->bondable != ERROR_ADAPTERINFO_VALUE) + return 0; } + BT_LOGE("load default adapter info!"); + adapter_properties_default(adapter); + bt_storage_save_adapter_info(adapter); return 0; } -int bt_storage_save_bonded_device(remote_device_properties_t* remote, uint16_t size) +static int bt_storage_save_remote_device(const char* key, void* value, uint16_t value_size, uint16_t items) { - return -1; + size_t prop_vlen; + char* prop_name; + remote_device_properties_t* data; + bt_address_t* addr; + int i; + int ret; + + if (!key || !value) + return 0; + + prop_name = (char*)malloc(PROP_NAME_MAX); + if (!prop_name) { + BT_LOGE("property_name malloc failed!"); + return -ENOMEM; + } + data = (remote_device_properties_t*)value; + prop_vlen = value_size - offsetof(remote_device_properties_t, addr_type); + for (i = 0; i < items; i++) { + addr = &data->addr; + GEN_PROP_KEY(prop_name, key, addr, PROP_NAME_MAX); + /** + * Note: It should be ensured that "addr" is the first member of the struct remote_device_properties_t + * and "addr_type" is the second member. + * */ + ret = storage_set_key(prop_name, &data->addr_type, prop_vlen); + if (ret < 0) { + free(prop_name); + return ret; + } + data++; + } + free(prop_name); + return 0; } -int bt_storage_save_whitelist(remote_device_le_properties_t* remote, uint16_t size) +/*BR_KVDB_BLEBOND or BT_KVDB_BLEWHITELIST*/ +static int bt_storage_save_le_remote_device(const char* key, void* value, uint16_t value_size, uint16_t items) { - return -1; + size_t prop_vlen; + char* prop_name; + remote_device_le_properties_t* data; + bt_address_t* addr; + int i; + int ret; + + if (!key || !value) + return 0; + + prop_name = (char*)malloc(PROP_NAME_MAX); + if (!prop_name) { + BT_LOGE("property_name malloc failed!"); + return -ENOMEM; + } + data = (remote_device_le_properties_t*)value; + prop_vlen = value_size - offsetof(remote_device_le_properties_t, addr_type); + for (i = 0; i < items; i++) { + addr = &data->addr; + GEN_PROP_KEY(prop_name, key, addr, PROP_NAME_MAX); + /** + * Note: It should be ensured that "addr" is the first member of the struct remote_device_le_properties_t + * and "addr_type" is the second member. + * */ + ret = storage_set_key(prop_name, &data->addr_type, prop_vlen); + if (ret < 0) { + free(prop_name); + return ret; + } + data++; + } + free(prop_name); + return 0; } -int bt_storage_save_le_bonded_device(remote_device_le_properties_t* remote, uint16_t size) +static void callback_bt_count(const char* name, const char* value, void* count_u16) { - return -1; + if (!strncmp(name, BT_KVDB_BTBOND, strlen(BT_KVDB_BTBOND))) { + (*(uint16_t*)count_u16)++; + } } -int bt_storage_load_bonded_device(load_storage_callback_t cb) +static void callback_le_count(const char* name, const char* value, void* count_u16) { - return -1; + if (!strncmp(name, BT_KVDB_BLEBOND, strlen(BT_KVDB_BLEBOND))) { + (*(uint16_t*)count_u16)++; + } } -int bt_storage_load_whitelist_device(load_storage_callback_t cb) +static void callback_whitelist_count(const char* name, const char* value, void* count_u16) { - return -1; + if (!strncmp(name, BT_KVDB_BLEWHITELIST, strlen(BT_KVDB_BLEWHITELIST))) { + (*(uint16_t*)count_u16)++; + } } -int bt_storage_load_le_bonded_device(load_storage_callback_t cb) +static void callback_load_key(const char* name, const char* value, void* cookie) +{ + char addr_str[BT_ADDR_STR_LENGTH]; + bt_property_value_t* prop_value; + bt_address_t* addr; + + prop_value = (bt_property_value_t*)cookie; + + if (strncmp(name, (char*)prop_value->key, strlen(prop_value->key))) + return; + + assert(prop_value->offset < prop_value->items); + addr = (bt_address_t*)prop_value->value + prop_value->offset; + PARSE_PROP_KEY(addr_str, name, strlen((char*)prop_value->key), BT_ADDR_STR_LENGTH, addr); + prop_value->offset++; +} + +static void bt_storage_delete(char* key, uint16_t items, char* prop_name) { - return -1; + bt_property_value_t* prop_value; + uint32_t total_length; + bt_address_t* addr; + int i; + + if (!key || !prop_name) + return; + + total_length = items * sizeof(bt_address_t); + prop_value = malloc(sizeof(bt_property_value_t) + total_length); + if (!prop_value) { + BT_LOGE("property malloc failed!"); + return; + } + + prop_value->key = key; + prop_value->items = items; + prop_value->offset = 0; + prop_value->value_length = total_length; + + property_list(callback_load_key, (void*)prop_value); + for (i = 0; i < items; i++) { + addr = (bt_address_t*)prop_value->value + i; + GEN_PROP_KEY(prop_name, key, addr, PROP_NAME_MAX); + property_delete(prop_name); + property_commit(); + } + free(prop_value); +} + +int bt_storage_save_bonded_device(remote_device_properties_t* remote, uint16_t size) +{ + uint16_t items = 0; + char* prop_name; + int ret; + + prop_name = (char*)malloc(PROP_NAME_MAX); + if (!prop_name) { + BT_LOGE("property_name malloc failed!"); + return -ENOMEM; + } + + /* remove all BREDR bond device property before save new property*/ + property_list(callback_bt_count, &items); + bt_storage_delete(BT_KVDB_BTBOND, items, prop_name); + + ret = bt_storage_save_remote_device(BT_KVDB_BTBOND, remote, sizeof(remote_device_properties_t), size); + if (ret < 0) { + BT_LOGE("save bonded device failed!"); + items = 0; + property_list(callback_bt_count, &items); + bt_storage_delete(BT_KVDB_BTBOND, items, prop_name); + } + + free(prop_name); + return ret; +} + +int bt_storage_save_whitelist(remote_device_le_properties_t* remote, uint16_t size) +{ + uint16_t items = 0; + char* prop_name; + int ret; + + prop_name = (char*)malloc(PROP_NAME_MAX); + if (!prop_name) { + BT_LOGE("property_name malloc failed!"); + return -ENOMEM; + } + + /* remove all whitelist device property before save new property*/ + property_list(callback_whitelist_count, &items); + bt_storage_delete(BT_KVDB_BLEWHITELIST, items, prop_name); + + ret = bt_storage_save_le_remote_device(BT_KVDB_BLEWHITELIST, remote, sizeof(remote_device_le_properties_t), size); + if (ret < 0) { + BT_LOGE("save whitelist device failed!"); + items = 0; + property_list(callback_whitelist_count, &items); + bt_storage_delete(BT_KVDB_BLEWHITELIST, items, prop_name); + } + + free(prop_name); + return ret; +} + +int bt_storage_save_le_bonded_device(remote_device_le_properties_t* remote, uint16_t size) +{ + uint16_t items = 0; + char* prop_name; + int ret; + + prop_name = (char*)malloc(PROP_NAME_MAX); + if (!prop_name) { + BT_LOGE("property_name malloc failed!"); + return -ENOMEM; + } + + /* remove all BLE bond device property before save new property*/ + property_list(callback_le_count, &items); + bt_storage_delete(BT_KVDB_BLEBOND, items, prop_name); + + ret = bt_storage_save_le_remote_device(BT_KVDB_BLEBOND, remote, sizeof(remote_device_le_properties_t), size); + if (ret < 0) { + BT_LOGE("save LE bonded device failed!"); + items = 0; + property_list(callback_le_count, &items); + bt_storage_delete(BT_KVDB_BLEBOND, items, prop_name); + } + + free(prop_name); + return ret; } -int bt_storage_delete_bonded_device(bt_address_t* addr) +int bt_storage_load_bonded_device(load_storage_callback_t cb) { - return -1; + uint16_t items; + bt_property_value_t* prop_value; + uint32_t total_length; + int ret; + + items = 0; + ret = property_list(callback_bt_count, &items); + if (ret < 0) { + BT_LOGE("property_list failed!"); + return ret; + } + + total_length = items * sizeof(remote_device_properties_t); + prop_value = malloc(sizeof(bt_property_value_t) + total_length); + if (!prop_value) { + BT_LOGE("property malloc failed!"); + return -ENOMEM; + } + + prop_value->key = BT_KVDB_BTBOND; + prop_value->items = items; + prop_value->offset = 0; + prop_value->value_length = total_length; + + storage_get_key(BT_KVDB_BTBOND, (void*)prop_value, sizeof(remote_device_properties_t), (void*)cb); + free(prop_value); + + return 0; } -int bt_storage_delete_whitelist_device(bt_address_t* addr) +int bt_storage_load_whitelist_device(load_storage_callback_t cb) { - return -1; + uint16_t items; + bt_property_value_t* prop_value; + uint32_t total_length; + int ret; + + items = 0; + ret = property_list(callback_whitelist_count, &items); + if (ret < 0) { + BT_LOGE("property_list failed!"); + return ret; + } + + total_length = items * sizeof(remote_device_le_properties_t); + prop_value = malloc(sizeof(bt_property_value_t) + total_length); + if (!prop_value) { + BT_LOGE("property malloc failed!"); + return -ENOMEM; + } + + prop_value->key = BT_KVDB_BLEWHITELIST; + prop_value->items = items; + prop_value->offset = 0; + prop_value->value_length = total_length; + + storage_get_key(BT_KVDB_BLEWHITELIST, (void*)prop_value, sizeof(remote_device_le_properties_t), (void*)cb); + free(prop_value); + + return 0; } -int bt_storage_delete_le_bonded_device(bt_address_t* addr) +int bt_storage_load_le_bonded_device(load_storage_callback_t cb) { - return -1; + uint16_t items; + bt_property_value_t* prop_value; + uint32_t total_length; + int ret; + + items = 0; + ret = property_list(callback_le_count, &items); + if (ret < 0) { + BT_LOGE("property_list failed!"); + return ret; + } + + total_length = items * sizeof(remote_device_le_properties_t); + prop_value = malloc(sizeof(bt_property_value_t) + total_length); + if (!prop_value) { + BT_LOGE("property malloc failed!"); + return -ENOMEM; + } + + prop_value->key = BT_KVDB_BLEBOND; + prop_value->items = items; + prop_value->offset = 0; + prop_value->value_length = total_length; + + storage_get_key(BT_KVDB_BLEBOND, (void*)prop_value, sizeof(remote_device_le_properties_t), (void*)cb); + free(prop_value); + + return 0; } int bt_storage_init(void) { - return -1; + return 0; } int bt_storage_cleanup(void) { - return -1; -} \ No newline at end of file + return 0; +} diff --git a/service/common/storage_property.h b/service/common/storage_property.h deleted file mode 100644 index 90bc70fd..00000000 --- a/service/common/storage_property.h +++ /dev/null @@ -1,38 +0,0 @@ -/**************************************************************************** - * Copyright (C) 2024 Xiaomi Corporation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - ***************************************************************************/ -#ifndef _BT_STORAGE_PROPERTY_H__ -#define _BT_STORAGE_PROPERTY_H__ - -#include "bluetooth_define.h" - -typedef void (*load_storage_callback_t)(void* data, uint16_t length, uint16_t items); - -int bt_storage_init(void); -int bt_storage_cleanup(void); - -int bt_storage_save_adapter_info(adapter_storage_t* adapter); -int bt_storage_load_adapter_info(adapter_storage_t* adapter); -int bt_storage_save_bonded_device(remote_device_properties_t* remote, uint16_t size); -int bt_storage_save_whitelist(remote_device_le_properties_t* remote, uint16_t size); -int bt_storage_save_le_bonded_device(remote_device_le_properties_t* remote, uint16_t size); -int bt_storage_load_bonded_device(load_storage_callback_t cb); -int bt_storage_load_whitelist_device(load_storage_callback_t cb); -int bt_storage_load_le_bonded_device(load_storage_callback_t cb); -int bt_storage_delete_bonded_device(bt_address_t* addr); -int bt_storage_delete_whitelist_device(bt_address_t* addr); -int bt_storage_delete_le_bonded_device(bt_address_t* addr); - -#endif /* _BT_STORAGE_PROPERTY_H__ */ \ No newline at end of file