wifi_data_provider_lacros.cc 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  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 "services/device/geolocation/wifi_data_provider_lacros.h"
  5. #include "base/bind.h"
  6. #include "base/logging.h"
  7. #include "base/time/time.h"
  8. #include "base/timer/timer.h"
  9. #include "chromeos/lacros/lacros_service.h"
  10. #include "services/device/geolocation/wifi_data_provider_handle.h"
  11. #include "services/device/geolocation/wifi_polling_policy.h"
  12. namespace device {
  13. namespace {
  14. // The time periods between successive polls of the wifi data.
  15. constexpr int kDefaultPollingIntervalMilliseconds = 10 * 1000;
  16. constexpr int kNoChangePollingIntervalMilliseconds = 2 * 60 * 1000;
  17. constexpr int kTwoNoChangePollingIntervalMilliseconds = 10 * 60 * 1000;
  18. constexpr int kNoWifiPollingIntervalMilliseconds = 20 * 1000;
  19. std::unique_ptr<WifiPollingPolicy> CreatePollingPolicy() {
  20. return std::make_unique<GenericWifiPollingPolicy<
  21. kDefaultPollingIntervalMilliseconds, kNoChangePollingIntervalMilliseconds,
  22. kTwoNoChangePollingIntervalMilliseconds,
  23. kNoWifiPollingIntervalMilliseconds>>();
  24. }
  25. void PopulateWifiData(
  26. const std::vector<crosapi::mojom::AccessPointDataPtr>& access_points,
  27. WifiData& wifi_data) {
  28. for (const auto& access_point : access_points) {
  29. AccessPointData ap_data;
  30. ap_data.mac_address = access_point->mac_address;
  31. ap_data.radio_signal_strength = access_point->radio_signal_strength;
  32. ap_data.channel = access_point->channel;
  33. ap_data.signal_to_noise = access_point->signal_to_noise;
  34. ap_data.ssid = access_point->ssid;
  35. wifi_data.access_point_data.insert(std::move(ap_data));
  36. }
  37. }
  38. // crosapi::GeolocationService is not available if either the LacrosService is
  39. // not available or if the current version of ash is not new enough to support
  40. // the GeolocationService.
  41. bool IsGeolocationServiceAvailable() {
  42. if (!chromeos::LacrosService::Get())
  43. return false;
  44. const int crosapiVersion =
  45. chromeos::LacrosService::Get()->GetInterfaceVersion(
  46. crosapi::mojom::Crosapi::Uuid_);
  47. const int minRequiredVersion = static_cast<int>(
  48. crosapi::mojom::Crosapi::kBindGeolocationServiceMinVersion);
  49. return crosapiVersion >= minRequiredVersion;
  50. }
  51. } // namespace
  52. WifiDataProviderLacros::WifiDataProviderLacros() = default;
  53. WifiDataProviderLacros::~WifiDataProviderLacros() = default;
  54. void WifiDataProviderLacros::StartDataProvider() {
  55. DCHECK(CalledOnClientThread());
  56. DCHECK(!started_);
  57. // Do not start the provider if the GeolocationService is not available.
  58. if (!IsGeolocationServiceAvailable()) {
  59. is_first_scan_complete_ = true;
  60. return;
  61. }
  62. if (!WifiPollingPolicy::IsInitialized())
  63. WifiPollingPolicy::Initialize(CreatePollingPolicy());
  64. DCHECK(WifiPollingPolicy::IsInitialized());
  65. started_ = true;
  66. int delay_interval_ms = WifiPollingPolicy::Get()->InitialInterval();
  67. ScheduleNextScan(delay_interval_ms);
  68. first_scan_delayed_ = (delay_interval_ms > 0);
  69. }
  70. void WifiDataProviderLacros::StopDataProvider() {
  71. DCHECK(CalledOnClientThread());
  72. if (started_) {
  73. wifi_scan_timer_.Stop();
  74. started_ = false;
  75. }
  76. }
  77. bool WifiDataProviderLacros::DelayedByPolicy() {
  78. DCHECK(CalledOnClientThread());
  79. return is_first_scan_complete_ ? true : first_scan_delayed_;
  80. }
  81. bool WifiDataProviderLacros::GetData(WifiData* data) {
  82. DCHECK(CalledOnClientThread());
  83. DCHECK(data);
  84. *data = wifi_data_;
  85. return is_first_scan_complete_;
  86. }
  87. // There is currently no reason to force a rescan on ChromeOS so this has not
  88. // been implemented.
  89. void WifiDataProviderLacros::ForceRescan() {}
  90. void WifiDataProviderLacros::DidWifiScanTaskForTesting(
  91. bool service_initialized,
  92. bool data_available,
  93. base::TimeDelta time_since_last_updated,
  94. std::vector<crosapi::mojom::AccessPointDataPtr> access_points) {
  95. DidWifiScanTask(service_initialized, data_available, time_since_last_updated,
  96. std::move(access_points));
  97. }
  98. void WifiDataProviderLacros::ScheduleNextScan(int interval_ms) {
  99. // Do not schedule a scan if the GeolocationService is not available or if not
  100. // `started_`. This could occur if DoWifiScanTask() is called back after the
  101. // provider has been stopped.
  102. if (!IsGeolocationServiceAvailable() || !started_)
  103. return;
  104. base::TimeDelta interval = base::Milliseconds(interval_ms);
  105. if (!wifi_scan_timer_.IsRunning() ||
  106. interval < wifi_scan_timer_.GetCurrentDelay()) {
  107. wifi_scan_timer_.Start(
  108. FROM_HERE, interval,
  109. base::BindRepeating(&WifiDataProviderLacros::DoWifiScanTask,
  110. base::Unretained(this)));
  111. }
  112. }
  113. void WifiDataProviderLacros::DoWifiScanTask() {
  114. DCHECK(started_);
  115. DCHECK(IsGeolocationServiceAvailable());
  116. if (!geolocation_service_.is_bound()) {
  117. chromeos::LacrosService::Get()->BindGeolocationService(
  118. geolocation_service_.BindNewPipeAndPassReceiver());
  119. }
  120. geolocation_service_->GetWifiAccessPoints(base::BindOnce(
  121. &WifiDataProviderLacros::DidWifiScanTask, weak_factory_.GetWeakPtr()));
  122. }
  123. void WifiDataProviderLacros::DidWifiScanTask(
  124. bool service_initialized,
  125. bool data_available,
  126. base::TimeDelta time_since_last_updated,
  127. std::vector<crosapi::mojom::AccessPointDataPtr> access_points) {
  128. if (!service_initialized) {
  129. LOG(ERROR) << "DoWifiScanTask() called with uninitialized NetworkHandler";
  130. return;
  131. }
  132. // If the age is significantly longer than our long polling time, assume the
  133. // data is stale and trigger a faster update.
  134. const bool is_data_stale =
  135. time_since_last_updated >
  136. base::Milliseconds(kTwoNoChangePollingIntervalMilliseconds * 2);
  137. if (!data_available || is_data_stale) {
  138. ScheduleNextScan(WifiPollingPolicy::Get()->NoWifiInterval());
  139. return;
  140. }
  141. WifiData new_data;
  142. PopulateWifiData(access_points, new_data);
  143. const bool update_available = wifi_data_.DiffersSignificantly(new_data);
  144. wifi_data_ = new_data;
  145. WifiPollingPolicy::Get()->UpdatePollingInterval(update_available);
  146. ScheduleNextScan(WifiPollingPolicy::Get()->PollingInterval());
  147. if (update_available || !is_first_scan_complete_) {
  148. is_first_scan_complete_ = true;
  149. RunCallbacks();
  150. }
  151. }
  152. // static
  153. WifiDataProvider* WifiDataProviderHandle::DefaultFactoryFunction() {
  154. return new WifiDataProviderLacros();
  155. }
  156. } // namespace device