/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "wificond/server.h"

#include <algorithm> // for std::find_if
#include <sstream>
#include <set>

#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/strings.h>
#include <binder/IPCThreadState.h>
#include <binder/PermissionCache.h>

#include "wificond/logging_utils.h"
#include "wificond/net/netlink_utils.h"
#include "wificond/scanning/scan_utils.h"

using android::base::WriteStringToFd;
using android::binder::Status;
using android::sp;
using android::IBinder;
using android::net::wifi::nl80211::IApInterface;
using android::net::wifi::nl80211::IClientInterface;
using android::net::wifi::nl80211::IInterfaceEventCallback;
using android::net::wifi::nl80211::DeviceWiphyCapabilities;
using android::net::wifi::nl80211::IWificondEventCallback;
using android::wifi_system::InterfaceTool;

using std::endl;
using std::optional;
using std::placeholders::_1;
using std::placeholders::_2;
using std::set;
using std::string;
using std::stringstream;
using std::unique_ptr;
using std::vector;

namespace android {
namespace wificond {

namespace {

constexpr const char* kPermissionDump = "android.permission.DUMP";

}  // namespace

Server::Server(unique_ptr<InterfaceTool> if_tool,
               NetlinkUtils* netlink_utils,
               ScanUtils* scan_utils)
    : if_tool_(std::move(if_tool)),
      netlink_utils_(netlink_utils),
      scan_utils_(scan_utils) {
}

Status Server::registerWificondEventCallback(const sp<IWificondEventCallback>& callback) {
  for (const auto& it : wificond_event_callbacks_) {
    if (IInterface::asBinder(callback) == IInterface::asBinder(it)) {
      LOG(WARNING) << "Ignore duplicate wificond event callback registration";
      return Status::ok();
    }
  }
  LOG(INFO) << "New wificond event callback registered";
  wificond_event_callbacks_.push_back(callback);
  return Status::ok();
}

Status Server::unregisterWificondEventCallback(const sp<IWificondEventCallback>& callback) {
  for (auto it = wificond_event_callbacks_.begin();
       it != wificond_event_callbacks_.end();
       it++) {
    if (IInterface::asBinder(callback) == IInterface::asBinder(*it)) {
      wificond_event_callbacks_.erase(it);
      LOG(INFO) << "Unregister interface event callback";
      return Status::ok();
    }
  }
  LOG(WARNING) << "Failed to find registered wificond event callback"
               << " to unregister";
  return Status::ok();
}

Status Server::RegisterCallback(const sp<IInterfaceEventCallback>& callback) {
  for (auto& it : interface_event_callbacks_) {
    if (IInterface::asBinder(callback) == IInterface::asBinder(it)) {
      LOG(WARNING) << "Ignore duplicate interface event callback registration";
      return Status::ok();
    }
  }
  LOG(INFO) << "New interface event callback registered";
  interface_event_callbacks_.push_back(callback);
  return Status::ok();
}

Status Server::UnregisterCallback(const sp<IInterfaceEventCallback>& callback) {
  for (auto it = interface_event_callbacks_.begin();
       it != interface_event_callbacks_.end();
       it++) {
    if (IInterface::asBinder(callback) == IInterface::asBinder(*it)) {
      interface_event_callbacks_.erase(it);
      LOG(INFO) << "Unregister interface event callback";
      return Status::ok();
    }
  }
  LOG(WARNING) << "Failed to find registered interface event callback"
               << " to unregister";
  return Status::ok();
}

Status Server::createApInterface(const std::string& iface_name,
                                 sp<IApInterface>* created_interface) {
  InterfaceInfo interface;
  uint32_t wiphy_index;

  if (!SetupInterface(iface_name, &interface, &wiphy_index)) {
    return Status::ok();  // Logging was done internally
  }

  LOG(INFO) << "createApInterface: wiphy_index " << wiphy_index << " iface_name " << iface_name;

  unique_ptr<ApInterfaceImpl> ap_interface(new ApInterfaceImpl(
      interface.name,
      interface.if_index,
      netlink_utils_,
      if_tool_.get()));
  *created_interface = ap_interface->GetBinder();
  BroadcastApInterfaceReady(ap_interface->GetBinder());
  ap_interfaces_[iface_name] = std::move(ap_interface);
  if (hasNoIfaceForWiphyIndex(wiphy_index)) {
    UpdateBandWiphyIndexMap(wiphy_index);
  } else {
    LOG(INFO) << "Band info for wiphy_index " << wiphy_index << " already available";
  }
  iface_to_wiphy_index_map_[iface_name] = wiphy_index;
  return Status::ok();
}

Status Server::tearDownApInterface(const std::string& iface_name,
                                   bool* out_success) {
  *out_success = false;
  const auto iter = ap_interfaces_.find(iface_name);
  if (iter != ap_interfaces_.end()) {
    BroadcastApInterfaceTornDown(iter->second->GetBinder());
    ap_interfaces_.erase(iter);
    *out_success = true;
  }

  const auto iter_wi = iface_to_wiphy_index_map_.find(iface_name);
  if (iter_wi != iface_to_wiphy_index_map_.end()) {
    int wiphy_index = iter_wi->second;
    LOG(INFO) << "tearDownApInterface: erasing wiphy_index for iface_name " << iface_name;
    iface_to_wiphy_index_map_.erase(iter_wi);
    if (hasNoIfaceForWiphyIndex(wiphy_index)) {
      EraseBandWiphyIndexMap(wiphy_index);
    } else {
      LOG(INFO) << "Band info for wiphy_index " << wiphy_index << " retained";
    }
  }

  return Status::ok();
}

bool Server::hasNoIfaceForWiphyIndex(int wiphy_index) {
  return std::find_if(
      iface_to_wiphy_index_map_.begin(),
      iface_to_wiphy_index_map_.end(),
      [wiphy_index](const auto& kv) { return kv.second == wiphy_index; })
      == iface_to_wiphy_index_map_.end();
}

Status Server::createClientInterface(const std::string& iface_name,
                                     sp<IClientInterface>* created_interface) {
  InterfaceInfo interface;
  uint32_t wiphy_index;

  if (!SetupInterface(iface_name, &interface, &wiphy_index)) {
    return Status::ok();  // Logging was done internally
  }

  LOG(INFO) << "createClientInterface: wiphy_index " << wiphy_index << " iface_name " << iface_name;

  unique_ptr<ClientInterfaceImpl> client_interface(new ClientInterfaceImpl(
      wiphy_index,
      interface.name,
      interface.if_index,
      interface.mac_address,
      if_tool_.get(),
      netlink_utils_,
      scan_utils_));
  *created_interface = client_interface->GetBinder();
  BroadcastClientInterfaceReady(client_interface->GetBinder());
  client_interfaces_[iface_name] = std::move(client_interface);
  if (hasNoIfaceForWiphyIndex(wiphy_index)) {
    UpdateBandWiphyIndexMap(wiphy_index);
  } else {
    LOG(INFO) << "Band info for wiphy_index " << wiphy_index << " already available";
  }
  iface_to_wiphy_index_map_[iface_name] = wiphy_index;

  return Status::ok();
}

Status Server::tearDownClientInterface(const std::string& iface_name,
                                       bool* out_success) {
  *out_success = false;
  const auto iter = client_interfaces_.find(iface_name);
  if (iter != client_interfaces_.end()) {
    BroadcastClientInterfaceTornDown(iter->second->GetBinder());
    client_interfaces_.erase(iter);
    *out_success = true;
  }

  const auto iter_wi = iface_to_wiphy_index_map_.find(iface_name);
  if (iter_wi != iface_to_wiphy_index_map_.end()) {
    int wiphy_index = iter_wi->second;
    LOG(INFO) << "tearDownClientInterface: erasing wiphy_index for iface_name " << iface_name;
    iface_to_wiphy_index_map_.erase(iter_wi);
    if (hasNoIfaceForWiphyIndex(wiphy_index)) {
      EraseBandWiphyIndexMap(wiphy_index);
    } else {
      LOG(INFO) << "Band info for wiphy_index " << wiphy_index << " retained";
    }
  }

  return Status::ok();
}

Status Server::tearDownInterfaces() {
  for (auto& it : client_interfaces_) {
    BroadcastClientInterfaceTornDown(it.second->GetBinder());
  }
  client_interfaces_.clear();

  for (auto& it : ap_interfaces_) {
    BroadcastApInterfaceTornDown(it.second->GetBinder());
  }
  ap_interfaces_.clear();

  MarkDownAllInterfaces();

  for (auto& it : iface_to_wiphy_index_map_) {
    netlink_utils_->UnsubscribeRegDomainChange(it.second);
    EraseBandWiphyIndexMap(it.second);
  }
  iface_to_wiphy_index_map_.clear();

  return Status::ok();
}

Status Server::GetClientInterfaces(vector<sp<IBinder>>* out_client_interfaces) {
  vector<sp<android::IBinder>> client_interfaces_binder;
  for (auto& it : client_interfaces_) {
    out_client_interfaces->push_back(asBinder(it.second->GetBinder()));
  }
  return binder::Status::ok();
}

Status Server::GetApInterfaces(vector<sp<IBinder>>* out_ap_interfaces) {
  vector<sp<IBinder>> ap_interfaces_binder;
  for (auto& it : ap_interfaces_) {
    out_ap_interfaces->push_back(asBinder(it.second->GetBinder()));
  }
  return binder::Status::ok();
}

status_t Server::dump(int fd, const Vector<String16>& /*args*/) {
  if (!PermissionCache::checkCallingPermission(String16(kPermissionDump))) {
    IPCThreadState* ipc = android::IPCThreadState::self();
    LOG(ERROR) << "Caller (uid: " << ipc->getCallingUid()
               << ") is not permitted to dump wificond state";
    return PERMISSION_DENIED;
  }

  stringstream ss;
  ss << "Cached interfaces list from kernel message: " << endl;
  for (const auto& iface : debug_interfaces_) {
    ss << "Interface index: " << iface.if_index
       << ", name: " << iface.name
       << ", wiphy index: " << iface.wiphy_index
       << ", mac address: "
       << LoggingUtils::GetMacString(iface.mac_address) << endl;
  }

  string country_code;
  if (netlink_utils_->GetCountryCode(&country_code)) {
    ss << "Current country code from kernel: " << country_code << endl;
  } else {
    ss << "Failed to get country code from kernel." << endl;
  }

  for (const auto& iface : client_interfaces_) {
    iface.second->Dump(&ss);
  }

  for (const auto& iface : ap_interfaces_) {
    iface.second->Dump(&ss);
  }

  ss << "Channel Type / Wiphy Index Mapping:" << endl;
  for (const auto& it : band_to_wiphy_index_map_) {
    ss << "Channel type " << it.first << ": " << it.second << endl;
  }

  if (!WriteStringToFd(ss.str(), fd)) {
    PLOG(ERROR) << "Failed to dump state to fd " << fd;
    return FAILED_TRANSACTION;
  }

  return OK;
}

void Server::MarkDownAllInterfaces() {
  std::string iface_name;

  for (auto& it : iface_to_wiphy_index_map_) {
    iface_name = it.first;
    if_tool_->SetUpState(iface_name.c_str(), false);
  }
}

Status Server::getAvailable2gChannels(
    std::optional<vector<int32_t>>* out_frequencies) {

  int wiphy_index = GetWiphyIndexFromBand(NL80211_BAND_2GHZ);
  BandInfo band_info;

  if (!GetBandInfo(wiphy_index, &band_info)) {
    out_frequencies->reset();
    return Status::ok();
  }

  if (band_info.band_2g.size() == 0)
    out_frequencies->reset();
  else
    out_frequencies->emplace(band_info.band_2g.begin(), band_info.band_2g.end());
  return Status::ok();
}

Status Server::getAvailable5gNonDFSChannels(
    std::optional<vector<int32_t>>* out_frequencies) {
  int wiphy_index = GetWiphyIndexFromBand(NL80211_BAND_5GHZ);
  BandInfo band_info;
  if (!GetBandInfo(wiphy_index, &band_info)) {
    out_frequencies->reset();
    return Status::ok();
  }

  if (band_info.band_5g.size() == 0)
    out_frequencies->reset();
  else
    out_frequencies->emplace(band_info.band_5g.begin(), band_info.band_5g.end());
  return Status::ok();
}

Status Server::getAvailableDFSChannels(
    std::optional<vector<int32_t>>* out_frequencies) {
  int wiphy_index = GetWiphyIndexFromBand(NL80211_BAND_5GHZ);
  BandInfo band_info;
  if (!GetBandInfo(wiphy_index, &band_info)) {
    out_frequencies->reset();
    return Status::ok();
  }

  if (band_info.band_dfs.size() == 0)
    out_frequencies->reset();
  else
    out_frequencies->emplace(band_info.band_dfs.begin(),
                           band_info.band_dfs.end());
  return Status::ok();
}

Status Server::getAvailable6gChannels(
    std::optional<vector<int32_t>>* out_frequencies) {
  int wiphy_index = GetWiphyIndexFromBand(NL80211_BAND_6GHZ);
  BandInfo band_info;
  if (!GetBandInfo(wiphy_index, &band_info)) {
    out_frequencies->reset();
    return Status::ok();
  }

  if (band_info.band_6g.size() == 0)
    out_frequencies->reset();
  else
    out_frequencies->emplace(band_info.band_6g.begin(), band_info.band_6g.end());
  return Status::ok();
}

Status Server::getAvailable60gChannels(
    std::optional<vector<int32_t>>* out_frequencies) {
  int wiphy_index = GetWiphyIndexFromBand(NL80211_BAND_60GHZ);
  BandInfo band_info;
  if (!GetBandInfo(wiphy_index, &band_info)) {
    out_frequencies->reset();
    return Status::ok();
  }

  if (band_info.band_60g.size() == 0)
    out_frequencies->reset();
  else
    out_frequencies->emplace(
      band_info.band_60g.begin(), band_info.band_60g.end());

  return Status::ok();
}

Status Server::getDeviceWiphyCapabilities(
    const std::string& iface_name,
    std::optional<DeviceWiphyCapabilities>* capabilities) {
  int wiphy_index = FindWiphyIndex(iface_name);

  if (wiphy_index == -1) {
    LOG(ERROR) << "Failed to find iface_name " << iface_name;
    capabilities = nullptr;
    return Status::ok();
  }

  BandInfo band_info;
  ScanCapabilities scan_capabilities_ignored;
  WiphyFeatures wiphy_features_ignored;

  if (!netlink_utils_->GetWiphyInfo(wiphy_index, &band_info,
                                    &scan_capabilities_ignored,
                                    &wiphy_features_ignored)) {
    LOG(ERROR) << "Failed to get wiphy info from kernel";
    capabilities = nullptr;
    return Status::ok();
  }

  capabilities->emplace();

  capabilities->value().is80211nSupported_  = band_info.is_80211n_supported;
  capabilities->value().is80211acSupported_ = band_info.is_80211ac_supported;
  capabilities->value().is80211axSupported_ = band_info.is_80211ax_supported;
  capabilities->value().is80211beSupported_ = band_info.is_80211be_supported;
  capabilities->value().is160MhzSupported_ = band_info.is_160_mhz_supported;
  capabilities->value().is80p80MhzSupported_ = band_info.is_80p80_mhz_supported;
  capabilities->value().is320MhzSupported_ = band_info.is_320_mhz_supported;
  capabilities->value().maxTxStreams_ = band_info.max_tx_streams;
  capabilities->value().maxRxStreams_ = band_info.max_rx_streams;

  return Status::ok();
}

bool Server::SetupInterface(const std::string& iface_name,
                            InterfaceInfo* interface,
                            uint32_t *wiphy_index) {
  if (!netlink_utils_->GetWiphyIndex(wiphy_index, iface_name)) {
    LOG(ERROR) << "Failed to get wiphy index";
    return false;
  }
  // TODO: It may need to handle multi-chips case to get multi-wiphy index and
  // register corresponding callback.
  netlink_utils_->SubscribeRegDomainChange(
          *wiphy_index,
           std::bind(&Server::OnRegDomainChanged,
           this,
           _1,
           _2));

  debug_interfaces_.clear();
  if (!netlink_utils_->GetInterfaces(*wiphy_index, &debug_interfaces_)) {
    LOG(ERROR) << "Failed to get interfaces info from kernel for iface_name " << iface_name << " wiphy_index " << *wiphy_index;
    return false;
  }

  for (const auto& iface : debug_interfaces_) {
    if (iface.name == iface_name) {
      *interface = iface;
      return true;
    }
  }

  LOG(ERROR) << "No usable interface found";
  return false;
}

void Server::handleCountryCodeChanged() {
  uint32_t wiphy_index;
  set<uint32_t> handled_wiphy_index;
  for (auto& it : client_interfaces_) {
    it.second->UpdateBandInfo();
    if (netlink_utils_->GetWiphyIndex(&wiphy_index, it.first)) {
      if (handled_wiphy_index.find(wiphy_index) == handled_wiphy_index.end()) {
        UpdateBandWiphyIndexMap(wiphy_index);
        LogSupportedBands(wiphy_index);
        handled_wiphy_index.insert(wiphy_index);
      }
    }
  }
  for (auto& it : ap_interfaces_) {
    if (netlink_utils_->GetWiphyIndex(&wiphy_index, it.first)) {
      if (handled_wiphy_index.find(wiphy_index) == handled_wiphy_index.end()) {
        UpdateBandWiphyIndexMap(wiphy_index);
        LogSupportedBands(wiphy_index);
        handled_wiphy_index.insert(wiphy_index);
      }
    }
  }
}

void Server::OnRegDomainChanged(uint32_t wiphy_index, std::string& country_code) {
  string current_country_code;
  if (country_code.empty()) {
    LOG(DEBUG) << "Regulatory domain changed with empty country code (world mode?)";
    if (!netlink_utils_->GetCountryCode(&current_country_code)) {
        LOG(ERROR) << "Fail to get country code on wiphy_index:" << wiphy_index;
    }
  } else {
      current_country_code = country_code;
  }
  if (!current_country_code.empty()) {
      LOG(INFO) << "Regulatory domain changed to country: " << current_country_code
                << " on wiphy_index: " << wiphy_index;
      BroadcastRegDomainChanged(current_country_code);
  }
  // Sometimes lower layer sends stale wiphy index when there are no
  // interfaces. So update band - wiphy index mapping only if an
  // interface exists
  if (!hasNoIfaceForWiphyIndex(wiphy_index)) {
    handleCountryCodeChanged();
  }
}

android::binder::Status Server::notifyCountryCodeChanged() {
  LOG(INFO) << "Receive notifyCountryCodeChanged";
  handleCountryCodeChanged();
  return Status::ok();
}

void Server::LogSupportedBands(uint32_t wiphy_index) {
  BandInfo band_info;
  ScanCapabilities scan_capabilities;
  WiphyFeatures wiphy_features;
  netlink_utils_->GetWiphyInfo(wiphy_index,
                               &band_info,
                               &scan_capabilities,
                               &wiphy_features);

  stringstream ss;
  for (unsigned int i = 0; i < band_info.band_2g.size(); i++) {
    ss << " " << band_info.band_2g[i];
  }
  LOG(INFO) << "2.4Ghz frequencies:"<< ss.str();
  ss.str("");

  for (unsigned int i = 0; i < band_info.band_5g.size(); i++) {
    ss << " " << band_info.band_5g[i];
  }
  LOG(INFO) << "5Ghz non-DFS frequencies:"<< ss.str();
  ss.str("");

  for (unsigned int i = 0; i < band_info.band_dfs.size(); i++) {
    ss << " " << band_info.band_dfs[i];
  }
  LOG(INFO) << "5Ghz DFS frequencies:"<< ss.str();
  ss.str("");

  for (unsigned int i = 0; i < band_info.band_6g.size(); i++) {
    ss << " " << band_info.band_6g[i];
  }
  LOG(INFO) << "6Ghz frequencies:"<< ss.str();
  ss.str("");

  for (unsigned int i = 0; i < band_info.band_60g.size(); i++) {
    ss << " " << band_info.band_60g[i];
  }
  LOG(INFO) << "60Ghz frequencies:"<< ss.str();
}

void Server::BroadcastClientInterfaceReady(
    sp<IClientInterface> network_interface) {
  for (auto& it : interface_event_callbacks_) {
    it->OnClientInterfaceReady(network_interface);
  }
}

void Server::BroadcastApInterfaceReady(
    sp<IApInterface> network_interface) {
  for (auto& it : interface_event_callbacks_) {
    it->OnApInterfaceReady(network_interface);
  }
}

void Server::BroadcastClientInterfaceTornDown(
    sp<IClientInterface> network_interface) {
  for (auto& it : interface_event_callbacks_) {
    it->OnClientTorndownEvent(network_interface);
  }
}

void Server::BroadcastApInterfaceTornDown(
    sp<IApInterface> network_interface) {
  for (auto& it : interface_event_callbacks_) {
    it->OnApTorndownEvent(network_interface);
  }
}

void Server::BroadcastRegDomainChanged(
    std::string country_code) {
  for (const auto& it : wificond_event_callbacks_) {
    it->OnRegDomainChanged(country_code);
  }
}

int Server::FindWiphyIndex(
    const std::string& iface_name) {
  int wiphy_index = -1;

  for (auto& it : iface_to_wiphy_index_map_) {
    if (it.first == iface_name) {
      wiphy_index = it.second;
      break;
    }
  }

  return wiphy_index;
}

bool Server::GetBandInfo(
    int wiphy_index,
    BandInfo* band_info) {

  if (wiphy_index == -1) return false;

  ScanCapabilities scan_capabilities_ignored;
  WiphyFeatures wiphy_features_ignored;

  if (!netlink_utils_->GetWiphyInfo(wiphy_index, band_info,
                                    &scan_capabilities_ignored,
                                    &wiphy_features_ignored)) {
    LOG(ERROR) << "Failed to get wiphy index " << wiphy_index << " info from kernel";
    return false;
  }

  return true;
}

int Server::GetWiphyIndexFromBand(int band) {
    auto iter = band_to_wiphy_index_map_.find(band);
    return (iter != band_to_wiphy_index_map_.end()) ? iter->second : -1;
}

void Server::UpdateBandWiphyIndexMap(int wiphy_index) {
  LOG(DEBUG) << "UpdateBandWiphyIndexMap for wiphy_index " << wiphy_index;
  BandInfo band_info;
  if (!GetBandInfo(wiphy_index, &band_info)) return;

  if (band_info.band_2g.size() != 0
      && band_to_wiphy_index_map_.find(NL80211_BAND_2GHZ) == band_to_wiphy_index_map_.end()) {
    band_to_wiphy_index_map_[NL80211_BAND_2GHZ] = wiphy_index;
    LOG(INFO) << "add channel type " << NL80211_BAND_2GHZ
               << " support at wiphy index: " << wiphy_index;
  }
  if (band_info.band_5g.size() != 0
      && band_to_wiphy_index_map_.find(NL80211_BAND_5GHZ) == band_to_wiphy_index_map_.end()) {
    band_to_wiphy_index_map_[NL80211_BAND_5GHZ] = wiphy_index;
    LOG(INFO) << "add channel type " << NL80211_BAND_5GHZ
               << " support at wiphy index: " << wiphy_index;
  }
  if (band_info.band_dfs.size() != 0
      && band_to_wiphy_index_map_.find(NL80211_BAND_5GHZ) == band_to_wiphy_index_map_.end()) {
    band_to_wiphy_index_map_[NL80211_BAND_5GHZ] = wiphy_index;
    LOG(INFO) << "add channel type " << NL80211_BAND_5GHZ
               << " support at wiphy index: " << wiphy_index;
  }
  if (band_info.band_6g.size() != 0
      && band_to_wiphy_index_map_.find(NL80211_BAND_6GHZ) == band_to_wiphy_index_map_.end()) {
    band_to_wiphy_index_map_[NL80211_BAND_6GHZ] = wiphy_index;
    LOG(INFO) << "add channel type " << NL80211_BAND_6GHZ
               << " support at wiphy index: " << wiphy_index;
  }
  if (band_info.band_60g.size() != 0
      && band_to_wiphy_index_map_.find(NL80211_BAND_60GHZ) == band_to_wiphy_index_map_.end()) {
    band_to_wiphy_index_map_[NL80211_BAND_60GHZ] = wiphy_index;
    LOG(INFO) << "add channel type " << NL80211_BAND_60GHZ
               << " support at wiphy index: " << wiphy_index;
  }
}

void Server::EraseBandWiphyIndexMap(int wiphy_index) {
  LOG(DEBUG) << "EraseBandWiphyIndexMap for wiphy_index " << wiphy_index;
  for (auto it = band_to_wiphy_index_map_.begin();
      // end() is computed every iteration since erase() could invalidate it
      it != band_to_wiphy_index_map_.end();
      /* no increment */ ) {
    if (it->second == wiphy_index) {
      LOG(INFO) << "remove channel type " << it->first
                 << " support at wiphy index " << it->second;
      // erase returns iterator to element following erased element, or end() if the last element
      // was erased
      it = band_to_wiphy_index_map_.erase(it);
    } else {
      ++it;
    }
  }
}
}  // namespace wificond
}  // namespace android
