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

Commit 1922df20 authored by Łukasz Rymanowski's avatar Łukasz Rymanowski
Browse files

leaudio: Add handling DATABASE_OUT_OF_SYNC

Bug: 262309077
Test: atest BluetoothInstrumentationTests
Tag: #feature
Change-Id: Ib324a3ec139074ee42b74cac1a084811ba41070f
parent 6237e4c7
Loading
Loading
Loading
Loading
+43 −8
Original line number Diff line number Diff line
@@ -1926,20 +1926,44 @@ class LeAudioClientImpl : public LeAudioClient {
    return iter == charac.descriptors.end() ? 0 : (*iter).handle;
  }

  void OnServiceChangeEvent(const RawAddress& address) {
    LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
  void ClearDeviceInformationAndStartSearch(LeAudioDevice* leAudioDevice) {
    if (!leAudioDevice) {
      DLOG(ERROR) << __func__
                  << ", skipping unknown leAudioDevice, address: "
                  << ADDRESS_TO_LOGGABLE_STR(address);
      LOG_WARN("leAudioDevice is null");
      return;
    }

    LOG_INFO("%s", ADDRESS_TO_LOGGABLE_CSTR(leAudioDevice->address_));

    if (leAudioDevice->known_service_handles_ == false) {
      LOG_DEBUG("Database already invalidated");
      return;
    }

    LOG(INFO) << __func__ << ": address=" << ADDRESS_TO_LOGGABLE_STR(address);
    leAudioDevice->known_service_handles_ = false;
    leAudioDevice->csis_member_ = false;
    BtaGattQueue::Clean(leAudioDevice->conn_id_);
    DeregisterNotifications(leAudioDevice);

    if (leAudioDevice->GetConnectionState() == DeviceConnectState::CONNECTED) {
      leAudioDevice->SetConnectionState(
          DeviceConnectState::CONNECTED_BY_USER_GETTING_READY);
    }

    btif_storage_remove_leaudio(leAudioDevice->address_);

    BTA_GATTC_ServiceSearchRequest(
        leAudioDevice->conn_id_,
        &le_audio::uuid::kPublishedAudioCapabilityServiceUuid);
  }

  void OnServiceChangeEvent(const RawAddress& address) {
    LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
    if (!leAudioDevice) {
      LOG_WARN("Skipping unknown leAudioDevice %s",
               ADDRESS_TO_LOGGABLE_CSTR(address));
      return;
    }
    ClearDeviceInformationAndStartSearch(leAudioDevice);
  }

  void OnMtuChanged(uint16_t conn_id, uint16_t mtu) {
@@ -2343,6 +2367,13 @@ class LeAudioClientImpl : public LeAudioClient {
      return;
    }

    if (status == GATT_DATABASE_OUT_OF_SYNC) {
      LOG_INFO("Database out of sync for %s, conn_id: 0x%04x",
               ADDRESS_TO_LOGGABLE_CSTR(leAudioDevice->address_), conn_id);
      ClearDeviceInformationAndStartSearch(leAudioDevice);
      return;
    }

    if (status == GATT_SUCCESS) {
      LOG(INFO) << __func__
                << ", successfully registered on ccc: " << loghex(hdl);
@@ -3939,14 +3970,18 @@ class LeAudioClientImpl : public LeAudioClient {
                                  void* data) {
    if (!instance) return;

    LeAudioDevice* leAudioDevice =
        instance->leAudioDevices_.FindByConnId(conn_id);

    if (status == GATT_SUCCESS) {
      instance->LeAudioCharValueHandle(conn_id, hdl, len, value);
    } else if (status == GATT_DATABASE_OUT_OF_SYNC) {
      instance->ClearDeviceInformationAndStartSearch(leAudioDevice);
      return;
    }

    /* We use data to keep notify connected flag. */
    if (data && !!PTR_TO_INT(data)) {
      LeAudioDevice* leAudioDevice =
          instance->leAudioDevices_.FindByConnId(conn_id);
      leAudioDevice->notify_connected_after_read_ = false;

      /* Update PACs and ASEs when all is read.*/
+58 −0
Original line number Diff line number Diff line
@@ -1463,6 +1463,7 @@ class UnicastTestNoInit : public Test {
                              base::Unretained(LeAudioClient::Get()), address));

    SyncOnMainLoop();
    Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
  }

  void DisconnectLeAudio(const RawAddress& address, uint16_t conn_id) {
@@ -4085,4 +4086,61 @@ TEST_F(UnicastTest, NotifyAboutGroupTunrnedIdleDisabled) {
  LeAudioClient::Get()->SetInCall(false);
}

TEST_F(UnicastTest, HandleDatabaseOutOfSync) {
  const RawAddress test_address0 = GetTestAddress(0);
  int group_id = bluetooth::groups::kGroupUnknown;

  SetSampleDatabaseEarbudsValid(
      1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
      codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
      default_channel_cnt, 0x0004, false /*add_csis*/, true /*add_cas*/,
      true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
      0 /*rank*/);
  EXPECT_CALL(mock_audio_hal_client_callbacks_,
              OnConnectionState(ConnectionState::CONNECTED, test_address0))
      .Times(1);
  EXPECT_CALL(mock_audio_hal_client_callbacks_,
              OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
      .WillOnce(DoAll(SaveArg<1>(&group_id)));

  ConnectLeAudio(test_address0);
  ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);

  SyncOnMainLoop();
  Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);

  EXPECT_CALL(mock_audio_hal_client_callbacks_,
              OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
      .Times(1);
  InjectDisconnectedEvent(1, GATT_CONN_TERMINATE_PEER_USER);
  SyncOnMainLoop();
  Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);

  // default action for WriteDescriptor function call
  ON_CALL(mock_gatt_queue_, WriteDescriptor(_, _, _, _, _, _))
      .WillByDefault(Invoke([](uint16_t conn_id, uint16_t handle,
                               std::vector<uint8_t> value,
                               tGATT_WRITE_TYPE write_type, GATT_WRITE_OP_CB cb,
                               void* cb_data) -> void {
        if (cb)
          do_in_main_thread(
              FROM_HERE,
              base::BindOnce(
                  [](GATT_WRITE_OP_CB cb, uint16_t conn_id, uint16_t handle,
                     uint16_t len, uint8_t* value, void* cb_data) {
                    cb(conn_id, GATT_DATABASE_OUT_OF_SYNC, handle, len, value,
                       cb_data);
                  },
                  cb, conn_id, handle, value.size(), value.data(), cb_data));
      }));

  ON_CALL(mock_gatt_interface_, ServiceSearchRequest(_, _))
      .WillByDefault(Return());
  EXPECT_CALL(mock_gatt_interface_, ServiceSearchRequest(_, _));

  InjectConnectedEvent(test_address0, 1);
  SyncOnMainLoop();
  Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
}

}  // namespace le_audio