bluetooth: ots: reduce directory listing memory usage

Allocating a buffer to hold the entire directory listing consumes a very
large sum of memory when a large number of OTS objects are supported.

This implementation minimizes the memory footprint of the directory
listing by only allocating the minimum necessary buffer size to allow
for efficient over the air transfer. The contents of the transferred
buffer are built incrementally and upon request.

The directory listing manipulation upon object creation and deletion can
be removed since the directory listing content is never constructed
until it is requested.

Signed-off-by: Abe Kohandel <abe.kohandel@gmail.com>
This commit is contained in:
Abe Kohandel 2022-03-07 21:39:47 -08:00 committed by Carles Cufí
commit 3a03d9c50d
4 changed files with 221 additions and 116 deletions

View file

@ -297,7 +297,7 @@ int bt_ots_obj_add_internal(struct bt_ots *ots, struct bt_conn *conn,
struct bt_ots_obj_created_desc created_desc;
if (IS_ENABLED(CONFIG_BT_OTS_DIR_LIST_OBJ) && ots->dir_list &&
ots->dir_list->dir_list_obj->state.type != BT_GATT_OTS_OBJECT_IDLE_STATE) {
!bt_ots_dir_list_is_idle(ots->dir_list)) {
LOG_DBG("Directory Listing Object is being read");
return -EBUSY;
}
@ -308,10 +308,6 @@ int bt_ots_obj_add_internal(struct bt_ots *ots, struct bt_conn *conn,
return err;
}
if (IS_ENABLED(CONFIG_BT_OTS_DIR_LIST_OBJ)) {
bt_ots_dir_list_obj_add(ots->dir_list, ots->obj_manager, ots->cur_obj, new_obj);
}
(void)memset(&created_desc, 0, sizeof(created_desc));
if (ots->cb->obj_created) {
@ -320,11 +316,6 @@ int bt_ots_obj_add_internal(struct bt_ots *ots, struct bt_conn *conn,
if (err) {
(void)bt_gatt_ots_obj_manager_obj_delete(new_obj);
if (IS_ENABLED(CONFIG_BT_OTS_DIR_LIST_OBJ)) {
bt_ots_dir_list_obj_remove(ots->dir_list, ots->obj_manager,
ots->cur_obj, new_obj);
}
return err;
}
@ -407,7 +398,7 @@ int bt_ots_obj_delete(struct bt_ots *ots, uint64_t id)
}
if (IS_ENABLED(CONFIG_BT_OTS_DIR_LIST_OBJ) && ots->dir_list &&
ots->dir_list->dir_list_obj->state.type != BT_GATT_OTS_OBJECT_IDLE_STATE) {
!bt_ots_dir_list_is_idle(ots->dir_list)) {
LOG_DBG("Directory Listing Object is being read");
return -EBUSY;
}
@ -424,10 +415,6 @@ int bt_ots_obj_delete(struct bt_ots *ots, uint64_t id)
return err;
}
if (IS_ENABLED(CONFIG_BT_OTS_DIR_LIST_OBJ)) {
bt_ots_dir_list_obj_remove(ots->dir_list, ots->obj_manager, ots->cur_obj, obj);
}
if (ots->cur_obj == obj) {
ots->cur_obj = NULL;
}
@ -594,11 +581,6 @@ static void ots_delete_empty_name_objects(struct bt_ots *ots, struct bt_conn *co
ots->cb->obj_deleted(ots, conn, obj->id);
}
if (IS_ENABLED(CONFIG_BT_OTS_DIR_LIST_OBJ)) {
bt_ots_dir_list_obj_remove(ots->dir_list, ots->obj_manager,
ots->cur_obj, obj);
}
if (bt_gatt_ots_obj_manager_obj_delete(obj)) {
LOG_ERR("Failed to remove object with %s ID from object manager",
log_strdup(id_str));