wifi_data_provider_chromeos.cc 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. // Copyright (c) 2012 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. // Provides wifi scan API binding for chromeos, using proprietary APIs.
  5. #include "services/device/geolocation/wifi_data_provider_chromeos.h"
  6. #include <stdint.h>
  7. #include "base/bind.h"
  8. #include "base/logging.h"
  9. #include "base/strings/utf_string_conversions.h"
  10. #include "chromeos/ash/components/network/geolocation_handler.h"
  11. #include "chromeos/ash/components/network/network_handler.h"
  12. #include "services/device/geolocation/wifi_data_provider_handle.h"
  13. using ::ash::NetworkHandler;
  14. namespace device {
  15. namespace {
  16. // The time periods between successive polls of the wifi data.
  17. const int kDefaultPollingIntervalMilliseconds = 10 * 1000; // 10s
  18. const int kNoChangePollingIntervalMilliseconds = 2 * 60 * 1000; // 2 mins
  19. const int kTwoNoChangePollingIntervalMilliseconds = 10 * 60 * 1000; // 10 mins
  20. const int kNoWifiPollingIntervalMilliseconds = 20 * 1000; // 20s
  21. } // namespace
  22. WifiDataProviderChromeOs::WifiDataProviderChromeOs() = default;
  23. WifiDataProviderChromeOs::~WifiDataProviderChromeOs() = default;
  24. void WifiDataProviderChromeOs::StartDataProvider() {
  25. DCHECK(CalledOnClientThread());
  26. if (!WifiPollingPolicy::IsInitialized())
  27. WifiPollingPolicy::Initialize(CreatePollingPolicy());
  28. DCHECK(WifiPollingPolicy::IsInitialized());
  29. ScheduleStart();
  30. }
  31. void WifiDataProviderChromeOs::StopDataProvider() {
  32. DCHECK(CalledOnClientThread());
  33. ScheduleStop();
  34. }
  35. bool WifiDataProviderChromeOs::DelayedByPolicy() {
  36. DCHECK(CalledOnClientThread());
  37. return is_first_scan_complete_ ? true : first_scan_delayed_;
  38. }
  39. bool WifiDataProviderChromeOs::GetData(WifiData* data) {
  40. DCHECK(CalledOnClientThread());
  41. DCHECK(data);
  42. *data = wifi_data_;
  43. return is_first_scan_complete_;
  44. }
  45. // There is currently no reason to force a rescan on ChromeOS so this has not
  46. // been implemented.
  47. void WifiDataProviderChromeOs::ForceRescan() {}
  48. std::unique_ptr<WifiPollingPolicy>
  49. WifiDataProviderChromeOs::CreatePollingPolicy() {
  50. return std::make_unique<GenericWifiPollingPolicy<
  51. kDefaultPollingIntervalMilliseconds, kNoChangePollingIntervalMilliseconds,
  52. kTwoNoChangePollingIntervalMilliseconds,
  53. kNoWifiPollingIntervalMilliseconds>>();
  54. }
  55. void WifiDataProviderChromeOs::DoWifiScanTaskOnNetworkHandlerThread() {
  56. // This method could be scheduled after a ScheduleStop.
  57. if (!started_)
  58. return;
  59. WifiData new_data;
  60. if (GetAccessPointData(&new_data.access_point_data)) {
  61. client_task_runner()->PostTask(
  62. FROM_HERE, base::BindOnce(&WifiDataProviderChromeOs::DidWifiScanTask,
  63. this, new_data));
  64. } else {
  65. client_task_runner()->PostTask(
  66. FROM_HERE,
  67. base::BindOnce(&WifiDataProviderChromeOs::DidWifiScanTaskNoResults,
  68. this));
  69. }
  70. }
  71. void WifiDataProviderChromeOs::DidWifiScanTaskNoResults() {
  72. DCHECK(CalledOnClientThread());
  73. // Schedule next scan if started (StopDataProvider could have been called
  74. // in between DoWifiScanTaskOnNetworkHandlerThread and this method).
  75. if (started_)
  76. ScheduleNextScan(WifiPollingPolicy::Get()->NoWifiInterval());
  77. }
  78. void WifiDataProviderChromeOs::DidWifiScanTask(const WifiData& new_data) {
  79. DCHECK(CalledOnClientThread());
  80. bool update_available = wifi_data_.DiffersSignificantly(new_data);
  81. wifi_data_ = new_data;
  82. // Schedule next scan if started (StopDataProvider could have been called
  83. // in between DoWifiScanTaskOnNetworkHandlerThread and this method).
  84. if (started_) {
  85. WifiPollingPolicy::Get()->UpdatePollingInterval(update_available);
  86. ScheduleNextScan(WifiPollingPolicy::Get()->PollingInterval());
  87. }
  88. if (update_available || !is_first_scan_complete_) {
  89. is_first_scan_complete_ = true;
  90. RunCallbacks();
  91. }
  92. }
  93. void WifiDataProviderChromeOs::ScheduleNextScan(int interval) {
  94. DCHECK(CalledOnClientThread());
  95. DCHECK(started_);
  96. if (!NetworkHandler::IsInitialized()) {
  97. LOG(ERROR) << "ScheduleNextScan called with uninitialized NetworkHandler";
  98. return;
  99. }
  100. NetworkHandler::Get()->task_runner()->PostDelayedTask(
  101. FROM_HERE,
  102. base::BindOnce(
  103. &WifiDataProviderChromeOs::DoWifiScanTaskOnNetworkHandlerThread,
  104. this),
  105. base::Milliseconds(interval));
  106. }
  107. void WifiDataProviderChromeOs::ScheduleStop() {
  108. DCHECK(CalledOnClientThread());
  109. DCHECK(started_);
  110. started_ = false;
  111. }
  112. void WifiDataProviderChromeOs::ScheduleStart() {
  113. DCHECK(CalledOnClientThread());
  114. DCHECK(!started_);
  115. if (!NetworkHandler::IsInitialized()) {
  116. LOG(ERROR) << "ScheduleStart called with uninitialized NetworkHandler";
  117. return;
  118. }
  119. started_ = true;
  120. int delay_interval = WifiPollingPolicy::Get()->InitialInterval();
  121. ScheduleNextScan(delay_interval);
  122. first_scan_delayed_ = (delay_interval > 0);
  123. }
  124. bool WifiDataProviderChromeOs::GetAccessPointData(
  125. WifiData::AccessPointDataSet* result) {
  126. // If in startup or shutdown, NetworkHandler is uninitialized.
  127. if (!NetworkHandler::IsInitialized())
  128. return false; // Data not ready.
  129. DCHECK(NetworkHandler::Get()->task_runner()->BelongsToCurrentThread());
  130. // If wifi isn't enabled, we've effectively completed the task.
  131. ash::GeolocationHandler* const geolocation_handler =
  132. NetworkHandler::Get()->geolocation_handler();
  133. if (!geolocation_handler || !geolocation_handler->wifi_enabled())
  134. return true; // Access point list is empty, no more data.
  135. ash::WifiAccessPointVector access_points;
  136. int64_t age_ms = 0;
  137. if (!geolocation_handler->GetWifiAccessPoints(&access_points, &age_ms))
  138. return false;
  139. for (const auto& access_point : access_points) {
  140. AccessPointData ap_data;
  141. ap_data.mac_address = base::ASCIIToUTF16(access_point.mac_address);
  142. ap_data.radio_signal_strength = access_point.signal_strength;
  143. ap_data.channel = access_point.channel;
  144. ap_data.signal_to_noise = access_point.signal_to_noise;
  145. ap_data.ssid = base::UTF8ToUTF16(access_point.ssid);
  146. result->insert(ap_data);
  147. }
  148. // If the age is significantly longer than our long polling time, assume the
  149. // data is stale and return false which will trigger a faster update.
  150. if (age_ms > kTwoNoChangePollingIntervalMilliseconds * 2)
  151. return false;
  152. return true;
  153. }
  154. // static
  155. WifiDataProvider* WifiDataProviderHandle::DefaultFactoryFunction() {
  156. return new WifiDataProviderChromeOs();
  157. }
  158. } // namespace device