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