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