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

Commit 874777f6 authored by Łukasz Rymanowski's avatar Łukasz Rymanowski
Browse files

leaudio: Add handling DATABASE_OUT_OF_SYNC

Bug: 262309077
Test: atest BluetoothInstrumentationTests
Tag: #feature
Merged-In: Ib324a3ec139074ee42b74cac1a084811ba41070f
Change-Id: Ib324a3ec139074ee42b74cac1a084811ba41070f
(cherry picked from commit 1922df20)
parent ab266d01
Loading
Loading
Loading
Loading
+42 −7
Original line number Original line Diff line number Diff line
@@ -1916,19 +1916,43 @@ class LeAudioClientImpl : public LeAudioClient {
    return iter == charac.descriptors.end() ? 0 : (*iter).handle;
    return iter == charac.descriptors.end() ? 0 : (*iter).handle;
  }
  }


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

    LOG_INFO("%s", leAudioDevice->address_.ToString().c_str());

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


    LOG(INFO) << __func__ << ": address=" << address;
    leAudioDevice->known_service_handles_ = false;
    leAudioDevice->known_service_handles_ = false;
    leAudioDevice->csis_member_ = false;
    leAudioDevice->csis_member_ = false;
    BtaGattQueue::Clean(leAudioDevice->conn_id_);
    BtaGattQueue::Clean(leAudioDevice->conn_id_);
    DeregisterNotifications(leAudioDevice);
    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.ToString().c_str());
      return;
    }
    ClearDeviceInformationAndStartSearch(leAudioDevice);
  }
  }


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


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

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


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

    if (status == GATT_SUCCESS) {
    if (status == GATT_SUCCESS) {
      instance->LeAudioCharValueHandle(conn_id, hdl, len, value);
      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. */
    /* We use data to keep notify connected flag. */
    if (data && !!PTR_TO_INT(data)) {
    if (data && !!PTR_TO_INT(data)) {
      LeAudioDevice* leAudioDevice =
          instance->leAudioDevices_.FindByConnId(conn_id);
      leAudioDevice->notify_connected_after_read_ = false;
      leAudioDevice->notify_connected_after_read_ = false;


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


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


  void DisconnectLeAudio(const RawAddress& address, uint16_t conn_id) {
  void DisconnectLeAudio(const RawAddress& address, uint16_t conn_id) {
@@ -4085,4 +4086,61 @@ TEST_F(UnicastTest, NotifyAboutGroupTunrnedIdleDisabled) {
  LeAudioClient::Get()->SetInCall(false);
  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
}  // namespace le_audio