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 
43 namespace shill {
44 
45 class ByteString;
46 class Error;
47 class EventDispatcher;
48 class GetWakeOnPacketConnMessage;
49 class Metrics;
50 class Nl80211Message;
51 class PropertyStore;
52 class 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 
171 class 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 
in_dark_resume()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.
OnTimerWakeDoNothing()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