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

Commit cee948c1 authored by Jakub Tyszkowski's avatar Jakub Tyszkowski Committed by Automerger Merge Worker
Browse files

Merge "LeAudio: Fix removing pending operations on disconnect" into main am: f059ee57

parents 05cdc087 f059ee57
Loading
Loading
Loading
Loading
+0 −2
Original line number Original line Diff line number Diff line
@@ -657,7 +657,6 @@ cc_test {
    srcs: [
    srcs: [
        ":TestCommonMockFunctions",
        ":TestCommonMockFunctions",
        ":TestMockStackBtmInterface",
        ":TestMockStackBtmInterface",
        ":TestStubOsi",
        "gatt/database.cc",
        "gatt/database.cc",
        "gatt/database_builder.cc",
        "gatt/database_builder.cc",
        "test/common/bta_gatt_api_mock.cc",
        "test/common/bta_gatt_api_mock.cc",
@@ -685,7 +684,6 @@ cc_test {
        "libbt_shim_ffi",
        "libbt_shim_ffi",
        "libchrome",
        "libchrome",
        "libgmock",
        "libgmock",
        "libosi",
    ],
    ],
    sanitize: {
    sanitize: {
        cfi: false,
        cfi: false,
+5 −0
Original line number Original line Diff line number Diff line
@@ -87,6 +87,11 @@ struct VolumeOperation {
    started_ = false;
    started_ = false;
  }
  }


  // Disallow copying due to owning operation_timeout_t which is freed in the
  // destructor - prevents double free.
  VolumeOperation(const VolumeOperation&) = delete;
  VolumeOperation& operator=(const VolumeOperation&) = delete;

  ~VolumeOperation() {
  ~VolumeOperation() {
    if (operation_timeout_ == nullptr) {
    if (operation_timeout_ == nullptr) {
      log::warn("operation_timeout_ should not be null, id {}, device cnt {}", operation_id_,
      log::warn("operation_timeout_ should not be null, id {}, device cnt {}", operation_id_,
+8 −3
Original line number Original line Diff line number Diff line
@@ -663,9 +663,14 @@ public:
    }
    }


    // Remove operations with no devices
    // Remove operations with no devices
    ongoing_operations_.erase(std::remove_if(ongoing_operations_.begin(), ongoing_operations_.end(),
    auto it = ongoing_operations_.begin();
                                             [](auto& op) { return op.devices_.empty(); }),
    while (it != ongoing_operations_.end()) {
                              ongoing_operations_.end());
      if (it->devices_.empty()) {
        it = ongoing_operations_.erase(it);
      } else {
        ++it;
      }
    }
  }
  }


  void RemoveDeviceFromOperationList(const RawAddress& addr, int operation_id) {
  void RemoveDeviceFromOperationList(const RawAddress& addr, int operation_id) {
+76 −10
Original line number Original line Diff line number Diff line
@@ -27,6 +27,7 @@
#include "gatt/database_builder.h"
#include "gatt/database_builder.h"
#include "hardware/bt_gatt_types.h"
#include "hardware/bt_gatt_types.h"
#include "mock_csis_client.h"
#include "mock_csis_client.h"
#include "osi/test/alarm_mock.h"
#include "stack/include/bt_uuid16.h"
#include "stack/include/bt_uuid16.h"
#include "test/common/mock_functions.h"
#include "test/common/mock_functions.h"
#include "types.h"
#include "types.h"
@@ -34,6 +35,12 @@
#include "types/raw_address.h"
#include "types/raw_address.h"
void btif_storage_add_volume_control(const RawAddress& addr, bool auto_conn) {}
void btif_storage_add_volume_control(const RawAddress& addr, bool auto_conn) {}


struct alarm_t {
  alarm_callback_t cb = nullptr;
  void* data = nullptr;
  bool on_main_loop = false;
};

namespace bluetooth {
namespace bluetooth {
namespace vc {
namespace vc {
namespace internal {
namespace internal {
@@ -276,6 +283,45 @@ protected:
                cb(conn_id, GATT_SUCCESS, handle, value.size(), value.data(), cb_data);
                cb(conn_id, GATT_SUCCESS, handle, value.size(), value.data(), cb_data);
              }
              }
            }));
            }));
    auto mock_alarm = AlarmMock::Get();
    ON_CALL(*mock_alarm, AlarmNew(_)).WillByDefault(Invoke([](const char* name) {
      return new alarm_t();
    }));
    ON_CALL(*mock_alarm, AlarmFree(_)).WillByDefault(Invoke([](alarm_t* alarm) {
      if (alarm) {
        free(alarm);
      }
    }));
    ON_CALL(*mock_alarm, AlarmCancel(_)).WillByDefault(Invoke([](alarm_t* alarm) {
      if (alarm) {
        alarm->cb = nullptr;
        alarm->data = nullptr;
        alarm->on_main_loop = false;
      }
    }));
    ON_CALL(*mock_alarm, AlarmIsScheduled(_)).WillByDefault(Invoke([](const alarm_t* alarm) {
      if (alarm) {
        return alarm->cb != nullptr;
      }
      return false;
    }));
    ON_CALL(*mock_alarm, AlarmSet(_, _, _, _))
            .WillByDefault(Invoke(
                    [](alarm_t* alarm, uint64_t interval_ms, alarm_callback_t cb, void* data) {
                      if (alarm) {
                        alarm->data = data;
                        alarm->cb = cb;
                      }
                    }));
    ON_CALL(*mock_alarm, AlarmSetOnMloop(_, _, _, _))
            .WillByDefault(Invoke(
                    [](alarm_t* alarm, uint64_t interval_ms, alarm_callback_t cb, void* data) {
                      if (alarm) {
                        alarm->on_main_loop = true;
                        alarm->data = data;
                        alarm->cb = cb;
                      }
                    }));
  }
  }


  void TearDown(void) override {
  void TearDown(void) override {
@@ -284,6 +330,7 @@ protected:
    gatt::SetMockBtaGattQueue(nullptr);
    gatt::SetMockBtaGattQueue(nullptr);
    gatt::SetMockBtaGattInterface(nullptr);
    gatt::SetMockBtaGattInterface(nullptr);
    bluetooth::manager::SetMockBtmInterface(nullptr);
    bluetooth::manager::SetMockBtmInterface(nullptr);
    AlarmMock::Reset();
  }
  }


  void TestAppRegister(void) {
  void TestAppRegister(void) {
@@ -1167,14 +1214,13 @@ TEST_F(VolumeControlValueSetTest, test_volume_operation_failed) {
                      cb(conn_id, status, handle, value.size(), value.data(), cb_data);
                      cb(conn_id, status, handle, value.size(), value.data(), cb_data);
                    }
                    }
                  }));
                  }));
  ASSERT_EQ(0, get_func_call_count("alarm_set_on_mloop"));
  ASSERT_EQ(0, get_func_call_count("alarm_cancel"));


  EXPECT_CALL(*AlarmMock::Get(), AlarmSetOnMloop(_, _, _, _)).Times(1);
  EXPECT_CALL(*AlarmMock::Get(), AlarmCancel(_)).Times(1);
  VolumeControl::Get()->SetVolume(test_address, 0x10);
  VolumeControl::Get()->SetVolume(test_address, 0x10);
  Mock::VerifyAndClearExpectations(&gatt_queue);


  ASSERT_EQ(1, get_func_call_count("alarm_set_on_mloop"));
  Mock::VerifyAndClearExpectations(&gatt_queue);
  ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
  Mock::VerifyAndClearExpectations(AlarmMock::Get());
}
}


TEST_F(VolumeControlValueSetTest, test_volume_operation_failed_due_to_device_disconnection) {
TEST_F(VolumeControlValueSetTest, test_volume_operation_failed_due_to_device_disconnection) {
@@ -1187,18 +1233,38 @@ TEST_F(VolumeControlValueSetTest, test_volume_operation_failed_due_to_device_dis
                    /* Do nothing */
                    /* Do nothing */
                  }));
                  }));


  ASSERT_EQ(0, get_func_call_count("alarm_set_on_mloop"));
  EXPECT_CALL(*AlarmMock::Get(), AlarmSetOnMloop(_, _, _, _)).Times(0);
  ASSERT_EQ(0, get_func_call_count("alarm_cancel"));

  alarm_callback_t active_alarm_cb = nullptr;
  EXPECT_CALL(*AlarmMock::Get(), AlarmSetOnMloop(_, _, _, _))
          .WillOnce(Invoke(
                  [&](alarm_t* alarm, uint64_t interval_ms, alarm_callback_t cb, void* data) {
                    if (alarm) {
                      alarm->on_main_loop = true;
                      alarm->cb = cb;
                      active_alarm_cb = cb;
                    }
                  }));
  ON_CALL(*AlarmMock::Get(), AlarmCancel(_)).WillByDefault(Invoke([&](alarm_t* alarm) {
    if (alarm) {
      alarm->cb = nullptr;
      alarm->on_main_loop = false;
      active_alarm_cb = nullptr;
    }
  }));


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

  Mock::VerifyAndClearExpectations(&gatt_queue);
  Mock::VerifyAndClearExpectations(&gatt_queue);
  Mock::VerifyAndClearExpectations(AlarmMock::Get());
  ASSERT_NE(active_alarm_cb, nullptr);


  EXPECT_CALL(*AlarmMock::Get(), AlarmCancel(_)).Times(1);
  EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address));
  EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address));
  GetDisconnectedEvent(test_address, conn_id);
  GetDisconnectedEvent(test_address, conn_id);
  Mock::VerifyAndClearExpectations(callbacks.get());


  ASSERT_EQ(1, get_func_call_count("alarm_set_on_mloop"));
  ASSERT_EQ(active_alarm_cb, nullptr);
  ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
  Mock::VerifyAndClearExpectations(callbacks.get());
}
}


TEST_F(VolumeControlValueSetTest, test_set_volume) {
TEST_F(VolumeControlValueSetTest, test_set_volume) {
+2 −16
Original line number Original line Diff line number Diff line
@@ -14,20 +14,6 @@ public:
               void(alarm_t* alarm, uint64_t interval_ms, alarm_callback_t cb, void* data));
               void(alarm_t* alarm, uint64_t interval_ms, alarm_callback_t cb, void* data));
  MOCK_METHOD1(AlarmIsScheduled, bool(const alarm_t*));
  MOCK_METHOD1(AlarmIsScheduled, bool(const alarm_t*));


  alarm_t* AlarmNewImpl(const char* name) {
    AlarmNew(name);
    // We must return something from alarm_new in tests, if we just return null,
    // unique_ptr will misbehave. Just reserve few bits they will be freed in
    // AlarmFreeImpl
    return (alarm_t*)new uint8_t[30];
  }

  void AlarmFreeImpl(alarm_t* alarm) {
    uint8_t* ptr = (uint8_t*)alarm;
    delete[] ptr;
    return AlarmFree(alarm);
  }

  static inline AlarmMock* Get() {
  static inline AlarmMock* Get() {
    if (!localAlarmMock) {
    if (!localAlarmMock) {
      localAlarmMock = std::make_unique<AlarmMock>();
      localAlarmMock = std::make_unique<AlarmMock>();
@@ -43,9 +29,9 @@ private:


std::unique_ptr<AlarmMock> AlarmMock::localAlarmMock;
std::unique_ptr<AlarmMock> AlarmMock::localAlarmMock;


alarm_t* alarm_new(const char* name) { return AlarmMock::Get()->AlarmNewImpl(name); }
alarm_t* alarm_new(const char* name) { return AlarmMock::Get()->AlarmNew(name); }


void alarm_free(alarm_t* alarm) { AlarmMock::Get()->AlarmFreeImpl(alarm); }
void alarm_free(alarm_t* alarm) { AlarmMock::Get()->AlarmFree(alarm); }


void alarm_set_on_mloop(alarm_t* alarm, uint64_t interval_ms, alarm_callback_t cb, void* data) {
void alarm_set_on_mloop(alarm_t* alarm, uint64_t interval_ms, alarm_callback_t cb, void* data) {
  AlarmMock::Get()->AlarmSetOnMloop(alarm, interval_ms, cb, data);
  AlarmMock::Get()->AlarmSetOnMloop(alarm, interval_ms, cb, data);
Loading