message_stream_lookup_impl.cc 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. // Copyright 2021 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ash/quick_pair/message_stream/message_stream_lookup_impl.h"
  5. #include "ash/quick_pair/common/constants.h"
  6. #include "ash/quick_pair/common/fast_pair/fast_pair_metrics.h"
  7. #include "ash/quick_pair/common/logging.h"
  8. #include "base/containers/contains.h"
  9. #include "device/bluetooth/bluetooth_adapter_factory.h"
  10. #include "device/bluetooth/bluetooth_device.h"
  11. #include "device/bluetooth/bluetooth_socket.h"
  12. namespace {
  13. const device::BluetoothUUID kMessageStreamUuid(
  14. "df21fe2c-2515-4fdb-8886-f12c4d67927c");
  15. } // namespace
  16. namespace ash {
  17. namespace quick_pair {
  18. std::string MessageStreamLookupImpl::CreateMessageStreamAttemptTypeToString(
  19. const CreateMessageStreamAttemptType& type) {
  20. switch (type) {
  21. case CreateMessageStreamAttemptType::kDeviceConnectedStateChanged:
  22. return "[DeviceConnectedStateChanged]";
  23. case CreateMessageStreamAttemptType::kDeviceAdded:
  24. return "[DeviceAdded]";
  25. case CreateMessageStreamAttemptType::kDevicePairedChanged:
  26. return "[DevicePairedChanged]";
  27. case CreateMessageStreamAttemptType::kDeviceChanged:
  28. return "[DeviceChanged]";
  29. }
  30. NOTREACHED();
  31. return "";
  32. }
  33. MessageStreamLookupImpl::MessageStreamLookupImpl() {
  34. device::BluetoothAdapterFactory::Get()->GetAdapter(base::BindOnce(
  35. &MessageStreamLookupImpl::OnGetAdapter, weak_ptr_factory_.GetWeakPtr()));
  36. }
  37. void MessageStreamLookupImpl::OnGetAdapter(
  38. scoped_refptr<device::BluetoothAdapter> adapter) {
  39. adapter_ = adapter;
  40. adapter_observation_.Observe(adapter_.get());
  41. }
  42. void MessageStreamLookupImpl::AddObserver(
  43. MessageStreamLookup::Observer* observer) {
  44. observers_.AddObserver(observer);
  45. }
  46. void MessageStreamLookupImpl::RemoveObserver(
  47. MessageStreamLookup::Observer* observer) {
  48. observers_.RemoveObserver(observer);
  49. }
  50. MessageStreamLookupImpl::~MessageStreamLookupImpl() = default;
  51. MessageStream* MessageStreamLookupImpl::GetMessageStream(
  52. const std::string& device_address) {
  53. auto it = message_streams_.find(device_address);
  54. // If we don't have a MessageStream for the device at |device_address|, return
  55. // a nullptr.
  56. if (it == message_streams_.end())
  57. return nullptr;
  58. // Return the pointer underneath the unique_ptr to the MessageStream we are
  59. // owning for the device at |device_address|.
  60. return it->second.get();
  61. }
  62. void MessageStreamLookupImpl::DevicePairedChanged(
  63. device::BluetoothAdapter* adapter,
  64. device::BluetoothDevice* device,
  65. bool new_paired_status) {
  66. // Check to see if the device supports Message Streams.
  67. if (!device || !base::Contains(device->GetUUIDs(), kMessageStreamUuid))
  68. return;
  69. // Remove and delete the memory stream for the device, if it exists.
  70. if (!new_paired_status) {
  71. AttemptRemoveMessageStream(device->GetAddress());
  72. return;
  73. }
  74. QP_LOG(VERBOSE) << __func__
  75. << ": Attempting to create MessageStream for device = ["
  76. << device->GetAddress() << "]";
  77. AttemptCreateMessageStream(
  78. device, CreateMessageStreamAttemptType::kDevicePairedChanged);
  79. }
  80. void MessageStreamLookupImpl::DeviceConnectedStateChanged(
  81. device::BluetoothAdapter* adapter,
  82. device::BluetoothDevice* device,
  83. bool is_now_connected) {
  84. // Check to see if the device supports Message Streams.
  85. if (!device || !device->IsPaired() ||
  86. !base::Contains(device->GetUUIDs(), kMessageStreamUuid)) {
  87. return;
  88. }
  89. // Remove and delete the memory stream for the device, if it exists.
  90. if (!is_now_connected) {
  91. AttemptRemoveMessageStream(device->GetAddress());
  92. return;
  93. }
  94. QP_LOG(VERBOSE) << __func__
  95. << ": Attempting to create MessageStream for device = ["
  96. << device->GetAddress() << "]";
  97. AttemptCreateMessageStream(
  98. device, CreateMessageStreamAttemptType::kDeviceConnectedStateChanged);
  99. }
  100. void MessageStreamLookupImpl::DeviceChanged(device::BluetoothAdapter* adapter,
  101. device::BluetoothDevice* device) {
  102. // Check to see if the device is connected and supports MessageStreams. We
  103. // need to check if the device is both connected and paired to the adapter
  104. // because it is possible for a device to be connected to the adapter but not
  105. // paired (example: a request for the adapter's SDP records).
  106. if (!device || !(device->IsConnected() && device->IsPaired()) ||
  107. !base::Contains(device->GetUUIDs(), kMessageStreamUuid)) {
  108. return;
  109. }
  110. QP_LOG(VERBOSE) << __func__
  111. << ": found connected device. Attempting to create "
  112. "MessageStream for device = ["
  113. << device->GetAddress() << "]";
  114. AttemptCreateMessageStream(device,
  115. CreateMessageStreamAttemptType::kDeviceChanged);
  116. }
  117. void MessageStreamLookupImpl::DeviceAdded(device::BluetoothAdapter* adapter,
  118. device::BluetoothDevice* device) {
  119. // Check to see if the device is connected and supports MessageStreams. We
  120. // need to check if the device is both connected and paired to the adapter
  121. // because it is possible for a device to be connected to the adapter but not
  122. // paired (example: a request for the adapter's SDP records).
  123. if (!device || !(device->IsConnected() && device->IsPaired()) ||
  124. !base::Contains(device->GetUUIDs(), kMessageStreamUuid)) {
  125. return;
  126. }
  127. QP_LOG(VERBOSE) << __func__
  128. << ": found connected device. Attempting to create "
  129. "MessageStream for device = ["
  130. << device->GetAddress() << "]";
  131. AttemptCreateMessageStream(device,
  132. CreateMessageStreamAttemptType::kDeviceAdded);
  133. }
  134. void MessageStreamLookupImpl::DeviceRemoved(device::BluetoothAdapter* adapter,
  135. device::BluetoothDevice* device) {
  136. if (!device)
  137. return;
  138. // Remove message stream if the device removed from the adapter has a
  139. // message stream and disconnect from socket if applicable. It isn't expected
  140. // to already have a MessageStream associated with it.
  141. AttemptEraseMessageStream(device->GetAddress());
  142. }
  143. void MessageStreamLookupImpl::AttemptRemoveMessageStream(
  144. const std::string& device_address) {
  145. QP_LOG(VERBOSE) << __func__ << ": device address = " << device_address;
  146. AttemptEraseMessageStream(device_address);
  147. }
  148. void MessageStreamLookupImpl::AttemptEraseMessageStream(
  149. const std::string& device_address) {
  150. // Remove map entry if it exists. It may not exist if it was failed to be
  151. // created due to a |ConnectToService| error.
  152. if (!base::Contains(message_streams_, device_address))
  153. return;
  154. // If the MessageStream still exists, we can attempt to gracefully disconnect
  155. // the socket before erasing (and therefore destructing) the MessageStream
  156. // instance.
  157. message_streams_[device_address]->Disconnect(
  158. base::BindOnce(&MessageStreamLookupImpl::OnSocketDisconnected,
  159. weak_ptr_factory_.GetWeakPtr(), device_address));
  160. }
  161. void MessageStreamLookupImpl::OnSocketDisconnected(
  162. const std::string& device_address) {
  163. message_streams_.erase(device_address);
  164. }
  165. void MessageStreamLookupImpl::AttemptCreateMessageStream(
  166. device::BluetoothDevice* device,
  167. const CreateMessageStreamAttemptType& type) {
  168. QP_LOG(VERBOSE) << __func__ << ": device address = " << device->GetAddress()
  169. << " type = " << CreateMessageStreamAttemptTypeToString(type);
  170. // Only open MessageStreams for new devices that don't already have a
  171. // MessageStream stored in the map. We can sometimes reach this point if
  172. // multiple BluetoothAdapter events fire for a device connected event, but
  173. // we need all of these BluetoothAdapter observation events to handle
  174. // different connection scenarios, and have coverage for different devices.
  175. const std::string& device_address = device->GetAddress();
  176. if (base::Contains(message_streams_, device->GetAddress())) {
  177. QP_LOG(VERBOSE) << "Message Stream exists already for device";
  178. return;
  179. }
  180. if (base::Contains(pending_connect_requests_, device->GetAddress())) {
  181. QP_LOG(VERBOSE) << __func__ << ": Ignoring due to matching pending request";
  182. return;
  183. }
  184. pending_connect_requests_.insert(device->GetAddress());
  185. device->ConnectToService(
  186. /*uuid=*/kMessageStreamUuid, /*callback=*/
  187. base::BindOnce(&MessageStreamLookupImpl::OnConnected,
  188. weak_ptr_factory_.GetWeakPtr(), device_address,
  189. base::TimeTicks::Now(), type),
  190. /*error_callback=*/
  191. base::BindOnce(&MessageStreamLookupImpl::OnConnectError,
  192. weak_ptr_factory_.GetWeakPtr(), device_address, type));
  193. }
  194. void MessageStreamLookupImpl::OnConnected(
  195. std::string device_address,
  196. base::TimeTicks connect_to_service_start_time,
  197. const CreateMessageStreamAttemptType& type,
  198. scoped_refptr<device::BluetoothSocket> socket) {
  199. QP_LOG(INFO) << __func__ << ": device = " << device_address
  200. << " Type = " << CreateMessageStreamAttemptTypeToString(type);
  201. RecordMessageStreamConnectToServiceResult(/*success=*/true);
  202. RecordMessageStreamConnectToServiceTime(base::TimeTicks::Now() -
  203. connect_to_service_start_time);
  204. std::unique_ptr<MessageStream> message_stream =
  205. std::make_unique<MessageStream>(device_address, std::move(socket));
  206. for (auto& observer : observers_)
  207. observer.OnMessageStreamConnected(device_address, message_stream.get());
  208. message_streams_[device_address] = std::move(message_stream);
  209. pending_connect_requests_.erase(device_address);
  210. }
  211. void MessageStreamLookupImpl::OnConnectError(
  212. std::string device_address,
  213. const CreateMessageStreamAttemptType& type,
  214. const std::string& error_message) {
  215. // Because we need to attempt to create MessageStreams at many different
  216. // iterations due to the variability of Bluetooth APIs, we can expect to
  217. // see errors here frequently, along with errors followed by a success.
  218. QP_LOG(INFO) << __func__ << ": Error = [ " << error_message
  219. << "]. Type = " << CreateMessageStreamAttemptTypeToString(type);
  220. RecordMessageStreamConnectToServiceResult(/*success=*/false);
  221. RecordMessageStreamConnectToServiceError(error_message);
  222. pending_connect_requests_.erase(device_address);
  223. }
  224. } // namespace quick_pair
  225. } // namespace ash