WifiEnabler.java revision 1c4e96864f054f0d3d754d21eb4803fe0df6d89f
1/*
2 * Copyright (C) 2007 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.settings.wifi;
18
19import static android.net.wifi.WifiManager.WIFI_STATE_DISABLED;
20import static android.net.wifi.WifiManager.WIFI_STATE_DISABLING;
21import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED;
22import static android.net.wifi.WifiManager.WIFI_STATE_ENABLING;
23import static android.net.wifi.WifiManager.WIFI_STATE_UNKNOWN;
24
25import com.android.settings.R;
26import com.android.settings.AirplaneModeEnabler;
27
28import android.content.BroadcastReceiver;
29import android.content.Context;
30import android.content.Intent;
31import android.content.IntentFilter;
32import android.net.NetworkInfo;
33import android.net.wifi.WifiManager;
34import android.preference.Preference;
35import android.preference.CheckBoxPreference;
36import android.provider.Settings;
37import android.text.TextUtils;
38import android.util.Config;
39import android.util.Log;
40
41public class WifiEnabler implements Preference.OnPreferenceChangeListener {
42
43    private static final boolean LOCAL_LOGD = Config.LOGD || WifiLayer.LOGV;
44    private static final String TAG = "SettingsWifiEnabler";
45
46    private final Context mContext;
47    private final WifiManager mWifiManager;
48    private final CheckBoxPreference mWifiCheckBoxPref;
49    private final CharSequence mOriginalSummary;
50
51    private final IntentFilter mWifiStateFilter;
52    private final BroadcastReceiver mWifiStateReceiver = new BroadcastReceiver() {
53
54        @Override
55        public void onReceive(Context context, Intent intent) {
56            if (intent.getAction().equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
57                handleWifiStateChanged(
58                        intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WIFI_STATE_UNKNOWN),
59                        intent.getIntExtra(WifiManager.EXTRA_PREVIOUS_WIFI_STATE,
60                                WIFI_STATE_UNKNOWN));
61            } else if (intent.getAction().equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
62                handleNetworkStateChanged(
63                        (NetworkInfo) intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO));
64            }
65        }
66    };
67
68    public WifiEnabler(Context context, WifiManager wifiManager,
69            CheckBoxPreference wifiCheckBoxPreference) {
70        mContext = context;
71        mWifiCheckBoxPref = wifiCheckBoxPreference;
72        mWifiManager = wifiManager;
73
74        mOriginalSummary = wifiCheckBoxPreference.getSummary();
75        wifiCheckBoxPreference.setPersistent(false);
76
77        mWifiStateFilter = new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION);
78        mWifiStateFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
79    }
80
81    public void resume() {
82        int state = mWifiManager.getWifiState();
83        // This is the widget enabled state, not the preference toggled state
84        mWifiCheckBoxPref.setEnabled(state == WIFI_STATE_ENABLED || state == WIFI_STATE_DISABLED
85                || state == WIFI_STATE_UNKNOWN);
86
87        mContext.registerReceiver(mWifiStateReceiver, mWifiStateFilter);
88        mWifiCheckBoxPref.setOnPreferenceChangeListener(this);
89    }
90
91    public void pause() {
92        mContext.unregisterReceiver(mWifiStateReceiver);
93        mWifiCheckBoxPref.setOnPreferenceChangeListener(null);
94    }
95
96    public boolean onPreferenceChange(Preference preference, Object value) {
97        // Turn on/off Wi-Fi
98        setWifiEnabled((Boolean) value);
99
100        // Don't update UI to opposite state until we're sure
101        return false;
102    }
103
104    private void setWifiEnabled(final boolean enable) {
105        // Disable button
106        mWifiCheckBoxPref.setEnabled(false);
107
108        if (!mWifiManager.setWifiEnabled(enable)) {
109            mWifiCheckBoxPref.setSummary(enable ? R.string.error_starting : R.string.error_stopping);
110        }
111    }
112
113    private void handleWifiStateChanged(int wifiState, int previousWifiState) {
114
115        if (LOCAL_LOGD) {
116            Log.d(TAG, "Received wifi state changed from "
117                    + getHumanReadableWifiState(previousWifiState) + " to "
118                    + getHumanReadableWifiState(wifiState));
119        }
120
121        if (wifiState == WIFI_STATE_DISABLED || wifiState == WIFI_STATE_ENABLED) {
122            mWifiCheckBoxPref.setChecked(wifiState == WIFI_STATE_ENABLED);
123            mWifiCheckBoxPref
124                    .setSummary(wifiState == WIFI_STATE_DISABLED ? mOriginalSummary : null);
125
126            final boolean hasDependency = !TextUtils.isEmpty(mWifiCheckBoxPref.getDependency());
127            final boolean wifiAllowed = isWifiAllowed(mContext);
128
129            // Avoid disabling when dependencies have been manually set,
130            // workaround for framework bug http://b/2053751
131            if (wifiAllowed) {
132                mWifiCheckBoxPref.setEnabled(true);
133            } else if (!hasDependency) {
134                mWifiCheckBoxPref.setEnabled(false);
135            }
136
137        } else if (wifiState == WIFI_STATE_DISABLING || wifiState == WIFI_STATE_ENABLING) {
138            mWifiCheckBoxPref.setSummary(wifiState == WIFI_STATE_ENABLING ? R.string.wifi_starting
139                    : R.string.wifi_stopping);
140
141        } else if (wifiState == WIFI_STATE_UNKNOWN) {
142            int message = R.string.wifi_error;
143            if (previousWifiState == WIFI_STATE_ENABLING) message = R.string.error_starting;
144            else if (previousWifiState == WIFI_STATE_DISABLING) message = R.string.error_stopping;
145
146            mWifiCheckBoxPref.setChecked(false);
147            mWifiCheckBoxPref.setSummary(message);
148            mWifiCheckBoxPref.setEnabled(true);
149        }
150    }
151
152    private void handleNetworkStateChanged(NetworkInfo networkInfo) {
153
154        if (LOCAL_LOGD) {
155            Log.d(TAG, "Received network state changed to " + networkInfo);
156        }
157
158        if (mWifiManager.isWifiEnabled()) {
159            String summary = WifiStatus.getStatus(mContext,
160                    mWifiManager.getConnectionInfo().getSSID(), networkInfo.getDetailedState());
161            mWifiCheckBoxPref.setSummary(summary);
162        }
163    }
164
165    private static boolean isWifiAllowed(Context context) {
166        // allowed if we are not in airplane mode
167        if (!AirplaneModeEnabler.isAirplaneModeOn(context)) {
168            return true;
169        }
170        // allowed if wifi is not in AIRPLANE_MODE_RADIOS
171        String radios = Settings.System.getString(context.getContentResolver(),
172                Settings.System.AIRPLANE_MODE_RADIOS);
173        if (radios == null || !radios.contains(Settings.System.RADIO_WIFI)) {
174            return true;
175        }
176        // allowed if wifi is in AIRPLANE_MODE_TOGGLEABLE_RADIOS
177        radios = Settings.System.getString(context.getContentResolver(),
178                Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS);
179        return (radios != null && radios.contains(Settings.System.RADIO_WIFI));
180    }
181
182    private static String getHumanReadableWifiState(int wifiState) {
183        switch (wifiState) {
184            case WIFI_STATE_DISABLED:
185                return "Disabled";
186            case WIFI_STATE_DISABLING:
187                return "Disabling";
188            case WIFI_STATE_ENABLED:
189                return "Enabled";
190            case WIFI_STATE_ENABLING:
191                return "Enabling";
192            case WIFI_STATE_UNKNOWN:
193                return "Unknown";
194            default:
195                return "Some other state!";
196        }
197    }
198}
199