| // Copyright 2018 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "shill/wifi/wake_on_wifi.h" |
| |
| #include <linux/nl80211.h> |
| |
| #include <memory> |
| #include <set> |
| #include <string> |
| |
| #include <base/files/file_descriptor_watcher_posix.h> |
| #include <base/message_loop/message_loop.h> |
| #include <base/strings/stringprintf.h> |
| #include <chromeos/dbus/service_constants.h> |
| #include <gmock/gmock.h> |
| #include <gtest/gtest.h> |
| |
| #include "shill/error.h" |
| #include "shill/event_dispatcher.h" |
| #include "shill/ip_address_store.h" |
| #include "shill/logging.h" |
| #include "shill/mock_control.h" |
| #include "shill/mock_event_dispatcher.h" |
| #include "shill/mock_log.h" |
| #include "shill/mock_metrics.h" |
| #include "shill/net/byte_string.h" |
| #include "shill/net/ip_address.h" |
| #include "shill/net/mock_netlink_manager.h" |
| #include "shill/net/mock_time.h" |
| #include "shill/net/netlink_message_matchers.h" |
| #include "shill/net/netlink_packet.h" |
| #include "shill/net/nl80211_message.h" |
| #include "shill/net/shill_time.h" |
| #include "shill/test_event_dispatcher.h" |
| #include "shill/testing.h" |
| |
| using base::Bind; |
| using base::Closure; |
| using base::Unretained; |
| using std::set; |
| using std::string; |
| using std::vector; |
| using testing::_; |
| using ::testing::AnyNumber; |
| using ::testing::HasSubstr; |
| using ::testing::Return; |
| |
| namespace shill { |
| |
| namespace { |
| |
| const uint16_t kNl80211FamilyId = 0x13; |
| |
| const uint8_t kSSIDBytes1[] = {0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, |
| 0x47, 0x75, 0x65, 0x73, 0x74}; |
| // Bytes representing a NL80211_CMD_SET_WOWLAN reporting that the system woke |
| // up because of an SSID match. The net detect results report a single SSID |
| // match represented by kSSIDBytes1, occurring in the frequencies in |
| // kSSID1FreqMatches. |
| const uint8_t kWakeReasonSSIDNlMsg[] = { |
| 0x90, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x4a, 0x01, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x99, 0x00, 0x01, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, |
| 0x60, 0x00, 0x75, 0x00, 0x5c, 0x00, 0x13, 0x00, 0x58, 0x00, 0x00, 0x00, |
| 0x0f, 0x00, 0x34, 0x00, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x47, 0x75, |
| 0x65, 0x73, 0x74, 0x00, 0x44, 0x00, 0x2c, 0x00, 0x08, 0x00, 0x00, 0x00, |
| 0x6c, 0x09, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x85, 0x09, 0x00, 0x00, |
| 0x08, 0x00, 0x02, 0x00, 0x9e, 0x09, 0x00, 0x00, 0x08, 0x00, 0x03, 0x00, |
| 0x3c, 0x14, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x78, 0x14, 0x00, 0x00, |
| 0x08, 0x00, 0x05, 0x00, 0x71, 0x16, 0x00, 0x00, 0x08, 0x00, 0x06, 0x00, |
| 0xad, 0x16, 0x00, 0x00, 0x08, 0x00, 0x07, 0x00, 0xc1, 0x16, 0x00, 0x00}; |
| const uint32_t kTimeToNextLeaseRenewalShort = 1; |
| const uint32_t kTimeToNextLeaseRenewalLong = 1000; |
| const uint32_t kNetDetectScanIntervalSeconds = 120; |
| // These blobs represent NL80211 messages from the kernel reporting the NIC's |
| // wake-on-packet settings, sent in response to NL80211_CMD_GET_WOWLAN requests. |
| const uint8_t kResponseNoIPAddresses[] = { |
| 0x14, 0x00, 0x00, 0x00, 0x13, 0x00, 0x01, 0x00, 0x01, 0x00, |
| 0x00, 0x00, 0x57, 0x40, 0x00, 0x00, 0x49, 0x01, 0x00, 0x00}; |
| const uint8_t kResponseIPV40[] = { |
| 0x4C, 0x00, 0x00, 0x00, 0x13, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, |
| 0x00, 0x57, 0x40, 0x00, 0x00, 0x49, 0x01, 0x00, 0x00, 0x38, 0x00, |
| 0x75, 0x00, 0x34, 0x00, 0x04, 0x00, 0x30, 0x00, 0x01, 0x00, 0x08, |
| 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x22, 0x00, 0x02, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0xC0, 0xA8, 0x0A, 0x14, 0x00, 0x00}; |
| const uint8_t kResponseIPV40WakeOnDisconnect[] = { |
| 0x50, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, |
| 0x57, 0x40, 0x00, 0x00, 0x49, 0x01, 0x00, 0x00, 0x3C, 0x00, 0x75, 0x00, |
| 0x04, 0x00, 0x02, 0x00, 0x34, 0x00, 0x04, 0x00, 0x30, 0x00, 0x01, 0x00, |
| 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x22, 0x00, 0x02, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0xC0, 0xA8, 0x0A, 0x14, 0x00, 0x00}; |
| const uint8_t kResponseIPV401[] = { |
| 0x7C, 0x00, 0x00, 0x00, 0x13, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, |
| 0x57, 0x40, 0x00, 0x00, 0x49, 0x01, 0x00, 0x00, 0x68, 0x00, 0x75, 0x00, |
| 0x64, 0x00, 0x04, 0x00, 0x30, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, |
| 0x00, 0x00, 0x00, 0x3C, 0x22, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, |
| 0x03, 0x04, 0x00, 0x00, 0x30, 0x00, 0x02, 0x00, 0x08, 0x00, 0x01, 0x00, |
| 0x00, 0x00, 0x00, 0x3C, 0x22, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xA8, |
| 0x0A, 0x14, 0x00, 0x00}; |
| const uint8_t kResponseIPV401IPV60[] = { |
| 0xB8, 0x00, 0x00, 0x00, 0x13, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, |
| 0x57, 0x40, 0x00, 0x00, 0x49, 0x01, 0x00, 0x00, 0xA4, 0x00, 0x75, 0x00, |
| 0xA0, 0x00, 0x04, 0x00, 0x30, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, |
| 0x00, 0x00, 0x00, 0x3C, 0x22, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, |
| 0x03, 0x04, 0x00, 0x00, 0x30, 0x00, 0x02, 0x00, 0x08, 0x00, 0x01, 0x00, |
| 0x00, 0x00, 0x00, 0x3C, 0x22, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xA8, |
| 0x0A, 0x14, 0x00, 0x00, 0x3C, 0x00, 0x03, 0x00, 0x09, 0x00, 0x01, 0x00, |
| 0x00, 0x00, 0xC0, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x02, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xDC, |
| 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, |
| 0x32, 0x10, 0x00, 0x00}; |
| const uint8_t kResponseIPV401IPV601[] = { |
| 0xF4, 0x00, 0x00, 0x00, 0x13, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, |
| 0x57, 0x40, 0x00, 0x00, 0x49, 0x01, 0x00, 0x00, 0xE0, 0x00, 0x75, 0x00, |
| 0xDC, 0x00, 0x04, 0x00, 0x30, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, |
| 0x00, 0x00, 0x00, 0x3C, 0x22, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, |
| 0x03, 0x04, 0x00, 0x00, 0x3C, 0x00, 0x02, 0x00, 0x09, 0x00, 0x01, 0x00, |
| 0x00, 0x00, 0xC0, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x02, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x80, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x20, 0x0C, |
| 0x41, 0x7A, 0x00, 0x00, 0x30, 0x00, 0x03, 0x00, 0x08, 0x00, 0x01, 0x00, |
| 0x00, 0x00, 0x00, 0x3C, 0x22, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xA8, |
| 0x0A, 0x14, 0x00, 0x00, 0x3C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x01, 0x00, |
| 0x00, 0x00, 0xC0, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x02, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xDC, |
| 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, |
| 0x32, 0x10, 0x00, 0x00}; |
| // This blob represents an NL80211 messages from the kernel reporting that the |
| // NIC is programmed to wake on the SSIDs represented by kSSIDBytes1 and |
| // kSSIDBytes2, and scans for these SSIDs at interval |
| // kNetDetectScanIntervalSeconds. |
| const uint8_t kResponseWakeOnSSID[] = { |
| 0x60, 0x01, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x9a, 0x01, 0x00, 0x00, |
| 0xfa, 0x02, 0x00, 0x00, 0x49, 0x01, 0x00, 0x00, 0x4c, 0x01, 0x75, 0x00, |
| 0x48, 0x01, 0x12, 0x00, 0x08, 0x00, 0x77, 0x00, 0xc0, 0xd4, 0x01, 0x00, |
| 0x0c, 0x01, 0x2c, 0x00, 0x08, 0x00, 0x00, 0x00, 0x6c, 0x09, 0x00, 0x00, |
| 0x08, 0x00, 0x01, 0x00, 0x71, 0x09, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, |
| 0x76, 0x09, 0x00, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7b, 0x09, 0x00, 0x00, |
| 0x08, 0x00, 0x04, 0x00, 0x80, 0x09, 0x00, 0x00, 0x08, 0x00, 0x05, 0x00, |
| 0x85, 0x09, 0x00, 0x00, 0x08, 0x00, 0x06, 0x00, 0x8a, 0x09, 0x00, 0x00, |
| 0x08, 0x00, 0x07, 0x00, 0x8f, 0x09, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, |
| 0x94, 0x09, 0x00, 0x00, 0x08, 0x00, 0x09, 0x00, 0x99, 0x09, 0x00, 0x00, |
| 0x08, 0x00, 0x0a, 0x00, 0x9e, 0x09, 0x00, 0x00, 0x08, 0x00, 0x0b, 0x00, |
| 0x3c, 0x14, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x50, 0x14, 0x00, 0x00, |
| 0x08, 0x00, 0x0d, 0x00, 0x64, 0x14, 0x00, 0x00, 0x08, 0x00, 0x0e, 0x00, |
| 0x78, 0x14, 0x00, 0x00, 0x08, 0x00, 0x0f, 0x00, 0x8c, 0x14, 0x00, 0x00, |
| 0x08, 0x00, 0x10, 0x00, 0xa0, 0x14, 0x00, 0x00, 0x08, 0x00, 0x11, 0x00, |
| 0xb4, 0x14, 0x00, 0x00, 0x08, 0x00, 0x12, 0x00, 0xc8, 0x14, 0x00, 0x00, |
| 0x08, 0x00, 0x13, 0x00, 0x7c, 0x15, 0x00, 0x00, 0x08, 0x00, 0x14, 0x00, |
| 0x90, 0x15, 0x00, 0x00, 0x08, 0x00, 0x15, 0x00, 0xa4, 0x15, 0x00, 0x00, |
| 0x08, 0x00, 0x16, 0x00, 0xb8, 0x15, 0x00, 0x00, 0x08, 0x00, 0x17, 0x00, |
| 0xcc, 0x15, 0x00, 0x00, 0x08, 0x00, 0x18, 0x00, 0x1c, 0x16, 0x00, 0x00, |
| 0x08, 0x00, 0x19, 0x00, 0x30, 0x16, 0x00, 0x00, 0x08, 0x00, 0x1a, 0x00, |
| 0x44, 0x16, 0x00, 0x00, 0x08, 0x00, 0x1b, 0x00, 0x58, 0x16, 0x00, 0x00, |
| 0x08, 0x00, 0x1c, 0x00, 0x71, 0x16, 0x00, 0x00, 0x08, 0x00, 0x1d, 0x00, |
| 0x85, 0x16, 0x00, 0x00, 0x08, 0x00, 0x1e, 0x00, 0x99, 0x16, 0x00, 0x00, |
| 0x08, 0x00, 0x1f, 0x00, 0xad, 0x16, 0x00, 0x00, 0x08, 0x00, 0x20, 0x00, |
| 0xc1, 0x16, 0x00, 0x00, 0x30, 0x00, 0x84, 0x00, 0x14, 0x00, 0x00, 0x00, |
| 0x0f, 0x00, 0x01, 0x00, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x47, 0x75, |
| 0x65, 0x73, 0x74, 0x00, 0x18, 0x00, 0x01, 0x00, 0x12, 0x00, 0x01, 0x00, |
| 0x54, 0x50, 0x2d, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x38, 0x37, 0x36, 0x44, |
| 0x33, 0x35, 0x00, 0x00}; |
| const uint8_t kSSIDBytes2[] = {0x54, 0x50, 0x2d, 0x4c, 0x49, 0x4e, 0x4b, |
| 0x5f, 0x38, 0x37, 0x36, 0x44, 0x33, 0x35}; |
| |
| // Bytes representing a NL80211_CMD_NEW_WIPHY message reporting the WiFi |
| // capabilities of a NIC. This message reports that the NIC supports wake on |
| // pattern (on up to |kNewWiphyNlMsg_MaxPatterns| registered patterns), supports |
| // wake on SSID (on up to |kNewWiphyNlMsg_MaxSSIDs| SSIDs), and supports wake on |
| // disconnect. |
| const uint8_t kNewWiphyNlMsg[] = { |
| 0xb8, 0x0d, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, |
| 0xd9, 0x53, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, |
| 0x02, 0x00, 0x00, 0x00, 0x09, 0x00, 0x02, 0x00, 0x70, 0x68, 0x79, 0x30, |
| 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x2e, 0x00, 0x01, 0x00, 0x00, 0x00, |
| 0x05, 0x00, 0x3d, 0x00, 0x07, 0x00, 0x00, 0x00, 0x05, 0x00, 0x3e, 0x00, |
| 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x3f, 0x00, 0xff, 0xff, 0xff, 0xff, |
| 0x08, 0x00, 0x40, 0x00, 0xff, 0xff, 0xff, 0xff, 0x05, 0x00, 0x59, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x2b, 0x00, 0x14, 0x00, 0x00, 0x00, |
| 0x05, 0x00, 0x7b, 0x00, 0x14, 0x00, 0x00, 0x00, 0x06, 0x00, 0x38, 0x00, |
| 0xa9, 0x01, 0x00, 0x00, 0x06, 0x00, 0x7c, 0x00, 0xe6, 0x01, 0x00, 0x00, |
| 0x05, 0x00, 0x85, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x04, 0x00, 0x68, 0x00, |
| 0x04, 0x00, 0x82, 0x00, 0x1c, 0x00, 0x39, 0x00, 0x04, 0xac, 0x0f, 0x00, |
| 0x02, 0xac, 0x0f, 0x00, 0x01, 0xac, 0x0f, 0x00, 0x05, 0xac, 0x0f, 0x00, |
| 0x06, 0xac, 0x0f, 0x00, 0x01, 0x72, 0x14, 0x00, 0x05, 0x00, 0x56, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x66, 0x00, 0x08, 0x00, 0x71, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x24, 0x00, 0x20, 0x00, 0x04, 0x00, 0x01, 0x00, 0x04, 0x00, 0x02, 0x00, |
| 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x06, 0x00, |
| 0x04, 0x00, 0x08, 0x00, 0x04, 0x00, 0x09, 0x00, 0x04, 0x00, 0x0a, 0x00, |
| 0x94, 0x05, 0x16, 0x00, 0xe8, 0x01, 0x00, 0x00, 0x14, 0x00, 0x03, 0x00, |
| 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x01, |
| 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x04, 0x00, 0xe2, 0x11, 0x00, 0x00, |
| 0x05, 0x00, 0x05, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, |
| 0x05, 0x00, 0x00, 0x00, 0x18, 0x01, 0x01, 0x00, 0x14, 0x00, 0x00, 0x00, |
| 0x08, 0x00, 0x01, 0x00, 0x6c, 0x09, 0x00, 0x00, 0x08, 0x00, 0x06, 0x00, |
| 0x98, 0x08, 0x00, 0x00, 0x14, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, |
| 0x71, 0x09, 0x00, 0x00, 0x08, 0x00, 0x06, 0x00, 0x98, 0x08, 0x00, 0x00, |
| 0x14, 0x00, 0x02, 0x00, 0x08, 0x00, 0x01, 0x00, 0x76, 0x09, 0x00, 0x00, |
| 0x08, 0x00, 0x06, 0x00, 0x98, 0x08, 0x00, 0x00, 0x14, 0x00, 0x03, 0x00, |
| 0x08, 0x00, 0x01, 0x00, 0x7b, 0x09, 0x00, 0x00, 0x08, 0x00, 0x06, 0x00, |
| 0x98, 0x08, 0x00, 0x00, 0x14, 0x00, 0x04, 0x00, 0x08, 0x00, 0x01, 0x00, |
| 0x80, 0x09, 0x00, 0x00, 0x08, 0x00, 0x06, 0x00, 0x98, 0x08, 0x00, 0x00, |
| 0x14, 0x00, 0x05, 0x00, 0x08, 0x00, 0x01, 0x00, 0x85, 0x09, 0x00, 0x00, |
| 0x08, 0x00, 0x06, 0x00, 0x98, 0x08, 0x00, 0x00, 0x14, 0x00, 0x06, 0x00, |
| 0x08, 0x00, 0x01, 0x00, 0x8a, 0x09, 0x00, 0x00, 0x08, 0x00, 0x06, 0x00, |
| 0x98, 0x08, 0x00, 0x00, 0x14, 0x00, 0x07, 0x00, 0x08, 0x00, 0x01, 0x00, |
| 0x8f, 0x09, 0x00, 0x00, 0x08, 0x00, 0x06, 0x00, 0x98, 0x08, 0x00, 0x00, |
| 0x14, 0x00, 0x08, 0x00, 0x08, 0x00, 0x01, 0x00, 0x94, 0x09, 0x00, 0x00, |
| 0x08, 0x00, 0x06, 0x00, 0x98, 0x08, 0x00, 0x00, 0x14, 0x00, 0x09, 0x00, |
| 0x08, 0x00, 0x01, 0x00, 0x99, 0x09, 0x00, 0x00, 0x08, 0x00, 0x06, 0x00, |
| 0x98, 0x08, 0x00, 0x00, 0x14, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x01, 0x00, |
| 0x9e, 0x09, 0x00, 0x00, 0x08, 0x00, 0x06, 0x00, 0x98, 0x08, 0x00, 0x00, |
| 0x1c, 0x00, 0x0b, 0x00, 0x08, 0x00, 0x01, 0x00, 0xa3, 0x09, 0x00, 0x00, |
| 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x00, 0x08, 0x00, 0x06, 0x00, |
| 0x98, 0x08, 0x00, 0x00, 0x1c, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x01, 0x00, |
| 0xa8, 0x09, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x00, |
| 0x08, 0x00, 0x06, 0x00, 0x98, 0x08, 0x00, 0x00, 0xa0, 0x00, 0x02, 0x00, |
| 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x00, |
| 0x10, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x14, 0x00, 0x00, 0x00, |
| 0x04, 0x00, 0x02, 0x00, 0x10, 0x00, 0x02, 0x00, 0x08, 0x00, 0x01, 0x00, |
| 0x37, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x10, 0x00, 0x03, 0x00, |
| 0x08, 0x00, 0x01, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, |
| 0x0c, 0x00, 0x04, 0x00, 0x08, 0x00, 0x01, 0x00, 0x3c, 0x00, 0x00, 0x00, |
| 0x0c, 0x00, 0x05, 0x00, 0x08, 0x00, 0x01, 0x00, 0x5a, 0x00, 0x00, 0x00, |
| 0x0c, 0x00, 0x06, 0x00, 0x08, 0x00, 0x01, 0x00, 0x78, 0x00, 0x00, 0x00, |
| 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x00, |
| 0x0c, 0x00, 0x08, 0x00, 0x08, 0x00, 0x01, 0x00, 0xf0, 0x00, 0x00, 0x00, |
| 0x0c, 0x00, 0x09, 0x00, 0x08, 0x00, 0x01, 0x00, 0x68, 0x01, 0x00, 0x00, |
| 0x0c, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x01, 0x00, 0xe0, 0x01, 0x00, 0x00, |
| 0x0c, 0x00, 0x0b, 0x00, 0x08, 0x00, 0x01, 0x00, 0x1c, 0x02, 0x00, 0x00, |
| 0xa8, 0x03, 0x01, 0x00, 0x14, 0x00, 0x03, 0x00, 0xff, 0xff, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x01, 0x01, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x04, 0x00, 0xe2, 0x11, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, |
| 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x05, 0x00, 0x00, 0x00, |
| 0x0c, 0x00, 0x07, 0x00, 0xfa, 0xff, 0x00, 0x00, 0xfa, 0xff, 0x00, 0x00, |
| 0x08, 0x00, 0x08, 0x00, 0xa0, 0x71, 0x80, 0x03, 0x00, 0x03, 0x01, 0x00, |
| 0x1c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x3c, 0x14, 0x00, 0x00, |
| 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x00, 0x08, 0x00, 0x06, 0x00, |
| 0x98, 0x08, 0x00, 0x00, 0x1c, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, |
| 0x50, 0x14, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x00, |
| 0x08, 0x00, 0x06, 0x00, 0x98, 0x08, 0x00, 0x00, 0x1c, 0x00, 0x02, 0x00, |
| 0x08, 0x00, 0x01, 0x00, 0x64, 0x14, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, |
| 0x04, 0x00, 0x03, 0x00, 0x08, 0x00, 0x06, 0x00, 0x98, 0x08, 0x00, 0x00, |
| 0x1c, 0x00, 0x03, 0x00, 0x08, 0x00, 0x01, 0x00, 0x78, 0x14, 0x00, 0x00, |
| 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x00, 0x08, 0x00, 0x06, 0x00, |
| 0x98, 0x08, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x08, 0x00, 0x01, 0x00, |
| 0x8c, 0x14, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x00, |
| 0x04, 0x00, 0x05, 0x00, 0x08, 0x00, 0x06, 0x00, 0x98, 0x08, 0x00, 0x00, |
| 0x20, 0x00, 0x05, 0x00, 0x08, 0x00, 0x01, 0x00, 0xa0, 0x14, 0x00, 0x00, |
| 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, |
| 0x08, 0x00, 0x06, 0x00, 0x98, 0x08, 0x00, 0x00, 0x20, 0x00, 0x06, 0x00, |
| 0x08, 0x00, 0x01, 0x00, 0xb4, 0x14, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, |
| 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x08, 0x00, 0x06, 0x00, |
| 0x98, 0x08, 0x00, 0x00, 0x20, 0x00, 0x07, 0x00, 0x08, 0x00, 0x01, 0x00, |
| 0xc8, 0x14, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x00, |
| 0x04, 0x00, 0x05, 0x00, 0x08, 0x00, 0x06, 0x00, 0x98, 0x08, 0x00, 0x00, |
| 0x20, 0x00, 0x08, 0x00, 0x08, 0x00, 0x01, 0x00, 0x7c, 0x15, 0x00, 0x00, |
| 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, |
| 0x08, 0x00, 0x06, 0x00, 0x98, 0x08, 0x00, 0x00, 0x20, 0x00, 0x09, 0x00, |
| 0x08, 0x00, 0x01, 0x00, 0x90, 0x15, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, |
| 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x08, 0x00, 0x06, 0x00, |
| 0x98, 0x08, 0x00, 0x00, 0x20, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x01, 0x00, |
| 0xa4, 0x15, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x00, |
| 0x04, 0x00, 0x05, 0x00, 0x08, 0x00, 0x06, 0x00, 0x98, 0x08, 0x00, 0x00, |
| 0x20, 0x00, 0x0b, 0x00, 0x08, 0x00, 0x01, 0x00, 0xb8, 0x15, 0x00, 0x00, |
| 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, |
| 0x08, 0x00, 0x06, 0x00, 0x98, 0x08, 0x00, 0x00, 0x20, 0x00, 0x0c, 0x00, |
| 0x08, 0x00, 0x01, 0x00, 0xcc, 0x15, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, |
| 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x08, 0x00, 0x06, 0x00, |
| 0x98, 0x08, 0x00, 0x00, 0x20, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x01, 0x00, |
| 0xe0, 0x15, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x00, |
| 0x04, 0x00, 0x05, 0x00, 0x08, 0x00, 0x06, 0x00, 0x98, 0x08, 0x00, 0x00, |
| 0x20, 0x00, 0x0e, 0x00, 0x08, 0x00, 0x01, 0x00, 0xf4, 0x15, 0x00, 0x00, |
| 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, |
| 0x08, 0x00, 0x06, 0x00, 0x98, 0x08, 0x00, 0x00, 0x20, 0x00, 0x0f, 0x00, |
| 0x08, 0x00, 0x01, 0x00, 0x08, 0x16, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, |
| 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x08, 0x00, 0x06, 0x00, |
| 0x98, 0x08, 0x00, 0x00, 0x20, 0x00, 0x10, 0x00, 0x08, 0x00, 0x01, 0x00, |
| 0x1c, 0x16, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x00, |
| 0x04, 0x00, 0x05, 0x00, 0x08, 0x00, 0x06, 0x00, 0x98, 0x08, 0x00, 0x00, |
| 0x20, 0x00, 0x11, 0x00, 0x08, 0x00, 0x01, 0x00, 0x30, 0x16, 0x00, 0x00, |
| 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, |
| 0x08, 0x00, 0x06, 0x00, 0x98, 0x08, 0x00, 0x00, 0x20, 0x00, 0x12, 0x00, |
| 0x08, 0x00, 0x01, 0x00, 0x44, 0x16, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, |
| 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x08, 0x00, 0x06, 0x00, |
| 0x98, 0x08, 0x00, 0x00, 0x20, 0x00, 0x13, 0x00, 0x08, 0x00, 0x01, 0x00, |
| 0x58, 0x16, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x00, |
| 0x04, 0x00, 0x05, 0x00, 0x08, 0x00, 0x06, 0x00, 0x98, 0x08, 0x00, 0x00, |
| 0x1c, 0x00, 0x14, 0x00, 0x08, 0x00, 0x01, 0x00, 0x71, 0x16, 0x00, 0x00, |
| 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x00, 0x08, 0x00, 0x06, 0x00, |
| 0x98, 0x08, 0x00, 0x00, 0x1c, 0x00, 0x15, 0x00, 0x08, 0x00, 0x01, 0x00, |
| 0x85, 0x16, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x00, |
| 0x08, 0x00, 0x06, 0x00, 0x98, 0x08, 0x00, 0x00, 0x1c, 0x00, 0x16, 0x00, |
| 0x08, 0x00, 0x01, 0x00, 0x99, 0x16, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, |
| 0x04, 0x00, 0x03, 0x00, 0x08, 0x00, 0x06, 0x00, 0x98, 0x08, 0x00, 0x00, |
| 0x1c, 0x00, 0x17, 0x00, 0x08, 0x00, 0x01, 0x00, 0xad, 0x16, 0x00, 0x00, |
| 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x00, 0x08, 0x00, 0x06, 0x00, |
| 0x98, 0x08, 0x00, 0x00, 0x1c, 0x00, 0x18, 0x00, 0x08, 0x00, 0x01, 0x00, |
| 0xc1, 0x16, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x00, |
| 0x08, 0x00, 0x06, 0x00, 0x98, 0x08, 0x00, 0x00, 0x64, 0x00, 0x02, 0x00, |
| 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x3c, 0x00, 0x00, 0x00, |
| 0x0c, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x5a, 0x00, 0x00, 0x00, |
| 0x0c, 0x00, 0x02, 0x00, 0x08, 0x00, 0x01, 0x00, 0x78, 0x00, 0x00, 0x00, |
| 0x0c, 0x00, 0x03, 0x00, 0x08, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x00, |
| 0x0c, 0x00, 0x04, 0x00, 0x08, 0x00, 0x01, 0x00, 0xf0, 0x00, 0x00, 0x00, |
| 0x0c, 0x00, 0x05, 0x00, 0x08, 0x00, 0x01, 0x00, 0x68, 0x01, 0x00, 0x00, |
| 0x0c, 0x00, 0x06, 0x00, 0x08, 0x00, 0x01, 0x00, 0xe0, 0x01, 0x00, 0x00, |
| 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x01, 0x00, 0x1c, 0x02, 0x00, 0x00, |
| 0xdc, 0x00, 0x32, 0x00, 0x08, 0x00, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, |
| 0x08, 0x00, 0x02, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0x00, |
| 0x0b, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00, |
| 0x08, 0x00, 0x05, 0x00, 0x13, 0x00, 0x00, 0x00, 0x08, 0x00, 0x06, 0x00, |
| 0x19, 0x00, 0x00, 0x00, 0x08, 0x00, 0x07, 0x00, 0x25, 0x00, 0x00, 0x00, |
| 0x08, 0x00, 0x08, 0x00, 0x26, 0x00, 0x00, 0x00, 0x08, 0x00, 0x09, 0x00, |
| 0x27, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0a, 0x00, 0x28, 0x00, 0x00, 0x00, |
| 0x08, 0x00, 0x0b, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, |
| 0x37, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0d, 0x00, 0x39, 0x00, 0x00, 0x00, |
| 0x08, 0x00, 0x0e, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0f, 0x00, |
| 0x43, 0x00, 0x00, 0x00, 0x08, 0x00, 0x10, 0x00, 0x31, 0x00, 0x00, 0x00, |
| 0x08, 0x00, 0x11, 0x00, 0x41, 0x00, 0x00, 0x00, 0x08, 0x00, 0x12, 0x00, |
| 0x42, 0x00, 0x00, 0x00, 0x08, 0x00, 0x13, 0x00, 0x4b, 0x00, 0x00, 0x00, |
| 0x08, 0x00, 0x14, 0x00, 0x54, 0x00, 0x00, 0x00, 0x08, 0x00, 0x15, 0x00, |
| 0x57, 0x00, 0x00, 0x00, 0x08, 0x00, 0x16, 0x00, 0x55, 0x00, 0x00, 0x00, |
| 0x08, 0x00, 0x17, 0x00, 0x59, 0x00, 0x00, 0x00, 0x08, 0x00, 0x18, 0x00, |
| 0x5c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x19, 0x00, 0x2d, 0x00, 0x00, 0x00, |
| 0x08, 0x00, 0x1a, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x08, 0x00, 0x1b, 0x00, |
| 0x30, 0x00, 0x00, 0x00, 0x08, 0x00, 0x6f, 0x00, 0x10, 0x27, 0x00, 0x00, |
| 0x04, 0x00, 0x6c, 0x00, 0x30, 0x04, 0x63, 0x00, 0x04, 0x00, 0x00, 0x00, |
| 0x84, 0x00, 0x01, 0x00, 0x06, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x30, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0x40, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0x50, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x60, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0x70, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0x80, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x90, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0xb0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xc0, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0xe0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xf0, 0x00, 0x00, 0x00, |
| 0x84, 0x00, 0x02, 0x00, 0x06, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x30, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0x40, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0x50, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x60, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0x70, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0x80, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x90, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0xb0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xc0, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0xe0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xf0, 0x00, 0x00, 0x00, |
| 0x84, 0x00, 0x03, 0x00, 0x06, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x30, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0x40, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0x50, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x60, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0x70, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0x80, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x90, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0xb0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xc0, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0xe0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xf0, 0x00, 0x00, 0x00, |
| 0x84, 0x00, 0x04, 0x00, 0x06, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x30, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0x40, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0x50, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x60, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0x70, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0x80, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x90, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0xb0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xc0, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0xe0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xf0, 0x00, 0x00, 0x00, |
| 0x04, 0x00, 0x05, 0x00, 0x04, 0x00, 0x06, 0x00, 0x84, 0x00, 0x07, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x20, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0x30, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0x40, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x50, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0x60, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0x70, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x80, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0x90, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0xa0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xb0, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0xd0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xe0, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x84, 0x00, 0x08, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x20, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0x30, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0x40, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x50, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0x60, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0x70, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x80, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0x90, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0xa0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xb0, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0xd0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xe0, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x84, 0x00, 0x09, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x20, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0x30, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0x40, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x50, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0x60, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0x70, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x80, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0x90, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0xa0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xb0, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0xd0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xe0, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x84, 0x00, 0x0a, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x20, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0x30, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0x40, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x50, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0x60, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0x70, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x80, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0x90, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0xa0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xb0, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0xd0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xe0, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x40, 0x01, 0x64, 0x00, |
| 0x04, 0x00, 0x00, 0x00, 0x24, 0x00, 0x01, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0x40, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xb0, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0xd0, 0x00, 0x00, 0x00, 0x14, 0x00, 0x02, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0x40, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xd0, 0x00, 0x00, 0x00, |
| 0x3c, 0x00, 0x03, 0x00, 0x06, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0x40, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xa0, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0xc0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xd0, 0x00, 0x00, 0x00, |
| 0x3c, 0x00, 0x04, 0x00, 0x06, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0x40, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xa0, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0xc0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xd0, 0x00, 0x00, 0x00, |
| 0x04, 0x00, 0x05, 0x00, 0x04, 0x00, 0x06, 0x00, 0x1c, 0x00, 0x07, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0xc0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xd0, 0x00, 0x00, 0x00, |
| 0x14, 0x00, 0x08, 0x00, 0x06, 0x00, 0x65, 0x00, 0x40, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x09, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x40, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0xb0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xc0, 0x00, 0x00, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x14, 0x00, 0x0a, 0x00, |
| 0x06, 0x00, 0x65, 0x00, 0x40, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, |
| 0xd0, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x76, 0x00, 0x04, 0x00, 0x02, 0x00, |
| 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x04, 0x00, 0x06, 0x00, |
| 0x04, 0x00, 0x07, 0x00, 0x04, 0x00, 0x08, 0x00, 0x04, 0x00, 0x09, 0x00, |
| 0x14, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, |
| 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x12, 0x00, |
| 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x79, 0x00, 0x04, 0x00, 0x04, 0x00, |
| 0x04, 0x00, 0x06, 0x00, 0x60, 0x00, 0x78, 0x00, 0x5c, 0x00, 0x01, 0x00, |
| 0x48, 0x00, 0x01, 0x00, 0x14, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, |
| 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x04, 0x00, 0x02, 0x00, |
| 0x1c, 0x00, 0x02, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, |
| 0x10, 0x00, 0x02, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x08, 0x00, |
| 0x04, 0x00, 0x09, 0x00, 0x14, 0x00, 0x03, 0x00, 0x08, 0x00, 0x01, 0x00, |
| 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x04, 0x00, 0x0a, 0x00, |
| 0x08, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, |
| 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x8f, 0x00, 0xe3, 0x1a, 0x00, 0x07, |
| 0x1e, 0x00, 0x94, 0x00, 0x63, 0x48, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0xa9, 0x00, |
| 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x0c, 0x00, 0xaa, 0x00, |
| 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40}; |
| |
| const char kIPV4Address0[] = "192.168.10.20"; |
| const char kIPV4Address1[] = "1.2.3.4"; |
| const char kIPV6Address0[] = "FEDC:BA98:7654:3210:FEDC:BA98:7654:3210"; |
| const char kIPV6Address1[] = "1080:0:0:0:8:800:200C:417A"; |
| const char kHardwareAddress[] = "00A0C914C829"; |
| |
| const int64_t kSuspendDurationSecs = 15; |
| const uint32_t kNewWiphyNlMsg_MinPatternLen = 16; |
| |
| #if !defined(DISABLE_WAKE_ON_WIFI) |
| |
| // Zero-byte pattern prefixes to match the offsetting bytes in the Ethernet |
| // frame that lie before the source IP address field. |
| const uint8_t kIPV4PatternPrefix[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00}; |
| const uint8_t kIPV6PatternPrefix[] = { |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; |
| |
| // These masks have bits set to 1 to match bytes in an IP address pattern that |
| // represent the source IP address of the frame. They are padded with zero |
| // bits in front to ignore the frame offset and at the end to byte-align the |
| // mask itself. |
| const uint8_t kIPV4MaskBytes[] = {0x00, 0x00, 0x00, 0x3c}; |
| const uint8_t kIPV6MaskBytes[] = {0x00, 0x00, 0xc0, 0xff, 0x3f}; |
| |
| const uint8_t KIPV4ProtocolTypeMaskBytes[] = {0x3f, 0x30, 0x80}; |
| const uint8_t KIPV6ProtocolTypeMaskBytes[] = {0x3f, 0x30, 0x10}; |
| |
| const uint8_t kIPV4Address0Bytes[] = {0xc0, 0xa8, 0x0a, 0x14}; |
| const uint8_t kIPV4Address1Bytes[] = {0x01, 0x02, 0x03, 0x04}; |
| |
| const uint8_t kIPV6Address0Bytes[] = {0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, |
| 0x32, 0x10, 0xfe, 0xdc, 0xba, 0x98, |
| 0x76, 0x54, 0x32, 0x10}; |
| const uint8_t kIPV6Address1Bytes[] = {0x10, 0x80, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, |
| 0x20, 0x0c, 0x41, 0x7a}; |
| const char kIPV6Address2[] = "1080::8:800:200C:417A"; |
| const uint8_t kIPV6Address2Bytes[] = {0x10, 0x80, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, |
| 0x20, 0x0c, 0x41, 0x7a}; |
| const char kIPV6Address3[] = "FF01::101"; |
| const uint8_t kIPV6Address3Bytes[] = {0xff, 0x01, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x01, 0x01}; |
| const char kIPV6Address4[] = "::1"; |
| const uint8_t kIPV6Address4Bytes[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x01}; |
| const char kIPV6Address5[] = "::"; |
| const uint8_t kIPV6Address5Bytes[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00}; |
| const char kIPV6Address6[] = "0:0:0:0:0:FFFF:129.144.52.38"; |
| const uint8_t kIPV6Address6Bytes[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, |
| 0x81, 0x90, 0x34, 0x26}; |
| const char kIPV6Address7[] = "::DEDE:190.144.52.38"; |
| const uint8_t kIPV6Address7Bytes[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0xde, 0xde, |
| 0xbe, 0x90, 0x34, 0x26}; |
| const uint32_t kNewWiphyNlMsg_MaxPatterns = 20; |
| const uint32_t kNewWiphyNlMsg_MaxSSIDs = 11; |
| const int kNewWiphyNlMsg_PattSupportOffset = 3300; |
| const int kNewWiphyNlMsg_WowlanTrigNetDetectAttributeOffset = 3316; |
| const int kNewWiphyNlMsg_WowlanTrigDisconnectAttributeOffset = 3268; |
| |
| const uint32_t kSSID1FreqMatches[] = {2412, 2437, 2462, 5180, |
| 5240, 5745, 5805, 5825}; |
| |
| const uint32_t kWakeReasonNlMsg_WiphyIndex = 0; |
| // NL80211_CMD_GET_WOWLAN message with nlmsg_type 0x16, which is different from |
| // kNl80211FamilyId (0x13). |
| const uint8_t kWrongMessageTypeNlMsg[] = { |
| 0x14, 0x00, 0x00, 0x00, 0x16, 0x00, 0x01, 0x00, 0x01, 0x00, |
| 0x00, 0x00, 0x57, 0x40, 0x00, 0x00, 0x49, 0x01, 0x00, 0x00}; |
| // Bytes representing a NL80211_CMD_SET_WOWLAN reporting that the system woke |
| // up because of a reason other than wake on WiFi. |
| const uint8_t kWakeReasonUnsupportedNlMsg[] = { |
| 0x30, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x4a, 0x01, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x99, 0x00, 0x01, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00}; |
| // Bytes representing a NL80211_CMD_SET_WOWLAN reporting that the system woke |
| // up because of a disconnect. |
| const uint8_t kWakeReasonDisconnectNlMsg[] = { |
| 0x38, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x4a, 0x01, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x99, 0x00, 0x01, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, |
| 0x08, 0x00, 0x75, 0x00, 0x04, 0x00, 0x02, 0x00}; |
| // Bytes representing a NL80211_CMD_SET_WOWLAN reporting that the system woke |
| // up because of a a match with packet pattern index |
| // kWakeReasonPatternNlMsg_PattIndex. |
| const uint8_t kWakeReasonPatternNlMsg[] = { |
| 0xac, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x4a, 0x01, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x99, 0x00, 0x01, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, |
| 0x7c, 0x00, 0x75, 0x00, 0x08, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x08, 0x00, 0x0d, 0x00, 0x62, 0x00, 0x00, 0x00, 0x66, 0x00, 0x0c, 0x00, |
| 0x6c, 0x29, 0x95, 0x16, 0x54, 0x68, 0x6c, 0x71, 0xd9, 0x8b, 0x3c, 0x6c, |
| 0x08, 0x00, 0x45, 0x00, 0x00, 0x54, 0x00, 0x00, 0x40, 0x00, 0x40, 0x01, |
| 0xb7, 0xdd, 0xc0, 0xa8, 0x00, 0xfe, 0xc0, 0xa8, 0x00, 0x7d, 0x08, 0x00, |
| 0x3f, 0x51, 0x28, 0x64, 0x00, 0x01, 0xb1, 0x0b, 0xd0, 0x54, 0x00, 0x00, |
| 0x00, 0x00, 0x4b, 0x16, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, |
| 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, |
| 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, |
| 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, |
| 0x36, 0x37, 0x00, 0x00}; |
| const uint32_t kWakeReasonPatternNlMsg_PattIndex = 0; |
| const uint8_t kDstHWAddressPatternBytes[] = {0x00, 0xA0, 0xC9, |
| 0x14, 0xc8, 0x29}; |
| const uint8_t KIPV4ProtocolTypeSuffixBytesForTCP[] = { |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06}; |
| const uint8_t KIPV4ProtocolTypeSuffixBytesForUDP[] = { |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11}; |
| const uint8_t KIPV6ProtocolTypeSuffixBytesForTCP[] = { |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0xDD, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06}; |
| const uint8_t KIPV6ProtocolTypeSuffixBytesForUDP[] = { |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0xDD, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11}; |
| |
| #endif // DISABLE_WAKE_ON_WIFI |
| |
| } // namespace |
| |
| class WakeOnWiFiTest : public ::testing::Test { |
| public: |
| WakeOnWiFiTest() = default; |
| ~WakeOnWiFiTest() override = default; |
| |
| void SetUp() override { |
| Nl80211Message::SetMessageType(kNl80211FamilyId); |
| // Assume our NIC has reported its wiphy index, and that it supports wake |
| // all wake triggers. |
| wake_on_wifi_->wiphy_index_received_ = true; |
| wake_on_wifi_->wake_on_wifi_triggers_supported_.insert( |
| WakeOnWiFi::kWakeTriggerPattern); |
| wake_on_wifi_->wake_on_wifi_triggers_supported_.insert( |
| WakeOnWiFi::kWakeTriggerDisconnect); |
| wake_on_wifi_->wake_on_wifi_triggers_supported_.insert( |
| WakeOnWiFi::kWakeTriggerSSID); |
| // By default our tests assume that the NIC supports more SSIDs than |
| // whitelisted SSIDs. |
| wake_on_wifi_->wake_on_wifi_max_ssids_ = 999; |
| wake_on_wifi_->dark_resume_history_.time_ = &time_; |
| |
| ON_CALL(netlink_manager_, SendNl80211Message(_, _, _, _)) |
| .WillByDefault(Return(true)); |
| } |
| |
| void SetWakeOnWiFiMaxSSIDs(uint32_t max_ssids) { |
| wake_on_wifi_->wake_on_wifi_max_ssids_ = max_ssids; |
| } |
| |
| void EnableWakeOnWiFiFeaturesPacket() { |
| wake_on_wifi_->wake_on_wifi_features_enabled_ = |
| kWakeOnWiFiFeaturesEnabledPacket; |
| } |
| |
| void EnableWakeOnWiFiFeaturesDarkConnect() { |
| wake_on_wifi_->wake_on_wifi_features_enabled_ = |
| kWakeOnWiFiFeaturesEnabledDarkConnect; |
| } |
| |
| void EnableWakeOnWiFiFeaturesPacketDarkConnect() { |
| wake_on_wifi_->wake_on_wifi_features_enabled_ = |
| kWakeOnWiFiFeaturesEnabledPacketDarkConnect; |
| } |
| |
| void SetWakeOnWiFiFeaturesNotSupported() { |
| wake_on_wifi_->wake_on_wifi_features_enabled_ = |
| kWakeOnWiFiFeaturesEnabledNotSupported; |
| } |
| |
| void DisableWakeOnWiFiFeatures() { |
| wake_on_wifi_->wake_on_wifi_features_enabled_ = |
| kWakeOnWiFiFeaturesEnabledNone; |
| } |
| |
| void AddWakeOnPacketConnection(const string& ip_endpoint, Error* error) { |
| wake_on_wifi_->AddWakeOnPacketConnection(ip_endpoint, error); |
| } |
| |
| void RemoveWakeOnPacketConnection(const string& ip_endpoint, Error* error) { |
| wake_on_wifi_->RemoveWakeOnPacketConnection(ip_endpoint, error); |
| } |
| |
| void RemoveAllWakeOnPacketConnections(Error* error) { |
| wake_on_wifi_->RemoveAllWakeOnPacketConnections(error); |
| } |
| |
| void AddWakeOnPacketOfTypes(const std::vector<std::string>& packet_types, |
| Error* error) { |
| wake_on_wifi_->AddWakeOnPacketOfTypes(packet_types, error); |
| } |
| |
| void RemoveWakeOnPacketOfTypes(const std::vector<std::string>& packet_types, |
| Error* error) { |
| wake_on_wifi_->RemoveWakeOnPacketOfTypes(packet_types, error); |
| } |
| |
| bool CreateIPAddressPatternAndMask(const IPAddress& ip_addr, |
| ByteString* pattern, |
| ByteString* mask, |
| uint32_t min_pattern_len) { |
| return WakeOnWiFi::CreateIPAddressPatternAndMask(ip_addr, min_pattern_len, |
| pattern, mask); |
| } |
| |
| void CreatePacketTypePatternAndMaskforIPV6( |
| const std::basic_string<char>& mac_address, |
| ByteString* pattern, |
| ByteString* mask, |
| uint32_t min_pattern_len, |
| uint8_t ip_protocol) { |
| WakeOnWiFi::CreatePacketTypePatternAndMaskforIPV6( |
| mac_address, min_pattern_len, ip_protocol, pattern, mask); |
| } |
| |
| void CreatePacketTypePatternAndMaskforIPV4( |
| const std::basic_string<char>& mac_address, |
| ByteString* pattern, |
| ByteString* mask, |
| uint32_t min_pattern_len, |
| uint8_t ip_protocol) { |
| WakeOnWiFi::CreatePacketTypePatternAndMaskforIPV4( |
| mac_address, min_pattern_len, ip_protocol, pattern, mask); |
| } |
| |
| bool ConvertIPProtoStrtoEnum(const std::vector<std::string>& ip_proto_strs, |
| set<uint8_t>* ip_proto_enums, |
| Error* error) { |
| return WakeOnWiFi::ConvertIPProtoStrtoEnum(ip_proto_strs, ip_proto_enums, |
| error); |
| } |
| |
| bool ConfigureWiphyIndex(Nl80211Message* msg, int32_t index) { |
| return WakeOnWiFi::ConfigureWiphyIndex(msg, index); |
| } |
| |
| bool ConfigureDisableWakeOnWiFiMessage(SetWakeOnPacketConnMessage* msg, |
| uint32_t wiphy_index, |
| Error* error) { |
| return WakeOnWiFi::ConfigureDisableWakeOnWiFiMessage(msg, wiphy_index, |
| error); |
| } |
| |
| bool WakeOnWiFiSettingsMatch(const Nl80211Message& msg, |
| const set<WakeOnWiFi::WakeOnWiFiTrigger>& trigs, |
| const IPAddressStore& addrs, |
| uint32_t net_detect_scan_period_seconds, |
| set<uint8_t> wake_on_packet_types, |
| const std::string& mac_address, |
| const vector<ByteString>& ssid_whitelist) { |
| return WakeOnWiFi::WakeOnWiFiSettingsMatch( |
| msg, trigs, addrs, net_detect_scan_period_seconds, wake_on_packet_types, |
| mac_address, kNewWiphyNlMsg_MinPatternLen, ssid_whitelist); |
| } |
| |
| bool ConfigureSetWakeOnWiFiSettingsMessage( |
| SetWakeOnPacketConnMessage* msg, |
| const set<WakeOnWiFi::WakeOnWiFiTrigger>& trigs, |
| const IPAddressStore& addrs, |
| uint32_t wiphy_index, |
| const set<uint8_t> wake_on_packet_types, |
| const std::string& mac_address, |
| uint32_t net_detect_scan_period_seconds, |
| const vector<ByteString>& ssid_whitelist, |
| Error* error) { |
| return WakeOnWiFi::ConfigureSetWakeOnWiFiSettingsMessage( |
| msg, trigs, addrs, wiphy_index, wake_on_packet_types, mac_address, |
| kNewWiphyNlMsg_MinPatternLen, net_detect_scan_period_seconds, |
| ssid_whitelist, error); |
| } |
| |
| void RequestWakeOnPacketSettings() { |
| wake_on_wifi_->RequestWakeOnPacketSettings(); |
| } |
| |
| void VerifyWakeOnWiFiSettings(const Nl80211Message& nl80211_message) { |
| wake_on_wifi_->VerifyWakeOnWiFiSettings(nl80211_message); |
| } |
| |
| size_t GetWakeOnWiFiMaxPatterns() { |
| return wake_on_wifi_->wake_on_wifi_max_patterns_; |
| } |
| |
| uint32_t GetWakeOnWiFiMaxSSIDs() { |
| return wake_on_wifi_->wake_on_wifi_max_ssids_; |
| } |
| |
| void SetWakeOnWiFiMaxPatterns(size_t max_patterns) { |
| wake_on_wifi_->wake_on_wifi_max_patterns_ = max_patterns; |
| } |
| |
| void ApplyWakeOnWiFiSettings() { wake_on_wifi_->ApplyWakeOnWiFiSettings(); } |
| |
| void DisableWakeOnWiFi() { wake_on_wifi_->DisableWakeOnWiFi(); } |
| |
| set<WakeOnWiFi::WakeOnWiFiTrigger>* GetWakeOnWiFiTriggers() { |
| return &wake_on_wifi_->wake_on_wifi_triggers_; |
| } |
| |
| set<WakeOnWiFi::WakeOnWiFiTrigger>* GetWakeOnWiFiTriggersSupported() { |
| return &wake_on_wifi_->wake_on_wifi_triggers_supported_; |
| } |
| |
| void ClearWakeOnWiFiTriggersSupported() { |
| wake_on_wifi_->wake_on_wifi_triggers_supported_.clear(); |
| } |
| |
| IPAddressStore* GetWakeOnPacketConnections() { |
| return &wake_on_wifi_->wake_on_packet_connections_; |
| } |
| |
| set<uint8_t> GetWakeOnPacketTypes() { |
| return wake_on_wifi_->wake_on_packet_types_; |
| } |
| |
| void RetrySetWakeOnPacketConnections() { |
| wake_on_wifi_->RetrySetWakeOnPacketConnections(); |
| } |
| |
| void SetSuspendActionsDoneCallback() { |
| wake_on_wifi_->suspend_actions_done_callback_ = |
| Bind(&WakeOnWiFiTest::DoneCallback, Unretained(this)); |
| } |
| |
| void ResetSuspendActionsDoneCallback() { |
| wake_on_wifi_->suspend_actions_done_callback_.Reset(); |
| } |
| |
| bool SuspendActionsCallbackIsNull() { |
| return wake_on_wifi_->suspend_actions_done_callback_.is_null(); |
| } |
| |
| void RunSuspendActionsCallback(const Error& error) { |
| wake_on_wifi_->suspend_actions_done_callback_.Run(error); |
| } |
| |
| int GetNumSetWakeOnPacketRetries() { |
| return wake_on_wifi_->num_set_wake_on_packet_retries_; |
| } |
| |
| void SetConnectedBeforeSuspend(bool was_connected) { |
| wake_on_wifi_->connected_before_suspend_ = was_connected; |
| } |
| |
| void SetNumSetWakeOnPacketRetries(int retries) { |
| wake_on_wifi_->num_set_wake_on_packet_retries_ = retries; |
| } |
| |
| void OnBeforeSuspend(bool is_connected, |
| const vector<ByteString>& ssid_whitelist, |
| bool have_dhcp_lease, |
| uint32_t time_to_next_lease_renewal) { |
| ResultCallback done_callback( |
| Bind(&WakeOnWiFiTest::DoneCallback, Unretained(this))); |
| Closure renew_dhcp_lease_callback( |
| Bind(&WakeOnWiFiTest::RenewDHCPLeaseCallback, Unretained(this))); |
| Closure remove_supplicant_networks_callback(Bind( |
| &WakeOnWiFiTest::RemoveSupplicantNetworksCallback, Unretained(this))); |
| wake_on_wifi_->OnBeforeSuspend(is_connected, ssid_whitelist, done_callback, |
| renew_dhcp_lease_callback, |
| remove_supplicant_networks_callback, |
| have_dhcp_lease, time_to_next_lease_renewal); |
| } |
| |
| void OnDarkResume(bool is_connected, |
| const vector<ByteString>& ssid_whitelist) { |
| ResultCallback done_callback( |
| Bind(&WakeOnWiFiTest::DoneCallback, Unretained(this))); |
| Closure renew_dhcp_lease_callback( |
| Bind(&WakeOnWiFiTest::RenewDHCPLeaseCallback, Unretained(this))); |
| WakeOnWiFi::InitiateScanCallback initiate_scan_callback( |
| Bind(&WakeOnWiFiTest::InitiateScanCallback, Unretained(this))); |
| Closure remove_supplicant_networks_callback(Bind( |
| &WakeOnWiFiTest::RemoveSupplicantNetworksCallback, Unretained(this))); |
| wake_on_wifi_->OnDarkResume( |
| is_connected, ssid_whitelist, done_callback, renew_dhcp_lease_callback, |
| initiate_scan_callback, remove_supplicant_networks_callback); |
| } |
| |
| void OnAfterResume() { wake_on_wifi_->OnAfterResume(); } |
| |
| void BeforeSuspendActions(bool is_connected, |
| bool start_lease_renewal_timer, |
| uint32_t time_to_next_lease_renewal) { |
| SetDarkResumeActionsTimeOutCallback(); |
| EXPECT_FALSE(DarkResumeActionsTimeOutCallbackIsCancelled()); |
| EXPECT_CALL(metrics_, |
| NotifyBeforeSuspendActions(is_connected, GetInDarkResume())); |
| Closure remove_supplicant_networks_callback(Bind( |
| &WakeOnWiFiTest::RemoveSupplicantNetworksCallback, Unretained(this))); |
| wake_on_wifi_->BeforeSuspendActions(is_connected, start_lease_renewal_timer, |
| time_to_next_lease_renewal, |
| remove_supplicant_networks_callback); |
| EXPECT_TRUE(DarkResumeActionsTimeOutCallbackIsCancelled()); |
| } |
| |
| void OnConnectedAndReachable(bool start_lease_renewal_timer, |
| uint32_t time_to_next_lease_renewal) { |
| wake_on_wifi_->OnConnectedAndReachable(start_lease_renewal_timer, |
| time_to_next_lease_renewal); |
| } |
| |
| void SetInDarkResume(bool val) { wake_on_wifi_->in_dark_resume_ = val; } |
| |
| bool GetInDarkResume() { return wake_on_wifi_->in_dark_resume_; } |
| |
| void SetWiphyIndexReceivedToFalse() { |
| wake_on_wifi_->wiphy_index_received_ = false; |
| } |
| |
| void SetWiphyIndex(uint32_t wiphy_index) { |
| wake_on_wifi_->wiphy_index_ = wiphy_index; |
| } |
| |
| void ParseWakeOnWiFiCapabilities(const Nl80211Message& nl80211_message) { |
| wake_on_wifi_->ParseWakeOnWiFiCapabilities(nl80211_message); |
| } |
| |
| bool SetWakeOnWiFiFeaturesEnabled(const std::string& enabled, Error* error) { |
| return wake_on_wifi_->SetWakeOnWiFiFeaturesEnabled(enabled, error); |
| } |
| |
| const string& GetWakeOnWiFiFeaturesEnabled() { |
| return wake_on_wifi_->wake_on_wifi_features_enabled_; |
| } |
| |
| void SetDarkResumeActionsTimeOutCallback() { |
| wake_on_wifi_->dark_resume_actions_timeout_callback_.Reset(Bind( |
| &WakeOnWiFiTest::DarkResumeActionsTimeoutCallback, Unretained(this))); |
| } |
| |
| bool DarkResumeActionsTimeOutCallbackIsCancelled() { |
| return wake_on_wifi_->dark_resume_actions_timeout_callback_.IsCancelled(); |
| } |
| |
| void StartDHCPLeaseRenewalTimer() { |
| wake_on_wifi_->dhcp_lease_renewal_timer_.Start( |
| FROM_HERE, base::TimeDelta::FromSeconds(kTimeToNextLeaseRenewalLong), |
| Bind(&WakeOnWiFiTest::OnTimerWakeDoNothing, Unretained(this))); |
| } |
| |
| void StartWakeToScanTimer() { |
| wake_on_wifi_->wake_to_scan_timer_.Start( |
| FROM_HERE, base::TimeDelta::FromSeconds(kTimeToNextLeaseRenewalLong), |
| Bind(&WakeOnWiFiTest::OnTimerWakeDoNothing, Unretained(this))); |
| } |
| |
| void StopDHCPLeaseRenewalTimer() { |
| wake_on_wifi_->dhcp_lease_renewal_timer_.Stop(); |
| } |
| |
| void StopWakeToScanTimer() { wake_on_wifi_->wake_to_scan_timer_.Stop(); } |
| |
| bool DHCPLeaseRenewalTimerIsRunning() { |
| return wake_on_wifi_->dhcp_lease_renewal_timer_.IsRunning(); |
| } |
| |
| bool WakeToScanTimerIsRunning() { |
| return wake_on_wifi_->wake_to_scan_timer_.IsRunning(); |
| } |
| |
| void SetDarkResumeActionsTimeoutMilliseconds(int64_t timeout) { |
| wake_on_wifi_->DarkResumeActionsTimeoutMilliseconds = timeout; |
| } |
| |
| void InitStateForDarkResume() { |
| SetInDarkResume(true); |
| GetWakeOnPacketConnections()->AddUnique(IPAddress("1.1.1.1")); |
| EnableWakeOnWiFiFeaturesPacketDarkConnect(); |
| SetDarkResumeActionsTimeoutMilliseconds(0); |
| } |
| |
| void SetExpectationsDisconnectedBeforeSuspend() { |
| EXPECT_TRUE(GetWakeOnWiFiTriggers()->empty()); |
| EXPECT_CALL(*this, DoneCallback(_)).Times(0); |
| EXPECT_CALL(*this, RemoveSupplicantNetworksCallback()).Times(1); |
| EXPECT_CALL(netlink_manager_, |
| SendNl80211Message( |
| IsNl80211Command(kNl80211FamilyId, |
| SetWakeOnPacketConnMessage::kCommand), |
| _, _, _)); |
| } |
| |
| void SetExpectationsConnectedBeforeSuspend() { |
| EXPECT_TRUE(GetWakeOnWiFiTriggers()->empty()); |
| EXPECT_CALL(*this, DoneCallback(_)).Times(0); |
| EXPECT_CALL(netlink_manager_, |
| SendNl80211Message( |
| IsNl80211Command(kNl80211FamilyId, |
| SetWakeOnPacketConnMessage::kCommand), |
| _, _, _)); |
| } |
| |
| void VerifyStateConnectedBeforeSuspend() { |
| EXPECT_TRUE(DarkResumeActionsTimeOutCallbackIsCancelled()); |
| EXPECT_FALSE(GetInDarkResume()); |
| EXPECT_EQ(GetWakeOnWiFiTriggers()->size(), 2); |
| EXPECT_TRUE( |
| GetWakeOnWiFiTriggers()->find(WakeOnWiFi::kWakeTriggerPattern) != |
| GetWakeOnWiFiTriggers()->end()); |
| EXPECT_TRUE( |
| GetWakeOnWiFiTriggers()->find(WakeOnWiFi::kWakeTriggerDisconnect) != |
| GetWakeOnWiFiTriggers()->end()); |
| } |
| |
| void VerifyStateDisconnectedBeforeSuspend() { |
| EXPECT_TRUE(DarkResumeActionsTimeOutCallbackIsCancelled()); |
| EXPECT_FALSE(GetInDarkResume()); |
| EXPECT_EQ(GetWakeOnWiFiTriggers()->size(), 1); |
| EXPECT_FALSE( |
| GetWakeOnWiFiTriggers()->find(WakeOnWiFi::kWakeTriggerPattern) != |
| GetWakeOnWiFiTriggers()->end()); |
| EXPECT_TRUE(GetWakeOnWiFiTriggers()->find(WakeOnWiFi::kWakeTriggerSSID) != |
| GetWakeOnWiFiTriggers()->end()); |
| } |
| |
| void ReportConnectedToServiceAfterWake(bool is_connected, |
| int seconds_in_suspend) { |
| wake_on_wifi_->ReportConnectedToServiceAfterWake(is_connected, |
| seconds_in_suspend); |
| } |
| |
| void OnNoAutoConnectableServicesAfterScan( |
| const vector<ByteString>& ssid_whitelist) { |
| Closure remove_supplicant_networks_callback(Bind( |
| &WakeOnWiFiTest::RemoveSupplicantNetworksCallback, Unretained(this))); |
| WakeOnWiFi::InitiateScanCallback initiate_scan_callback( |
| Bind(&WakeOnWiFiTest::InitiateScanCallback, Unretained(this))); |
| wake_on_wifi_->OnNoAutoConnectableServicesAfterScan( |
| ssid_whitelist, remove_supplicant_networks_callback, |
| initiate_scan_callback); |
| } |
| |
| EventHistory* GetDarkResumeHistory() { |
| return &wake_on_wifi_->dark_resume_history_; |
| } |
| |
| void SetNetDetectScanPeriodSeconds(uint32_t period) { |
| wake_on_wifi_->net_detect_scan_period_seconds_ = period; |
| } |
| |
| void AddSSIDToWhitelist(const uint8_t* ssid, |
| int num_bytes, |
| vector<ByteString>* whitelist) { |
| vector<uint8_t> ssid_vector(ssid, ssid + num_bytes); |
| whitelist->push_back(ByteString(ssid_vector)); |
| } |
| |
| vector<ByteString>* GetWakeOnSSIDWhitelist() { |
| return &wake_on_wifi_->wake_on_ssid_whitelist_; |
| } |
| |
| void OnWakeupReasonReceived(const NetlinkMessage& netlink_message) { |
| wake_on_wifi_->OnWakeupReasonReceived(netlink_message); |
| } |
| |
| WiFi::FreqSet ParseWakeOnSSIDResults(AttributeListConstRefPtr results_list) { |
| return wake_on_wifi_->ParseWakeOnSSIDResults(results_list); |
| } |
| |
| NetlinkMessage::MessageContext GetWakeupReportMsgContext() { |
| NetlinkMessage::MessageContext context; |
| context.nl80211_cmd = NL80211_CMD_SET_WOWLAN; |
| context.is_broadcast = true; |
| return context; |
| } |
| |
| void SetLastWakeReason(WakeOnWiFi::WakeOnWiFiTrigger reason) { |
| wake_on_wifi_->last_wake_reason_ = reason; |
| } |
| |
| WakeOnWiFi::WakeOnWiFiTrigger GetLastWakeReason() { |
| return wake_on_wifi_->last_wake_reason_; |
| } |
| |
| void OnScanStarted(bool is_active_scan) { |
| wake_on_wifi_->OnScanStarted(is_active_scan); |
| } |
| |
| const WiFi::FreqSet& GetLastSSIDMatchFreqs() { |
| return wake_on_wifi_->last_ssid_match_freqs_; |
| } |
| |
| void AddResultToLastSSIDResults() { |
| wake_on_wifi_->last_ssid_match_freqs_.insert(1); |
| } |
| |
| void InitiateScanInDarkResume(const WiFi::FreqSet& freqs) { |
| wake_on_wifi_->InitiateScanInDarkResume( |
| Bind(&WakeOnWiFiTest::InitiateScanCallback, Unretained(this)), freqs); |
| } |
| |
| int GetDarkResumeScanRetriesLeft() { |
| return wake_on_wifi_->dark_resume_scan_retries_left_; |
| } |
| |
| void SetDarkResumeScanRetriesLeft(int retries) { |
| wake_on_wifi_->dark_resume_scan_retries_left_ = retries; |
| } |
| |
| Timestamp GetTimestampBootTime(int boottime_seconds) { |
| struct timeval monotonic = {.tv_sec = 0, .tv_usec = 0}; |
| struct timeval boottime = {.tv_sec = boottime_seconds, .tv_usec = 0}; |
| return Timestamp(monotonic, boottime, ""); |
| } |
| |
| MOCK_METHOD(void, DoneCallback, (const Error&)); |
| MOCK_METHOD(void, RenewDHCPLeaseCallback, ()); |
| MOCK_METHOD(void, InitiateScanCallback, (const WiFi::FreqSet&)); |
| MOCK_METHOD(void, RemoveSupplicantNetworksCallback, ()); |
| MOCK_METHOD(void, DarkResumeActionsTimeoutCallback, ()); |
| MOCK_METHOD(void, OnTimerWakeDoNothing, ()); |
| MOCK_METHOD(void, RecordDarkResumeWakeReasonCallback, (const string&)); |
| |
| protected: |
| MockControl control_interface_; |
| MockMetrics metrics_; |
| MockNetlinkManager netlink_manager_; |
| MockTime time_; |
| std::unique_ptr<WakeOnWiFi> wake_on_wifi_; |
| }; |
| |
| class WakeOnWiFiTestWithDispatcher : public WakeOnWiFiTest { |
| public: |
| WakeOnWiFiTestWithDispatcher() : WakeOnWiFiTest() { |
| wake_on_wifi_.reset(new WakeOnWiFi( |
| &netlink_manager_, &dispatcher_, &metrics_, kHardwareAddress, |
| Bind(&WakeOnWiFiTest::RecordDarkResumeWakeReasonCallback, |
| Unretained(this)))); |
| } |
| virtual ~WakeOnWiFiTestWithDispatcher() = default; |
| |
| protected: |
| EventDispatcherForTest dispatcher_; |
| }; |
| |
| class WakeOnWiFiTestWithMockDispatcher : public WakeOnWiFiTest { |
| public: |
| WakeOnWiFiTestWithMockDispatcher() : WakeOnWiFiTest() { |
| wake_on_wifi_.reset(new WakeOnWiFi( |
| &netlink_manager_, &mock_dispatcher_, &metrics_, kHardwareAddress, |
| Bind(&WakeOnWiFiTest::RecordDarkResumeWakeReasonCallback, |
| Unretained(this)))); |
| } |
| virtual ~WakeOnWiFiTestWithMockDispatcher() = default; |
| |
| protected: |
| // TODO(zqiu): message loop is needed by AlarmTimer, should restructure the |
| // code so that it can be mocked out. |
| base::MessageLoopForIO message_loop_; |
| base::FileDescriptorWatcher watcher_{&message_loop_}; |
| MockEventDispatcher mock_dispatcher_; |
| }; |
| |
| ByteString CreatePattern(const unsigned char* prefix, |
| size_t prefix_len, |
| const unsigned char* addr, |
| size_t addr_len) { |
| ByteString result(prefix, prefix_len); |
| result.Append(ByteString(addr, addr_len)); |
| return result; |
| } |
| |
| ByteString CreateDstHWPattern(const unsigned char* addr, |
| size_t addr_len, |
| const unsigned char* addr_suffix, |
| size_t suffix_len) { |
| ByteString result(addr, addr_len); |
| result.Append(ByteString(addr_suffix, suffix_len)); |
| return result; |
| } |
| |
| #if !defined(DISABLE_WAKE_ON_WIFI) |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, CreateIPAddressPatternAndMask) { |
| ByteString pattern; |
| ByteString mask; |
| ByteString expected_pattern; |
| |
| CreateIPAddressPatternAndMask(IPAddress(kIPV4Address0), &pattern, &mask, |
| kNewWiphyNlMsg_MinPatternLen); |
| expected_pattern = |
| CreatePattern(kIPV4PatternPrefix, sizeof(kIPV4PatternPrefix), |
| kIPV4Address0Bytes, sizeof(kIPV4Address0Bytes)); |
| EXPECT_TRUE(pattern.Equals(expected_pattern)); |
| EXPECT_TRUE(mask.Equals(ByteString(kIPV4MaskBytes, sizeof(kIPV4MaskBytes)))); |
| |
| pattern.Clear(); |
| expected_pattern.Clear(); |
| mask.Clear(); |
| CreateIPAddressPatternAndMask(IPAddress(kIPV4Address1), &pattern, &mask, |
| kNewWiphyNlMsg_MinPatternLen); |
| expected_pattern = |
| CreatePattern(kIPV4PatternPrefix, sizeof(kIPV4PatternPrefix), |
| kIPV4Address1Bytes, sizeof(kIPV4Address1Bytes)); |
| EXPECT_TRUE(pattern.Equals(expected_pattern)); |
| EXPECT_TRUE(mask.Equals(ByteString(kIPV4MaskBytes, sizeof(kIPV4MaskBytes)))); |
| |
| pattern.Clear(); |
| expected_pattern.Clear(); |
| mask.Clear(); |
| CreateIPAddressPatternAndMask(IPAddress(kIPV6Address0), &pattern, &mask, |
| kNewWiphyNlMsg_MinPatternLen); |
| expected_pattern = |
| CreatePattern(kIPV6PatternPrefix, sizeof(kIPV6PatternPrefix), |
| kIPV6Address0Bytes, sizeof(kIPV6Address0Bytes)); |
| EXPECT_TRUE(pattern.Equals(expected_pattern)); |
| EXPECT_TRUE(mask.Equals(ByteString(kIPV6MaskBytes, sizeof(kIPV6MaskBytes)))); |
| |
| pattern.Clear(); |
| expected_pattern.Clear(); |
| mask.Clear(); |
| CreateIPAddressPatternAndMask(IPAddress(kIPV6Address1), &pattern, &mask, |
| kNewWiphyNlMsg_MinPatternLen); |
| expected_pattern = |
| CreatePattern(kIPV6PatternPrefix, sizeof(kIPV6PatternPrefix), |
| kIPV6Address1Bytes, sizeof(kIPV6Address1Bytes)); |
| EXPECT_TRUE(pattern.Equals(expected_pattern)); |
| EXPECT_TRUE(mask.Equals(ByteString(kIPV6MaskBytes, sizeof(kIPV6MaskBytes)))); |
| |
| pattern.Clear(); |
| expected_pattern.Clear(); |
| mask.Clear(); |
| CreateIPAddressPatternAndMask(IPAddress(kIPV6Address2), &pattern, &mask, |
| kNewWiphyNlMsg_MinPatternLen); |
| expected_pattern = |
| CreatePattern(kIPV6PatternPrefix, sizeof(kIPV6PatternPrefix), |
| kIPV6Address2Bytes, sizeof(kIPV6Address2Bytes)); |
| EXPECT_TRUE(pattern.Equals(expected_pattern)); |
| EXPECT_TRUE(mask.Equals(ByteString(kIPV6MaskBytes, sizeof(kIPV6MaskBytes)))); |
| |
| pattern.Clear(); |
| expected_pattern.Clear(); |
| mask.Clear(); |
| CreateIPAddressPatternAndMask(IPAddress(kIPV6Address3), &pattern, &mask, |
| kNewWiphyNlMsg_MinPatternLen); |
| expected_pattern = |
| CreatePattern(kIPV6PatternPrefix, sizeof(kIPV6PatternPrefix), |
| kIPV6Address3Bytes, sizeof(kIPV6Address3Bytes)); |
| EXPECT_TRUE(pattern.Equals(expected_pattern)); |
| EXPECT_TRUE(mask.Equals(ByteString(kIPV6MaskBytes, sizeof(kIPV6MaskBytes)))); |
| |
| pattern.Clear(); |
| expected_pattern.Clear(); |
| mask.Clear(); |
| CreateIPAddressPatternAndMask(IPAddress(kIPV6Address4), &pattern, &mask, |
| kNewWiphyNlMsg_MinPatternLen); |
| expected_pattern = |
| CreatePattern(kIPV6PatternPrefix, sizeof(kIPV6PatternPrefix), |
| kIPV6Address4Bytes, sizeof(kIPV6Address4Bytes)); |
| EXPECT_TRUE(pattern.Equals(expected_pattern)); |
| EXPECT_TRUE(mask.Equals(ByteString(kIPV6MaskBytes, sizeof(kIPV6MaskBytes)))); |
| |
| pattern.Clear(); |
| expected_pattern.Clear(); |
| mask.Clear(); |
| CreateIPAddressPatternAndMask(IPAddress(kIPV6Address5), &pattern, &mask, |
| kNewWiphyNlMsg_MinPatternLen); |
| expected_pattern = |
| CreatePattern(kIPV6PatternPrefix, sizeof(kIPV6PatternPrefix), |
| kIPV6Address5Bytes, sizeof(kIPV6Address5Bytes)); |
| EXPECT_TRUE(pattern.Equals(expected_pattern)); |
| EXPECT_TRUE(mask.Equals(ByteString(kIPV6MaskBytes, sizeof(kIPV6MaskBytes)))); |
| |
| pattern.Clear(); |
| expected_pattern.Clear(); |
| mask.Clear(); |
| CreateIPAddressPatternAndMask(IPAddress(kIPV6Address6), &pattern, &mask, |
| kNewWiphyNlMsg_MinPatternLen); |
| expected_pattern = |
| CreatePattern(kIPV6PatternPrefix, sizeof(kIPV6PatternPrefix), |
| kIPV6Address6Bytes, sizeof(kIPV6Address6Bytes)); |
| EXPECT_TRUE(pattern.Equals(expected_pattern)); |
| EXPECT_TRUE(mask.Equals(ByteString(kIPV6MaskBytes, sizeof(kIPV6MaskBytes)))); |
| |
| pattern.Clear(); |
| expected_pattern.Clear(); |
| mask.Clear(); |
| CreateIPAddressPatternAndMask(IPAddress(kIPV6Address7), &pattern, &mask, |
| kNewWiphyNlMsg_MinPatternLen); |
| expected_pattern = |
| CreatePattern(kIPV6PatternPrefix, sizeof(kIPV6PatternPrefix), |
| kIPV6Address7Bytes, sizeof(kIPV6Address7Bytes)); |
| EXPECT_TRUE(pattern.Equals(expected_pattern)); |
| EXPECT_TRUE(mask.Equals(ByteString(kIPV6MaskBytes, sizeof(kIPV6MaskBytes)))); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, CreatePatternAndMaskForProtocolType) { |
| ByteString pattern; |
| ByteString mask; |
| ByteString expected_pattern; |
| |
| CreatePacketTypePatternAndMaskforIPV4(kHardwareAddress, &pattern, &mask, |
| kNewWiphyNlMsg_MinPatternLen, |
| IPPROTO_TCP); |
| expected_pattern = CreatePattern(kDstHWAddressPatternBytes, |
| sizeof(kDstHWAddressPatternBytes), |
| KIPV4ProtocolTypeSuffixBytesForTCP, |
| sizeof(KIPV4ProtocolTypeSuffixBytesForTCP)); |
| EXPECT_TRUE(pattern.Equals(expected_pattern)); |
| EXPECT_TRUE(mask.Equals(ByteString(KIPV4ProtocolTypeMaskBytes, |
| sizeof(KIPV4ProtocolTypeMaskBytes)))); |
| |
| pattern.Clear(); |
| expected_pattern.Clear(); |
| mask.Clear(); |
| CreatePacketTypePatternAndMaskforIPV4(kHardwareAddress, &pattern, &mask, |
| kNewWiphyNlMsg_MinPatternLen, |
| IPPROTO_UDP); |
| expected_pattern = CreatePattern(kDstHWAddressPatternBytes, |
| sizeof(kDstHWAddressPatternBytes), |
| KIPV4ProtocolTypeSuffixBytesForUDP, |
| sizeof(KIPV4ProtocolTypeSuffixBytesForUDP)); |
| EXPECT_TRUE(pattern.Equals(expected_pattern)); |
| EXPECT_TRUE(mask.Equals(ByteString(KIPV4ProtocolTypeMaskBytes, |
| sizeof(KIPV4ProtocolTypeMaskBytes)))); |
| pattern.Clear(); |
| expected_pattern.Clear(); |
| mask.Clear(); |
| CreatePacketTypePatternAndMaskforIPV6(kHardwareAddress, &pattern, &mask, |
| kNewWiphyNlMsg_MinPatternLen, |
| IPPROTO_TCP); |
| expected_pattern = CreatePattern(kDstHWAddressPatternBytes, |
| sizeof(kDstHWAddressPatternBytes), |
| KIPV6ProtocolTypeSuffixBytesForTCP, |
| sizeof(KIPV6ProtocolTypeSuffixBytesForTCP)); |
| EXPECT_TRUE(pattern.Equals(expected_pattern)); |
| EXPECT_TRUE(mask.Equals(ByteString(KIPV6ProtocolTypeMaskBytes, |
| sizeof(KIPV6ProtocolTypeMaskBytes)))); |
| pattern.Clear(); |
| expected_pattern.Clear(); |
| mask.Clear(); |
| CreatePacketTypePatternAndMaskforIPV6(kHardwareAddress, &pattern, &mask, |
| kNewWiphyNlMsg_MinPatternLen, |
| IPPROTO_UDP); |
| expected_pattern = CreatePattern(kDstHWAddressPatternBytes, |
| sizeof(kDstHWAddressPatternBytes), |
| KIPV6ProtocolTypeSuffixBytesForUDP, |
| sizeof(KIPV6ProtocolTypeSuffixBytesForUDP)); |
| EXPECT_TRUE(pattern.Equals(expected_pattern)); |
| EXPECT_TRUE(mask.Equals(ByteString(KIPV6ProtocolTypeMaskBytes, |
| sizeof(KIPV6ProtocolTypeMaskBytes)))); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, ConvertIPProtoStrtoEnum) { |
| std::vector<std::string> ip_proto_strs = {"IP", "ICMP", "IGMP", "IPIP", |
| "TCP", "UDP", "IDP"}; |
| set<uint8_t> ip_proto_enums; |
| Error e; |
| bool return_val = ConvertIPProtoStrtoEnum(ip_proto_strs, &ip_proto_enums, &e); |
| |
| EXPECT_TRUE(return_val); |
| EXPECT_EQ(ip_proto_strs.size(), ip_proto_enums.size()); |
| EXPECT_FALSE(ip_proto_enums.find(IPPROTO_TCP) == ip_proto_enums.end()); |
| EXPECT_FALSE(ip_proto_enums.find(IPPROTO_UDP) == ip_proto_enums.end()); |
| EXPECT_FALSE(ip_proto_enums.find(IPPROTO_ICMP) == ip_proto_enums.end()); |
| EXPECT_FALSE(ip_proto_enums.find(IPPROTO_IGMP) == ip_proto_enums.end()); |
| EXPECT_FALSE(ip_proto_enums.find(IPPROTO_IPIP) == ip_proto_enums.end()); |
| EXPECT_FALSE(ip_proto_enums.find(IPPROTO_IP) == ip_proto_enums.end()); |
| EXPECT_FALSE(ip_proto_enums.find(IPPROTO_IDP) == ip_proto_enums.end()); |
| |
| ip_proto_strs = {" IP", "ICMP", "IGMP", "IPIP", "TCP", "UDP", "IDP"}; |
| ip_proto_enums.clear(); |
| return_val = ConvertIPProtoStrtoEnum(ip_proto_strs, &ip_proto_enums, &e); |
| EXPECT_FALSE(return_val); |
| EXPECT_TRUE(ip_proto_enums.empty()); |
| EXPECT_EQ(ip_proto_enums.find(IPPROTO_TCP), ip_proto_enums.end()); |
| EXPECT_EQ(ip_proto_enums.find(IPPROTO_UDP), ip_proto_enums.end()); |
| EXPECT_EQ(ip_proto_enums.find(IPPROTO_ICMP), ip_proto_enums.end()); |
| EXPECT_EQ(ip_proto_enums.find(IPPROTO_IGMP), ip_proto_enums.end()); |
| EXPECT_EQ(ip_proto_enums.find(IPPROTO_IPIP), ip_proto_enums.end()); |
| EXPECT_EQ(ip_proto_enums.find(IPPROTO_IP), ip_proto_enums.end()); |
| EXPECT_EQ(ip_proto_enums.find(IPPROTO_IDP), ip_proto_enums.end()); |
| |
| ip_proto_strs = {"IP", "IP", "IP", "IP", "IP", "IP"}; |
| ip_proto_enums.clear(); |
| return_val = ConvertIPProtoStrtoEnum(ip_proto_strs, &ip_proto_enums, &e); |
| EXPECT_TRUE(return_val); |
| EXPECT_EQ(ip_proto_enums.size(), 1); |
| EXPECT_FALSE(ip_proto_enums.find(IPPROTO_IP) == ip_proto_enums.end()); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, ConfigureWiphyIndex) { |
| SetWakeOnPacketConnMessage msg; |
| uint32_t value; |
| EXPECT_FALSE( |
| msg.attributes()->GetU32AttributeValue(NL80211_ATTR_WIPHY, &value)); |
| |
| ConfigureWiphyIndex(&msg, 137); |
| EXPECT_TRUE( |
| msg.attributes()->GetU32AttributeValue(NL80211_ATTR_WIPHY, &value)); |
| EXPECT_EQ(value, 137); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, ConfigureDisableWakeOnWiFiMessage) { |
| SetWakeOnPacketConnMessage msg; |
| Error e; |
| uint32_t value; |
| EXPECT_FALSE( |
| msg.attributes()->GetU32AttributeValue(NL80211_ATTR_WIPHY, &value)); |
| |
| ConfigureDisableWakeOnWiFiMessage(&msg, 57, &e); |
| EXPECT_EQ(e.type(), Error::Type::kSuccess); |
| EXPECT_TRUE( |
| msg.attributes()->GetU32AttributeValue(NL80211_ATTR_WIPHY, &value)); |
| EXPECT_EQ(value, 57); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, WakeOnWiFiSettingsMatch) { |
| IPAddressStore all_addresses; |
| set<WakeOnWiFi::WakeOnWiFiTrigger> trigs; |
| vector<ByteString> whitelist; |
| const uint32_t interval = kNetDetectScanIntervalSeconds; |
| |
| GetWakeOnPacketConnMessage msg0; |
| NetlinkPacket packet0(kResponseNoIPAddresses, sizeof(kResponseNoIPAddresses)); |
| msg0.InitFromPacket(&packet0, NetlinkMessage::MessageContext()); |
| EXPECT_TRUE(WakeOnWiFiSettingsMatch(msg0, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| |
| trigs.insert(WakeOnWiFi::kWakeTriggerPattern); |
| all_addresses.AddUnique( |
| IPAddress(string(kIPV4Address0, sizeof(kIPV4Address0)))); |
| GetWakeOnPacketConnMessage msg1; |
| NetlinkPacket packet1(kResponseIPV40, sizeof(kResponseIPV40)); |
| msg1.InitFromPacket(&packet1, NetlinkMessage::MessageContext()); |
| EXPECT_TRUE(WakeOnWiFiSettingsMatch(msg1, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg0, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| |
| // Test matching of wake on disconnect trigger. |
| trigs.insert(WakeOnWiFi::kWakeTriggerDisconnect); |
| GetWakeOnPacketConnMessage msg2; |
| NetlinkPacket packet2(kResponseIPV40WakeOnDisconnect, |
| sizeof(kResponseIPV40WakeOnDisconnect)); |
| msg2.InitFromPacket(&packet2, NetlinkMessage::MessageContext()); |
| EXPECT_TRUE(WakeOnWiFiSettingsMatch(msg2, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg1, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg0, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| |
| trigs.erase(WakeOnWiFi::kWakeTriggerDisconnect); |
| all_addresses.AddUnique( |
| IPAddress(string(kIPV4Address1, sizeof(kIPV4Address1)))); |
| GetWakeOnPacketConnMessage msg3; |
| NetlinkPacket packet3(kResponseIPV401, sizeof(kResponseIPV401)); |
| msg3.InitFromPacket(&packet3, NetlinkMessage::MessageContext()); |
| EXPECT_TRUE(WakeOnWiFiSettingsMatch(msg3, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg2, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg1, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg0, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| |
| all_addresses.AddUnique( |
| IPAddress(string(kIPV6Address0, sizeof(kIPV6Address0)))); |
| GetWakeOnPacketConnMessage msg4; |
| NetlinkPacket packet4(kResponseIPV401IPV60, sizeof(kResponseIPV401IPV60)); |
| msg4.InitFromPacket(&packet4, NetlinkMessage::MessageContext()); |
| EXPECT_TRUE(WakeOnWiFiSettingsMatch(msg4, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg3, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg2, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg1, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg0, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| |
| all_addresses.AddUnique( |
| IPAddress(string(kIPV6Address1, sizeof(kIPV6Address1)))); |
| GetWakeOnPacketConnMessage msg5; |
| NetlinkPacket packet5(kResponseIPV401IPV601, sizeof(kResponseIPV401IPV601)); |
| msg5.InitFromPacket(&packet5, NetlinkMessage::MessageContext()); |
| EXPECT_TRUE(WakeOnWiFiSettingsMatch(msg5, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg4, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg3, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg2, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg1, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg0, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| |
| // Test matching of wake on SSID trigger. |
| all_addresses.Clear(); |
| trigs.clear(); |
| trigs.insert(WakeOnWiFi::kWakeTriggerSSID); |
| AddSSIDToWhitelist(kSSIDBytes1, sizeof(kSSIDBytes1), &whitelist); |
| AddSSIDToWhitelist(kSSIDBytes2, sizeof(kSSIDBytes2), &whitelist); |
| GetWakeOnPacketConnMessage msg6; |
| NetlinkPacket packet6(kResponseWakeOnSSID, sizeof(kResponseWakeOnSSID)); |
| msg6.InitFromPacket(&packet6, NetlinkMessage::MessageContext()); |
| EXPECT_TRUE(WakeOnWiFiSettingsMatch(msg6, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg5, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg4, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg3, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg2, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg1, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg0, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| |
| // Test that we get a mismatch if triggers are present in the message that we |
| // don't expect. |
| trigs.clear(); |
| EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg6, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg5, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg4, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg3, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg2, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg1, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, |
| ConfigureSetWakeOnWiFiSettingsMessage) { |
| IPAddressStore all_addresses; |
| set<WakeOnWiFi::WakeOnWiFiTrigger> trigs; |
| const int index = 1; // wiphy device number |
| vector<ByteString> whitelist; |
| const uint32_t interval = kNetDetectScanIntervalSeconds; |
| SetWakeOnPacketConnMessage msg0; |
| Error e; |
| trigs.insert(WakeOnWiFi::kWakeTriggerPattern); |
| all_addresses.AddUnique( |
| IPAddress(string(kIPV4Address0, sizeof(kIPV4Address0)))); |
| EXPECT_TRUE(ConfigureSetWakeOnWiFiSettingsMessage(&msg0, trigs, all_addresses, |
| index, {}, kHardwareAddress, |
| interval, whitelist, &e)); |
| EXPECT_TRUE(WakeOnWiFiSettingsMatch(msg0, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| |
| SetWakeOnPacketConnMessage msg1; |
| all_addresses.AddUnique( |
| IPAddress(string(kIPV4Address1, sizeof(kIPV4Address1)))); |
| EXPECT_TRUE(ConfigureSetWakeOnWiFiSettingsMessage(&msg1, trigs, all_addresses, |
| index, {}, kHardwareAddress, |
| interval, whitelist, &e)); |
| EXPECT_TRUE(WakeOnWiFiSettingsMatch(msg1, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| |
| SetWakeOnPacketConnMessage msg2; |
| all_addresses.AddUnique( |
| IPAddress(string(kIPV6Address0, sizeof(kIPV6Address0)))); |
| EXPECT_TRUE(ConfigureSetWakeOnWiFiSettingsMessage(&msg2, trigs, all_addresses, |
| index, {}, kHardwareAddress, |
| interval, whitelist, &e)); |
| EXPECT_TRUE(WakeOnWiFiSettingsMatch(msg2, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| |
| SetWakeOnPacketConnMessage msg3; |
| all_addresses.AddUnique( |
| IPAddress(string(kIPV6Address1, sizeof(kIPV6Address1)))); |
| EXPECT_TRUE(ConfigureSetWakeOnWiFiSettingsMessage(&msg3, trigs, all_addresses, |
| index, {}, kHardwareAddress, |
| interval, whitelist, &e)); |
| EXPECT_TRUE(WakeOnWiFiSettingsMatch(msg3, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| |
| SetWakeOnPacketConnMessage msg4; |
| all_addresses.AddUnique( |
| IPAddress(string(kIPV6Address2, sizeof(kIPV6Address2)))); |
| EXPECT_TRUE(ConfigureSetWakeOnWiFiSettingsMessage(&msg4, trigs, all_addresses, |
| index, {}, kHardwareAddress, |
| interval, whitelist, &e)); |
| EXPECT_TRUE(WakeOnWiFiSettingsMatch(msg4, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| |
| SetWakeOnPacketConnMessage msg5; |
| all_addresses.AddUnique( |
| IPAddress(string(kIPV6Address3, sizeof(kIPV6Address3)))); |
| EXPECT_TRUE(ConfigureSetWakeOnWiFiSettingsMessage(&msg5, trigs, all_addresses, |
| index, {}, kHardwareAddress, |
| interval, whitelist, &e)); |
| EXPECT_TRUE(WakeOnWiFiSettingsMatch(msg5, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| |
| SetWakeOnPacketConnMessage msg6; |
| all_addresses.AddUnique( |
| IPAddress(string(kIPV6Address4, sizeof(kIPV6Address4)))); |
| EXPECT_TRUE(ConfigureSetWakeOnWiFiSettingsMessage(&msg6, trigs, all_addresses, |
| index, {}, kHardwareAddress, |
| interval, whitelist, &e)); |
| EXPECT_TRUE(WakeOnWiFiSettingsMatch(msg6, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| |
| SetWakeOnPacketConnMessage msg7; |
| all_addresses.AddUnique( |
| IPAddress(string(kIPV6Address5, sizeof(kIPV6Address5)))); |
| EXPECT_TRUE(ConfigureSetWakeOnWiFiSettingsMessage(&msg7, trigs, all_addresses, |
| index, {}, kHardwareAddress, |
| interval, whitelist, &e)); |
| EXPECT_TRUE(WakeOnWiFiSettingsMatch(msg7, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| |
| SetWakeOnPacketConnMessage msg8; |
| all_addresses.AddUnique( |
| IPAddress(string(kIPV6Address6, sizeof(kIPV6Address6)))); |
| EXPECT_TRUE(ConfigureSetWakeOnWiFiSettingsMessage(&msg8, trigs, all_addresses, |
| index, {}, kHardwareAddress, |
| interval, whitelist, &e)); |
| EXPECT_TRUE(WakeOnWiFiSettingsMatch(msg8, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| |
| SetWakeOnPacketConnMessage msg9; |
| all_addresses.AddUnique( |
| IPAddress(string(kIPV6Address7, sizeof(kIPV6Address7)))); |
| EXPECT_TRUE(ConfigureSetWakeOnWiFiSettingsMessage(&msg9, trigs, all_addresses, |
| index, {}, kHardwareAddress, |
| interval, whitelist, &e)); |
| EXPECT_TRUE(WakeOnWiFiSettingsMatch(msg9, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| |
| SetWakeOnPacketConnMessage msg10; |
| uint8_t proto_tcp = static_cast<uint8_t>(IPPROTO_TCP); |
| EXPECT_TRUE(ConfigureSetWakeOnWiFiSettingsMessage( |
| &msg10, trigs, all_addresses, index, {proto_tcp}, kHardwareAddress, |
| interval, whitelist, &e)); |
| EXPECT_TRUE(WakeOnWiFiSettingsMatch(msg10, trigs, all_addresses, interval, |
| {proto_tcp}, kHardwareAddress, |
| whitelist)); |
| SetWakeOnPacketConnMessage msg11; |
| all_addresses.Clear(); |
| uint8_t proto_udp = static_cast<uint8_t>(IPPROTO_UDP); |
| EXPECT_TRUE(ConfigureSetWakeOnWiFiSettingsMessage( |
| &msg11, trigs, all_addresses, index, {proto_udp}, kHardwareAddress, |
| interval, whitelist, &e)); |
| EXPECT_TRUE(WakeOnWiFiSettingsMatch(msg11, trigs, all_addresses, interval, |
| {proto_udp}, kHardwareAddress, |
| whitelist)); |
| |
| SetWakeOnPacketConnMessage msg12; |
| all_addresses.Clear(); |
| trigs.clear(); |
| trigs.insert(WakeOnWiFi::kWakeTriggerSSID); |
| AddSSIDToWhitelist(kSSIDBytes1, sizeof(kSSIDBytes1), &whitelist); |
| AddSSIDToWhitelist(kSSIDBytes2, sizeof(kSSIDBytes2), &whitelist); |
| EXPECT_TRUE(ConfigureSetWakeOnWiFiSettingsMessage( |
| &msg12, trigs, all_addresses, index, {}, kHardwareAddress, interval, |
| whitelist, &e)); |
| EXPECT_TRUE(WakeOnWiFiSettingsMatch(msg12, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, RequestWakeOnPacketSettings) { |
| EXPECT_CALL( |
| netlink_manager_, |
| SendNl80211Message(IsNl80211Command(kNl80211FamilyId, |
| GetWakeOnPacketConnMessage::kCommand), |
| _, _, _)) |
| .Times(1); |
| RequestWakeOnPacketSettings(); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, |
| VerifyWakeOnWiFiSettings_NoWakeOnPacketRules) { |
| ScopedMockLog log; |
| // Create an Nl80211 response to a NL80211_CMD_GET_WOWLAN request |
| // indicating that there are no wake-on-packet rules programmed into the NIC. |
| GetWakeOnPacketConnMessage msg; |
| NetlinkPacket packet(kResponseNoIPAddresses, sizeof(kResponseNoIPAddresses)); |
| msg.InitFromPacket(&packet, NetlinkMessage::MessageContext()); |
| // Successful verification and consequent invocation of callback. |
| SetSuspendActionsDoneCallback(); |
| ScopeLogger::GetInstance()->EnableScopesByName("wifi"); |
| ScopeLogger::GetInstance()->set_verbose_level(2); |
| EXPECT_TRUE(GetWakeOnPacketConnections()->Empty()); |
| EXPECT_FALSE(SuspendActionsCallbackIsNull()); |
| EXPECT_CALL(*this, DoneCallback(ErrorTypeIs(Error::kSuccess))).Times(1); |
| EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); |
| EXPECT_CALL( |
| log, Log(_, _, HasSubstr("Wake on WiFi settings successfully verified"))); |
| EXPECT_CALL(metrics_, NotifyVerifyWakeOnWiFiSettingsResult( |
| Metrics::kVerifyWakeOnWiFiSettingsResultSuccess)); |
| VerifyWakeOnWiFiSettings(msg); |
| // Suspend action callback cleared after being invoked. |
| EXPECT_TRUE(SuspendActionsCallbackIsNull()); |
| ScopeLogger::GetInstance()->EnableScopesByName("-wifi"); |
| ScopeLogger::GetInstance()->set_verbose_level(0); |
| |
| // Unsuccessful verification if locally stored settings do not match. |
| GetWakeOnPacketConnections()->AddUnique(IPAddress("1.1.1.1")); |
| GetWakeOnWiFiTriggers()->insert(WakeOnWiFi::kWakeTriggerPattern); |
| EXPECT_CALL( |
| log, |
| Log(logging::LOG_ERROR, _, |
| HasSubstr(" failed: discrepancy between wake-on-packet settings on " |
| "NIC and those in local data structure detected"))); |
| EXPECT_CALL(metrics_, NotifyVerifyWakeOnWiFiSettingsResult( |
| Metrics::kVerifyWakeOnWiFiSettingsResultFailure)); |
| VerifyWakeOnWiFiSettings(msg); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, |
| VerifyWakeOnWiFiSettings_WakeOnPatternAndDisconnectRules) { |
| ScopedMockLog log; |
| // Create a non-trivial Nl80211 response to a NL80211_CMD_GET_WOWLAN request |
| // indicating that that the NIC wakes on packets from 192.168.10.20 and on |
| // disconnects. |
| GetWakeOnPacketConnMessage msg; |
| NetlinkPacket packet(kResponseIPV40WakeOnDisconnect, |
| sizeof(kResponseIPV40WakeOnDisconnect)); |
| msg.InitFromPacket(&packet, NetlinkMessage::MessageContext()); |
| // Successful verification and consequent invocation of callback. |
| SetSuspendActionsDoneCallback(); |
| EXPECT_FALSE(SuspendActionsCallbackIsNull()); |
| GetWakeOnPacketConnections()->AddUnique(IPAddress("192.168.10.20")); |
| GetWakeOnWiFiTriggers()->insert(WakeOnWiFi::kWakeTriggerPattern); |
| GetWakeOnWiFiTriggers()->insert(WakeOnWiFi::kWakeTriggerDisconnect); |
| ScopeLogger::GetInstance()->EnableScopesByName("wifi"); |
| ScopeLogger::GetInstance()->set_verbose_level(2); |
| EXPECT_CALL(*this, DoneCallback(ErrorTypeIs(Error::kSuccess))).Times(1); |
| EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); |
| EXPECT_CALL( |
| log, Log(_, _, HasSubstr("Wake on WiFi settings successfully verified"))); |
| EXPECT_CALL(metrics_, NotifyVerifyWakeOnWiFiSettingsResult( |
| Metrics::kVerifyWakeOnWiFiSettingsResultSuccess)); |
| VerifyWakeOnWiFiSettings(msg); |
| // Suspend action callback cleared after being invoked. |
| EXPECT_TRUE(SuspendActionsCallbackIsNull()); |
| ScopeLogger::GetInstance()->EnableScopesByName("-wifi"); |
| ScopeLogger::GetInstance()->set_verbose_level(0); |
| |
| // Unsuccessful verification if locally stored settings do not match. |
| GetWakeOnWiFiTriggers()->erase(WakeOnWiFi::kWakeTriggerDisconnect); |
| EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); |
| EXPECT_CALL( |
| log, |
| Log(logging::LOG_ERROR, _, |
| HasSubstr(" failed: discrepancy between wake-on-packet settings on " |
| "NIC and those in local data structure detected"))); |
| EXPECT_CALL(metrics_, NotifyVerifyWakeOnWiFiSettingsResult( |
| Metrics::kVerifyWakeOnWiFiSettingsResultFailure)); |
| VerifyWakeOnWiFiSettings(msg); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, |
| VerifyWakeOnWiFiSettings_WakeOnSSIDRules) { |
| ScopedMockLog log; |
| // Create a non-trivial Nl80211 response to a NL80211_CMD_GET_WOWLAN request |
| // indicating that that the NIC wakes on two SSIDs represented by kSSIDBytes1 |
| // and kSSIDBytes2 and scans for them at interval |
| // kNetDetectScanIntervalSeconds. |
| GetWakeOnPacketConnMessage msg; |
| NetlinkPacket packet(kResponseWakeOnSSID, sizeof(kResponseWakeOnSSID)); |
| msg.InitFromPacket(&packet, NetlinkMessage::MessageContext()); |
| // Successful verification and consequent invocation of callback. |
| SetSuspendActionsDoneCallback(); |
| EXPECT_FALSE(SuspendActionsCallbackIsNull()); |
| GetWakeOnWiFiTriggers()->insert(WakeOnWiFi::kWakeTriggerSSID); |
| AddSSIDToWhitelist(kSSIDBytes1, sizeof(kSSIDBytes1), |
| GetWakeOnSSIDWhitelist()); |
| AddSSIDToWhitelist(kSSIDBytes2, sizeof(kSSIDBytes2), |
| GetWakeOnSSIDWhitelist()); |
| SetNetDetectScanPeriodSeconds(kNetDetectScanIntervalSeconds); |
| ScopeLogger::GetInstance()->EnableScopesByName("wifi"); |
| ScopeLogger::GetInstance()->set_verbose_level(2); |
| EXPECT_CALL(*this, DoneCallback(ErrorTypeIs(Error::kSuccess))).Times(1); |
| EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); |
| EXPECT_CALL( |
| log, Log(_, _, HasSubstr("Wake on WiFi settings successfully verified"))); |
| EXPECT_CALL(metrics_, NotifyVerifyWakeOnWiFiSettingsResult( |
| Metrics::kVerifyWakeOnWiFiSettingsResultSuccess)); |
| VerifyWakeOnWiFiSettings(msg); |
| // Suspend action callback cleared after being invoked. |
| EXPECT_TRUE(SuspendActionsCallbackIsNull()); |
| ScopeLogger::GetInstance()->EnableScopesByName("-wifi"); |
| ScopeLogger::GetInstance()->set_verbose_level(0); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, |
| VerifyWakeOnWiFiSettingsSuccess_NoDoneCallback) { |
| ScopedMockLog log; |
| // Create an Nl80211 response to a NL80211_CMD_GET_WOWLAN request |
| // indicating that there are no wake-on-packet rules programmed into the NIC. |
| GetWakeOnPacketConnMessage msg; |
| NetlinkPacket packet(kResponseNoIPAddresses, sizeof(kResponseNoIPAddresses)); |
| msg.InitFromPacket(&packet, NetlinkMessage::MessageContext()); |
| // Successful verification, but since there is no suspend action callback |
| // set, no callback is invoked. |
| EXPECT_TRUE(SuspendActionsCallbackIsNull()); |
| EXPECT_TRUE(GetWakeOnPacketConnections()->Empty()); |
| ScopeLogger::GetInstance()->EnableScopesByName("wifi"); |
| ScopeLogger::GetInstance()->set_verbose_level(2); |
| EXPECT_CALL(*this, DoneCallback(_)).Times(0); |
| EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); |
| EXPECT_CALL( |
| log, Log(_, _, HasSubstr("Wake on WiFi settings successfully verified"))); |
| EXPECT_CALL(metrics_, NotifyVerifyWakeOnWiFiSettingsResult( |
| Metrics::kVerifyWakeOnWiFiSettingsResultSuccess)); |
| VerifyWakeOnWiFiSettings(msg); |
| ScopeLogger::GetInstance()->EnableScopesByName("-wifi"); |
| ScopeLogger::GetInstance()->set_verbose_level(0); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, |
| RetrySetWakeOnPacketConnections_LessThanMaxRetries) { |
| ScopedMockLog log; |
| // Max retries not reached yet, so send Nl80211 message to program NIC again. |
| GetWakeOnWiFiTriggers()->insert(WakeOnWiFi::kWakeTriggerDisconnect); |
| SetNumSetWakeOnPacketRetries(WakeOnWiFi::kMaxSetWakeOnPacketRetries - 1); |
| EXPECT_CALL( |
| netlink_manager_, |
| SendNl80211Message(IsNl80211Command(kNl80211FamilyId, |
| SetWakeOnPacketConnMessage::kCommand), |
| _, _, _)) |
| .Times(1); |
| RetrySetWakeOnPacketConnections(); |
| EXPECT_EQ(GetNumSetWakeOnPacketRetries(), |
| WakeOnWiFi::kMaxSetWakeOnPacketRetries); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, |
| RetrySetWakeOnPacketConnections_MaxAttemptsWithCallbackSet) { |
| ScopedMockLog log; |
| // Max retry attempts reached. Suspend actions done callback is set, so it |
| // is invoked. |
| SetNumSetWakeOnPacketRetries(WakeOnWiFi::kMaxSetWakeOnPacketRetries); |
| SetSuspendActionsDoneCallback(); |
| ScopeLogger::GetInstance()->EnableScopesByName("wifi"); |
| ScopeLogger::GetInstance()->set_verbose_level(3); |
| EXPECT_FALSE(SuspendActionsCallbackIsNull()); |
| EXPECT_CALL(*this, DoneCallback(ErrorTypeIs(Error::kOperationFailed))) |
| .Times(1); |
| EXPECT_CALL(netlink_manager_, SendNl80211Message(_, _, _, _)).Times(0); |
| EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); |
| EXPECT_CALL(log, Log(_, _, HasSubstr("max retry attempts reached"))); |
| RetrySetWakeOnPacketConnections(); |
| EXPECT_TRUE(SuspendActionsCallbackIsNull()); |
| EXPECT_EQ(GetNumSetWakeOnPacketRetries(), 0); |
| ScopeLogger::GetInstance()->EnableScopesByName("-wifi"); |
| ScopeLogger::GetInstance()->set_verbose_level(0); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, |
| RetrySetWakeOnPacketConnections_MaxAttemptsCallbackUnset) { |
| ScopedMockLog log; |
| // If there is no suspend action callback set, no suspend callback should be |
| // invoked. |
| SetNumSetWakeOnPacketRetries(WakeOnWiFi::kMaxSetWakeOnPacketRetries); |
| ScopeLogger::GetInstance()->EnableScopesByName("wifi"); |
| ScopeLogger::GetInstance()->set_verbose_level(3); |
| EXPECT_TRUE(SuspendActionsCallbackIsNull()); |
| EXPECT_CALL(*this, DoneCallback(_)).Times(0); |
| EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); |
| EXPECT_CALL(log, Log(_, _, HasSubstr("max retry attempts reached"))); |
| RetrySetWakeOnPacketConnections(); |
| ScopeLogger::GetInstance()->EnableScopesByName("-wifi"); |
| ScopeLogger::GetInstance()->set_verbose_level(0); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, |
| ParseWakeOnWiFiCapabilities_DisconnectPatternSSIDSupported) { |
| ClearWakeOnWiFiTriggersSupported(); |
| NewWiphyMessage msg; |
| NetlinkPacket packet(kNewWiphyNlMsg, sizeof(kNewWiphyNlMsg)); |
| msg.InitFromPacket(&packet, NetlinkMessage::MessageContext()); |
| ParseWakeOnWiFiCapabilities(msg); |
| EXPECT_TRUE(GetWakeOnWiFiTriggersSupported()->find( |
| WakeOnWiFi::kWakeTriggerDisconnect) != |
| GetWakeOnWiFiTriggersSupported()->end()); |
| EXPECT_TRUE( |
| GetWakeOnWiFiTriggersSupported()->find(WakeOnWiFi::kWakeTriggerPattern) != |
| GetWakeOnWiFiTriggersSupported()->end()); |
| EXPECT_TRUE( |
| GetWakeOnWiFiTriggersSupported()->find(WakeOnWiFi::kWakeTriggerSSID) != |
| GetWakeOnWiFiTriggersSupported()->end()); |
| EXPECT_EQ(GetWakeOnWiFiMaxPatterns(), kNewWiphyNlMsg_MaxPatterns); |
| EXPECT_EQ(GetWakeOnWiFiMaxSSIDs(), kNewWiphyNlMsg_MaxSSIDs); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, |
| ParseWakeOnWiFiCapabilities_UnsupportedPatternLen) { |
| ClearWakeOnWiFiTriggersSupported(); |
| NewWiphyMessage msg; |
| // Modify the range of support pattern lengths to [0-1] bytes, which is less |
| // than what we need to use our IPV4 (30 bytes) or IPV6 (38 bytes) patterns. |
| MutableNetlinkPacket packet(kNewWiphyNlMsg, sizeof(kNewWiphyNlMsg)); |
| struct nl80211_pattern_support* patt_support = |
| reinterpret_cast<struct nl80211_pattern_support*>( |
| &packet.GetMutablePayload() |
| ->GetData()[kNewWiphyNlMsg_PattSupportOffset]); |
| patt_support->min_pattern_len = 0; |
| patt_support->max_pattern_len = 1; |
| msg.InitFromPacket(&packet, NetlinkMessage::MessageContext()); |
| ParseWakeOnWiFiCapabilities(msg); |
| EXPECT_TRUE(GetWakeOnWiFiTriggersSupported()->find( |
| WakeOnWiFi::kWakeTriggerDisconnect) != |
| GetWakeOnWiFiTriggersSupported()->end()); |
| EXPECT_TRUE( |
| GetWakeOnWiFiTriggersSupported()->find(WakeOnWiFi::kWakeTriggerSSID) != |
| GetWakeOnWiFiTriggersSupported()->end()); |
| // Ensure that ParseWakeOnWiFiCapabilities realizes that our IP address |
| // patterns cannot be used given the support pattern length range reported. |
| EXPECT_FALSE( |
| GetWakeOnWiFiTriggersSupported()->find(WakeOnWiFi::kWakeTriggerPattern) != |
| GetWakeOnWiFiTriggersSupported()->end()); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, |
| ParseWakeOnWiFiCapabilities_DisconnectNotSupported) { |
| ClearWakeOnWiFiTriggersSupported(); |
| NewWiphyMessage msg; |
| // Change the NL80211_WOWLAN_TRIG_DISCONNECT flag attribute into the |
| // NL80211_WOWLAN_TRIG_MAGIC_PKT flag attribute, so that this message |
| // no longer reports wake on disconnect as a supported capability. |
| MutableNetlinkPacket packet(kNewWiphyNlMsg, sizeof(kNewWiphyNlMsg)); |
| struct nlattr* wowlan_trig_disconnect_attr = reinterpret_cast<struct nlattr*>( |
| &packet.GetMutablePayload() |
| ->GetData()[kNewWiphyNlMsg_WowlanTrigDisconnectAttributeOffset]); |
| wowlan_trig_disconnect_attr->nla_type = NL80211_WOWLAN_TRIG_MAGIC_PKT; |
| msg.InitFromPacket(&packet, NetlinkMessage::MessageContext()); |
| ParseWakeOnWiFiCapabilities(msg); |
| EXPECT_TRUE( |
| GetWakeOnWiFiTriggersSupported()->find(WakeOnWiFi::kWakeTriggerPattern) != |
| GetWakeOnWiFiTriggersSupported()->end()); |
| EXPECT_TRUE( |
| GetWakeOnWiFiTriggersSupported()->find(WakeOnWiFi::kWakeTriggerSSID) != |
| GetWakeOnWiFiTriggersSupported()->end()); |
| // Ensure that ParseWakeOnWiFiCapabilities realizes that wake on disconnect |
| // is not supported. |
| EXPECT_FALSE(GetWakeOnWiFiTriggersSupported()->find( |
| WakeOnWiFi::kWakeTriggerDisconnect) != |
| GetWakeOnWiFiTriggersSupported()->end()); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, |
| ParseWakeOnWiFiCapabilities_SSIDNotSupported) { |
| ClearWakeOnWiFiTriggersSupported(); |
| NewWiphyMessage msg; |
| // Change the NL80211_WOWLAN_TRIG_NET_DETECT flag attribute type to an invalid |
| // attribute type (0), so that this message no longer reports wake on SSID |
| // as a supported capability. |
| MutableNetlinkPacket packet(kNewWiphyNlMsg, sizeof(kNewWiphyNlMsg)); |
| struct nlattr* wowlan_trig_net_detect_attr = reinterpret_cast<struct nlattr*>( |
| &packet.GetMutablePayload() |
| ->GetData()[kNewWiphyNlMsg_WowlanTrigNetDetectAttributeOffset]); |
| wowlan_trig_net_detect_attr->nla_type = 0; |
| msg.InitFromPacket(&packet, NetlinkMessage::MessageContext()); |
| ParseWakeOnWiFiCapabilities(msg); |
| EXPECT_TRUE( |
| GetWakeOnWiFiTriggersSupported()->find(WakeOnWiFi::kWakeTriggerPattern) != |
| GetWakeOnWiFiTriggersSupported()->end()); |
| EXPECT_TRUE(GetWakeOnWiFiTriggersSupported()->find( |
| WakeOnWiFi::kWakeTriggerDisconnect) != |
| GetWakeOnWiFiTriggersSupported()->end()); |
| // Ensure that ParseWakeOnWiFiCapabilities realizes that wake on SSID is not |
| // supported. |
| EXPECT_FALSE( |
| GetWakeOnWiFiTriggersSupported()->find(WakeOnWiFi::kWakeTriggerSSID) != |
| GetWakeOnWiFiTriggersSupported()->end()); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, |
| ApplyWakeOnWiFiSettings_WiphyIndexNotReceived) { |
| ScopedMockLog log; |
| // ApplyWakeOnWiFiSettings should return immediately if the wifi interface |
| // index has not been received when the function is called. |
| SetWiphyIndexReceivedToFalse(); |
| EXPECT_CALL(netlink_manager_, |
| SendNl80211Message(IsDisableWakeOnWiFiMsg(), _, _, _)) |
| .Times(0); |
| EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); |
| EXPECT_CALL(log, Log(logging::LOG_ERROR, _, |
| HasSubstr("Interface index not yet received"))); |
| ApplyWakeOnWiFiSettings(); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, |
| ApplyWakeOnWiFiSettings_WiphyIndexReceived) { |
| // Disable wake on WiFi if there are no wake on WiFi triggers registered. |
| EXPECT_CALL( |
| netlink_manager_, |
| SendNl80211Message(IsNl80211Command(kNl80211FamilyId, |
| SetWakeOnPacketConnMessage::kCommand), |
| _, _, _)) |
| .Times(0); |
| EXPECT_CALL(netlink_manager_, |
| SendNl80211Message(IsDisableWakeOnWiFiMsg(), _, _, _)) |
| .Times(1); |
| ApplyWakeOnWiFiSettings(); |
| |
| // Otherwise, program the NIC. |
| IPAddress ip_addr("1.1.1.1"); |
| GetWakeOnPacketConnections()->AddUnique(ip_addr); |
| GetWakeOnWiFiTriggers()->insert(WakeOnWiFi::kWakeTriggerPattern); |
| EXPECT_FALSE(GetWakeOnPacketConnections()->Empty()); |
| EXPECT_CALL( |
| netlink_manager_, |
| SendNl80211Message(IsNl80211Command(kNl80211FamilyId, |
| SetWakeOnPacketConnMessage::kCommand), |
| _, _, _)) |
| .Times(1); |
| EXPECT_CALL(netlink_manager_, |
| SendNl80211Message(IsDisableWakeOnWiFiMsg(), _, _, _)) |
| .Times(0); |
| ApplyWakeOnWiFiSettings(); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, |
| BeforeSuspendActions_ReportDoneImmediately) { |
| ScopedMockLog log; |
| const bool is_connected = true; |
| const bool start_lease_renewal_timer = true; |
| AddSSIDToWhitelist(kSSIDBytes1, sizeof(kSSIDBytes1), |
| GetWakeOnSSIDWhitelist()); |
| // If no triggers are supported, no triggers will be programmed into the NIC. |
| ClearWakeOnWiFiTriggersSupported(); |
| SetSuspendActionsDoneCallback(); |
| SetInDarkResume(true); |
| SetLastWakeReason(WakeOnWiFi::kWakeTriggerPattern); |
| AddResultToLastSSIDResults(); |
| // Do not report done immediately in dark resume, since we need to program it |
| // to disable wake on WiFi. |
| EXPECT_CALL(*this, DoneCallback(_)).Times(0); |
| BeforeSuspendActions(is_connected, start_lease_renewal_timer, |
| kTimeToNextLeaseRenewalLong); |
| EXPECT_FALSE(GetInDarkResume()); |
| EXPECT_EQ(WakeOnWiFi::kWakeTriggerUnsupported, GetLastWakeReason()); |
| EXPECT_TRUE(GetLastSSIDMatchFreqs().empty()); |
| |
| SetInDarkResume(false); |
| SetLastWakeReason(WakeOnWiFi::kWakeTriggerPattern); |
| AddResultToLastSSIDResults(); |
| // Report done immediately on normal suspend, since wake on WiFi should |
| // already have been disabled on the NIC on a previous resume. |
| EXPECT_CALL(*this, DoneCallback(_)).Times(1); |
| EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); |
| ScopeLogger::GetInstance()->EnableScopesByName("wifi"); |
| ScopeLogger::GetInstance()->set_verbose_level(1); |
| EXPECT_CALL( |
| log, |
| Log(_, _, |
| HasSubstr( |
| "No need to disable wake on WiFi on NIC in regular suspend"))); |
| BeforeSuspendActions(is_connected, start_lease_renewal_timer, |
| kTimeToNextLeaseRenewalLong); |
| EXPECT_EQ(WakeOnWiFi::kWakeTriggerUnsupported, GetLastWakeReason()); |
| EXPECT_TRUE(GetLastSSIDMatchFreqs().empty()); |
| ScopeLogger::GetInstance()->EnableScopesByName("-wifi"); |
| ScopeLogger::GetInstance()->set_verbose_level(0); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, |
| BeforeSuspendActions_FeaturesDisabledOrTriggersUnsupported) { |
| const bool is_connected = true; |
| const bool start_lease_renewal_timer = true; |
| AddSSIDToWhitelist(kSSIDBytes1, sizeof(kSSIDBytes1), |
| GetWakeOnSSIDWhitelist()); |
| SetInDarkResume(false); |
| SetSuspendActionsDoneCallback(); |
| // No features enabled, so no triggers programmed. |
| DisableWakeOnWiFiFeatures(); |
| SetLastWakeReason(WakeOnWiFi::kWakeTriggerPattern); |
| AddResultToLastSSIDResults(); |
| EXPECT_TRUE(GetWakeOnWiFiTriggers()->empty()); |
| EXPECT_CALL(*this, DoneCallback(_)); |
| BeforeSuspendActions(is_connected, start_lease_renewal_timer, |
| kTimeToNextLeaseRenewalLong); |
| EXPECT_TRUE(GetWakeOnWiFiTriggers()->empty()); |
| EXPECT_EQ(WakeOnWiFi::kWakeTriggerUnsupported, GetLastWakeReason()); |
| EXPECT_TRUE(GetLastSSIDMatchFreqs().empty()); |
| |
| // No triggers supported, so no triggers programmed. |
| SetSuspendActionsDoneCallback(); |
| EnableWakeOnWiFiFeaturesPacketDarkConnect(); |
| GetWakeOnWiFiTriggersSupported()->clear(); |
| SetLastWakeReason(WakeOnWiFi::kWakeTriggerPattern); |
| AddResultToLastSSIDResults(); |
| EXPECT_TRUE(GetWakeOnWiFiTriggers()->empty()); |
| EXPECT_CALL(*this, DoneCallback(_)); |
| BeforeSuspendActions(is_connected, start_lease_renewal_timer, |
| kTimeToNextLeaseRenewalLong); |
| EXPECT_TRUE(GetWakeOnWiFiTriggers()->empty()); |
| EXPECT_EQ(WakeOnWiFi::kWakeTriggerUnsupported, GetLastWakeReason()); |
| EXPECT_TRUE(GetLastSSIDMatchFreqs().empty()); |
| |
| // Only wake on packet feature enabled and supported. |
| EnableWakeOnWiFiFeaturesPacket(); |
| GetWakeOnWiFiTriggersSupported()->insert(WakeOnWiFi::kWakeTriggerPattern); |
| GetWakeOnPacketConnections()->AddUnique(IPAddress("1.1.1.1")); |
| SetLastWakeReason(WakeOnWiFi::kWakeTriggerPattern); |
| AddResultToLastSSIDResults(); |
| EXPECT_TRUE(GetWakeOnWiFiTriggers()->empty()); |
| BeforeSuspendActions(is_connected, start_lease_renewal_timer, |
| kTimeToNextLeaseRenewalLong); |
| EXPECT_EQ(GetWakeOnWiFiTriggers()->size(), 1); |
| EXPECT_TRUE(GetWakeOnWiFiTriggers()->find(WakeOnWiFi::kWakeTriggerPattern) != |
| GetWakeOnWiFiTriggers()->end()); |
| EXPECT_EQ(WakeOnWiFi::kWakeTriggerUnsupported, GetLastWakeReason()); |
| EXPECT_TRUE(GetLastSSIDMatchFreqs().empty()); |
| |
| // Only wake on SSID feature supported. |
| EnableWakeOnWiFiFeaturesDarkConnect(); |
| GetWakeOnPacketConnections()->Clear(); |
| GetWakeOnWiFiTriggersSupported()->clear(); |
| GetWakeOnWiFiTriggersSupported()->insert(WakeOnWiFi::kWakeTriggerDisconnect); |
| GetWakeOnWiFiTriggersSupported()->insert(WakeOnWiFi::kWakeTriggerSSID); |
| GetWakeOnWiFiTriggers()->clear(); |
| SetLastWakeReason(WakeOnWiFi::kWakeTriggerPattern); |
| AddResultToLastSSIDResults(); |
| EXPECT_TRUE(GetWakeOnWiFiTriggers()->empty()); |
| BeforeSuspendActions(is_connected, start_lease_renewal_timer, |
| kTimeToNextLeaseRenewalLong); |
| EXPECT_EQ(GetWakeOnWiFiTriggers()->size(), 1); |
| EXPECT_TRUE( |
| GetWakeOnWiFiTriggers()->find(WakeOnWiFi::kWakeTriggerDisconnect) != |
| GetWakeOnWiFiTriggers()->end()); |
| EXPECT_EQ(WakeOnWiFi::kWakeTriggerUnsupported, GetLastWakeReason()); |
| EXPECT_TRUE(GetLastSSIDMatchFreqs().empty()); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, |
| BeforeSuspendActions_ConnectedBeforeSuspend) { |
| const bool is_connected = true; |
| const bool start_lease_renewal_timer = true; |
| AddSSIDToWhitelist(kSSIDBytes1, sizeof(kSSIDBytes1), |
| GetWakeOnSSIDWhitelist()); |
| SetSuspendActionsDoneCallback(); |
| EnableWakeOnWiFiFeaturesPacketDarkConnect(); |
| GetWakeOnPacketConnections()->AddUnique(IPAddress("1.1.1.1")); |
| |
| SetInDarkResume(true); |
| GetWakeOnWiFiTriggers()->clear(); |
| EXPECT_TRUE(GetWakeOnWiFiTriggers()->empty()); |
| StartWakeToScanTimer(); |
| StopDHCPLeaseRenewalTimer(); |
| SetLastWakeReason(WakeOnWiFi::kWakeTriggerPattern); |
| AddResultToLastSSIDResults(); |
| EXPECT_TRUE(WakeToScanTimerIsRunning()); |
| EXPECT_FALSE(DHCPLeaseRenewalTimerIsRunning()); |
| EXPECT_CALL(*this, DoneCallback(_)).Times(0); |
| BeforeSuspendActions(is_connected, start_lease_renewal_timer, |
| kTimeToNextLeaseRenewalLong); |
| EXPECT_FALSE(GetInDarkResume()); |
| EXPECT_EQ(GetWakeOnWiFiTriggers()->size(), 2); |
| EXPECT_TRUE( |
| GetWakeOnWiFiTriggers()->find(WakeOnWiFi::kWakeTriggerDisconnect) != |
| GetWakeOnWiFiTriggers()->end()); |
| EXPECT_TRUE(GetWakeOnWiFiTriggers()->find(WakeOnWiFi::kWakeTriggerPattern) != |
| GetWakeOnWiFiTriggers()->end()); |
| EXPECT_TRUE(DHCPLeaseRenewalTimerIsRunning()); |
| EXPECT_FALSE(WakeToScanTimerIsRunning()); |
| EXPECT_EQ(WakeOnWiFi::kWakeTriggerUnsupported, GetLastWakeReason()); |
| EXPECT_TRUE(GetLastSSIDMatchFreqs().empty()); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, |
| BeforeSuspendActions_DisconnectedBeforeSuspend) { |
| const bool is_connected = false; |
| const bool start_lease_renewal_timer = true; |
| AddSSIDToWhitelist(kSSIDBytes1, sizeof(kSSIDBytes1), |
| GetWakeOnSSIDWhitelist()); |
| AddSSIDToWhitelist(kSSIDBytes2, sizeof(kSSIDBytes2), |
| GetWakeOnSSIDWhitelist()); |
| SetSuspendActionsDoneCallback(); |
| EnableWakeOnWiFiFeaturesPacketDarkConnect(); |
| |
| // Do not start wake to scan timer if there are less whitelisted SSIDs (2) |
| // than net detect SSIDs we support (10). |
| SetInDarkResume(true); |
| GetWakeOnWiFiTriggers()->clear(); |
| StopWakeToScanTimer(); |
| StartDHCPLeaseRenewalTimer(); |
| SetWakeOnWiFiMaxSSIDs(10); |
| SetLastWakeReason(WakeOnWiFi::kWakeTriggerPattern); |
| AddResultToLastSSIDResults(); |
| EXPECT_EQ(2, GetWakeOnSSIDWhitelist()->size()); |
| EXPECT_FALSE(WakeToScanTimerIsRunning()); |
| EXPECT_TRUE(DHCPLeaseRenewalTimerIsRunning()); |
| EXPECT_CALL(*this, DoneCallback(_)).Times(0); |
| BeforeSuspendActions(is_connected, start_lease_renewal_timer, |
| kTimeToNextLeaseRenewalLong); |
| EXPECT_EQ(2, GetWakeOnSSIDWhitelist()->size()); |
| EXPECT_FALSE(GetInDarkResume()); |
| EXPECT_EQ(GetWakeOnWiFiTriggers()->size(), 1); |
| EXPECT_TRUE(GetWakeOnWiFiTriggers()->find(WakeOnWiFi::kWakeTriggerSSID) != |
| GetWakeOnWiFiTriggers()->end()); |
| EXPECT_FALSE(DHCPLeaseRenewalTimerIsRunning()); |
| EXPECT_FALSE(WakeToScanTimerIsRunning()); |
| EXPECT_EQ(WakeOnWiFi::kWakeTriggerUnsupported, GetLastWakeReason()); |
| EXPECT_TRUE(GetLastSSIDMatchFreqs().empty()); |
| |
| // Start wake to scan timer if there are more whitelisted SSIDs (2) than |
| // net detect SSIDs we support (1). Also, truncate the wake on SSID whitelist |
| // so that it only contains as many SSIDs as we support (1). |
| SetInDarkResume(true); |
| GetWakeOnWiFiTriggers()->clear(); |
| StopWakeToScanTimer(); |
| StartDHCPLeaseRenewalTimer(); |
| SetWakeOnWiFiMaxSSIDs(1); |
| SetLastWakeReason(WakeOnWiFi::kWakeTriggerPattern); |
| AddResultToLastSSIDResults(); |
| EXPECT_EQ(2, GetWakeOnSSIDWhitelist()->size()); |
| EXPECT_FALSE(WakeToScanTimerIsRunning()); |
| EXPECT_TRUE(DHCPLeaseRenewalTimerIsRunning()); |
| EXPECT_CALL(*this, DoneCallback(_)).Times(0); |
| BeforeSuspendActions(is_connected, start_lease_renewal_timer, |
| kTimeToNextLeaseRenewalLong); |
| EXPECT_EQ(1, GetWakeOnSSIDWhitelist()->size()); |
| EXPECT_FALSE(GetInDarkResume()); |
| EXPECT_EQ(GetWakeOnWiFiTriggers()->size(), 1); |
| EXPECT_TRUE(GetWakeOnWiFiTriggers()->find(WakeOnWiFi::kWakeTriggerSSID) != |
| GetWakeOnWiFiTriggers()->end()); |
| EXPECT_FALSE(DHCPLeaseRenewalTimerIsRunning()); |
| EXPECT_TRUE(WakeToScanTimerIsRunning()); |
| EXPECT_EQ(WakeOnWiFi::kWakeTriggerUnsupported, GetLastWakeReason()); |
| EXPECT_TRUE(GetLastSSIDMatchFreqs().empty()); |
| |
| // Neither add the wake on SSID trigger nor start the wake to scan timer if |
| // there are no whitelisted SSIDs. |
| SetInDarkResume(true); |
| GetWakeOnSSIDWhitelist()->clear(); |
| StopWakeToScanTimer(); |
| StartDHCPLeaseRenewalTimer(); |
| SetWakeOnWiFiMaxSSIDs(10); |
| SetLastWakeReason(WakeOnWiFi::kWakeTriggerPattern); |
| AddResultToLastSSIDResults(); |
| EXPECT_TRUE(GetWakeOnSSIDWhitelist()->empty()); |
| EXPECT_FALSE(WakeToScanTimerIsRunning()); |
| EXPECT_TRUE(DHCPLeaseRenewalTimerIsRunning()); |
| EXPECT_CALL(*this, DoneCallback(_)).Times(0); |
| BeforeSuspendActions(is_connected, start_lease_renewal_timer, |
| kTimeToNextLeaseRenewalLong); |
| EXPECT_TRUE(GetWakeOnSSIDWhitelist()->empty()); |
| EXPECT_FALSE(GetInDarkResume()); |
| EXPECT_TRUE(GetWakeOnWiFiTriggers()->empty()); |
| EXPECT_FALSE(DHCPLeaseRenewalTimerIsRunning()); |
| EXPECT_FALSE(WakeToScanTimerIsRunning()); |
| EXPECT_EQ(WakeOnWiFi::kWakeTriggerUnsupported, GetLastWakeReason()); |
| EXPECT_TRUE(GetLastSSIDMatchFreqs().empty()); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, DisableWakeOnWiFi_ClearsTriggers) { |
| GetWakeOnWiFiTriggers()->insert(WakeOnWiFi::kWakeTriggerPattern); |
| EXPECT_FALSE(GetWakeOnWiFiTriggers()->empty()); |
| DisableWakeOnWiFi(); |
| EXPECT_TRUE(GetWakeOnWiFiTriggers()->empty()); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, ParseWakeOnSSIDResults) { |
| SetWakeOnPacketConnMessage msg; |
| NetlinkPacket packet(kWakeReasonSSIDNlMsg, sizeof(kWakeReasonSSIDNlMsg)); |
| msg.InitFromPacket(&packet, GetWakeupReportMsgContext()); |
| AttributeListConstRefPtr triggers; |
| ASSERT_TRUE(msg.const_attributes()->ConstGetNestedAttributeList( |
| NL80211_ATTR_WOWLAN_TRIGGERS, &triggers)); |
| AttributeListConstRefPtr results_list; |
| ASSERT_TRUE(triggers->ConstGetNestedAttributeList( |
| NL80211_WOWLAN_TRIG_NET_DETECT_RESULTS, &results_list)); |
| WiFi::FreqSet freqs = ParseWakeOnSSIDResults(results_list); |
| EXPECT_EQ(arraysize(kSSID1FreqMatches), freqs.size()); |
| for (uint32_t freq : kSSID1FreqMatches) { |
| EXPECT_TRUE(freqs.find(freq) != freqs.end()); |
| } |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, OnScanStarted_NotInDarkResume) { |
| SetInDarkResume(false); |
| EXPECT_CALL(metrics_, NotifyScanStartedInDarkResume(_)).Times(0); |
| OnScanStarted(false); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, OnScanStarted_IgnoredWakeReasons) { |
| // Do not log metrics if we entered dark resume because of wake on SSID or |
| // wake on disconnect. |
| SetInDarkResume(true); |
| SetLastWakeReason(WakeOnWiFi::kWakeTriggerSSID); |
| EXPECT_CALL(metrics_, NotifyScanStartedInDarkResume(_)).Times(0); |
| OnScanStarted(false); |
| |
| SetLastWakeReason(WakeOnWiFi::kWakeTriggerDisconnect); |
| EXPECT_CALL(metrics_, NotifyScanStartedInDarkResume(_)).Times(0); |
| OnScanStarted(false); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, OnScanStarted_LogMetrics) { |
| // Log metrics if we entered dark resume because of wake on pattern or an |
| // unsupported wake reason. |
| SetInDarkResume(true); |
| SetLastWakeReason(WakeOnWiFi::kWakeTriggerUnsupported); |
| EXPECT_CALL(metrics_, NotifyScanStartedInDarkResume(_)); |
| OnScanStarted(false); |
| |
| SetLastWakeReason(WakeOnWiFi::kWakeTriggerPattern); |
| EXPECT_CALL(metrics_, NotifyScanStartedInDarkResume(_)); |
| OnScanStarted(false); |
| |
| // Log error if an active scan is launched. |
| ScopedMockLog log; |
| EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); |
| EXPECT_CALL(log, |
| Log(logging::LOG_ERROR, _, |
| HasSubstr("Unexpected active scan launched in dark resume"))); |
| EXPECT_CALL(metrics_, NotifyScanStartedInDarkResume(_)); |
| OnScanStarted(true); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithDispatcher, InitiateScanInDarkResume) { |
| WiFi::FreqSet freqs; |
| |
| // If we are not scanning on specific frequencies, do not enable the retry |
| // mechanism. |
| EXPECT_EQ(0, GetDarkResumeScanRetriesLeft()); |
| EXPECT_CALL(*this, InitiateScanCallback(freqs)); |
| InitiateScanInDarkResume(freqs); |
| EXPECT_EQ(0, GetDarkResumeScanRetriesLeft()); |
| |
| // Otherwise, start channel specific passive scan with retries. |
| freqs.insert(1); |
| EXPECT_LE(freqs.size(), WakeOnWiFi::kMaxFreqsForDarkResumeScanRetries); |
| EXPECT_EQ(0, GetDarkResumeScanRetriesLeft()); |
| EXPECT_CALL(*this, InitiateScanCallback(freqs)); |
| InitiateScanInDarkResume(freqs); |
| EXPECT_EQ(WakeOnWiFi::kMaxDarkResumeScanRetries, |
| GetDarkResumeScanRetriesLeft()); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, AddRemoveWakeOnPacketConnection) { |
| const string bad_ip_string("1.1"); |
| const string ip_string1("192.168.0.19"); |
| const string ip_string2("192.168.0.55"); |
| const string ip_string3("192.168.0.74"); |
| IPAddress ip_addr1(ip_string1); |
| IPAddress ip_addr2(ip_string2); |
| IPAddress ip_addr3(ip_string3); |
| Error e; |
| |
| // Add and remove operations will fail if we provide an invalid IP address |
| // string. |
| EnableWakeOnWiFiFeaturesPacket(); |
| AddWakeOnPacketConnection(bad_ip_string, &e); |
| EXPECT_EQ(e.type(), Error::kInvalidArguments); |
| EXPECT_STREQ(e.message().c_str(), |
| ("Invalid ip_address " + bad_ip_string).c_str()); |
| RemoveWakeOnPacketConnection(bad_ip_string, &e); |
| EXPECT_EQ(e.type(), Error::kInvalidArguments); |
| EXPECT_STREQ(e.message().c_str(), |
| ("Invalid ip_address " + bad_ip_string).c_str()); |
| |
| // Add and remove operations will fail if WiFi device does not support |
| // pattern matching functionality, even if the feature is enabled. |
| EnableWakeOnWiFiFeaturesPacket(); |
| ClearWakeOnWiFiTriggersSupported(); |
| AddWakeOnPacketConnection(ip_string1, &e); |
| EXPECT_EQ(e.type(), Error::kNotSupported); |
| EXPECT_STREQ(e.message().c_str(), |
| "Wake on IP address patterns not supported by this WiFi device"); |
| RemoveAllWakeOnPacketConnections(&e); |
| EXPECT_EQ(e.type(), Error::kNotSupported); |
| EXPECT_STREQ(e.message().c_str(), |
| "Wake on IP address patterns not supported by this WiFi device"); |
| RemoveWakeOnPacketConnection(ip_string2, &e); |
| EXPECT_EQ(e.type(), Error::kNotSupported); |
| EXPECT_STREQ(e.message().c_str(), |
| "Wake on IP address patterns not supported by this WiFi device"); |
| |
| // Add operation will fail if pattern matching is supported but the max number |
| // of IP address patterns have already been registered. |
| EnableWakeOnWiFiFeaturesPacketDarkConnect(); |
| GetWakeOnWiFiTriggersSupported()->insert(WakeOnWiFi::kWakeTriggerPattern); |
| SetWakeOnWiFiMaxPatterns(1); |
| GetWakeOnPacketConnections()->AddUnique(IPAddress(ip_string1)); |
| AddWakeOnPacketConnection(ip_string2, &e); |
| EXPECT_EQ(e.type(), Error::kOperationFailed); |
| EXPECT_STREQ(e.message().c_str(), |
| "Max number of IP address patterns already registered"); |
| |
| // Add and remove operations will still execute even when the wake on packet |
| // feature has been disabled. |
| e.Reset(); |
| GetWakeOnPacketConnections()->Clear(); |
| SetWakeOnWiFiMaxPatterns(50); |
| DisableWakeOnWiFiFeatures(); |
| GetWakeOnWiFiTriggersSupported()->insert(WakeOnWiFi::kWakeTriggerPattern); |
| AddWakeOnPacketConnection(ip_string1, &e); |
| EXPECT_EQ(GetWakeOnPacketConnections()->Count(), 1); |
| EXPECT_TRUE(GetWakeOnPacketConnections()->Contains(ip_addr1)); |
| AddWakeOnPacketConnection(ip_string2, &e); |
| EXPECT_EQ(GetWakeOnPacketConnections()->Count(), 2); |
| EXPECT_TRUE(GetWakeOnPacketConnections()->Contains(ip_addr2)); |
| RemoveWakeOnPacketConnection(ip_string1, &e); |
| EXPECT_EQ(GetWakeOnPacketConnections()->Count(), 1); |
| |
| AddWakeOnPacketOfTypes({"TCP", "UDP"}, &e); |
| RemoveAllWakeOnPacketConnections(&e); |
| EXPECT_TRUE(GetWakeOnPacketConnections()->Empty()); |
| EXPECT_TRUE(GetWakeOnPacketTypes().empty()); |
| |
| // Normal functioning of add/remove operations when wake on WiFi features |
| // are enabled, the NIC supports pattern matching, and the max number |
| // of patterns have not been registered yet. |
| EnableWakeOnWiFiFeaturesPacketDarkConnect(); |
| GetWakeOnPacketConnections()->Clear(); |
| EXPECT_TRUE(GetWakeOnPacketConnections()->Empty()); |
| AddWakeOnPacketConnection(ip_string1, &e); |
| EXPECT_EQ(GetWakeOnPacketConnections()->Count(), 1); |
| EXPECT_TRUE(GetWakeOnPacketConnections()->Contains(ip_addr1)); |
| EXPECT_FALSE(GetWakeOnPacketConnections()->Contains(ip_addr2)); |
| EXPECT_FALSE(GetWakeOnPacketConnections()->Contains(ip_addr3)); |
| |
| AddWakeOnPacketConnection(ip_string2, &e); |
| EXPECT_EQ(GetWakeOnPacketConnections()->Count(), 2); |
| EXPECT_TRUE(GetWakeOnPacketConnections()->Contains(ip_addr1)); |
| EXPECT_TRUE(GetWakeOnPacketConnections()->Contains(ip_addr2)); |
| EXPECT_FALSE(GetWakeOnPacketConnections()->Contains(ip_addr3)); |
| |
| AddWakeOnPacketConnection(ip_string3, &e); |
| EXPECT_EQ(GetWakeOnPacketConnections()->Count(), 3); |
| EXPECT_TRUE(GetWakeOnPacketConnections()->Contains(ip_addr1)); |
| EXPECT_TRUE(GetWakeOnPacketConnections()->Contains(ip_addr2)); |
| EXPECT_TRUE(GetWakeOnPacketConnections()->Contains(ip_addr3)); |
| |
| RemoveWakeOnPacketConnection(ip_string2, &e); |
| EXPECT_EQ(GetWakeOnPacketConnections()->Count(), 2); |
| EXPECT_TRUE(GetWakeOnPacketConnections()->Contains(ip_addr1)); |
| EXPECT_FALSE(GetWakeOnPacketConnections()->Contains(ip_addr2)); |
| EXPECT_TRUE(GetWakeOnPacketConnections()->Contains(ip_addr3)); |
| |
| // Remove fails if no such address is registered. |
| RemoveWakeOnPacketConnection(ip_string2, &e); |
| EXPECT_EQ(e.type(), Error::kNotFound); |
| EXPECT_STREQ(e.message().c_str(), |
| "No such IP address match registered to wake device"); |
| EXPECT_EQ(GetWakeOnPacketConnections()->Count(), 2); |
| |
| RemoveWakeOnPacketConnection(ip_string1, &e); |
| EXPECT_EQ(GetWakeOnPacketConnections()->Count(), 1); |
| EXPECT_FALSE(GetWakeOnPacketConnections()->Contains(ip_addr1)); |
| EXPECT_FALSE(GetWakeOnPacketConnections()->Contains(ip_addr2)); |
| EXPECT_TRUE(GetWakeOnPacketConnections()->Contains(ip_addr3)); |
| |
| AddWakeOnPacketConnection(ip_string2, &e); |
| EXPECT_EQ(GetWakeOnPacketConnections()->Count(), 2); |
| EXPECT_FALSE(GetWakeOnPacketConnections()->Contains(ip_addr1)); |
| EXPECT_TRUE(GetWakeOnPacketConnections()->Contains(ip_addr2)); |
| EXPECT_TRUE(GetWakeOnPacketConnections()->Contains(ip_addr3)); |
| |
| RemoveAllWakeOnPacketConnections(&e); |
| EXPECT_EQ(GetWakeOnPacketConnections()->Count(), 0); |
| EXPECT_FALSE(GetWakeOnPacketConnections()->Contains(ip_addr1)); |
| EXPECT_FALSE(GetWakeOnPacketConnections()->Contains(ip_addr2)); |
| EXPECT_FALSE(GetWakeOnPacketConnections()->Contains(ip_addr3)); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, AddRemoveWakeOnPacketOfType) { |
| const string ip_string1("192.168.0.19"); |
| IPAddress ip_addr1(ip_string1); |
| Error e; |
| |
| // Add and remove operations will fail if WiFi device does not support |
| // pattern matching functionality, even if the feature is enabled. |
| EnableWakeOnWiFiFeaturesPacket(); |
| ClearWakeOnWiFiTriggersSupported(); |
| AddWakeOnPacketOfTypes({"TCP", "UDP"}, &e); |
| EXPECT_EQ(e.type(), Error::kNotSupported); |
| EXPECT_STREQ(e.message().c_str(), |
| "Wake on patterns not supported by this WiFi device"); |
| EXPECT_EQ(e.type(), Error::kNotSupported); |
| EXPECT_STREQ(e.message().c_str(), |
| "Wake on patterns not supported by this WiFi device"); |
| |
| // Add operation will fail if pattern matching is supported but the max number |
| // of IP address patterns have already been registered. |
| EnableWakeOnWiFiFeaturesPacketDarkConnect(); |
| GetWakeOnWiFiTriggersSupported()->insert(WakeOnWiFi::kWakeTriggerPattern); |
| SetWakeOnWiFiMaxPatterns(1); |
| GetWakeOnPacketConnections()->AddUnique(IPAddress(ip_string1)); |
| AddWakeOnPacketOfTypes({"TCP", "UDP"}, &e); |
| EXPECT_EQ(e.type(), Error::kOperationFailed); |
| EXPECT_STREQ(e.message().c_str(), |
| "Max number of patterns already registered"); |
| // Add and remove operations will still execute even when the wake on packet |
| // feature has been disabled. |
| GetWakeOnPacketConnections()->Clear(); |
| SetWakeOnWiFiMaxPatterns(50); |
| DisableWakeOnWiFiFeatures(); |
| GetWakeOnWiFiTriggersSupported()->insert(WakeOnWiFi::kWakeTriggerPattern); |
| AddWakeOnPacketOfTypes({"TCP", "UDP"}, &e); |
| EXPECT_EQ(GetWakeOnPacketConnections()->Count(), 0); |
| |
| EXPECT_EQ(GetWakeOnPacketTypes().size(), 2); |
| EXPECT_EQ(GetWakeOnWiFiMaxPatterns(), 50); |
| // Normal functioning of add/remove operations when wake on WiFi features |
| // are enabled, the NIC supports pattern matching, and the max number |
| // of patterns have not been registered yet. |
| EnableWakeOnWiFiFeaturesPacketDarkConnect(); |
| GetWakeOnPacketConnections()->Clear(); |
| SetWakeOnWiFiMaxPatterns(50); |
| EXPECT_TRUE(GetWakeOnPacketConnections()->Empty()); |
| AddWakeOnPacketConnection(ip_string1, &e); |
| AddWakeOnPacketOfTypes({"TCP", "UDP"}, &e); |
| EXPECT_EQ(GetWakeOnPacketConnections()->Count(), 1); |
| EXPECT_TRUE(GetWakeOnPacketConnections()->Contains(ip_addr1)); |
| |
| EXPECT_EQ(GetWakeOnWiFiMaxPatterns(), 50); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithDispatcher, OnBeforeSuspend_SetsWakeOnSSIDWhitelist) { |
| vector<ByteString> whitelist; |
| AddSSIDToWhitelist(kSSIDBytes1, sizeof(kSSIDBytes1), &whitelist); |
| EXPECT_TRUE(GetWakeOnSSIDWhitelist()->empty()); |
| OnBeforeSuspend(true, whitelist, true, 0); |
| EXPECT_FALSE(GetWakeOnSSIDWhitelist()->empty()); |
| EXPECT_EQ(1, GetWakeOnSSIDWhitelist()->size()); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithDispatcher, OnBeforeSuspend_SetsDoneCallback) { |
| vector<ByteString> whitelist; |
| EXPECT_TRUE(SuspendActionsCallbackIsNull()); |
| OnBeforeSuspend(true, whitelist, true, 0); |
| EXPECT_FALSE(SuspendActionsCallbackIsNull()); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, OnBeforeSuspend_DHCPLeaseRenewal) { |
| bool is_connected; |
| bool have_dhcp_lease; |
| vector<ByteString> whitelist; |
| AddSSIDToWhitelist(kSSIDBytes1, sizeof(kSSIDBytes1), &whitelist); |
| // If we are connected the time to next lease renewal is short enough, we will |
| // initiate DHCP lease renewal immediately. |
| is_connected = true; |
| have_dhcp_lease = true; |
| EXPECT_CALL(*this, RenewDHCPLeaseCallback()).Times(1); |
| EXPECT_CALL(mock_dispatcher_, PostTask(_, _)).Times(1); |
| OnBeforeSuspend(is_connected, whitelist, have_dhcp_lease, |
| kTimeToNextLeaseRenewalShort); |
| |
| // No immediate DHCP lease renewal because we are not connected. |
| is_connected = false; |
| have_dhcp_lease = true; |
| EXPECT_CALL(*this, RenewDHCPLeaseCallback()).Times(0); |
| EXPECT_CALL(mock_dispatcher_, PostTask(_, _)).Times(1); |
| OnBeforeSuspend(is_connected, whitelist, have_dhcp_lease, |
| kTimeToNextLeaseRenewalShort); |
| |
| // No immediate DHCP lease renewal because the time to the next lease renewal |
| // is longer than the threshold. |
| is_connected = true; |
| have_dhcp_lease = true; |
| EXPECT_CALL(*this, RenewDHCPLeaseCallback()).Times(0); |
| EXPECT_CALL(mock_dispatcher_, PostTask(_, _)).Times(1); |
| OnBeforeSuspend(is_connected, whitelist, have_dhcp_lease, |
| kTimeToNextLeaseRenewalLong); |
| |
| // No immediate DHCP lease renewal because we do not have a DHCP lease that |
| // needs to be renewed. |
| is_connected = true; |
| have_dhcp_lease = false; |
| EXPECT_CALL(*this, RenewDHCPLeaseCallback()).Times(0); |
| EXPECT_CALL(mock_dispatcher_, PostTask(_, _)).Times(1); |
| OnBeforeSuspend(is_connected, whitelist, have_dhcp_lease, |
| kTimeToNextLeaseRenewalLong); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithDispatcher, OnDarkResume_ResetsDarkResumeScanRetries) { |
| const bool is_connected = true; |
| vector<ByteString> whitelist; |
| SetDarkResumeScanRetriesLeft(3); |
| EXPECT_EQ(3, GetDarkResumeScanRetriesLeft()); |
| OnDarkResume(is_connected, whitelist); |
| EXPECT_EQ(0, GetDarkResumeScanRetriesLeft()); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithDispatcher, OnDarkResume_SetsWakeOnSSIDWhitelist) { |
| const bool is_connected = true; |
| vector<ByteString> whitelist; |
| AddSSIDToWhitelist(kSSIDBytes1, sizeof(kSSIDBytes1), &whitelist); |
| EXPECT_TRUE(GetWakeOnSSIDWhitelist()->empty()); |
| OnDarkResume(is_connected, whitelist); |
| EXPECT_FALSE(GetWakeOnSSIDWhitelist()->empty()); |
| EXPECT_EQ(1, GetWakeOnSSIDWhitelist()->size()); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithDispatcher, |
| OnDarkResume_WakeReasonUnsupported_Connected_Timeout) { |
| // Test that correct actions are taken if we enter OnDarkResume on an |
| // unsupported wake trigger while connected, then timeout on suspend actions |
| // before suspending again. |
| const bool is_connected = true; |
| SetLastWakeReason(WakeOnWiFi::kWakeTriggerUnsupported); |
| vector<ByteString> whitelist; |
| AddSSIDToWhitelist(kSSIDBytes1, sizeof(kSSIDBytes1), &whitelist); |
| InitStateForDarkResume(); |
| EXPECT_TRUE(DarkResumeActionsTimeOutCallbackIsCancelled()); |
| // Renew DHCP lease if we are connected in dark resume. |
| EXPECT_CALL(*this, RenewDHCPLeaseCallback()); |
| EXPECT_CALL(metrics_, NotifyWakeOnWiFiOnDarkResume( |
| WakeOnWiFi::kWakeTriggerUnsupported)); |
| OnDarkResume(is_connected, whitelist); |
| EXPECT_FALSE(DarkResumeActionsTimeOutCallbackIsCancelled()); |
| // Trigger timeout callback. |
| // Since we timeout, we are disconnected before suspend. |
| StartDHCPLeaseRenewalTimer(); |
| SetExpectationsDisconnectedBeforeSuspend(); |
| dispatcher_.DispatchPendingEvents(); |
| EXPECT_FALSE(DHCPLeaseRenewalTimerIsRunning()); |
| VerifyStateDisconnectedBeforeSuspend(); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithDispatcher, |
| OnDarkResume_WakeReasonUnsupported_Connected_NoAutoconnectableServices) { |
| // Test that correct actions are taken if we enter OnDarkResume on an |
| // unsupported wake trigger while connected, then go back to suspend because |
| // we could not find any services available for autoconnect. |
| const bool is_connected = true; |
| SetLastWakeReason(WakeOnWiFi::kWakeTriggerUnsupported); |
| vector<ByteString> whitelist; |
| AddSSIDToWhitelist(kSSIDBytes1, sizeof(kSSIDBytes1), &whitelist); |
| InitStateForDarkResume(); |
| EXPECT_TRUE(DarkResumeActionsTimeOutCallbackIsCancelled()); |
| // Renew DHCP lease if we are connected in dark resume. |
| EXPECT_CALL(*this, RenewDHCPLeaseCallback()); |
| EXPECT_CALL(metrics_, NotifyWakeOnWiFiOnDarkResume( |
| WakeOnWiFi::kWakeTriggerUnsupported)); |
| OnDarkResume(is_connected, whitelist); |
| EXPECT_FALSE(DarkResumeActionsTimeOutCallbackIsCancelled()); |
| |
| StartDHCPLeaseRenewalTimer(); |
| SetExpectationsDisconnectedBeforeSuspend(); |
| OnNoAutoConnectableServicesAfterScan(whitelist); |
| EXPECT_FALSE(DHCPLeaseRenewalTimerIsRunning()); |
| VerifyStateDisconnectedBeforeSuspend(); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithDispatcher, |
| OnDarkResume_WakeReasonUnsupported_Connected_LeaseObtained) { |
| // Test that correct actions are taken if we enter OnDarkResume on an |
| // unsupported wake trigger while connected, then connect and obtain a DHCP |
| // lease before suspending again. |
| const bool is_connected = true; |
| const bool have_dhcp_lease = true; |
| const uint32_t time_to_next_lease_renewal = 10; |
| SetLastWakeReason(WakeOnWiFi::kWakeTriggerUnsupported); |
| vector<ByteString> whitelist; |
| AddSSIDToWhitelist(kSSIDBytes1, sizeof(kSSIDBytes1), &whitelist); |
| InitStateForDarkResume(); |
| EXPECT_TRUE(DarkResumeActionsTimeOutCallbackIsCancelled()); |
| // Renew DHCP lease if we are connected in dark resume. |
| EXPECT_CALL(*this, RenewDHCPLeaseCallback()); |
| EXPECT_CALL(metrics_, NotifyWakeOnWiFiOnDarkResume( |
| WakeOnWiFi::kWakeTriggerUnsupported)); |
| OnDarkResume(is_connected, whitelist); |
| EXPECT_FALSE(DarkResumeActionsTimeOutCallbackIsCancelled()); |
| // Lease obtained. |
| // Since a lease is obtained, we are connected before suspend. |
| StopDHCPLeaseRenewalTimer(); |
| StartWakeToScanTimer(); |
| SetExpectationsConnectedBeforeSuspend(); |
| OnConnectedAndReachable(have_dhcp_lease, time_to_next_lease_renewal); |
| EXPECT_TRUE(DHCPLeaseRenewalTimerIsRunning()); |
| EXPECT_FALSE(WakeToScanTimerIsRunning()); |
| VerifyStateConnectedBeforeSuspend(); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithDispatcher, |
| OnDarkResume_WakeReasonUnsupported_NotConnected_Timeout) { |
| // Test that correct actions are taken if we enter OnDarkResume on an |
| // unsupported wake trigger while not connected, then timeout on suspend |
| // actions before suspending again. |
| const bool is_connected = false; |
| SetLastWakeReason(WakeOnWiFi::kWakeTriggerUnsupported); |
| vector<ByteString> whitelist; |
| AddSSIDToWhitelist(kSSIDBytes1, sizeof(kSSIDBytes1), &whitelist); |
| InitStateForDarkResume(); |
| EXPECT_TRUE(DarkResumeActionsTimeOutCallbackIsCancelled()); |
| // Initiate scan if we are not connected in dark resume. |
| EXPECT_CALL(*this, RemoveSupplicantNetworksCallback()); |
| EXPECT_CALL(metrics_, NotifyDarkResumeInitiateScan()); |
| EXPECT_CALL(*this, InitiateScanCallback(_)); |
| EXPECT_CALL(metrics_, NotifyWakeOnWiFiOnDarkResume( |
| WakeOnWiFi::kWakeTriggerUnsupported)); |
| OnDarkResume(is_connected, whitelist); |
| EXPECT_FALSE(DarkResumeActionsTimeOutCallbackIsCancelled()); |
| // Trigger timeout callback. |
| // Since we timeout, we are disconnected before suspend. |
| StartDHCPLeaseRenewalTimer(); |
| SetExpectationsDisconnectedBeforeSuspend(); |
| dispatcher_.DispatchPendingEvents(); |
| EXPECT_FALSE(DHCPLeaseRenewalTimerIsRunning()); |
| VerifyStateDisconnectedBeforeSuspend(); |
| } |
| |
| TEST_F( |
| WakeOnWiFiTestWithDispatcher, |
| OnDarkResume_WakeReasonUnsupported_NotConnected_NoAutoconnectableServices) { |
| // Test that correct actions are taken if we enter OnDarkResume on an |
| // unsupported wake trigger while not connected, then go back to suspend |
| // because we could not find any services available for autoconnect. |
| const bool is_connected = false; |
| SetLastWakeReason(WakeOnWiFi::kWakeTriggerUnsupported); |
| vector<ByteString> whitelist; |
| AddSSIDToWhitelist(kSSIDBytes1, sizeof(kSSIDBytes1), &whitelist); |
| InitStateForDarkResume(); |
| EXPECT_TRUE(DarkResumeActionsTimeOutCallbackIsCancelled()); |
| // Initiate scan if we are not connected in dark resume. |
| EXPECT_CALL(*this, RemoveSupplicantNetworksCallback()); |
| EXPECT_CALL(metrics_, NotifyDarkResumeInitiateScan()); |
| EXPECT_CALL(*this, InitiateScanCallback(_)); |
| EXPECT_CALL(metrics_, NotifyWakeOnWiFiOnDarkResume( |
| WakeOnWiFi::kWakeTriggerUnsupported)); |
| OnDarkResume(is_connected, whitelist); |
| EXPECT_FALSE(DarkResumeActionsTimeOutCallbackIsCancelled()); |
| |
| StartDHCPLeaseRenewalTimer(); |
| SetExpectationsDisconnectedBeforeSuspend(); |
| OnNoAutoConnectableServicesAfterScan(whitelist); |
| EXPECT_FALSE(DHCPLeaseRenewalTimerIsRunning()); |
| VerifyStateDisconnectedBeforeSuspend(); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithDispatcher, |
| OnDarkResume_WakeReasonUnsupported_NotConnected_LeaseObtained) { |
| // Test that correct actions are taken if we enter OnDarkResume on an |
| // unsupported wake trigger while connected, then connect and obtain a DHCP |
| // lease before suspending again. |
| const bool is_connected = false; |
| const bool have_dhcp_lease = true; |
| const uint32_t time_to_next_lease_renewal = 10; |
| SetLastWakeReason(WakeOnWiFi::kWakeTriggerUnsupported); |
| vector<ByteString> whitelist; |
| AddSSIDToWhitelist(kSSIDBytes1, sizeof(kSSIDBytes1), &whitelist); |
| InitStateForDarkResume(); |
| EXPECT_TRUE(DarkResumeActionsTimeOutCallbackIsCancelled()); |
| // Initiate scan if we are not connected in dark resume. |
| EXPECT_CALL(*this, RemoveSupplicantNetworksCallback()); |
| EXPECT_CALL(metrics_, NotifyDarkResumeInitiateScan()); |
| EXPECT_CALL(*this, InitiateScanCallback(_)); |
| EXPECT_CALL(metrics_, NotifyWakeOnWiFiOnDarkResume( |
| WakeOnWiFi::kWakeTriggerUnsupported)); |
| OnDarkResume(is_connected, whitelist); |
| EXPECT_FALSE(DarkResumeActionsTimeOutCallbackIsCancelled()); |
| // Lease obtained. |
| // Since a lease is obtained, we are connected before suspend. |
| StopDHCPLeaseRenewalTimer(); |
| StartWakeToScanTimer(); |
| SetExpectationsConnectedBeforeSuspend(); |
| OnConnectedAndReachable(have_dhcp_lease, time_to_next_lease_renewal); |
| EXPECT_TRUE(DHCPLeaseRenewalTimerIsRunning()); |
| EXPECT_FALSE(WakeToScanTimerIsRunning()); |
| VerifyStateConnectedBeforeSuspend(); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithDispatcher, OnDarkResume_WakeReasonPattern) { |
| // Test that correct actions are taken if we enter dark resume because the |
| // system woke on a packet pattern match. We assume that we wake connected and |
| // and go back to sleep connected if we wake on pattern. |
| const bool is_connected = true; |
| SetLastWakeReason(WakeOnWiFi::kWakeTriggerPattern); |
| vector<ByteString> whitelist; |
| AddSSIDToWhitelist(kSSIDBytes1, sizeof(kSSIDBytes1), &whitelist); |
| |
| InitStateForDarkResume(); |
| EXPECT_TRUE(DarkResumeActionsTimeOutCallbackIsCancelled()); |
| EXPECT_CALL(metrics_, |
| NotifyWakeOnWiFiOnDarkResume(WakeOnWiFi::kWakeTriggerPattern)); |
| OnDarkResume(is_connected, whitelist); |
| EXPECT_FALSE(DarkResumeActionsTimeOutCallbackIsCancelled()); |
| |
| StartWakeToScanTimer(); |
| SetExpectationsConnectedBeforeSuspend(); |
| dispatcher_.DispatchPendingEvents(); |
| EXPECT_EQ(WakeOnWiFi::kWakeTriggerUnsupported, GetLastWakeReason()); |
| EXPECT_FALSE(WakeToScanTimerIsRunning()); |
| VerifyStateConnectedBeforeSuspend(); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithDispatcher, |
| OnDarkResume_WakeReasonDisconnect_NoAutoconnectableServices) { |
| // Test that correct actions are taken if we enter dark resume because the |
| // system woke on a disconnect, and go back to suspend because we could not |
| // find any networks available for autoconnect. |
| const bool is_connected = false; |
| SetLastWakeReason(WakeOnWiFi::kWakeTriggerDisconnect); |
| vector<ByteString> whitelist; |
| AddSSIDToWhitelist(kSSIDBytes1, sizeof(kSSIDBytes1), &whitelist); |
| |
| InitStateForDarkResume(); |
| EXPECT_TRUE(DarkResumeActionsTimeOutCallbackIsCancelled()); |
| EXPECT_CALL(*this, RemoveSupplicantNetworksCallback()); |
| EXPECT_CALL(metrics_, NotifyDarkResumeInitiateScan()); |
| EXPECT_CALL(*this, InitiateScanCallback(_)); |
| EXPECT_CALL(metrics_, |
| NotifyWakeOnWiFiOnDarkResume(WakeOnWiFi::kWakeTriggerDisconnect)); |
| OnDarkResume(is_connected, whitelist); |
| EXPECT_FALSE(DarkResumeActionsTimeOutCallbackIsCancelled()); |
| |
| StartDHCPLeaseRenewalTimer(); |
| SetExpectationsDisconnectedBeforeSuspend(); |
| OnNoAutoConnectableServicesAfterScan(whitelist); |
| EXPECT_EQ(WakeOnWiFi::kWakeTriggerUnsupported, GetLastWakeReason()); |
| EXPECT_FALSE(DHCPLeaseRenewalTimerIsRunning()); |
| VerifyStateDisconnectedBeforeSuspend(); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithDispatcher, |
| OnDarkResume_WakeReasonDisconnect_Timeout) { |
| // Test that correct actions are taken if we enter dark resume because the |
| // system woke on a disconnect, then timeout on suspend actions before |
| // suspending again. |
| const bool is_connected = false; |
| SetLastWakeReason(WakeOnWiFi::kWakeTriggerDisconnect); |
| vector<ByteString> whitelist; |
| AddSSIDToWhitelist(kSSIDBytes1, sizeof(kSSIDBytes1), &whitelist); |
| |
| InitStateForDarkResume(); |
| EXPECT_TRUE(DarkResumeActionsTimeOutCallbackIsCancelled()); |
| EXPECT_CALL(*this, RemoveSupplicantNetworksCallback()); |
| EXPECT_CALL(metrics_, NotifyDarkResumeInitiateScan()); |
| EXPECT_CALL(*this, InitiateScanCallback(_)); |
| EXPECT_CALL(metrics_, |
| NotifyWakeOnWiFiOnDarkResume(WakeOnWiFi::kWakeTriggerDisconnect)); |
| OnDarkResume(is_connected, whitelist); |
| EXPECT_FALSE(DarkResumeActionsTimeOutCallbackIsCancelled()); |
| |
| StartDHCPLeaseRenewalTimer(); |
| SetExpectationsDisconnectedBeforeSuspend(); |
| dispatcher_.DispatchPendingEvents(); |
| EXPECT_EQ(WakeOnWiFi::kWakeTriggerUnsupported, GetLastWakeReason()); |
| EXPECT_FALSE(DHCPLeaseRenewalTimerIsRunning()); |
| VerifyStateDisconnectedBeforeSuspend(); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithDispatcher, |
| OnDarkResume_WakeReasonDisconnect_LeaseObtained) { |
| // Test that correct actions are taken if we enter dark resume because the |
| // system woke on a disconnect, then connect and obtain a DHCP lease before |
| // suspending again. |
| const bool is_connected = false; |
| const bool have_dhcp_lease = true; |
| const uint32_t time_to_next_lease_renewal = 10; |
| SetLastWakeReason(WakeOnWiFi::kWakeTriggerDisconnect); |
| vector<ByteString> whitelist; |
| AddSSIDToWhitelist(kSSIDBytes1, sizeof(kSSIDBytes1), &whitelist); |
| |
| InitStateForDarkResume(); |
| EXPECT_TRUE(DarkResumeActionsTimeOutCallbackIsCancelled()); |
| EXPECT_CALL(*this, RemoveSupplicantNetworksCallback()); |
| EXPECT_CALL(metrics_, NotifyDarkResumeInitiateScan()); |
| EXPECT_CALL(*this, InitiateScanCallback(_)); |
| EXPECT_CALL(metrics_, |
| NotifyWakeOnWiFiOnDarkResume(WakeOnWiFi::kWakeTriggerDisconnect)); |
| OnDarkResume(is_connected, whitelist); |
| EXPECT_FALSE(DarkResumeActionsTimeOutCallbackIsCancelled()); |
| |
| StopDHCPLeaseRenewalTimer(); |
| StartWakeToScanTimer(); |
| SetExpectationsConnectedBeforeSuspend(); |
| OnConnectedAndReachable(have_dhcp_lease, time_to_next_lease_renewal); |
| EXPECT_EQ(WakeOnWiFi::kWakeTriggerUnsupported, GetLastWakeReason()); |
| EXPECT_TRUE(DHCPLeaseRenewalTimerIsRunning()); |
| EXPECT_FALSE(WakeToScanTimerIsRunning()); |
| VerifyStateConnectedBeforeSuspend(); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithDispatcher, |
| OnDarkResume_WakeReasonSSID_NoAutoconnectableServices) { |
| // Test that correct actions are taken if we enter dark resume because the |
| // system woke on SSID, and go back to suspend because we could not find any |
| // networks available for autoconnect. |
| const bool is_connected = false; |
| SetLastWakeReason(WakeOnWiFi::kWakeTriggerSSID); |
| vector<ByteString> whitelist; |
| AddSSIDToWhitelist(kSSIDBytes1, sizeof(kSSIDBytes1), &whitelist); |
| |
| InitStateForDarkResume(); |
| EXPECT_TRUE(DarkResumeActionsTimeOutCallbackIsCancelled()); |
| EXPECT_CALL(*this, RemoveSupplicantNetworksCallback()); |
| EXPECT_CALL(metrics_, NotifyDarkResumeInitiateScan()); |
| EXPECT_CALL(*this, InitiateScanCallback(_)); |
| EXPECT_CALL(metrics_, |
| NotifyWakeOnWiFiOnDarkResume(WakeOnWiFi::kWakeTriggerSSID)); |
| OnDarkResume(is_connected, whitelist); |
| EXPECT_FALSE(DarkResumeActionsTimeOutCallbackIsCancelled()); |
| |
| StartDHCPLeaseRenewalTimer(); |
| SetExpectationsDisconnectedBeforeSuspend(); |
| OnNoAutoConnectableServicesAfterScan(whitelist); |
| EXPECT_EQ(WakeOnWiFi::kWakeTriggerUnsupported, GetLastWakeReason()); |
| EXPECT_FALSE(DHCPLeaseRenewalTimerIsRunning()); |
| VerifyStateDisconnectedBeforeSuspend(); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithDispatcher, OnDarkResume_WakeReasonSSID_Timeout) { |
| // Test that correct actions are taken if we enter dark resume because the |
| // system woke on SSID, then timeout on suspend actions before suspending |
| // again. |
| const bool is_connected = false; |
| SetLastWakeReason(WakeOnWiFi::kWakeTriggerSSID); |
| vector<ByteString> whitelist; |
| AddSSIDToWhitelist(kSSIDBytes1, sizeof(kSSIDBytes1), &whitelist); |
| |
| InitStateForDarkResume(); |
| EXPECT_TRUE(DarkResumeActionsTimeOutCallbackIsCancelled()); |
| EXPECT_CALL(*this, RemoveSupplicantNetworksCallback()); |
| EXPECT_CALL(metrics_, NotifyDarkResumeInitiateScan()); |
| EXPECT_CALL(*this, InitiateScanCallback(GetLastSSIDMatchFreqs())); |
| EXPECT_CALL(metrics_, |
| NotifyWakeOnWiFiOnDarkResume(WakeOnWiFi::kWakeTriggerSSID)); |
| OnDarkResume(is_connected, whitelist); |
| EXPECT_FALSE(DarkResumeActionsTimeOutCallbackIsCancelled()); |
| |
| StartDHCPLeaseRenewalTimer(); |
| SetExpectationsDisconnectedBeforeSuspend(); |
| dispatcher_.DispatchPendingEvents(); |
| EXPECT_EQ(WakeOnWiFi::kWakeTriggerUnsupported, GetLastWakeReason()); |
| EXPECT_FALSE(DHCPLeaseRenewalTimerIsRunning()); |
| VerifyStateDisconnectedBeforeSuspend(); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithDispatcher, |
| OnDarkResume_WakeReasonSSID_LeaseObtained) { |
| // Test that correct actions are taken if we enter dark resume because the |
| // system woke on SSID, then connect and obtain a DHCP lease before suspending |
| // again. |
| const bool is_connected = false; |
| const bool have_dhcp_lease = true; |
| const uint32_t time_to_next_lease_renewal = 10; |
| SetLastWakeReason(WakeOnWiFi::kWakeTriggerSSID); |
| vector<ByteString> whitelist; |
| AddSSIDToWhitelist(kSSIDBytes1, sizeof(kSSIDBytes1), &whitelist); |
| |
| InitStateForDarkResume(); |
| EXPECT_TRUE(DarkResumeActionsTimeOutCallbackIsCancelled()); |
| EXPECT_CALL(*this, RemoveSupplicantNetworksCallback()); |
| EXPECT_CALL(metrics_, NotifyDarkResumeInitiateScan()); |
| EXPECT_CALL(*this, InitiateScanCallback(GetLastSSIDMatchFreqs())); |
| EXPECT_CALL(metrics_, |
| NotifyWakeOnWiFiOnDarkResume(WakeOnWiFi::kWakeTriggerSSID)); |
| OnDarkResume(is_connected, whitelist); |
| EXPECT_FALSE(DarkResumeActionsTimeOutCallbackIsCancelled()); |
| |
| StopDHCPLeaseRenewalTimer(); |
| StartWakeToScanTimer(); |
| SetExpectationsConnectedBeforeSuspend(); |
| OnConnectedAndReachable(have_dhcp_lease, time_to_next_lease_renewal); |
| EXPECT_EQ(WakeOnWiFi::kWakeTriggerUnsupported, GetLastWakeReason()); |
| EXPECT_TRUE(DHCPLeaseRenewalTimerIsRunning()); |
| EXPECT_FALSE(WakeToScanTimerIsRunning()); |
| VerifyStateConnectedBeforeSuspend(); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithDispatcher, OnDarkResume_Connected_DoNotRecordEvent) { |
| const bool is_connected = true; |
| vector<ByteString> whitelist; |
| EXPECT_TRUE(GetDarkResumeHistory()->Empty()); |
| OnDarkResume(is_connected, whitelist); |
| EXPECT_TRUE(GetDarkResumeHistory()->Empty()); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithDispatcher, OnDarkResume_NotConnected_RecordEvent) { |
| const bool is_connected = false; |
| vector<ByteString> whitelist; |
| EXPECT_TRUE(GetDarkResumeHistory()->Empty()); |
| OnDarkResume(is_connected, whitelist); |
| EXPECT_EQ(1, GetDarkResumeHistory()->Size()); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithDispatcher, |
| OnDarkResume_NotConnected_MaxDarkResumes_ShortPeriod) { |
| // These 3 dark resume timings are within a 1 minute interval, so as to |
| // trigger the short throttling threshold (3 in 1 minute). |
| const int kTimeSeconds[] = {10, 20, 30}; |
| CHECK_EQ(static_cast<const unsigned int>( |
| WakeOnWiFi::kMaxDarkResumesPerPeriodShort), |
| arraysize(kTimeSeconds)); |
| vector<ByteString> whitelist; |
| |
| // This test assumes that throttling takes place when 3 dark resumes have |
| // been triggered in the last 1 minute. |
| EXPECT_EQ(3, WakeOnWiFi::kMaxDarkResumesPerPeriodShort); |
| EXPECT_EQ(1, WakeOnWiFi::kDarkResumeFrequencySamplingPeriodShortMinutes); |
| |
| // Wake on SSID dark resumes should be recorded in the dark resume history. |
| const bool is_connected = false; |
| SetLastWakeReason(WakeOnWiFi::kWakeTriggerSSID); |
| EXPECT_TRUE(GetDarkResumeHistory()->Empty()); |
| |
| // First two dark resumes take place at 10 and 20 seconds respectively. This |
| // is still within the throttling threshold. |
| for (int i = 0; i < WakeOnWiFi::kMaxDarkResumesPerPeriodShort - 1; ++i) { |
| EXPECT_CALL(metrics_, NotifyWakeOnWiFiThrottled()).Times(0); |
| EXPECT_CALL(time_, GetNow()) |
| .WillRepeatedly(Return(GetTimestampBootTime(kTimeSeconds[i]))); |
| OnDarkResume(is_connected, whitelist); |
| } |
| SetInDarkResume(false); // this happens after BeforeSuspendActions |
| EXPECT_EQ(WakeOnWiFi::kMaxDarkResumesPerPeriodShort - 1, |
| GetDarkResumeHistory()->Size()); |
| |
| // The 3rd dark resume takes place at 30 seconds, which makes 3 dark resumes |
| // in the past minute. Disable wake on WiFi and start wake to scan timer. |
| ResetSuspendActionsDoneCallback(); |
| StartDHCPLeaseRenewalTimer(); |
| StopWakeToScanTimer(); |
| EXPECT_TRUE(SuspendActionsCallbackIsNull()); |
| EXPECT_TRUE(DHCPLeaseRenewalTimerIsRunning()); |
| EXPECT_FALSE(WakeToScanTimerIsRunning()); |
| EXPECT_FALSE(GetDarkResumeHistory()->Empty()); |
| EXPECT_CALL(metrics_, NotifyWakeOnWiFiThrottled()); |
| EXPECT_CALL(time_, GetNow()) |
| .WillRepeatedly(Return(GetTimestampBootTime( |
| kTimeSeconds[WakeOnWiFi::kMaxDarkResumesPerPeriodShort - 1]))); |
| OnDarkResume(is_connected, whitelist); |
| EXPECT_FALSE(SuspendActionsCallbackIsNull()); |
| EXPECT_FALSE(DHCPLeaseRenewalTimerIsRunning()); |
| EXPECT_TRUE(WakeToScanTimerIsRunning()); |
| EXPECT_TRUE(GetDarkResumeHistory()->Empty()); |
| EXPECT_FALSE(GetInDarkResume()); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithDispatcher, |
| OnDarkResume_NotConnected_MaxDarkResumes_LongPeriod) { |
| // These 10 dark resume timings are spaced 1 minute apart so as to trigger the |
| // long throttling threshold (10 in 10 minute) without triggering the short |
| // throttling threshold (3 in 1 minute). |
| const int kTimeSeconds[] = {10, 70, 130, 190, 250, 310, 370, 430, 490, 550}; |
| CHECK_EQ( |
| static_cast<const unsigned int>(WakeOnWiFi::kMaxDarkResumesPerPeriodLong), |
| arraysize(kTimeSeconds)); |
| vector<ByteString> whitelist; |
| |
| // This test assumes that throttling takes place when 3 dark resumes have been |
| // triggered in the last 1 minute, or when 10 dark resumes have been triggered |
| // in the last 10 minutes. |
| EXPECT_EQ(3, WakeOnWiFi::kMaxDarkResumesPerPeriodShort); |
| EXPECT_EQ(1, WakeOnWiFi::kDarkResumeFrequencySamplingPeriodShortMinutes); |
| EXPECT_EQ(10, WakeOnWiFi::kMaxDarkResumesPerPeriodLong); |
| EXPECT_EQ(10, WakeOnWiFi::kDarkResumeFrequencySamplingPeriodLongMinutes); |
| |
| // Wake on SSID dark resumes should be recorded in the dark resume history. |
| const bool is_connected = false; |
| SetLastWakeReason(WakeOnWiFi::kWakeTriggerSSID); |
| EXPECT_TRUE(GetDarkResumeHistory()->Empty()); |
| |
| // The first 9 dark resumes happen once per minute. This is still within the |
| // throttling threshold. |
| for (int i = 0; i < WakeOnWiFi::kMaxDarkResumesPerPeriodLong - 1; ++i) { |
| EXPECT_CALL(metrics_, NotifyWakeOnWiFiThrottled()).Times(0); |
| EXPECT_CALL(time_, GetNow()) |
| .WillRepeatedly(Return(GetTimestampBootTime(kTimeSeconds[i]))); |
| OnDarkResume(is_connected, whitelist); |
| } |
| SetInDarkResume(false); // this happens after BeforeSuspendActions |
| EXPECT_EQ(WakeOnWiFi::kMaxDarkResumesPerPeriodLong - 1, |
| GetDarkResumeHistory()->Size()); |
| |
| // The occurrence of the 10th dark resume makes 10 dark resumes in the past 10 |
| // minutes. Disable wake on WiFi and start wake to scan timer. |
| ResetSuspendActionsDoneCallback(); |
| StartDHCPLeaseRenewalTimer(); |
| StopWakeToScanTimer(); |
| EXPECT_TRUE(SuspendActionsCallbackIsNull()); |
| EXPECT_TRUE(DHCPLeaseRenewalTimerIsRunning()); |
| EXPECT_FALSE(WakeToScanTimerIsRunning()); |
| EXPECT_FALSE(GetDarkResumeHistory()->Empty()); |
| EXPECT_CALL(metrics_, NotifyWakeOnWiFiThrottled()); |
| EXPECT_CALL(time_, GetNow()) |
| .WillRepeatedly(Return(GetTimestampBootTime( |
| kTimeSeconds[WakeOnWiFi::kMaxDarkResumesPerPeriodLong - 1]))); |
| OnDarkResume(is_connected, whitelist); |
| EXPECT_FALSE(SuspendActionsCallbackIsNull()); |
| EXPECT_FALSE(DHCPLeaseRenewalTimerIsRunning()); |
| EXPECT_TRUE(WakeToScanTimerIsRunning()); |
| EXPECT_TRUE(GetDarkResumeHistory()->Empty()); |
| EXPECT_FALSE(GetInDarkResume()); |
| EXPECT_TRUE(GetLastSSIDMatchFreqs().empty()); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, OnConnectedAndReachable) { |
| const bool start_lease_renewal_timer = true; |
| ScopedMockLog log; |
| |
| EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); |
| SetInDarkResume(true); |
| ScopeLogger::GetInstance()->EnableScopesByName("wifi"); |
| ScopeLogger::GetInstance()->set_verbose_level(3); |
| EXPECT_CALL(log, Log(_, _, HasSubstr("BeforeSuspendActions"))); |
| OnConnectedAndReachable(start_lease_renewal_timer, |
| kTimeToNextLeaseRenewalLong); |
| |
| SetInDarkResume(false); |
| EXPECT_CALL(log, Log(_, _, HasSubstr("Not in dark resume, so do nothing"))); |
| OnConnectedAndReachable(start_lease_renewal_timer, |
| kTimeToNextLeaseRenewalLong); |
| ScopeLogger::GetInstance()->EnableScopesByName("-wifi"); |
| ScopeLogger::GetInstance()->set_verbose_level(0); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, WakeOnWiFiDisabledAfterResume) { |
| // At least one wake on WiFi trigger supported and Wake on WiFi features |
| // are enabled, so disable Wake on WiFi on resume.] |
| EnableWakeOnWiFiFeaturesPacketDarkConnect(); |
| GetWakeOnWiFiTriggers()->insert(WakeOnWiFi::kWakeTriggerPattern); |
| EXPECT_CALL(netlink_manager_, |
| SendNl80211Message(IsDisableWakeOnWiFiMsg(), _, _, _)) |
| .Times(1); |
| EXPECT_CALL(metrics_, NotifySuspendWithWakeOnWiFiEnabledDone()).Times(1); |
| OnAfterResume(); |
| |
| // No wake no WiFi triggers supported, so do nothing. |
| ClearWakeOnWiFiTriggersSupported(); |
| EXPECT_CALL(netlink_manager_, |
| SendNl80211Message(IsDisableWakeOnWiFiMsg(), _, _, _)) |
| .Times(0); |
| EXPECT_CALL(metrics_, NotifySuspendWithWakeOnWiFiEnabledDone()).Times(0); |
| OnAfterResume(); |
| |
| // Wake on WiFi features disabled, so do nothing. |
| GetWakeOnWiFiTriggersSupported()->insert(WakeOnWiFi::kWakeTriggerPattern); |
| DisableWakeOnWiFiFeatures(); |
| EXPECT_CALL(netlink_manager_, |
| SendNl80211Message(IsDisableWakeOnWiFiMsg(), _, _, _)) |
| .Times(0); |
| EXPECT_CALL(metrics_, NotifySuspendWithWakeOnWiFiEnabledDone()).Times(0); |
| OnAfterResume(); |
| |
| // Both WakeOnWiFi triggers are empty and Wake on WiFi features are disabled, |
| // so do nothing. |
| ClearWakeOnWiFiTriggersSupported(); |
| DisableWakeOnWiFiFeatures(); |
| EXPECT_CALL(netlink_manager_, |
| SendNl80211Message(IsDisableWakeOnWiFiMsg(), _, _, _)) |
| .Times(0); |
| EXPECT_CALL(metrics_, NotifySuspendWithWakeOnWiFiEnabledDone()).Times(0); |
| OnAfterResume(); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, SetWakeOnWiFiFeaturesEnabled) { |
| const string bad_feature("blahblah"); |
| Error e; |
| EnableWakeOnWiFiFeaturesPacketDarkConnect(); |
| EXPECT_STREQ(GetWakeOnWiFiFeaturesEnabled().c_str(), |
| kWakeOnWiFiFeaturesEnabledPacketDarkConnect); |
| EXPECT_FALSE(SetWakeOnWiFiFeaturesEnabled( |
| kWakeOnWiFiFeaturesEnabledPacketDarkConnect, &e)); |
| EXPECT_STREQ(GetWakeOnWiFiFeaturesEnabled().c_str(), |
| kWakeOnWiFiFeaturesEnabledPacketDarkConnect); |
| |
| EXPECT_FALSE(SetWakeOnWiFiFeaturesEnabled(bad_feature, &e)); |
| EXPECT_EQ(e.type(), Error::kInvalidArguments); |
| EXPECT_STREQ(e.message().c_str(), "Invalid Wake on WiFi feature"); |
| EXPECT_STREQ(GetWakeOnWiFiFeaturesEnabled().c_str(), |
| kWakeOnWiFiFeaturesEnabledPacketDarkConnect); |
| |
| EXPECT_TRUE( |
| SetWakeOnWiFiFeaturesEnabled(kWakeOnWiFiFeaturesEnabledPacket, &e)); |
| EXPECT_STREQ(GetWakeOnWiFiFeaturesEnabled().c_str(), |
| kWakeOnWiFiFeaturesEnabledPacket); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, |
| ReportConnectedToServiceAfterWake_WakeOnDarkConnectEnabledAndConnected) { |
| const bool is_connected = true; |
| EnableWakeOnWiFiFeaturesPacketDarkConnect(); |
| EXPECT_CALL(metrics_, |
| NotifyConnectedToServiceAfterWake( |
| Metrics::kWiFiConnectionStatusAfterWakeWoWOnConnected)); |
| ReportConnectedToServiceAfterWake(is_connected, kSuspendDurationSecs); |
| |
| EnableWakeOnWiFiFeaturesDarkConnect(); |
| EXPECT_CALL(metrics_, |
| NotifyConnectedToServiceAfterWake( |
| Metrics::kWiFiConnectionStatusAfterWakeWoWOnConnected)); |
| ReportConnectedToServiceAfterWake(is_connected, kSuspendDurationSecs); |
| } |
| |
| TEST_F( |
| WakeOnWiFiTestWithMockDispatcher, |
| ReportConnectedToServiceAfterWake_WakeOnDarkConnectEnabledAndNotConnected) { |
| const bool is_connected = false; |
| EnableWakeOnWiFiFeaturesPacketDarkConnect(); |
| EXPECT_CALL(metrics_, |
| NotifyConnectedToServiceAfterWake( |
| Metrics::kWiFiConnectionStatusAfterWakeWoWOnDisconnected)); |
| ReportConnectedToServiceAfterWake(is_connected, kSuspendDurationSecs); |
| |
| EnableWakeOnWiFiFeaturesDarkConnect(); |
| EXPECT_CALL(metrics_, |
| NotifyConnectedToServiceAfterWake( |
| Metrics::kWiFiConnectionStatusAfterWakeWoWOnDisconnected)); |
| ReportConnectedToServiceAfterWake(is_connected, kSuspendDurationSecs); |
| } |
| |
| TEST_F( |
| WakeOnWiFiTestWithMockDispatcher, |
| ReportConnectedToServiceAfterWake_WakeOnDarkConnectDisabledAndConnected) { |
| const bool is_connected = true; |
| EnableWakeOnWiFiFeaturesPacket(); |
| EXPECT_CALL(metrics_, |
| NotifyConnectedToServiceAfterWake( |
| Metrics::kWiFiConnectionStatusAfterWakeWoWOffConnected)); |
| ReportConnectedToServiceAfterWake(is_connected, kSuspendDurationSecs); |
| |
| DisableWakeOnWiFiFeatures(); |
| EXPECT_CALL(metrics_, |
| NotifyConnectedToServiceAfterWake( |
| Metrics::kWiFiConnectionStatusAfterWakeWoWOffConnected)); |
| ReportConnectedToServiceAfterWake(is_connected, kSuspendDurationSecs); |
| } |
| |
| TEST_F( |
| WakeOnWiFiTestWithMockDispatcher, |
| ReportConnectedToServiceAfterWake_WakeOnDarkConnectDisabledAndDisonnected) { |
| const bool is_connected = false; |
| EnableWakeOnWiFiFeaturesPacket(); |
| EXPECT_CALL(metrics_, |
| NotifyConnectedToServiceAfterWake( |
| Metrics::kWiFiConnectionStatusAfterWakeWoWOffDisconnected)); |
| ReportConnectedToServiceAfterWake(is_connected, kSuspendDurationSecs); |
| |
| DisableWakeOnWiFiFeatures(); |
| EXPECT_CALL(metrics_, |
| NotifyConnectedToServiceAfterWake( |
| Metrics::kWiFiConnectionStatusAfterWakeWoWOffDisconnected)); |
| ReportConnectedToServiceAfterWake(is_connected, kSuspendDurationSecs); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, |
| OnNoAutoConnectableServicesAfterScan_InDarkResume) { |
| vector<ByteString> whitelist; |
| AddSSIDToWhitelist(kSSIDBytes1, sizeof(kSSIDBytes1), &whitelist); |
| EnableWakeOnWiFiFeaturesDarkConnect(); |
| SetInDarkResume(true); |
| |
| // Perform disconnect before suspend actions if we are in dark resume. |
| GetWakeOnWiFiTriggers()->clear(); |
| StartDHCPLeaseRenewalTimer(); |
| StopWakeToScanTimer(); |
| OnNoAutoConnectableServicesAfterScan(whitelist); |
| EXPECT_FALSE(DHCPLeaseRenewalTimerIsRunning()); |
| EXPECT_FALSE(WakeToScanTimerIsRunning()); |
| EXPECT_EQ(GetWakeOnWiFiTriggers()->size(), 1); |
| EXPECT_TRUE(GetWakeOnWiFiTriggers()->find(WakeOnWiFi::kWakeTriggerSSID) != |
| GetWakeOnWiFiTriggers()->end()); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, |
| OnNoAutoConnectableServicesAfterScan_NotInDarkResume) { |
| vector<ByteString> whitelist; |
| AddSSIDToWhitelist(kSSIDBytes1, sizeof(kSSIDBytes1), &whitelist); |
| EnableWakeOnWiFiFeaturesDarkConnect(); |
| SetInDarkResume(false); |
| |
| // If we are not in dark resume, do nothing. |
| GetWakeOnWiFiTriggers()->clear(); |
| StartDHCPLeaseRenewalTimer(); |
| StopWakeToScanTimer(); |
| OnNoAutoConnectableServicesAfterScan(whitelist); |
| EXPECT_TRUE(DHCPLeaseRenewalTimerIsRunning()); |
| EXPECT_EQ(GetWakeOnWiFiTriggers()->size(), 0); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, |
| OnNoAutoConnectableServicesAfterScan_Retry) { |
| vector<ByteString> whitelist; |
| AddSSIDToWhitelist(kSSIDBytes1, sizeof(kSSIDBytes1), &whitelist); |
| EnableWakeOnWiFiFeaturesDarkConnect(); |
| SetInDarkResume(true); |
| SetDarkResumeScanRetriesLeft(1); |
| |
| // Perform a retry. |
| EXPECT_EQ(1, GetDarkResumeScanRetriesLeft()); |
| EXPECT_CALL(metrics_, NotifyDarkResumeScanRetry()); |
| EXPECT_CALL(*this, InitiateScanCallback(GetLastSSIDMatchFreqs())); |
| OnNoAutoConnectableServicesAfterScan(whitelist); |
| EXPECT_EQ(0, GetDarkResumeScanRetriesLeft()); |
| |
| // Still no auto-connectable services after retry. No more retries, so perform |
| // disconnect before suspend actions. |
| GetWakeOnWiFiTriggers()->clear(); |
| StartDHCPLeaseRenewalTimer(); |
| StopWakeToScanTimer(); |
| EXPECT_CALL(*this, InitiateScanCallback(GetLastSSIDMatchFreqs())).Times(0); |
| OnNoAutoConnectableServicesAfterScan(whitelist); |
| EXPECT_FALSE(DHCPLeaseRenewalTimerIsRunning()); |
| EXPECT_FALSE(WakeToScanTimerIsRunning()); |
| EXPECT_EQ(GetWakeOnWiFiTriggers()->size(), 1); |
| EXPECT_TRUE(GetWakeOnWiFiTriggers()->find(WakeOnWiFi::kWakeTriggerSSID) != |
| GetWakeOnWiFiTriggers()->end()); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, OnWakeupReasonReceived_Unsupported) { |
| ScopedMockLog log; |
| ScopeLogger::GetInstance()->EnableScopesByName("wifi"); |
| ScopeLogger::GetInstance()->set_verbose_level(3); |
| SetWiphyIndex(kWakeReasonNlMsg_WiphyIndex); |
| |
| SetWakeOnPacketConnMessage msg; |
| NetlinkPacket packet(kWakeReasonUnsupportedNlMsg, |
| sizeof(kWakeReasonUnsupportedNlMsg)); |
| msg.InitFromPacket(&packet, GetWakeupReportMsgContext()); |
| EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); |
| EXPECT_CALL(log, |
| Log(_, _, HasSubstr("Wakeup reason: Not wake on WiFi related"))); |
| EXPECT_CALL(metrics_, NotifyWakeupReasonReceived()); |
| EXPECT_CALL(*this, RecordDarkResumeWakeReasonCallback(_)).Times(0); |
| OnWakeupReasonReceived(msg); |
| EXPECT_EQ(WakeOnWiFi::kWakeTriggerUnsupported, GetLastWakeReason()); |
| |
| ScopeLogger::GetInstance()->EnableScopesByName("-wifi"); |
| ScopeLogger::GetInstance()->set_verbose_level(0); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, OnWakeupReasonReceived_Disconnect) { |
| ScopedMockLog log; |
| ScopeLogger::GetInstance()->EnableScopesByName("wifi"); |
| ScopeLogger::GetInstance()->set_verbose_level(3); |
| SetWiphyIndex(kWakeReasonNlMsg_WiphyIndex); |
| |
| SetWakeOnPacketConnMessage msg; |
| NetlinkPacket packet(kWakeReasonDisconnectNlMsg, |
| sizeof(kWakeReasonDisconnectNlMsg)); |
| msg.InitFromPacket(&packet, GetWakeupReportMsgContext()); |
| EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); |
| EXPECT_CALL(log, Log(_, _, HasSubstr("Wakeup reason: Disconnect"))); |
| EXPECT_CALL(metrics_, NotifyWakeupReasonReceived()); |
| EXPECT_CALL(*this, RecordDarkResumeWakeReasonCallback( |
| WakeOnWiFi::kWakeReasonStringDisconnect)); |
| OnWakeupReasonReceived(msg); |
| EXPECT_EQ(WakeOnWiFi::kWakeTriggerDisconnect, GetLastWakeReason()); |
| |
| ScopeLogger::GetInstance()->EnableScopesByName("-wifi"); |
| ScopeLogger::GetInstance()->set_verbose_level(0); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, OnWakeupReasonReceived_SSID) { |
| ScopedMockLog log; |
| ScopeLogger::GetInstance()->EnableScopesByName("wifi"); |
| ScopeLogger::GetInstance()->set_verbose_level(3); |
| SetWiphyIndex(kWakeReasonNlMsg_WiphyIndex); |
| |
| SetWakeOnPacketConnMessage msg; |
| NetlinkPacket packet(kWakeReasonSSIDNlMsg, sizeof(kWakeReasonSSIDNlMsg)); |
| msg.InitFromPacket(&packet, GetWakeupReportMsgContext()); |
| EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); |
| EXPECT_CALL(log, Log(_, _, HasSubstr("Wakeup reason: SSID"))); |
| EXPECT_CALL(metrics_, NotifyWakeupReasonReceived()); |
| EXPECT_CALL(*this, RecordDarkResumeWakeReasonCallback( |
| WakeOnWiFi::kWakeReasonStringSSID)); |
| OnWakeupReasonReceived(msg); |
| EXPECT_EQ(WakeOnWiFi::kWakeTriggerSSID, GetLastWakeReason()); |
| EXPECT_EQ(arraysize(kSSID1FreqMatches), GetLastSSIDMatchFreqs().size()); |
| for (uint32_t freq : kSSID1FreqMatches) { |
| EXPECT_TRUE(GetLastSSIDMatchFreqs().find(freq) != |
| GetLastSSIDMatchFreqs().end()); |
| } |
| |
| ScopeLogger::GetInstance()->EnableScopesByName("-wifi"); |
| ScopeLogger::GetInstance()->set_verbose_level(0); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, OnWakeupReasonReceived_Pattern) { |
| ScopedMockLog log; |
| ScopeLogger::GetInstance()->EnableScopesByName("wifi"); |
| ScopeLogger::GetInstance()->set_verbose_level(3); |
| SetWiphyIndex(kWakeReasonNlMsg_WiphyIndex); |
| |
| SetWakeOnPacketConnMessage msg; |
| NetlinkPacket packet(kWakeReasonPatternNlMsg, |
| sizeof(kWakeReasonPatternNlMsg)); |
| msg.InitFromPacket(&packet, GetWakeupReportMsgContext()); |
| EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); |
| EXPECT_CALL( |
| log, |
| Log(_, _, |
| HasSubstr(base::StringPrintf("Wakeup reason: Pattern %d", |
| kWakeReasonPatternNlMsg_PattIndex)))); |
| EXPECT_CALL(metrics_, NotifyWakeupReasonReceived()); |
| EXPECT_CALL(*this, RecordDarkResumeWakeReasonCallback( |
| WakeOnWiFi::kWakeReasonStringPattern)); |
| OnWakeupReasonReceived(msg); |
| EXPECT_EQ(WakeOnWiFi::kWakeTriggerPattern, GetLastWakeReason()); |
| |
| ScopeLogger::GetInstance()->EnableScopesByName("-wifi"); |
| ScopeLogger::GetInstance()->set_verbose_level(0); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, OnWakeupReasonReceived_Error) { |
| ScopedMockLog log; |
| ScopeLogger::GetInstance()->EnableScopesByName("wifi"); |
| ScopeLogger::GetInstance()->set_verbose_level(7); |
| SetWiphyIndex(kWakeReasonNlMsg_WiphyIndex); |
| |
| // kWrongMessageTypeNlMsg has an nlmsg_type of 0x16, which is different from |
| // the 0x13 (i.e. kNl80211FamilyId) that we expect in these unittests. |
| GetWakeOnPacketConnMessage msg0; |
| NetlinkPacket packet0(kWrongMessageTypeNlMsg, sizeof(kWrongMessageTypeNlMsg)); |
| msg0.InitFromPacket(&packet0, GetWakeupReportMsgContext()); |
| EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); |
| EXPECT_CALL(log, Log(_, _, HasSubstr("Not a NL80211 Message"))); |
| EXPECT_CALL(metrics_, NotifyWakeupReasonReceived()).Times(0); |
| EXPECT_CALL(*this, RecordDarkResumeWakeReasonCallback(_)).Times(0); |
| OnWakeupReasonReceived(msg0); |
| EXPECT_EQ(WakeOnWiFi::kWakeTriggerUnsupported, GetLastWakeReason()); |
| |
| // This message has command NL80211_CMD_GET_WOWLAN, not a |
| // NL80211_CMD_SET_WOWLAN. |
| GetWakeOnPacketConnMessage msg1; |
| NetlinkPacket packet1(kResponseNoIPAddresses, sizeof(kResponseNoIPAddresses)); |
| msg1.InitFromPacket(&packet1, GetWakeupReportMsgContext()); |
| EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); |
| EXPECT_CALL(log, |
| Log(_, _, HasSubstr("Not a NL80211_CMD_SET_WOWLAN message"))); |
| EXPECT_CALL(metrics_, NotifyWakeupReasonReceived()).Times(0); |
| EXPECT_CALL(*this, RecordDarkResumeWakeReasonCallback(_)).Times(0); |
| OnWakeupReasonReceived(msg1); |
| EXPECT_EQ(WakeOnWiFi::kWakeTriggerUnsupported, GetLastWakeReason()); |
| |
| // Valid message, but wrong wiphy index. |
| SetWiphyIndex(kWakeReasonNlMsg_WiphyIndex + 1); |
| SetWakeOnPacketConnMessage msg2; |
| NetlinkPacket packet(kWakeReasonDisconnectNlMsg, |
| sizeof(kWakeReasonDisconnectNlMsg)); |
| msg2.InitFromPacket(&packet, GetWakeupReportMsgContext()); |
| EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); |
| EXPECT_CALL( |
| log, Log(_, _, HasSubstr("Wakeup reason not meant for this interface"))); |
| EXPECT_CALL(metrics_, NotifyWakeupReasonReceived()).Times(0); |
| EXPECT_CALL(*this, RecordDarkResumeWakeReasonCallback(_)).Times(0); |
| OnWakeupReasonReceived(msg2); |
| EXPECT_EQ(WakeOnWiFi::kWakeTriggerUnsupported, GetLastWakeReason()); |
| |
| ScopeLogger::GetInstance()->EnableScopesByName("-wifi"); |
| ScopeLogger::GetInstance()->set_verbose_level(0); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, |
| WakeOnWiFiEnabled_ReportConnectedToServiceAfterWakeAndConnected) { |
| const bool is_connected = true; |
| |
| EnableWakeOnWiFiFeaturesPacketDarkConnect(); |
| |
| /* Setting connected_before_suspend_ to true: |
| * ensures that SuspendDuration is logged by metrics */ |
| SetConnectedBeforeSuspend(true); |
| |
| EXPECT_CALL(metrics_, |
| NotifyConnectedToServiceAfterWake( |
| Metrics::kWiFiConnectionStatusAfterWakeWoWOnConnected)); |
| EXPECT_CALL(metrics_, |
| NotifySuspendDurationAfterWake( |
| Metrics::kWiFiConnectionStatusAfterWakeWoWOnConnected, |
| kSuspendDurationSecs)); |
| ReportConnectedToServiceAfterWake(is_connected, kSuspendDurationSecs); |
| |
| /* Setting connected_before_suspend_ to false: |
| * SuspendDuration should not be logged */ |
| SetConnectedBeforeSuspend(false); |
| |
| EXPECT_CALL(metrics_, |
| NotifyConnectedToServiceAfterWake( |
| Metrics::kWiFiConnectionStatusAfterWakeWoWOnConnected)); |
| EXPECT_CALL(metrics_, NotifySuspendDurationAfterWake(_, _)).Times(0); |
| ReportConnectedToServiceAfterWake(is_connected, kSuspendDurationSecs); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, |
| WakeOnWiFiEnabled_ReportConnectedToServiceAfterWakeAndNotConnected) { |
| const bool is_connected = false; |
| |
| EnableWakeOnWiFiFeaturesPacketDarkConnect(); |
| |
| /* Setting connected_before_suspend_ to true: |
| * ensures that SuspendDuration is logged by metrics */ |
| SetConnectedBeforeSuspend(true); |
| |
| EXPECT_CALL(metrics_, |
| NotifyConnectedToServiceAfterWake( |
| Metrics::kWiFiConnectionStatusAfterWakeWoWOnDisconnected)); |
| EXPECT_CALL(metrics_, |
| NotifySuspendDurationAfterWake( |
| Metrics::kWiFiConnectionStatusAfterWakeWoWOnDisconnected, |
| kSuspendDurationSecs)); |
| ReportConnectedToServiceAfterWake(is_connected, kSuspendDurationSecs); |
| |
| /* Setting connected_before_suspend_ to false: |
| * SuspendDuration should not be logged */ |
| SetConnectedBeforeSuspend(false); |
| |
| EXPECT_CALL(metrics_, |
| NotifyConnectedToServiceAfterWake( |
| Metrics::kWiFiConnectionStatusAfterWakeWoWOnDisconnected)); |
| EXPECT_CALL(metrics_, NotifySuspendDurationAfterWake(_, _)).Times(0); |
| ReportConnectedToServiceAfterWake(is_connected, kSuspendDurationSecs); |
| } |
| |
| #else // DISABLE_WAKE_ON_WIFI |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, |
| WakeOnWiFiDisabled_AddWakeOnPacketConnection_ReturnsError) { |
| DisableWakeOnWiFiFeatures(); |
| Error e; |
| AddWakeOnPacketConnection("1.1.1.1", &e); |
| EXPECT_EQ(e.type(), Error::kNotSupported); |
| EXPECT_STREQ(e.message().c_str(), WakeOnWiFi::kWakeOnWiFiNotSupported); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, |
| WakeOnWiFiDisabled_RemoveWakeOnPacketConnection_ReturnsError) { |
| DisableWakeOnWiFiFeatures(); |
| Error e; |
| RemoveWakeOnPacketConnection("1.1.1.1", &e); |
| EXPECT_EQ(e.type(), Error::kNotSupported); |
| EXPECT_STREQ(e.message().c_str(), WakeOnWiFi::kWakeOnWiFiNotSupported); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, |
| WakeOnWiFiDisabled_RemoveAllWakeOnPacketConnections_ReturnsError) { |
| DisableWakeOnWiFiFeatures(); |
| Error e; |
| RemoveAllWakeOnPacketConnections(&e); |
| EXPECT_EQ(e.type(), Error::kNotSupported); |
| EXPECT_STREQ(e.message().c_str(), WakeOnWiFi::kWakeOnWiFiNotSupported); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, |
| WakeOnWiFiDisabled_OnBeforeSuspend_ReportsDoneImmediately) { |
| const bool is_connected = true; |
| const bool have_dhcp_lease = true; |
| vector<ByteString> whitelist; |
| AddSSIDToWhitelist(kSSIDBytes1, sizeof(kSSIDBytes1), &whitelist); |
| EXPECT_CALL(*this, DoneCallback(ErrorTypeIs(Error::kSuccess))).Times(1); |
| EXPECT_CALL(*this, RenewDHCPLeaseCallback()).Times(0); |
| OnBeforeSuspend(is_connected, whitelist, have_dhcp_lease, |
| kTimeToNextLeaseRenewalShort); |
| |
| EXPECT_CALL(*this, DoneCallback(ErrorTypeIs(Error::kSuccess))).Times(1); |
| EXPECT_CALL(*this, RenewDHCPLeaseCallback()).Times(0); |
| OnBeforeSuspend(is_connected, whitelist, have_dhcp_lease, |
| kTimeToNextLeaseRenewalLong); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, |
| WakeOnWiFiDisabled_OnDarkResume_ReportsDoneImmediately) { |
| const bool is_connected = true; |
| vector<ByteString> whitelist; |
| AddSSIDToWhitelist(kSSIDBytes1, sizeof(kSSIDBytes1), &whitelist); |
| EXPECT_CALL(*this, DoneCallback(ErrorTypeIs(Error::kSuccess))).Times(1); |
| EXPECT_CALL(mock_dispatcher_, PostDelayedTask(_, _, _)).Times(0); |
| EXPECT_CALL(metrics_, NotifyWakeOnWiFiOnDarkResume(_)).Times(0); |
| OnDarkResume(is_connected, whitelist); |
| |
| EXPECT_CALL(*this, DoneCallback(ErrorTypeIs(Error::kSuccess))).Times(1); |
| EXPECT_CALL(mock_dispatcher_, PostDelayedTask(_, _, _)).Times(0); |
| EXPECT_CALL(metrics_, NotifyWakeOnWiFiOnDarkResume(_)).Times(0); |
| OnDarkResume(is_connected, whitelist); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, |
| WakeOnWiFiDisabled_OnAfterResume_DoesNothing) { |
| DisableWakeOnWiFiFeatures(); |
| EXPECT_CALL(netlink_manager_, SendNl80211Message(_, _, _, _)).Times(0); |
| EXPECT_CALL(metrics_, NotifySuspendWithWakeOnWiFiEnabledDone()).Times(0); |
| OnAfterResume(); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, |
| WakeOnWiFiDisabled_SetWakeOnWiFiFeaturesEnabled) { |
| Error e; |
| SetWakeOnWiFiFeaturesNotSupported(); |
| EXPECT_STREQ(GetWakeOnWiFiFeaturesEnabled().c_str(), |
| kWakeOnWiFiFeaturesEnabledNotSupported); |
| EXPECT_FALSE( |
| SetWakeOnWiFiFeaturesEnabled(kWakeOnWiFiFeaturesEnabledNotSupported, &e)); |
| EXPECT_STREQ(GetWakeOnWiFiFeaturesEnabled().c_str(), |
| kWakeOnWiFiFeaturesEnabledNotSupported); |
| EXPECT_EQ(e.type(), Error::kNotSupported); |
| EXPECT_STREQ(e.message().c_str(), WakeOnWiFi::kWakeOnWiFiNotSupported); |
| |
| EXPECT_FALSE( |
| SetWakeOnWiFiFeaturesEnabled(kWakeOnWiFiFeaturesEnabledPacket, &e)); |
| EXPECT_STREQ(GetWakeOnWiFiFeaturesEnabled().c_str(), |
| kWakeOnWiFiFeaturesEnabledNotSupported); |
| EXPECT_EQ(e.type(), Error::kNotSupported); |
| EXPECT_STREQ(e.message().c_str(), WakeOnWiFi::kWakeOnWiFiNotSupported); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, |
| WakeOnWiFiDisabled_OnConnectedAndReachable) { |
| ScopedMockLog log; |
| const bool start_lease_renewal_timer = true; |
| ScopeLogger::GetInstance()->EnableScopesByName("wifi"); |
| ScopeLogger::GetInstance()->set_verbose_level(3); |
| |
| EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); |
| SetInDarkResume(true); |
| EXPECT_CALL( |
| log, Log(_, _, HasSubstr("Wake on WiFi not supported, so do nothing"))); |
| OnConnectedAndReachable(start_lease_renewal_timer, |
| kTimeToNextLeaseRenewalLong); |
| |
| SetInDarkResume(false); |
| EXPECT_CALL(log, Log(_, _, HasSubstr("Not in dark resume, so do nothing"))); |
| OnConnectedAndReachable(start_lease_renewal_timer, |
| kTimeToNextLeaseRenewalLong); |
| ScopeLogger::GetInstance()->EnableScopesByName("-wifi"); |
| ScopeLogger::GetInstance()->set_verbose_level(0); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, |
| WakeOnWiFiDisabled_ReportConnectedToServiceAfterWakeAndConnected) { |
| const bool is_connected = true; |
| |
| /* Setting connected_before_suspend_ to true: |
| * ensures that SuspendDuration is logged by metrics */ |
| SetConnectedBeforeSuspend(true); |
| |
| EXPECT_CALL(metrics_, |
| NotifyConnectedToServiceAfterWake( |
| Metrics::kWiFiConnectionStatusAfterWakeWoWOffConnected)); |
| EXPECT_CALL(metrics_, |
| NotifySuspendDurationAfterWake( |
| Metrics::kWiFiConnectionStatusAfterWakeWoWOffConnected, |
| kSuspendDurationSecs)); |
| ReportConnectedToServiceAfterWake(is_connected, kSuspendDurationSecs); |
| |
| /* Setting connected_before_suspend_ to false: |
| * SuspendDuration should not be logged */ |
| SetConnectedBeforeSuspend(false); |
| |
| EXPECT_CALL(metrics_, |
| NotifyConnectedToServiceAfterWake( |
| Metrics::kWiFiConnectionStatusAfterWakeWoWOffConnected)); |
| EXPECT_CALL(metrics_, NotifySuspendDurationAfterWake(_, _)).Times(0); |
| ReportConnectedToServiceAfterWake(is_connected, kSuspendDurationSecs); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, |
| WakeOnWiFiDisabled_ReportConnectedToServiceAfterWakeAndNotConnected) { |
| const bool is_connected = false; |
| |
| /* Setting connected_before_suspend_ to true: |
| * ensures that SuspendDuration is logged by metrics */ |
| SetConnectedBeforeSuspend(true); |
| |
| EXPECT_CALL(metrics_, |
| NotifyConnectedToServiceAfterWake( |
| Metrics::kWiFiConnectionStatusAfterWakeWoWOffDisconnected)); |
| EXPECT_CALL(metrics_, |
| NotifySuspendDurationAfterWake( |
| Metrics::kWiFiConnectionStatusAfterWakeWoWOffDisconnected, |
| kSuspendDurationSecs)); |
| ReportConnectedToServiceAfterWake(is_connected, kSuspendDurationSecs); |
| |
| /* Setting connected_before_suspend_ to false: |
| * SuspendDuration should not be logged */ |
| SetConnectedBeforeSuspend(false); |
| |
| EXPECT_CALL(metrics_, |
| NotifyConnectedToServiceAfterWake( |
| Metrics::kWiFiConnectionStatusAfterWakeWoWOffDisconnected)); |
| EXPECT_CALL(metrics_, NotifySuspendDurationAfterWake(_, _)).Times(0); |
| ReportConnectedToServiceAfterWake(is_connected, kSuspendDurationSecs); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithDispatcher, |
| WakeOnWiFiDisabled_OnNoAutoConnectableServicesAfterScan) { |
| vector<ByteString> whitelist; |
| AddSSIDToWhitelist(kSSIDBytes1, sizeof(kSSIDBytes1), &whitelist); |
| |
| // Do nothing (i.e. do not invoke WakeOnWiFi::BeforeSuspendActions) if wake |
| // on WiFi is not supported, whether or not we are in dark resume. |
| SetInDarkResume(true); |
| GetWakeOnWiFiTriggers()->clear(); |
| StartDHCPLeaseRenewalTimer(); |
| StopWakeToScanTimer(); |
| OnNoAutoConnectableServicesAfterScan(whitelist); |
| EXPECT_FALSE(WakeToScanTimerIsRunning()); |
| EXPECT_TRUE(DHCPLeaseRenewalTimerIsRunning()); |
| EXPECT_EQ(GetWakeOnWiFiTriggers()->size(), 0); |
| |
| SetInDarkResume(false); |
| GetWakeOnWiFiTriggers()->clear(); |
| StartDHCPLeaseRenewalTimer(); |
| StopWakeToScanTimer(); |
| OnNoAutoConnectableServicesAfterScan(whitelist); |
| EXPECT_FALSE(WakeToScanTimerIsRunning()); |
| EXPECT_TRUE(DHCPLeaseRenewalTimerIsRunning()); |
| EXPECT_EQ(GetWakeOnWiFiTriggers()->size(), 0); |
| |
| dispatcher_.DispatchPendingEvents(); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, |
| WakeOnWiFiDisabled_OnWakeupReasonReceived_DoesNothing) { |
| ScopedMockLog log; |
| ScopeLogger::GetInstance()->EnableScopesByName("wifi"); |
| ScopeLogger::GetInstance()->set_verbose_level(7); |
| |
| SetWakeOnPacketConnMessage msg; |
| NetlinkPacket packet(kWakeReasonSSIDNlMsg, sizeof(kWakeReasonSSIDNlMsg)); |
| msg.InitFromPacket(&packet, GetWakeupReportMsgContext()); |
| EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); |
| EXPECT_CALL( |
| log, Log(_, _, HasSubstr("Wake on WiFi not supported, so do nothing"))); |
| EXPECT_CALL(metrics_, NotifyWakeupReasonReceived()).Times(0); |
| EXPECT_CALL(*this, RecordDarkResumeWakeReasonCallback(_)).Times(0); |
| OnWakeupReasonReceived(msg); |
| |
| ScopeLogger::GetInstance()->EnableScopesByName("-wifi"); |
| ScopeLogger::GetInstance()->set_verbose_level(0); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, |
| WakeOnWiFiDisabled_ConfigureSetWakeOnWiFiSettingsMessage_ReturnsFalse) { |
| IPAddressStore no_addresses; |
| IPAddressStore one_address; |
| const char kIPv4AddrString[] = "1.1.1.1"; |
| one_address.AddUnique( |
| IPAddress(string(kIPv4AddrString, sizeof(kIPv4AddrString)))); |
| set<WakeOnWiFi::WakeOnWiFiTrigger> no_trigs; |
| set<WakeOnWiFi::WakeOnWiFiTrigger> one_trig; |
| one_trig.insert(WakeOnWiFi::kWakeTriggerPattern); |
| const int index = 1; // wiphy device number |
| vector<ByteString> whitelist; |
| const uint32_t interval = kNetDetectScanIntervalSeconds; |
| SetWakeOnPacketConnMessage msg; |
| Error e; |
| EXPECT_FALSE(ConfigureSetWakeOnWiFiSettingsMessage( |
| &msg, no_trigs, no_addresses, index, {}, kHardwareAddress, interval, |
| whitelist, &e)); |
| EXPECT_FALSE(ConfigureSetWakeOnWiFiSettingsMessage( |
| &msg, one_trig, one_address, index, {}, kHardwareAddress, interval, |
| whitelist, &e)); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, |
| WakeOnWiFiDisabled_WakeOnWiFiSettingsMatch_ReturnsFalse) { |
| // Test that WakeOnWiFi::WakeOnWiFiSettingsMatch unconditionally returns false |
| // when wake-on-WiFi is disabled by testing it against several cases where we |
| // expect it to return true. |
| IPAddressStore all_addresses; |
| set<WakeOnWiFi::WakeOnWiFiTrigger> trigs; |
| vector<ByteString> whitelist; |
| const uint32_t interval = kNetDetectScanIntervalSeconds; |
| |
| GetWakeOnPacketConnMessage msg0; |
| NetlinkPacket packet0(kResponseNoIPAddresses, sizeof(kResponseNoIPAddresses)); |
| msg0.InitFromPacket(&packet0, NetlinkMessage::MessageContext()); |
| EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg0, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| |
| trigs.insert(WakeOnWiFi::kWakeTriggerPattern); |
| all_addresses.AddUnique( |
| IPAddress(string(kIPV4Address0, sizeof(kIPV4Address0)))); |
| GetWakeOnPacketConnMessage msg1; |
| NetlinkPacket packet1(kResponseIPV40, sizeof(kResponseIPV40)); |
| msg1.InitFromPacket(&packet1, NetlinkMessage::MessageContext()); |
| EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg1, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| |
| trigs.insert(WakeOnWiFi::kWakeTriggerDisconnect); |
| GetWakeOnPacketConnMessage msg2; |
| NetlinkPacket packet2(kResponseIPV40WakeOnDisconnect, |
| sizeof(kResponseIPV40WakeOnDisconnect)); |
| msg2.InitFromPacket(&packet2, NetlinkMessage::MessageContext()); |
| EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg2, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| |
| trigs.erase(WakeOnWiFi::kWakeTriggerDisconnect); |
| all_addresses.AddUnique( |
| IPAddress(string(kIPV4Address1, sizeof(kIPV4Address1)))); |
| GetWakeOnPacketConnMessage msg3; |
| NetlinkPacket packet3(kResponseIPV401, sizeof(kResponseIPV401)); |
| msg3.InitFromPacket(&packet3, NetlinkMessage::MessageContext()); |
| EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg3, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| |
| all_addresses.AddUnique( |
| IPAddress(string(kIPV6Address0, sizeof(kIPV6Address0)))); |
| GetWakeOnPacketConnMessage msg4; |
| NetlinkPacket packet4(kResponseIPV401IPV60, sizeof(kResponseIPV401IPV60)); |
| msg4.InitFromPacket(&packet4, NetlinkMessage::MessageContext()); |
| EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg4, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| |
| all_addresses.AddUnique( |
| IPAddress(string(kIPV6Address1, sizeof(kIPV6Address1)))); |
| GetWakeOnPacketConnMessage msg5; |
| NetlinkPacket packet5(kResponseIPV401IPV601, sizeof(kResponseIPV401IPV601)); |
| msg5.InitFromPacket(&packet5, NetlinkMessage::MessageContext()); |
| EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg5, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| |
| all_addresses.Clear(); |
| trigs.clear(); |
| trigs.insert(WakeOnWiFi::kWakeTriggerSSID); |
| AddSSIDToWhitelist(kSSIDBytes1, sizeof(kSSIDBytes1), &whitelist); |
| AddSSIDToWhitelist(kSSIDBytes2, sizeof(kSSIDBytes2), &whitelist); |
| GetWakeOnPacketConnMessage msg6; |
| NetlinkPacket packet6(kResponseWakeOnSSID, sizeof(kResponseWakeOnSSID)); |
| msg6.InitFromPacket(&packet6, NetlinkMessage::MessageContext()); |
| EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg6, trigs, all_addresses, interval, {}, |
| kHardwareAddress, whitelist)); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, |
| WakeOnWiFiDisabled_ParseWakeOnWiFiCapabilities_DoesNothing) { |
| // |kNewWiphyNlMsg| should indicate that the NIC supports wake on pattern |
| // (on up to |kNewWiphyNlMsg_MaxPatterns| registered patterns), |
| // supports wake on SSID (on up to |kNewWiphyNlMsg_MaxSSIDs| SSIDs), and |
| // supports wake on disconnect. Test that |
| // WakeOnWiFi::ParseWakeOnWiFiCapabilities does nothing and does not parse |
| // these capabilities when wake-on-WiFi is disabled. |
| ClearWakeOnWiFiTriggersSupported(); |
| SetWakeOnWiFiMaxSSIDs(0); |
| NewWiphyMessage msg; |
| NetlinkPacket packet(kNewWiphyNlMsg, sizeof(kNewWiphyNlMsg)); |
| msg.InitFromPacket(&packet, NetlinkMessage::MessageContext()); |
| ParseWakeOnWiFiCapabilities(msg); |
| EXPECT_TRUE(GetWakeOnWiFiTriggersSupported()->empty()); |
| EXPECT_EQ(0, GetWakeOnWiFiMaxPatterns()); |
| EXPECT_EQ(0, GetWakeOnWiFiMaxSSIDs()); |
| } |
| |
| TEST_F(WakeOnWiFiTestWithMockDispatcher, WakeOnWiFi_RemoveNetlinkHandler) { |
| // WakeOnWifi is deleted when we go out of scope. |
| EXPECT_CALL(netlink_manager_, RemoveBroadcastHandler(_)).Times(1); |
| } |
| |
| #endif // DISABLE_WAKE_ON_WIFI |
| |
| } // namespace shill |