// 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) {
: 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();
}
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);
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<bt_local_le_features_t*>(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);
// 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;
// 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<Observer> observers_;
PrintFieldAndValue("\tState", bluetooth::AdapterStateToString(
static_cast<bluetooth::AdapterState>(bt_iface->GetState())));
PrintFieldAndValue("\tName", bt_iface->GetName());
+ PrintFieldAndBoolValue("\tMulti-Adv. supported",
+ bt_iface->IsMultiAdvertisementSupported());
+}
+
+void HandleSupportsMultiAdv(IBluetooth* bt_iface, const vector<string>& args) {
+ CHECK_NO_ARGS(args);
+
+ bool status = bt_iface->IsMultiAdvertisementSupported();
+ PrintFieldAndBoolValue("Multi-advertisement support", status);
}
void HandleHelp(IBluetooth* bt_iface, const vector<string>& args);
{ "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" },
{},
};
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);
}
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;
const char IBluetooth::kBluetoothServiceName[] = "bluetooth-service";
// static
-android::sp<IBluetooth> IBluetooth::getClientInterface() {
+sp<IBluetooth> IBluetooth::getClientInterface() {
sp<IServiceManager> sm = defaultServiceManager();
if (!sm.get()) {
LOG(ERROR) << "Failed to obtain a handle to the default Service Manager";
UnregisterCallback(interface_cast<IBluetoothCallback>(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);
}
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
virtual void UnregisterCallback(
const android::sp<IBluetoothCallback>& callback) = 0;
+ virtual bool IsMultiAdvertisementSupported() = 0;
+
// TODO(armansito): Complete the API definition.
+
private:
DISALLOW_COPY_AND_ASSIGN(IBluetooth);
};
const android::Parcel& data,
android::Parcel* reply,
uint32_t flags = 0);
+
+ DISALLOW_COPY_AND_ASSIGN(BnBluetooth);
};
// The Binder client interface to IBluetooth.
bool Enable() override;
bool EnableNoAutoConnect() override;
bool Disable() override;
+
std::string GetAddress() override;
std::vector<bluetooth::UUID> GetUUIDs() override;
bool SetName(const std::string& name) override;
std::string GetName() override;
+
void RegisterCallback(
const android::sp<IBluetoothCallback>& callback) override;
void UnregisterCallback(
const android::sp<IBluetoothCallback>& callback) override;
+ bool IsMultiAdvertisementSupported() override;
+
private:
DISALLOW_COPY_AND_ASSIGN(BpBluetooth);
};
callbacks_.Unregister(callback);
}
+bool BluetoothBinderServer::IsMultiAdvertisementSupported() {
+ VLOG(2) << __func__;
+ return adapter_->IsMultiAdvertisementSupported();
+}
+
void BluetoothBinderServer::OnAdapterStateChanged(
bluetooth::Adapter* adapter,
bluetooth::AdapterState prev_state,
void UnregisterCallback(
const android::sp<IBluetoothCallback>& callback) override;
+ bool IsMultiAdvertisementSupported() override;
+
// bluetooth::Adapter::Observer overrides:
void OnAdapterStateChanged(bluetooth::Adapter* adapter,
bluetooth::AdapterState prev_state,
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