From 10b54c4b7f1a863a27eca4158f256062ec9c3770 Mon Sep 17 00:00:00 2001 From: Arman Uguray Date: Fri, 21 Aug 2015 14:59:57 -0700 Subject: [PATCH] service: Implement IBluetooth.isMultiAdvertisementSupported() Added the Binder bindings, bluetoothtbd implementation, and new bluetooth-cli command for testing it. Bug: 23227962 Change-Id: I2de62e49e5d8b0bcc118ccb654d72fdd9f11f748 --- service/adapter.cpp | 26 ++++++++++++++++++++++++++ service/adapter.h | 9 +++++++++ service/client/main.cpp | 11 +++++++++++ service/hal/fake_bluetooth_interface.cpp | 10 ++++++++++ service/hal/fake_bluetooth_interface.h | 2 ++ service/ipc/binder/IBluetooth.cpp | 18 +++++++++++++++++- service/ipc/binder/IBluetooth.h | 9 +++++++++ service/ipc/binder/bluetooth_binder_server.cpp | 5 +++++ service/ipc/binder/bluetooth_binder_server.h | 2 ++ service/test/adapter_unittest.cpp | 15 +++++++++++++++ 10 files changed, 106 insertions(+), 1 deletion(-) diff --git a/service/adapter.cpp b/service/adapter.cpp index aba6c4c33..6e3fdd742 100644 --- a/service/adapter.cpp +++ b/service/adapter.cpp @@ -27,6 +27,15 @@ const char Adapter::kDefaultAddress[] = "00:00:00:00:00:00"; // static const char Adapter::kDefaultName[] = "not-initialized"; +// The minimum number of advertising instances required for multi-advertisement +// support. +// +// TODO(armansito): This number comes straight from +// packages/apps/Bluetooth/src/c/a/b/btservice/AdapterService.java. It would be +// nice to know if there were a way to obtain this number from the stack instead +// of hardcoding it here. +const char kMinAdvInstancesForMultiAdv = 5; + void Adapter::Observer::OnAdapterStateChanged(Adapter* adapter, AdapterState prev_state, AdapterState new_state) { @@ -37,6 +46,7 @@ Adapter::Adapter() : state_(ADAPTER_STATE_OFF), address_(kDefaultAddress), name_(kDefaultName) { + memset(&local_le_features_, 0, sizeof(local_le_features_)); hal::BluetoothInterface::Get()->AddObserver(this); hal::BluetoothInterface::Get()->GetHALInterface()->get_adapter_properties(); } @@ -145,6 +155,10 @@ std::string Adapter::GetAddress() const { return address_.Get(); } +bool Adapter::IsMultiAdvertisementSupported() const { + return local_le_features_.max_adv_instance >= kMinAdvInstancesForMultiAdv; +} + void Adapter::AdapterStateChangedCallback(bt_state_t state) { LOG(INFO) << "Adapter state changed: " << BtStateText(state); @@ -193,6 +207,18 @@ void Adapter::AdapterPropertiesCallback(bt_status_t status, name_.Set(name); break; } + case BT_PROPERTY_LOCAL_LE_FEATURES: { + if (property->len != sizeof(bt_local_le_features_t)) { + LOG(WARNING) << "Malformed value received for property: " + << "BT_PROPERTY_LOCAL_LE_FEATURES"; + break; + } + bt_local_le_features_t* features = + reinterpret_cast(property->val); + memcpy(&local_le_features_, features, sizeof(*features)); + LOG(INFO) << "Supported LE features updated"; + break; + } default: VLOG(1) << "Unhandled adapter property: " << BtPropertyText(property->type); diff --git a/service/adapter.h b/service/adapter.h index dc543fc85..dececd6fe 100644 --- a/service/adapter.h +++ b/service/adapter.h @@ -84,6 +84,10 @@ class Adapter : hal::BluetoothInterface::Observer { // Returns the local adapter addess in string form (XX:XX:XX:XX:XX:XX). std::string GetAddress() const; + // Returns true if the local adapter supports the Low-Energy + // multi-advertisement feature. + bool IsMultiAdvertisementSupported() const; + private: // hal::BluetoothInterface::Observer overrides. void AdapterStateChangedCallback(bt_state_t state) override; @@ -108,6 +112,11 @@ class Adapter : hal::BluetoothInterface::Observer { // The current local adapter name. util::AtomicString name_; + // The current set of supported LE features as obtained from the stack. The + // values here are all initially set to 0 and updated when the corresponding + // adapter property has been received from the stack. + bt_local_le_features_t local_le_features_; + // List of observers that are interested in notifications from us. std::mutex observers_lock_; base::ObserverList observers_; diff --git a/service/client/main.cpp b/service/client/main.cpp index d3cefa181..5a3816d61 100644 --- a/service/client/main.cpp +++ b/service/client/main.cpp @@ -170,6 +170,15 @@ void HandleAdapterInfo(IBluetooth* bt_iface, const vector& args) { PrintFieldAndValue("\tState", bluetooth::AdapterStateToString( static_cast(bt_iface->GetState()))); PrintFieldAndValue("\tName", bt_iface->GetName()); + PrintFieldAndBoolValue("\tMulti-Adv. supported", + bt_iface->IsMultiAdvertisementSupported()); +} + +void HandleSupportsMultiAdv(IBluetooth* bt_iface, const vector& args) { + CHECK_NO_ARGS(args); + + bool status = bt_iface->IsMultiAdvertisementSupported(); + PrintFieldAndBoolValue("Multi-advertisement support", status); } void HandleHelp(IBluetooth* bt_iface, const vector& args); @@ -189,6 +198,8 @@ struct { { "set-local-name", HandleSetLocalName, "\t\tSet the local adapter name" }, { "get-local-name", HandleGetLocalName, "\t\tGet the local adapter name" }, { "adapter-info", HandleAdapterInfo, "\t\tPrint adapter properties" }, + { "supports-multi-adv", HandleSupportsMultiAdv, + "\tWhether multi-advertisement is currently supported" }, {}, }; diff --git a/service/hal/fake_bluetooth_interface.cpp b/service/hal/fake_bluetooth_interface.cpp index fb4980a29..6a2309c7c 100644 --- a/service/hal/fake_bluetooth_interface.cpp +++ b/service/hal/fake_bluetooth_interface.cpp @@ -124,6 +124,16 @@ void FakeBluetoothInterface::NotifyAdapterAddressPropertyChanged( NotifyAdapterPropertiesChanged(1, &property); } +void FakeBluetoothInterface::NotifyAdapterLocalLeFeaturesPropertyChanged( + const bt_local_le_features_t* features) { + bt_property_t property; + property.len = sizeof(*features); + property.val = (void*)features; + property.type = BT_PROPERTY_LOCAL_LE_FEATURES; + + NotifyAdapterPropertiesChanged(1, &property); +} + void FakeBluetoothInterface::AddObserver(Observer* observer) { observers_.AddObserver(observer); } diff --git a/service/hal/fake_bluetooth_interface.h b/service/hal/fake_bluetooth_interface.h index 49f424d66..4297eb373 100644 --- a/service/hal/fake_bluetooth_interface.h +++ b/service/hal/fake_bluetooth_interface.h @@ -50,6 +50,8 @@ class FakeBluetoothInterface : public BluetoothInterface { bt_property_t* properties); void NotifyAdapterNamePropertyChanged(const std::string& name); void NotifyAdapterAddressPropertyChanged(const bt_bdaddr_t* address); + void NotifyAdapterLocalLeFeaturesPropertyChanged( + const bt_local_le_features_t* features); // hal::BluetoothInterface overrides: void AddObserver(Observer* observer) override; diff --git a/service/ipc/binder/IBluetooth.cpp b/service/ipc/binder/IBluetooth.cpp index dd9781ca2..e14dbcf33 100644 --- a/service/ipc/binder/IBluetooth.cpp +++ b/service/ipc/binder/IBluetooth.cpp @@ -35,7 +35,7 @@ namespace binder { const char IBluetooth::kBluetoothServiceName[] = "bluetooth-service"; // static -android::sp IBluetooth::getClientInterface() { +sp IBluetooth::getClientInterface() { sp sm = defaultServiceManager(); if (!sm.get()) { LOG(ERROR) << "Failed to obtain a handle to the default Service Manager"; @@ -121,6 +121,11 @@ android::status_t BnBluetooth::onTransact( UnregisterCallback(interface_cast(callback)); return android::NO_ERROR; } + case IS_MULTI_ADVERTISEMENT_SUPPORTED_TRANSACTION: { + bool result = IsMultiAdvertisementSupported(); + reply->writeInt32(result); + return android::NO_ERROR; + } default: return BBinder::onTransact(code, data, reply, flags); } @@ -231,6 +236,17 @@ void BpBluetooth::UnregisterCallback(const sp& callback) { remote()->transact(IBluetooth::UNREGISTER_CALLBACK_TRANSACTION, data, &reply); } +bool BpBluetooth::IsMultiAdvertisementSupported() { + Parcel data, reply; + + data.writeInterfaceToken(IBluetooth::getInterfaceDescriptor()); + + remote()->transact(IBluetooth::IS_MULTI_ADVERTISEMENT_SUPPORTED_TRANSACTION, + data, &reply); + + return reply.readInt32(); +} + IMPLEMENT_META_INTERFACE(Bluetooth, IBluetooth::kBluetoothServiceName); } // namespace binder diff --git a/service/ipc/binder/IBluetooth.h b/service/ipc/binder/IBluetooth.h index a40af70e2..6a2e32bc6 100644 --- a/service/ipc/binder/IBluetooth.h +++ b/service/ipc/binder/IBluetooth.h @@ -142,7 +142,10 @@ class IBluetooth : public android::IInterface { virtual void UnregisterCallback( const android::sp& callback) = 0; + virtual bool IsMultiAdvertisementSupported() = 0; + // TODO(armansito): Complete the API definition. + private: DISALLOW_COPY_AND_ASSIGN(IBluetooth); }; @@ -162,6 +165,8 @@ class BnBluetooth : public android::BnInterface { const android::Parcel& data, android::Parcel* reply, uint32_t flags = 0); + + DISALLOW_COPY_AND_ASSIGN(BnBluetooth); }; // The Binder client interface to IBluetooth. @@ -176,15 +181,19 @@ class BpBluetooth : public android::BpInterface { bool Enable() override; bool EnableNoAutoConnect() override; bool Disable() override; + std::string GetAddress() override; std::vector GetUUIDs() override; bool SetName(const std::string& name) override; std::string GetName() override; + void RegisterCallback( const android::sp& callback) override; void UnregisterCallback( const android::sp& callback) override; + bool IsMultiAdvertisementSupported() override; + private: DISALLOW_COPY_AND_ASSIGN(BpBluetooth); }; diff --git a/service/ipc/binder/bluetooth_binder_server.cpp b/service/ipc/binder/bluetooth_binder_server.cpp index 3a1631b9a..43568ee38 100644 --- a/service/ipc/binder/bluetooth_binder_server.cpp +++ b/service/ipc/binder/bluetooth_binder_server.cpp @@ -97,6 +97,11 @@ void BluetoothBinderServer::UnregisterCallback( callbacks_.Unregister(callback); } +bool BluetoothBinderServer::IsMultiAdvertisementSupported() { + VLOG(2) << __func__; + return adapter_->IsMultiAdvertisementSupported(); +} + void BluetoothBinderServer::OnAdapterStateChanged( bluetooth::Adapter* adapter, bluetooth::AdapterState prev_state, diff --git a/service/ipc/binder/bluetooth_binder_server.h b/service/ipc/binder/bluetooth_binder_server.h index cf0069e26..e6e708b27 100644 --- a/service/ipc/binder/bluetooth_binder_server.h +++ b/service/ipc/binder/bluetooth_binder_server.h @@ -54,6 +54,8 @@ class BluetoothBinderServer : public BnBluetooth, void UnregisterCallback( const android::sp& callback) override; + bool IsMultiAdvertisementSupported() override; + // bluetooth::Adapter::Observer overrides: void OnAdapterStateChanged(bluetooth::Adapter* adapter, bluetooth::AdapterState prev_state, diff --git a/service/test/adapter_unittest.cpp b/service/test/adapter_unittest.cpp index 09d2cfaaf..6d67d7e77 100644 --- a/service/test/adapter_unittest.cpp +++ b/service/test/adapter_unittest.cpp @@ -211,5 +211,20 @@ TEST_F(AdapterTest, GetAddress) { EXPECT_EQ(kTestAdapterAddressOutput, adapter_->GetAddress()); } +TEST_F(AdapterTest, IsMultiAdvertisementSupported) { + EXPECT_FALSE(adapter_->IsMultiAdvertisementSupported()); + + bt_local_le_features_t features; + memset(&features, 0, sizeof(features)); + + features.max_adv_instance = 10; // Some high number. + fake_hal_iface_->NotifyAdapterLocalLeFeaturesPropertyChanged(&features); + EXPECT_TRUE(adapter_->IsMultiAdvertisementSupported()); + + features.max_adv_instance = 0; // Low number. + fake_hal_iface_->NotifyAdapterLocalLeFeaturesPropertyChanged(&features); + EXPECT_FALSE(adapter_->IsMultiAdvertisementSupported()); +} + } // namespace } // namespace bluetooth -- 2.11.0