// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef DEVICE_GEOLOCATION_WIFI_POLLING_POLICY_H_ #define DEVICE_GEOLOCATION_WIFI_POLLING_POLICY_H_ #include #include "base/macros.h" #include "base/time/time.h" #include "device/geolocation/geolocation_export.h" namespace device { // Allows sharing and mocking of the update polling policy function. class DEVICE_GEOLOCATION_EXPORT WifiPollingPolicy { public: virtual ~WifiPollingPolicy() = default; // Methods for managing the single instance of WifiPollingPolicy. The WiFi // policy is global so it can outlive the WifiDataProvider instance, which is // shut down and destroyed when no WiFi scanning is active. static void Initialize(std::unique_ptr); static void Shutdown(); static WifiPollingPolicy* Get(); static bool IsInitialized(); // Calculates the new polling interval for wifi scans, given the previous // interval and whether the last scan produced new results. virtual void UpdatePollingInterval(bool scan_results_differ) = 0; // Use InitialInterval to schedule the initial scan when the wifi data // provider is first started. Returns the number of milliseconds before the // initial scan should be performed. May return zero if the policy allows a // scan to be performed immediately. virtual int InitialInterval() = 0; // Use PollingInterval to schedule a new scan after the previous scan results // are available. Only use PollingInterval if WLAN hardware is available and // can perform scans for nearby access points. If the current interval is // complete, PollingInterval returns the duration for a new interval starting // at the current time. virtual int PollingInterval() = 0; // Use NoWifiInterval to schedule a new scan after the previous scan results // are available. NoWifiInterval is typically shorter than PollingInterval // and should not be used if wifi scanning is available in order to conserve // power. If the current interval is complete, NoWifiInterval returns the // duration for a new interval starting at the current time. virtual int NoWifiInterval() = 0; protected: WifiPollingPolicy() = default; private: DISALLOW_COPY_AND_ASSIGN(WifiPollingPolicy); }; // Generic polling policy, constants are compile-time parameterized to allow // tuning on a per-platform basis. template class GenericWifiPollingPolicy : public WifiPollingPolicy { public: GenericWifiPollingPolicy() = default; // WifiPollingPolicy void UpdatePollingInterval(bool scan_results_differ) override { if (scan_results_differ) { polling_interval_ = DEFAULT_INTERVAL; } else if (polling_interval_ == DEFAULT_INTERVAL) { polling_interval_ = NO_CHANGE_INTERVAL; } else { DCHECK(polling_interval_ == NO_CHANGE_INTERVAL || polling_interval_ == TWO_NO_CHANGE_INTERVAL); polling_interval_ = TWO_NO_CHANGE_INTERVAL; } } int InitialInterval() override { return ComputeInterval(polling_interval_); } int PollingInterval() override { int interval = ComputeInterval(polling_interval_); return interval <= 0 ? polling_interval_ : interval; } int NoWifiInterval() override { int interval = ComputeInterval(NO_WIFI_INTERVAL); return interval <= 0 ? NO_WIFI_INTERVAL : interval; } private: int ComputeInterval(int polling_interval) { base::Time now = base::Time::Now(); int64_t remaining_millis = 0; if (!interval_start_.is_null()) { // If the new interval duration differs from the initial duration, use the // shorter duration. if (polling_interval < interval_duration_) interval_duration_ = polling_interval; // Compute the remaining duration of the current interval. If the interval // is not yet complete, we will schedule a scan to occur once it is. base::TimeDelta remaining = interval_start_ + base::TimeDelta::FromMilliseconds(interval_duration_) - now; remaining_millis = remaining.InMilliseconds(); } // If the current interval is complete (or if this is our first scan), // start a new interval beginning now. if (remaining_millis <= 0) { interval_start_ = now; interval_duration_ = polling_interval; remaining_millis = 0; } return remaining_millis; } // The current duration of the polling interval. When wifi data is // substantially the same from one scan to the next, this may be increased to // reduce the frequency of wifi scanning. int polling_interval_ = DEFAULT_INTERVAL; // The start time for the most recent interval. Initialized to the "null" time // value. base::Time interval_start_; // Duration for the interval starting at |interval_start_|. int interval_duration_ = DEFAULT_INTERVAL; }; } // namespace device #endif // DEVICE_GEOLOCATION_WIFI_POLLING_POLICY_H_