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

Commit 44b4bfa3 authored by Michal Belusiak (xWF)'s avatar Michal Belusiak (xWF) Committed by Gerrit Code Review
Browse files

Merge "VC: Allow to set the same volume during already pending operation" into main

parents 05ff0c2f 38240f1c
Loading
Loading
Loading
Loading
+25 −2
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_util.h>
#include <bluetooth/log.h>
#include <com_android_bluetooth_flags.h>
#include <hardware/bt_gatt_types.h>
#include <hardware/bt_vc.h>
#include <stdio.h>
@@ -934,6 +935,27 @@ public:
    }
  }

  bool isPendingVolumeControlOperation(const RawAddress& addr) {
    if (!com::android::bluetooth::flags::vcp_allow_set_same_volume_if_pending()) {
      return false;
    }

    if (std::find_if(ongoing_operations_.begin(), ongoing_operations_.end(),
                     [&addr](const VolumeOperation& op) {
                       auto it = find(op.devices_.begin(), op.devices_.end(), addr);
                       if (it != op.devices_.end()) {
                         bluetooth::log::debug(
                                 "There is a pending volume operation {} for device {}",
                                 op.operation_id_, addr);
                         return true;
                       }
                       return false;
                     }) != ongoing_operations_.end()) {
      return true;
    }
    return false;
  }

  void RemovePendingVolumeControlOperations(const std::vector<RawAddress>& devices, int group_id) {
    bluetooth::log::debug("");
    for (auto op = ongoing_operations_.begin(); op != ongoing_operations_.end();) {
@@ -1156,7 +1178,8 @@ public:
              volume_control_devices_.FindByAddress(std::get<RawAddress>(addr_or_group_id));
      if (dev != nullptr) {
        bluetooth::log::debug("Address: {}: isReady: {}", dev->address, dev->IsReady());
        if (dev->IsReady() && (dev->volume != volume)) {
        if (dev->IsReady() &&
            ((dev->volume != volume) || isPendingVolumeControlOperation(dev->address))) {
          std::vector<RawAddress> devices = {dev->address};
          RemovePendingVolumeControlOperations(devices, bluetooth::groups::kGroupUnknown);
          PrepareVolumeControlOperation(devices, bluetooth::groups::kGroupUnknown, false, opcode,
@@ -1189,7 +1212,7 @@ public:
          continue;
        }

        if (!dev->IsReady() || (dev->volume == volume)) {
        if (!dev->IsReady() || ((dev->volume == volume) && !isPendingVolumeControlOperation(*it))) {
          it = devices.erase(it);
          volumeNotChanged = volumeNotChanged ? volumeNotChanged : (dev->volume == volume);
          deviceNotReady = deviceNotReady ? deviceNotReady : !dev->IsReady();
+41 −0
Original line number Diff line number Diff line
@@ -1703,6 +1703,47 @@ TEST_F(VolumeControlValueSetTest, test_set_volume) {
  VolumeControl::Get()->SetVolume(test_address, 0x20);
}

TEST_F(VolumeControlValueSetTest, test_set_volume_to_previous_during_pending) {
  com::android::bluetooth::flags::provider_->vcp_allow_set_same_volume_if_pending(true);
  // In this test we simulate notification coming later and operations will be queued
  ON_CALL(gatt_queue, WriteCharacteristic(conn_id, 0x0024, _, GATT_WRITE, _, _))
          .WillByDefault([](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) {
            uint8_t write_rsp;

            switch (value[0]) {
              case 0x04:  // set abs. volume
                break;
              default:
                break;
            }
            cb(conn_id, GATT_SUCCESS, handle, 0, &write_rsp, cb_data);
          });

  const std::vector<uint8_t> vol_x10({0x04, /*change_cnt*/ 0, 0x10});
  std::vector<uint8_t> ntf_value_x10({0x10, 0, 1});
  const std::vector<uint8_t> vol_x11({0x04, /*change_cnt*/ 1, 0x11});
  std::vector<uint8_t> ntf_value_x11({0x11, 0, 2});
  const std::vector<uint8_t> vol_x10_2({0x04, /*change_cnt*/ 2, 0x10});
  std::vector<uint8_t> ntf_value_x10_2({0x10, 0, 3});

  EXPECT_CALL(gatt_queue, WriteCharacteristic(conn_id, 0x0024, vol_x10, GATT_WRITE, _, _)).Times(1);

  VolumeControl::Get()->SetVolume(test_address, 0x10);
  GetNotificationEvent(0x0021, ntf_value_x10);

  EXPECT_CALL(gatt_queue, WriteCharacteristic(conn_id, 0x0024, vol_x11, GATT_WRITE, _, _)).Times(1);
  EXPECT_CALL(gatt_queue, WriteCharacteristic(conn_id, 0x0024, vol_x10_2, GATT_WRITE, _, _))
          .Times(1);

  VolumeControl::Get()->SetVolume(test_address, 0x11);
  VolumeControl::Get()->SetVolume(test_address, 0x10);
  GetNotificationEvent(0x0021, ntf_value_x11);
  GetNotificationEvent(0x0021, ntf_value_x10_2);

  Mock::VerifyAndClearExpectations(&gatt_queue);
}

TEST_F(VolumeControlValueSetTest, test_set_volume_stress) {
  uint8_t n = 100;
  uint8_t change_cnt = 0;