1//
2// Copyright (C) 2014 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//      http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
17#ifndef SHILL_WIFI_WAKE_ON_WIFI_H_
18#define SHILL_WIFI_WAKE_ON_WIFI_H_
19
20#include <linux/if_ether.h>
21#include <netinet/ip.h>
22#include <netinet/ip6.h>
23
24#include <set>
25#include <string>
26#include <utility>
27#include <vector>
28
29#include <base/cancelable_callback.h>
30#include <gtest/gtest_prod.h>  // for FRIEND_TEST
31#include <base/memory/ref_counted.h>
32#include <base/memory/weak_ptr.h>
33#include <components/timers/alarm_timer_chromeos.h>
34
35#include "shill/callbacks.h"
36#include "shill/ip_address_store.h"
37#include "shill/net/event_history.h"
38#include "shill/net/ip_address.h"
39#include "shill/net/netlink_manager.h"
40#include "shill/refptr_types.h"
41#include "shill/wifi/wifi.h"
42
43namespace shill {
44
45class ByteString;
46class Error;
47class EventDispatcher;
48class GetWakeOnPacketConnMessage;
49class Metrics;
50class Nl80211Message;
51class PropertyStore;
52class SetWakeOnPacketConnMessage;
53
54// |WakeOnWiFi| performs all wake on WiFi related tasks and logic (e.g.
55// suspend/dark resume/resume logic, NIC wowlan programming via nl80211), and
56// stores the state necessary to perform these actions.
57//
58// Shill implements two wake on WiFi features:
59//   1) Dark connect: this feature allows the CrOS device to maintain WiFi
60//      connectivity while suspended, and to wake from suspend in a low-power
61//      state (dark resume) to maintain or re-establish WiFi connectivity.
62//   2) Packet: this feature allows the CrOS device to wake from suspend upon
63//      receiving network packets from any whitelisted hosts.
64// Either or both of these features can be enabled/disabled by assigning the
65// appropriate value to |wake_on_wifi_features_enabled_|.
66//
67// Note that wake on WiFi features are different from wake on WiFi triggers. The
68// former refers to shill's suspend/resume/dark resume handling logic, whereas
69// the latter refers to the NIC's  ability to wake the CPU on certain network
70// events (e.g. disconnects). In order for shill's wake on WiFi features to
71// work, the platform must be compiled with wake on WiFi support (i.e.
72// DISABLE_WAKE_ON_WIFI not set), and its NIC must support the triggers required
73// for the features to work (see WakeOnWiFi::WakeOnWiFiPacketEnabledAndSupported
74// and WakeOnWiFi::WakeOnWiFiDarkConnectEnabledAndSupported for more details).
75//
76// The logic shill uses before, during (i.e. during dark resume), and after
77// suspend when both wake on WiFi features are enabled are described below:
78//
79// OnBeforeSuspend
80// ================
81// This function is run when Manager announces an upcoming system suspend.
82//
83//         +--------------+
84//         |          Yes |   +----------------+
85// +-------+--------+     +-->|Renew DHCP Lease|
86// |  Connected &   |         +------+---------+
87// |holding expiring|                |
88// |  DHCP lease?   |                v
89// +------+---------+         +--------------------+
90//        |               +-> |BeforeSuspendActions|
91//        |           No  |   +--------------------+
92//        +---------------+
93//
94// OnDarkResume
95// =============
96// This function is run when Manager announces that the system has entered
97// dark resume and that there is an upcoming system suspend.
98//
99// +-------------+      +------------+     Unsupported     +----------+
100// |  Too many   +----->|Wake reason?+-------------------->|Connected?|
101// |dark resumes?|  No  +-+----------+                     +-+-----+--+
102// +------+------+        |       |                          |     |
103//        | Yes           |       | Disconnect/           No |     | Yes
104//        v               |       |    SSID                  |     |
105// +-------------------+  |       v                          |     |
106// |  Disable Wake on  |  |     +------------+               |     v
107// |  WiFi, start wake |  |     |  Initiate  |<--------------+    +--------+
108// |  to scan timer &  |  |     |passive scan|                    |Get DHCP|
109// |  report readiness |  |     +-+----------+           +------->| Lease  |
110// +-------------------+  |       | ScanDone         Yes |        +--+---+-+
111//    +-------------------+       v                      |           |   |
112//    | Pattern                 +-------------+      +---------+     |   |
113//    |                    No   | Any services| Yes  |Connected|     |   |
114//    |    +--------------------+available for+----->| to AP?  |     |   |
115//    |    |                    | autoconnect?|      +---+-----+     |   |
116//    |    |                    +-------------+          |           |   |
117//    |    |                                             |No         |   |
118//    v    v                                             |           |   |
119// +--------------------+       +-------+                |           |   |
120// |BeforeSuspendActions|<------+Timeout|<---------------+       No  |   |
121// +--------------------+       +-------+<---------------------------+   |
122//         ^                                                             |
123//         |                   +-------------------+                     |
124//         +-------------------+ OnIPConfigUpdated/|             Yes     |
125//                             |OnIPv6ConfigUpdated|<--------------------+
126//                             +-------------------+
127//
128// BeforeSuspendActions
129// =====================
130// This function is run immediately before the system reports suspend readiness
131// to Manager. This is the common "exit path" taken by OnBeforeSuspend and
132// OnDarkResume before suspending.
133//
134// +----------------------+
135// |Packet feature enabled|   Yes   +------------------------+
136// |    and supported?    +-------->|Set Wake on Pattern flag|
137// +-----+----------------+         +------------+-----------+
138//       |                                       |
139//    No |        +------------------------------+
140//       |        |
141// +-----v--------v-------+        No
142// | Dark connect feature +---------------------------------+
143// |enabled and supported?|                                 |
144// +--+-------------------+                                 |
145//    |                                                     |
146//    |Yes    Yes   +----------------------------+          |        +---------+
147//    |     +-----> |Set Wake on Disconnect flag,+--+    +--v----+   |Report   |
148//    |     |       |Start Lease Renewal Timer*  |  |    |Program|   |Suspend  |
149//    |     |       +----------------------------+  +--> |  NIC  |   |Readiness|
150// +--v-----+-+                                     |    +-+---+-+   +--+------+
151// |Connected?|                                     |      |   ^        ^
152// +--------+-+                                     |      |   |Failed  |
153//          |                                       |      ^   |        |Success
154//          |       +----------------------------+  |  +---+---+---+    |
155//          +-----> |Set Wake on SSID flag,      +--+  |  Verify   +----+
156//            No    |Start Wake To Scan Timer**  |     |Programming|
157//                  +----------------------------+     +-----------+
158//
159// *  if necessary (as indicated by caller of BeforeSuspendActions).
160// ** if we need to whitelist more SSIDs than our NIC supports.
161//
162// OnAfterResume
163// ==============
164// This is run after Manager announces that the system has fully resumed from
165// suspend.
166//
167// Wake on WiFi is disabled on the NIC if it was enabled before suspend or
168// dark resume, and both the wake to scan timer and DHCP lease renewal timers
169// are stopped.
170
171class WakeOnWiFi {
172 public:
173  typedef base::Callback<void(const WiFi::FreqSet&)> InitiateScanCallback;
174  // Callback used to report the wake reason for the current dark resume to
175  // powerd.
176  typedef base::Callback<void(const std::string&)> RecordWakeReasonCallback;
177
178  // Types of triggers that we can program the NIC to wake the WiFi device.
179  enum WakeOnWiFiTrigger {
180    kWakeTriggerUnsupported = 0,  // Used for reporting, not programming NIC.
181    kWakeTriggerPattern = 1,
182    kWakeTriggerDisconnect = 2,
183    kWakeTriggerSSID = 3
184  };
185
186  WakeOnWiFi(NetlinkManager* netlink_manager, EventDispatcher* dispatcher,
187             Metrics* metrics,
188             RecordWakeReasonCallback record_wake_reason_callback);
189  virtual ~WakeOnWiFi();
190
191  // Registers |store| with properties related to wake on WiFi.
192  void InitPropertyStore(PropertyStore* store);
193
194  // Starts |metrics_timer_| so that wake on WiFi related metrics are
195  // periodically collected.
196  void StartMetricsTimer();
197
198  // Enable the NIC to wake on packets received from |ip_endpoint|.
199  // Note: The actual programming of the NIC only happens before the system
200  // suspends, in |OnBeforeSuspend|.
201  void AddWakeOnPacketConnection(const std::string& ip_endpoint, Error* error);
202  // Remove rule to wake on packets received from |ip_endpoint| from the NIC.
203  // Note: The actual programming of the NIC only happens before the system
204  // suspends, in |OnBeforeSuspend|.
205  void RemoveWakeOnPacketConnection(const std::string& ip_endpoint,
206                                    Error* error);
207  // Remove all rules to wake on incoming packets from the NIC.
208  // Note: The actual programming of the NIC only happens before the system
209  // suspends, in |OnBeforeSuspend|.
210  void RemoveAllWakeOnPacketConnections(Error* error);
211  // Given a NL80211_CMD_NEW_WIPHY message |nl80211_message|, parses the
212  // wake on WiFi capabilities of the NIC and set relevant members of this
213  // WakeOnWiFi object to reflect the supported capbilities.
214  virtual void ParseWakeOnWiFiCapabilities(
215      const Nl80211Message& nl80211_message);
216  // Callback invoked when the system reports its wakeup reason.
217  //
218  // Arguments:
219  //  - |netlink_message|: wakeup report message (note: must manually check
220  //    this message to make sure it is a wakeup report message).
221  //
222  // Note: Assumes only one wakeup reason is received. If more than one is
223  // received, the only first one parsed will be handled.
224  virtual void OnWakeupReasonReceived(const NetlinkMessage& netlink_message);
225  // Performs pre-suspend actions relevant to wake on WiFi functionality.
226  //
227  // Arguments:
228  //  - |is_connected|: whether the WiFi device is connected.
229  //  - |ssid_whitelist|: list of SSIDs that the NIC will be programmed to wake
230  //    the system on if the NIC is programmed to wake on SSID.
231  //  - |done_callback|: callback to invoke when suspend  actions have
232  //    completed.
233  //  - |renew_dhcp_lease_callback|: callback to invoke to initiate DHCP lease
234  //    renewal.
235  //  - |remove_supplicant_networks_callback|: callback to invoke
236  //    to remove all networks from WPA supplicant.
237  //  - |have_dhcp_lease|: whether or not there is a DHCP lease to renew.
238  //  - |time_to_next_lease_renewal|: number of seconds until next DHCP lease
239  //    renewal is due.
240  virtual void OnBeforeSuspend(
241      bool is_connected,
242      const std::vector<ByteString>& ssid_whitelist,
243      const ResultCallback& done_callback,
244      const base::Closure& renew_dhcp_lease_callback,
245      const base::Closure& remove_supplicant_networks_callback,
246      bool have_dhcp_lease,
247      uint32_t time_to_next_lease_renewal);
248  // Performs post-resume actions relevant to wake on wireless functionality.
249  virtual void OnAfterResume();
250  // Performs and post actions to be performed in dark resume.
251  //
252  // Arguments:
253  //  - |is_connected|: whether the WiFi device is connected.
254  //  - |ssid_whitelist|: list of SSIDs that the NIC will be programmed to wake
255  //    the system on if the NIC is programmed to wake on SSID.
256  //  - |done_callback|: callback to invoke when dark resume actions have
257  //    completed.
258  //  - |renew_dhcp_lease_callback|: callback to invoke to initiate DHCP lease
259  //    renewal.
260  //  - |initate_scan_callback|: callback to invoke to initiate a scan.
261  //  - |remove_supplicant_networks_callback|: callback to invoke
262  //    to remove all networks from WPA supplicant.
263  virtual void OnDarkResume(
264      bool is_connected,
265      const std::vector<ByteString>& ssid_whitelist,
266      const ResultCallback& done_callback,
267      const base::Closure& renew_dhcp_lease_callback,
268      const InitiateScanCallback& initiate_scan_callback,
269      const base::Closure& remove_supplicant_networks_callback);
270  // Called when we the current service is connected, and we have IP
271  // reachability. Calls WakeOnWiFi::BeforeSuspendActions if we are in dark
272  // resume to end the current dark resume. Otherwise, does nothing.
273  virtual void OnConnectedAndReachable(bool start_lease_renewal_timer,
274                                       uint32_t time_to_next_lease_renewal);
275  // Callback invoked to report whether this WiFi device is connected to
276  // a service after waking from suspend.
277  virtual void ReportConnectedToServiceAfterWake(bool is_connected);
278  // Called in WiFi::ScanDoneTask when there are no WiFi services available
279  // for auto-connect after a scan. |initiate_scan_callback| is used for dark
280  // resume scan retries.
281  virtual void OnNoAutoConnectableServicesAfterScan(
282      const std::vector<ByteString>& ssid_whitelist,
283      const base::Closure& remove_supplicant_networks_callback,
284      const InitiateScanCallback& initiate_scan_callback);
285  // Called by WiFi when it is notified by the kernel that a scan has started.
286  // If |is_active_scan| is true, the scan is an active scan. Otherwise, the
287  // scan is a passive scan.
288  virtual void OnScanStarted(bool is_active_scan);
289
290  bool in_dark_resume() { return in_dark_resume_; }
291
292  virtual void OnWiphyIndexReceived(uint32_t index);
293
294 private:
295  friend class WakeOnWiFiTest;  // access to several members for tests
296  friend class WiFiObjectTest;  // netlink_manager_
297  // kWakeOnWiFiNotSupported.
298  FRIEND_TEST(WakeOnWiFiTestWithMockDispatcher,
299              WakeOnWiFiDisabled_SetWakeOnWiFiFeaturesEnabled);
300  FRIEND_TEST(WakeOnWiFiTestWithMockDispatcher,
301              WakeOnWiFiDisabled_AddWakeOnPacketConnection_ReturnsError);
302  FRIEND_TEST(WakeOnWiFiTestWithMockDispatcher,
303              WakeOnWiFiDisabled_RemoveWakeOnPacketConnection_ReturnsError);
304  FRIEND_TEST(WakeOnWiFiTestWithMockDispatcher,
305              WakeOnWiFiDisabled_RemoveAllWakeOnPacketConnections_ReturnsError);
306  // kMaxSetWakeOnPacketRetries.
307  FRIEND_TEST(WakeOnWiFiTestWithMockDispatcher,
308              RetrySetWakeOnPacketConnections_LessThanMaxRetries);
309  FRIEND_TEST(WakeOnWiFiTestWithMockDispatcher,
310              RetrySetWakeOnPacketConnections_MaxAttemptsWithCallbackSet);
311  FRIEND_TEST(WakeOnWiFiTestWithMockDispatcher,
312              RetrySetWakeOnPacketConnections_MaxAttemptsCallbackUnset);
313  // kDarkResumeActionsTimeoutMilliseconds
314  FRIEND_TEST(WakeOnWiFiTestWithMockDispatcher,
315              OnBeforeSuspend_DHCPLeaseRenewal);
316  // Dark resume wake reason strings (e.g. kWakeReasonStringDisconnect)
317  FRIEND_TEST(WakeOnWiFiTestWithMockDispatcher,
318              OnWakeupReasonReceived_Disconnect);
319  FRIEND_TEST(WakeOnWiFiTestWithMockDispatcher, OnWakeupReasonReceived_SSID);
320  FRIEND_TEST(WakeOnWiFiTestWithMockDispatcher, OnWakeupReasonReceived_Pattern);
321  // kMaxDarkResumesPerPeriodShort
322  FRIEND_TEST(WakeOnWiFiTestWithDispatcher, OnBeforeSuspend_ClearsEventHistory);
323  // kDarkResumeFrequencySamplingPeriodShortMinutes,
324  // kMaxDarkResumesPerPeriodShort
325  FRIEND_TEST(WakeOnWiFiTestWithDispatcher,
326              OnDarkResume_NotConnected_MaxDarkResumes_ShortPeriod);
327  // kDarkResumeFrequencySamplingPeriodLongMinutes,
328  // kMaxDarkResumesPerPeriodLong,
329  // kDarkResumeFrequencySamplingPeriodShortMinutes,
330  // kMaxDarkResumesPerPeriodShort
331  FRIEND_TEST(WakeOnWiFiTestWithDispatcher,
332              OnDarkResume_NotConnected_MaxDarkResumes_LongPeriod);
333  // kMaxFreqsForDarkResumeScanRetries, kMaxDarkResumeScanRetries
334  FRIEND_TEST(WakeOnWiFiTestWithDispatcher, InitiateScanInDarkResume);
335
336  static const char kWakeOnIPAddressPatternsNotSupported[];
337  static const char kWakeOnWiFiNotSupported[];
338  static const int kVerifyWakeOnWiFiSettingsDelayMilliseconds;
339  static const int kMaxSetWakeOnPacketRetries;
340  static const int kMetricsReportingFrequencySeconds;
341  static const uint32_t kDefaultWakeToScanPeriodSeconds;
342  static const uint32_t kDefaultNetDetectScanPeriodSeconds;
343  static const uint32_t kImmediateDHCPLeaseRenewalThresholdSeconds;
344  static const int kDarkResumeFrequencySamplingPeriodShortMinutes;
345  static const int kDarkResumeFrequencySamplingPeriodLongMinutes;
346  static const int kMaxDarkResumesPerPeriodShort;
347  static const int kMaxDarkResumesPerPeriodLong;
348  static int64_t DarkResumeActionsTimeoutMilliseconds;  // non-const for testing
349  static const int kMaxFreqsForDarkResumeScanRetries;
350  static const int kMaxDarkResumeScanRetries;
351  // Dark resume wake reason names. These will be sent to powerd via
352  // RecordDarkResumeWakeReason, to tell it the reason the system woke in the
353  // current dark resume.
354  static const char kWakeReasonStringPattern[];
355  static const char kWakeReasonStringDisconnect[];
356  static const char kWakeReasonStringSSID[];
357
358  std::string GetWakeOnWiFiFeaturesEnabled(Error* error);
359  bool SetWakeOnWiFiFeaturesEnabled(const std::string& enabled, Error* error);
360  // Helper function to run and reset |suspend_actions_done_callback_|.
361  void RunAndResetSuspendActionsDoneCallback(const Error& error);
362  // Used for comparison of ByteString pairs in a set.
363  static bool ByteStringPairIsLessThan(
364      const std::pair<ByteString, ByteString>& lhs,
365      const std::pair<ByteString, ByteString>& rhs);
366  // Creates a mask which specifies which bytes in pattern of length
367  // |pattern_len| to match against. Bits |offset| to |pattern_len| - 1 are set,
368  // which bits 0 to bits 0 to |offset| - 1 are unset. This mask is saved in
369  // |mask|.
370  static void SetMask(ByteString* mask, uint32_t pattern_len, uint32_t offset);
371  // Creates a pattern and mask for a NL80211 message that programs the NIC to
372  // wake on packets originating from IP address |ip_addr|. The pattern and mask
373  // are saved in |pattern| and |mask| respectively. Returns true iff the
374  // pattern and mask are successfully created and written to |pattern| and
375  // |mask| respectively.
376  static bool CreateIPAddressPatternAndMask(const IPAddress& ip_addr,
377                                            ByteString* pattern,
378                                            ByteString* mask);
379  static void CreateIPV4PatternAndMask(const IPAddress& ip_addr,
380                                       ByteString* pattern, ByteString* mask);
381  static void CreateIPV6PatternAndMask(const IPAddress& ip_addr,
382                                       ByteString* pattern, ByteString* mask);
383  // Creates and sets an attribute in a NL80211 message |msg| which indicates
384  // the index of the wiphy interface to program. Returns true iff |msg| is
385  // successfully configured.
386  static bool ConfigureWiphyIndex(Nl80211Message* msg, int32_t index);
387  // Creates and sets attributes in an SetWakeOnPacketConnMessage |msg| so that
388  // the message will disable wake-on-packet functionality of the NIC with wiphy
389  // index |wiphy_index|. Returns true iff |msg| is successfully configured.
390  // NOTE: Assumes that |msg| has not been altered since construction.
391  static bool ConfigureDisableWakeOnWiFiMessage(SetWakeOnPacketConnMessage* msg,
392                                                uint32_t wiphy_index,
393                                                Error* error);
394  // Creates and sets attributes in a SetWakeOnPacketConnMessage |msg|
395  // so that the message will program the NIC with wiphy index |wiphy_index|
396  // with wake on wireless triggers in |trigs|. If |trigs| contains the
397  // kWakeTriggerPattern trigger, the message is configured to program the NIC
398  // to wake on packets from the IP addresses in |addrs|. If |trigs| contains
399  // the kSSID trigger, the message is configured to program the NIC to wake on
400  // the SSIDs in |ssid_whitelist|.
401  // Returns true iff |msg| is successfully configured.
402  // NOTE: Assumes that |msg| has not been altered since construction.
403  static bool ConfigureSetWakeOnWiFiSettingsMessage(
404      SetWakeOnPacketConnMessage* msg, const std::set<WakeOnWiFiTrigger>& trigs,
405      const IPAddressStore& addrs, uint32_t wiphy_index,
406      uint32_t net_detect_scan_period_seconds,
407      const std::vector<ByteString>& ssid_whitelist,
408      Error* error);
409  // Helper function to ConfigureSetWakeOnWiFiSettingsMessage that creates a
410  // single nested attribute inside the attribute list referenced by |patterns|
411  // representing a wake-on-packet pattern matching rule with index |patnum|.
412  // Returns true iff the attribute is successfully created and set.
413  // NOTE: |patterns| is assumed to reference the nested attribute list
414  // NL80211_WOWLAN_TRIG_PKT_PATTERN.
415  // NOTE: |patnum| should be unique across multiple calls to this function to
416  // prevent the formation of a erroneous nl80211 message or the overwriting of
417  // pattern matching rules.
418  static bool CreateSinglePattern(const IPAddress& ip_addr,
419                                  AttributeListRefPtr patterns, uint8_t patnum,
420                                  Error* error);
421  // Creates and sets attributes in an GetWakeOnPacketConnMessage msg| so that
422  // the message will request for wake-on-packet settings information from the
423  // NIC with wiphy index |wiphy_index|. Returns true iff |msg| is successfully
424  // configured.
425  // NOTE: Assumes that |msg| has not been altered since construction.
426  static bool ConfigureGetWakeOnWiFiSettingsMessage(
427      GetWakeOnPacketConnMessage* msg, uint32_t wiphy_index, Error* error);
428  // Given a NL80211_CMD_GET_WOWLAN response or NL80211_CMD_SET_WOWLAN request
429  // |msg|, returns true iff the wake-on-wifi trigger settings in |msg| match
430  // those in |trigs|. Performs the following checks for the following triggers:
431  // - kWakeTriggerDisconnect: checks that the wake on disconnect flag is
432  //   present and set.
433  // - kIPAddress: checks that source IP addresses in |msg| match those reported
434  //   in |addrs|.
435  // - kSSID: checks that the SSIDs in |ssid_whitelist| and the scan interval
436  //   |net_detect_scan_period_seconds| match those reported in |msg|.
437  // Note: finding a trigger is in |msg| that is not expected based on the flags
438  // in |trig| also counts as a mismatch.
439  static bool WakeOnWiFiSettingsMatch(
440      const Nl80211Message& msg, const std::set<WakeOnWiFiTrigger>& trigs,
441      const IPAddressStore& addrs, uint32_t net_detect_scan_period_seconds,
442      const std::vector<ByteString>& ssid_whitelist);
443  // Handler for NL80211 message error responses from NIC wake on WiFi setting
444  // programming attempts.
445  void OnWakeOnWiFiSettingsErrorResponse(
446      NetlinkManager::AuxilliaryMessageType type,
447      const NetlinkMessage* raw_message);
448  // Message handler for NL80211_CMD_SET_WOWLAN responses.
449  static void OnSetWakeOnPacketConnectionResponse(
450      const Nl80211Message& nl80211_message);
451  // Request wake on WiFi settings for this WiFi device.
452  void RequestWakeOnPacketSettings();
453  // Verify that the wake on WiFi settings programmed into the NIC match
454  // those recorded locally for this device in |wake_on_packet_connections_|,
455  // |wake_on_wifi_triggers_|, and |wake_on_ssid_whitelist_|.
456  void VerifyWakeOnWiFiSettings(const Nl80211Message& nl80211_message);
457  // Sends an NL80211 message to program the NIC with wake on WiFi settings
458  // configured in |wake_on_packet_connections_|, |wake_on_ssid_whitelist_|, and
459  // |wake_on_wifi_triggers_|. If |wake_on_wifi_triggers_| is empty, calls
460  // WakeOnWiFi::DisableWakeOnWiFi.
461  void ApplyWakeOnWiFiSettings();
462  // Helper function called by |ApplyWakeOnWiFiSettings| that sends an NL80211
463  // message to program the NIC to disable wake on WiFi.
464  void DisableWakeOnWiFi();
465  // Calls |ApplyWakeOnWiFiSettings| and counts this call as
466  // a retry. If |kMaxSetWakeOnPacketRetries| retries have already been
467  // performed, resets counter and returns.
468  void RetrySetWakeOnPacketConnections();
469  // Utility functions to check which wake on WiFi features are currently
470  // enabled based on the descriptor |wake_on_wifi_features_enabled_| and
471  // are supported by the NIC.
472  bool WakeOnWiFiPacketEnabledAndSupported();
473  bool WakeOnWiFiDarkConnectEnabledAndSupported();
474  // Called by metrics_timer_ to reports metrics.
475  void ReportMetrics();
476  // Actions executed before normal suspend and dark resume suspend.
477  //
478  // Arguments:
479  //  - |is_connected|: whether the WiFi device is connected.
480  //  - |start_lease_renewal_timer|: whether or not to start the DHCP lease
481  //    renewal timer.
482  //  - |time_to_next_lease_renewal|: number of seconds until next DHCP lease
483  //    renewal is due.
484  //  - |remove_supplicant_networks_callback|: callback to invoke
485  //    to remove all networks from WPA supplicant.
486  void BeforeSuspendActions(
487      bool is_connected,
488      bool start_lease_renewal_timer,
489      uint32_t time_to_next_lease_renewal,
490      const base::Closure& remove_supplicant_networks_callback);
491
492  // Needed for |dhcp_lease_renewal_timer_| and |wake_to_scan_timer_| since
493  // passing a empty base::Closure() causes a run-time DCHECK error when
494  // SimpleAlarmTimer::Start or SimpleAlarmTimer::Reset are called.
495  void OnTimerWakeDoNothing() {}
496
497  // Parses an attribute list containing the SSID matches that caused the
498  // system wake, along with the corresponding channels that these SSIDs were
499  // detected in. Returns a set of unique frequencies that the reported
500  // SSID matches occured in.
501  //
502  // Arguments:
503  //  - |results_list|: Nested attribute list containing an array of nested
504  //    attributes which contain the NL80211_ATTR_SSID or
505  //    NL80211_ATTR_SCAN_FREQUENCIES attributes. This attribute list is assumed
506  //    to have been extracted from a NL80211_CMD_SET_WOWLAN response message
507  //    using the NL80211_WOWLAN_TRIG_NET_DETECT_RESULTS id.
508  static WiFi::FreqSet ParseWakeOnSSIDResults(
509      AttributeListConstRefPtr results_list);
510
511  // Sets the |dark_resume_scan_retries_left_| counter if necessary, then runs
512  // |initiate_scan_callback| with |freqs|.
513  void InitiateScanInDarkResume(
514      const InitiateScanCallback& initiate_scan_callback,
515      const WiFi::FreqSet& freqs);
516
517  // Pointers to objects owned by the WiFi object that created this object.
518  EventDispatcher* dispatcher_;
519  NetlinkManager* netlink_manager_;
520  Metrics* metrics_;
521  // Executes after the NIC's wake-on-packet settings are configured via
522  // NL80211 messages to verify that the new configuration has taken effect.
523  // Calls RequestWakeOnPacketSettings.
524  base::CancelableClosure verify_wake_on_packet_settings_callback_;
525  // Callback to be invoked after all suspend actions finish executing both
526  // before regular suspend and before suspend in dark resume.
527  ResultCallback suspend_actions_done_callback_;
528  // Callback to report wake on WiFi related metrics.
529  base::CancelableClosure report_metrics_callback_;
530  // Number of retry attempts to program the NIC's wake-on-packet settings.
531  int num_set_wake_on_packet_retries_;
532  // Keeps track of triggers that the NIC will be programmed to wake from
533  // while suspended.
534  std::set<WakeOnWiFi::WakeOnWiFiTrigger> wake_on_wifi_triggers_;
535  // Keeps track of what wake on wifi triggers this WiFi device supports.
536  std::set<WakeOnWiFi::WakeOnWiFiTrigger> wake_on_wifi_triggers_supported_;
537  // Max number of patterns this WiFi device can be programmed to wake on at one
538  // time.
539  size_t wake_on_wifi_max_patterns_;
540  // Max number of SSIDs this WiFi device can be programmed to wake on at one
541  // time.
542  uint32_t wake_on_wifi_max_ssids_;
543  // Keeps track of IP addresses whose packets this device will wake upon
544  // receiving while the device is suspended. Only used if the NIC is programmed
545  // to wake on IP address patterns.
546  IPAddressStore wake_on_packet_connections_;
547  // Keeps track of SSIDs that this device will wake on the appearance of while
548  // the device is suspended. Only used if the NIC is programmed to wake on
549  // SSIDs.
550  std::vector<ByteString> wake_on_ssid_whitelist_;
551  uint32_t wiphy_index_;
552  bool wiphy_index_received_;
553  // Describes the wake on WiFi features that are currently enabled.
554  std::string wake_on_wifi_features_enabled_;
555  // Timer that wakes the system to renew DHCP leases.
556  timers::SimpleAlarmTimer dhcp_lease_renewal_timer_;
557  // Timer that wakes the system to scan for networks.
558  timers::SimpleAlarmTimer wake_to_scan_timer_;
559  // Executes when the dark resume actions timer expires. Calls
560  // ScanTimerHandler.
561  base::CancelableClosure dark_resume_actions_timeout_callback_;
562  // Whether shill is currently in dark resume.
563  bool in_dark_resume_;
564  // Period (in seconds) between instances where the system wakes from suspend
565  // to scan for networks in dark resume.
566  uint32_t wake_to_scan_period_seconds_;
567  // Period (in seconds) between instances where the NIC performs Net Detect
568  // scans while the system is suspended.
569  uint32_t net_detect_scan_period_seconds_;
570  // Timestamps of dark resume wakes that took place during the current
571  // or most recent suspend.
572  EventHistory dark_resume_history_;
573  // Last wake reason reported by the kernel.
574  WakeOnWiFiTrigger last_wake_reason_;
575  // Whether or not to always start |wake_to_scan_timer_| before suspend.
576  bool force_wake_to_scan_timer_;
577  // Frequencies that the last wake on SSID matches reported by the kernel
578  // occurred in.
579  WiFi::FreqSet last_ssid_match_freqs_;
580  // How many more times to retry the last dark resume scan that shill launched
581  // if no auto-connectable services were found.
582  int dark_resume_scan_retries_left_;
583
584  // Callback invoked to report the wake reason for the current dark resume to
585  // powerd.
586  RecordWakeReasonCallback record_wake_reason_callback_;
587
588  base::WeakPtrFactory<WakeOnWiFi> weak_ptr_factory_;
589
590  DISALLOW_COPY_AND_ASSIGN(WakeOnWiFi);
591};
592
593}  // namespace shill
594
595#endif  // SHILL_WIFI_WAKE_ON_WIFI_H_
596