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 3b8cf87ba4cd2e19c14df0cc88ef04ff501e8bc6..d3e7e6bf15471950ffe8876afbd7d5e488eaf903 100644 |
--- a/components/arc/bluetooth/arc_bluetooth_bridge.cc |
+++ b/components/arc/bluetooth/arc_bluetooth_bridge.cc |
@@ -69,6 +69,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; |
@@ -78,7 +79,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; |
// Bluetooth SDP Service Class ID List Attribute identifier |
constexpr uint16_t kServiceClassIDListAttributeID = 0x0001; |
// Timeout for Bluetooth Discovery (scan) |
@@ -1631,6 +1631,134 @@ void ArcBluetoothBridge::RemoveSdpRecord( |
base::Bind(&OnRemoveServiceRecordError, 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, |
+ std::unique_ptr<device::BluetoothAdvertisement::Data> advertisement, |
+ const BroadcastAdvertisementCallback& callback) { |
+ DCHECK(CalledOnValidThread()); |
+ if (advertisements_.find(adv_handle) == advertisements_.end()) { |
+ callback.Run(mojom::BluetoothGattStatus::GATT_FAILURE); |
+ return; |
+ } |
+ |
+ if (!advertisements_[adv_handle]) { |
+ OnReadyToRegisterAdvertisement(callback, adv_handle, |
+ std::move(advertisement)); |
+ return; |
+ } |
+ |
+ advertisements_[adv_handle]->Unregister( |
+ base::Bind(&ArcBluetoothBridge::OnReadyToRegisterAdvertisement, |
+ weak_factory_.GetWeakPtr(), callback, adv_handle, |
+ base::Passed(std::move(advertisement))), |
+ 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) { |
+ DCHECK(CalledOnValidThread()); |
+ 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) { |
+ DCHECK(CalledOnValidThread()); |
+ 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) { |
+ DCHECK(CalledOnValidThread()); |
+ 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) { |
+ DCHECK(CalledOnValidThread()); |
+ advertisements_.erase(adv_handle); |
+ callback.Run(mojom::BluetoothGattStatus::GATT_SUCCESS); |
+} |
+ |
+void ArcBluetoothBridge::OnUnregisterAdvertisementError( |
+ const ReleaseAdvertisementHandleCallback& callback, |
+ int32_t adv_handle, |
+ BluetoothAdvertisement::ErrorCode error_code) { |
+ DCHECK(CalledOnValidThread()); |
+ 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"; |
} |
@@ -1845,7 +1973,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; |