Home | History | Annotate | Download | only in wifi
      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 
     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      */
     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      */
     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      */
     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      */
    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      */
    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      */
    154     public synchronized String getCurrentCountryCode() {
    155         return mCurrentCountryCode;
    156     }
    157 
    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 
    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 
    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