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

Commit 80503c12 authored by Jakub Tyszkowski's avatar Jakub Tyszkowski
Browse files

LeAudio: Add persistent storage for GMAP

For the bonded devices, service discovery is
skipped and service data needs to be restored from the persistent
storage for the GMAS client to work. The storage will not be used when
GMAP feature flag is disabled.

Bug: 383623629
Bug: 353978074
Test: atest bluetooth_le_audio_test
Flag: Exempt; Covered with unit tests
Change-Id: Ib01c38e7e6eed6103fccb70953483bb0e32abb87
parent e97e59c7
Loading
Loading
Loading
Loading
+6 −8
Original line number Diff line number Diff line
@@ -36,10 +36,8 @@ using namespace bluetooth;
using bluetooth::le_audio::GmapClient;
bool GmapClient::is_offloader_support_gmap_ = false;

void GmapClient::AddFromStorage(const RawAddress &addr, const uint8_t role,
                                const uint16_t role_handle, const uint8_t UGT_feature,
                                const uint16_t UGT_feature_handle) {
  addr_ = addr;
void GmapClient::AddFromStorage(uint8_t role, uint16_t role_handle, uint8_t UGT_feature,
                                uint16_t UGT_feature_handle) {
  role_ = role;
  role_handle_ = role_handle;
  UGT_feature_ = UGT_feature;
@@ -90,14 +88,14 @@ bool GmapClient::parseAndSaveUGTFeature(uint16_t len, const uint8_t *value) {
  return true;
}

std::bitset<8> GmapClient::getRole() { return role_; }
std::bitset<8> GmapClient::getRole() const { return role_; }

uint16_t GmapClient::getRoleHandle() { return role_handle_; }
uint16_t GmapClient::getRoleHandle() const { return role_handle_; }

void GmapClient::setRoleHandle(uint16_t handle) { role_handle_ = handle; }

std::bitset<8> GmapClient::getUGTFeature() { return UGT_feature_; }
std::bitset<8> GmapClient::getUGTFeature() const { return UGT_feature_; }

uint16_t GmapClient::getUGTFeatureHandle() { return UGT_feature_handle_; }
uint16_t GmapClient::getUGTFeatureHandle() const { return UGT_feature_handle_; }

void GmapClient::setUGTFeatureHandle(uint16_t handle) { UGT_feature_handle_ = handle; }
+1 −1
Original line number Diff line number Diff line
@@ -68,7 +68,7 @@ TEST_F(GmapClientTest, test_add_from_storage) {
  const uint16_t role_handle = 2;
  const uint8_t UGT_feature = 0b0011;
  const uint16_t UGT_feature_handle = 4;
  gmapClient.AddFromStorage(addr, role, role_handle, UGT_feature, UGT_feature_handle);
  gmapClient.AddFromStorage(role, role_handle, UGT_feature, UGT_feature_handle);
  ASSERT_EQ(gmapClient.getRole(), role);
  ASSERT_EQ(gmapClient.getRoleHandle(), role_handle);
  ASSERT_EQ(gmapClient.getUGTFeature(), UGT_feature);
+2 −1
Original line number Diff line number Diff line
@@ -86,8 +86,9 @@ public:
                             const std::vector<uint8_t>& handles,
                             const std::vector<uint8_t>& sink_pacs,
                             const std::vector<uint8_t>& source_pacs,
                             const std::vector<uint8_t>& ases);
                             const std::vector<uint8_t>& ases, const std::vector<uint8_t>& gmap);
  static bool GetHandlesForStorage(const RawAddress& addr, std::vector<uint8_t>& out);
  static bool GetGmapForStorage(const RawAddress& addr, std::vector<uint8_t>& out);
  static bool GetSinkPacsForStorage(const RawAddress& addr, std::vector<uint8_t>& out);
  static bool GetSourcePacsForStorage(const RawAddress& addr, std::vector<uint8_t>& out);
  static bool GetAsesForStorage(const RawAddress& addr, std::vector<uint8_t>& out);
+33 −10
Original line number Diff line number Diff line
@@ -1847,7 +1847,8 @@ public:
                      int source_audio_location, int sink_supported_context_types,
                      int source_supported_context_types, const std::vector<uint8_t>& handles,
                      const std::vector<uint8_t>& sink_pacs,
                      const std::vector<uint8_t>& source_pacs, const std::vector<uint8_t>& ases) {
                      const std::vector<uint8_t>& source_pacs, const std::vector<uint8_t>& ases,
                      const std::vector<uint8_t>& gmap) {
    LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);

    if (leAudioDevice) {
@@ -1916,6 +1917,14 @@ public:
      log::warn("Could not load ases");
    }

    if (gmap.size() != 0) {
      leAudioDevice->gmap_client_ = std::make_unique<GmapClient>(leAudioDevice->address_);
      if (!le_audio::DeserializeGmap(leAudioDevice->gmap_client_.get(), gmap)) {
        leAudioDevice->gmap_client_.reset();
        log::warn("Invalid GMAP storage for {}", leAudioDevice->address_);
      }
    }

    leAudioDevice->autoconnect_flag_ = autoconnect;
    /* When adding from storage, make sure that autoconnect is used
     * by all the devices in the group.
@@ -1929,6 +1938,11 @@ public:
    return SerializeHandles(leAudioDevice, out);
  }

  bool GetGmapForStorage(const RawAddress& addr, std::vector<uint8_t>& out) {
    LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(addr);
    return SerializeGmap(leAudioDevice->gmap_client_.get(), out);
  }

  bool GetSinkPacsForStorage(const RawAddress& addr, std::vector<uint8_t>& out) {
    LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(addr);
    return SerializeSinkPacs(leAudioDevice, out);
@@ -2330,9 +2344,11 @@ public:
    } else if (leAudioDevice->gmap_client_ != nullptr && GmapClient::IsGmapClientEnabled() &&
               hdl == leAudioDevice->gmap_client_->getRoleHandle()) {
      leAudioDevice->gmap_client_->parseAndSaveGmapRole(len, value);
      btif_storage_leaudio_update_gmap_bin(leAudioDevice->address_);
    } else if (leAudioDevice->gmap_client_ != nullptr && GmapClient::IsGmapClientEnabled() &&
               hdl == leAudioDevice->gmap_client_->getUGTFeatureHandle()) {
      leAudioDevice->gmap_client_->parseAndSaveUGTFeature(len, value);
      btif_storage_leaudio_update_gmap_bin(leAudioDevice->address_);
    } else {
      log::error("Unknown attribute read: 0x{:x}", hdl);
    }
@@ -6469,14 +6485,12 @@ DeviceGroupsCallbacksImpl deviceGroupsCallbacksImpl;

}  // namespace

void LeAudioClient::AddFromStorage(const RawAddress& addr, bool autoconnect,
                                   int sink_audio_location, int source_audio_location,
                                   int sink_supported_context_types,
                                   int source_supported_context_types,
                                   const std::vector<uint8_t>& handles,
                                   const std::vector<uint8_t>& sink_pacs,
                                   const std::vector<uint8_t>& source_pacs,
                                   const std::vector<uint8_t>& ases) {
void LeAudioClient::AddFromStorage(
        const RawAddress& addr, bool autoconnect, int sink_audio_location,
        int source_audio_location, int sink_supported_context_types,
        int source_supported_context_types, const std::vector<uint8_t>& handles,
        const std::vector<uint8_t>& sink_pacs, const std::vector<uint8_t>& source_pacs,
        const std::vector<uint8_t>& ases, const std::vector<uint8_t>& gmap) {
  if (!instance) {
    log::error("Not initialized yet");
    return;
@@ -6484,7 +6498,7 @@ void LeAudioClient::AddFromStorage(const RawAddress& addr, bool autoconnect,

  instance->AddFromStorage(addr, autoconnect, sink_audio_location, source_audio_location,
                           sink_supported_context_types, source_supported_context_types, handles,
                           sink_pacs, source_pacs, ases);
                           sink_pacs, source_pacs, ases, gmap);
}

bool LeAudioClient::GetHandlesForStorage(const RawAddress& addr, std::vector<uint8_t>& out) {
@@ -6523,6 +6537,15 @@ bool LeAudioClient::GetAsesForStorage(const RawAddress& addr, std::vector<uint8_
  return instance->GetAsesForStorage(addr, out);
}

bool LeAudioClient::GetGmapForStorage(const RawAddress& addr, std::vector<uint8_t>& out) {
  if (!instance) {
    log::error("Not initialized yet");
    return false;
  }

  return instance->GetGmapForStorage(addr, out);
}

bool LeAudioClient::IsLeAudioClientRunning(void) { return instance != nullptr; }

bool LeAudioClient::IsLeAudioClientInStreaming(void) {
+9 −8
Original line number Diff line number Diff line
@@ -48,14 +48,12 @@ void LeAudioClient::Initialize(
void LeAudioClient::Cleanup(void) {}
LeAudioClient* LeAudioClient::Get(void) { return nullptr; }
void LeAudioClient::DebugDump(int fd) {}
void LeAudioClient::AddFromStorage(const RawAddress& addr, bool autoconnect,
                                   int sink_audio_location, int source_audio_location,
                                   int sink_supported_context_types,
                                   int source_supported_context_types,
                                   const std::vector<uint8_t>& handles,
                                   const std::vector<uint8_t>& sink_pacs,
                                   const std::vector<uint8_t>& source_pacs,
                                   const std::vector<uint8_t>& ases) {}
void LeAudioClient::AddFromStorage(
        const RawAddress& addr, bool autoconnect, int sink_audio_location,
        int source_audio_location, int sink_supported_context_types,
        int source_supported_context_types, const std::vector<uint8_t>& handles,
        const std::vector<uint8_t>& sink_pacs, const std::vector<uint8_t>& source_pacs,
        const std::vector<uint8_t>& ases, const std::vector<uint8_t>& gmap) {}
bool LeAudioClient::GetHandlesForStorage(const RawAddress& addr, std::vector<uint8_t>& out) {
  return false;
}
@@ -68,5 +66,8 @@ bool LeAudioClient::GetSourcePacsForStorage(const RawAddress& addr, std::vector<
bool LeAudioClient::GetAsesForStorage(const RawAddress& addr, std::vector<uint8_t>& out) {
  return false;
}
bool LeAudioClient::GetGmapForStorage(const RawAddress& addr, std::vector<uint8_t>& out) {
  return false;
}
bool LeAudioClient::IsLeAudioClientRunning() { return false; }
bool LeAudioClient::IsLeAudioClientInStreaming() { return false; }
Loading