bluetooth_adapter_winrt.cc 53 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476
  1. // Copyright 2018 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 "device/bluetooth/bluetooth_adapter_winrt.h"
  5. #include <windows.foundation.collections.h>
  6. #include <windows.foundation.h>
  7. #include <windows.storage.streams.h>
  8. #include <wrl/event.h>
  9. #include <memory>
  10. #include <utility>
  11. #include <vector>
  12. #include "base/bind.h"
  13. #include "base/callback.h"
  14. #include "base/callback_helpers.h"
  15. #include "base/containers/contains.h"
  16. #include "base/containers/cxx20_erase.h"
  17. #include "base/containers/span.h"
  18. #include "base/logging.h"
  19. #include "base/memory/ptr_util.h"
  20. #include "base/memory/scoped_refptr.h"
  21. #include "base/scoped_native_library.h"
  22. #include "base/strings/string_number_conversions.h"
  23. #include "base/strings/string_piece.h"
  24. #include "base/strings/stringprintf.h"
  25. #include "base/strings/utf_string_conversions.h"
  26. #include "base/task/single_thread_task_runner.h"
  27. #include "base/task/task_traits.h"
  28. #include "base/task/thread_pool.h"
  29. #include "base/threading/thread_task_runner_handle.h"
  30. #include "base/win/com_init_util.h"
  31. #include "base/win/core_winrt_util.h"
  32. #include "base/win/post_async_results.h"
  33. #include "components/device_event_log/device_event_log.h"
  34. #include "device/bluetooth/bluetooth_advertisement_winrt.h"
  35. #include "device/bluetooth/bluetooth_device_winrt.h"
  36. #include "device/bluetooth/bluetooth_discovery_filter.h"
  37. #include "device/bluetooth/bluetooth_discovery_session_outcome.h"
  38. #include "device/bluetooth/event_utils_winrt.h"
  39. #include "device/bluetooth/public/cpp/bluetooth_address.h"
  40. namespace device {
  41. namespace {
  42. // In order to avoid a name clash with device::BluetoothAdapter we need this
  43. // auxiliary namespace.
  44. namespace uwp {
  45. using ABI::Windows::Devices::Bluetooth::BluetoothAdapter;
  46. } // namespace uwp
  47. using ABI::Windows::Devices::Bluetooth::BluetoothError;
  48. using ABI::Windows::Devices::Bluetooth::IBluetoothAdapter;
  49. using ABI::Windows::Devices::Bluetooth::IBluetoothAdapterStatics;
  50. using ABI::Windows::Devices::Bluetooth::IID_IBluetoothAdapterStatics;
  51. using ABI::Windows::Devices::Bluetooth::Advertisement::
  52. BluetoothLEAdvertisementDataSection;
  53. using ABI::Windows::Devices::Bluetooth::Advertisement::
  54. BluetoothLEAdvertisementFlags;
  55. using ABI::Windows::Devices::Bluetooth::Advertisement::
  56. BluetoothLEAdvertisementWatcherStatus;
  57. using ABI::Windows::Devices::Bluetooth::Advertisement::
  58. BluetoothLEAdvertisementWatcherStatus_Aborted;
  59. using ABI::Windows::Devices::Bluetooth::Advertisement::
  60. BluetoothLEManufacturerData;
  61. using ABI::Windows::Devices::Bluetooth::Advertisement::
  62. BluetoothLEScanningMode_Active;
  63. using ABI::Windows::Devices::Bluetooth::Advertisement::
  64. IBluetoothLEAdvertisement;
  65. using ABI::Windows::Devices::Bluetooth::Advertisement::
  66. IBluetoothLEAdvertisementDataSection;
  67. using ABI::Windows::Devices::Bluetooth::Advertisement::
  68. IBluetoothLEAdvertisementReceivedEventArgs;
  69. using ABI::Windows::Devices::Bluetooth::Advertisement::
  70. IBluetoothLEAdvertisementWatcher;
  71. using ABI::Windows::Devices::Bluetooth::Advertisement::
  72. IBluetoothLEManufacturerData;
  73. using ABI::Windows::Devices::Enumeration::DeviceInformation;
  74. using ABI::Windows::Devices::Enumeration::IDeviceInformation;
  75. using ABI::Windows::Devices::Enumeration::IDeviceInformationStatics;
  76. using ABI::Windows::Devices::Enumeration::IDeviceInformationUpdate;
  77. using ABI::Windows::Devices::Enumeration::IDeviceWatcher;
  78. using ABI::Windows::Devices::Enumeration::IID_IDeviceInformationStatics;
  79. using ABI::Windows::Devices::Radios::IID_IRadioStatics;
  80. using ABI::Windows::Devices::Radios::IRadio;
  81. using ABI::Windows::Devices::Radios::IRadioStatics;
  82. using ABI::Windows::Devices::Radios::Radio;
  83. using ABI::Windows::Devices::Radios::RadioAccessStatus;
  84. using ABI::Windows::Devices::Radios::RadioAccessStatus_Allowed;
  85. using ABI::Windows::Devices::Radios::RadioAccessStatus_DeniedBySystem;
  86. using ABI::Windows::Devices::Radios::RadioAccessStatus_DeniedByUser;
  87. using ABI::Windows::Devices::Radios::RadioAccessStatus_Unspecified;
  88. using ABI::Windows::Devices::Radios::RadioState;
  89. using ABI::Windows::Devices::Radios::RadioState_Off;
  90. using ABI::Windows::Devices::Radios::RadioState_On;
  91. using ABI::Windows::Devices::Radios::RadioState_Unknown;
  92. using ABI::Windows::Foundation::IAsyncOperation;
  93. using ABI::Windows::Foundation::IReference;
  94. using ABI::Windows::Foundation::Collections::IVector;
  95. using ABI::Windows::Foundation::Collections::IVectorView;
  96. using ABI::Windows::Storage::Streams::IBuffer;
  97. using ABI::Windows::Storage::Streams::IDataReader;
  98. using ABI::Windows::Storage::Streams::IDataReaderStatics;
  99. using Microsoft::WRL::Callback;
  100. using Microsoft::WRL::ComPtr;
  101. bool ResolveCoreWinRT() {
  102. return base::win::ResolveCoreWinRTDelayload() &&
  103. base::win::ScopedHString::ResolveCoreWinRTStringDelayload();
  104. }
  105. // Query string for powered Bluetooth radios. GUID Reference:
  106. // https://docs.microsoft.com/en-us/windows-hardware/drivers/install/guid-bthport-device-interface
  107. // TODO(https://crbug.com/821766): Consider adding WindowsCreateStringReference
  108. // to base::win::ScopedHString to avoid allocating memory for this string.
  109. constexpr wchar_t kPoweredRadiosAqsFilter[] =
  110. L"System.Devices.InterfaceClassGuid:=\"{0850302A-B344-4fda-9BE9-"
  111. L"90576B8D46F0}\" AND "
  112. L"System.Devices.InterfaceEnabled:=System.StructuredQueryType.Boolean#True";
  113. // Utility functions to pretty print enum values.
  114. constexpr const char* ToCString(RadioAccessStatus access_status) {
  115. switch (access_status) {
  116. case RadioAccessStatus_Unspecified:
  117. return "RadioAccessStatus::Unspecified";
  118. case RadioAccessStatus_Allowed:
  119. return "RadioAccessStatus::Allowed";
  120. case RadioAccessStatus_DeniedByUser:
  121. return "RadioAccessStatus::DeniedByUser";
  122. case RadioAccessStatus_DeniedBySystem:
  123. return "RadioAccessStatus::DeniedBySystem";
  124. }
  125. NOTREACHED();
  126. return "";
  127. }
  128. template <typename VectorView, typename T>
  129. bool ToStdVector(VectorView* view, std::vector<T>* vector) {
  130. unsigned size;
  131. HRESULT hr = view->get_Size(&size);
  132. if (FAILED(hr)) {
  133. BLUETOOTH_LOG(ERROR) << "get_Size() failed: "
  134. << logging::SystemErrorCodeToString(hr);
  135. return false;
  136. }
  137. vector->resize(size);
  138. for (size_t i = 0; i < size; ++i) {
  139. hr = view->GetAt(i, &(*vector)[i]);
  140. DCHECK(SUCCEEDED(hr)) << "GetAt(" << i << ") failed: "
  141. << logging::SystemErrorCodeToString(hr);
  142. }
  143. return true;
  144. }
  145. absl::optional<std::vector<uint8_t>> ExtractVector(IBuffer* buffer) {
  146. ComPtr<IDataReaderStatics> data_reader_statics;
  147. HRESULT hr = base::win::GetActivationFactory<
  148. IDataReaderStatics, RuntimeClass_Windows_Storage_Streams_DataReader>(
  149. &data_reader_statics);
  150. if (FAILED(hr)) {
  151. BLUETOOTH_LOG(ERROR)
  152. << "Getting DataReaderStatics Activation Factory failed: "
  153. << logging::SystemErrorCodeToString(hr);
  154. return absl::nullopt;
  155. }
  156. ComPtr<IDataReader> data_reader;
  157. hr = data_reader_statics->FromBuffer(buffer, &data_reader);
  158. if (FAILED(hr)) {
  159. BLUETOOTH_LOG(ERROR) << "FromBuffer() failed: "
  160. << logging::SystemErrorCodeToString(hr);
  161. return absl::nullopt;
  162. }
  163. uint32_t buffer_length;
  164. hr = buffer->get_Length(&buffer_length);
  165. if (FAILED(hr)) {
  166. BLUETOOTH_LOG(ERROR) << "get_Length() failed: "
  167. << logging::SystemErrorCodeToString(hr);
  168. return absl::nullopt;
  169. }
  170. std::vector<uint8_t> bytes(buffer_length);
  171. hr = data_reader->ReadBytes(buffer_length, bytes.data());
  172. if (FAILED(hr)) {
  173. BLUETOOTH_LOG(ERROR) << "ReadBytes() failed: "
  174. << logging::SystemErrorCodeToString(hr);
  175. return absl::nullopt;
  176. }
  177. return bytes;
  178. }
  179. absl::optional<uint8_t> ExtractFlags(IBluetoothLEAdvertisement* advertisement) {
  180. if (!advertisement)
  181. return absl::nullopt;
  182. ComPtr<IReference<BluetoothLEAdvertisementFlags>> flags_ref;
  183. HRESULT hr = advertisement->get_Flags(&flags_ref);
  184. if (FAILED(hr)) {
  185. BLUETOOTH_LOG(ERROR) << "get_Flags() failed: "
  186. << logging::SystemErrorCodeToString(hr);
  187. return absl::nullopt;
  188. }
  189. if (!flags_ref) {
  190. BLUETOOTH_LOG(DEBUG) << "No advertisement flags found.";
  191. return absl::nullopt;
  192. }
  193. BluetoothLEAdvertisementFlags flags;
  194. hr = flags_ref->get_Value(&flags);
  195. if (FAILED(hr)) {
  196. BLUETOOTH_LOG(ERROR) << "get_Value() failed: "
  197. << logging::SystemErrorCodeToString(hr);
  198. return absl::nullopt;
  199. }
  200. return flags;
  201. }
  202. BluetoothDevice::UUIDList ExtractAdvertisedUUIDs(
  203. IBluetoothLEAdvertisement* advertisement) {
  204. if (!advertisement)
  205. return {};
  206. ComPtr<IVector<GUID>> service_uuids;
  207. HRESULT hr = advertisement->get_ServiceUuids(&service_uuids);
  208. if (FAILED(hr)) {
  209. BLUETOOTH_LOG(ERROR) << "get_ServiceUuids() failed: "
  210. << logging::SystemErrorCodeToString(hr);
  211. return {};
  212. }
  213. std::vector<GUID> guids;
  214. if (!ToStdVector(service_uuids.Get(), &guids))
  215. return {};
  216. BluetoothDevice::UUIDList advertised_uuids;
  217. advertised_uuids.reserve(guids.size());
  218. for (const auto& guid : guids)
  219. advertised_uuids.emplace_back(guid);
  220. return advertised_uuids;
  221. }
  222. // This method populates service data for a particular sized UUID. Given the
  223. // lack of tailored platform APIs, we need to parse the raw advertisement data
  224. // sections ourselves. These data sections are effectively a list of blobs,
  225. // where each blob starts with the corresponding UUID in little endian order,
  226. // followed by the corresponding service data.
  227. void PopulateServiceData(
  228. BluetoothDevice::ServiceDataMap* service_data,
  229. const std::vector<ComPtr<IBluetoothLEAdvertisementDataSection>>&
  230. data_sections,
  231. size_t num_bytes_uuid) {
  232. for (const auto& data_section : data_sections) {
  233. ComPtr<IBuffer> buffer;
  234. HRESULT hr = data_section->get_Data(&buffer);
  235. if (FAILED(hr)) {
  236. BLUETOOTH_LOG(ERROR) << "get_Data() failed: "
  237. << logging::SystemErrorCodeToString(hr);
  238. continue;
  239. }
  240. auto bytes = ExtractVector(buffer.Get());
  241. if (!bytes)
  242. continue;
  243. auto bytes_span = base::make_span(*bytes);
  244. if (bytes_span.size() < num_bytes_uuid) {
  245. BLUETOOTH_LOG(ERROR) << "Buffer Length is too small: "
  246. << bytes_span.size() << " vs. " << num_bytes_uuid;
  247. continue;
  248. }
  249. auto uuid_span = bytes_span.first(num_bytes_uuid);
  250. // The UUID is specified in little endian format, thus we reverse the bytes
  251. // here.
  252. std::vector<uint8_t> uuid_bytes(uuid_span.rbegin(), uuid_span.rend());
  253. // HexEncode the bytes and add dashes as required.
  254. std::string uuid_str;
  255. for (char c : base::HexEncode(uuid_bytes.data(), uuid_bytes.size())) {
  256. const size_t size = uuid_str.size();
  257. if (size == 8 || size == 13 || size == 18 || size == 23)
  258. uuid_str.push_back('-');
  259. uuid_str.push_back(c);
  260. }
  261. auto service_data_span = bytes_span.subspan(num_bytes_uuid);
  262. auto result = service_data->emplace(
  263. BluetoothUUID(uuid_str), std::vector<uint8_t>(service_data_span.begin(),
  264. service_data_span.end()));
  265. // Check that an insertion happened.
  266. DCHECK(result.second);
  267. // Check that the inserted UUID is valid.
  268. DCHECK(result.first->first.IsValid());
  269. }
  270. }
  271. BluetoothDevice::ServiceDataMap ExtractServiceData(
  272. IBluetoothLEAdvertisement* advertisement) {
  273. BluetoothDevice::ServiceDataMap service_data;
  274. if (!advertisement)
  275. return service_data;
  276. static constexpr std::pair<uint8_t, size_t> kServiceDataTypesAndNumBits[] = {
  277. {BluetoothDeviceWinrt::k16BitServiceDataSection, 16},
  278. {BluetoothDeviceWinrt::k32BitServiceDataSection, 32},
  279. {BluetoothDeviceWinrt::k128BitServiceDataSection, 128},
  280. };
  281. for (const auto& data_type_and_num_bits : kServiceDataTypesAndNumBits) {
  282. ComPtr<IVectorView<BluetoothLEAdvertisementDataSection*>> data_sections;
  283. HRESULT hr = advertisement->GetSectionsByType(data_type_and_num_bits.first,
  284. &data_sections);
  285. if (FAILED(hr)) {
  286. BLUETOOTH_LOG(ERROR) << "GetSectionsByType() failed: "
  287. << logging::SystemErrorCodeToString(hr);
  288. continue;
  289. }
  290. std::vector<ComPtr<IBluetoothLEAdvertisementDataSection>> vector;
  291. if (!ToStdVector(data_sections.Get(), &vector))
  292. continue;
  293. PopulateServiceData(&service_data, vector,
  294. data_type_and_num_bits.second / 8);
  295. }
  296. return service_data;
  297. }
  298. BluetoothDevice::ManufacturerDataMap ExtractManufacturerData(
  299. IBluetoothLEAdvertisement* advertisement) {
  300. if (!advertisement)
  301. return {};
  302. ComPtr<IVector<BluetoothLEManufacturerData*>> manufacturer_data_ptr;
  303. HRESULT hr = advertisement->get_ManufacturerData(&manufacturer_data_ptr);
  304. if (FAILED(hr)) {
  305. BLUETOOTH_LOG(ERROR) << "GetManufacturerData() failed: "
  306. << logging::SystemErrorCodeToString(hr);
  307. return {};
  308. }
  309. std::vector<ComPtr<IBluetoothLEManufacturerData>> manufacturer_data;
  310. if (!ToStdVector(manufacturer_data_ptr.Get(), &manufacturer_data))
  311. return {};
  312. BluetoothDevice::ManufacturerDataMap manufacturer_data_map;
  313. for (const auto& manufacturer_datum : manufacturer_data) {
  314. uint16_t company_id;
  315. hr = manufacturer_datum->get_CompanyId(&company_id);
  316. if (FAILED(hr)) {
  317. BLUETOOTH_LOG(ERROR) << "get_CompanyId() failed: "
  318. << logging::SystemErrorCodeToString(hr);
  319. continue;
  320. }
  321. ComPtr<IBuffer> buffer;
  322. hr = manufacturer_datum->get_Data(&buffer);
  323. if (FAILED(hr)) {
  324. BLUETOOTH_LOG(ERROR) << "get_Data() failed: "
  325. << logging::SystemErrorCodeToString(hr);
  326. continue;
  327. }
  328. auto bytes = ExtractVector(buffer.Get());
  329. if (!bytes)
  330. continue;
  331. manufacturer_data_map.emplace(company_id, std::move(*bytes));
  332. }
  333. return manufacturer_data_map;
  334. }
  335. // Similarly to extracting the service data Windows does not provide a specific
  336. // API to extract the tx power. Thus we also parse the raw data sections here.
  337. // If present, we expect a single entry for tx power with a blob of size 1 byte.
  338. absl::optional<int8_t> ExtractTxPower(
  339. IBluetoothLEAdvertisement* advertisement) {
  340. if (!advertisement)
  341. return absl::nullopt;
  342. ComPtr<IVectorView<BluetoothLEAdvertisementDataSection*>> data_sections;
  343. HRESULT hr = advertisement->GetSectionsByType(
  344. BluetoothDeviceWinrt::kTxPowerLevelDataSection, &data_sections);
  345. if (FAILED(hr)) {
  346. BLUETOOTH_LOG(ERROR) << "GetSectionsByType() failed: "
  347. << logging::SystemErrorCodeToString(hr);
  348. return absl::nullopt;
  349. }
  350. std::vector<ComPtr<IBluetoothLEAdvertisementDataSection>> vector;
  351. if (!ToStdVector(data_sections.Get(), &vector) || vector.empty())
  352. return absl::nullopt;
  353. if (vector.size() != 1u) {
  354. BLUETOOTH_LOG(ERROR) << "Unexpected number of data sections: "
  355. << vector.size();
  356. return absl::nullopt;
  357. }
  358. ComPtr<IBuffer> buffer;
  359. hr = vector.front()->get_Data(&buffer);
  360. if (FAILED(hr)) {
  361. BLUETOOTH_LOG(ERROR) << "get_Data() failed: "
  362. << logging::SystemErrorCodeToString(hr);
  363. return absl::nullopt;
  364. }
  365. auto bytes = ExtractVector(buffer.Get());
  366. if (!bytes)
  367. return absl::nullopt;
  368. if (bytes->size() != 1) {
  369. BLUETOOTH_LOG(ERROR) << "Unexpected number of bytes: " << bytes->size();
  370. return absl::nullopt;
  371. }
  372. return bytes->front();
  373. }
  374. ComPtr<IBluetoothLEAdvertisement> GetAdvertisement(
  375. IBluetoothLEAdvertisementReceivedEventArgs* received) {
  376. ComPtr<IBluetoothLEAdvertisement> advertisement;
  377. HRESULT hr = received->get_Advertisement(&advertisement);
  378. if (FAILED(hr)) {
  379. BLUETOOTH_LOG(ERROR) << "get_Advertisement() failed: "
  380. << logging::SystemErrorCodeToString(hr);
  381. }
  382. return advertisement;
  383. }
  384. absl::optional<std::string> ExtractDeviceName(
  385. IBluetoothLEAdvertisement* advertisement) {
  386. if (!advertisement)
  387. return absl::nullopt;
  388. HSTRING local_name;
  389. HRESULT hr = advertisement->get_LocalName(&local_name);
  390. if (FAILED(hr)) {
  391. BLUETOOTH_LOG(ERROR) << "Getting Local Name failed: "
  392. << logging::SystemErrorCodeToString(hr);
  393. return absl::nullopt;
  394. }
  395. // Return early otherwise ScopedHString will create an empty string.
  396. if (!local_name)
  397. return absl::nullopt;
  398. return base::win::ScopedHString(local_name).GetAsUTF8();
  399. }
  400. RadioState GetState(IRadio* radio) {
  401. RadioState state;
  402. HRESULT hr = radio->get_State(&state);
  403. if (FAILED(hr)) {
  404. BLUETOOTH_LOG(ERROR) << "Getting Radio State failed: "
  405. << logging::SystemErrorCodeToString(hr);
  406. return RadioState_Unknown;
  407. }
  408. return state;
  409. }
  410. } // namespace
  411. std::string BluetoothAdapterWinrt::GetAddress() const {
  412. return address_;
  413. }
  414. std::string BluetoothAdapterWinrt::GetName() const {
  415. return name_;
  416. }
  417. void BluetoothAdapterWinrt::SetName(const std::string& name,
  418. base::OnceClosure callback,
  419. ErrorCallback error_callback) {
  420. NOTIMPLEMENTED();
  421. }
  422. bool BluetoothAdapterWinrt::IsInitialized() const {
  423. return is_initialized_;
  424. }
  425. bool BluetoothAdapterWinrt::IsPresent() const {
  426. // Obtaining the default adapter will fail if no physical adapter is present.
  427. // Thus a non-zero |adapter| implies that a physical adapter is present.
  428. return adapter_ != nullptr;
  429. }
  430. bool BluetoothAdapterWinrt::CanPower() const {
  431. return radio_ != nullptr && radio_access_allowed_;
  432. }
  433. bool BluetoothAdapterWinrt::IsPowered() const {
  434. // Due to an issue on WoW64 we might fail to obtain the radio in OnGetRadio().
  435. // This is why it can be null here.
  436. if (!radio_)
  437. return num_powered_radios_ != 0;
  438. return GetState(radio_.Get()) == RadioState_On;
  439. }
  440. bool BluetoothAdapterWinrt::IsPeripheralRoleSupported() const {
  441. if (!adapter_) {
  442. return false;
  443. }
  444. boolean supported = false;
  445. HRESULT hr = adapter_->get_IsPeripheralRoleSupported(&supported);
  446. if (FAILED(hr)) {
  447. BLUETOOTH_LOG(ERROR) << "Getting IsPeripheralRoleSupported failed: "
  448. << logging::SystemErrorCodeToString(hr);
  449. }
  450. return supported;
  451. }
  452. bool BluetoothAdapterWinrt::IsDiscoverable() const {
  453. NOTIMPLEMENTED();
  454. return false;
  455. }
  456. void BluetoothAdapterWinrt::SetDiscoverable(bool discoverable,
  457. base::OnceClosure callback,
  458. ErrorCallback error_callback) {
  459. NOTIMPLEMENTED();
  460. }
  461. bool BluetoothAdapterWinrt::IsDiscovering() const {
  462. return NumDiscoverySessions() > 0;
  463. }
  464. BluetoothAdapter::UUIDList BluetoothAdapterWinrt::GetUUIDs() const {
  465. NOTIMPLEMENTED();
  466. return UUIDList();
  467. }
  468. void BluetoothAdapterWinrt::CreateRfcommService(
  469. const BluetoothUUID& uuid,
  470. const ServiceOptions& options,
  471. CreateServiceCallback callback,
  472. CreateServiceErrorCallback error_callback) {
  473. NOTIMPLEMENTED();
  474. }
  475. void BluetoothAdapterWinrt::CreateL2capService(
  476. const BluetoothUUID& uuid,
  477. const ServiceOptions& options,
  478. CreateServiceCallback callback,
  479. CreateServiceErrorCallback error_callback) {
  480. NOTIMPLEMENTED();
  481. }
  482. void BluetoothAdapterWinrt::RegisterAdvertisement(
  483. std::unique_ptr<BluetoothAdvertisement::Data> advertisement_data,
  484. CreateAdvertisementCallback callback,
  485. AdvertisementErrorCallback error_callback) {
  486. auto advertisement = CreateAdvertisement();
  487. if (!advertisement->Initialize(std::move(advertisement_data))) {
  488. BLUETOOTH_LOG(ERROR) << "Failed to Initialize Advertisement.";
  489. ui_task_runner_->PostTask(
  490. FROM_HERE,
  491. base::BindOnce(std::move(error_callback),
  492. BluetoothAdvertisement::ERROR_STARTING_ADVERTISEMENT));
  493. return;
  494. }
  495. // In order to avoid |advertisement| holding a strong reference to itself, we
  496. // pass only a weak reference to the callbacks, and store a strong reference
  497. // in |pending_advertisements_|. When the callbacks are run, they will remove
  498. // the corresponding advertisement from the list of pending advertisements.
  499. advertisement->Register(
  500. base::BindOnce(&BluetoothAdapterWinrt::OnRegisterAdvertisement,
  501. weak_ptr_factory_.GetWeakPtr(),
  502. base::Unretained(advertisement.get()),
  503. std::move(callback)),
  504. base::BindOnce(&BluetoothAdapterWinrt::OnRegisterAdvertisementError,
  505. weak_ptr_factory_.GetWeakPtr(),
  506. base::Unretained(advertisement.get()),
  507. std::move(error_callback)));
  508. pending_advertisements_.push_back(std::move(advertisement));
  509. }
  510. std::vector<BluetoothAdvertisement*>
  511. BluetoothAdapterWinrt::GetPendingAdvertisementsForTesting() const {
  512. std::vector<BluetoothAdvertisement*> pending_advertisements;
  513. for (const auto& pending_advertisement : pending_advertisements_)
  514. pending_advertisements.push_back(pending_advertisement.get());
  515. return pending_advertisements;
  516. }
  517. BluetoothLocalGattService* BluetoothAdapterWinrt::GetGattService(
  518. const std::string& identifier) const {
  519. NOTIMPLEMENTED();
  520. return nullptr;
  521. }
  522. IRadio* BluetoothAdapterWinrt::GetRadioForTesting() {
  523. return radio_.Get();
  524. }
  525. IDeviceWatcher* BluetoothAdapterWinrt::GetPoweredRadioWatcherForTesting() {
  526. return powered_radio_watcher_.Get();
  527. }
  528. BluetoothAdapterWinrt::BluetoothAdapterWinrt() {
  529. ui_task_runner_ = base::ThreadTaskRunnerHandle::Get();
  530. }
  531. BluetoothAdapterWinrt::~BluetoothAdapterWinrt() {
  532. // Explicitly move |pending_advertisements_| into a local variable and clear
  533. // them out. Any remaining pending advertisement will attempt to remove itself
  534. // from |pending_advertisements_|, which would result in a double-free
  535. // otherwise.
  536. auto pending_advertisements = std::move(pending_advertisements_);
  537. pending_advertisements_.clear();
  538. if (radio_)
  539. TryRemoveRadioStateChangedHandler();
  540. if (powered_radio_watcher_) {
  541. TryRemovePoweredRadioEventHandlers();
  542. HRESULT hr = powered_radio_watcher_->Stop();
  543. if (FAILED(hr)) {
  544. BLUETOOTH_LOG(ERROR) << "Stopping powered radio watcher failed: "
  545. << logging::SystemErrorCodeToString(hr);
  546. }
  547. }
  548. }
  549. BluetoothAdapterWinrt::StaticsInterfaces::StaticsInterfaces(
  550. ComPtr<IAgileReference> adapter_statics_in,
  551. ComPtr<IAgileReference> device_information_statics_in,
  552. ComPtr<IAgileReference> radio_statics_in)
  553. : adapter_statics(std::move(adapter_statics_in)),
  554. device_information_statics(std::move(device_information_statics_in)),
  555. radio_statics(std::move(radio_statics_in)) {}
  556. BluetoothAdapterWinrt::StaticsInterfaces::StaticsInterfaces(
  557. const StaticsInterfaces& copy_from) = default;
  558. BluetoothAdapterWinrt::StaticsInterfaces::StaticsInterfaces() = default;
  559. BluetoothAdapterWinrt::StaticsInterfaces::~StaticsInterfaces() {}
  560. void BluetoothAdapterWinrt::Initialize(base::OnceClosure init_callback) {
  561. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  562. // Some of the initialization work requires loading libraries and should not
  563. // be run on the browser main thread.
  564. base::ThreadPool::PostTaskAndReplyWithResult(
  565. FROM_HERE,
  566. {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
  567. base::ThreadPolicy::MUST_USE_FOREGROUND},
  568. base::BindOnce(&BluetoothAdapterWinrt::PerformSlowInitTasks),
  569. base::BindOnce(&BluetoothAdapterWinrt::CompleteInitAgile,
  570. weak_ptr_factory_.GetWeakPtr(), std::move(init_callback)));
  571. }
  572. void BluetoothAdapterWinrt::InitForTests(
  573. base::OnceClosure init_callback,
  574. ComPtr<IBluetoothAdapterStatics> bluetooth_adapter_statics,
  575. ComPtr<IDeviceInformationStatics> device_information_statics,
  576. ComPtr<IRadioStatics> radio_statics) {
  577. if (!ResolveCoreWinRT()) {
  578. CompleteInit(std::move(init_callback), std::move(bluetooth_adapter_statics),
  579. std::move(device_information_statics),
  580. std::move(radio_statics));
  581. return;
  582. }
  583. auto statics = PerformSlowInitTasks();
  584. // This allows any passed in values (which would be fakes) to replace
  585. // the return values of PerformSlowInitTasks().
  586. if (!bluetooth_adapter_statics)
  587. statics.adapter_statics->Resolve(IID_IBluetoothAdapterStatics,
  588. &bluetooth_adapter_statics);
  589. if (!device_information_statics)
  590. statics.device_information_statics->Resolve(IID_IDeviceInformationStatics,
  591. &device_information_statics);
  592. if (!radio_statics)
  593. statics.radio_statics->Resolve(IID_IRadioStatics, &radio_statics);
  594. StaticsInterfaces agile_statics = GetAgileReferencesForStatics(
  595. std::move(bluetooth_adapter_statics),
  596. std::move(device_information_statics), std::move(radio_statics));
  597. CompleteInitAgile(std::move(init_callback), std::move(agile_statics));
  598. }
  599. // static
  600. BluetoothAdapterWinrt::StaticsInterfaces
  601. BluetoothAdapterWinrt::PerformSlowInitTasks() {
  602. base::win::AssertComApartmentType(base::win::ComApartmentType::MTA);
  603. if (!ResolveCoreWinRT())
  604. return BluetoothAdapterWinrt::StaticsInterfaces();
  605. ComPtr<IBluetoothAdapterStatics> adapter_statics;
  606. HRESULT hr = base::win::GetActivationFactory<
  607. IBluetoothAdapterStatics,
  608. RuntimeClass_Windows_Devices_Bluetooth_BluetoothAdapter>(
  609. &adapter_statics);
  610. if (FAILED(hr)) {
  611. BLUETOOTH_LOG(ERROR)
  612. << "GetBluetoothAdapterStaticsActivationFactory failed: "
  613. << logging::SystemErrorCodeToString(hr);
  614. return BluetoothAdapterWinrt::StaticsInterfaces();
  615. }
  616. ComPtr<IDeviceInformationStatics> device_information_statics;
  617. hr = base::win::GetActivationFactory<
  618. IDeviceInformationStatics,
  619. RuntimeClass_Windows_Devices_Enumeration_DeviceInformation>(
  620. &device_information_statics);
  621. if (FAILED(hr)) {
  622. BLUETOOTH_LOG(ERROR)
  623. << "GetDeviceInformationStaticsActivationFactory failed: "
  624. << logging::SystemErrorCodeToString(hr);
  625. return BluetoothAdapterWinrt::StaticsInterfaces();
  626. }
  627. ComPtr<IRadioStatics> radio_statics;
  628. hr = base::win::GetActivationFactory<
  629. IRadioStatics, RuntimeClass_Windows_Devices_Radios_Radio>(&radio_statics);
  630. if (FAILED(hr)) {
  631. BLUETOOTH_LOG(ERROR) << "GetRadioStaticsActivationFactory failed: "
  632. << logging::SystemErrorCodeToString(hr);
  633. return BluetoothAdapterWinrt::StaticsInterfaces();
  634. }
  635. return GetAgileReferencesForStatics(std::move(adapter_statics),
  636. std::move(device_information_statics),
  637. std::move(radio_statics));
  638. }
  639. // static
  640. BluetoothAdapterWinrt::StaticsInterfaces
  641. BluetoothAdapterWinrt::GetAgileReferencesForStatics(
  642. ComPtr<IBluetoothAdapterStatics> adapter_statics,
  643. ComPtr<IDeviceInformationStatics> device_information_statics,
  644. ComPtr<IRadioStatics> radio_statics) {
  645. base::ScopedNativeLibrary ole32_library(base::FilePath(L"Ole32.dll"));
  646. CHECK(ole32_library.is_valid());
  647. auto ro_get_agile_reference =
  648. reinterpret_cast<decltype(&::RoGetAgileReference)>(
  649. ole32_library.GetFunctionPointer("RoGetAgileReference"));
  650. CHECK(ro_get_agile_reference);
  651. ComPtr<IAgileReference> adapter_statics_agileref;
  652. HRESULT hr = ro_get_agile_reference(
  653. AGILEREFERENCE_DEFAULT,
  654. ABI::Windows::Devices::Bluetooth::IID_IBluetoothAdapterStatics,
  655. adapter_statics.Get(), &adapter_statics_agileref);
  656. if (FAILED(hr))
  657. return StaticsInterfaces();
  658. ComPtr<IAgileReference> device_information_statics_agileref;
  659. hr = ro_get_agile_reference(
  660. AGILEREFERENCE_DEFAULT,
  661. ABI::Windows::Devices::Enumeration::IID_IDeviceInformationStatics,
  662. device_information_statics.Get(), &device_information_statics_agileref);
  663. if (FAILED(hr))
  664. return StaticsInterfaces();
  665. ComPtr<IAgileReference> radio_statics_agileref;
  666. hr = ro_get_agile_reference(AGILEREFERENCE_DEFAULT,
  667. ABI::Windows::Devices::Radios::IID_IRadioStatics,
  668. radio_statics.Get(), &radio_statics_agileref);
  669. if (FAILED(hr))
  670. return StaticsInterfaces();
  671. return StaticsInterfaces(std::move(adapter_statics_agileref),
  672. std::move(device_information_statics_agileref),
  673. std::move(radio_statics_agileref));
  674. }
  675. void BluetoothAdapterWinrt::CompleteInitAgile(base::OnceClosure init_callback,
  676. StaticsInterfaces agile_statics) {
  677. if (!agile_statics.adapter_statics ||
  678. !agile_statics.device_information_statics ||
  679. !agile_statics.radio_statics) {
  680. CompleteInit(std::move(init_callback), nullptr, nullptr, nullptr);
  681. return;
  682. }
  683. ComPtr<IBluetoothAdapterStatics> bluetooth_adapter_statics;
  684. HRESULT hr = agile_statics.adapter_statics->Resolve(
  685. IID_IBluetoothAdapterStatics, &bluetooth_adapter_statics);
  686. DCHECK(SUCCEEDED(hr));
  687. ComPtr<IDeviceInformationStatics> device_information_statics;
  688. hr = agile_statics.device_information_statics->Resolve(
  689. IID_IDeviceInformationStatics, &device_information_statics);
  690. DCHECK(SUCCEEDED(hr));
  691. ComPtr<IRadioStatics> radio_statics;
  692. hr = agile_statics.radio_statics->Resolve(IID_IRadioStatics, &radio_statics);
  693. DCHECK(SUCCEEDED(hr));
  694. CompleteInit(std::move(init_callback), std::move(bluetooth_adapter_statics),
  695. std::move(device_information_statics), std::move(radio_statics));
  696. }
  697. void BluetoothAdapterWinrt::CompleteInit(
  698. base::OnceClosure init_callback,
  699. ComPtr<IBluetoothAdapterStatics> bluetooth_adapter_statics,
  700. ComPtr<IDeviceInformationStatics> device_information_statics,
  701. ComPtr<IRadioStatics> radio_statics) {
  702. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  703. // We are wrapping |init_callback| in a ScopedClosureRunner to ensure it gets
  704. // run no matter how the function exits. Furthermore, we set |is_initialized_|
  705. // to true if adapter is still active when the callback gets run.
  706. base::ScopedClosureRunner on_init(base::BindOnce(
  707. [](base::WeakPtr<BluetoothAdapterWinrt> adapter,
  708. base::OnceClosure init_callback) {
  709. if (adapter)
  710. adapter->is_initialized_ = true;
  711. std::move(init_callback).Run();
  712. },
  713. weak_ptr_factory_.GetWeakPtr(), std::move(init_callback)));
  714. bluetooth_adapter_statics_ = bluetooth_adapter_statics;
  715. device_information_statics_ = device_information_statics;
  716. radio_statics_ = radio_statics;
  717. if (!bluetooth_adapter_statics_ || !device_information_statics_ ||
  718. !radio_statics_) {
  719. return;
  720. }
  721. ComPtr<IAsyncOperation<uwp::BluetoothAdapter*>> get_default_adapter_op;
  722. HRESULT hr =
  723. bluetooth_adapter_statics_->GetDefaultAsync(&get_default_adapter_op);
  724. if (FAILED(hr)) {
  725. BLUETOOTH_LOG(ERROR) << "BluetoothAdapter::GetDefaultAsync failed: "
  726. << logging::SystemErrorCodeToString(hr);
  727. return;
  728. }
  729. hr = base::win::PostAsyncResults(
  730. std::move(get_default_adapter_op),
  731. base::BindOnce(&BluetoothAdapterWinrt::OnGetDefaultAdapter,
  732. weak_ptr_factory_.GetWeakPtr(), std::move(on_init)));
  733. if (FAILED(hr)) {
  734. BLUETOOTH_LOG(ERROR) << "PostAsyncResults failed: "
  735. << logging::SystemErrorCodeToString(hr);
  736. }
  737. }
  738. base::WeakPtr<BluetoothAdapter> BluetoothAdapterWinrt::GetWeakPtr() {
  739. return weak_ptr_factory_.GetWeakPtr();
  740. }
  741. bool BluetoothAdapterWinrt::SetPoweredImpl(bool powered) {
  742. // Due to an issue on WoW64 we might fail to obtain the radio in
  743. // OnGetRadio(). This is why it can be null here.
  744. if (!radio_)
  745. return false;
  746. const RadioState state = powered ? RadioState_On : RadioState_Off;
  747. ComPtr<IAsyncOperation<RadioAccessStatus>> set_state_op;
  748. HRESULT hr = radio_->SetStateAsync(state, &set_state_op);
  749. if (FAILED(hr)) {
  750. BLUETOOTH_LOG(ERROR) << "Radio::SetStateAsync failed: "
  751. << logging::SystemErrorCodeToString(hr);
  752. return false;
  753. }
  754. hr = base::win::PostAsyncResults(
  755. std::move(set_state_op),
  756. base::BindOnce(&BluetoothAdapterWinrt::OnSetRadioState,
  757. weak_ptr_factory_.GetWeakPtr()));
  758. if (FAILED(hr)) {
  759. BLUETOOTH_LOG(ERROR) << "PostAsyncResults failed: "
  760. << logging::SystemErrorCodeToString(hr);
  761. return false;
  762. }
  763. return true;
  764. }
  765. void BluetoothAdapterWinrt::UpdateFilter(
  766. std::unique_ptr<BluetoothDiscoveryFilter> discovery_filter,
  767. DiscoverySessionResultCallback callback) {
  768. ui_task_runner_->PostTask(
  769. FROM_HERE, base::BindOnce(std::move(callback), /*is_error=*/false,
  770. UMABluetoothDiscoverySessionOutcome::SUCCESS));
  771. }
  772. void BluetoothAdapterWinrt::StartScanWithFilter(
  773. std::unique_ptr<BluetoothDiscoveryFilter> discovery_filter,
  774. DiscoverySessionResultCallback callback) {
  775. // should only have 1 discovery session since we are just starting the scan
  776. // now
  777. DCHECK_EQ(NumDiscoverySessions(), 1);
  778. HRESULT hr = ActivateBluetoothAdvertisementLEWatcherInstance(
  779. &ble_advertisement_watcher_);
  780. if (FAILED(hr)) {
  781. BLUETOOTH_LOG(ERROR)
  782. << "ActivateBluetoothAdvertisementLEWatcherInstance failed: "
  783. << logging::SystemErrorCodeToString(hr);
  784. ui_task_runner_->PostTask(
  785. FROM_HERE,
  786. base::BindOnce(std::move(callback), /*is_error=*/true,
  787. UMABluetoothDiscoverySessionOutcome::UNKNOWN));
  788. return;
  789. }
  790. hr = ble_advertisement_watcher_->put_ScanningMode(
  791. BluetoothLEScanningMode_Active);
  792. if (FAILED(hr)) {
  793. BLUETOOTH_LOG(ERROR) << "Setting ScanningMode to Active failed: "
  794. << logging::SystemErrorCodeToString(hr);
  795. ui_task_runner_->PostTask(
  796. FROM_HERE,
  797. base::BindOnce(std::move(callback), /*is_error=*/true,
  798. UMABluetoothDiscoverySessionOutcome::UNKNOWN));
  799. return;
  800. }
  801. advertisement_received_token_ = AddTypedEventHandler(
  802. ble_advertisement_watcher_.Get(),
  803. &IBluetoothLEAdvertisementWatcher::add_Received,
  804. base::BindRepeating(&BluetoothAdapterWinrt::OnAdvertisementReceived,
  805. weak_ptr_factory_.GetWeakPtr()));
  806. if (!advertisement_received_token_) {
  807. ui_task_runner_->PostTask(
  808. FROM_HERE,
  809. base::BindOnce(std::move(callback), /*is_error=*/true,
  810. UMABluetoothDiscoverySessionOutcome::UNKNOWN));
  811. return;
  812. }
  813. advertisement_watcher_stopped_token_ = AddTypedEventHandler(
  814. ble_advertisement_watcher_.Get(),
  815. &IBluetoothLEAdvertisementWatcher::add_Stopped,
  816. base::BindRepeating(&BluetoothAdapterWinrt::OnAdvertisementWatcherStopped,
  817. weak_ptr_factory_.GetWeakPtr()));
  818. if (!advertisement_watcher_stopped_token_) {
  819. RemoveAdvertisementWatcherEventHandlers();
  820. ui_task_runner_->PostTask(
  821. FROM_HERE,
  822. base::BindOnce(std::move(callback), /*is_error=*/true,
  823. UMABluetoothDiscoverySessionOutcome::UNKNOWN));
  824. return;
  825. }
  826. hr = ble_advertisement_watcher_->Start();
  827. if (FAILED(hr)) {
  828. BLUETOOTH_LOG(ERROR) << "Starting the Advertisement Watcher failed: "
  829. << logging::SystemErrorCodeToString(hr);
  830. RemoveAdvertisementWatcherEventHandlers();
  831. ui_task_runner_->PostTask(
  832. FROM_HERE,
  833. base::BindOnce(std::move(callback), /*is_error=*/true,
  834. UMABluetoothDiscoverySessionOutcome::UNKNOWN));
  835. return;
  836. }
  837. BluetoothLEAdvertisementWatcherStatus watcher_status;
  838. hr = ble_advertisement_watcher_->get_Status(&watcher_status);
  839. if (FAILED(hr)) {
  840. BLUETOOTH_LOG(ERROR) << "Getting the Watcher Status failed: "
  841. << logging::SystemErrorCodeToString(hr);
  842. } else if (watcher_status == BluetoothLEAdvertisementWatcherStatus_Aborted) {
  843. BLUETOOTH_LOG(ERROR)
  844. << "Starting Advertisement Watcher failed, it is in the Aborted "
  845. "state.";
  846. RemoveAdvertisementWatcherEventHandlers();
  847. ui_task_runner_->PostTask(
  848. FROM_HERE,
  849. base::BindOnce(std::move(callback), /*is_error=*/true,
  850. UMABluetoothDiscoverySessionOutcome::UNKNOWN));
  851. return;
  852. }
  853. for (auto& observer : observers_) {
  854. observer.AdapterDiscoveringChanged(this, /*discovering=*/true);
  855. }
  856. ui_task_runner_->PostTask(
  857. FROM_HERE, base::BindOnce(std::move(callback), false,
  858. UMABluetoothDiscoverySessionOutcome::SUCCESS));
  859. }
  860. void BluetoothAdapterWinrt::StopScan(DiscoverySessionResultCallback callback) {
  861. DCHECK_EQ(NumDiscoverySessions(), 0);
  862. RemoveAdvertisementWatcherEventHandlers();
  863. HRESULT hr = ble_advertisement_watcher_->Stop();
  864. if (FAILED(hr)) {
  865. BLUETOOTH_LOG(ERROR) << "Stopped the Advertisement Watcher failed: "
  866. << logging::SystemErrorCodeToString(hr);
  867. ui_task_runner_->PostTask(
  868. FROM_HERE,
  869. base::BindOnce(std::move(callback), /*is_error=*/true,
  870. UMABluetoothDiscoverySessionOutcome::UNKNOWN));
  871. return;
  872. }
  873. for (auto& device : devices_) {
  874. device.second->ClearAdvertisementData();
  875. }
  876. for (auto& observer : observers_) {
  877. observer.AdapterDiscoveringChanged(this, /*discovering=*/false);
  878. }
  879. ble_advertisement_watcher_.Reset();
  880. ui_task_runner_->PostTask(
  881. FROM_HERE, base::BindOnce(std::move(callback), /*is_error=*/false,
  882. UMABluetoothDiscoverySessionOutcome::SUCCESS));
  883. }
  884. void BluetoothAdapterWinrt::RemovePairingDelegateInternal(
  885. BluetoothDevice::PairingDelegate* pairing_delegate) {
  886. NOTIMPLEMENTED();
  887. }
  888. HRESULT
  889. BluetoothAdapterWinrt::ActivateBluetoothAdvertisementLEWatcherInstance(
  890. IBluetoothLEAdvertisementWatcher** instance) const {
  891. auto watcher_hstring = base::win::ScopedHString::Create(
  892. RuntimeClass_Windows_Devices_Bluetooth_Advertisement_BluetoothLEAdvertisementWatcher);
  893. if (!watcher_hstring.is_valid())
  894. return E_FAIL;
  895. ComPtr<IInspectable> inspectable;
  896. HRESULT hr =
  897. base::win::RoActivateInstance(watcher_hstring.get(), &inspectable);
  898. if (FAILED(hr)) {
  899. BLUETOOTH_LOG(ERROR) << "RoActivateInstance failed: "
  900. << logging::SystemErrorCodeToString(hr);
  901. return hr;
  902. }
  903. ComPtr<IBluetoothLEAdvertisementWatcher> watcher;
  904. hr = inspectable.As(&watcher);
  905. if (FAILED(hr)) {
  906. BLUETOOTH_LOG(ERROR) << "As IBluetoothLEAdvertisementWatcher failed: "
  907. << logging::SystemErrorCodeToString(hr);
  908. return hr;
  909. }
  910. return watcher.CopyTo(instance);
  911. }
  912. scoped_refptr<BluetoothAdvertisementWinrt>
  913. BluetoothAdapterWinrt::CreateAdvertisement() const {
  914. return base::MakeRefCounted<BluetoothAdvertisementWinrt>();
  915. }
  916. std::unique_ptr<BluetoothDeviceWinrt> BluetoothAdapterWinrt::CreateDevice(
  917. uint64_t raw_address) {
  918. return std::make_unique<BluetoothDeviceWinrt>(this, raw_address);
  919. }
  920. void BluetoothAdapterWinrt::OnGetDefaultAdapter(
  921. base::ScopedClosureRunner on_init,
  922. ComPtr<IBluetoothAdapter> adapter) {
  923. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  924. if (!adapter) {
  925. BLUETOOTH_LOG(ERROR) << "Getting Default Adapter failed.";
  926. return;
  927. }
  928. adapter_ = std::move(adapter);
  929. uint64_t raw_address;
  930. HRESULT hr = adapter_->get_BluetoothAddress(&raw_address);
  931. if (FAILED(hr)) {
  932. BLUETOOTH_LOG(ERROR) << "Getting BluetoothAddress failed: "
  933. << logging::SystemErrorCodeToString(hr);
  934. return;
  935. }
  936. address_ =
  937. CanonicalizeBluetoothAddress(base::StringPrintf("%012llX", raw_address));
  938. DCHECK(!address_.empty());
  939. HSTRING device_id;
  940. hr = adapter_->get_DeviceId(&device_id);
  941. if (FAILED(hr)) {
  942. BLUETOOTH_LOG(ERROR) << "Getting DeviceId failed: "
  943. << logging::SystemErrorCodeToString(hr);
  944. return;
  945. }
  946. ComPtr<IAsyncOperation<DeviceInformation*>> create_from_id_op;
  947. hr = device_information_statics_->CreateFromIdAsync(device_id,
  948. &create_from_id_op);
  949. if (FAILED(hr)) {
  950. BLUETOOTH_LOG(ERROR) << "CreateFromIdAsync failed: "
  951. << logging::SystemErrorCodeToString(hr);
  952. return;
  953. }
  954. hr = base::win::PostAsyncResults(
  955. std::move(create_from_id_op),
  956. base::BindOnce(&BluetoothAdapterWinrt::OnCreateFromIdAsync,
  957. weak_ptr_factory_.GetWeakPtr(), std::move(on_init)));
  958. if (FAILED(hr)) {
  959. BLUETOOTH_LOG(ERROR) << "PostAsyncResults failed: "
  960. << logging::SystemErrorCodeToString(hr);
  961. }
  962. }
  963. void BluetoothAdapterWinrt::OnCreateFromIdAsync(
  964. base::ScopedClosureRunner on_init,
  965. ComPtr<IDeviceInformation> device_information) {
  966. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  967. if (!device_information) {
  968. BLUETOOTH_LOG(ERROR) << "Getting Device Information failed.";
  969. return;
  970. }
  971. HSTRING name;
  972. HRESULT hr = device_information->get_Name(&name);
  973. if (FAILED(hr)) {
  974. BLUETOOTH_LOG(ERROR) << "Getting Name failed: "
  975. << logging::SystemErrorCodeToString(hr);
  976. return;
  977. }
  978. name_ = base::win::ScopedHString(name).GetAsUTF8();
  979. ComPtr<IAsyncOperation<RadioAccessStatus>> request_access_op;
  980. hr = radio_statics_->RequestAccessAsync(&request_access_op);
  981. if (FAILED(hr)) {
  982. BLUETOOTH_LOG(ERROR) << "RequestAccessAsync failed: "
  983. << logging::SystemErrorCodeToString(hr);
  984. return;
  985. }
  986. hr = base::win::PostAsyncResults(
  987. std::move(request_access_op),
  988. base::BindOnce(&BluetoothAdapterWinrt::OnRequestRadioAccess,
  989. weak_ptr_factory_.GetWeakPtr(), std::move(on_init)));
  990. if (FAILED(hr)) {
  991. BLUETOOTH_LOG(ERROR) << "PostAsyncResults failed: "
  992. << logging::SystemErrorCodeToString(hr);
  993. }
  994. }
  995. void BluetoothAdapterWinrt::OnRequestRadioAccess(
  996. base::ScopedClosureRunner on_init,
  997. RadioAccessStatus access_status) {
  998. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  999. radio_access_allowed_ = access_status == RadioAccessStatus_Allowed;
  1000. if (!radio_access_allowed_) {
  1001. // This happens if "Allow apps to control device radios" is off in Privacy
  1002. // settings.
  1003. BLUETOOTH_LOG(ERROR) << "RequestRadioAccessAsync failed: "
  1004. << ToCString(access_status)
  1005. << "Will not be able to change radio power.";
  1006. }
  1007. ComPtr<IAsyncOperation<Radio*>> get_radio_op;
  1008. HRESULT hr = adapter_->GetRadioAsync(&get_radio_op);
  1009. if (FAILED(hr)) {
  1010. BLUETOOTH_LOG(ERROR) << "GetRadioAsync failed: "
  1011. << logging::SystemErrorCodeToString(hr);
  1012. return;
  1013. }
  1014. hr = base::win::PostAsyncResults(
  1015. std::move(get_radio_op),
  1016. base::BindOnce(&BluetoothAdapterWinrt::OnGetRadio,
  1017. weak_ptr_factory_.GetWeakPtr(), std::move(on_init)));
  1018. if (FAILED(hr)) {
  1019. BLUETOOTH_LOG(ERROR) << "PostAsyncResults failed: "
  1020. << logging::SystemErrorCodeToString(hr);
  1021. }
  1022. }
  1023. void BluetoothAdapterWinrt::OnGetRadio(base::ScopedClosureRunner on_init,
  1024. ComPtr<IRadio> radio) {
  1025. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  1026. if (radio) {
  1027. radio_ = std::move(radio);
  1028. radio_was_powered_ = GetState(radio_.Get()) == RadioState_On;
  1029. radio_state_changed_token_ = AddTypedEventHandler(
  1030. radio_.Get(), &IRadio::add_StateChanged,
  1031. base::BindRepeating(&BluetoothAdapterWinrt::OnRadioStateChanged,
  1032. weak_ptr_factory_.GetWeakPtr()));
  1033. if (!radio_state_changed_token_)
  1034. BLUETOOTH_LOG(ERROR) << "Adding Radio State Changed Handler failed.";
  1035. return;
  1036. }
  1037. // This happens within WoW64, due to an issue with non-native APIs.
  1038. BLUETOOTH_LOG(ERROR)
  1039. << "Getting Radio failed. Chrome will be unable to change the power "
  1040. "state by itself.";
  1041. // Attempt to create a DeviceWatcher for powered radios, so that querying
  1042. // the power state is still possible.
  1043. auto aqs_filter = base::win::ScopedHString::Create(kPoweredRadiosAqsFilter);
  1044. HRESULT hr = device_information_statics_->CreateWatcherAqsFilter(
  1045. aqs_filter.get(), &powered_radio_watcher_);
  1046. if (FAILED(hr)) {
  1047. BLUETOOTH_LOG(ERROR) << "Creating Powered Radios Watcher failed: "
  1048. << logging::SystemErrorCodeToString(hr);
  1049. return;
  1050. }
  1051. powered_radio_added_token_ = AddTypedEventHandler(
  1052. powered_radio_watcher_.Get(), &IDeviceWatcher::add_Added,
  1053. base::BindRepeating(&BluetoothAdapterWinrt::OnPoweredRadioAdded,
  1054. weak_ptr_factory_.GetWeakPtr()));
  1055. powered_radio_removed_token_ = AddTypedEventHandler(
  1056. powered_radio_watcher_.Get(), &IDeviceWatcher::add_Removed,
  1057. base::BindRepeating(&BluetoothAdapterWinrt::OnPoweredRadioRemoved,
  1058. weak_ptr_factory_.GetWeakPtr()));
  1059. powered_radios_enumerated_token_ = AddTypedEventHandler(
  1060. powered_radio_watcher_.Get(), &IDeviceWatcher::add_EnumerationCompleted,
  1061. base::BindRepeating(&BluetoothAdapterWinrt::OnPoweredRadiosEnumerated,
  1062. weak_ptr_factory_.GetWeakPtr()));
  1063. if (!powered_radio_added_token_ || !powered_radio_removed_token_ ||
  1064. !powered_radios_enumerated_token_) {
  1065. BLUETOOTH_LOG(ERROR) << "Failed to Register Powered Radio Event Handlers.";
  1066. TryRemovePoweredRadioEventHandlers();
  1067. return;
  1068. }
  1069. hr = powered_radio_watcher_->Start();
  1070. if (FAILED(hr)) {
  1071. BLUETOOTH_LOG(ERROR) << "Starting the Powered Radio Watcher failed: "
  1072. << logging::SystemErrorCodeToString(hr);
  1073. TryRemovePoweredRadioEventHandlers();
  1074. return;
  1075. }
  1076. // Store the Closure Runner. It is expected that OnPoweredRadiosEnumerated()
  1077. // is invoked soon after.
  1078. on_init_ = std::make_unique<base::ScopedClosureRunner>(std::move(on_init));
  1079. }
  1080. void BluetoothAdapterWinrt::OnSetRadioState(RadioAccessStatus access_status) {
  1081. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  1082. if (access_status != RadioAccessStatus_Allowed) {
  1083. BLUETOOTH_LOG(ERROR) << "Got unexpected Radio Access Status: "
  1084. << ToCString(access_status);
  1085. RunPendingPowerCallbacks();
  1086. }
  1087. }
  1088. void BluetoothAdapterWinrt::OnRadioStateChanged(IRadio* radio,
  1089. IInspectable* object) {
  1090. DCHECK(radio_.Get() == radio);
  1091. RunPendingPowerCallbacks();
  1092. // Deduplicate StateChanged events, which can occur twice for a single
  1093. // power-on change.
  1094. const bool is_powered = GetState(radio) == RadioState_On;
  1095. if (radio_was_powered_ == is_powered) {
  1096. return;
  1097. }
  1098. radio_was_powered_ = is_powered;
  1099. NotifyAdapterPoweredChanged(is_powered);
  1100. }
  1101. void BluetoothAdapterWinrt::OnPoweredRadioAdded(IDeviceWatcher* watcher,
  1102. IDeviceInformation* info) {
  1103. if (++num_powered_radios_ == 1)
  1104. NotifyAdapterPoweredChanged(true);
  1105. BLUETOOTH_LOG(ERROR) << "OnPoweredRadioAdded(), Number of Powered Radios: "
  1106. << num_powered_radios_;
  1107. }
  1108. void BluetoothAdapterWinrt::OnPoweredRadioRemoved(
  1109. IDeviceWatcher* watcher,
  1110. IDeviceInformationUpdate* update) {
  1111. if (--num_powered_radios_ == 0)
  1112. NotifyAdapterPoweredChanged(false);
  1113. BLUETOOTH_LOG(ERROR) << "OnPoweredRadioRemoved(), Number of Powered Radios: "
  1114. << num_powered_radios_;
  1115. }
  1116. void BluetoothAdapterWinrt::OnPoweredRadiosEnumerated(IDeviceWatcher* watcher,
  1117. IInspectable* object) {
  1118. BLUETOOTH_LOG(ERROR)
  1119. << "OnPoweredRadiosEnumerated(), Number of Powered Radios: "
  1120. << num_powered_radios_;
  1121. // Destroy the ScopedClosureRunner, triggering the contained Closure to be
  1122. // run. Note this may destroy |this|.
  1123. DCHECK(on_init_);
  1124. on_init_.reset();
  1125. }
  1126. void BluetoothAdapterWinrt::OnAdvertisementReceived(
  1127. IBluetoothLEAdvertisementWatcher* watcher,
  1128. IBluetoothLEAdvertisementReceivedEventArgs* received) {
  1129. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  1130. uint64_t raw_bluetooth_address;
  1131. HRESULT hr = received->get_BluetoothAddress(&raw_bluetooth_address);
  1132. if (FAILED(hr)) {
  1133. BLUETOOTH_LOG(ERROR) << "get_BluetoothAddress() failed: "
  1134. << logging::SystemErrorCodeToString(hr);
  1135. return;
  1136. }
  1137. const std::string bluetooth_address =
  1138. BluetoothDeviceWinrt::CanonicalizeAddress(raw_bluetooth_address);
  1139. auto it = devices_.find(bluetooth_address);
  1140. const bool is_new_device = (it == devices_.end());
  1141. if (is_new_device) {
  1142. bool was_inserted = false;
  1143. std::tie(it, was_inserted) = devices_.emplace(
  1144. bluetooth_address, CreateDevice(raw_bluetooth_address));
  1145. DCHECK(was_inserted);
  1146. }
  1147. BluetoothDevice* const device = it->second.get();
  1148. int16_t rssi = 0;
  1149. hr = received->get_RawSignalStrengthInDBm(&rssi);
  1150. if (FAILED(hr)) {
  1151. BLUETOOTH_LOG(ERROR) << "get_RawSignalStrengthInDBm() failed: "
  1152. << logging::SystemErrorCodeToString(hr);
  1153. }
  1154. // Extract the remaining advertisement data.
  1155. ComPtr<IBluetoothLEAdvertisement> advertisement = GetAdvertisement(received);
  1156. absl::optional<std::string> device_name =
  1157. ExtractDeviceName(advertisement.Get());
  1158. absl::optional<int8_t> tx_power = ExtractTxPower(advertisement.Get());
  1159. BluetoothDevice::UUIDList advertised_uuids =
  1160. ExtractAdvertisedUUIDs(advertisement.Get());
  1161. BluetoothDevice::ServiceDataMap service_data_map =
  1162. ExtractServiceData(advertisement.Get());
  1163. BluetoothDevice::ManufacturerDataMap manufacturer_data_map =
  1164. ExtractManufacturerData(advertisement.Get());
  1165. static_cast<BluetoothDeviceWinrt*>(device)->UpdateLocalName(device_name);
  1166. device->UpdateAdvertisementData(rssi, ExtractFlags(advertisement.Get()),
  1167. advertised_uuids, tx_power, service_data_map,
  1168. manufacturer_data_map);
  1169. for (auto& observer : observers_) {
  1170. observer.DeviceAdvertisementReceived(
  1171. bluetooth_address, device->GetName(),
  1172. /*advertisement_name=*/device_name, rssi, tx_power,
  1173. device->GetAppearance(), advertised_uuids, service_data_map,
  1174. manufacturer_data_map);
  1175. is_new_device ? observer.DeviceAdded(this, device)
  1176. : observer.DeviceChanged(this, device);
  1177. }
  1178. }
  1179. void BluetoothAdapterWinrt::OnAdvertisementWatcherStopped(
  1180. ABI::Windows::Devices::Bluetooth::Advertisement::
  1181. IBluetoothLEAdvertisementWatcher* watcher,
  1182. ABI::Windows::Devices::Bluetooth::Advertisement::
  1183. IBluetoothLEAdvertisementWatcherStoppedEventArgs* args) {
  1184. BluetoothError error;
  1185. HRESULT hr = args->get_Error(&error);
  1186. if (FAILED(hr)) {
  1187. BLUETOOTH_LOG(ERROR) << "get_Error() failed: " << hr;
  1188. return;
  1189. }
  1190. BLUETOOTH_LOG(DEBUG) << "OnAdvertisementWatcherStopped() error=" << error;
  1191. MarkDiscoverySessionsAsInactive();
  1192. }
  1193. void BluetoothAdapterWinrt::OnRegisterAdvertisement(
  1194. BluetoothAdvertisement* advertisement,
  1195. CreateAdvertisementCallback callback) {
  1196. DCHECK(base::Contains(pending_advertisements_, advertisement));
  1197. auto wrapped_advertisement = base::WrapRefCounted(advertisement);
  1198. base::Erase(pending_advertisements_, advertisement);
  1199. std::move(callback).Run(std::move(wrapped_advertisement));
  1200. }
  1201. void BluetoothAdapterWinrt::OnRegisterAdvertisementError(
  1202. BluetoothAdvertisement* advertisement,
  1203. AdvertisementErrorCallback error_callback,
  1204. BluetoothAdvertisement::ErrorCode error_code) {
  1205. // Note: We are not DCHECKing that |pending_advertisements_| contains
  1206. // |advertisement|, as this method might be invoked during destruction.
  1207. base::Erase(pending_advertisements_, advertisement);
  1208. std::move(error_callback).Run(error_code);
  1209. }
  1210. void BluetoothAdapterWinrt::TryRemoveRadioStateChangedHandler() {
  1211. DCHECK(radio_);
  1212. if (!radio_state_changed_token_)
  1213. return;
  1214. HRESULT hr = radio_->remove_StateChanged(*radio_state_changed_token_);
  1215. if (FAILED(hr)) {
  1216. BLUETOOTH_LOG(ERROR) << "Removing Radio State Changed Handler failed: "
  1217. << logging::SystemErrorCodeToString(hr);
  1218. }
  1219. radio_state_changed_token_.reset();
  1220. }
  1221. void BluetoothAdapterWinrt::TryRemovePoweredRadioEventHandlers() {
  1222. DCHECK(powered_radio_watcher_);
  1223. if (powered_radio_added_token_) {
  1224. HRESULT hr =
  1225. powered_radio_watcher_->remove_Added(*powered_radio_removed_token_);
  1226. if (FAILED(hr)) {
  1227. BLUETOOTH_LOG(ERROR)
  1228. << "Removing the Powered Radio Added Handler failed: "
  1229. << logging::SystemErrorCodeToString(hr);
  1230. }
  1231. powered_radio_added_token_.reset();
  1232. }
  1233. if (powered_radio_removed_token_) {
  1234. HRESULT hr =
  1235. powered_radio_watcher_->remove_Removed(*powered_radio_removed_token_);
  1236. if (FAILED(hr)) {
  1237. BLUETOOTH_LOG(ERROR)
  1238. << "Removing the Powered Radio Removed Handler failed: "
  1239. << logging::SystemErrorCodeToString(hr);
  1240. }
  1241. powered_radio_removed_token_.reset();
  1242. }
  1243. if (powered_radios_enumerated_token_) {
  1244. HRESULT hr = powered_radio_watcher_->remove_EnumerationCompleted(
  1245. *powered_radios_enumerated_token_);
  1246. if (FAILED(hr)) {
  1247. BLUETOOTH_LOG(ERROR)
  1248. << "Removing the Powered Radios Enumerated Handler failed: "
  1249. << logging::SystemErrorCodeToString(hr);
  1250. }
  1251. powered_radios_enumerated_token_.reset();
  1252. }
  1253. }
  1254. void BluetoothAdapterWinrt::RemoveAdvertisementWatcherEventHandlers() {
  1255. DCHECK(ble_advertisement_watcher_);
  1256. if (advertisement_received_token_) {
  1257. HRESULT hr = ble_advertisement_watcher_->remove_Received(
  1258. *advertisement_received_token_);
  1259. if (FAILED(hr)) {
  1260. BLUETOOTH_LOG(ERROR) << "Removing the Received Handler failed: "
  1261. << logging::SystemErrorCodeToString(hr);
  1262. }
  1263. }
  1264. if (advertisement_watcher_stopped_token_) {
  1265. HRESULT hr = ble_advertisement_watcher_->remove_Stopped(
  1266. *advertisement_watcher_stopped_token_);
  1267. if (FAILED(hr)) {
  1268. BLUETOOTH_LOG(ERROR) << "Removing the Stopped Handler failed: "
  1269. << logging::SystemErrorCodeToString(hr);
  1270. }
  1271. }
  1272. }
  1273. } // namespace device