/*
 * 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 <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::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::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)) {
    UpdateBandWiphyIndexMap(wiphy_index);
  }
  LogSupportedBands(wiphy_index);
}

android::binder::Status Server::notifyCountryCodeChanged() {
  LOG(INFO) << "Receive notifyCountryCodeChanged";
  uint32_t wiphy_index;
  for (auto& it : client_interfaces_) {
    if (netlink_utils_->GetWiphyIndex(&wiphy_index, it.first)) {
      UpdateBandWiphyIndexMap(wiphy_index);
      LogSupportedBands(wiphy_index);
    }
  }
  for (auto& it : ap_interfaces_) {
    if (netlink_utils_->GetWiphyIndex(&wiphy_index, it.first)) {
      UpdateBandWiphyIndexMap(wiphy_index);
      LogSupportedBands(wiphy_index);
    }
  }
  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
