1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.wifi.util; 18 19 import android.net.wifi.WifiConfiguration; 20 import android.net.wifi.WifiScanner; 21 import android.util.Log; 22 23 import com.android.server.wifi.WifiNative; 24 25 import java.util.ArrayList; 26 import java.util.Random; 27 28 /** 29 * Provide utility functions for updating soft AP related configuration. 30 */ 31 public class ApConfigUtil { 32 private static final String TAG = "ApConfigUtil"; 33 34 public static final int DEFAULT_AP_BAND = WifiConfiguration.AP_BAND_2GHZ; 35 public static final int DEFAULT_AP_CHANNEL = 6; 36 37 /* Return code for updateConfiguration. */ 38 public static final int SUCCESS = 0; 39 public static final int ERROR_NO_CHANNEL = 1; 40 public static final int ERROR_GENERIC = 2; 41 42 /* Random number generator used for AP channel selection. */ 43 private static final Random sRandom = new Random(); 44 45 /** 46 * Convert frequency to channel. 47 * @param frequency frequency to convert 48 * @return channel number associated with given frequency, -1 if no match 49 */ 50 public static int convertFrequencyToChannel(int frequency) { 51 if (frequency >= 2412 && frequency <= 2472) { 52 return (frequency - 2412) / 5 + 1; 53 } else if (frequency == 2484) { 54 return 14; 55 } else if (frequency >= 5170 && frequency <= 5825) { 56 /* DFS is included. */ 57 return (frequency - 5170) / 5 + 34; 58 } 59 60 return -1; 61 } 62 63 /** 64 * Return a channel number for AP setup based on the frequency band. 65 * @param apBand 0 for 2GHz, 1 for 5GHz 66 * @param allowed2GChannels list of allowed 2GHz channels 67 * @param allowed5GFreqList list of allowed 5GHz frequencies 68 * @return a valid channel number on success, -1 on failure. 69 */ 70 public static int chooseApChannel(int apBand, 71 ArrayList<Integer> allowed2GChannels, 72 int[] allowed5GFreqList) { 73 if (apBand != WifiConfiguration.AP_BAND_2GHZ 74 && apBand != WifiConfiguration.AP_BAND_5GHZ) { 75 Log.e(TAG, "Invalid band: " + apBand); 76 return -1; 77 } 78 79 if (apBand == WifiConfiguration.AP_BAND_2GHZ) { 80 /* Select a channel from 2GHz band. */ 81 if (allowed2GChannels == null || allowed2GChannels.size() == 0) { 82 Log.d(TAG, "2GHz allowed channel list not specified"); 83 /* Use default channel. */ 84 return DEFAULT_AP_CHANNEL; 85 } 86 87 /* Pick a random channel. */ 88 int index = sRandom.nextInt(allowed2GChannels.size()); 89 return allowed2GChannels.get(index).intValue(); 90 } 91 92 /* 5G without DFS. */ 93 if (allowed5GFreqList != null && allowed5GFreqList.length > 0) { 94 /* Pick a random channel from the list of supported channels. */ 95 return convertFrequencyToChannel( 96 allowed5GFreqList[sRandom.nextInt(allowed5GFreqList.length)]); 97 } 98 99 Log.e(TAG, "No available channels on 5GHz band"); 100 return -1; 101 } 102 103 /** 104 * Update AP band and channel based on the provided country code and band. 105 * This will also set 106 * @param wifiNative reference to WifiNative 107 * @param countryCode country code 108 * @param allowed2GChannels list of allowed 2GHz channels 109 * @param config configuration to update 110 * @return an integer result code 111 */ 112 public static int updateApChannelConfig(WifiNative wifiNative, 113 String countryCode, 114 ArrayList<Integer> allowed2GChannels, 115 WifiConfiguration config) { 116 /* Use default band and channel for device without HAL. */ 117 if (!wifiNative.isHalStarted()) { 118 config.apBand = DEFAULT_AP_BAND; 119 config.apChannel = DEFAULT_AP_CHANNEL; 120 return SUCCESS; 121 } 122 123 /* Country code is mandatory for 5GHz band. */ 124 if (config.apBand == WifiConfiguration.AP_BAND_5GHZ 125 && countryCode == null) { 126 Log.e(TAG, "5GHz band is not allowed without country code"); 127 return ERROR_GENERIC; 128 } 129 130 /* Select a channel if it is not specified. */ 131 if (config.apChannel == 0) { 132 config.apChannel = chooseApChannel( 133 config.apBand, allowed2GChannels, 134 wifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ)); 135 if (config.apChannel == -1) { 136 if (wifiNative.isGetChannelsForBandSupported()) { 137 /* We're not able to get channel when it is supported by HAL. */ 138 Log.e(TAG, "Failed to get available channel."); 139 return ERROR_NO_CHANNEL; 140 } 141 142 /* Use the default for HAL without get channel support. */ 143 config.apBand = DEFAULT_AP_BAND; 144 config.apChannel = DEFAULT_AP_CHANNEL; 145 } 146 } 147 148 return SUCCESS; 149 } 150 } 151