Home | History | Annotate | Download | only in wifi
      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 
    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