/*
|
* 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 one of the value of WifiConfiguration.AP_BAND_*.
|
* @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<Integer> allowed2GChannels,
|
int[] allowed5GFreqList) {
|
if (apBand != WifiConfiguration.AP_BAND_2GHZ
|
&& apBand != WifiConfiguration.AP_BAND_5GHZ
|
&& apBand != WifiConfiguration.AP_BAND_ANY) {
|
Log.e(TAG, "Invalid band: " + apBand);
|
return -1;
|
}
|
|
// TODO(b/72120668): Create channel selection logic for AP_BAND_ANY.
|
if (apBand == WifiConfiguration.AP_BAND_2GHZ
|
|| apBand == WifiConfiguration.AP_BAND_ANY) {
|
/* 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<Integer> 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) {
|
/* We're not able to get channel from wificond. */
|
Log.e(TAG, "Failed to get available channel.");
|
return ERROR_NO_CHANNEL;
|
}
|
}
|
|
return SUCCESS;
|
}
|
}
|