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

Commit 35b0836f authored by Łukasz Rymanowski's avatar Łukasz Rymanowski Committed by Jakub Pawlowski
Browse files

vc: Implement Volume Control Profile

 This implements basic version of VCP which allows to control Volume
 Control Service on ther remote side.

 This profile for expose only connect/disconnect/set volume

 Bug: 150670922
 Tag: #feature
 Test: atest --host bluetooth_test_vc
 Sponsor: jpawlowski@

Change-Id: Ie68c333ffece3958d68580fbfd3a86aec1186711
parent db448f37
Loading
Loading
Loading
Loading
+45 −0
Original line number Diff line number Diff line
@@ -80,6 +80,8 @@ cc_library_static {
        "gatt/bta_gatts_utils.cc",
        "gatt/database.cc",
        "gatt/database_builder.cc",
        "vc/device.cc",
        "vc/vc.cc",
        "hearing_aid/hearing_aid.cc",
        "hearing_aid/hearing_aid_audio_source.cc",
        "hf_client/bta_hf_client_act.cc",
@@ -255,3 +257,46 @@ cc_test {
    ],
    cflags: ["-DBUILDCFG"],
}


// bta unit tests for host
// ========================================================
cc_test {
    name: "bluetooth_vc_test",
    test_suites: ["device-tests"],
    defaults: [
        "fluoride_bta_defaults",
        "clang_coverage_bin",
    ],
    host_supported: true,
    include_dirs: [
        "packages/modules/Bluetooth/system",
        "packages/modules/Bluetooth/system/bta/include",
        "packages/modules/Bluetooth/system/bta/test/common",
        "packages/modules/Bluetooth/system/stack/include",
    ],
    srcs : [
        "gatt/database.cc",
        "gatt/database_builder.cc",
        "test/common/bta_gatt_api_mock.cc",
        "test/common/bta_gatt_queue_mock.cc",
        "test/common/btm_api_mock.cc",
        "vc/devices_test.cc",
        "vc/device.cc",
        "vc/vc.cc",
        "vc/vc_test.cc",
    ],
    shared_libs: [
        "libprotobuf-cpp-lite",
        "libcrypto",
    ],
    static_libs : [
        "crypto_toolbox_for_tests",
        "libgmock",
        "libbt-common",
        "libbt-protos-lite",
    ],
    sanitize: {
        cfi: false,
    },
}
+40 −0
Original line number Diff line number Diff line
/*
 * 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.
 */

#pragma once

#include <hardware/bt_vc.h>

class VolumeControl {
 public:
  virtual ~VolumeControl() = default;

  static void Initialize(bluetooth::vc::VolumeControlCallbacks* callbacks);
  static void CleanUp();
  static VolumeControl* Get();
  static void DebugDump(int fd);

  static void AddFromStorage(const RawAddress& address, bool auto_connect);

  static bool IsVolumeControlRunning();

  /* Volume Control Server (VCS) */
  virtual void Connect(const RawAddress& address) = 0;
  virtual void Disconnect(const RawAddress& address) = 0;
  virtual void SetVolume(std::variant<RawAddress, int> addr_or_group_id,
                         uint8_t volume) = 0;
};
+86 −0
Original line number Diff line number Diff line
/*
 * 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 "bta_gatt_api_mock.h"

static gatt::MockBtaGattInterface* gatt_interface = nullptr;

void gatt::SetMockBtaGattInterface(
    MockBtaGattInterface* mock_bta_gatt_interface) {
  gatt_interface = mock_bta_gatt_interface;
}

void BTA_GATTC_AppRegister(tBTA_GATTC_CBACK* p_client_cb,
                           BtaAppRegisterCallback cb, bool eatt_support) {
  gatt_interface->AppRegister(p_client_cb, cb, eatt_support);
}

void BTA_GATTC_AppDeregister(tGATT_IF client_if) {
  gatt_interface->AppDeregister(client_if);
}

void BTA_GATTC_Open(tGATT_IF client_if, const RawAddress& remote_bda,
                    bool is_direct, tBT_TRANSPORT transport,
                    bool opportunistic) {
  gatt_interface->Open(client_if, remote_bda, is_direct, transport,
                       opportunistic);
}

void BTA_GATTC_Open(tGATT_IF client_if, const RawAddress& remote_bda,
                    bool is_direct, bool opportunistic) {
  gatt_interface->Open(client_if, remote_bda, is_direct, opportunistic);
}

void BTA_GATTC_CancelOpen(tGATT_IF client_if, const RawAddress& remote_bda,
                          bool is_direct) {
  gatt_interface->CancelOpen(client_if, remote_bda, is_direct);
}

void BTA_GATTC_Close(uint16_t conn_id) { gatt_interface->Close(conn_id); }

void BTA_GATTC_ServiceSearchRequest(uint16_t conn_id,
                                    const bluetooth::Uuid* p_srvc_uuid) {
  gatt_interface->ServiceSearchRequest(conn_id, p_srvc_uuid);
}

const std::list<gatt::Service>* BTA_GATTC_GetServices(uint16_t conn_id) {
  return gatt_interface->GetServices(conn_id);
}

const gatt::Characteristic* BTA_GATTC_GetCharacteristic(uint16_t conn_id,
                                                        uint16_t handle) {
  return gatt_interface->GetCharacteristic(conn_id, handle);
}

const gatt::Service* BTA_GATTC_GetOwningService(uint16_t conn_id,
                                                uint16_t handle) {
  return gatt_interface->GetOwningService(conn_id, handle);
}

tGATT_STATUS BTA_GATTC_RegisterForNotifications(tGATT_IF client_if,
                                                const RawAddress& remote_bda,
                                                uint16_t handle) {
  return gatt_interface->RegisterForNotifications(client_if, remote_bda,
                                                  handle);
}

tGATT_STATUS BTA_GATTC_DeregisterForNotifications(tGATT_IF client_if,
                                                  const RawAddress& remote_bda,
                                                  uint16_t handle) {
  return gatt_interface->DeregisterForNotifications(client_if, remote_bda,
                                                    handle);
}
+95 −0
Original line number Diff line number Diff line
/*
 * 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.
 */
#pragma once

#include <base/callback.h>
#include <gmock/gmock.h>

#include "bta_gatt_api.h"

namespace gatt {

class BtaGattInterface {
 public:
  virtual void AppRegister(tBTA_GATTC_CBACK* p_client_cb,
                           BtaAppRegisterCallback cb, bool eatt_support) = 0;
  virtual void AppDeregister(tGATT_IF client_if) = 0;
  virtual void Open(tGATT_IF client_if, const RawAddress& remote_bda,
                    bool is_direct, tBT_TRANSPORT transport,
                    bool opportunistic) = 0;
  virtual void Open(tGATT_IF client_if, const RawAddress& remote_bda,
                    bool is_direct, bool opportunistic) = 0;
  virtual void CancelOpen(tGATT_IF client_if, const RawAddress& remote_bda,
                          bool is_direct) = 0;
  virtual void Close(uint16_t conn_id) = 0;
  virtual void ServiceSearchRequest(uint16_t conn_id,
                                    const bluetooth::Uuid* p_srvc_uuid) = 0;
  virtual const std::list<Service>* GetServices(uint16_t conn_id) = 0;
  virtual const Characteristic* GetCharacteristic(uint16_t conn_id,
                                                  uint16_t handle) = 0;
  virtual const Service* GetOwningService(uint16_t conn_id,
                                          uint16_t handle) = 0;
  virtual tGATT_STATUS RegisterForNotifications(tGATT_IF client_if,
                                                const RawAddress& remote_bda,
                                                uint16_t handle) = 0;
  virtual tGATT_STATUS DeregisterForNotifications(tGATT_IF client_if,
                                                  const RawAddress& remote_bda,
                                                  uint16_t handle) = 0;
  virtual ~BtaGattInterface() = default;
};

class MockBtaGattInterface : public BtaGattInterface {
 public:
  MOCK_METHOD((void), AppRegister,
              (tBTA_GATTC_CBACK * p_client_cb, BtaAppRegisterCallback cb,
               bool eatt_support),
              (override));
  MOCK_METHOD((void), AppDeregister, (tGATT_IF client_if), (override));
  MOCK_METHOD((void), Open,
              (tGATT_IF client_if, const RawAddress& remote_bda, bool is_direct,
               tBT_TRANSPORT transport, bool opportunistic));
  MOCK_METHOD((void), Open,
              (tGATT_IF client_if, const RawAddress& remote_bda, bool is_direct,
               bool opportunistic));
  MOCK_METHOD((void), CancelOpen,
              (tGATT_IF client_if, const RawAddress& remote_bda,
               bool is_direct));
  MOCK_METHOD((void), Close, (uint16_t conn_id));
  MOCK_METHOD((void), ServiceSearchRequest,
              (uint16_t conn_id, const bluetooth::Uuid* p_srvc_uuid));
  MOCK_METHOD((std::list<Service>*), GetServices, (uint16_t conn_id));
  MOCK_METHOD((const Characteristic*), GetCharacteristic,
              (uint16_t conn_id, uint16_t handle));
  MOCK_METHOD((const Service*), GetOwningService,
              (uint16_t conn_id, uint16_t handle));
  MOCK_METHOD((tGATT_STATUS), RegisterForNotifications,
              (tGATT_IF client_if, const RawAddress& remote_bda,
               uint16_t handle));
  MOCK_METHOD((tGATT_STATUS), DeregisterForNotifications,
              (tGATT_IF client_if, const RawAddress& remote_bda,
               uint16_t handle));
};

/**
 * Set the {@link MockBtaGattInterface} for testing
 *
 * @param mock_bta_gatt_interface pointer to mock bta gatt interface,
 * could be null
 */
void SetMockBtaGattInterface(MockBtaGattInterface* mock_bta_gatt_interface);

}  // namespace gatt
+46 −0
Original line number Diff line number Diff line
/*
 * 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 "bta_gatt_queue_mock.h"

static gatt::MockBtaGattQueue* gatt_queue = nullptr;

void gatt::SetMockBtaGattQueue(MockBtaGattQueue* mock_bta_gatt_queue) {
  gatt_queue = mock_bta_gatt_queue;
}

void BtaGattQueue::Clean(uint16_t conn_id) { gatt_queue->Clean(conn_id); }

void BtaGattQueue::ReadCharacteristic(uint16_t conn_id, uint16_t handle,
                                      GATT_READ_OP_CB cb, void* cb_data) {
  gatt_queue->ReadCharacteristic(conn_id, handle, cb, cb_data);
}

void BtaGattQueue::WriteCharacteristic(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) {
  gatt_queue->WriteCharacteristic(conn_id, handle, value, write_type, cb,
                                  cb_data);
}

void BtaGattQueue::WriteDescriptor(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) {
  gatt_queue->WriteDescriptor(conn_id, handle, value, write_type, cb, cb_data);
}
Loading