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 964f1986f31971bd6144b5708049f9f2f68fef93..47b82ed731960687bcf6279cb2633dda945f3db4 100644 |
| --- a/components/arc/bluetooth/arc_bluetooth_bridge.cc |
| +++ b/components/arc/bluetooth/arc_bluetooth_bridge.cc |
| @@ -67,6 +67,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 +77,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 +1392,137 @@ void ArcBluetoothBridge::SendIndication( |
| mojo::Array<uint8_t> value, |
| const SendIndicationCallback& callback) {} |
| +bool ArcBluetoothBridge::GetAdvertisementHandle(int32_t* adv_handle) { |
| + 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()); |
| + // 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] = nullptr; |
| + |
| + // 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 (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) { |
| + LOG(WARNING) << "Tried to broadcast malformed advertisement data for " |
| + << "handle " << adv_handle; |
| + callback.Run(mojom::BluetoothGattStatus::GATT_FAILURE); |
| + return; |
| + } |
| + |
| + if (!advertisements_[adv_handle]) { |
| + OnReadyToRegisterAdvertisement(callback, adv_handle, std::move(adv_data)); |
| + return; |
| + } |
| + |
| + 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 (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) { |
|
Luis Héctor Chávez
2016/08/31 16:58:46
Can you add DCHECK(CalledOnValidThread()); in this
|
| + 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] = std::move(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; |
| + 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(WARNING) << "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"; |
| } |
| @@ -1598,7 +1729,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; |