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