#include <base/observer_list.h>
#include "service/hal/bluetooth_interface.h"
+#include "service/logging_helpers.h"
using std::lock_guard;
using std::mutex;
RegisterClientCallback(g_interface, status, client_if, *app_uuid));
}
+void ScanResultCallback(bt_bdaddr_t* bda, int rssi, uint8_t* adv_data) {
+ lock_guard<mutex> lock(g_instance_lock);
+ VERIFY_INTERFACE_OR_RETURN();
+ CHECK(bda);
+ CHECK(adv_data);
+
+ VLOG(2) << __func__ << " - BD_ADDR: " << BtAddrString(bda)
+ << " RSSI: " << rssi;
+ FOR_EACH_CLIENT_OBSERVER(
+ ScanResultCallback(g_interface, *bda, rssi, adv_data));
+}
+
+void ListenCallback(int status, int client_if) {
+ lock_guard<mutex> lock(g_instance_lock);
+ VLOG(2) << __func__ << " - status: " << status << " client_if: " << client_if;
+ VERIFY_INTERFACE_OR_RETURN();
+
+ FOR_EACH_CLIENT_OBSERVER(ListenCallback(g_interface, status, client_if));
+}
+
void MultiAdvEnableCallback(int client_if, int status) {
lock_guard<mutex> lock(g_instance_lock);
VLOG(2) << __func__ << " - status: " << status << " client_if: " << client_if;
g_interface, status, server_if, srvc_handle));
}
+void ServiceDeletedCallback(int status, int server_if, int srvc_handle) {
+ lock_guard<mutex> lock(g_instance_lock);
+ VLOG(2) << __func__ << " - status: " << status << " server_if: " << server_if
+ << " handle: " << srvc_handle;
+ VERIFY_INTERFACE_OR_RETURN();
+
+ FOR_EACH_SERVER_OBSERVER(ServiceDeletedCallback(
+ g_interface, status, server_if, srvc_handle));
+}
+
void RequestReadCallback(int conn_id, int trans_id, bt_bdaddr_t* bda,
int attr_handle, int offset, bool is_long) {
lock_guard<mutex> lock(g_instance_lock);
// GATT client-role and GAP events.
const btgatt_client_callbacks_t gatt_client_callbacks = {
RegisterClientCallback,
- nullptr, // scan_result_cb
+ ScanResultCallback,
nullptr, // open_cb
nullptr, // close_cb
nullptr, // search_complete_cb
nullptr, // write_descriptor_cb
nullptr, // execute_write_cb
nullptr, // read_remote_rssi_cb
- nullptr, // listen_cb
+ ListenCallback,
nullptr, // configure_mtu_cb
nullptr, // scan_filter_cfg_cb
nullptr, // scan_filter_param_cb
RegisterServerCallback,
ConnectionCallback,
ServiceAddedCallback,
- nullptr, // included_service_added_cb,
+ nullptr, // included_service_added_cb
CharacteristicAddedCallback,
DescriptorAddedCallback,
ServiceStartedCallback,
ServiceStoppedCallback,
- nullptr, // service_deleted_cb,
+ ServiceDeletedCallback,
RequestReadCallback,
RequestWriteCallback,
RequestExecWriteCallback,
- nullptr, // response_confirmation_cb,
+ nullptr, // response_confirmation_cb
IndicationSentCallback,
nullptr, // congestion_cb
nullptr, // mtu_changed_cb
const bt_uuid_t& /* app_uuid */) {
// Do nothing.
}
+void BluetoothGattInterface::ClientObserver::ScanResultCallback(
+ BluetoothGattInterface* /* gatt_iface */,
+ const bt_bdaddr_t& /* bda */,
+ int /* rssi */,
+ uint8_t* /* adv_data */) {
+ // Do Nothing.
+}
+void BluetoothGattInterface::ClientObserver::ListenCallback(
+ BluetoothGattInterface* /* gatt_iface */,
+ int /* status */,
+ int /* client_if */) {
+ // Do nothing.
+}
void BluetoothGattInterface::ClientObserver::MultiAdvEnableCallback(
BluetoothGattInterface* /* gatt_iface */,
int /* status */,
// Do nothing.
}
+void BluetoothGattInterface::ServerObserver::ServiceDeletedCallback(
+ BluetoothGattInterface* /* gatt_iface */,
+ int /* status */,
+ int /* server_if */,
+ int /* srvc_handle */) {
+ // Do nothing.
+}
+
void BluetoothGattInterface::ServerObserver::RequestReadCallback(
BluetoothGattInterface* /* gatt_iface */,
int /* conn_id */,
int status, int client_if,
const bt_uuid_t& app_uuid);
+ virtual void ScanResultCallback(
+ BluetoothGattInterface* gatt_iface,
+ const bt_bdaddr_t& bda, int rssi,
+ uint8_t* adv_data);
+
+ virtual void ListenCallback(
+ BluetoothGattInterface* gatt_iface,
+ int status, int client_if);
+
virtual void MultiAdvEnableCallback(
BluetoothGattInterface* gatt_iface,
int client_if, int status);
int status, int server_if,
int srvc_handle);
+ virtual void ServiceDeletedCallback(
+ BluetoothGattInterface* gatt_iface,
+ int status, int server_if,
+ int srvc_handle);
+
virtual void RequestReadCallback(
BluetoothGattInterface* gatt_iface,
int conn_id, int trans_id,
# with the interface using C++
# TODO: Make the bluetoothtbd HAL a static library
bluetoothHalSrc := \
+ ../../service/hal/bluetooth_gatt_interface.cpp \
../../service/hal/bluetooth_interface.cpp \
../../service/logging_helpers.cpp
$(LOCAL_PATH)/../../
LOCAL_SRC_FILES := \
- adapter_unittest.cpp \
- bluetooth_test.cpp \
+ adapter/adapter_unittest.cpp \
+ adapter/bluetooth_test.cpp \
+ gatt/gatt_test.cpp \
+ gatt/gatt_unittest.cpp \
$(bluetoothHalSrc)
LOCAL_SHARED_LIBRARIES += \
*
******************************************************************************/
-#include "bluetooth_test.h"
+#include "adapter/bluetooth_test.h"
extern "C" {
#include "btcore/include/property.h"
*
******************************************************************************/
-#include "bluetooth_test.h"
+#include "adapter/bluetooth_test.h"
#include <mutex>
--- /dev/null
+/******************************************************************************
+ *
+ * Copyright (C) 2015 Google, Inc.
+ *
+ * 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 "adapter/bluetooth_test.h"
+#include "gatt/gatt_test.h"
+
+extern "C" {
+#include "btcore/include/bdaddr.h"
+}
+
+namespace bttest {
+
+void GattTest::SetUp() {
+ gatt_client_interface_ = nullptr;
+ gatt_server_interface_ = nullptr;
+
+ client_interface_id_ = 0;
+ server_interface_id_ = 0;
+ service_handle_ = 0;
+ characteristic_handle_ = 0;
+ descriptor_handle_ = 0;
+ status_ = 0;
+
+ BluetoothTest::SetUp();
+ ASSERT_EQ(bt_interface()->enable(), BT_STATUS_SUCCESS);
+ semaphore_wait(adapter_state_changed_callback_sem_);
+ EXPECT_TRUE(GetState() == BT_STATE_ON);
+
+ register_client_callback_sem_ = semaphore_new(0);
+ scan_result_callback_sem_ = semaphore_new(0);
+ listen_callback_sem_ = semaphore_new(0);
+
+ register_server_callback_sem_ = semaphore_new(0);
+ service_added_callback_sem_ = semaphore_new(0);
+ characteristic_added_callback_sem_ = semaphore_new(0);
+ descriptor_added_callback_sem_ = semaphore_new(0);
+ service_started_callback_sem_ = semaphore_new(0);
+ service_stopped_callback_sem_ = semaphore_new(0);
+ service_deleted_callback_sem_ = semaphore_new(0);
+
+ bluetooth::hal::BluetoothGattInterface::Initialize();
+ ASSERT_TRUE(bluetooth::hal::BluetoothGattInterface::IsInitialized());
+ auto gatt_interface = bluetooth::hal::BluetoothGattInterface::Get();
+ gatt_interface->AddClientObserver(this);
+ gatt_interface->AddServerObserver(this);
+
+ gatt_client_interface_ = gatt_interface->GetClientHALInterface();
+ gatt_server_interface_ = gatt_interface->GetServerHALInterface();
+
+ ASSERT_NE(nullptr, gatt_client_interface_);
+ ASSERT_NE(nullptr, gatt_server_interface_);
+}
+
+void GattTest::TearDown() {
+ gatt_client_interface_ = nullptr;
+ gatt_server_interface_ = nullptr;
+
+ semaphore_free(register_client_callback_sem_);
+ semaphore_free(scan_result_callback_sem_);
+ semaphore_free(listen_callback_sem_);
+
+ semaphore_free(register_server_callback_sem_);
+ semaphore_free(service_added_callback_sem_);
+ semaphore_free(characteristic_added_callback_sem_);
+ semaphore_free(descriptor_added_callback_sem_);
+ semaphore_free(service_started_callback_sem_);
+ semaphore_free(service_stopped_callback_sem_);
+ semaphore_free(service_deleted_callback_sem_);
+
+ bluetooth::hal::BluetoothGattInterface::CleanUp();
+
+ ASSERT_EQ(bt_interface()->disable(), BT_STATUS_SUCCESS);
+ semaphore_wait(adapter_state_changed_callback_sem_);
+ BluetoothTest::TearDown();
+}
+
+const btgatt_client_interface_t* GattTest::gatt_client_interface() {
+ return gatt_client_interface_;
+}
+
+const btgatt_server_interface_t* GattTest::gatt_server_interface() {
+ return gatt_server_interface_;
+}
+
+void GattTest::RegisterClientCallback(
+ bluetooth::hal::BluetoothGattInterface* /* unused */,
+ int status, int clientIf, const bt_uuid_t& app_uuid) {
+ status_ = status;
+ client_interface_id_ = clientIf;
+ semaphore_post(register_client_callback_sem_);
+}
+
+void GattTest::ScanResultCallback(
+ bluetooth::hal::BluetoothGattInterface* /* unused */,
+ const bt_bdaddr_t& bda, int rssi, uint8_t* adv_data) {
+ semaphore_post(scan_result_callback_sem_);
+}
+
+void GattTest::ListenCallback(
+ bluetooth::hal::BluetoothGattInterface* /* unused */,
+ int status, int client_if) {
+ status_ = status;
+ client_interface_id_ = client_if;
+ semaphore_post(listen_callback_sem_);
+}
+
+// GATT server callbacks
+void GattTest::RegisterServerCallback(
+ bluetooth::hal::BluetoothGattInterface* /* unused */,
+ int status, int server_if, const bt_uuid_t& uuid) {
+ status_ = status;
+ server_interface_id_ = server_if;
+ semaphore_post(register_server_callback_sem_);
+}
+
+void GattTest::ServiceAddedCallback(
+ bluetooth::hal::BluetoothGattInterface* /* unused */,
+ int status, int server_if, const btgatt_srvc_id_t& srvc_id,
+ int srvc_handle) {
+ status_ = status;
+ server_interface_id_ = server_if;
+ service_handle_ = srvc_handle;
+ semaphore_post(service_added_callback_sem_);
+}
+
+void GattTest::CharacteristicAddedCallback(
+ bluetooth::hal::BluetoothGattInterface* /* unused */,
+ int status, int server_if, const bt_uuid_t& char_id,
+ int srvc_handle, int char_handle) {
+ status_ = status;
+ server_interface_id_ = server_if;
+ service_handle_ = srvc_handle;
+ characteristic_handle_ = char_handle;
+ semaphore_post(characteristic_added_callback_sem_);
+}
+
+void GattTest::DescriptorAddedCallback(
+ bluetooth::hal::BluetoothGattInterface* /* unused */,
+ int status, int server_if, const bt_uuid_t& descr_id,
+ int srvc_handle, int descr_handle) {
+ status_ = status;
+ server_interface_id_ = server_if;
+ service_handle_ = srvc_handle;
+ descriptor_handle_ = descr_handle;
+ semaphore_post(descriptor_added_callback_sem_);
+}
+
+void GattTest::ServiceStartedCallback(
+ bluetooth::hal::BluetoothGattInterface* /* unused */,
+ int status, int server_if, int srvc_handle) {
+ status_ = status;
+ server_interface_id_ = server_if;
+ service_handle_ = srvc_handle;
+ semaphore_post(service_started_callback_sem_);
+}
+
+void GattTest::ServiceStoppedCallback(
+ bluetooth::hal::BluetoothGattInterface* /* unused */,
+ int status, int server_if, int srvc_handle) {
+ status_ = status;
+ server_interface_id_ = server_if;
+ service_handle_ = srvc_handle;
+ semaphore_post(service_stopped_callback_sem_);
+}
+
+void GattTest::ServiceDeletedCallback(
+ bluetooth::hal::BluetoothGattInterface* /* unused */,
+ int status, int server_if, int srvc_handle) {
+ status_ = status;
+ server_interface_id_ = server_if;
+ service_handle_ = srvc_handle;
+ semaphore_post(service_deleted_callback_sem_);
+}
+
+} // bttest
--- /dev/null
+/******************************************************************************
+ *
+ * Copyright (C) 2015 Google, Inc.
+ *
+ * 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 "adapter/bluetooth_test.h"
+#include "service/hal/bluetooth_gatt_interface.h"
+
+namespace bttest {
+
+// This class represents the Bluetooth GATT testing framework and provides
+// helpers and callbacks for GUnit to use for testing gatt.
+class GattTest : public BluetoothTest,
+ public bluetooth::hal::BluetoothGattInterface::ClientObserver,
+ public bluetooth::hal::BluetoothGattInterface::ServerObserver {
+ protected:
+ GattTest() = default;
+ virtual ~GattTest() = default;
+
+ // Gets the gatt_client_interface
+ const btgatt_client_interface_t* gatt_client_interface();
+
+ // Gets the gatt_server_interface
+ const btgatt_server_interface_t* gatt_server_interface();
+
+ // Getters for variables that track GATT-related state
+ int client_interface_id() const { return client_interface_id_; }
+ int server_interface_id() const { return server_interface_id_; }
+ int service_handle() const { return service_handle_; }
+ int characteristic_handle() const { return characteristic_handle_; }
+ int descriptor_handle() const { return descriptor_handle_; }
+ int status() const { return status_; }
+
+ // SetUp initializes the Bluetooth interfaces and the GATT Interface as well
+ // as registers the callbacks and initializes the semaphores before every test
+ virtual void SetUp();
+
+ // TearDown cleans up the Bluetooth and GATT interfaces and destroys the
+ // callback semaphores at the end of every test
+ virtual void TearDown();
+
+ // bluetooth::hal::BluetoothGattInterface::ClientObserver overrides
+ void RegisterClientCallback(
+ bluetooth::hal::BluetoothGattInterface* /* unused */,
+ int status, int clientIf, const bt_uuid_t& app_uuid) override;
+ void ScanResultCallback(
+ bluetooth::hal::BluetoothGattInterface* /* unused */,
+ const bt_bdaddr_t& bda, int rssi, uint8_t* adv_data) override;
+ void ListenCallback(
+ bluetooth::hal::BluetoothGattInterface* /* unused */,
+ int status, int client_if) override;
+
+ // bluetooth::hal::BluetoothGattInterface::ServerObserver overrides
+ void RegisterServerCallback(
+ bluetooth::hal::BluetoothGattInterface* /* unused */,
+ int status, int server_if, const bt_uuid_t& uuid) override;
+ void ServiceAddedCallback(
+ bluetooth::hal::BluetoothGattInterface* /* unused */,
+ int status, int server_if, const btgatt_srvc_id_t& srvc_id,
+ int srvc_handle) override;
+ void CharacteristicAddedCallback(
+ bluetooth::hal::BluetoothGattInterface* /* unused */,
+ int status, int server_if, const bt_uuid_t& char_id,
+ int srvc_handle, int char_handle) override;
+ void DescriptorAddedCallback(
+ bluetooth::hal::BluetoothGattInterface* /* unused */,
+ int status, int server_if, const bt_uuid_t& descr_id,
+ int srvc_handle, int descr_handle) override;
+ void ServiceStartedCallback(
+ bluetooth::hal::BluetoothGattInterface* /* unused */,
+ int status, int server_if, int srvc_handle) override;
+ void ServiceStoppedCallback(
+ bluetooth::hal::BluetoothGattInterface* /* unused */,
+ int status, int server_if, int srvc_handle) override;
+ void ServiceDeletedCallback(
+ bluetooth::hal::BluetoothGattInterface* /* unused */,
+ int status, int server_if, int srvc_handle) override;
+
+ // Semaphores used to wait for specific callback execution. Each callback
+ // has its own semaphore associated with it
+ semaphore_t* register_client_callback_sem_;
+ semaphore_t* scan_result_callback_sem_;
+ semaphore_t* listen_callback_sem_;
+
+ semaphore_t* register_server_callback_sem_;
+ semaphore_t* service_added_callback_sem_;
+ semaphore_t* characteristic_added_callback_sem_;
+ semaphore_t* descriptor_added_callback_sem_;
+ semaphore_t* service_started_callback_sem_;
+ semaphore_t* service_stopped_callback_sem_;
+ semaphore_t* service_deleted_callback_sem_;
+
+ private:
+ // The gatt_client_interface that all the tests use to interact with the HAL
+ const btgatt_client_interface_t* gatt_client_interface_;
+
+ // The gatt_server_interface that all the tests use to interact with the HAL
+ const btgatt_server_interface_t* gatt_server_interface_;
+
+ // No mutex needed for these as the semaphores should ensure
+ // synchronous access
+
+ // An ID that is used as a handle for each gatt client.
+ int client_interface_id_;
+
+ // An ID that is used as a handle for each gatt server.
+ int server_interface_id_;
+
+ // A handle to the last used service.
+ int service_handle_;
+
+ // A handle to the last characteristic added.
+ int characteristic_handle_;
+
+ // A handle to the last descriptor added.
+ int descriptor_handle_;
+
+ // The status of the last callback. Is BT_STATUS_SUCCESS if no issues.
+ int status_;
+
+ DISALLOW_COPY_AND_ASSIGN(GattTest);
+};
+
+} // bttest
--- /dev/null
+/******************************************************************************
+ *
+ * Copyright (C) 2015 Google, Inc.
+ *
+ * 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 <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "gatt/gatt_test.h"
+
+#define DEFAULT_RANDOM_SEED 42
+
+namespace {
+
+static void create_random_uuid(bt_uuid_t *uuid, int seed) {
+ srand(seed < 0 ? time(NULL) : seed);
+ for (int i = 0; i < 16; ++i) {
+ uuid->uu[i] = (uint8_t) (rand() % 256);
+ }
+}
+
+} // namespace
+
+namespace bttest {
+
+TEST_F(GattTest, GattClientRegister) {
+ // Registers gatt client.
+ bt_uuid_t gatt_client_uuid;
+ create_random_uuid(&gatt_client_uuid, DEFAULT_RANDOM_SEED);
+ gatt_client_interface()->register_client(&gatt_client_uuid);
+ semaphore_wait(register_client_callback_sem_);
+ EXPECT_TRUE(status() == BT_STATUS_SUCCESS)
+ << "Error registering GATT client app callback.";
+
+ // Unregisters gatt client. No callback is expected.
+ gatt_client_interface()->unregister_client(client_interface_id());
+}
+
+TEST_F(GattTest, GattClientScanRemoteDevice) {
+ // Starts BLE scan. NB: This test assumes there is a BLE beacon advertising nearby.
+ gatt_client_interface()->scan(true);
+ semaphore_wait(scan_result_callback_sem_);
+
+ // Ends BLE scan. No callback is expected.
+ gatt_client_interface()->scan(false);
+}
+
+TEST_F(GattTest, GattClientAdvertise) {
+ // Registers a new client app.
+ bt_uuid_t gatt_client_uuid;
+ create_random_uuid(&gatt_client_uuid, DEFAULT_RANDOM_SEED);
+ gatt_client_interface()->register_client(&gatt_client_uuid);
+ semaphore_wait(register_client_callback_sem_);
+ EXPECT_TRUE(status() == BT_STATUS_SUCCESS)
+ << "Error registering GATT client app callback.";
+
+ // Starts advertising.
+ gatt_client_interface()->listen(client_interface_id(), true);
+ semaphore_wait(listen_callback_sem_);
+ EXPECT_TRUE(status() == BT_STATUS_SUCCESS)
+ << "Error starting BLE advertisement.";
+
+ // Stops advertising.
+ gatt_client_interface()->listen(client_interface_id(), false);
+ semaphore_wait(listen_callback_sem_);
+ EXPECT_TRUE(status() == BT_STATUS_SUCCESS)
+ << "Error stopping BLE advertisement.";
+
+ // Unregisters gatt server. No callback is expected.
+ gatt_client_interface()->unregister_client(client_interface_id());
+}
+
+TEST_F(GattTest, GattServerRegister) {
+ // Registers gatt server.
+ bt_uuid_t gatt_server_uuid;
+ create_random_uuid(&gatt_server_uuid, DEFAULT_RANDOM_SEED);
+ gatt_server_interface()->register_server(&gatt_server_uuid);
+ semaphore_wait(register_server_callback_sem_);
+ EXPECT_TRUE(status() == BT_STATUS_SUCCESS)
+ << "Error registering GATT server app callback.";
+
+ // Unregisters gatt server. No callback is expected.
+ gatt_server_interface()->unregister_server(server_interface_id());
+}
+
+TEST_F(GattTest, GattServerBuild) {
+ // Registers gatt server.
+ bt_uuid_t gatt_server_uuid;
+ create_random_uuid(&gatt_server_uuid, DEFAULT_RANDOM_SEED);
+ gatt_server_interface()->register_server(&gatt_server_uuid);
+ semaphore_wait(register_server_callback_sem_);
+ EXPECT_TRUE(status() == BT_STATUS_SUCCESS)
+ << "Error registering GATT server app callback.";
+
+ // Service UUID.
+ btgatt_srvc_id_t srvc_id;
+ srvc_id.id.inst_id = 0; // there is only one instance of this service.
+ srvc_id.is_primary = 1; // this service is primary.
+ create_random_uuid(&srvc_id.id.uuid, -1);
+
+ // Characteristics UUID.
+ bt_uuid_t char_uuid;
+ create_random_uuid(&char_uuid, -1);
+
+ // Descriptor UUID.
+ bt_uuid_t desc_uuid;
+ create_random_uuid(&desc_uuid, -1);
+
+ // Adds service.
+ int server_if = server_interface_id();
+ gatt_server_interface()->add_service(server_if, &srvc_id, 4 /* # handles */);
+ semaphore_wait(service_added_callback_sem_);
+ EXPECT_TRUE(status() == BT_STATUS_SUCCESS) << "Error adding service.";
+
+ // Adds characteristics.
+ int srvc_handle = service_handle();
+ gatt_server_interface()->add_characteristic(server_if, srvc_handle,
+ &char_uuid, 0x10 /* notification */, 0x01 /* read only */);
+ semaphore_wait(characteristic_added_callback_sem_);
+ EXPECT_TRUE(status() == BT_STATUS_SUCCESS)
+ << "Error adding characteristics.";
+
+ // Adds descriptor.
+ gatt_server_interface()->add_descriptor(server_if, srvc_handle,
+ &desc_uuid, 0x01);
+ semaphore_wait(descriptor_added_callback_sem_);
+ EXPECT_TRUE(status() == BT_STATUS_SUCCESS)
+ << "Error adding descriptor.";
+
+ // Starts server.
+ gatt_server_interface()->start_service(server_if, srvc_handle, 2 /*BREDR/LE*/);
+ semaphore_wait(service_started_callback_sem_);
+ EXPECT_TRUE(status() == BT_STATUS_SUCCESS) << "Error starting server.";
+
+ // Stops server.
+ gatt_server_interface()->stop_service(server_if, srvc_handle);
+ semaphore_wait(service_stopped_callback_sem_);
+ EXPECT_TRUE(status() == BT_STATUS_SUCCESS) << "Error stopping server.";
+
+ // Deletes service.
+ gatt_server_interface()->delete_service(server_if, srvc_handle);
+ semaphore_wait(service_deleted_callback_sem_);
+ EXPECT_TRUE(status() == BT_STATUS_SUCCESS) << "Error deleting service.";
+
+ // Unregisters gatt server. No callback is expected.
+ gatt_server_interface()->unregister_server(server_if);
+}
+
+} // bttest