// 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/wifi.h"

#include <inttypes.h>
#include <linux/if.h>  // Needs definitions from netinet/ether.h
#include <linux/nl80211.h>
#include <netinet/ether.h>
#include <stdio.h>
#include <string.h>

#include <cstdint>
#include <cstdlib>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <utility>
#include <vector>

#include <base/bind.h>
#include <base/check.h>
#include <base/files/file_util.h>
#include <base/notreached.h>
#include <base/numerics/safe_conversions.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <chromeos/dbus/service_constants.h>

#include "shill/control_interface.h"
#include "shill/device.h"
#include "shill/eap_credentials.h"
#include "shill/error.h"
#include "shill/file_reader.h"
#include "shill/link_monitor.h"
#include "shill/logging.h"
#include "shill/manager.h"
#include "shill/metrics.h"
#include "shill/net/ieee80211.h"
#include "shill/net/ip_address.h"
#include "shill/net/netlink_manager.h"
#include "shill/net/netlink_message.h"
#include "shill/net/nl80211_message.h"
#include "shill/net/rtnl_handler.h"
#include "shill/net/shill_time.h"
#include "shill/property_accessor.h"
#include "shill/scope_logger.h"
#include "shill/supplicant/supplicant_eap_state_handler.h"
#include "shill/supplicant/supplicant_interface_proxy_interface.h"
#include "shill/supplicant/supplicant_manager.h"
#include "shill/supplicant/supplicant_network_proxy_interface.h"
#include "shill/supplicant/supplicant_process_proxy_interface.h"
#include "shill/supplicant/wpa_supplicant.h"
#include "shill/technology.h"
#include "shill/wifi/wake_on_wifi.h"
#include "shill/wifi/wifi_endpoint.h"
#include "shill/wifi/wifi_provider.h"
#include "shill/wifi/wifi_service.h"

using base::Bind;
using base::StringPrintf;
using std::map;
using std::string;
using std::vector;

namespace shill {

namespace Logging {
static auto kModuleLogScope = ScopeLogger::kWiFi;
static string ObjectID(const WiFi* w) {
  return w->GetRpcIdentifier().value();
}
}  // namespace Logging

// statics
const char* const WiFi::kDefaultBgscanMethod =
    WPASupplicant::kNetworkBgscanMethodSimple;
const uint16_t WiFi::kDefaultScanIntervalSeconds = 60;

// Scan interval while connected.
const uint16_t WiFi::kBackgroundScanIntervalSeconds = 360;
// Default background scan interval when there is only one endpoint on the
// network. We'd like to strike a balance between 1) not triggering too
// frequently with poor signal, 2) hardly triggering at all with good signal,
// and 3) being able to discover additional APs that weren't initially visible.
const int WiFi::kSingleEndpointBgscanIntervalSeconds = 86400;
// Age (in seconds) beyond which a BSS cache entry will not be preserved,
// across a suspend/resume.
const time_t WiFi::kMaxBSSResumeAgeSeconds = 10;
const char WiFi::kInterfaceStateUnknown[] = "shill-unknown";
const int WiFi::kNumFastScanAttempts = 3;
const int WiFi::kFastScanIntervalSeconds = 10;
const int WiFi::kReconnectTimeoutSeconds = 10;
const int WiFi::kRequestStationInfoPeriodSeconds = 20;
// 1 second is less than the time it takes to scan and establish a new
// connection after waking, but should be enough time for supplicant to update
// its state.
const int WiFi::kPostWakeConnectivityReportDelayMilliseconds = 1000;
const uint32_t WiFi::kDefaultWiphyIndex = UINT32_MAX;
const int WiFi::kPostScanFailedDelayMilliseconds = 10000;

// The default random MAC mask is FF:FF:FF:00:00:00. Bits which are a 1 in
// the mask stay the same during randomization, and bits which are 0 are
// randomized. This mask means the OUI will remain unchanged but the last
// three octets will be different.
const std::vector<unsigned char> WiFi::kRandomMacMask{255, 255, 255, 0, 0, 0};

const char WiFi::kWakeOnWiFiNotSupported[] = "Wake on WiFi not supported";

namespace {
const uint16_t kDefaultBgscanShortIntervalSeconds = 64;
const uint16_t kSingleEndpointBgscanShortIntervalSeconds = 360;
const int32_t kDefaultBgscanSignalThresholdDbm = -72;
// Delay between scans when supplicant finds "No suitable network".
const time_t kRescanIntervalSeconds = 1;
const int kPendingTimeoutSeconds = 15;
const int kMaxRetryCreateInterfaceAttempts = 6;
const int kRetryCreateInterfaceIntervalSeconds = 10;
const int16_t kDefaultDisconnectDbm = 0;
const int16_t kDefaultDisconnectThresholdDbm = -75;

bool IsPrintableAsciiChar(char c) {
  return (c >= ' ' && c <= '~');
}
}  // namespace

WiFi::WiFi(Manager* manager,
           const string& link,
           const string& address,
           int interface_index,
           std::unique_ptr<WakeOnWiFiInterface> wake_on_wifi)
    : Device(manager, link, address, interface_index, Technology::kWifi),
      provider_(manager->wifi_provider()),
      time_(Time::GetInstance()),
      supplicant_connect_attempts_(0),
      supplicant_present_(false),
      supplicant_state_(kInterfaceStateUnknown),
      supplicant_bss_(RpcIdentifier("(unknown)")),
      supplicant_assoc_status_(IEEE_80211::kStatusCodeSuccessful),
      supplicant_auth_status_(IEEE_80211::kStatusCodeSuccessful),
      supplicant_disconnect_reason_(IEEE_80211::kReasonCodeInvalid),
      disconnect_signal_dbm_(kDefaultDisconnectDbm),
      disconnect_threshold_dbm_(kDefaultDisconnectThresholdDbm),
      supplicant_auth_mode_(WPASupplicant::kAuthModeUnknown),
      need_bss_flush_(false),
      resumed_at_((struct timeval){0}),
      fast_scans_remaining_(kNumFastScanAttempts),
      has_already_completed_(false),
      is_roaming_in_progress_(false),
      pending_eap_failure_(Service::kFailureNone),
      is_debugging_connection_(false),
      eap_state_handler_(new SupplicantEAPStateHandler()),
      bgscan_short_interval_seconds_(kDefaultBgscanShortIntervalSeconds),
      bgscan_signal_threshold_dbm_(kDefaultBgscanSignalThresholdDbm),
      scan_interval_seconds_(kDefaultScanIntervalSeconds),
      netlink_manager_(NetlinkManager::GetInstance()),
      random_mac_supported_(false),
      random_mac_enabled_(false),
      sched_scan_supported_(false),
      scan_state_(kScanIdle),
      scan_method_(kScanMethodNone),
      receive_byte_count_at_connect_(0),
      wiphy_index_(kDefaultWiphyIndex),
      wake_on_wifi_(std::move(wake_on_wifi)),
      weak_ptr_factory_while_started_(this),
      weak_ptr_factory_(this) {
  scoped_supplicant_listener_.reset(
      new SupplicantManager::ScopedSupplicantListener(
          manager->supplicant_manager(),
          Bind(&WiFi::OnSupplicantPresence, weak_ptr_factory_.GetWeakPtr())));

  PropertyStore* store = this->mutable_store();
  store->RegisterDerivedString(
      kBgscanMethodProperty,
      StringAccessor(new CustomAccessor<WiFi, string>(
          this, &WiFi::GetBgscanMethod, &WiFi::SetBgscanMethod,
          &WiFi::ClearBgscanMethod)));
  HelpRegisterDerivedUint16(store, kBgscanShortIntervalProperty,
                            &WiFi::GetBgscanShortInterval,
                            &WiFi::SetBgscanShortInterval);
  HelpRegisterDerivedInt32(store, kBgscanSignalThresholdProperty,
                           &WiFi::GetBgscanSignalThreshold,
                           &WiFi::SetBgscanSignalThreshold);
  store->RegisterConstBool(kMacAddressRandomizationSupportedProperty,
                           &random_mac_supported_);
  HelpRegisterDerivedBool(store, kMacAddressRandomizationEnabledProperty,
                          &WiFi::GetRandomMacEnabled,
                          &WiFi::SetRandomMacEnabled);

  store->RegisterDerivedKeyValueStore(
      kLinkStatisticsProperty,
      KeyValueStoreAccessor(new CustomAccessor<WiFi, KeyValueStore>(
          this, &WiFi::GetLinkStatistics, nullptr)));

  // TODO(quiche): Decide if scan_pending_ is close enough to
  // "currently scanning" that we don't care, or if we want to track
  // scan pending/currently scanning/no scan scheduled as a tri-state
  // kind of thing.
  HelpRegisterConstDerivedBool(store, kScanningProperty, &WiFi::GetScanPending);
  HelpRegisterConstDerivedUint16s(store, kWifiSupportedFrequenciesProperty,
                                  &WiFi::GetAllScanFrequencies);
  HelpRegisterDerivedUint16(store, kScanIntervalProperty,
                            &WiFi::GetScanInterval, &WiFi::SetScanInterval);
  HelpRegisterConstDerivedBool(store, kWakeOnWiFiSupportedProperty,
                               &WiFi::GetWakeOnWiFiSupported);
  if (wake_on_wifi_) {
    wake_on_wifi_->InitPropertyStore(store);
  }
  ScopeLogger::GetInstance()->RegisterScopeEnableChangedCallback(
      ScopeLogger::kWiFi,
      Bind(&WiFi::OnWiFiDebugScopeChanged, weak_ptr_factory_.GetWeakPtr()));
  CHECK(netlink_manager_);
  netlink_handler_ =
      Bind(&WiFi::HandleNetlinkBroadcast, weak_ptr_factory_.GetWeakPtr());
  netlink_manager_->AddBroadcastHandler(netlink_handler_);
  SLOG(this, 2) << "WiFi device " << link_name() << " initialized.";
}

WiFi::~WiFi() {
  netlink_manager_->RemoveBroadcastHandler(netlink_handler_);
}

void WiFi::Start(Error* error,
                 const EnabledStateChangedCallback& /*callback*/) {
  SLOG(this, 2) << "WiFi " << link_name() << " starting.";
  if (enabled()) {
    return;
  }
  OnEnabledStateChanged(EnabledStateChangedCallback(), Error());
  if (error) {
    error->Reset();  // indicate immediate completion
  }

  // Subscribe to multicast events.
  netlink_manager_->SubscribeToEvents(Nl80211Message::kMessageTypeString,
                                      NetlinkManager::kEventTypeConfig);
  netlink_manager_->SubscribeToEvents(Nl80211Message::kMessageTypeString,
                                      NetlinkManager::kEventTypeScan);
  netlink_manager_->SubscribeToEvents(Nl80211Message::kMessageTypeString,
                                      NetlinkManager::kEventTypeRegulatory);
  netlink_manager_->SubscribeToEvents(Nl80211Message::kMessageTypeString,
                                      NetlinkManager::kEventTypeMlme);
  GetPhyInfo();
  // Connect to WPA supplicant if it's already present. If not, we'll connect to
  // it when it appears.
  supplicant_connect_attempts_ = 0;
  ConnectToSupplicant();
  if (wake_on_wifi_) {
    wake_on_wifi_->Start();
  }
}

void WiFi::Stop(Error* error, const EnabledStateChangedCallback& /*callback*/) {
  SLOG(this, 2) << "WiFi " << link_name() << " stopping.";
  // Unlike other devices, we leave the DBus name watcher in place here, because
  // WiFi callbacks expect notifications even if the device is disabled.
  DropConnection();
  StopScanTimer();
  for (const auto& endpoint : endpoint_by_rpcid_) {
    provider_->OnEndpointRemoved(endpoint.second);
  }
  endpoint_by_rpcid_.clear();
  for (const auto& map_entry : rpcid_by_service_) {
    RemoveNetwork(map_entry.second);
  }
  rpcid_by_service_.clear();
  // Remove interface from supplicant.
  if (supplicant_present_ && supplicant_interface_proxy_) {
    supplicant_process_proxy()->RemoveInterface(supplicant_interface_path_);
  }
  pending_scan_results_.reset();
  current_service_ = nullptr;  // breaks a reference cycle
  pending_service_ = nullptr;  // breaks a reference cycle
  is_debugging_connection_ = false;
  SetScanState(kScanIdle, kScanMethodNone, __func__);
  StopPendingTimer();
  StopReconnectTimer();
  StopRequestingStationInfo();

  OnEnabledStateChanged(EnabledStateChangedCallback(), Error());
  if (error)
    error->Reset();  // indicate immediate completion
  weak_ptr_factory_while_started_.InvalidateWeakPtrs();

  SLOG(this, 3) << "WiFi " << link_name() << " supplicant_interface_proxy_ "
                << (supplicant_interface_proxy_.get() ? "is set."
                                                      : "is not set.");
  SLOG(this, 3) << "WiFi " << link_name() << " pending_service_ "
                << (pending_service_.get() ? "is set." : "is not set.");
  SLOG(this, 3) << "WiFi " << link_name() << " has "
                << endpoint_by_rpcid_.size() << " EndpointMap entries.";
}

void WiFi::Scan(Error* /*error*/, const string& reason) {
  if ((scan_state_ != kScanIdle) ||
      (current_service_.get() && current_service_->IsConnecting())) {
    SLOG(this, 2) << "Ignoring scan request while scanning or connecting.";
    return;
  }
  SLOG(this, 1) << __func__ << " on " << link_name() << " from " << reason;
  // Needs to send a D-Bus message, but may be called from D-Bus
  // signal handler context (via Manager::RequestScan). So defer work
  // to event loop.
  dispatcher()->PostTask(
      FROM_HERE,
      Bind(&WiFi::ScanTask, weak_ptr_factory_while_started_.GetWeakPtr()));
}

void WiFi::AddPendingScanResult(const RpcIdentifier& path,
                                const KeyValueStore& properties,
                                bool is_removal) {
  // BSS events might come immediately after Stop(). Don't bother stashing them
  // at all.
  if (!enabled()) {
    return;
  }

  if (!pending_scan_results_) {
    pending_scan_results_.reset(new PendingScanResults(
        Bind(&WiFi::PendingScanResultsHandler,
             weak_ptr_factory_while_started_.GetWeakPtr())));
    dispatcher()->PostTask(FROM_HERE,
                           pending_scan_results_->callback.callback());
  }
  pending_scan_results_->results.emplace_back(path, properties, is_removal);
}

void WiFi::BSSAdded(const RpcIdentifier& path,
                    const KeyValueStore& properties) {
  // Called from a D-Bus signal handler, and may need to send a D-Bus
  // message. So defer work to event loop.
  AddPendingScanResult(path, properties, false);
}

void WiFi::BSSRemoved(const RpcIdentifier& path) {
  // Called from a D-Bus signal handler, and may need to send a D-Bus
  // message. So defer work to event loop.
  AddPendingScanResult(path, {}, true);
}

void WiFi::Certification(const KeyValueStore& properties) {
  dispatcher()->PostTask(
      FROM_HERE,
      Bind(&WiFi::CertificationTask,
           weak_ptr_factory_while_started_.GetWeakPtr(), properties));
}

void WiFi::EAPEvent(const string& status, const string& parameter) {
  dispatcher()->PostTask(
      FROM_HERE,
      Bind(&WiFi::EAPEventTask, weak_ptr_factory_while_started_.GetWeakPtr(),
           status, parameter));
}

void WiFi::PropertiesChanged(const KeyValueStore& properties) {
  SLOG(this, 2) << __func__;
  // Called from D-Bus signal handler, but may need to send a D-Bus
  // message. So defer work to event loop.
  dispatcher()->PostTask(FROM_HERE,
                         Bind(&WiFi::PropertiesChangedTask,
                              weak_ptr_factory_.GetWeakPtr(), properties));
}

void WiFi::ScanDone(const bool& success) {
  // This log line should be kept at INFO level to support the Shill log
  // processor.
  LOG(INFO) << __func__;

  if (!enabled()) {
    SLOG(this, 2) << "Ignoring scan completion while disabled";
    return;
  }

  // Defer handling of scan result processing, because that processing
  // may require the the registration of new D-Bus objects. And such
  // registration can't be done in the context of a D-Bus signal
  // handler.
  if (pending_scan_results_) {
    pending_scan_results_->is_complete = true;
    return;
  }
  if (success) {
    scan_failed_callback_.Cancel();
    dispatcher()->PostTask(FROM_HERE,
                           Bind(&WiFi::ScanDoneTask,
                                weak_ptr_factory_while_started_.GetWeakPtr()));
  } else {
    scan_failed_callback_.Reset(Bind(
        &WiFi::ScanFailedTask, weak_ptr_factory_while_started_.GetWeakPtr()));
    dispatcher()->PostDelayedTask(FROM_HERE, scan_failed_callback_.callback(),
                                  kPostScanFailedDelayMilliseconds);
  }
}

void WiFi::ConnectTo(WiFiService* service, Error* error) {
  CHECK(service) << "Can't connect to NULL service.";
  RpcIdentifier network_rpcid;

  // Ignore this connection attempt if suppplicant is not present.
  // This is possible when we try to connect right after WiFi
  // boostrapping is completed (through weaved). Refer to b/24605760
  // for more information.
  // Once supplicant is detected, shill will auto-connect to this
  // service (if this service is configured for auto-connect) when
  // it is discovered in the scan.
  if (!supplicant_present_) {
    LOG(WARNING) << "Trying to connect before supplicant is present";
    return;
  }

  // TODO(quiche): Handle cases where already connected.
  if (pending_service_ && pending_service_ == service) {
    Error::PopulateAndLog(
        FROM_HERE, error, Error::kInProgress,
        StringPrintf("%s: ignoring ConnectTo %s, which is already pending",
                     link_name().c_str(), service->log_name().c_str()));
    return;
  }

  if (pending_service_ && pending_service_ != service) {
    LOG(INFO) << "Connecting to: " << service->log_name() << ", "
              << "mode: " << service->mode() << ", "
              << "key management: " << service->key_management() << ", "
              << "physical mode: " << service->physical_mode() << ", "
              << "frequency: " << service->frequency();
    // This is a signal to SetPendingService(nullptr) to not modify the scan
    // state since the overall story arc isn't reflected by the disconnect.
    // It is, instead, described by the transition to either kScanFoundNothing
    // or kScanConnecting (made by |SetPendingService|, below).
    if (scan_method_ != kScanMethodNone) {
      SetScanState(kScanTransitionToConnecting, scan_method_, __func__);
    }
    // Explicitly disconnect pending service.
    pending_service_->set_expecting_disconnect(true);
    DisconnectFrom(pending_service_.get());
  }

  Error unused_error;
  network_rpcid = FindNetworkRpcidForService(service, &unused_error);
  if (network_rpcid.value().empty()) {
    KeyValueStore service_params =
        service->GetSupplicantConfigurationParameters();
    const uint32_t scan_ssid = 1;  // "True": Use directed probe.
    service_params.Set<uint32_t>(WPASupplicant::kNetworkPropertyScanSSID,
                                 scan_ssid);
    string bgscan_string = AppendBgscan(service, &service_params);
    service_params.Set<uint32_t>(WPASupplicant::kNetworkPropertyDisableVHT,
                                 provider_->disable_vht());
    if (!supplicant_interface_proxy_->AddNetwork(service_params,
                                                 &network_rpcid)) {
      Error::PopulateAndLog(FROM_HERE, error, Error::kOperationFailed,
                            "Failed to add network");
      SetScanState(kScanIdle, scan_method_, __func__);
      return;
    }
    CHECK(!network_rpcid.value().empty());  // No DBus path should be empty.
    service->set_bgscan_string(bgscan_string);
    rpcid_by_service_[service] = network_rpcid;
  }

  if (service->HasRecentConnectionIssues()) {
    SetConnectionDebugging(true);
  }

  supplicant_interface_proxy_->SelectNetwork(network_rpcid);
  SetPendingService(service);
  CHECK(current_service_.get() != pending_service_.get());

  // SelectService here (instead of in LinkEvent, like Ethernet), so
  // that, if we fail to bring up L2, we can attribute failure correctly.
  //
  // TODO(quiche): When we add code for dealing with connection failures,
  // reconsider if this is the right place to change the selected service.
  // see discussion in crbug.com/203282.
  SelectService(service);
}

void WiFi::DisconnectFromIfActive(WiFiService* service) {
  SLOG(this, 2) << __func__ << " service " << service->log_name();

  if (service != current_service_ && service != pending_service_) {
    if (!service->IsActive(nullptr)) {
      SLOG(this, 2) << "In " << __func__ << "(): " << service->log_name()
                    << " is not active, no need to initiate disconnect";
      return;
    }
  }

  DisconnectFrom(service);
}

void WiFi::DisconnectFrom(WiFiService* service) {
  SLOG(this, 2) << __func__ << " service " << service->log_name();

  if (service != current_service_ && service != pending_service_) {
    // TODO(quiche): Once we have asynchronous reply support, we should
    // generate a D-Bus error here. (crbug.com/206812)
    LOG(WARNING) << "In " << __func__ << "(): "
                 << " ignoring request to disconnect from: "
                 << service->log_name()
                 << " which is neither current nor pending";
    return;
  }

  if (pending_service_ && service != pending_service_) {
    // TODO(quiche): Once we have asynchronous reply support, we should
    // generate a D-Bus error here. (crbug.com/206812)
    LOG(WARNING) << "In " << __func__ << "(): "
                 << " ignoring request to disconnect from: "
                 << service->log_name() << " which is not the pending service.";
    return;
  }

  if (!pending_service_ && service != current_service_) {
    // TODO(quiche): Once we have asynchronous reply support, we should
    // generate a D-Bus error here. (crbug.com/206812)
    LOG(WARNING) << "In " << __func__ << "(): "
                 << " ignoring request to disconnect from: "
                 << service->log_name() << " which is not the current service.";
    return;
  }

  if (pending_service_) {
    // Since wpa_supplicant has not yet set CurrentBSS, we can't depend
    // on this to drive the service state back to idle.  Do that here.
    // Update service state for pending service.
    disconnect_signal_dbm_ = pending_service_->SignalLevel();
    ServiceDisconnected(pending_service_);
  } else if (service) {
    disconnect_signal_dbm_ = service->SignalLevel();
  }

  SetPendingService(nullptr);
  StopReconnectTimer();
  StopRequestingStationInfo();

  if (!supplicant_present_) {
    LOG(ERROR) << "In " << __func__ << "(): "
               << "wpa_supplicant is not present; silently resetting "
               << "current_service_.";
    if (current_service_ == selected_service()) {
      DropConnection();
    }
    current_service_ = nullptr;
    return;
  }

  bool disconnect_in_progress = true;
  // We'll call RemoveNetwork and reset |current_service_| after
  // supplicant notifies us that the CurrentBSS has changed.
  if (!supplicant_interface_proxy_->Disconnect()) {
    disconnect_in_progress = false;
  }

  if (supplicant_state_ != WPASupplicant::kInterfaceStateCompleted ||
      !disconnect_in_progress) {
    // Can't depend on getting a notification of CurrentBSS change.
    // So effect changes immediately.  For instance, this can happen when
    // a disconnect is triggered by a BSS going away.
    Error unused_error;
    RemoveNetworkForService(service, &unused_error);
    if (service == selected_service()) {
      DropConnection();
    } else {
      SLOG(this, 5) << __func__ << " skipping DropConnection, "
                    << "selected_service is "
                    << (selected_service() ? selected_service()->log_name()
                                           : "(null)");
    }
    current_service_ = nullptr;
  }

  CHECK(current_service_ == nullptr ||
        current_service_.get() != pending_service_.get());
}

bool WiFi::DisableNetwork(const RpcIdentifier& network) {
  std::unique_ptr<SupplicantNetworkProxyInterface> supplicant_network_proxy =
      control_interface()->CreateSupplicantNetworkProxy(network);
  if (!supplicant_network_proxy->SetEnabled(false)) {
    LOG(ERROR) << "DisableNetwork for " << network.value() << " failed.";
    return false;
  }
  return true;
}

bool WiFi::RemoveNetwork(const RpcIdentifier& network) {
  return supplicant_interface_proxy_->RemoveNetwork(network);
}

bool WiFi::IsIdle() const {
  return !current_service_ && !pending_service_;
}

void WiFi::ClearCachedCredentials(const WiFiService* service) {
  // Give up on the connection attempt for the pending service immediately since
  // the credential for it had already changed. This will allow the Manager to
  // start a new connection attempt for the pending service immediately without
  // waiting for the pending connection timeout.
  // current_service_ will get disconnect notification from the CurrentBSS
  // change event, so no need to explicitly disconnect here.
  if (service == pending_service_) {
    LOG(INFO) << "Disconnect pending service: credential changed";
    DisconnectFrom(pending_service_.get());
  }

  Error unused_error;
  RemoveNetworkForService(service, &unused_error);
}

void WiFi::NotifyEndpointChanged(const WiFiEndpointConstRefPtr& endpoint) {
  provider_->OnEndpointUpdated(endpoint);
}

string WiFi::AppendBgscan(WiFiService* service,
                          KeyValueStore* service_params) const {
  string method = bgscan_method_;
  int short_interval = bgscan_short_interval_seconds_;
  int signal_threshold = bgscan_signal_threshold_dbm_;
  int scan_interval = kBackgroundScanIntervalSeconds;
  if (method.empty()) {
    // If multiple APs are detected for this SSID, configure the default method
    // with pre-set parameters. Otherwise, use extended scan intervals.
    method = kDefaultBgscanMethod;
    if (service->GetEndpointCount() <= 1) {
      SLOG(nullptr, 3) << "Background scan intervals extended -- single "
                       << "Endpoint for Service.";
      short_interval = kSingleEndpointBgscanShortIntervalSeconds;
      scan_interval = kSingleEndpointBgscanIntervalSeconds;
    }
  } else if (method == WPASupplicant::kNetworkBgscanMethodNone) {
    SLOG(nullptr, 3) << "Background scan disabled -- chose None method.";
  } else {
    // If the background scan method was explicitly specified, honor the
    // configured background scan interval.
    scan_interval = scan_interval_seconds_;
  }
  string config_string;
  if (method != WPASupplicant::kNetworkBgscanMethodNone) {
    config_string = StringPrintf("%s:%d:%d:%d", method.c_str(), short_interval,
                                 signal_threshold, scan_interval);
  }
  SLOG(nullptr, 3) << "Background scan: '" << config_string << "'";
  service_params->Set<string>(WPASupplicant::kNetworkPropertyBgscan,
                              config_string);
  return config_string;
}

bool WiFi::ReconfigureBgscan(WiFiService* service) {
  SLOG(this, 3) << __func__ << " for " << service->log_name();
  KeyValueStore bgscan_params;
  string bgscan_string = AppendBgscan(service, &bgscan_params);
  if (service->bgscan_string() == bgscan_string) {
    SLOG(this, 3) << "No change in bgscan parameters.";
    return false;
  }

  Error unused_error;
  RpcIdentifier id = FindNetworkRpcidForService(service, &unused_error);
  if (id.value().empty()) {
    return false;
  }

  std::unique_ptr<SupplicantNetworkProxyInterface> network_proxy =
      control_interface()->CreateSupplicantNetworkProxy(id);
  if (!network_proxy->SetProperties(bgscan_params)) {
    LOG(ERROR) << "SetProperties for " << id.value() << " failed.";
    return false;
  }
  LOG(INFO) << "Updated bgscan parameters: " << bgscan_string;
  service->set_bgscan_string(bgscan_string);
  return true;
}

bool WiFi::ReconfigureBgscanForRelevantServices() {
  bool ret = true;
  if (current_service_) {
    ret = ReconfigureBgscan(current_service_.get()) && ret;
  }
  if (pending_service_) {
    ret = ReconfigureBgscan(pending_service_.get()) && ret;
  }
  return ret;
}

string WiFi::GetBgscanMethod(Error* /* error */) {
  return bgscan_method_.empty() ? kDefaultBgscanMethod : bgscan_method_;
}

bool WiFi::SetBgscanMethod(const string& method, Error* error) {
  if (method != WPASupplicant::kNetworkBgscanMethodSimple &&
      method != WPASupplicant::kNetworkBgscanMethodLearn &&
      method != WPASupplicant::kNetworkBgscanMethodNone) {
    const string error_message =
        StringPrintf("Unrecognized bgscan method %s", method.c_str());
    LOG(WARNING) << error_message;
    error->Populate(Error::kInvalidArguments, error_message);
    return false;
  }
  if (bgscan_method_ == method) {
    return false;
  }
  bgscan_method_ = method;
  return ReconfigureBgscanForRelevantServices();
}

bool WiFi::SetBgscanShortInterval(const uint16_t& seconds, Error* /*error*/) {
  if (bgscan_short_interval_seconds_ == seconds) {
    return false;
  }
  bgscan_short_interval_seconds_ = seconds;
  return ReconfigureBgscanForRelevantServices();
}

bool WiFi::SetBgscanSignalThreshold(const int32_t& dbm, Error* /*error*/) {
  if (bgscan_signal_threshold_dbm_ == dbm) {
    return false;
  }
  bgscan_signal_threshold_dbm_ = dbm;
  return ReconfigureBgscanForRelevantServices();
}

bool WiFi::SetScanInterval(const uint16_t& seconds, Error* /*error*/) {
  if (scan_interval_seconds_ == seconds) {
    return false;
  }
  scan_interval_seconds_ = seconds;
  if (running()) {
    StartScanTimer();
  }
  // The scan interval affects both foreground scans (handled by
  // |scan_timer_callback_|), and background scans (handled by
  // supplicant).
  return ReconfigureBgscanForRelevantServices();
}

bool WiFi::GetRandomMacEnabled(Error* /*error*/) {
  return random_mac_enabled_;
}

bool WiFi::SetRandomMacEnabled(const bool& enabled, Error* error) {
  if (!supplicant_present_ || !supplicant_interface_proxy_.get()) {
    SLOG(this, 2) << "Ignoring random MAC while supplicant is not present.";
    return false;
  }

  if (random_mac_enabled_ == enabled) {
    return false;
  }
  if (!random_mac_supported_) {
    Error::PopulateAndLog(
        FROM_HERE, error, Error::kNotSupported,
        "This WiFi device does not support MAC address randomization");
    return false;
  }
  if ((enabled && supplicant_interface_proxy_->EnableMacAddressRandomization(
                      kRandomMacMask, sched_scan_supported_)) ||
      (!enabled &&
       supplicant_interface_proxy_->DisableMacAddressRandomization())) {
    random_mac_enabled_ = enabled;
    return true;
  }
  return false;
}

void WiFi::ClearBgscanMethod(Error* /*error*/) {
  bgscan_method_.clear();
}

void WiFi::AssocStatusChanged(const int32_t new_assoc_status) {
  SLOG(this, 3) << "WiFi " << link_name()
                << " supplicant updated AssocStatusCode to " << new_assoc_status
                << " (was " << supplicant_assoc_status_ << ")";
  if (supplicant_auth_status_ != IEEE_80211::kStatusCodeSuccessful) {
    LOG(WARNING) << "Supplicant authentication status is set to "
                 << supplicant_auth_status_
                 << " despite getting a new association status.";
    supplicant_auth_status_ = IEEE_80211::kStatusCodeSuccessful;
  }
  supplicant_assoc_status_ = new_assoc_status;
}

void WiFi::AuthStatusChanged(const int32_t new_auth_status) {
  SLOG(this, 3) << "WiFi " << link_name()
                << " supplicant updated AuthStatusCode to " << new_auth_status
                << " (was " << supplicant_auth_status_ << ")";
  if (supplicant_assoc_status_ != IEEE_80211::kStatusCodeSuccessful) {
    LOG(WARNING) << "Supplicant association status is set to "
                 << supplicant_assoc_status_
                 << " despite getting a new authentication status.";
    supplicant_assoc_status_ = IEEE_80211::kStatusCodeSuccessful;
  }
  supplicant_auth_status_ = new_auth_status;
}

void WiFi::CurrentBSSChanged(const RpcIdentifier& new_bss) {
  SLOG(this, 3) << "WiFi " << link_name() << " CurrentBSS "
                << supplicant_bss_.value() << " -> " << new_bss.value();

  // Store signal strength of BSS when disconnecting.
  if (supplicant_bss_.value() != WPASupplicant::kCurrentBSSNull &&
      new_bss.value() == WPASupplicant::kCurrentBSSNull) {
    const WiFiEndpointConstRefPtr endpoint(GetCurrentEndpoint());
    if (endpoint == nullptr) {
      LOG(ERROR) << "Can't get endpoint for current supplicant BSS "
                 << supplicant_bss_.value();
      // Default to value that will not imply out of range error in
      // ServiceDisconnected or PendingTimeoutHandler.
      disconnect_signal_dbm_ = kDefaultDisconnectDbm;
    } else {
      disconnect_signal_dbm_ = endpoint->signal_strength();
      LOG(INFO) << "Current BSS signal strength at disconnect: "
                << disconnect_signal_dbm_;
    }
  }

  supplicant_bss_ = new_bss;
  has_already_completed_ = false;
  is_roaming_in_progress_ = false;
  if (current_service_) {
    current_service_->SetIsRekeyInProgress(false);
  }

  // Any change in CurrentBSS means supplicant is actively changing our
  // connectivity.  We no longer need to track any previously pending
  // reconnect.
  StopReconnectTimer();
  StopRequestingStationInfo();

  if (new_bss.value() == WPASupplicant::kCurrentBSSNull) {
    HandleDisconnect();
    if (!provider_->GetHiddenSSIDList().empty()) {
      // Before disconnecting, wpa_supplicant probably scanned for
      // APs. So, in the normal case, we defer to the timer for the next scan.
      //
      // However, in the case of hidden SSIDs, supplicant knows about
      // at most one of them. (That would be the hidden SSID we were
      // connected to, if applicable.)
      //
      // So, in this case, we initiate an immediate scan. This scan
      // will include the hidden SSIDs we know about (up to the limit of
      // kScanMAxSSIDsPerScan).
      //
      // We may want to reconsider this immediate scan, if/when shill
      // takes greater responsibility for scanning (vs. letting
      // supplicant handle most of it).
      Scan(nullptr, __func__);
    }
  } else {
    HandleRoam(new_bss);
  }

  // Reset the EAP handler only after calling HandleDisconnect() above
  // so our EAP state could be used to detect a failed authentication.
  eap_state_handler_->Reset();
  pending_eap_failure_ = Service::kFailureNone;

  // If we are selecting a new service, or if we're clearing selection
  // of a something other than the pending service, call SelectService.
  // Otherwise skip SelectService, since this will cause the pending
  // service to be marked as Idle.
  if (current_service_ || selected_service() != pending_service_) {
    SelectService(current_service_);
  }

  // Invariant check: a Service can either be current, or pending, but
  // not both.
  CHECK(current_service_.get() != pending_service_.get() ||
        current_service_.get() == nullptr);

  // If we are no longer debugging a problematic WiFi connection, return
  // to the debugging level indicated by the WiFi debugging scope.
  if ((!current_service_ || !current_service_->HasRecentConnectionIssues()) &&
      (!pending_service_ || !pending_service_->HasRecentConnectionIssues())) {
    SetConnectionDebugging(false);
  }
}

void WiFi::DisconnectReasonChanged(const int32_t new_value) {
  int32_t sanitized_value =
      (new_value == INT32_MIN) ? INT32_MAX : abs(new_value);
  if (sanitized_value > IEEE_80211::kReasonCodeMax) {
    LOG(WARNING) << "Received disconnect reason " << sanitized_value
                 << " from supplicant greater than kReasonCodeMax."
                 << " Perhaps WiFiReasonCode needs to be updated.";
    sanitized_value = IEEE_80211::kReasonCodeMax;
  }
  auto new_reason = static_cast<IEEE_80211::WiFiReasonCode>(sanitized_value);

  std::string update;
  if (supplicant_disconnect_reason_ != IEEE_80211::kReasonCodeInvalid) {
    update = StringPrintf(" from %d", supplicant_disconnect_reason_);
  }

  std::string new_disconnect_description = "Success";
  if (new_reason != 0) {
    new_disconnect_description = IEEE_80211::ReasonToString(new_reason);
  }

  LOG(INFO) << StringPrintf(
      "WiFi %s supplicant updated DisconnectReason%s to %d (%s)",
      link_name().c_str(), update.c_str(), new_reason,
      new_disconnect_description.c_str());
  supplicant_disconnect_reason_ = new_reason;

  Metrics::WiFiDisconnectByWhom by_whom = (new_value < 0)
                                              ? Metrics::kDisconnectedNotByAp
                                              : Metrics::kDisconnectedByAp;
  metrics()->Notify80211Disconnect(by_whom, new_reason);
}

void WiFi::CurrentAuthModeChanged(const string& auth_mode) {
  if (auth_mode != WPASupplicant::kAuthModeInactive &&
      auth_mode != WPASupplicant::kAuthModeUnknown) {
    supplicant_auth_mode_ = auth_mode;
  }
}

void WiFi::HandleDisconnect() {
  // Identify the affected service. We expect to get a disconnect
  // event when we fall off a Service that we were connected
  // to. However, we also allow for the case where we get a disconnect
  // event while attempting to connect from a disconnected state.
  WiFiService* affected_service =
      current_service_.get() ? current_service_.get() : pending_service_.get();

  if (!affected_service) {
    SLOG(this, 2) << "WiFi " << link_name()
                  << " disconnected while not connected or connecting";
    return;
  }

  SLOG(this, 2) << "WiFi " << link_name() << " disconnected from "
                << " (or failed to connect to) "
                << affected_service->log_name();

  if (affected_service == current_service_.get() && pending_service_.get()) {
    // Current service disconnected intentionally for network switching,
    // set service state to idle.
    affected_service->SetState(Service::kStateIdle);
  } else {
    // Perform necessary handling for disconnected service.
    ServiceDisconnected(affected_service);
  }

  current_service_ = nullptr;

  if (affected_service == selected_service()) {
    // If our selected service has disconnected, destroy IP configuration state.
    DropConnection();
  }

  Error error;
  if (!DisableNetworkForService(affected_service, &error)) {
    if (error.type() == Error::kNotFound) {
      SLOG(this, 2) << "WiFi " << link_name() << " disconnected from "
                    << " (or failed to connect to) service "
                    << affected_service->log_name() << ", "
                    << "but could not find supplicant network to disable.";
    } else {
      LOG(ERROR) << "DisableNetwork failed on " << link_name()
                 << "for: " << affected_service->log_name() << ".";
    }
  }

  metrics()->NotifySignalAtDisconnect(*affected_service,
                                      disconnect_signal_dbm_);
  affected_service->NotifyCurrentEndpoint(nullptr);
  metrics()->NotifyServiceDisconnect(*affected_service);

  if (affected_service == pending_service_.get()) {
    // The attempt to connect to |pending_service_| failed. Clear
    // |pending_service_|, to indicate we're no longer in the middle
    // of a connect request.
    SetPendingService(nullptr);
  } else if (pending_service_) {
    // We've attributed the disconnection to what was the
    // |current_service_|, rather than the |pending_service_|.
    //
    // If we're wrong about that (i.e. supplicant reported this
    // CurrentBSS change after attempting to connect to
    // |pending_service_|), we're depending on supplicant to retry
    // connecting to |pending_service_|, and delivering another
    // CurrentBSS change signal in the future.
    //
    // Log this fact, to help us debug (in case our assumptions are
    // wrong).
    SLOG(this, 2) << "WiFi " << link_name()
                  << " pending connection to: " << pending_service_->log_name()
                  << " after disconnect";
  }

  // If we disconnect, initially scan at a faster frequency, to make sure
  // we've found all available APs.
  RestartFastScanAttempts();
}

void WiFi::ServiceDisconnected(WiFiServiceRefPtr affected_service) {
  SLOG(this, 1) << __func__ << " service " << affected_service->log_name();

  // Check if service was explicitly disconnected due to failure or
  // is explicitly disconnected by user.
  if (!affected_service->IsInFailState() &&
      !affected_service->explicitly_disconnected() &&
      !affected_service->expecting_disconnect()) {
    // Check auth/assoc status codes and send metric if a status code indicates
    // failure (otherwise logs and UMA will only contain status code failures
    // caused by a pending connection timeout).
    Service::ConnectFailure failure_from_status = ExamineStatusCodes();

    // Determine disconnect failure reason.
    Service::ConnectFailure failure;
    if (SuspectCredentials(affected_service, &failure)) {
      // If we've reached here, |SuspectCredentials| has already set
      // |failure| to the appropriate value.
    } else {
      SLOG(this, 2) << "Supplicant disconnect reason: "
                    << IEEE_80211::ReasonToString(
                           supplicant_disconnect_reason_);
      // Disconnected for some other reason.
      // Map IEEE error codes to shill error codes.
      switch (supplicant_disconnect_reason_) {
        case IEEE_80211::kReasonCodeInactivity:
        case IEEE_80211::kReasonCodeSenderHasLeft:
          SLOG(this, 2) << "Disconnect signal: " << disconnect_signal_dbm_;
          if (disconnect_signal_dbm_ <= disconnect_threshold_dbm_ &&
              disconnect_signal_dbm_ != kDefaultDisconnectDbm) {
            failure = Service::kFailureOutOfRange;
          } else {
            failure = Service::kFailureDisconnect;
          }
          break;
        case IEEE_80211::kReasonCodeNonAuthenticated:
        case IEEE_80211::kReasonCodeReassociationNotAuthenticated:
        case IEEE_80211::kReasonCodePreviousAuthenticationInvalid:
          failure = Service::kFailureNotAuthenticated;
          break;
        case IEEE_80211::kReasonCodeNonAssociated:
          failure = Service::kFailureNotAssociated;
          break;
        case IEEE_80211::kReasonCodeTooManySTAs:
          failure = Service::kFailureTooManySTAs;
          break;
        case IEEE_80211::kReasonCode8021XAuth:
          failure = Service::kFailureEAPAuthentication;
          break;
        default:
          // If we don't have a failure type to set given the disconnect reason,
          // see if assoc/auth status codes can lead to an informative failure
          // reason. Will be kFailureUnknown if that isn't the case.
          failure = failure_from_status;
          break;
      }
    }
    if (failure == Service::kFailureEAPAuthentication &&
        pending_eap_failure_ != Service::kFailureNone) {
      failure = pending_eap_failure_;
    }
    if (!affected_service->ShouldIgnoreFailure()) {
      affected_service->SetFailure(failure);
    }
    LOG(ERROR) << "Disconnected due to reason: "
               << Service::ConnectFailureToString(failure);
  }

  // Set service state back to idle, so this service can be used for
  // future connections.
  affected_service->SetState(Service::kStateIdle);
}

Service::ConnectFailure WiFi::ExamineStatusCodes() const {
  bool is_auth_error =
      supplicant_auth_status_ != IEEE_80211::kStatusCodeSuccessful;
  bool is_assoc_error =
      supplicant_assoc_status_ != IEEE_80211::kStatusCodeSuccessful;
  DCHECK(!(is_auth_error && is_assoc_error));
  if (!is_auth_error && !is_assoc_error) {
    return Service::kFailureUnknown;
  }

  int32_t status = supplicant_auth_status_;
  std::string error_name = "Authentication";
  std::string metric_name = Metrics::kMetricWiFiAuthFailureType;
  Service::ConnectFailure proposed_failure = Service::kFailureNotAuthenticated;
  if (is_assoc_error) {
    status = supplicant_assoc_status_;
    error_name = "Association";
    metric_name = Metrics::kMetricWiFiAssocFailureType;
    proposed_failure = Service::kFailureNotAssociated;
  }

  LOG(INFO) << "WiFi Device " << link_name() << ": " << error_name << " error "
            << status << " ("
            << IEEE_80211::StatusToString(
                   static_cast<IEEE_80211::WiFiStatusCode>(status))
            << ")";
  metrics()->SendEnumToUMA(metric_name, status, IEEE_80211::kStatusCodeMax);

  if (status == IEEE_80211::kStatusCodeMaxSta) {
    proposed_failure = Service::kFailureTooManySTAs;
  }
  return proposed_failure;
}

// We use the term "Roam" loosely. In particular, we include the case
// where we "Roam" to a BSS from the disconnected state.
void WiFi::HandleRoam(const RpcIdentifier& new_bss) {
  EndpointMap::iterator endpoint_it = endpoint_by_rpcid_.find(new_bss);
  if (endpoint_it == endpoint_by_rpcid_.end()) {
    LOG(WARNING) << "WiFi " << link_name() << " connected to unknown BSS "
                 << new_bss.value();
    return;
  }

  const WiFiEndpointConstRefPtr endpoint(endpoint_it->second);
  WiFiServiceRefPtr service = provider_->FindServiceForEndpoint(endpoint);
  if (!service) {
    LOG(WARNING) << "WiFi " << link_name()
                 << " could not find Service for Endpoint "
                 << endpoint->bssid_string() << " (service will be unchanged)";
    return;
  }

  metrics()->NotifyAp80211kSupport(
      endpoint->krv_support().neighbor_list_supported);
  metrics()->NotifyAp80211rSupport(endpoint->krv_support().ota_ft_supported,
                                   endpoint->krv_support().otds_ft_supported);
  metrics()->NotifyAp80211vDMSSupport(endpoint->krv_support().dms_supported);
  metrics()->NotifyAp80211vBSSMaxIdlePeriodSupport(
      endpoint->krv_support().bss_max_idle_period_supported);
  metrics()->NotifyAp80211vBSSTransitionSupport(
      endpoint->krv_support().bss_transition_supported);
  metrics()->NotifyHS20Support(endpoint->hs20_information().supported,
                               endpoint->hs20_information().version);

  SLOG(this, 2) << "WiFi " << link_name() << " roamed to Endpoint "
                << endpoint->bssid_string() << " "
                << LogSSID(endpoint->ssid_string());

  service->NotifyCurrentEndpoint(endpoint);

  if (pending_service_.get() && service.get() != pending_service_.get()) {
    // The Service we've roamed on to is not the one we asked for.
    // We assume that this is transient, and that wpa_supplicant
    // is trying / will try to connect to |pending_service_|.
    //
    // If it succeeds, we'll end up back here, but with |service|
    // pointing at the same service as |pending_service_|.
    //
    // If it fails, we'll process things in HandleDisconnect.
    //
    // So we leave |pending_service_| untouched.
    SLOG(this, 2) << "WiFi " << link_name() << " new current Endpoint "
                  << endpoint->bssid_string()
                  << " is not part of pending service "
                  << pending_service_->log_name();

    // Sanity check: if we didn't roam onto |pending_service_|, we
    // should still be on |current_service_|.
    if (service.get() != current_service_.get()) {
      LOG(WARNING) << "WiFi " << link_name() << " new current Endpoint "
                   << endpoint->bssid_string()
                   << " is neither part of pending service "
                   << pending_service_->log_name()
                   << " nor part of current service "
                   << (current_service_ ? current_service_->log_name()
                                        : "(nullptr)");
      // wpa_supplicant has no knowledge of the pending_service_ at this point.
      // Disconnect the pending_service_, so that it can be connectable again.
      // Otherwise, we'd have to wait for the pending timeout to trigger the
      // disconnect. This will speed up the connection attempt process for
      // the pending_service_.
      DisconnectFrom(pending_service_.get());
    }
    return;
  }

  if (pending_service_) {
    // We assume service.get() == pending_service_.get() here, because
    // of the return in the previous if clause.
    //
    // Boring case: we've connected to the service we asked
    // for. Simply update |current_service_| and |pending_service_|.
    current_service_ = service;
    SetScanState(kScanConnected, scan_method_, __func__);
    SetPendingService(nullptr);
    return;
  }

  // |pending_service_| was nullptr, so we weren't attempting to connect
  // to a new Service. Sanity check that we're still on
  // |current_service_|.
  if (service.get() != current_service_.get()) {
    LOG(WARNING) << "WiFi " << link_name() << " new current Endpoint "
                 << endpoint->bssid_string()
                 << (current_service_.get()
                         ? StringPrintf(" is not part of current service %s",
                                        current_service_->log_name().c_str())
                         : " with no current service");
    // We didn't expect to be here, but let's cope as well as we
    // can. Update |current_service_| to keep it in sync with
    // supplicant.
    current_service_ = service;

    // If this service isn't already marked as actively connecting (likely,
    // since this service is a bit of a surprise) set the service as
    // associating.
    if (!current_service_->IsConnecting()) {
      current_service_->SetState(Service::kStateAssociating);
    }

    return;
  }

  // At this point, we know that |pending_service_| was nullptr, and that
  // we're still on |current_service_|.  We should track this roaming
  // event so we can refresh our IPConfig if it succeeds.
  is_roaming_in_progress_ = true;

  return;
}

RpcIdentifier WiFi::FindNetworkRpcidForService(const WiFiService* service,
                                               Error* error) {
  ReverseServiceMap::const_iterator rpcid_it = rpcid_by_service_.find(service);
  if (rpcid_it == rpcid_by_service_.end()) {
    const string error_message = StringPrintf(
        "WiFi %s cannot find supplicant network rpcid for service %s",
        link_name().c_str(), service->log_name().c_str());
    // There are contexts where this is not an error, such as when a service
    // is clearing whatever cached credentials may not exist.
    SLOG(this, 2) << error_message;
    if (error) {
      error->Populate(Error::kNotFound, error_message);
    }
    return RpcIdentifier("");
  }

  return rpcid_it->second;
}

bool WiFi::DisableNetworkForService(const WiFiService* service, Error* error) {
  RpcIdentifier rpcid = FindNetworkRpcidForService(service, error);
  if (rpcid.value().empty()) {
    // Error is already populated.
    return false;
  }

  if (!DisableNetwork(rpcid)) {
    const string error_message = StringPrintf(
        "WiFi %s cannot disable network for service %s: "
        "DBus operation failed for rpcid %s.",
        link_name().c_str(), service->log_name().c_str(),
        rpcid.value().c_str());
    Error::PopulateAndLog(FROM_HERE, error, Error::kOperationFailed,
                          error_message);

    // Make sure that such errored networks are removed, so problems do not
    // propagate to future connection attempts.
    RemoveNetwork(rpcid);
    rpcid_by_service_.erase(service);

    return false;
  }

  return true;
}

bool WiFi::RemoveNetworkForService(const WiFiService* service, Error* error) {
  RpcIdentifier rpcid = FindNetworkRpcidForService(service, error);
  if (rpcid.value().empty()) {
    // Error is already populated.
    return false;
  }

  // Erase the rpcid from our tables regardless of failure below, since even
  // if in failure, we never want to use this network again.
  rpcid_by_service_.erase(service);

  // TODO(quiche): Reconsider giving up immediately. Maybe give
  // wpa_supplicant some time to retry, first.
  if (!RemoveNetwork(rpcid)) {
    const string error_message = StringPrintf(
        "WiFi %s cannot remove network for service %s: "
        "DBus operation failed for rpcid %s.",
        link_name().c_str(), service->log_name().c_str(),
        rpcid.value().c_str());
    Error::PopulateAndLog(FROM_HERE, error, Error::kOperationFailed,
                          error_message);
    return false;
  }

  return true;
}

void WiFi::PendingScanResultsHandler() {
  CHECK(pending_scan_results_);
  SLOG(this, 2) << __func__ << " with " << pending_scan_results_->results.size()
                << " results and is_complete set to "
                << pending_scan_results_->is_complete;
  for (const auto& result : pending_scan_results_->results) {
    if (result.is_removal) {
      BSSRemovedTask(result.path);
    } else {
      BSSAddedTask(result.path, result.properties);
    }
  }
  if (pending_scan_results_->is_complete) {
    ScanDoneTask();
  }
  pending_scan_results_.reset();
}

bool WiFi::ParseWiphyIndex(const Nl80211Message& nl80211_message) {
  // Verify NL80211_CMD_NEW_WIPHY.
  if (nl80211_message.command() != NewWiphyMessage::kCommand) {
    LOG(ERROR) << "Received unexpected command: " << nl80211_message.command();
    return false;
  }
  if (!nl80211_message.const_attributes()->GetU32AttributeValue(
          NL80211_ATTR_WIPHY, &wiphy_index_)) {
    LOG(ERROR) << "NL80211_CMD_NEW_WIPHY had no NL80211_ATTR_WIPHY";
    return false;
  }
  return true;
}

void WiFi::ParseFeatureFlags(const Nl80211Message& nl80211_message) {
  // Verify NL80211_CMD_NEW_WIPHY.
  if (nl80211_message.command() != NewWiphyMessage::kCommand) {
    LOG(ERROR) << "Received unexpected command: " << nl80211_message.command();
    return;
  }

  uint32_t flags;
  if (!nl80211_message.const_attributes()->GetU32AttributeValue(
          NL80211_ATTR_FEATURE_FLAGS, &flags)) {
    LOG(WARNING) << "NL80211_CMD_NEW_WIPHY had no NL80211_ATTR_FEATURE_FLAGS";
    return;
  }

  // Look for scheduled scan support.
  AttributeListConstRefPtr cmds;
  if (!nl80211_message.const_attributes()->ConstGetNestedAttributeList(
          NL80211_ATTR_SUPPORTED_COMMANDS, &cmds)) {
    LOG(WARNING)
        << "NL80211_CMD_NEW_WIPHY had no NL80211_ATTR_SUPPORTED_COMMANDS";
    return;
  }

  AttributeIdIterator cmds_iter(*cmds);
  for (; !cmds_iter.AtEnd(); cmds_iter.Advance()) {
    uint32_t cmd;
    if (!cmds->GetU32AttributeValue(cmds_iter.GetId(), &cmd)) {
      LOG(ERROR) << "Failed to get supported cmd " << cmds_iter.GetId();
      return;
    }
    if (cmd == NL80211_CMD_START_SCHED_SCAN)
      sched_scan_supported_ = true;
  }

  // There are two flags for MAC randomization: one for regular scans and one
  // for scheduled scans. Only look for the latter if scheduled scans are
  // supported.
  random_mac_supported_ =
      (flags & NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR) &&
      (!sched_scan_supported_ ||
       (flags & NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR));

  SLOG(this, 7) << __func__ << ": "
                << "Supports random MAC: " << random_mac_supported_;
}

void WiFi::HandleNetlinkBroadcast(const NetlinkMessage& netlink_message) {
  // We only handle nl80211 commands.
  if (netlink_message.message_type() != Nl80211Message::GetMessageType()) {
    SLOG(this, 7) << __func__ << ": "
                  << "Not a NL80211 Message";
    return;
  }
  const Nl80211Message& nl80211_msg =
      *reinterpret_cast<const Nl80211Message*>(&netlink_message);

  // Pass nl80211 message to appropriate handler function.
  if (nl80211_msg.command() == TriggerScanMessage::kCommand) {
    OnScanStarted(nl80211_msg);
  } else if (nl80211_msg.command() == WiphyRegChangeMessage::kCommand ||
             nl80211_msg.command() == RegChangeMessage::kCommand) {
    OnRegChange(nl80211_msg);
  }
}

void WiFi::OnScanStarted(const Nl80211Message& scan_trigger_msg) {
  if (scan_trigger_msg.command() != TriggerScanMessage::kCommand) {
    SLOG(this, 7) << __func__ << ": "
                  << "Not a NL80211_CMD_TRIGGER_SCAN message";
    return;
  }
  uint32_t wiphy_index;
  if (!scan_trigger_msg.const_attributes()->GetU32AttributeValue(
          NL80211_ATTR_WIPHY, &wiphy_index)) {
    LOG(ERROR) << "NL80211_CMD_TRIGGER_SCAN had no NL80211_ATTR_WIPHY";
    return;
  }
  if (wiphy_index != wiphy_index_) {
    SLOG(this, 7) << __func__ << ": "
                  << "Scan trigger not meant for this interface";
    return;
  }
  bool is_active_scan = false;
  AttributeListConstRefPtr ssids;
  if (scan_trigger_msg.const_attributes()->ConstGetNestedAttributeList(
          NL80211_ATTR_SCAN_SSIDS, &ssids)) {
    AttributeIdIterator ssid_iter(*ssids);
    // If any SSIDs (even the empty wild card) are reported, an active scan was
    // launched. Otherwise, a passive scan was launched.
    is_active_scan = !ssid_iter.AtEnd();
  }
  if (wake_on_wifi_) {
    wake_on_wifi_->OnScanStarted(is_active_scan);
  }
}

void WiFi::OnGetReg(const Nl80211Message& nl80211_message) {
  if (nl80211_message.command() != GetRegMessage::kCommand) {
    LOG(ERROR) << __func__
               << ": unexpected command: " << nl80211_message.command_string();
    return;
  }

  // Extract country code.
  std::string country_code;
  if (!nl80211_message.const_attributes()->GetStringAttributeValue(
          NL80211_ATTR_REG_ALPHA2, &country_code)) {
    SLOG(this, 3) << "Regulatory message had no NL80211_ATTR_REG_ALPHA2";
    return;  // If no alpha2 value present, ignore it.
  }
  HandleCountryChange(country_code);

  uint8_t region;
  if (!nl80211_message.const_attributes()->GetU8AttributeValue(
          NL80211_ATTR_DFS_REGION, &region)) {
    SLOG(this, 1) << "Regulatory message has no DFS region, using: "
                  << NL80211_DFS_UNSET;
    region = NL80211_DFS_UNSET;
  } else {
    SLOG(this, 1) << "DFS region: " << region;
  }

  manager()->power_manager()->ChangeRegDomain(
      static_cast<nl80211_dfs_regions>(region));
}

void WiFi::OnRegChange(const Nl80211Message& nl80211_message) {
  if (nl80211_message.command() != WiphyRegChangeMessage::kCommand &&
      nl80211_message.command() != RegChangeMessage::kCommand) {
    LOG(ERROR) << __func__
               << ": unexpected command: " << nl80211_message.command_string();
    return;
  }

  // Ignore regulatory domain CHANGE events initiated by user.
  uint32_t initiator;
  if (!nl80211_message.const_attributes()->GetU32AttributeValue(
          NL80211_ATTR_REG_INITIATOR, &initiator)) {
    SLOG(this, 3) << "No NL80211_ATTR_REG_INITIATOR in command "
                  << nl80211_message.command_string();
    return;
  }
  if (initiator == NL80211_REGDOM_SET_BY_USER) {
    SLOG(this, 3) << "Ignoring regulatory domain change initiated by user.";
    return;
  }

  // CHANGE events don't have all the useful attributes (e.g.,
  // NL80211_ATTR_DFS_REGION); request the full info now.
  GetRegulatory();
}

void WiFi::HandleCountryChange(std::string country_code) {
  // Variable to keep track of current regulatory domain to reduce noise in
  // reported "change" events.
  static int current_reg_dom_val = -1;

  // Get Regulatory Domain value from received country code.
  int reg_dom_val = Metrics::GetRegulatoryDomainValue(country_code);
  if (reg_dom_val == Metrics::RegulatoryDomain::kCountryCodeInvalid) {
    LOG(ERROR) << "Unsupported NL80211_ATTR_REG_ALPHA2 attribute: "
               << country_code;
  } else {
    SLOG(this, 3) << StringPrintf(
        "Regulatory domain change message received with alpha2 %s (metric val: "
        "%d)",
        country_code.c_str(), reg_dom_val);
  }

  // Only send to UMA when regulatory domain changes to reduce noise in metrics.
  if (reg_dom_val != current_reg_dom_val) {
    current_reg_dom_val = reg_dom_val;
    metrics()->SendEnumToUMA(Metrics::kMetricRegulatoryDomain, reg_dom_val,
                             Metrics::RegulatoryDomain::kRegDomMaxValue);
  }
}

void WiFi::BSSAddedTask(const RpcIdentifier& path,
                        const KeyValueStore& properties) {
  // Note: we assume that BSSIDs are unique across endpoints. This
  // means that if an AP reuses the same BSSID for multiple SSIDs, we
  // lose.
  WiFiEndpointRefPtr endpoint(
      new WiFiEndpoint(control_interface(), this, path, properties, metrics()));
  SLOG(this, 5) << "Found endpoint. "
                << "RPC path: " << path.value() << ", "
                << LogSSID(endpoint->ssid_string()) << ", "
                << "bssid: " << endpoint->bssid_string() << ", "
                << "signal: " << endpoint->signal_strength() << ", "
                << "security: " << endpoint->security_mode() << ", "
                << "frequency: " << endpoint->frequency();

  if (endpoint->ssid_string().empty()) {
    // Don't bother trying to find or create a Service for an Endpoint
    // without an SSID. We wouldn't be able to connect to it anyway.
    return;
  }

  if (endpoint->ssid()[0] == 0) {
    // Assume that an SSID starting with nullptr is bogus/misconfigured,
    // and filter it out.
    return;
  }

  if (endpoint->network_mode().empty()) {
    // Unsupported modes (e.g., ad-hoc) should be ignored.
    return;
  }

  provider_->OnEndpointAdded(endpoint);
  // Adding a single endpoint can change the bgscan parameters for no more than
  // one active Service. Try pending_service_ only if current_service_ doesn't
  // change.
  if ((!current_service_ || !ReconfigureBgscan(current_service_.get())) &&
      pending_service_) {
    ReconfigureBgscan(pending_service_.get());
  }

  // Do this last, to maintain the invariant that any Endpoint we
  // know about has a corresponding Service.
  //
  // TODO(quiche): Write test to verify correct behavior in the case
  // where we get multiple BSSAdded events for a single endpoint.
  // (Old Endpoint's refcount should fall to zero, and old Endpoint
  // should be destroyed.)
  endpoint_by_rpcid_[path] = endpoint;
  endpoint->Start();
}

void WiFi::BSSRemovedTask(const RpcIdentifier& path) {
  EndpointMap::iterator i = endpoint_by_rpcid_.find(path);
  if (i == endpoint_by_rpcid_.end()) {
    SLOG(this, 1) << "WiFi " << link_name() << " could not find BSS "
                  << path.value() << " to remove.";
    return;
  }

  WiFiEndpointRefPtr endpoint = i->second;
  CHECK(endpoint);
  endpoint_by_rpcid_.erase(i);

  WiFiServiceRefPtr service = provider_->OnEndpointRemoved(endpoint);
  if (!service) {
    // Removing a single endpoint can change the bgscan parameters for no more
    // than one active Service. Try pending_service_ only if current_service_
    // doesn't change.
    if ((!current_service_ || !ReconfigureBgscan(current_service_.get())) &&
        pending_service_) {
      ReconfigureBgscan(pending_service_.get());
    }
    return;
  }
  Error unused_error;
  RemoveNetworkForService(service.get(), &unused_error);

  bool disconnect_service = !service->HasEndpoints() &&
                            (service->IsConnecting() || service->IsConnected());

  if (disconnect_service) {
    LOG(INFO) << "Disconnecting from: " << service->log_name()
              << ": BSSRemoved";
    DisconnectFrom(service.get());
  }
}

void WiFi::CertificationTask(const KeyValueStore& properties) {
  // Events may come immediately after Stop().
  if (!enabled()) {
    return;
  }

  if (!current_service_) {
    LOG(ERROR) << "WiFi " << link_name() << " " << __func__
               << " with no current service.";
    return;
  }

  string subject;
  uint32_t depth;
  if (WPASupplicant::ExtractRemoteCertification(properties, &subject, &depth)) {
    current_service_->AddEAPCertification(subject, depth);
  }
}

void WiFi::EAPEventTask(const string& status, const string& parameter) {
  // Events may come immediately after Stop().
  if (!enabled()) {
    return;
  }

  if (!current_service_) {
    LOG(ERROR) << "WiFi " << link_name() << " " << __func__
               << " with no current service.";
    return;
  }
  Service::ConnectFailure failure = Service::kFailureNone;
  eap_state_handler_->ParseStatus(status, parameter, &failure);
  if (failure == Service::kFailurePinMissing) {
    // wpa_supplicant can sometimes forget the PIN on disconnect from the AP.
    const string& pin = current_service_->eap()->pin();
    Error unused_error;
    RpcIdentifier rpcid =
        FindNetworkRpcidForService(current_service_.get(), &unused_error);
    if (!pin.empty() && !rpcid.value().empty()) {
      // We have a PIN configured, so we can provide it back to wpa_supplicant.
      LOG(INFO) << "Re-supplying PIN parameter to wpa_supplicant.";
      supplicant_interface_proxy_->NetworkReply(
          rpcid, WPASupplicant::kEAPRequestedParameterPin, pin);
      failure = Service::kFailureNone;
    }
  }
  if (failure != Service::kFailureNone) {
    // Avoid a reporting failure twice by resetting EAP state handler early.
    eap_state_handler_->Reset();
    pending_eap_failure_ = failure;
  }
}

void WiFi::PropertiesChangedTask(const KeyValueStore& properties) {
  // TODO(quiche): Handle changes in other properties (e.g. signal
  // strength).

  // Note that order matters here. In particular, we want to process
  // changes in the current BSS before changes in state. This is so
  // that we update the state of the correct Endpoint/Service.
  // Also note that events may occur (briefly) after Stop(), so we need to make
  // explicit decisions here on what to do when !enabled().
  if (enabled() && properties.Contains<RpcIdentifier>(
                       WPASupplicant::kInterfacePropertyCurrentBSS)) {
    CurrentBSSChanged(properties.Get<RpcIdentifier>(
        WPASupplicant::kInterfacePropertyCurrentBSS));
  }

  if (properties.Contains<string>(WPASupplicant::kInterfacePropertyState)) {
    StateChanged(
        properties.Get<string>(WPASupplicant::kInterfacePropertyState));

    // These properties should only be updated when there is a state change.
    if (properties.Contains<string>(
            WPASupplicant::kInterfacePropertyCurrentAuthMode)) {
      CurrentAuthModeChanged(properties.Get<string>(
          WPASupplicant::kInterfacePropertyCurrentAuthMode));
    }

    string suffix = GetSuffixFromAuthMode(supplicant_auth_mode_);
    if (!suffix.empty()) {
      if (properties.Contains<int32_t>(
              WPASupplicant::kInterfacePropertyRoamTime)) {
        // Network.Shill.WiFi.RoamTime.{PSK,FTPSK,EAP,FTEAP}
        metrics()->SendToUMA(
            base::StringPrintf("%s.%s", Metrics::kMetricWifiRoamTimePrefix,
                               suffix.c_str()),
            properties.Get<int32_t>(WPASupplicant::kInterfacePropertyRoamTime),
            Metrics::kMetricWifiRoamTimeMillisecondsMin,
            Metrics::kMetricWifiRoamTimeMillisecondsMax,
            Metrics::kMetricWifiRoamTimeNumBuckets);
      }

      if (properties.Contains<bool>(
              WPASupplicant::kInterfacePropertyRoamComplete)) {
        // Network.Shill.WiFi.RoamComplete.{PSK,FTPSK,EAP,FTEAP}
        metrics()->SendEnumToUMA(
            base::StringPrintf("%s.%s", Metrics::kMetricWifiRoamCompletePrefix,
                               suffix.c_str()),
            properties.Get<bool>(WPASupplicant::kInterfacePropertyRoamComplete)
                ? Metrics::kWiFiRoamSuccess
                : Metrics::kWiFiRoamFailure,
            Metrics::kWiFiRoamCompleteMax);
      }

      if (properties.Contains<int32_t>(
              WPASupplicant::kInterfacePropertySessionLength)) {
        // Network.Shill.WiFi.SessionLength.{PSK,FTPSK,EAP,FTEAP}
        metrics()->SendToUMA(
            base::StringPrintf("%s.%s", Metrics::kMetricWifiSessionLengthPrefix,
                               suffix.c_str()),
            properties.Get<int32_t>(
                WPASupplicant::kInterfacePropertySessionLength),
            Metrics::kMetricWifiSessionLengthMillisecondsMin,
            Metrics::kMetricWifiSessionLengthMillisecondsMax,
            Metrics::kMetricWifiSessionLengthNumBuckets);
      }
    }
  }

  if (properties.Contains<int32_t>(
          WPASupplicant::kInterfacePropertyAssocStatusCode)) {
    AssocStatusChanged(properties.Get<int32_t>(
        WPASupplicant::kInterfacePropertyAssocStatusCode));
  }

  if (properties.Contains<int32_t>(
          WPASupplicant::kInterfacePropertyAuthStatusCode)) {
    AuthStatusChanged(properties.Get<int32_t>(
        WPASupplicant::kInterfacePropertyAuthStatusCode));
  }

  if (properties.Contains<int32_t>(
          WPASupplicant::kInterfacePropertyDisconnectReason)) {
    DisconnectReasonChanged(properties.Get<int32_t>(
        WPASupplicant::kInterfacePropertyDisconnectReason));
  }
}

string WiFi::GetSuffixFromAuthMode(const string& auth_mode) const {
  if (auth_mode == WPASupplicant::kAuthModeWPAPSK ||
      auth_mode == WPASupplicant::kAuthModeWPA2PSK ||
      auth_mode == WPASupplicant::kAuthModeBothPSK) {
    return Metrics::kMetricWifiPSKSuffix;
  } else if (auth_mode == WPASupplicant::kAuthModeFTPSK) {
    return Metrics::kMetricWifiFTPSKSuffix;
  } else if (auth_mode == WPASupplicant::kAuthModeFTEAP) {
    return Metrics::kMetricWifiFTEAPSuffix;
  } else if (base::StartsWith(auth_mode, WPASupplicant::kAuthModeEAPPrefix,
                              base::CompareCase::SENSITIVE)) {
    return Metrics::kMetricWifiEAPSuffix;
  }
  return "";
}

void WiFi::ScanDoneTask() {
  SLOG(this, 2) << __func__ << " need_bss_flush_ " << need_bss_flush_;
  // Unsets this flag if it was set in InitiateScanInDarkResume since that scan
  // has completed.
  manager()->set_suppress_autoconnect(false);
  if (wake_on_wifi_) {
    wake_on_wifi_->OnScanCompleted();
  }
  // Post |UpdateScanStateAfterScanDone| so it runs after any pending scan
  // results have been processed.  This allows connections on new BSSes to be
  // started before we decide whether the scan was fruitful.
  dispatcher()->PostTask(FROM_HERE,
                         Bind(&WiFi::UpdateScanStateAfterScanDone,
                              weak_ptr_factory_while_started_.GetWeakPtr()));
  if (wake_on_wifi_ && (provider_->NumAutoConnectableServices() < 1) &&
      IsIdle()) {
    // Ensure we are also idle in case we are in the midst of connecting to
    // the only service that was available for auto-connect on the previous
    // scan (which will cause it to show up as unavailable for auto-connect
    // when we query the WiFiProvider this time).
    wake_on_wifi_->OnNoAutoConnectableServicesAfterScan(
        provider_->GetSsidsConfiguredForAutoConnect(),
        Bind(&WiFi::RemoveSupplicantNetworks,
             weak_ptr_factory_while_started_.GetWeakPtr()),
        Bind(&WiFi::TriggerPassiveScan,
             weak_ptr_factory_while_started_.GetWeakPtr()));
  }
  if (need_bss_flush_) {
    CHECK(supplicant_interface_proxy_);
    // Compute |max_age| relative to |resumed_at_|, to account for the
    // time taken to scan.
    struct timeval now;
    uint32_t max_age;
    time_->GetTimeMonotonic(&now);
    max_age = kMaxBSSResumeAgeSeconds + (now.tv_sec - resumed_at_.tv_sec);
    supplicant_interface_proxy_->FlushBSS(max_age);
    need_bss_flush_ = false;
  }
  StartScanTimer();
}

void WiFi::ScanFailedTask() {
  SLOG(this, 2) << __func__;
  SetScanState(kScanIdle, kScanMethodNone, __func__);
}

void WiFi::UpdateScanStateAfterScanDone() {
  if (scan_method_ == kScanMethodFull) {
    // Only notify the Manager on completion of full scans, since the manager
    // will replace any cached geolocation info with the BSSes we have right
    // now.
    manager()->OnDeviceGeolocationInfoUpdated(this);
  }
  if (scan_state_ == kScanBackgroundScanning) {
    // Going directly to kScanIdle (instead of to kScanFoundNothing) inhibits
    // some UMA reporting in SetScanState.  That's desired -- we don't want
    // to report background scan results to UMA since the drivers may play
    // background scans over a longer period in order to not interfere with
    // traffic.
    SetScanState(kScanIdle, kScanMethodNone, __func__);
  } else if (scan_state_ != kScanIdle && IsIdle()) {
    SetScanState(kScanFoundNothing, scan_method_, __func__);
  }
}

void WiFi::ScanTask() {
  SLOG(this, 2) << "WiFi " << link_name() << " scan requested.";
  if (!enabled()) {
    SLOG(this, 2) << "Ignoring scan request while device is not enabled.";
    SetScanState(kScanIdle, kScanMethodNone, __func__);  // Probably redundant.
    return;
  }
  if (!supplicant_present_ || !supplicant_interface_proxy_.get()) {
    SLOG(this, 2) << "Ignoring scan request while supplicant is not present.";
    SetScanState(kScanIdle, kScanMethodNone, __func__);
    return;
  }
  if ((pending_service_.get() && pending_service_->IsConnecting()) ||
      (current_service_.get() && current_service_->IsConnecting())) {
    SLOG(this, 2) << "Ignoring scan request while connecting to an AP.";
    return;
  }
  KeyValueStore scan_args;
  scan_args.Set<string>(WPASupplicant::kPropertyScanType,
                        WPASupplicant::kScanTypeActive);

  ByteArrays hidden_ssids = provider_->GetHiddenSSIDList();
  if (!hidden_ssids.empty()) {
    // TODO(pstew): Devise a better method for time-sharing with SSIDs that do
    // not fit in.
    if (hidden_ssids.size() >= WPASupplicant::kScanMaxSSIDsPerScan) {
      hidden_ssids.erase(
          hidden_ssids.begin() + WPASupplicant::kScanMaxSSIDsPerScan - 1,
          hidden_ssids.end());
    }
    // Add Broadcast SSID, signified by an empty ByteArray.  If we specify
    // SSIDs to wpa_supplicant, we need to explicitly specify the default
    // behavior of doing a broadcast probe.
    hidden_ssids.push_back(ByteArray());

    scan_args.Set<ByteArrays>(WPASupplicant::kPropertyScanSSIDs, hidden_ssids);
  }

  if (!supplicant_interface_proxy_->Scan(scan_args)) {
    // A scan may fail if, for example, the wpa_supplicant vanishing
    // notification is posted after this task has already started running.
    LOG(WARNING) << "Scan failed";
    return;
  }

  // Only set the scan state/method if we are starting a full scan from
  // scratch.
  if (scan_state_ != kScanScanning) {
    SetScanState(IsIdle() ? kScanScanning : kScanBackgroundScanning,
                 kScanMethodFull, __func__);
  }
}

string WiFi::GetServiceLeaseName(const WiFiService& service) {
  return service.GetStorageIdentifier();
}

const WiFiEndpointConstRefPtr WiFi::GetCurrentEndpoint() const {
  EndpointMap::const_iterator endpoint_it =
      endpoint_by_rpcid_.find(supplicant_bss_);
  if (endpoint_it == endpoint_by_rpcid_.end()) {
    return nullptr;
  }

  return endpoint_it->second.get();
}

void WiFi::DestroyServiceLease(const WiFiService& service) {
  DestroyIPConfigLease(GetServiceLeaseName(service));
}

void WiFi::StateChanged(const string& new_state) {
  const string old_state = supplicant_state_;
  supplicant_state_ = new_state;
  LOG(INFO) << "WiFi " << link_name() << " " << __func__ << " " << old_state
            << " -> " << new_state;

  if (old_state == WPASupplicant::kInterfaceStateDisconnected &&
      new_state != WPASupplicant::kInterfaceStateDisconnected) {
    // The state has been changed from disconnect to something else, clearing
    // out disconnect reason to avoid confusion about future disconnects.
    SLOG(this, 3) << "WiFi clearing DisconnectReason for " << link_name();
    supplicant_disconnect_reason_ = IEEE_80211::kReasonCodeInvalid;
  }

  // Identify the service to which the state change applies. If
  // |pending_service_| is non-NULL, then the state change applies to
  // |pending_service_|. Otherwise, it applies to |current_service_|.
  //
  // This policy is driven by the fact that the |pending_service_|
  // doesn't become the |current_service_| until wpa_supplicant
  // reports a CurrentBSS change to the |pending_service_|. And the
  // CurrentBSS change won't be reported until the |pending_service_|
  // reaches the WPASupplicant::kInterfaceStateCompleted state.
  WiFiService* affected_service =
      pending_service_.get() ? pending_service_.get() : current_service_.get();
  if (!affected_service) {
    SLOG(this, 2) << "WiFi " << link_name() << " " << __func__
                  << " with no service";
    return;
  }

  if (new_state == WPASupplicant::kInterfaceStateCompleted) {
    if (affected_service->IsConnected()) {
      StopReconnectTimer();
      if (is_roaming_in_progress_) {
        // This means wpa_supplicant completed a roam without an intervening
        // disconnect. We should renew our DHCP lease just in case the new
        // AP is on a different subnet than where we started.
        // TODO(matthewmwang): Handle the IPv6 roam case.
        is_roaming_in_progress_ = false;
        if (ipconfig()) {
          LOG(INFO) << link_name() << " renewing L3 configuration after roam.";
          ipconfig()->RenewIP();
          affected_service->SetRoamState(Service::kRoamStateConfiguring);
        }
      } else if (affected_service->is_rekey_in_progress()) {
        affected_service->SetIsRekeyInProgress(false);
        LOG(INFO) << link_name()
                  << " EAP re-key complete. No need to renew L3 configuration.";
      }
    } else if (has_already_completed_) {
      LOG(INFO) << link_name() << " L3 configuration already started.";
    } else {
      if (AcquireIPConfigWithLeaseName(
              GetServiceLeaseName(*affected_service))) {
        LOG(INFO) << link_name() << " is up; started L3 configuration.";
        affected_service->SetState(Service::kStateConfiguring);
        if (affected_service->IsSecurityMatch(kSecurityWep)) {
          // With the overwhelming majority of WEP networks, we cannot assume
          // our credentials are correct just because we have successfully
          // connected.  It is more useful to track received data as the L3
          // configuration proceeds to see if we can decrypt anything.
          receive_byte_count_at_connect_ = GetReceiveByteCount();
        } else {
          affected_service->ResetSuspectedCredentialFailures();
        }
      } else {
        LOG(ERROR) << "Unable to acquire DHCP config.";
      }
    }
    has_already_completed_ = true;
  } else if (new_state == WPASupplicant::kInterfaceStateAuthenticating ||
             new_state == WPASupplicant::kInterfaceStateAssociating ||
             new_state == WPASupplicant::kInterfaceStateAssociated ||
             new_state == WPASupplicant::kInterfaceState4WayHandshake ||
             new_state == WPASupplicant::kInterfaceStateGroupHandshake) {
    if (new_state == WPASupplicant::kInterfaceStateAssociating) {
      // Ensure auth status is kept up-to-date
      supplicant_auth_status_ = IEEE_80211::kStatusCodeSuccessful;
    } else if (new_state == WPASupplicant::kInterfaceStateAssociated) {
      // Supplicant does not indicate successful association in assoc status
      // messages, but we know at this point that 802.11 association succeeded
      supplicant_assoc_status_ = IEEE_80211::kStatusCodeSuccessful;
    }

    if (is_roaming_in_progress_) {
      // Instead of transitioning into the associating state and potentially
      // reordering the service list, set the roam state to keep track of the
      // actual state.
      affected_service->SetRoamState(Service::kRoamStateAssociating);
    } else if (!affected_service->is_rekey_in_progress()) {
      // Ignore transitions into these states when roaming is in progress, to
      // avoid bothering the user when roaming, or re-keying.
      if (old_state == WPASupplicant::kInterfaceStateCompleted) {
        // Shill gets EAP events when a re-key happens in an 802.1X network, but
        // nothing when it happens in a PSK network. Unless roaming is in
        // progress, we assume supplicant state transitions from completed to an
        // auth/assoc state are a result of a re-key.
        affected_service->SetIsRekeyInProgress(true);
      } else {
        affected_service->SetState(Service::kStateAssociating);
      }
    }
    // TODO(quiche): On backwards transitions, we should probably set
    // a timeout for getting back into the completed state. At present,
    // we depend on wpa_supplicant eventually reporting that CurrentBSS
    // has changed. But there may be cases where that signal is not sent.
    // (crbug.com/206208)
  } else if (new_state == WPASupplicant::kInterfaceStateDisconnected &&
             affected_service == current_service_ &&
             affected_service->IsConnected()) {
    // This means that wpa_supplicant failed in a re-connect attempt, but
    // may still be reconnecting.  Give wpa_supplicant a limited amount of
    // time to transition out this condition by either connecting or changing
    // CurrentBSS.
    StartReconnectTimer();
  } else {
    // Other transitions do not affect Service state.
    //
    // Note in particular that we ignore a State change into
    // kInterfaceStateDisconnected, in favor of observing the corresponding
    // change in CurrentBSS.
  }
}

bool WiFi::SuspectCredentials(WiFiServiceRefPtr service,
                              Service::ConnectFailure* failure) const {
  if (service->IsSecurityMatch(kSecurityPsk)) {
    if (supplicant_state_ == WPASupplicant::kInterfaceState4WayHandshake &&
        service->AddSuspectedCredentialFailure()) {
      if (failure) {
        *failure = Service::kFailureBadPassphrase;
      }
      return true;
    }
  } else if (service->IsSecurityMatch(kSecurity8021x)) {
    if (eap_state_handler_->is_eap_in_progress() &&
        service->AddSuspectedCredentialFailure()) {
      if (failure) {
        *failure = Service::kFailureEAPAuthentication;
      }
      return true;
    }
  }

  return false;
}

// static
bool WiFi::SanitizeSSID(string* ssid) {
  CHECK(ssid);

  size_t ssid_len = ssid->length();
  size_t i;
  bool changed = false;

  for (i = 0; i < ssid_len; ++i) {
    if (!IsPrintableAsciiChar((*ssid)[i])) {
      (*ssid)[i] = '?';
      changed = true;
    }
  }

  return changed;
}

// static
string WiFi::LogSSID(const string& ssid) {
  string out;
  for (const auto& chr : ssid) {
    // Replace '[' and ']' (in addition to non-printable characters) so that
    // it's easy to match the right substring through a non-greedy regex.
    if (chr == '[' || chr == ']' || !IsPrintableAsciiChar(chr)) {
      base::StringAppendF(&out, "\\x%02x", chr);
    } else {
      out += chr;
    }
  }
  return StringPrintf("[SSID=%s]", out.c_str());
}

void WiFi::OnLinkMonitorFailure() {
  // Invoke base class call first to allow it to determine the reliability of
  // the link.
  Device::OnLinkMonitorFailure();

  // If we have never found the gateway, let's be conservative and not
  // do anything, in case this network topology does not have a gateway.
  if (!link_monitor()->IsGatewayFound()) {
    LOG(INFO) << "In " << __func__ << "(): "
              << "Skipping reassociate since gateway was never found.";
    return;
  }

  if (!supplicant_present_) {
    LOG(ERROR) << "In " << __func__ << "(): "
               << "wpa_supplicant is not present.  Cannot reassociate.";
    return;
  }

  // Skip reassociate attempt if service is not reliable, meaning multiple link
  // failures in short period of time.
  if (current_service_->unreliable()) {
    LOG(INFO) << "Current service is unreliable, skipping reassociate attempt.";
    return;
  }

  // This will force a transition out of connected, if we are actually
  // connected.
  if (!supplicant_interface_proxy_->Reattach()) {
    LOG(ERROR) << "In " << __func__ << "(): failed to call Reattach().";
    return;
  }

  // If we don't eventually get a transition back into a connected state,
  // there is something wrong.
  StartReconnectTimer();
  LOG(INFO) << "In " << __func__ << "(): Called Reattach().";
}

bool WiFi::ShouldUseArpGateway() const {
  return !IsUsingStaticIP();
}

void WiFi::DisassociateFromService(const WiFiServiceRefPtr& service) {
  SLOG(this, 2) << "In " << __func__ << " for service: " << service->log_name();
  DisconnectFromIfActive(service.get());
  if (service == selected_service()) {
    DropConnection();
  }
  Error unused_error;
  RemoveNetworkForService(service.get(), &unused_error);
}

vector<GeolocationInfo> WiFi::GetGeolocationObjects() const {
  vector<GeolocationInfo> objects;
  for (const auto& endpoint_entry : endpoint_by_rpcid_) {
    GeolocationInfo geoinfo;
    const WiFiEndpointRefPtr& endpoint = endpoint_entry.second;
    geoinfo[kGeoMacAddressProperty] = endpoint->bssid_string();
    geoinfo[kGeoSignalStrengthProperty] =
        StringPrintf("%d", endpoint->signal_strength());
    geoinfo[kGeoChannelProperty] = StringPrintf(
        "%d", Metrics::WiFiFrequencyToChannel(endpoint->frequency()));
    AddLastSeenTime(&geoinfo, endpoint->last_seen());
    objects.push_back(geoinfo);
  }
  return objects;
}

void WiFi::HelpRegisterDerivedInt32(PropertyStore* store,
                                    const string& name,
                                    int32_t (WiFi::*get)(Error* error),
                                    bool (WiFi::*set)(const int32_t& value,
                                                      Error* error)) {
  store->RegisterDerivedInt32(
      name, Int32Accessor(new CustomAccessor<WiFi, int32_t>(this, get, set)));
}

void WiFi::HelpRegisterDerivedUint16(PropertyStore* store,
                                     const string& name,
                                     uint16_t (WiFi::*get)(Error* error),
                                     bool (WiFi::*set)(const uint16_t& value,
                                                       Error* error)) {
  store->RegisterDerivedUint16(
      name, Uint16Accessor(new CustomAccessor<WiFi, uint16_t>(this, get, set)));
}

void WiFi::HelpRegisterDerivedBool(PropertyStore* store,
                                   const string& name,
                                   bool (WiFi::*get)(Error* error),
                                   bool (WiFi::*set)(const bool& value,
                                                     Error* error)) {
  store->RegisterDerivedBool(
      name, BoolAccessor(new CustomAccessor<WiFi, bool>(this, get, set)));
}

void WiFi::HelpRegisterConstDerivedBool(PropertyStore* store,
                                        const string& name,
                                        bool (WiFi::*get)(Error* error)) {
  store->RegisterDerivedBool(
      name, BoolAccessor(new CustomAccessor<WiFi, bool>(this, get, nullptr)));
}

void WiFi::HelpRegisterConstDerivedUint16s(PropertyStore* store,
                                           const std::string& name,
                                           Uint16s (WiFi::*get)(Error* error)) {
  store->RegisterDerivedUint16s(
      name,
      Uint16sAccessor(new CustomAccessor<WiFi, Uint16s>(this, get, nullptr)));
}

void WiFi::OnBeforeSuspend(const ResultCallback& callback) {
  if (!enabled()) {
    callback.Run(Error(Error::kSuccess));
    return;
  }
  LOG(INFO) << __func__ << ": "
            << (IsConnectedToCurrentService() ? "connected" : "not connected");
  StopScanTimer();
  supplicant_process_proxy()->ExpectDisconnect();
  if (!wake_on_wifi_) {
    callback.Run(Error(Error::kSuccess));
    return;
  }
  uint32_t time_to_next_lease_renewal;
  bool have_dhcp_lease =
      TimeToNextDHCPLeaseRenewal(&time_to_next_lease_renewal);
  wake_on_wifi_->OnBeforeSuspend(
      IsConnectedToCurrentService(),
      provider_->GetSsidsConfiguredForAutoConnect(), callback,
      Bind(&Device::RenewDHCPLease,
           weak_ptr_factory_while_started_.GetWeakPtr(), false, nullptr),
      Bind(&WiFi::RemoveSupplicantNetworks,
           weak_ptr_factory_while_started_.GetWeakPtr()),
      have_dhcp_lease, time_to_next_lease_renewal);
}

void WiFi::OnDarkResume(const ResultCallback& callback) {
  if (!enabled()) {
    callback.Run(Error(Error::kSuccess));
    return;
  }
  LOG(INFO) << __func__ << ": "
            << (IsConnectedToCurrentService() ? "connected" : "not connected");
  StopScanTimer();
  if (!wake_on_wifi_) {
    callback.Run(Error(Error::kSuccess));
    return;
  }
  wake_on_wifi_->OnDarkResume(
      IsConnectedToCurrentService(),
      provider_->GetSsidsConfiguredForAutoConnect(), callback,
      Bind(&Device::RenewDHCPLease,
           weak_ptr_factory_while_started_.GetWeakPtr(), false, nullptr),
      Bind(&WiFi::InitiateScanInDarkResume,
           weak_ptr_factory_while_started_.GetWeakPtr()),
      Bind(&WiFi::RemoveSupplicantNetworks,
           weak_ptr_factory_while_started_.GetWeakPtr()));
}

void WiFi::OnAfterResume() {
  LOG(INFO) << __func__ << ": "
            << (IsConnectedToCurrentService() ? "connected" : "not connected")
            << ", " << (enabled() ? "enabled" : "disabled");
  Device::OnAfterResume();  // May refresh ipconfig_
  // We let the Device class do its thing, but we did nothing in
  // OnBeforeSuspend(), so why undo anything now?
  if (!enabled()) {
    return;
  }
  dispatcher()->PostDelayedTask(
      FROM_HERE,
      Bind(&WiFi::ReportConnectedToServiceAfterWake,
           weak_ptr_factory_while_started_.GetWeakPtr()),
      kPostWakeConnectivityReportDelayMilliseconds);
  if (wake_on_wifi_) {
    wake_on_wifi_->OnAfterResume();
  }

  // We want to flush the BSS cache, but we don't want to conflict
  // with an active connection attempt. So record the need to flush,
  // and take care of flushing when the next scan completes.
  //
  // Note that supplicant will automatically expire old cache
  // entries (after, e.g., a BSS is not found in two consecutive
  // scans). However, our explicit flush accelerates re-association
  // in cases where a BSS disappeared while we were asleep. (See,
  // e.g. WiFiRoaming.005SuspendRoam.)
  time_->GetTimeMonotonic(&resumed_at_);
  need_bss_flush_ = true;

  if (!IsConnectedToCurrentService()) {
    InitiateScan();
  }

  // Since we stopped the scan timer before suspending, start it again here.
  StartScanTimer();
}

void WiFi::AbortScan() {
  SetScanState(kScanIdle, kScanMethodNone, __func__);
}

void WiFi::InitiateScan() {
  LOG(INFO) << __func__;
  // Abort any current scan (at the shill-level; let any request that's
  // already gone out finish) since we don't know when it started.
  AbortScan();

  if (IsIdle()) {
    // Not scanning/connecting/connected, so let's get things rolling.
    Scan(nullptr, __func__);
    RestartFastScanAttempts();
  } else {
    SLOG(this, 1) << __func__
                  << " skipping scan, already connecting or connected.";
  }
}

void WiFi::InitiateScanInDarkResume(const FreqSet& freqs) {
  LOG(INFO) << __func__;
  AbortScan();
  if (!IsIdle()) {
    SLOG(this, 1) << __func__
                  << " skipping scan, already connecting or connected.";
    return;
  }

  CHECK(supplicant_interface_proxy_);
  // Force complete flush of BSS cache since we want WPA supplicant and shill to
  // have an accurate view of what endpoints are available in dark resume. This
  // prevents either from performing incorrect actions that can prolong dark
  // resume (e.g. attempting to auto-connect to a WiFi service whose endpoint
  // disappeared before the dark resume).
  if (!supplicant_interface_proxy_->FlushBSS(0)) {
    LOG(WARNING) << __func__ << ": Failed to flush wpa_supplicant BSS cache";
  }
  // Suppress any autoconnect attempts until this scan is done and endpoints
  // are updated.
  manager()->set_suppress_autoconnect(true);

  TriggerPassiveScan(freqs);
}

void WiFi::TriggerPassiveScan(const FreqSet& freqs) {
  LOG(INFO) << __func__;
  TriggerScanMessage trigger_scan;
  trigger_scan.attributes()->SetU32AttributeValue(NL80211_ATTR_IFINDEX,
                                                  interface_index());
  if (!freqs.empty()) {
    SLOG(this, 3) << __func__ << ": "
                  << "Scanning on specific channels";
    trigger_scan.attributes()->CreateNl80211Attribute(
        NL80211_ATTR_SCAN_FREQUENCIES, NetlinkMessage::MessageContext());

    AttributeListRefPtr frequency_list;
    if (!trigger_scan.attributes()->GetNestedAttributeList(
            NL80211_ATTR_SCAN_FREQUENCIES, &frequency_list) ||
        !frequency_list) {
      LOG(ERROR) << __func__ << ": "
                 << "Couldn't get NL80211_ATTR_SCAN_FREQUENCIES";
    }
    trigger_scan.attributes()->SetNestedAttributeHasAValue(
        NL80211_ATTR_SCAN_FREQUENCIES);

    string attribute_name;
    int i = 0;
    for (uint32_t freq : freqs) {
      SLOG(this, 7) << __func__ << ": "
                    << "Frequency-" << i << ": " << freq;
      attribute_name = StringPrintf("Frequency-%d", i);
      frequency_list->CreateU32Attribute(i, attribute_name.c_str());
      frequency_list->SetU32AttributeValue(i, freq);
      ++i;
    }
  }

  netlink_manager_->SendNl80211Message(
      &trigger_scan,
      Bind(&WiFi::OnTriggerPassiveScanResponse,
           weak_ptr_factory_while_started_.GetWeakPtr()),
      Bind(&NetlinkManager::OnAckDoNothing),
      Bind(&NetlinkManager::OnNetlinkMessageError));
}

void WiFi::OnConnected() {
  Device::OnConnected();
  if (current_service_ && current_service_->IsSecurityMatch(kSecurityWep)) {
    // With a WEP network, we are now reasonably certain the credentials are
    // correct, whereas with other network types we were able to determine
    // this earlier when the association process succeeded.
    current_service_->ResetSuspectedCredentialFailures();
  }
  RequestStationInfo();
}

void WiFi::OnIPConfigFailure() {
  if (!current_service_) {
    LOG(ERROR) << "WiFi " << link_name() << " " << __func__
               << " with no current service.";
    return;
  }
  if (current_service_->IsSecurityMatch(kSecurityWep) &&
      GetReceiveByteCount() == receive_byte_count_at_connect_ &&
      current_service_->AddSuspectedCredentialFailure()) {
    // If we've connected to a WEP network and haven't successfully
    // decrypted any bytes at all during the configuration process,
    // it is fair to suspect that our credentials to this network
    // may not be correct.
    Error error;
    current_service_->DisconnectWithFailure(Service::kFailureBadPassphrase,
                                            &error, __func__);
    return;
  }

  Device::OnIPConfigFailure();
}

void WiFi::AddWakeOnPacketConnection(const string& ip_endpoint, Error* error) {
  if (wake_on_wifi_) {
    wake_on_wifi_->AddWakeOnPacketConnection(ip_endpoint, error);
  } else {
    Error::PopulateAndLog(FROM_HERE, error, Error::kNotSupported,
                          kWakeOnWiFiNotSupported);
  }
}

void WiFi::AddWakeOnPacketOfTypes(const std::vector<std::string>& packet_types,
                                  Error* error) {
  if (wake_on_wifi_) {
    wake_on_wifi_->AddWakeOnPacketOfTypes(packet_types, error);
  } else {
    Error::PopulateAndLog(FROM_HERE, error, Error::kNotSupported,
                          kWakeOnWiFiNotSupported);
  }
}

void WiFi::RemoveWakeOnPacketConnection(const string& ip_endpoint,
                                        Error* error) {
  if (wake_on_wifi_) {
    wake_on_wifi_->RemoveWakeOnPacketConnection(ip_endpoint, error);
  } else {
    Error::PopulateAndLog(FROM_HERE, error, Error::kNotSupported,
                          kWakeOnWiFiNotSupported);
  }
}

void WiFi::RemoveWakeOnPacketOfTypes(
    const std::vector<std::string>& packet_types, Error* error) {
  if (wake_on_wifi_) {
    wake_on_wifi_->RemoveWakeOnPacketOfTypes(packet_types, error);
  } else {
    Error::PopulateAndLog(FROM_HERE, error, Error::kNotSupported,
                          kWakeOnWiFiNotSupported);
  }
}

void WiFi::RemoveAllWakeOnPacketConnections(Error* error) {
  if (wake_on_wifi_) {
    wake_on_wifi_->RemoveAllWakeOnPacketConnections(error);
  } else {
    Error::PopulateAndLog(FROM_HERE, error, Error::kNotSupported,
                          kWakeOnWiFiNotSupported);
  }
}

void WiFi::RestartFastScanAttempts() {
  if (!enabled()) {
    SLOG(this, 2) << "Skpping fast scan attempts while not enabled.";
    return;
  }
  fast_scans_remaining_ = kNumFastScanAttempts;
  StartScanTimer();
}

void WiFi::StartScanTimer() {
  SLOG(this, 2) << __func__;
  if (scan_interval_seconds_ == 0) {
    StopScanTimer();
    return;
  }
  scan_timer_callback_.Reset(Bind(
      &WiFi::ScanTimerHandler, weak_ptr_factory_while_started_.GetWeakPtr()));
  // Repeat the first few scans after disconnect relatively quickly so we
  // have reasonable trust that no APs we are looking for are present.
  size_t wait_time_milliseconds = fast_scans_remaining_ > 0
                                      ? kFastScanIntervalSeconds * 1000
                                      : scan_interval_seconds_ * 1000;
  dispatcher()->PostDelayedTask(FROM_HERE, scan_timer_callback_.callback(),
                                wait_time_milliseconds);
  SLOG(this, 5) << "Next scan scheduled for " << wait_time_milliseconds << "ms";
}

void WiFi::StopScanTimer() {
  SLOG(this, 2) << __func__;
  scan_timer_callback_.Cancel();
}

void WiFi::ScanTimerHandler() {
  SLOG(this, 2) << "WiFi Device " << link_name() << ": " << __func__;
  if (manager()->IsSuspending()) {
    SLOG(this, 5) << "Not scanning: still in suspend";
    return;
  }
  if (scan_state_ == kScanIdle && IsIdle()) {
    Scan(nullptr, __func__);
    if (fast_scans_remaining_ > 0) {
      --fast_scans_remaining_;
    }
  } else {
    if (scan_state_ != kScanIdle) {
      SLOG(this, 5) << "Skipping scan: scan_state_ is " << scan_state_;
    }
    if (current_service_) {
      SLOG(this, 5) << "Skipping scan: current_service_ is service "
                    << current_service_->log_name();
    }
    if (pending_service_) {
      SLOG(this, 5) << "Skipping scan: pending_service_ is service"
                    << pending_service_->log_name();
    }
  }
  StartScanTimer();
}

void WiFi::StartPendingTimer() {
  pending_timeout_callback_.Reset(
      Bind(&WiFi::PendingTimeoutHandler,
           weak_ptr_factory_while_started_.GetWeakPtr()));
  dispatcher()->PostDelayedTask(FROM_HERE, pending_timeout_callback_.callback(),
                                kPendingTimeoutSeconds * 1000);
}

void WiFi::StopPendingTimer() {
  SLOG(this, 2) << "WiFi Device " << link_name() << ": " << __func__;
  pending_timeout_callback_.Cancel();
}

void WiFi::SetPendingService(const WiFiServiceRefPtr& service) {
  SLOG(this, 2) << "WiFi " << link_name() << " setting pending service to "
                << (service ? service->log_name() : "<none>");
  if (service) {
    SetScanState(kScanConnecting, scan_method_, __func__);
    service->SetState(Service::kStateAssociating);
    StartPendingTimer();
  } else {
    // SetPendingService(nullptr) is called in the following cases:
    //  a) |ConnectTo|->|DisconnectFrom|.  Connecting to a service, disconnect
    //     the old service (scan_state_ == kScanTransitionToConnecting).  No
    //     state transition is needed here.
    //  b) |HandleRoam|.  Connected to a service, it's no longer pending
    //     (scan_state_ == kScanIdle).  No state transition is needed here.
    //  c) |DisconnectFrom| and |HandleDisconnect|. Disconnected/disconnecting
    //     from a service not during a scan (scan_state_ == kScanIdle).  No
    //     state transition is needed here.
    //  d) |DisconnectFrom| and |HandleDisconnect|. Disconnected/disconnecting
    //     from a service during a scan (scan_state_ == kScanScanning or
    //     kScanConnecting).  This is an odd case -- let's discard any
    //     statistics we're gathering by transitioning directly into kScanIdle.
    if (scan_state_ == kScanScanning ||
        scan_state_ == kScanBackgroundScanning ||
        scan_state_ == kScanConnecting) {
      SetScanState(kScanIdle, kScanMethodNone, __func__);
    }
    if (pending_service_) {
      StopPendingTimer();
    }
  }
  pending_service_ = service;
}

void WiFi::PendingTimeoutHandler() {
  Error unused_error;
  LOG(INFO) << "WiFi Device " << link_name() << ": " << __func__;
  CHECK(pending_service_);
  SetScanState(kScanFoundNothing, scan_method_, __func__);
  WiFiServiceRefPtr pending_service = pending_service_;

  SLOG(this, 4) << "Supplicant authentication status: "
                << supplicant_auth_status_;
  SLOG(this, 4) << "Supplicant association status: "
                << supplicant_assoc_status_;

  Service::ConnectFailure failure = ExamineStatusCodes();
  if (failure == Service::kFailureUnknown && pending_service_ &&
      pending_service_->SignalLevel() <= disconnect_threshold_dbm_ &&
      pending_service_->SignalLevel() != kDefaultDisconnectDbm) {
    failure = Service::kFailureOutOfRange;
  }
  pending_service_->DisconnectWithFailure(failure, &unused_error, __func__);

  // A hidden service may have no endpoints, since wpa_supplicant
  // failed to attain a CurrentBSS.  If so, the service has no
  // reference to |this| device and cannot call WiFi::DisconnectFrom()
  // to reset pending_service_.  In this case, we must perform the
  // disconnect here ourselves.
  if (pending_service_) {
    CHECK(!pending_service_->HasEndpoints());
    LOG(INFO) << "Hidden service was not found.";
    DisconnectFrom(pending_service_.get());
  }

  // DisconnectWithFailure will leave the pending service's state in failure
  // state. Reset its state back to idle, to allow it to be connectable again.
  pending_service->SetState(Service::kStateIdle);
}

void WiFi::StartReconnectTimer() {
  if (!reconnect_timeout_callback_.IsCancelled()) {
    LOG(INFO) << "WiFi Device " << link_name() << ": " << __func__
              << ": reconnect timer already running.";
    return;
  }
  LOG(INFO) << "WiFi Device " << link_name() << ": " << __func__;
  reconnect_timeout_callback_.Reset(
      Bind(&WiFi::ReconnectTimeoutHandler,
           weak_ptr_factory_while_started_.GetWeakPtr()));
  dispatcher()->PostDelayedTask(FROM_HERE,
                                reconnect_timeout_callback_.callback(),
                                kReconnectTimeoutSeconds * 1000);
}

void WiFi::StopReconnectTimer() {
  SLOG(this, 2) << "WiFi Device " << link_name() << ": " << __func__;
  reconnect_timeout_callback_.Cancel();
}

void WiFi::ReconnectTimeoutHandler() {
  LOG(INFO) << "WiFi Device " << link_name() << ": " << __func__;
  reconnect_timeout_callback_.Cancel();
  CHECK(current_service_);
  current_service_->SetFailure(Service::kFailureConnect);
  DisconnectFrom(current_service_.get());
}

void WiFi::OnSupplicantPresence(bool present) {
  LOG(INFO) << "WPA supplicant presence changed: " << present;

  if (present) {
    if (supplicant_present_) {
      // Restart the WiFi device if it's started already. This will reset the
      // state and connect the device to the new WPA supplicant instance.
      if (enabled()) {
        Restart();
      }
      return;
    }
    supplicant_present_ = true;
    ConnectToSupplicant();
    return;
  }

  if (!supplicant_present_) {
    return;
  }
  supplicant_present_ = false;
  // Restart the WiFi device if it's started already. This will effectively
  // suspend the device until the WPA supplicant reappears.
  if (enabled()) {
    Restart();
  }
}

void WiFi::OnWiFiDebugScopeChanged(bool enabled) {
  SLOG(this, 2) << "WiFi debug scope changed; enable is now " << enabled;
  if (!Device::enabled() || !supplicant_present_) {
    SLOG(this, 2) << "Supplicant process proxy not connected.";
    return;
  }
  string current_level;
  if (!supplicant_process_proxy()->GetDebugLevel(&current_level)) {
    LOG(ERROR) << __func__ << ": Failed to get wpa_supplicant debug level.";
    return;
  }

  if (current_level != WPASupplicant::kDebugLevelInfo &&
      current_level != WPASupplicant::kDebugLevelDebug) {
    SLOG(this, 2) << "WiFi debug level is currently " << current_level
                  << "; assuming that it is being controlled elsewhere.";
    return;
  }
  string new_level = enabled ? WPASupplicant::kDebugLevelDebug
                             : WPASupplicant::kDebugLevelInfo;

  if (new_level == current_level) {
    SLOG(this, 2) << "WiFi debug level is already the desired level "
                  << current_level;
    return;
  }

  if (!supplicant_process_proxy()->SetDebugLevel(new_level)) {
    LOG(ERROR) << __func__ << ": Failed to set wpa_supplicant debug level.";
  }
}

void WiFi::SetConnectionDebugging(bool enabled) {
  if (is_debugging_connection_ == enabled) {
    return;
  }
  OnWiFiDebugScopeChanged(enabled || ScopeLogger::GetInstance()->IsScopeEnabled(
                                         ScopeLogger::kWiFi));
  is_debugging_connection_ = enabled;
}

void WiFi::SetSupplicantInterfaceProxy(
    std::unique_ptr<SupplicantInterfaceProxyInterface> proxy) {
  if (proxy) {
    supplicant_interface_proxy_ = std::move(proxy);
  } else {
    supplicant_interface_proxy_.reset();
  }
}

void WiFi::ConnectToSupplicant() {
  LOG(INFO) << link_name() << ": " << (enabled() ? "enabled" : "disabled")
            << " supplicant: " << (supplicant_present_ ? "present" : "absent")
            << " proxy: "
            << (supplicant_interface_proxy_.get() ? "non-null" : "null");
  if (!enabled() || !supplicant_present_) {
    return;
  }
  OnWiFiDebugScopeChanged(
      ScopeLogger::GetInstance()->IsScopeEnabled(ScopeLogger::kWiFi));

  RpcIdentifier previous_supplicant_interface_path(supplicant_interface_path_);

  KeyValueStore create_interface_args;
  create_interface_args.Set<string>(WPASupplicant::kInterfacePropertyName,
                                    link_name());
  create_interface_args.Set<string>(WPASupplicant::kInterfacePropertyDriver,
                                    WPASupplicant::kDriverNL80211);
  create_interface_args.Set<string>(WPASupplicant::kInterfacePropertyConfigFile,
                                    WPASupplicant::kSupplicantConfPath);
  supplicant_connect_attempts_++;
  if (!supplicant_process_proxy()->CreateInterface(
          create_interface_args, &supplicant_interface_path_)) {
    // Interface might've already been created, attempt to retrieve it.
    if (!supplicant_process_proxy()->GetInterface(
            link_name(), &supplicant_interface_path_)) {
      LOG(ERROR) << __func__
                 << ": Failed to create interface with supplicant, attempt "
                 << supplicant_connect_attempts_;

      // Interface could not be created at the moment. This could be a
      // transient error in trying to bring the interface UP, or it could be a
      // persistent device failure. We continue to rety a few times until
      // either we succeed or the device disappears or is disabled, in the hope
      // that the device will recover.
      if (supplicant_connect_attempts_ >= kMaxRetryCreateInterfaceAttempts) {
        LOG(ERROR) << "Giving up.";
        SetEnabled(false);
        metrics()->NotifyWiFiSupplicantAbort();
      } else {
        dispatcher()->PostDelayedTask(
            FROM_HERE,
            Bind(&WiFi::ConnectToSupplicant, weak_ptr_factory_.GetWeakPtr()),
            kRetryCreateInterfaceIntervalSeconds * 1000);
      }
      return;
    }
  }

  LOG(INFO) << "connected to supplicant on attempt "
            << supplicant_connect_attempts_;
  metrics()->NotifyWiFiSupplicantSuccess(supplicant_connect_attempts_);

  // Only (re)create the interface proxy if its D-Bus path changed, or if we
  // haven't created one yet. This lets us watch interface properties
  // immediately after Stop() (e.g., for metrics collection) and also allows
  // tests to skip recreation (by retaining the same interface path).
  if (!supplicant_interface_proxy_ ||
      previous_supplicant_interface_path != supplicant_interface_path_) {
    SLOG(this, 2) << StringPrintf(
        "Updating interface path from \"%s\" to \"%s\"",
        previous_supplicant_interface_path.value().c_str(),
        supplicant_interface_path_.value().c_str());
    SetSupplicantInterfaceProxy(
        control_interface()->CreateSupplicantInterfaceProxy(
            this, supplicant_interface_path_));
  } else {
    SLOG(this, 2) << "Reusing existing interface at "
                  << supplicant_interface_path_.value();
  }

  RTNLHandler::GetInstance()->SetInterfaceFlags(interface_index(), IFF_UP,
                                                IFF_UP);
  // TODO(quiche) Set ApScan=1 and BSSExpireAge=190, like flimflam does?

  // Clear out any networks that might previously have been configured
  // for this interface.
  supplicant_interface_proxy_->RemoveAllNetworks();

  // Flush interface's BSS cache, so that we get BSSAdded signals for
  // all BSSes (not just new ones since the last scan).
  supplicant_interface_proxy_->FlushBSS(0);

  // TODO(pstew): Disable fast_reauth until supplicant can properly deal
  // with RADIUS servers that respond strangely to such requests.
  // crbug.com/208561
  if (!supplicant_interface_proxy_->SetFastReauth(false)) {
    LOG(ERROR) << "Failed to disable fast_reauth. "
               << "May be running an older version of wpa_supplicant.";
  }

  // Helps with passing WiFiRoaming.001SSIDSwitchBack.
  if (!supplicant_interface_proxy_->SetScanInterval(kRescanIntervalSeconds)) {
    LOG(ERROR) << "Failed to set scan_interval. "
               << "May be running an older version of wpa_supplicant.";
  }

  if (random_mac_enabled_ &&
      !supplicant_interface_proxy_->EnableMacAddressRandomization(
          kRandomMacMask, sched_scan_supported_)) {
    LOG(ERROR) << "Failed to enable MAC address randomization. "
               << "May be running an older version of wpa_supplicant.";
  }

  Scan(nullptr, __func__);
  StartScanTimer();
}

void WiFi::Restart() {
  LOG(INFO) << link_name() << " restarting.";
  WiFiRefPtr me = this;  // Make sure we don't get destructed.
  // Go through the manager rather than starting and stopping the device
  // directly so that the device can be configured with the profile.
  manager()->DeregisterDevice(me);
  manager()->RegisterDevice(me);
}

void WiFi::GetPhyInfo() {
  GetWiphyMessage get_wiphy;
  get_wiphy.attributes()->SetU32AttributeValue(NL80211_ATTR_IFINDEX,
                                               interface_index());
  netlink_manager_->SendNl80211Message(
      &get_wiphy,
      Bind(&WiFi::OnNewWiphy, weak_ptr_factory_while_started_.GetWeakPtr()),
      Bind(&NetlinkManager::OnAckDoNothing),
      Bind(&NetlinkManager::OnNetlinkMessageError));
}

void WiFi::OnNewWiphy(const Nl80211Message& nl80211_message) {
  // Verify NL80211_CMD_NEW_WIPHY.
  if (nl80211_message.command() != NewWiphyMessage::kCommand) {
    LOG(ERROR) << "Received unexpected command:" << nl80211_message.command();
    return;
  }

  if (wake_on_wifi_) {
    wake_on_wifi_->ParseWakeOnWiFiCapabilities(nl80211_message);
  }
  // Parse and set wiphy_index_.
  bool wiphy_index_parsed = ParseWiphyIndex(nl80211_message);
  if (wiphy_index_parsed && wake_on_wifi_) {
    wake_on_wifi_->OnWiphyIndexReceived(wiphy_index_);
  }

  // Requires wiphy_index_.
  GetRegulatory();

  // This checks NL80211_ATTR_FEATURE_FLAGS.
  ParseFeatureFlags(nl80211_message);

  // The attributes, for this message, are complicated.
  // NL80211_ATTR_BANDS contains an array of bands...
  AttributeListConstRefPtr wiphy_bands;
  if (!nl80211_message.const_attributes()->ConstGetNestedAttributeList(
          NL80211_ATTR_WIPHY_BANDS, &wiphy_bands)) {
    LOG(ERROR) << "NL80211_CMD_NEW_WIPHY had no NL80211_ATTR_WIPHY_BANDS";
    return;
  }

  AttributeIdIterator band_iter(*wiphy_bands);
  for (; !band_iter.AtEnd(); band_iter.Advance()) {
    AttributeListConstRefPtr wiphy_band;
    if (!wiphy_bands->ConstGetNestedAttributeList(band_iter.GetId(),
                                                  &wiphy_band)) {
      LOG(WARNING) << "WiFi band " << band_iter.GetId() << " not found";
      continue;
    }

    // ...Each band has a FREQS attribute...
    AttributeListConstRefPtr frequencies;
    if (!wiphy_band->ConstGetNestedAttributeList(NL80211_BAND_ATTR_FREQS,
                                                 &frequencies)) {
      LOG(ERROR) << "BAND " << band_iter.GetId()
                 << " had no 'frequencies' attribute";
      continue;
    }

    // ...And each FREQS attribute contains an array of information about the
    // frequency...
    AttributeIdIterator freq_iter(*frequencies);
    for (; !freq_iter.AtEnd(); freq_iter.Advance()) {
      AttributeListConstRefPtr frequency;
      if (frequencies->ConstGetNestedAttributeList(freq_iter.GetId(),
                                                   &frequency)) {
        // ...Including the frequency, itself (the part we want).
        uint32_t frequency_value = 0;
        if (frequency->GetU32AttributeValue(NL80211_FREQUENCY_ATTR_FREQ,
                                            &frequency_value)) {
          SLOG(this, 7) << "Found frequency[" << freq_iter.GetId()
                        << "] = " << frequency_value;
          all_scan_frequencies_.insert(frequency_value);
        }
      }
    }
  }
}

void WiFi::GetRegulatory() {
  GetRegMessage reg_msg;
  if (wiphy_index_ != kDefaultWiphyIndex) {
    reg_msg.attributes()->SetU32AttributeValue(NL80211_ATTR_WIPHY,
                                               wiphy_index_);
  }
  netlink_manager_->SendNl80211Message(
      &reg_msg,
      Bind(&WiFi::OnGetReg, weak_ptr_factory_while_started_.GetWeakPtr()),
      Bind(&NetlinkManager::OnAckDoNothing),
      Bind(&NetlinkManager::OnNetlinkMessageError));
}

void WiFi::OnTriggerPassiveScanResponse(const Nl80211Message& netlink_message) {
  LOG(WARNING) << "Didn't expect _this_netlink message ("
               << netlink_message.command() << " here:";
  netlink_message.Print(0, 0);
  return;
}

SupplicantProcessProxyInterface* WiFi::supplicant_process_proxy() const {
  return manager()->supplicant_manager()->proxy();
}

KeyValueStore WiFi::GetLinkStatistics(Error* /*error*/) {
  return link_statistics_;
}

Uint16s WiFi::GetAllScanFrequencies(Error* /* error */) {
  return {begin(all_scan_frequencies_), end(all_scan_frequencies_)};
}

bool WiFi::GetScanPending(Error* /* error */) {
  return scan_state_ == kScanScanning || scan_state_ == kScanBackgroundScanning;
}

bool WiFi::GetWakeOnWiFiSupported(Error* /* error */) {
  return wake_on_wifi_ != nullptr;
}

void WiFi::SetScanState(ScanState new_state,
                        ScanMethod new_method,
                        const char* reason) {
  if (new_state == kScanIdle)
    new_method = kScanMethodNone;
  if (new_state == kScanConnected) {
    // The scan method shouldn't be changed by the connection process, so
    // we'll put a CHECK, here, to verify.  NOTE: this assumption is also
    // enforced by the parameters to the call to |ReportScanResultToUma|.
    CHECK(new_method == scan_method_);
  }

  int log_level = 6;
  bool state_or_method_changed = true;
  bool is_terminal_state = false;
  if (new_state == scan_state_ && new_method == scan_method_) {
    log_level = 7;
    state_or_method_changed = false;
  } else if (new_state == kScanConnected || new_state == kScanFoundNothing) {
    // These 'terminal' states are slightly more interesting than the
    // intermediate states.
    // NOTE: Since background scan goes directly to kScanIdle (skipping over
    // the states required to set |is_terminal_state|), ReportScanResultToUma,
    // below, doesn't get called.  That's intentional.
    log_level = 5;
    is_terminal_state = true;
  }

  SLOG(this, log_level) << (reason ? reason : "<unknown>") << " - "
                        << link_name() << ": Scan state: "
                        << ScanStateString(scan_state_, scan_method_) << " -> "
                        << ScanStateString(new_state, new_method);
  if (!state_or_method_changed)
    return;

  // Actually change the state.
  ScanState old_state = scan_state_;
  ScanMethod old_method = scan_method_;
  bool old_scan_pending = GetScanPending(nullptr);
  scan_state_ = new_state;
  scan_method_ = new_method;
  bool new_scan_pending = GetScanPending(nullptr);
  if (old_scan_pending != new_scan_pending) {
    adaptor()->EmitBoolChanged(kScanningProperty, new_scan_pending);
  }
  switch (new_state) {
    case kScanIdle:
      metrics()->ResetScanTimer(interface_index());
      metrics()->ResetConnectTimer(interface_index());
      break;
    case kScanScanning:  // FALLTHROUGH
    case kScanBackgroundScanning:
      if (new_state != old_state) {
        metrics()->NotifyDeviceScanStarted(interface_index());
      }
      break;
    case kScanConnecting:
      metrics()->NotifyDeviceScanFinished(interface_index());
      // TODO(wdg): Provide |is_auto_connecting| to this interface.  For now,
      // I'll lie (because I don't care about the auto-connect metrics).
      metrics()->NotifyDeviceConnectStarted(interface_index(), false);
      break;
    case kScanConnected:
      metrics()->NotifyDeviceConnectFinished(interface_index());
      break;
    case kScanFoundNothing:
      // Note that finishing a scan that hasn't started (if, for example, we
      // get here when we fail to complete a connection) does nothing.
      metrics()->NotifyDeviceScanFinished(interface_index());
      metrics()->ResetConnectTimer(interface_index());
      break;
    case kScanTransitionToConnecting:  // FALLTHROUGH
    default:
      break;
  }
  if (is_terminal_state) {
    ReportScanResultToUma(new_state, old_method);
    // Now that we've logged a terminal state, let's call ourselves to
    // transition to the idle state.
    SetScanState(kScanIdle, kScanMethodNone, reason);
  }
}

// static
string WiFi::ScanStateString(ScanState state, ScanMethod method) {
  switch (state) {
    case kScanIdle:
      return "IDLE";
    case kScanScanning:
      DCHECK(method != kScanMethodNone) << "Scanning with no scan method.";
      switch (method) {
        case kScanMethodFull:
          return "FULL_START";
        default:
          NOTREACHED();
      }
      // TODO(denik): Remove break after fall-through check
      // is fixed with NOTREACHED(), https://crbug.com/973960.
      break;
    case kScanBackgroundScanning:
      return "BACKGROUND_START";
    case kScanTransitionToConnecting:
      return "TRANSITION_TO_CONNECTING";
    case kScanConnecting:
      switch (method) {
        case kScanMethodNone:
          return "CONNECTING (not scan related)";
        case kScanMethodFull:
          return "FULL_CONNECTING";
        default:
          NOTREACHED();
      }
      // TODO(denik): Remove break after fall-through check
      // is fixed with NOTREACHED(), https://crbug.com/973960.
      break;
    case kScanConnected:
      switch (method) {
        case kScanMethodNone:
          return "CONNECTED (not scan related; e.g., from a supplicant roam)";
        case kScanMethodFull:
          return "FULL_CONNECTED";
        default:
          NOTREACHED();
      }
      // TODO(denik): Remove break after fall-through check
      // is fixed with NOTREACHED(), https://crbug.com/973960.
      break;
    case kScanFoundNothing:
      switch (method) {
        case kScanMethodNone:
          return "CONNECT FAILED (not scan related)";
        case kScanMethodFull:
          return "FULL_NOCONNECTION";
        default:
          NOTREACHED();
      }
      // TODO(denik): Remove break after fall-through check
      // is fixed with NOTREACHED(), https://crbug.com/973960.
      break;
    default:
      NOTREACHED();
  }
  return "";  // To shut up the compiler (that doesn't understand NOTREACHED).
}

void WiFi::ReportScanResultToUma(ScanState state, ScanMethod method) {
  Metrics::WiFiScanResult result = Metrics::kScanResultMax;
  if (state == kScanConnected) {
    switch (method) {
      case kScanMethodFull:
        result = Metrics::kScanResultFullScanConnected;
        break;
      default:
        // OK: Connect resulting from something other than scan.
        break;
    }
  } else if (state == kScanFoundNothing) {
    switch (method) {
      case kScanMethodFull:
        result = Metrics::kScanResultFullScanFoundNothing;
        break;
      default:
        // OK: Connect failed, not scan related.
        break;
    }
  }

  if (result != Metrics::kScanResultMax) {
    metrics()->SendEnumToUMA(Metrics::kMetricScanResult, result,
                             Metrics::kScanResultMax);
  }
}

void WiFi::RequestStationInfo() {
  if (!IsConnectedToCurrentService()) {
    LOG(ERROR) << "Not collecting station info because we are not connected.";
    return;
  }

  EndpointMap::iterator endpoint_it = endpoint_by_rpcid_.find(supplicant_bss_);
  if (endpoint_it == endpoint_by_rpcid_.end()) {
    LOG(ERROR) << "Can't get endpoint for current supplicant BSS "
               << supplicant_bss_.value();
    return;
  }

  GetStationMessage get_station;
  if (!get_station.attributes()->SetU32AttributeValue(NL80211_ATTR_IFINDEX,
                                                      interface_index())) {
    LOG(ERROR) << "Could not add IFINDEX attribute for GetStation message.";
    return;
  }

  const WiFiEndpointConstRefPtr endpoint(endpoint_it->second);
  if (!get_station.attributes()->SetRawAttributeValue(
          NL80211_ATTR_MAC,
          ByteString::CreateFromHexString(endpoint->bssid_hex()))) {
    LOG(ERROR) << "Could not add MAC attribute for GetStation message.";
    return;
  }

  netlink_manager_->SendNl80211Message(
      &get_station,
      Bind(&WiFi::OnReceivedStationInfo,
           weak_ptr_factory_while_started_.GetWeakPtr()),
      Bind(&NetlinkManager::OnAckDoNothing),
      Bind(&NetlinkManager::OnNetlinkMessageError));

  request_station_info_callback_.Reset(Bind(
      &WiFi::RequestStationInfo, weak_ptr_factory_while_started_.GetWeakPtr()));
  dispatcher()->PostDelayedTask(FROM_HERE,
                                request_station_info_callback_.callback(),
                                kRequestStationInfoPeriodSeconds * 1000);
}

// static
bool WiFi::ParseStationBitrate(const AttributeListConstRefPtr& rate_info,
                               string* out,
                               int* rate_out) {
  uint32_t rate = 0;      // In 100Kbps.
  uint16_t u16_rate = 0;  // In 100Kbps.
  uint8_t mcs = 0;
  uint8_t nss = 0;
  bool band_flag = false;
  bool is_short_gi = false;
  string mcs_info;
  string nss_info;
  string band_info;

  if (rate_info->GetU16AttributeValue(NL80211_RATE_INFO_BITRATE, &u16_rate)) {
    rate = static_cast<uint32_t>(u16_rate);
  } else {
    rate_info->GetU32AttributeValue(NL80211_RATE_INFO_BITRATE32, &rate);
  }

  if (rate_info->GetU8AttributeValue(NL80211_RATE_INFO_MCS, &mcs)) {
    mcs_info = StringPrintf(" MCS %d", mcs);
  } else if (rate_info->GetU8AttributeValue(NL80211_RATE_INFO_VHT_MCS, &mcs)) {
    mcs_info = StringPrintf(" VHT-MCS %d", mcs);
  }

  if (rate_info->GetU8AttributeValue(NL80211_RATE_INFO_VHT_NSS, &nss)) {
    nss_info = StringPrintf(" VHT-NSS %d", nss);
  }

  if (rate_info->GetFlagAttributeValue(NL80211_RATE_INFO_40_MHZ_WIDTH,
                                       &band_flag) &&
      band_flag) {
    band_info = StringPrintf(" 40MHz");
  } else if (rate_info->GetFlagAttributeValue(NL80211_RATE_INFO_80_MHZ_WIDTH,
                                              &band_flag) &&
             band_flag) {
    band_info = StringPrintf(" 80MHz");
  } else if (rate_info->GetFlagAttributeValue(NL80211_RATE_INFO_80P80_MHZ_WIDTH,
                                              &band_flag) &&
             band_flag) {
    band_info = StringPrintf(" 80+80MHz");
  } else if (rate_info->GetFlagAttributeValue(NL80211_RATE_INFO_160_MHZ_WIDTH,
                                              &band_flag) &&
             band_flag) {
    band_info = StringPrintf(" 160MHz");
  }

  rate_info->GetFlagAttributeValue(NL80211_RATE_INFO_SHORT_GI, &is_short_gi);

  if (rate) {
    *out = StringPrintf("%d.%d MBit/s%s%s%s%s", rate / 10, rate % 10,
                        mcs_info.c_str(), band_info.c_str(),
                        is_short_gi ? " short GI" : "", nss_info.c_str());
    *rate_out = rate / 10;
    return true;
  }

  return false;
}

void WiFi::OnReceivedStationInfo(const Nl80211Message& nl80211_message) {
  // Verify NL80211_CMD_NEW_STATION
  if (nl80211_message.command() != NewStationMessage::kCommand) {
    LOG(ERROR) << "Received unexpected command:" << nl80211_message.command();
    return;
  }

  if (!IsConnectedToCurrentService()) {
    LOG(ERROR) << "Not accepting station info because we are not connected.";
    return;
  }

  EndpointMap::iterator endpoint_it = endpoint_by_rpcid_.find(supplicant_bss_);
  if (endpoint_it == endpoint_by_rpcid_.end()) {
    LOG(ERROR) << "Can't get endpoint for current supplicant BSS."
               << supplicant_bss_.value();
    return;
  }

  ByteString station_bssid;
  if (!nl80211_message.const_attributes()->GetRawAttributeValue(
          NL80211_ATTR_MAC, &station_bssid)) {
    LOG(ERROR) << "Unable to get MAC attribute from received station info.";
    return;
  }

  WiFiEndpointRefPtr endpoint(endpoint_it->second);

  if (!station_bssid.Equals(
          ByteString::CreateFromHexString(endpoint->bssid_hex()))) {
    LOG(ERROR) << "Received station info for a non-current BSS.";
    return;
  }

  AttributeListConstRefPtr station_info;
  if (!nl80211_message.const_attributes()->ConstGetNestedAttributeList(
          NL80211_ATTR_STA_INFO, &station_info)) {
    LOG(ERROR) << "Received station info had no NL80211_ATTR_STA_INFO.";
    return;
  }

  uint8_t signal;
  if (!station_info->GetU8AttributeValue(NL80211_STA_INFO_SIGNAL, &signal)) {
    LOG(ERROR) << "Received station info had no NL80211_STA_INFO_SIGNAL.";
    return;
  }

  endpoint->UpdateSignalStrength(static_cast<signed char>(signal));

  link_statistics_.Clear();

  map<int, string> u32_property_map = {
      {NL80211_STA_INFO_INACTIVE_TIME, kInactiveTimeMillisecondsProperty},
      {NL80211_STA_INFO_RX_PACKETS, kPacketReceiveSuccessesProperty},
      {NL80211_STA_INFO_TX_FAILED, kPacketTransmitFailuresProperty},
      {NL80211_STA_INFO_TX_PACKETS, kPacketTransmitSuccessesProperty},
      {NL80211_STA_INFO_TX_RETRIES, kTransmitRetriesProperty}};

  for (const auto& kv : u32_property_map) {
    uint32_t value;
    if (station_info->GetU32AttributeValue(kv.first, &value)) {
      link_statistics_.Set<uint32_t>(kv.second, value);
    }
  }

  map<int, string> s8_property_map = {
      {NL80211_STA_INFO_SIGNAL, kLastReceiveSignalDbmProperty},
      {NL80211_STA_INFO_SIGNAL_AVG, kAverageReceiveSignalDbmProperty}};

  for (const auto& kv : s8_property_map) {
    uint8_t value;
    if (station_info->GetU8AttributeValue(kv.first, &value)) {
      // Despite these values being reported as a U8 by the kernel, these
      // should be interpreted as signed char.
      link_statistics_.Set<int32_t>(kv.second, static_cast<signed char>(value));
    }
  }

  AttributeListConstRefPtr transmit_info;
  if (station_info->ConstGetNestedAttributeList(NL80211_STA_INFO_TX_BITRATE,
                                                &transmit_info)) {
    string str;
    int rate;
    if (ParseStationBitrate(transmit_info, &str, &rate)) {
      link_statistics_.Set<string>(kTransmitBitrateProperty, str);
      metrics()->NotifyWifiTxBitrate(rate);
    }
  }

  AttributeListConstRefPtr receive_info;
  if (station_info->ConstGetNestedAttributeList(NL80211_STA_INFO_RX_BITRATE,
                                                &receive_info)) {
    string str;
    int rate;
    if (ParseStationBitrate(receive_info, &str, &rate)) {
      link_statistics_.Set<string>(kReceiveBitrateProperty, str);
    }
  }
}

void WiFi::StopRequestingStationInfo() {
  SLOG(this, 2) << "WiFi Device " << link_name() << ": " << __func__;
  request_station_info_callback_.Cancel();
  link_statistics_.Clear();
}

// Traffic monitor is enabled for wifi.
bool WiFi::IsTrafficMonitorEnabled() const {
  return true;
}

void WiFi::RemoveSupplicantNetworks() {
  for (const auto& map_entry : rpcid_by_service_) {
    RemoveNetwork(map_entry.second);
  }
  rpcid_by_service_.clear();
}

void WiFi::OnIPConfigUpdated(const IPConfigRefPtr& ipconfig,
                             bool new_lease_acquired) {
  Device::OnIPConfigUpdated(ipconfig, new_lease_acquired);
  if (!wake_on_wifi_) {
    return;
  }
  if (new_lease_acquired) {
    SLOG(this, 3) << __func__ << ": "
                  << "IPv4 DHCP lease obtained";
    uint32_t time_to_next_lease_renewal;
    bool have_dhcp_lease =
        TimeToNextDHCPLeaseRenewal(&time_to_next_lease_renewal);
    wake_on_wifi_->OnConnectedAndReachable(have_dhcp_lease,
                                           time_to_next_lease_renewal);
  } else {
    SLOG(this, 3) << __func__ << ": "
                  << "Gateway ARP received";
    // Do nothing since we are waiting until the DHCP lease is actually
    // obtained.
    return;
  }
}

void WiFi::OnIPv6ConfigUpdated() {
  Device::OnIPv6ConfigUpdated();
  if (!IsConnectedToCurrentService()) {
    return;
  }
  if (!wake_on_wifi_) {
    return;
  }
  SLOG(this, 3) << __func__ << ": "
                << "IPv6 configuration obtained";
  uint32_t time_to_next_lease_renewal;
  bool have_dhcp_lease =
      TimeToNextDHCPLeaseRenewal(&time_to_next_lease_renewal);
  wake_on_wifi_->OnConnectedAndReachable(have_dhcp_lease,
                                         time_to_next_lease_renewal);
}

bool WiFi::IsConnectedToCurrentService() {
  return (current_service_ && current_service_->IsConnected());
}

void WiFi::ReportConnectedToServiceAfterWake() {
  int seconds_in_suspend = (manager()->GetSuspendDurationUsecs() / 1000000);
  if (wake_on_wifi_) {
    wake_on_wifi_->ReportConnectedToServiceAfterWake(
        IsConnectedToCurrentService(), seconds_in_suspend);
  }
}

bool WiFi::RequestRoam(const std::string& addr, Error* error) {
  if (!supplicant_interface_proxy_->Roam(addr)) {
    Error::PopulateAndLog(FROM_HERE, error, Error::kOperationFailed,
                          StringPrintf("%s: requested roam to %s failed",
                                       link_name().c_str(), addr.c_str()));
    return false;
  }
  return true;
}

}  // namespace shill
