Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b500a2a8 authored by Jakub Pawlowski's avatar Jakub Pawlowski Committed by Jakub Pawłowski
Browse files

LE Audio: Use Read Multiple for initial ASE read

For some earbuds this can reduce LE profile connection time by 300ms

Devices that don't support EATT, might not support Read Multiple
Variable Length. For them, we would simulate "Read Multiple" in stack.

Test: atest bluetooth_le_audio_client_test
Flag: le_ase_read_multiple_variable
Bug: 352085435
Bug: 296836982
Change-Id: I5aeb3178115eb02e503a9f18ca4cf11fe14dec7f
parent 09b86f65
Loading
Loading
Loading
Loading
+69 −3
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@

#include "audio_hal_client/audio_hal_client.h"
#include "audio_hal_interface/le_audio_software.h"
#include "bt_types.h"
#include "bta/csis/csis_types.h"
#include "bta_gatt_api.h"
#include "bta_gatt_queue.h"
@@ -43,6 +44,7 @@
#include "common/time_util.h"
#include "content_control_id_keeper.h"
#include "devices.h"
#include "gatt_api.h"
#include "hci/controller_interface.h"
#include "internal_include/stack_config.h"
#include "le_audio_health_status.h"
@@ -353,6 +355,8 @@ public:
    int ases_num = leAudioDevice->ases_.size();
    void* notify_flag_ptr = NULL;

    tBTA_GATTC_MULTI multi_read{};

    for (int i = 0; i < ases_num; i++) {
      /* Last read ase characteristic should issue connected state callback
       * to upper layer
@@ -362,9 +366,26 @@ public:
        notify_flag_ptr = INT_TO_PTR(leAudioDevice->notify_connected_after_read_);
      }

      if (!com::android::bluetooth::flags::le_ase_read_multiple_variable()) {
        BtaGattQueue::ReadCharacteristic(leAudioDevice->conn_id_,
                                         leAudioDevice->ases_[i].hdls.val_hdl, OnGattReadRspStatic,
                                         notify_flag_ptr);
        continue;
      }

      if (i != 0 && (i % GATT_MAX_READ_MULTI_HANDLES == 0)) {
        multi_read.num_attr = GATT_MAX_READ_MULTI_HANDLES;
        BtaGattQueue::ReadMultiCharacteristic(leAudioDevice->conn_id_, multi_read,
                                              OnGattReadMultiRspStatic, notify_flag_ptr);
        memset(multi_read.handles, 0, GATT_MAX_READ_MULTI_HANDLES * sizeof(uint16_t));
      }
      multi_read.handles[i % GATT_MAX_READ_MULTI_HANDLES] = leAudioDevice->ases_[i].hdls.val_hdl;
    }

    if (ases_num % GATT_MAX_READ_MULTI_HANDLES != 0) {
      multi_read.num_attr = ases_num % GATT_MAX_READ_MULTI_HANDLES;
      BtaGattQueue::ReadMultiCharacteristic(leAudioDevice->conn_id_, multi_read,
                                            OnGattReadMultiRspStatic, notify_flag_ptr);
    }
  }

@@ -4960,6 +4981,51 @@ public:
    }
  }

  static void OnGattReadMultiRspStatic(uint16_t conn_id, tGATT_STATUS status,
                                       tBTA_GATTC_MULTI& handles, uint16_t total_len,
                                       uint8_t* value, void* data) {
    if (!instance) {
      return;
    }

    if (status == GATT_DATABASE_OUT_OF_SYNC) {
      LeAudioDevice* leAudioDevice = instance->leAudioDevices_.FindByConnId(conn_id);
      instance->ClearDeviceInformationAndStartSearch(leAudioDevice);
      return;
    }
    if (status != GATT_SUCCESS) {
      log::error("Failed to read multiple attributes, conn_id: 0x{:04x}, status: 0x{:02x}", conn_id,
                 +status);
      return;
    }

    size_t position = 0;
    int index = 0;
    while (position != total_len) {
      uint8_t* ptr = value + position;
      uint16_t len;
      STREAM_TO_UINT16(len, ptr);
      uint16_t hdl = handles.handles[index];

      if (position + len >= total_len) {
        log::warn("Multi read was too long, value truncated conn_id: 0x{:04x} handle: 0x{:04x}",
                  conn_id, hdl);
        break;
      }

      OnGattReadRspStatic(conn_id, status, hdl, len, ptr,
                          ((index == (handles.num_attr - 1)) ? data : nullptr));

      position += len + 2; /* skip the length of data */
      index++;
    }

    if (handles.num_attr - 1 != index) {
      log::warn("Attempted to read {} handles, but received just {} values", +handles.num_attr,
                index + 1);
    }
  }

  void LeAudioHealthSendRecommendation(const RawAddress& address, int group_id,
                                       LeAudioHealthBasedAction action) {
    log::debug("{}, {}, {}", address, group_id, ToString(action));