• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 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.settings.wifi;
18 
19 import android.content.BroadcastReceiver;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.content.IntentFilter;
23 import android.net.ConnectivityManager;
24 import android.net.NetworkInfo;
25 import android.net.wifi.SupplicantState;
26 import android.net.wifi.WifiInfo;
27 import android.net.wifi.WifiManager;
28 import android.os.UserHandle;
29 import android.os.UserManager;
30 import android.provider.Settings;
31 import android.support.annotation.VisibleForTesting;
32 import android.widget.Toast;
33 
34 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
35 import com.android.settings.R;
36 import com.android.settings.core.instrumentation.MetricsFeatureProvider;
37 import com.android.settings.widget.SwitchWidgetController;
38 import com.android.settingslib.RestrictedLockUtils;
39 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
40 import com.android.settingslib.WirelessUtils;
41 
42 import java.util.concurrent.atomic.AtomicBoolean;
43 
44 public class WifiEnabler implements SwitchWidgetController.OnSwitchChangeListener  {
45 
46     private final SwitchWidgetController mSwitchWidget;
47     private final WifiManager mWifiManager;
48     private final ConnectivityManagerWrapper mConnectivityManager;
49     private final MetricsFeatureProvider mMetricsFeatureProvider;
50 
51     private Context mContext;
52     private boolean mListeningToOnSwitchChange = false;
53     private AtomicBoolean mConnected = new AtomicBoolean(false);
54 
55 
56     private boolean mStateMachineEvent;
57     private final IntentFilter mIntentFilter;
58     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
59         @Override
60         public void onReceive(Context context, Intent intent) {
61             String action = intent.getAction();
62             if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {
63                 handleWifiStateChanged(mWifiManager.getWifiState());
64             } else if (WifiManager.SUPPLICANT_STATE_CHANGED_ACTION.equals(action)) {
65                 if (!mConnected.get()) {
66                     handleStateChanged(WifiInfo.getDetailedStateOf((SupplicantState)
67                             intent.getParcelableExtra(WifiManager.EXTRA_NEW_STATE)));
68                 }
69             } else if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)) {
70                 NetworkInfo info = (NetworkInfo) intent.getParcelableExtra(
71                         WifiManager.EXTRA_NETWORK_INFO);
72                 mConnected.set(info.isConnected());
73                 handleStateChanged(info.getDetailedState());
74             }
75         }
76     };
77 
78     private static final String EVENT_DATA_IS_WIFI_ON = "is_wifi_on";
79     private static final int EVENT_UPDATE_INDEX = 0;
80 
WifiEnabler(Context context, SwitchWidgetController switchWidget, MetricsFeatureProvider metricsFeatureProvider)81     public WifiEnabler(Context context, SwitchWidgetController switchWidget,
82         MetricsFeatureProvider metricsFeatureProvider) {
83         this(context, switchWidget, metricsFeatureProvider, new ConnectivityManagerWrapper(
84             (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE)));
85     }
86 
87     @VisibleForTesting
WifiEnabler(Context context, SwitchWidgetController switchWidget, MetricsFeatureProvider metricsFeatureProvider, ConnectivityManagerWrapper connectivityManagerWrapper)88     WifiEnabler(Context context, SwitchWidgetController switchWidget,
89             MetricsFeatureProvider metricsFeatureProvider,
90             ConnectivityManagerWrapper connectivityManagerWrapper) {
91         mContext = context;
92         mSwitchWidget = switchWidget;
93         mSwitchWidget.setListener(this);
94         mMetricsFeatureProvider = metricsFeatureProvider;
95         mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
96         mConnectivityManager = connectivityManagerWrapper;
97 
98         mIntentFilter = new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION);
99         // The order matters! We really should not depend on this. :(
100         mIntentFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
101         mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
102 
103         setupSwitchController();
104     }
105 
setupSwitchController()106     public void setupSwitchController() {
107         final int state = mWifiManager.getWifiState();
108         handleWifiStateChanged(state);
109         if (!mListeningToOnSwitchChange) {
110             mSwitchWidget.startListening();
111             mListeningToOnSwitchChange = true;
112         }
113         mSwitchWidget.setupView();
114     }
115 
teardownSwitchController()116     public void teardownSwitchController() {
117         if (mListeningToOnSwitchChange) {
118             mSwitchWidget.stopListening();
119             mListeningToOnSwitchChange = false;
120         }
121         mSwitchWidget.teardownView();
122     }
123 
resume(Context context)124     public void resume(Context context) {
125         mContext = context;
126         // Wi-Fi state is sticky, so just let the receiver update UI
127         mContext.registerReceiver(mReceiver, mIntentFilter);
128         if (!mListeningToOnSwitchChange) {
129             mSwitchWidget.startListening();
130             mListeningToOnSwitchChange = true;
131         }
132     }
133 
pause()134     public void pause() {
135         mContext.unregisterReceiver(mReceiver);
136         if (mListeningToOnSwitchChange) {
137             mSwitchWidget.stopListening();
138             mListeningToOnSwitchChange = false;
139         }
140     }
141 
handleWifiStateChanged(int state)142     private void handleWifiStateChanged(int state) {
143         // Clear any previous state
144         mSwitchWidget.setDisabledByAdmin(null);
145 
146         switch (state) {
147             case WifiManager.WIFI_STATE_ENABLING:
148                 break;
149             case WifiManager.WIFI_STATE_ENABLED:
150                 setSwitchBarChecked(true);
151                 mSwitchWidget.setEnabled(true);
152                 break;
153             case WifiManager.WIFI_STATE_DISABLING:
154                 break;
155             case WifiManager.WIFI_STATE_DISABLED:
156                 setSwitchBarChecked(false);
157                 mSwitchWidget.setEnabled(true);
158                 break;
159             default:
160                 setSwitchBarChecked(false);
161                 mSwitchWidget.setEnabled(true);
162         }
163         if (mayDisableTethering(!mSwitchWidget.isChecked())) {
164             if (RestrictedLockUtils.hasBaseUserRestriction(mContext,
165                     UserManager.DISALLOW_CONFIG_TETHERING, UserHandle.myUserId())) {
166                 mSwitchWidget.setEnabled(false);
167             } else {
168                 final EnforcedAdmin admin = RestrictedLockUtils.checkIfRestrictionEnforced(mContext,
169                     UserManager.DISALLOW_CONFIG_TETHERING, UserHandle.myUserId());
170                 mSwitchWidget.setDisabledByAdmin(admin);
171             }
172         }
173     }
174 
setSwitchBarChecked(boolean checked)175     private void setSwitchBarChecked(boolean checked) {
176         mStateMachineEvent = true;
177         mSwitchWidget.setChecked(checked);
178         mStateMachineEvent = false;
179     }
180 
handleStateChanged(@uppressWarnings"unused") NetworkInfo.DetailedState state)181     private void handleStateChanged(@SuppressWarnings("unused") NetworkInfo.DetailedState state) {
182         // After the refactoring from a CheckBoxPreference to a Switch, this method is useless since
183         // there is nowhere to display a summary.
184         // This code is kept in case a future change re-introduces an associated text.
185         /*
186         // WifiInfo is valid if and only if Wi-Fi is enabled.
187         // Here we use the state of the switch as an optimization.
188         if (state != null && mSwitch.isChecked()) {
189             WifiInfo info = mWifiManager.getConnectionInfo();
190             if (info != null) {
191                 //setSummary(Summary.get(mContext, info.getSSID(), state));
192             }
193         }
194         */
195     }
196 
197     @Override
onSwitchToggled(boolean isChecked)198     public boolean onSwitchToggled(boolean isChecked) {
199         //Do nothing if called as a result of a state machine event
200         if (mStateMachineEvent) {
201             return true;
202         }
203         // Show toast message if Wi-Fi is not allowed in airplane mode
204         if (isChecked && !WirelessUtils.isRadioAllowed(mContext, Settings.Global.RADIO_WIFI)) {
205             Toast.makeText(mContext, R.string.wifi_in_airplane_mode, Toast.LENGTH_SHORT).show();
206             // Reset switch to off. No infinite check/listenenr loop.
207             mSwitchWidget.setChecked(false);
208             return false;
209         }
210 
211         // Disable tethering if enabling Wifi
212         if (mayDisableTethering(isChecked)) {
213             mConnectivityManager.stopTethering(ConnectivityManager.TETHERING_WIFI);
214         }
215         if (isChecked) {
216             mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_WIFI_ON);
217         } else {
218             // Log if user was connected at the time of switching off.
219             mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_WIFI_OFF,
220                     mConnected.get());
221         }
222         if (!mWifiManager.setWifiEnabled(isChecked)) {
223             // Error
224             mSwitchWidget.setEnabled(true);
225             Toast.makeText(mContext, R.string.wifi_error, Toast.LENGTH_SHORT).show();
226         }
227         return true;
228     }
229 
mayDisableTethering(boolean isChecked)230     private boolean mayDisableTethering(boolean isChecked) {
231         final int wifiApState = mWifiManager.getWifiApState();
232         return isChecked && ((wifiApState == WifiManager.WIFI_AP_STATE_ENABLING) ||
233             (wifiApState == WifiManager.WIFI_AP_STATE_ENABLED));
234     }
235 }
236