Chromium Code Reviews| Index: components/arc/bluetooth/arc_bluetooth_bridge.cc |
| diff --git a/components/arc/bluetooth/arc_bluetooth_bridge.cc b/components/arc/bluetooth/arc_bluetooth_bridge.cc |
| index ba97d46403beb9e2fa4d16031ccc4b4f58cca2d2..401fb48a76cdebf6d8b92d709a838cd7f59acd06 100644 |
| --- a/components/arc/bluetooth/arc_bluetooth_bridge.cc |
| +++ b/components/arc/bluetooth/arc_bluetooth_bridge.cc |
| @@ -56,6 +56,7 @@ constexpr int32_t kMinBtleVersion = 1; |
| constexpr int32_t kMinBtleNotifyVersion = 2; |
| constexpr int32_t kMinGattServerVersion = 3; |
| constexpr int32_t kMinAddrChangeVersion = 4; |
| +constexpr int32_t kMinMultiAdvertisementVersion = 5; |
| constexpr uint32_t kGattReadPermission = |
| BluetoothGattCharacteristic::Permission::PERMISSION_READ | |
| BluetoothGattCharacteristic::Permission::PERMISSION_READ_ENCRYPTED | |
| @@ -67,6 +68,7 @@ constexpr uint32_t kGattWritePermission = |
| BluetoothGattCharacteristic::Permission:: |
| PERMISSION_WRITE_ENCRYPTED_AUTHENTICATED; |
| constexpr int32_t kInvalidGattAttributeHandle = -1; |
| +constexpr int32_t kInvalidAdvertisementHandle = -1; |
| // Bluetooth Specification Version 4.2 Vol 3 Part F Section 3.2.2 |
| // An attribute handle of value 0xFFFF is known as the maximum attribute handle. |
| constexpr int32_t kMaxGattAttributeHandle = 0xFFFF; |
| @@ -76,7 +78,6 @@ constexpr int kMaxGattAttributeLength = 512; |
| // Copied from Android at system/bt/stack/btm/btm_ble_int.h |
| // https://goo.gl/k7PM6u |
| constexpr uint16_t kAndroidMBluetoothVersionNumber = 95; |
| -constexpr uint16_t kMaxAdvertisement = 5; |
| using GattStatusCallback = |
| base::Callback<void(arc::mojom::BluetoothGattStatus)>; |
| @@ -1392,6 +1393,150 @@ void ArcBluetoothBridge::SendIndication( |
| mojo::Array<uint8_t> value, |
| const SendIndicationCallback& callback) {} |
| +bool ArcBluetoothBridge::GetAdvertisementHandle(int32_t* adv_handle) { |
|
puthik_chromium
2016/08/19 23:43:24
I don't think advertisementHandle need to be in ra
|
| + for (int i = 0; i < kMaxAdvertisements; i++) { |
| + if (advertisements_.find(i) == advertisements_.end()) { |
| + *adv_handle = i; |
| + return true; |
| + } |
| + } |
| + return false; |
| +} |
| + |
| +void ArcBluetoothBridge::ReserveAdvertisementHandle( |
| + const ReserveAdvertisementHandleCallback& callback) { |
| + DCHECK(CalledOnValidThread()); |
| + if (!CheckBluetoothInstanceVersion(kMinMultiAdvertisementVersion)) { |
| + callback.Run(mojom::BluetoothGattStatus::GATT_FAILURE, |
| + kInvalidAdvertisementHandle); |
| + return; |
| + } |
| + |
| + // Find an empty advertisement slot. |
| + int32_t adv_handle; |
| + if (!GetAdvertisementHandle(&adv_handle)) { |
| + LOG(WARNING) << "Out of space for advertisement data"; |
| + callback.Run(mojom::BluetoothGattStatus::GATT_FAILURE, |
| + kInvalidAdvertisementHandle); |
| + return; |
| + } |
| + |
| + // We have a handle. Put an entry in the map to reserve it. |
| + advertisements_[adv_handle] = scoped_refptr<device::BluetoothAdvertisement>(); |
| + |
| + // The advertisement will be registered when we get the call |
| + // to SetAdvertisingData. For now, just return the adv_handle. |
| + callback.Run(mojom::BluetoothGattStatus::GATT_SUCCESS, adv_handle); |
| +} |
| + |
| +void ArcBluetoothBridge::BroadcastAdvertisement( |
| + int32_t adv_handle, |
| + mojom::BluetoothAdvertisementPtr advertisement, |
| + const BroadcastAdvertisementCallback& callback) { |
| + DCHECK(CalledOnValidThread()); |
| + if (!CheckBluetoothInstanceVersion(kMinMultiAdvertisementVersion)) { |
| + callback.Run(mojom::BluetoothGattStatus::GATT_FAILURE); |
| + return; |
| + } |
| + |
| + if (advertisements_.find(adv_handle) == advertisements_.end()) { |
| + callback.Run(mojom::BluetoothGattStatus::GATT_FAILURE); |
| + return; |
| + } |
| + |
| + auto adv_data = |
| + advertisement.To<std::unique_ptr<device::BluetoothAdvertisement::Data>>(); |
| + if (!adv_data) { |
| + callback.Run(mojom::BluetoothGattStatus::GATT_FAILURE); |
| + return; |
| + } |
| + |
| + if (!advertisements_[adv_handle]) { |
| + OnReadyToRegisterAdvertisement(callback, adv_handle, std::move(adv_data)); |
| + } |
| + |
| + advertisements_[adv_handle]->Unregister( |
| + base::Bind(&ArcBluetoothBridge::OnReadyToRegisterAdvertisement, |
| + weak_factory_.GetWeakPtr(), callback, adv_handle, |
| + base::Passed(std::move(adv_data))), |
| + base::Bind(&ArcBluetoothBridge::OnRegisterAdvertisementError, |
| + weak_factory_.GetWeakPtr(), callback, adv_handle)); |
| +} |
| + |
| +void ArcBluetoothBridge::ReleaseAdvertisementHandle( |
| + int32_t adv_handle, |
| + const ReleaseAdvertisementHandleCallback& callback) { |
| + DCHECK(CalledOnValidThread()); |
| + if (!CheckBluetoothInstanceVersion(kMinMultiAdvertisementVersion)) { |
| + callback.Run(mojom::BluetoothGattStatus::GATT_FAILURE); |
| + return; |
| + } |
| + |
| + if (advertisements_.find(adv_handle) == advertisements_.end()) { |
| + callback.Run(mojom::BluetoothGattStatus::GATT_FAILURE); |
| + return; |
| + } |
| + |
| + if (!advertisements_[adv_handle]) { |
| + advertisements_.erase(adv_handle); |
| + callback.Run(mojom::BluetoothGattStatus::GATT_SUCCESS); |
| + return; |
| + } |
| + |
| + advertisements_[adv_handle]->Unregister( |
| + base::Bind(&ArcBluetoothBridge::OnUnregisterAdvertisementDone, |
| + weak_factory_.GetWeakPtr(), callback, adv_handle), |
| + base::Bind(&ArcBluetoothBridge::OnUnregisterAdvertisementError, |
| + weak_factory_.GetWeakPtr(), callback, adv_handle)); |
| +} |
| + |
| +void ArcBluetoothBridge::OnReadyToRegisterAdvertisement( |
| + const BroadcastAdvertisementCallback& callback, |
| + int32_t adv_handle, |
| + std::unique_ptr<device::BluetoothAdvertisement::Data> data) { |
| + bluetooth_adapter_->RegisterAdvertisement( |
| + std::move(data), |
| + base::Bind(&ArcBluetoothBridge::OnRegisterAdvertisementDone, |
| + weak_factory_.GetWeakPtr(), callback, adv_handle), |
| + base::Bind(&ArcBluetoothBridge::OnRegisterAdvertisementError, |
| + weak_factory_.GetWeakPtr(), callback, adv_handle)); |
| +} |
| + |
| +void ArcBluetoothBridge::OnRegisterAdvertisementDone( |
| + const BroadcastAdvertisementCallback& callback, |
| + int32_t adv_handle, |
| + scoped_refptr<BluetoothAdvertisement> advertisement) { |
| + advertisements_[adv_handle] = advertisement; |
| + callback.Run(mojom::BluetoothGattStatus::GATT_SUCCESS); |
| +} |
| + |
| +void ArcBluetoothBridge::OnRegisterAdvertisementError( |
| + const BroadcastAdvertisementCallback& callback, |
| + int32_t adv_handle, |
| + BluetoothAdvertisement::ErrorCode error_code) { |
| + LOG(WARNING) << "Failed to register advertisement for handle " << adv_handle |
| + << ", error code = " << error_code; |
| + advertisements_[adv_handle] = nullptr; |
|
puthik_chromium
2016/08/19 23:43:24
Maybe advertisements_.erase(adv_handle);
Eric Caruso
2016/08/20 00:33:17
The comment on this method says it leaves the mapp
|
| + callback.Run(mojom::BluetoothGattStatus::GATT_FAILURE); |
| +} |
| + |
| +void ArcBluetoothBridge::OnUnregisterAdvertisementDone( |
| + const ReleaseAdvertisementHandleCallback& callback, |
| + int32_t adv_handle) { |
| + advertisements_.erase(adv_handle); |
| + callback.Run(mojom::BluetoothGattStatus::GATT_SUCCESS); |
| +} |
| + |
| +void ArcBluetoothBridge::OnUnregisterAdvertisementError( |
| + const ReleaseAdvertisementHandleCallback& callback, |
| + int32_t adv_handle, |
| + BluetoothAdvertisement::ErrorCode error_code) { |
| + LOG(ERROR) << "Failed to unregister advertisement for handle " << adv_handle |
| + << ", error code = " << error_code; |
| + advertisements_.erase(adv_handle); |
| + callback.Run(mojom::BluetoothGattStatus::GATT_FAILURE); |
| +} |
| + |
| void ArcBluetoothBridge::OnDiscoveryError() { |
| LOG(WARNING) << "failed to change discovery state"; |
| } |
| @@ -1596,7 +1741,7 @@ ArcBluetoothBridge::GetAdapterProperties( |
| mojom::BluetoothLocalLEFeatures::New(); |
| le_features->version_supported = kAndroidMBluetoothVersionNumber; |
| le_features->local_privacy_enabled = 0; |
| - le_features->max_adv_instance = kMaxAdvertisement; |
| + le_features->max_adv_instance = kMaxAdvertisements; |
| le_features->rpa_offload_supported = 0; |
| le_features->max_irk_list_size = 0; |
| le_features->max_adv_filter_supported = 0; |