/*
 * Copyright 2021 HIMSA II K/S - www.himsa.com.
 * Represented by EHIMA - www.ehima.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include 
#include 
#include 
#include "bind_helpers.h"
#include "bta_gatt_api_mock.h"
#include "bta_gatt_queue_mock.h"
#include "bta_vc_api.h"
#include "btm_api_mock.h"
#include "gatt/database_builder.h"
#include "hardware/bt_gatt_types.h"
#include "mock_csis_client.h"
#include "types.h"
#include "types/bluetooth/uuid.h"
#include "types/raw_address.h"
std::map mock_function_count_map;
void btif_storage_add_volume_control(const RawAddress& addr, bool auto_conn) {}
namespace bluetooth {
namespace vc {
namespace internal {
namespace {
using base::Bind;
using base::Unretained;
using bluetooth::vc::ConnectionState;
using bluetooth::vc::VolumeControlCallbacks;
using testing::_;
using testing::DoAll;
using testing::DoDefault;
using testing::Invoke;
using testing::Mock;
using testing::NotNull;
using testing::Return;
using testing::SaveArg;
using testing::SetArgPointee;
using testing::WithArg;
RawAddress GetTestAddress(int index) {
  CHECK_LT(index, UINT8_MAX);
  RawAddress result = {
      {0xC0, 0xDE, 0xC0, 0xDE, 0x00, static_cast(index)}};
  return result;
}
class MockVolumeControlCallbacks : public VolumeControlCallbacks {
 public:
  MockVolumeControlCallbacks() = default;
  MockVolumeControlCallbacks(const MockVolumeControlCallbacks&) = delete;
  MockVolumeControlCallbacks& operator=(const MockVolumeControlCallbacks&) =
      delete;
  ~MockVolumeControlCallbacks() override = default;
  MOCK_METHOD((void), OnConnectionState,
              (ConnectionState state, const RawAddress& address), (override));
  MOCK_METHOD((void), OnDeviceAvailable,
              (const RawAddress& address, uint8_t num_offset), (override));
  MOCK_METHOD((void), OnVolumeStateChanged,
              (const RawAddress& address, uint8_t volume, bool mute,
               bool isAutonomous),
              (override));
  MOCK_METHOD((void), OnGroupVolumeStateChanged,
              (int group_id, uint8_t volume, bool mute, bool isAutonomous),
              (override));
  MOCK_METHOD((void), OnExtAudioOutVolumeOffsetChanged,
              (const RawAddress& address, uint8_t ext_output_id,
               int16_t offset),
              (override));
  MOCK_METHOD((void), OnExtAudioOutLocationChanged,
              (const RawAddress& address, uint8_t ext_output_id,
               uint32_t location),
              (override));
  MOCK_METHOD((void), OnExtAudioOutDescriptionChanged,
              (const RawAddress& address, uint8_t ext_output_id,
               std::string descr),
              (override));
};
class VolumeControlTest : public ::testing::Test {
 private:
  void set_sample_database(uint16_t conn_id, bool vcs, bool vcs_broken,
                           bool aics, bool aics_broken, bool vocs,
                           bool vocs_broken) {
    gatt::DatabaseBuilder builder;
    builder.AddService(0x0001, 0x0003, Uuid::From16Bit(0x1800), true);
    builder.AddCharacteristic(0x0002, 0x0003, Uuid::From16Bit(0x2a00),
                              GATT_CHAR_PROP_BIT_READ);
    /* 0x0004-0x000f RFU */
    if (vcs) {
      /* VCS */
      builder.AddService(0x0010, 0x0026, kVolumeControlUuid, true);
      if (aics) {
        /* TODO Place holder */
      }
      if (vocs) {
        builder.AddIncludedService(0x0013, kVolumeOffsetUuid, 0x0070, 0x0079);
        builder.AddIncludedService(0x0014, kVolumeOffsetUuid, 0x0080, 0x008b);
      }
      /* 0x0015-0x001f RFU */
      builder.AddCharacteristic(
          0x0020, 0x0021, kVolumeControlStateUuid,
          GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
      builder.AddDescriptor(0x0022,
                            Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
      if (!vcs_broken) {
        builder.AddCharacteristic(0x0023, 0x0024, kVolumeControlPointUuid,
                                  GATT_CHAR_PROP_BIT_WRITE);
      }
      builder.AddCharacteristic(0x0025, 0x0026, kVolumeFlagsUuid,
                                GATT_CHAR_PROP_BIT_READ);
      /* 0x0027-0x002f RFU */
      if (aics) {
        /* TODO Place holder for AICS */
      }
      if (vocs) {
        /* VOCS 1st instance */
        builder.AddService(0x0070, 0x0079, kVolumeOffsetUuid, false);
        builder.AddCharacteristic(
            0x0071, 0x0072, kVolumeOffsetStateUuid,
            GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
        builder.AddDescriptor(0x0073,
                              Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
        builder.AddCharacteristic(0x0074, 0x0075, kVolumeOffsetLocationUuid,
                                  GATT_CHAR_PROP_BIT_READ);
        builder.AddCharacteristic(0x0076, 0x0077, kVolumeOffsetControlPointUuid,
                                  GATT_CHAR_PROP_BIT_WRITE);
        builder.AddCharacteristic(0x0078, 0x0079,
                                  kVolumeOffsetOutputDescriptionUuid,
                                  GATT_CHAR_PROP_BIT_READ);
        /* 0x007a-0x007f RFU */
        /* VOCS 2nd instance */
        builder.AddService(0x0080, 0x008b, kVolumeOffsetUuid, false);
        builder.AddCharacteristic(
            0x0081, 0x0082, kVolumeOffsetStateUuid,
            GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
        builder.AddDescriptor(0x0083,
                              Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
        if (!vocs_broken) {
          builder.AddCharacteristic(0x0084, 0x0085, kVolumeOffsetLocationUuid,
                                    GATT_CHAR_PROP_BIT_READ |
                                        GATT_CHAR_PROP_BIT_WRITE_NR |
                                        GATT_CHAR_PROP_BIT_NOTIFY);
          builder.AddDescriptor(0x0086,
                                Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
        }
        builder.AddCharacteristic(0x0087, 0x0088, kVolumeOffsetControlPointUuid,
                                  GATT_CHAR_PROP_BIT_WRITE);
        builder.AddCharacteristic(
            0x0089, 0x008a, kVolumeOffsetOutputDescriptionUuid,
            GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_WRITE_NR |
                GATT_CHAR_PROP_BIT_NOTIFY);
        builder.AddDescriptor(0x008b,
                              Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
      }
    }
    /* 0x008c-0x008f RFU */
    /* GATTS */
    builder.AddService(0x0090, 0x0093,
                       Uuid::From16Bit(UUID_SERVCLASS_GATT_SERVER), true);
    builder.AddCharacteristic(0x0091, 0x0092,
                              Uuid::From16Bit(GATT_UUID_GATT_SRV_CHGD),
                              GATT_CHAR_PROP_BIT_NOTIFY);
    builder.AddDescriptor(0x0093,
                          Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
    services_map[conn_id] = builder.Build().Services();
    ON_CALL(gatt_queue, ReadCharacteristic(conn_id, _, _, _))
        .WillByDefault(Invoke([&](uint16_t conn_id, uint16_t handle,
                                  GATT_READ_OP_CB cb, void* cb_data) -> void {
          std::vector value;
          switch (handle) {
            case 0x0003:
              /* device name */
              value.resize(20);
              break;
            case 0x0021:
              /* volume state */
              value.resize(3);
              break;
            case 0x0026:
              /* volume flags */
              value.resize(1);
              break;
            case 0x0072:  // 1st VOCS instance
            case 0x0082:  // 2nd VOCS instance
              /* offset state */
              value.resize(3);
              break;
            case 0x0075:  // 1st VOCS instance
            case 0x0085:  // 2nd VOCS instance
              /* offset location */
              value.resize(4);
              break;
            case 0x0079:  // 1st VOCS instance
            case 0x008a:  // 2nd VOCS instance
              /* offset output description */
              value.resize(10);
              break;
            default:
              ASSERT_TRUE(false);
              return;
          }
          if (do_not_respond_to_reads) return;
          cb(conn_id, GATT_SUCCESS, handle, value.size(), value.data(),
             cb_data);
        }));
  }
 protected:
  bool do_not_respond_to_reads = false;
  void SetUp(void) override {
    bluetooth::manager::SetMockBtmInterface(&btm_interface);
    MockCsisClient::SetMockInstanceForTesting(&mock_csis_client_module_);
    gatt::SetMockBtaGattInterface(&gatt_interface);
    gatt::SetMockBtaGattQueue(&gatt_queue);
    callbacks.reset(new MockVolumeControlCallbacks());
    // default action for GetCharacteristic function call
    ON_CALL(gatt_interface, GetCharacteristic(_, _))
        .WillByDefault(
            Invoke([&](uint16_t conn_id,
                       uint16_t handle) -> const gatt::Characteristic* {
              std::list& services = services_map[conn_id];
              for (auto const& service : services) {
                for (auto const& characteristic : service.characteristics) {
                  if (characteristic.value_handle == handle) {
                    return &characteristic;
                  }
                }
              }
              return nullptr;
            }));
    // default action for GetOwningService function call
    ON_CALL(gatt_interface, GetOwningService(_, _))
        .WillByDefault(Invoke(
            [&](uint16_t conn_id, uint16_t handle) -> const gatt::Service* {
              std::list& services = services_map[conn_id];
              for (auto const& service : services) {
                if (service.handle <= handle && service.end_handle >= handle) {
                  return &service;
                }
              }
              return nullptr;
            }));
    // default action for GetServices function call
    ON_CALL(gatt_interface, GetServices(_))
        .WillByDefault(WithArg<0>(
            Invoke([&](uint16_t conn_id) -> std::list* {
              return &services_map[conn_id];
            })));
    // default action for RegisterForNotifications function call
    ON_CALL(gatt_interface, RegisterForNotifications(gatt_if, _, _))
        .WillByDefault(Return(GATT_SUCCESS));
    // default action for DeregisterForNotifications function call
    ON_CALL(gatt_interface, DeregisterForNotifications(gatt_if, _, _))
        .WillByDefault(Return(GATT_SUCCESS));
    // default action for WriteDescriptor function call
    ON_CALL(gatt_queue, WriteDescriptor(_, _, _, _, _, _))
        .WillByDefault(
            Invoke([](uint16_t conn_id, uint16_t handle,
                      std::vector value, tGATT_WRITE_TYPE write_type,
                      GATT_WRITE_OP_CB cb, void* cb_data) -> void {
              if (cb)
                cb(conn_id, GATT_SUCCESS, handle, value.size(), value.data(),
                   cb_data);
            }));
  }
  void TearDown(void) override {
    services_map.clear();
    callbacks.reset();
    gatt::SetMockBtaGattQueue(nullptr);
    gatt::SetMockBtaGattInterface(nullptr);
    bluetooth::manager::SetMockBtmInterface(nullptr);
  }
  void TestAppRegister(void) {
    BtaAppRegisterCallback app_register_callback;
    EXPECT_CALL(gatt_interface, AppRegister(_, _, _))
        .WillOnce(DoAll(SaveArg<0>(&gatt_callback),
                        SaveArg<1>(&app_register_callback)));
    VolumeControl::Initialize(callbacks.get());
    ASSERT_TRUE(gatt_callback);
    ASSERT_TRUE(app_register_callback);
    app_register_callback.Run(gatt_if, GATT_SUCCESS);
    ASSERT_TRUE(VolumeControl::IsVolumeControlRunning());
  }
  void TestAppUnregister(void) {
    EXPECT_CALL(gatt_interface, AppDeregister(gatt_if));
    VolumeControl::CleanUp();
    ASSERT_FALSE(VolumeControl::IsVolumeControlRunning());
    gatt_callback = nullptr;
  }
  void TestConnect(const RawAddress& address) {
    // by default indicate link as encrypted
    ON_CALL(btm_interface, BTM_IsEncrypted(address, _))
        .WillByDefault(DoAll(Return(true)));
    EXPECT_CALL(gatt_interface,
                Open(gatt_if, address, BTM_BLE_DIRECT_CONNECTION, _));
    VolumeControl::Get()->Connect(address);
    Mock::VerifyAndClearExpectations(&gatt_interface);
  }
  void TestDisconnect(const RawAddress& address, uint16_t conn_id) {
    if (conn_id) {
      EXPECT_CALL(gatt_interface, Close(conn_id));
    } else {
      EXPECT_CALL(gatt_interface, CancelOpen(gatt_if, address, _));
    }
    VolumeControl::Get()->Disconnect(address);
    Mock::VerifyAndClearExpectations(&gatt_interface);
  }
  void TestAddFromStorage(const RawAddress& address, bool auto_connect) {
    // by default indicate link as encrypted
    ON_CALL(btm_interface, BTM_IsEncrypted(address, _))
        .WillByDefault(DoAll(Return(true)));
    if (auto_connect) {
      EXPECT_CALL(gatt_interface,
                  Open(gatt_if, address, BTM_BLE_BKG_CONNECT_ALLOW_LIST, _));
    } else {
      EXPECT_CALL(gatt_interface, Open(gatt_if, address, _, _)).Times(0);
    }
    VolumeControl::Get()->AddFromStorage(address, auto_connect);
  }
  void TestSubscribeNotifications(const RawAddress& address, uint16_t conn_id,
                                  std::map& handle_pairs) {
    SetSampleDatabase(conn_id);
    TestAppRegister();
    TestConnect(address);
    GetConnectedEvent(address, conn_id);
    EXPECT_CALL(gatt_queue, WriteDescriptor(_, _, _, _, _, _))
        .WillRepeatedly(DoDefault());
    EXPECT_CALL(gatt_interface, RegisterForNotifications(_, _, _))
        .WillRepeatedly(DoDefault());
    std::vector notify_value({0x01, 0x00});
    for (auto const& handles : handle_pairs) {
      EXPECT_CALL(gatt_queue, WriteDescriptor(conn_id, handles.second,
                                              notify_value, GATT_WRITE, _, _))
          .WillOnce(DoDefault());
      EXPECT_CALL(gatt_interface,
                  RegisterForNotifications(gatt_if, address, handles.first))
          .WillOnce(DoDefault());
    }
    GetSearchCompleteEvent(conn_id);
    TestAppUnregister();
  }
  void TestReadCharacteristic(const RawAddress& address, uint16_t conn_id,
                              std::vector handles) {
    SetSampleDatabase(conn_id);
    TestAppRegister();
    TestConnect(address);
    GetConnectedEvent(address, conn_id);
    EXPECT_CALL(gatt_queue, ReadCharacteristic(conn_id, _, _, _))
        .WillRepeatedly(DoDefault());
    for (auto const& handle : handles) {
      EXPECT_CALL(gatt_queue, ReadCharacteristic(conn_id, handle, _, _))
          .WillOnce(DoDefault());
    }
    GetSearchCompleteEvent(conn_id);
    TestAppUnregister();
  }
  void GetConnectedEvent(const RawAddress& address, uint16_t conn_id) {
    tBTA_GATTC_OPEN event_data = {
        .status = GATT_SUCCESS,
        .conn_id = conn_id,
        .client_if = gatt_if,
        .remote_bda = address,
        .transport = GATT_TRANSPORT_LE,
        .mtu = 240,
    };
    gatt_callback(BTA_GATTC_OPEN_EVT, (tBTA_GATTC*)&event_data);
  }
  void GetDisconnectedEvent(const RawAddress& address, uint16_t conn_id) {
    tBTA_GATTC_CLOSE event_data = {
        .status = GATT_SUCCESS,
        .conn_id = conn_id,
        .client_if = gatt_if,
        .remote_bda = address,
        .reason = GATT_CONN_TERMINATE_PEER_USER,
    };
    gatt_callback(BTA_GATTC_CLOSE_EVT, (tBTA_GATTC*)&event_data);
  }
  void GetSearchCompleteEvent(uint16_t conn_id) {
    tBTA_GATTC_SEARCH_CMPL event_data = {
        .status = GATT_SUCCESS,
        .conn_id = conn_id,
    };
    gatt_callback(BTA_GATTC_SEARCH_CMPL_EVT, (tBTA_GATTC*)&event_data);
  }
  void GetEncryptionCompleteEvt(const RawAddress& bda) {
    tBTA_GATTC cb_data{};
    cb_data.enc_cmpl.client_if = gatt_if;
    cb_data.enc_cmpl.remote_bda = bda;
    gatt_callback(BTA_GATTC_ENC_CMPL_CB_EVT, &cb_data);
  }
  void SetEncryptionResult(const RawAddress& address, bool success) {
    ON_CALL(btm_interface, BTM_IsEncrypted(address, _))
        .WillByDefault(DoAll(Return(false)));
    ON_CALL(btm_interface, SetEncryption(address, _, _, _, BTM_BLE_SEC_ENCRYPT))
        .WillByDefault(Invoke(
            [&success, this](const RawAddress& bd_addr, tBT_TRANSPORT transport,
                             tBTM_SEC_CALLBACK* p_callback, void* p_ref_data,
                             tBTM_BLE_SEC_ACT sec_act) -> tBTM_STATUS {
              if (p_callback) {
                p_callback(&bd_addr, transport, p_ref_data,
                           success ? BTM_SUCCESS : BTM_FAILED_ON_SECURITY);
              }
              GetEncryptionCompleteEvt(bd_addr);
              return BTM_SUCCESS;
            }));
    EXPECT_CALL(btm_interface,
                SetEncryption(address, _, _, _, BTM_BLE_SEC_ENCRYPT))
        .Times(1);
  }
  void SetSampleDatabaseVCS(uint16_t conn_id) {
    set_sample_database(conn_id, true, false, false, false, false, false);
  }
  void SetSampleDatabaseNoVCS(uint16_t conn_id) {
    set_sample_database(conn_id, false, false, true, false, true, false);
  }
  void SetSampleDatabaseVCSBroken(uint16_t conn_id) {
    set_sample_database(conn_id, true, true, true, false, true, false);
  }
  void SetSampleDatabaseVOCS(uint16_t conn_id) {
    set_sample_database(conn_id, true, false, false, false, true, false);
  }
  void SetSampleDatabaseVOCSBroken(uint16_t conn_id) {
    set_sample_database(conn_id, true, false, true, false, true, true);
  }
  void SetSampleDatabase(uint16_t conn_id) {
    set_sample_database(conn_id, true, false, true, false, true, false);
  }
  std::unique_ptr callbacks;
  bluetooth::manager::MockBtmInterface btm_interface;
  MockCsisClient mock_csis_client_module_;
  gatt::MockBtaGattInterface gatt_interface;
  gatt::MockBtaGattQueue gatt_queue;
  tBTA_GATTC_CBACK* gatt_callback;
  const uint8_t gatt_if = 0xff;
  std::map> services_map;
};
TEST_F(VolumeControlTest, test_get_uninitialized) {
  ASSERT_DEATH(VolumeControl::Get(), "");
}
TEST_F(VolumeControlTest, test_initialize) {
  VolumeControl::Initialize(callbacks.get());
  ASSERT_TRUE(VolumeControl::IsVolumeControlRunning());
  VolumeControl::CleanUp();
}
TEST_F(VolumeControlTest, test_initialize_twice) {
  VolumeControl::Initialize(callbacks.get());
  VolumeControl* volume_control_p = VolumeControl::Get();
  VolumeControl::Initialize(callbacks.get());
  ASSERT_EQ(volume_control_p, VolumeControl::Get());
  VolumeControl::CleanUp();
}
TEST_F(VolumeControlTest, test_cleanup_initialized) {
  VolumeControl::Initialize(callbacks.get());
  VolumeControl::CleanUp();
  ASSERT_FALSE(VolumeControl::IsVolumeControlRunning());
}
TEST_F(VolumeControlTest, test_cleanup_uninitialized) {
  VolumeControl::CleanUp();
  ASSERT_FALSE(VolumeControl::IsVolumeControlRunning());
}
TEST_F(VolumeControlTest, test_app_registration) {
  TestAppRegister();
  TestAppUnregister();
}
TEST_F(VolumeControlTest, test_connect) {
  TestAppRegister();
  TestConnect(GetTestAddress(0));
  TestAppUnregister();
}
TEST_F(VolumeControlTest, test_reconnect_after_interrupted_discovery) {
  const RawAddress test_address = GetTestAddress(0);
  // Initial connection - no callback calls yet as we want to disconnect in the
  // middle
  SetSampleDatabaseVOCS(1);
  TestAppRegister();
  TestConnect(test_address);
  EXPECT_CALL(*callbacks,
              OnConnectionState(ConnectionState::CONNECTED, test_address))
      .Times(0);
  EXPECT_CALL(*callbacks, OnDeviceAvailable(test_address, 2)).Times(0);
  GetConnectedEvent(test_address, 1);
  Mock::VerifyAndClearExpectations(callbacks.get());
  // Remote disconnects in the middle of the service discovery
  EXPECT_CALL(*callbacks,
              OnConnectionState(ConnectionState::DISCONNECTED, test_address));
  GetDisconnectedEvent(test_address, 1);
  Mock::VerifyAndClearExpectations(callbacks.get());
  // This time let the service discovery pass
  ON_CALL(gatt_interface, ServiceSearchRequest(_, _))
      .WillByDefault(Invoke(
          [&](uint16_t conn_id, const bluetooth::Uuid* p_srvc_uuid) -> void {
            if (*p_srvc_uuid == kVolumeControlUuid)
              GetSearchCompleteEvent(conn_id);
          }));
  // Remote is being connected by another GATT client
  EXPECT_CALL(*callbacks,
              OnConnectionState(ConnectionState::CONNECTED, test_address));
  EXPECT_CALL(*callbacks, OnDeviceAvailable(test_address, 2));
  GetConnectedEvent(test_address, 1);
  Mock::VerifyAndClearExpectations(callbacks.get());
  // Request connect when the remote was already connected by another service
  EXPECT_CALL(*callbacks, OnDeviceAvailable(test_address, 2)).Times(0);
  EXPECT_CALL(*callbacks,
              OnConnectionState(ConnectionState::CONNECTED, test_address));
  VolumeControl::Get()->Connect(test_address);
  // The GetConnectedEvent(test_address, 1); should not be triggered here, since
  // GATT implementation will not send this event for the already connected
  // device
  Mock::VerifyAndClearExpectations(callbacks.get());
  TestAppUnregister();
}
TEST_F(VolumeControlTest, test_add_from_storage) {
  TestAppRegister();
  TestAddFromStorage(GetTestAddress(0), true);
  TestAddFromStorage(GetTestAddress(1), false);
  TestAppUnregister();
}
TEST_F(VolumeControlTest, test_disconnect_non_connected) {
  const RawAddress test_address = GetTestAddress(0);
  TestAppRegister();
  TestConnect(test_address);
  EXPECT_CALL(*callbacks,
              OnConnectionState(ConnectionState::DISCONNECTED, test_address));
  TestDisconnect(test_address, 0);
  TestAppUnregister();
}
TEST_F(VolumeControlTest, test_disconnect_connected) {
  const RawAddress test_address = GetTestAddress(0);
  TestAppRegister();
  TestConnect(test_address);
  GetConnectedEvent(test_address, 1);
  EXPECT_CALL(*callbacks,
              OnConnectionState(ConnectionState::DISCONNECTED, test_address));
  TestDisconnect(test_address, 1);
  TestAppUnregister();
}
TEST_F(VolumeControlTest, test_disconnected) {
  const RawAddress test_address = GetTestAddress(0);
  TestAppRegister();
  TestConnect(test_address);
  GetConnectedEvent(test_address, 1);
  EXPECT_CALL(*callbacks,
              OnConnectionState(ConnectionState::DISCONNECTED, test_address));
  GetDisconnectedEvent(test_address, 1);
  TestAppUnregister();
}
TEST_F(VolumeControlTest, test_disconnected_while_autoconnect) {
  const RawAddress test_address = GetTestAddress(0);
  TestAppRegister();
  TestAddFromStorage(test_address, true);
  GetConnectedEvent(test_address, 1);
  // autoconnect - don't indicate disconnection
  EXPECT_CALL(*callbacks,
              OnConnectionState(ConnectionState::DISCONNECTED, test_address))
      .Times(0);
  GetDisconnectedEvent(test_address, 1);
  TestAppUnregister();
}
TEST_F(VolumeControlTest, test_reconnect_after_encryption_failed) {
  const RawAddress test_address = GetTestAddress(0);
  TestAppRegister();
  TestAddFromStorage(test_address, true);
  SetEncryptionResult(test_address, false);
  // autoconnect - don't indicate disconnection
  EXPECT_CALL(*callbacks,
              OnConnectionState(ConnectionState::DISCONNECTED, test_address))
      .Times(0);
  GetConnectedEvent(test_address, 1);
  Mock::VerifyAndClearExpectations(&btm_interface);
  SetEncryptionResult(test_address, true);
  GetConnectedEvent(test_address, 1);
  TestAppUnregister();
}
TEST_F(VolumeControlTest, test_discovery_vcs_found) {
  const RawAddress test_address = GetTestAddress(0);
  SetSampleDatabaseVCS(1);
  TestAppRegister();
  TestConnect(test_address);
  EXPECT_CALL(*callbacks, OnDeviceAvailable(test_address, _));
  EXPECT_CALL(*callbacks,
              OnConnectionState(ConnectionState::CONNECTED, test_address));
  GetConnectedEvent(test_address, 1);
  GetSearchCompleteEvent(1);
  Mock::VerifyAndClearExpectations(callbacks.get());
  TestAppUnregister();
}
TEST_F(VolumeControlTest, test_discovery_vcs_not_found) {
  const RawAddress test_address = GetTestAddress(0);
  SetSampleDatabaseNoVCS(1);
  TestAppRegister();
  TestConnect(test_address);
  EXPECT_CALL(*callbacks,
              OnConnectionState(ConnectionState::DISCONNECTED, test_address));
  GetConnectedEvent(test_address, 1);
  GetSearchCompleteEvent(1);
  Mock::VerifyAndClearExpectations(callbacks.get());
  TestAppUnregister();
}
TEST_F(VolumeControlTest, test_discovery_vcs_broken) {
  const RawAddress test_address = GetTestAddress(0);
  SetSampleDatabaseVCSBroken(1);
  TestAppRegister();
  TestConnect(test_address);
  EXPECT_CALL(*callbacks,
              OnConnectionState(ConnectionState::DISCONNECTED, test_address));
  GetConnectedEvent(test_address, 1);
  GetSearchCompleteEvent(1);
  Mock::VerifyAndClearExpectations(callbacks.get());
  TestAppUnregister();
}
TEST_F(VolumeControlTest, test_subscribe_vcs_volume_state) {
  std::map handles({{0x0021, 0x0022}});
  TestSubscribeNotifications(GetTestAddress(0), 1, handles);
}
TEST_F(VolumeControlTest, test_subscribe_vocs_offset_state) {
  std::map handles({{0x0072, 0x0073}, {0x0082, 0x0083}});
  TestSubscribeNotifications(GetTestAddress(0), 1, handles);
}
TEST_F(VolumeControlTest, test_subscribe_vocs_offset_location) {
  std::map handles({{0x0085, 0x0086}});
  TestSubscribeNotifications(GetTestAddress(0), 1, handles);
}
TEST_F(VolumeControlTest, test_subscribe_vocs_output_description) {
  std::map handles({{0x008a, 0x008b}});
  TestSubscribeNotifications(GetTestAddress(0), 1, handles);
}
TEST_F(VolumeControlTest, test_read_vcs_volume_state) {
  const RawAddress test_address = GetTestAddress(0);
  EXPECT_CALL(*callbacks, OnVolumeStateChanged(test_address, _, _, false));
  std::vector handles({0x0021});
  TestReadCharacteristic(test_address, 1, handles);
}
TEST_F(VolumeControlTest, test_read_vcs_volume_flags) {
  std::vector handles({0x0026});
  TestReadCharacteristic(GetTestAddress(0), 1, handles);
}
TEST_F(VolumeControlTest, test_read_vocs_volume_offset) {
  const RawAddress test_address = GetTestAddress(0);
  EXPECT_CALL(*callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 1, _));
  EXPECT_CALL(*callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 2, _));
  std::vector handles({0x0072, 0x0082});
  TestReadCharacteristic(test_address, 1, handles);
}
TEST_F(VolumeControlTest, test_read_vocs_offset_location) {
  const RawAddress test_address = GetTestAddress(0);
  EXPECT_CALL(*callbacks, OnExtAudioOutLocationChanged(test_address, 1, _));
  EXPECT_CALL(*callbacks, OnExtAudioOutLocationChanged(test_address, 2, _));
  std::vector handles({0x0075, 0x0085});
  TestReadCharacteristic(test_address, 1, handles);
}
TEST_F(VolumeControlTest, test_read_vocs_output_description) {
  const RawAddress test_address = GetTestAddress(0);
  EXPECT_CALL(*callbacks, OnExtAudioOutDescriptionChanged(test_address, 1, _));
  EXPECT_CALL(*callbacks, OnExtAudioOutDescriptionChanged(test_address, 2, _));
  std::vector handles({0x0079, 0x008a});
  TestReadCharacteristic(test_address, 1, handles);
}
TEST_F(VolumeControlTest, test_discovery_vocs_found) {
  const RawAddress test_address = GetTestAddress(0);
  SetSampleDatabaseVOCS(1);
  TestAppRegister();
  TestConnect(test_address);
  EXPECT_CALL(*callbacks,
              OnConnectionState(ConnectionState::CONNECTED, test_address));
  EXPECT_CALL(*callbacks, OnDeviceAvailable(test_address, 2));
  GetConnectedEvent(test_address, 1);
  GetSearchCompleteEvent(1);
  Mock::VerifyAndClearExpectations(callbacks.get());
  TestAppUnregister();
}
TEST_F(VolumeControlTest, test_discovery_vocs_not_found) {
  const RawAddress test_address = GetTestAddress(0);
  SetSampleDatabaseVCS(1);
  TestAppRegister();
  TestConnect(test_address);
  EXPECT_CALL(*callbacks,
              OnConnectionState(ConnectionState::CONNECTED, test_address));
  EXPECT_CALL(*callbacks, OnDeviceAvailable(test_address, 0));
  GetConnectedEvent(test_address, 1);
  GetSearchCompleteEvent(1);
  Mock::VerifyAndClearExpectations(callbacks.get());
  TestAppUnregister();
}
TEST_F(VolumeControlTest, test_discovery_vocs_broken) {
  const RawAddress test_address = GetTestAddress(0);
  SetSampleDatabaseVOCSBroken(1);
  TestAppRegister();
  TestConnect(test_address);
  EXPECT_CALL(*callbacks,
              OnConnectionState(ConnectionState::CONNECTED, test_address));
  EXPECT_CALL(*callbacks, OnDeviceAvailable(test_address, 1));
  GetConnectedEvent(test_address, 1);
  GetSearchCompleteEvent(1);
  Mock::VerifyAndClearExpectations(callbacks.get());
  TestAppUnregister();
}
TEST_F(VolumeControlTest, test_read_vcs_database_out_of_sync) {
  const RawAddress test_address = GetTestAddress(0);
  EXPECT_CALL(*callbacks, OnVolumeStateChanged(test_address, _, _, false));
  std::vector handles({0x0021});
  uint16_t conn_id = 1;
  SetSampleDatabase(conn_id);
  TestAppRegister();
  TestConnect(test_address);
  GetConnectedEvent(test_address, conn_id);
  EXPECT_CALL(gatt_queue, ReadCharacteristic(conn_id, _, _, _))
      .WillRepeatedly(DoDefault());
  for (auto const& handle : handles) {
    EXPECT_CALL(gatt_queue, ReadCharacteristic(conn_id, handle, _, _))
        .WillOnce(DoDefault());
  }
  GetSearchCompleteEvent(conn_id);
  /* Simulate database change on the remote side. */
  ON_CALL(gatt_queue, WriteCharacteristic(_, _, _, _, _, _))
      .WillByDefault(
          Invoke([this](uint16_t conn_id, uint16_t handle,
                        std::vector value, tGATT_WRITE_TYPE write_type,
                        GATT_WRITE_OP_CB cb, void* cb_data) {
            auto* svc = gatt::FindService(services_map[conn_id], handle);
            if (svc == nullptr) return;
            tGATT_STATUS status = GATT_DATABASE_OUT_OF_SYNC;
            if (cb)
              cb(conn_id, status, handle, value.size(), value.data(), cb_data);
          }));
  ON_CALL(gatt_interface, ServiceSearchRequest(_, _)).WillByDefault(Return());
  EXPECT_CALL(gatt_interface, ServiceSearchRequest(_, _));
  VolumeControl::Get()->SetVolume(test_address, 15);
  Mock::VerifyAndClearExpectations(&gatt_interface);
  TestAppUnregister();
}
class VolumeControlCallbackTest : public VolumeControlTest {
 protected:
  const RawAddress test_address = GetTestAddress(0);
  uint16_t conn_id = 22;
  void SetUp(void) override {
    VolumeControlTest::SetUp();
    SetSampleDatabase(conn_id);
    TestAppRegister();
    TestConnect(test_address);
    GetConnectedEvent(test_address, conn_id);
    GetSearchCompleteEvent(conn_id);
  }
  void TearDown(void) override {
    TestAppUnregister();
    VolumeControlTest::TearDown();
  }
  void GetNotificationEvent(uint16_t handle, std::vector& value) {
    tBTA_GATTC_NOTIFY event_data = {
        .conn_id = conn_id,
        .bda = test_address,
        .handle = handle,
        .len = (uint8_t)value.size(),
        .is_notify = true,
    };
    std::copy(value.begin(), value.end(), event_data.value);
    gatt_callback(BTA_GATTC_NOTIF_EVT, (tBTA_GATTC*)&event_data);
  }
};
TEST_F(VolumeControlCallbackTest, test_volume_state_changed) {
  std::vector value({0x03, 0x01, 0x02});
  EXPECT_CALL(*callbacks, OnVolumeStateChanged(test_address, 0x03, true, true));
  GetNotificationEvent(0x0021, value);
}
TEST_F(VolumeControlCallbackTest, test_volume_state_changed_malformed) {
  EXPECT_CALL(*callbacks, OnVolumeStateChanged(test_address, _, _, _)).Times(0);
  std::vector too_short({0x03, 0x01});
  GetNotificationEvent(0x0021, too_short);
  std::vector too_long({0x03, 0x01, 0x02, 0x03});
  GetNotificationEvent(0x0021, too_long);
}
TEST_F(VolumeControlCallbackTest, test_volume_offset_changed) {
  std::vector value({0x04, 0x05, 0x06});
  EXPECT_CALL(*callbacks,
              OnExtAudioOutVolumeOffsetChanged(test_address, 2, 0x0504));
  GetNotificationEvent(0x0082, value);
}
TEST_F(VolumeControlCallbackTest, test_volume_offset_changed_malformed) {
  EXPECT_CALL(*callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 2, _))
      .Times(0);
  std::vector too_short({0x04});
  GetNotificationEvent(0x0082, too_short);
  std::vector too_long({0x04, 0x05, 0x06, 0x07});
  GetNotificationEvent(0x0082, too_long);
}
TEST_F(VolumeControlCallbackTest, test_offset_location_changed) {
  std::vector value({0x01, 0x02, 0x03, 0x04});
  EXPECT_CALL(*callbacks,
              OnExtAudioOutLocationChanged(test_address, 2, 0x04030201));
  GetNotificationEvent(0x0085, value);
}
TEST_F(VolumeControlCallbackTest, test_offset_location_changed_malformed) {
  EXPECT_CALL(*callbacks, OnExtAudioOutLocationChanged(test_address, 2, _))
      .Times(0);
  std::vector too_short({0x04});
  GetNotificationEvent(0x0085, too_short);
  std::vector too_long({0x04, 0x05, 0x06});
  GetNotificationEvent(0x0085, too_long);
}
TEST_F(VolumeControlCallbackTest, test_audio_output_description_changed) {
  std::string descr = "left";
  std::vector value(descr.begin(), descr.end());
  EXPECT_CALL(*callbacks,
              OnExtAudioOutDescriptionChanged(test_address, 2, descr));
  GetNotificationEvent(0x008a, value);
}
class VolumeControlValueGetTest : public VolumeControlTest {
 protected:
  const RawAddress test_address = GetTestAddress(0);
  uint16_t conn_id = 22;
  GATT_READ_OP_CB cb;
  void* cb_data;
  uint16_t handle;
  void SetUp(void) override {
    VolumeControlTest::SetUp();
    SetSampleDatabase(conn_id);
    TestAppRegister();
    TestConnect(test_address);
    GetConnectedEvent(test_address, conn_id);
    GetSearchCompleteEvent(conn_id);
    EXPECT_CALL(gatt_queue, ReadCharacteristic(conn_id, _, _, _))
        .WillOnce(
            DoAll(SaveArg<1>(&handle), SaveArg<2>(&cb), SaveArg<3>(&cb_data)));
  }
  void TearDown(void) override {
    TestAppUnregister();
    cb = nullptr;
    cb_data = nullptr;
    handle = 0;
    VolumeControlTest::TearDown();
  }
};
TEST_F(VolumeControlValueGetTest, test_get_ext_audio_out_volume_offset) {
  VolumeControl::Get()->GetExtAudioOutVolumeOffset(test_address, 1);
  EXPECT_TRUE(cb);
  std::vector value({0x01, 0x02, 0x03});
  EXPECT_CALL(*callbacks,
              OnExtAudioOutVolumeOffsetChanged(test_address, 1, 0x0201));
  cb(conn_id, GATT_SUCCESS, handle, (uint16_t)value.size(), value.data(),
     cb_data);
}
TEST_F(VolumeControlValueGetTest, test_get_ext_audio_out_location) {
  VolumeControl::Get()->GetExtAudioOutLocation(test_address, 2);
  EXPECT_TRUE(cb);
  std::vector value({0x01, 0x02, 0x03, 0x04});
  EXPECT_CALL(*callbacks,
              OnExtAudioOutLocationChanged(test_address, 2, 0x04030201));
  cb(conn_id, GATT_SUCCESS, handle, (uint16_t)value.size(), value.data(),
     cb_data);
}
TEST_F(VolumeControlValueGetTest, test_get_ext_audio_out_description) {
  VolumeControl::Get()->GetExtAudioOutDescription(test_address, 2);
  EXPECT_TRUE(cb);
  std::string descr = "right";
  std::vector value(descr.begin(), descr.end());
  EXPECT_CALL(*callbacks,
              OnExtAudioOutDescriptionChanged(test_address, 2, descr));
  cb(conn_id, GATT_SUCCESS, handle, (uint16_t)value.size(), value.data(),
     cb_data);
}
class VolumeControlValueSetTest : public VolumeControlTest {
 protected:
  const RawAddress test_address = GetTestAddress(0);
  uint16_t conn_id = 22;
  void SetUp(void) override {
    VolumeControlTest::SetUp();
    SetSampleDatabase(conn_id);
    TestAppRegister();
    TestConnect(test_address);
    GetConnectedEvent(test_address, conn_id);
    GetSearchCompleteEvent(conn_id);
  }
  void GetNotificationEvent(uint16_t handle, std::vector& value) {
    tBTA_GATTC_NOTIFY event_data = {
        .conn_id = conn_id,
        .bda = test_address,
        .handle = handle,
        .len = (uint8_t)value.size(),
        .is_notify = true,
    };
    std::copy(value.begin(), value.end(), event_data.value);
    gatt_callback(BTA_GATTC_NOTIF_EVT, (tBTA_GATTC*)&event_data);
  }
  void TearDown(void) override {
    TestAppUnregister();
    VolumeControlTest::TearDown();
  }
};
TEST_F(VolumeControlValueSetTest, test_set_volume) {
  ON_CALL(gatt_queue, WriteCharacteristic(conn_id, 0x0024, _, GATT_WRITE, _, _))
      .WillByDefault([this](uint16_t conn_id, uint16_t handle,
                            std::vector value,
                            tGATT_WRITE_TYPE write_type, GATT_WRITE_OP_CB cb,
                            void* cb_data) {
        std::vector ntf_value({
            value[2],                            // volume level
            0,                                   // muted
            static_cast(value[1] + 1),  // change counter
        });
        GetNotificationEvent(0x0021, ntf_value);
      });
  const std::vector vol_x10({0x04, 0x00, 0x10});
  EXPECT_CALL(gatt_queue,
              WriteCharacteristic(conn_id, 0x0024, vol_x10, GATT_WRITE, _, _))
      .Times(1);
  VolumeControl::Get()->SetVolume(test_address, 0x10);
  // Same volume level should not be applied twice
  const std::vector vol_x10_2({0x04, 0x01, 0x10});
  EXPECT_CALL(gatt_queue,
              WriteCharacteristic(conn_id, 0x0024, vol_x10_2, GATT_WRITE, _, _))
      .Times(0);
  VolumeControl::Get()->SetVolume(test_address, 0x10);
  const std::vector vol_x20({0x04, 0x01, 0x20});
  EXPECT_CALL(gatt_queue,
              WriteCharacteristic(conn_id, 0x0024, vol_x20, GATT_WRITE, _, _))
      .Times(1);
  VolumeControl::Get()->SetVolume(test_address, 0x20);
}
TEST_F(VolumeControlValueSetTest, test_mute) {
  std::vector mute({0x06, 0x00});
  EXPECT_CALL(gatt_queue,
              WriteCharacteristic(conn_id, 0x0024, mute, GATT_WRITE, _, _));
  VolumeControl::Get()->Mute(test_address);
}
TEST_F(VolumeControlValueSetTest, test_unmute) {
  std::vector unmute({0x05, 0x00});
  EXPECT_CALL(gatt_queue,
              WriteCharacteristic(conn_id, 0x0024, unmute, GATT_WRITE, _, _));
  VolumeControl::Get()->UnMute(test_address);
}
TEST_F(VolumeControlValueSetTest, test_set_ext_audio_out_volume_offset) {
  std::vector expected_data({0x01, 0x00, 0x34, 0x12});
  EXPECT_CALL(gatt_queue, WriteCharacteristic(conn_id, 0x0088, expected_data,
                                              GATT_WRITE, _, _));
  VolumeControl::Get()->SetExtAudioOutVolumeOffset(test_address, 2, 0x1234);
}
TEST_F(VolumeControlValueSetTest, test_set_ext_audio_out_location) {
  std::vector expected_data({0x44, 0x33, 0x22, 0x11});
  EXPECT_CALL(gatt_queue, WriteCharacteristic(conn_id, 0x0085, expected_data,
                                              GATT_WRITE_NO_RSP, _, _));
  VolumeControl::Get()->SetExtAudioOutLocation(test_address, 2, 0x11223344);
}
TEST_F(VolumeControlValueSetTest,
       test_set_ext_audio_out_location_non_writable) {
  EXPECT_CALL(gatt_queue, WriteCharacteristic(_, _, _, _, _, _)).Times(0);
  VolumeControl::Get()->SetExtAudioOutLocation(test_address, 1, 0x11223344);
}
TEST_F(VolumeControlValueSetTest, test_set_ext_audio_out_description) {
  std::string descr = "right front";
  std::vector expected_data(descr.begin(), descr.end());
  EXPECT_CALL(gatt_queue, WriteCharacteristic(conn_id, 0x008a, expected_data,
                                              GATT_WRITE_NO_RSP, _, _));
  VolumeControl::Get()->SetExtAudioOutDescription(test_address, 2, descr);
}
TEST_F(VolumeControlValueSetTest,
       test_set_ext_audio_out_description_non_writable) {
  std::string descr = "left front";
  EXPECT_CALL(gatt_queue, WriteCharacteristic(_, _, _, _, _, _)).Times(0);
  VolumeControl::Get()->SetExtAudioOutDescription(test_address, 1, descr);
}
class VolumeControlCsis : public VolumeControlTest {
 protected:
  const RawAddress test_address_1 = GetTestAddress(0);
  const RawAddress test_address_2 = GetTestAddress(1);
  std::vector csis_group = {test_address_1, test_address_2};
  uint16_t conn_id_1 = 22;
  uint16_t conn_id_2 = 33;
  int group_id = 5;
  void SetUp(void) override {
    VolumeControlTest::SetUp();
    ON_CALL(mock_csis_client_module_, Get())
        .WillByDefault(Return(&mock_csis_client_module_));
    // Report working CSIS
    ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
        .WillByDefault(Return(true));
    ON_CALL(mock_csis_client_module_, GetDeviceList(_))
        .WillByDefault(Return(csis_group));
    ON_CALL(mock_csis_client_module_, GetGroupId(_, _))
        .WillByDefault(Return(group_id));
    SetSampleDatabase(conn_id_1);
    SetSampleDatabase(conn_id_2);
    TestAppRegister();
  }
  void TearDown(void) override {
    TestAppUnregister();
    VolumeControlTest::TearDown();
  }
  void GetNotificationEvent(uint16_t conn_id, const RawAddress& test_address,
                            uint16_t handle, std::vector& value) {
    tBTA_GATTC_NOTIFY event_data = {
        .conn_id = conn_id,
        .bda = test_address,
        .handle = handle,
        .len = (uint8_t)value.size(),
        .is_notify = true,
    };
    std::copy(value.begin(), value.end(), event_data.value);
    gatt_callback(BTA_GATTC_NOTIF_EVT, (tBTA_GATTC*)&event_data);
  }
};
TEST_F(VolumeControlCsis, test_set_volume) {
  TestConnect(test_address_1);
  GetConnectedEvent(test_address_1, conn_id_1);
  GetSearchCompleteEvent(conn_id_1);
  TestConnect(test_address_2);
  GetConnectedEvent(test_address_2, conn_id_2);
  GetSearchCompleteEvent(conn_id_2);
  /* Set value for the group */
  EXPECT_CALL(gatt_queue,
              WriteCharacteristic(conn_id_1, 0x0024, _, GATT_WRITE, _, _));
  EXPECT_CALL(gatt_queue,
              WriteCharacteristic(conn_id_2, 0x0024, _, GATT_WRITE, _, _));
  VolumeControl::Get()->SetVolume(group_id, 10);
  /* Now inject notification and make sure callback is sent up to Java layer */
  EXPECT_CALL(*callbacks,
              OnGroupVolumeStateChanged(group_id, 0x03, true, false));
  std::vector value({0x03, 0x01, 0x02});
  GetNotificationEvent(conn_id_1, test_address_1, 0x0021, value);
  GetNotificationEvent(conn_id_2, test_address_2, 0x0021, value);
  /* Verify exactly one operation with this exact value is queued for each
   * device */
  EXPECT_CALL(gatt_queue,
              WriteCharacteristic(conn_id_1, 0x0024, _, GATT_WRITE, _, _))
      .Times(1);
  EXPECT_CALL(gatt_queue,
              WriteCharacteristic(conn_id_2, 0x0024, _, GATT_WRITE, _, _))
      .Times(1);
  VolumeControl::Get()->SetVolume(test_address_1, 20);
  VolumeControl::Get()->SetVolume(test_address_2, 20);
  VolumeControl::Get()->SetVolume(test_address_1, 20);
  VolumeControl::Get()->SetVolume(test_address_2, 20);
  std::vector value2({20, 0x00, 0x03});
  GetNotificationEvent(conn_id_1, test_address_1, 0x0021, value2);
  GetNotificationEvent(conn_id_2, test_address_2, 0x0021, value2);
}
TEST_F(VolumeControlCsis, test_set_volume_device_not_ready) {
  /* Make sure we did not get responds to the initial reads,
   * so that the device was not marked as ready yet.
   */
  do_not_respond_to_reads = true;
  TestConnect(test_address_1);
  GetConnectedEvent(test_address_1, conn_id_1);
  GetSearchCompleteEvent(conn_id_1);
  TestConnect(test_address_2);
  GetConnectedEvent(test_address_2, conn_id_2);
  GetSearchCompleteEvent(conn_id_2);
  /* Set value for the group */
  EXPECT_CALL(gatt_queue,
              WriteCharacteristic(conn_id_1, 0x0024, _, GATT_WRITE, _, _))
      .Times(0);
  EXPECT_CALL(gatt_queue,
              WriteCharacteristic(conn_id_2, 0x0024, _, GATT_WRITE, _, _))
      .Times(0);
  VolumeControl::Get()->SetVolume(group_id, 10);
}
TEST_F(VolumeControlCsis, autonomus_test_set_volume) {
  TestConnect(test_address_1);
  GetConnectedEvent(test_address_1, conn_id_1);
  GetSearchCompleteEvent(conn_id_1);
  TestConnect(test_address_2);
  GetConnectedEvent(test_address_2, conn_id_2);
  GetSearchCompleteEvent(conn_id_2);
  /* Now inject notification and make sure callback is sent up to Java layer */
  EXPECT_CALL(*callbacks,
              OnGroupVolumeStateChanged(group_id, 0x03, false, true));
  std::vector value({0x03, 0x00, 0x02});
  GetNotificationEvent(conn_id_1, test_address_1, 0x0021, value);
  GetNotificationEvent(conn_id_2, test_address_2, 0x0021, value);
}
TEST_F(VolumeControlCsis, autonomus_single_device_test_set_volume) {
  TestConnect(test_address_1);
  GetConnectedEvent(test_address_1, conn_id_1);
  GetSearchCompleteEvent(conn_id_1);
  TestConnect(test_address_2);
  GetConnectedEvent(test_address_2, conn_id_2);
  GetSearchCompleteEvent(conn_id_2);
  /* Disconnect one device. */
  EXPECT_CALL(*callbacks,
              OnConnectionState(ConnectionState::DISCONNECTED, test_address_1));
  GetDisconnectedEvent(test_address_1, conn_id_1);
  /* Now inject notification and make sure callback is sent up to Java layer */
  EXPECT_CALL(*callbacks,
              OnGroupVolumeStateChanged(group_id, 0x03, false, true));
  std::vector value({0x03, 0x00, 0x02});
  GetNotificationEvent(conn_id_2, test_address_2, 0x0021, value);
}
}  // namespace
}  // namespace internal
}  // namespace vc
}  // namespace bluetooth