/* * 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. */ package com.android.server.wifi.util; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiScanner; import android.util.Log; import com.android.server.wifi.WifiNative; import java.util.ArrayList; import java.util.Random; /** * Provide utility functions for updating soft AP related configuration. */ public class ApConfigUtil { private static final String TAG = "ApConfigUtil"; public static final int DEFAULT_AP_BAND = WifiConfiguration.AP_BAND_2GHZ; public static final int DEFAULT_AP_CHANNEL = 6; /* Return code for updateConfiguration. */ public static final int SUCCESS = 0; public static final int ERROR_NO_CHANNEL = 1; public static final int ERROR_GENERIC = 2; /* Random number generator used for AP channel selection. */ private static final Random sRandom = new Random(); /** * Convert frequency to channel. * @param frequency frequency to convert * @return channel number associated with given frequency, -1 if no match */ public static int convertFrequencyToChannel(int frequency) { if (frequency >= 2412 && frequency <= 2472) { return (frequency - 2412) / 5 + 1; } else if (frequency == 2484) { return 14; } else if (frequency >= 5170 && frequency <= 5825) { /* DFS is included. */ return (frequency - 5170) / 5 + 34; } return -1; } /** * Return a channel number for AP setup based on the frequency band. * @param apBand 0 for 2GHz, 1 for 5GHz * @param allowed2GChannels list of allowed 2GHz channels * @param allowed5GFreqList list of allowed 5GHz frequencies * @return a valid channel number on success, -1 on failure. */ public static int chooseApChannel(int apBand, ArrayList allowed2GChannels, int[] allowed5GFreqList) { if (apBand != WifiConfiguration.AP_BAND_2GHZ && apBand != WifiConfiguration.AP_BAND_5GHZ) { Log.e(TAG, "Invalid band: " + apBand); return -1; } if (apBand == WifiConfiguration.AP_BAND_2GHZ) { /* Select a channel from 2GHz band. */ if (allowed2GChannels == null || allowed2GChannels.size() == 0) { Log.d(TAG, "2GHz allowed channel list not specified"); /* Use default channel. */ return DEFAULT_AP_CHANNEL; } /* Pick a random channel. */ int index = sRandom.nextInt(allowed2GChannels.size()); return allowed2GChannels.get(index).intValue(); } /* 5G without DFS. */ if (allowed5GFreqList != null && allowed5GFreqList.length > 0) { /* Pick a random channel from the list of supported channels. */ return convertFrequencyToChannel( allowed5GFreqList[sRandom.nextInt(allowed5GFreqList.length)]); } Log.e(TAG, "No available channels on 5GHz band"); return -1; } /** * Update AP band and channel based on the provided country code and band. * This will also set * @param wifiNative reference to WifiNative * @param countryCode country code * @param allowed2GChannels list of allowed 2GHz channels * @param config configuration to update * @return an integer result code */ public static int updateApChannelConfig(WifiNative wifiNative, String countryCode, ArrayList allowed2GChannels, WifiConfiguration config) { /* Use default band and channel for device without HAL. */ if (!wifiNative.isHalStarted()) { config.apBand = DEFAULT_AP_BAND; config.apChannel = DEFAULT_AP_CHANNEL; return SUCCESS; } /* Country code is mandatory for 5GHz band. */ if (config.apBand == WifiConfiguration.AP_BAND_5GHZ && countryCode == null) { Log.e(TAG, "5GHz band is not allowed without country code"); return ERROR_GENERIC; } /* Select a channel if it is not specified. */ if (config.apChannel == 0) { config.apChannel = chooseApChannel( config.apBand, allowed2GChannels, wifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ)); if (config.apChannel == -1) { if (wifiNative.isGetChannelsForBandSupported()) { /* We're not able to get channel when it is supported by HAL. */ Log.e(TAG, "Failed to get available channel."); return ERROR_NO_CHANNEL; } /* Use the default for HAL without get channel support. */ config.apBand = DEFAULT_AP_BAND; config.apChannel = DEFAULT_AP_CHANNEL; } } return SUCCESS; } }