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; 18 19 import android.text.TextUtils; 20 import android.util.Log; 21 22 /** 23 * Provide functions for making changes to WiFi country code. 24 */ 25 public class WifiCountryCode { 26 private static final String TAG = "WifiCountryCode"; 27 private final WifiNative mWifiNative; 28 private boolean DBG = false; 29 private boolean mReady = false; 30 31 /** config option that indicate whether or not to reset country code to default when 32 * cellular radio indicates country code loss 33 */ 34 private boolean mRevertCountryCodeOnCellularLoss; 35 private String mDefaultCountryCode = null; 36 private String mTelephonyCountryCode = null; 37 private String mCurrentCountryCode = null; 38 WifiCountryCode( WifiNative wifiNative, String oemDefaultCountryCode, String persistentCountryCode, boolean revertCountryCodeOnCellularLoss)39 public WifiCountryCode( 40 WifiNative wifiNative, 41 String oemDefaultCountryCode, 42 String persistentCountryCode, 43 boolean revertCountryCodeOnCellularLoss) { 44 45 mWifiNative = wifiNative; 46 mRevertCountryCodeOnCellularLoss = revertCountryCodeOnCellularLoss; 47 48 if (!TextUtils.isEmpty(persistentCountryCode)) { 49 mDefaultCountryCode = persistentCountryCode.toUpperCase(); 50 } else if (!TextUtils.isEmpty(oemDefaultCountryCode)) { 51 mDefaultCountryCode = oemDefaultCountryCode.toUpperCase(); 52 } else { 53 if (mRevertCountryCodeOnCellularLoss) { 54 Log.w(TAG, "config_wifi_revert_country_code_on_cellular_loss is set, " 55 + "but there is no default country code."); 56 mRevertCountryCodeOnCellularLoss = false; 57 return; 58 } 59 } 60 61 if (mRevertCountryCodeOnCellularLoss) { 62 Log.d(TAG, "Country code will be reverted to " + mDefaultCountryCode 63 + " on MCC loss"); 64 } 65 } 66 67 /** 68 * Enable verbose logging for WifiCountryCode. 69 */ enableVerboseLogging(int verbose)70 public void enableVerboseLogging(int verbose) { 71 if (verbose > 0) { 72 DBG = true; 73 } else { 74 DBG = false; 75 } 76 } 77 78 /** 79 * This is called when sim card is removed. 80 * In this case we should invalid all other country codes except the 81 * phone default one. 82 */ simCardRemoved()83 public synchronized void simCardRemoved() { 84 if (DBG) Log.d(TAG, "SIM Card Removed"); 85 // SIM card is removed, we need to reset the country code to phone default. 86 if (mRevertCountryCodeOnCellularLoss) { 87 mTelephonyCountryCode = null; 88 if (mReady) { 89 updateCountryCode(); 90 } 91 } 92 } 93 94 /** 95 * This is called when airplane mode is enabled. 96 * In this case we should invalidate all other country code except the 97 * phone default one. 98 */ airplaneModeEnabled()99 public synchronized void airplaneModeEnabled() { 100 if (DBG) Log.d(TAG, "Airplane Mode Enabled"); 101 mTelephonyCountryCode = null; 102 // Airplane mode is enabled, we need to reset the country code to phone default. 103 if (mRevertCountryCodeOnCellularLoss) { 104 mTelephonyCountryCode = null; 105 // Country code will be set upon when wpa_supplicant starts next time. 106 } 107 } 108 109 /** 110 * Change the state to indicates if wpa_supplicant is ready to handle country code changing 111 * request or not. 112 * We call native code to request country code changes only when wpa_supplicant is 113 * started but not yet L2 connected. 114 */ setReadyForChange(boolean ready)115 public synchronized void setReadyForChange(boolean ready) { 116 if (DBG) Log.d(TAG, "Set ready: " + ready); 117 mReady = ready; 118 // We are ready to set country code now. 119 // We need to post pending country code request. 120 if (mReady) { 121 updateCountryCode(); 122 } 123 } 124 125 /** 126 * Handle country code change request. 127 * @param countryCode The country code intended to set. 128 * This is supposed to be from Telephony service. 129 * otherwise we think it is from other applications. 130 * @return Returns true if the country code passed in is acceptable. 131 */ setCountryCode(String countryCode, boolean persist)132 public synchronized boolean setCountryCode(String countryCode, boolean persist) { 133 if (DBG) Log.d(TAG, "Receive set country code request: " + countryCode); 134 // Ignore empty country code. 135 if (TextUtils.isEmpty(countryCode)) { 136 if (DBG) Log.d(TAG, "Ignore empty country code"); 137 return false; 138 } 139 if (persist) { 140 mDefaultCountryCode = countryCode; 141 } 142 mTelephonyCountryCode = countryCode.toUpperCase(); 143 // If wpa_supplicant is ready we set the country code now, otherwise it will be 144 // set once wpa_supplicant is ready. 145 if (mReady) { 146 updateCountryCode(); 147 } 148 return true; 149 } 150 151 /** 152 * @return Get the current country code, returns null if no country code is set. 153 */ getCurrentCountryCode()154 public synchronized String getCurrentCountryCode() { 155 return mCurrentCountryCode; 156 } 157 updateCountryCode()158 private void updateCountryCode() { 159 if (DBG) Log.d(TAG, "Update country code"); 160 String country = pickCountryCode(); 161 // We do not check if the country code equals the current one. 162 // There are two reasons: 163 // 1. Wpa supplicant may silently modify the country code. 164 // 2. If Wifi restarted therefoere wpa_supplicant also restarted, 165 // the country code counld be reset to '00' by wpa_supplicant. 166 if (country.length() != 0) { 167 setCountryCodeNative(country); 168 } 169 // We do not set country code if there is no candidate. This is reasonable 170 // because wpa_supplicant usually starts with an international safe country 171 // code setting: '00'. 172 } 173 pickCountryCode()174 private String pickCountryCode() { 175 if (mTelephonyCountryCode != null) { 176 return mTelephonyCountryCode; 177 } 178 if (mDefaultCountryCode != null) { 179 return mDefaultCountryCode; 180 } 181 // If there is no candidate country code we will return an empty string. 182 return ""; 183 } 184 setCountryCodeNative(String country)185 private boolean setCountryCodeNative(String country) { 186 if (mWifiNative.setCountryCode(country)) { 187 Log.d(TAG, "Succeeded to set country code to: " + country); 188 mCurrentCountryCode = country; 189 return true; 190 } 191 Log.d(TAG, "Failed to set country code to: " + country); 192 return false; 193 } 194 } 195 196