Home | History | Annotate | Download | only in wifi
      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.NetworkInfo;
     24 import android.net.wifi.SupplicantState;
     25 import android.net.wifi.WifiInfo;
     26 import android.net.wifi.WifiManager;
     27 import android.os.Handler;
     28 import android.os.Message;
     29 import android.provider.Settings;
     30 import android.widget.Switch;
     31 import android.widget.Toast;
     32 
     33 import com.android.internal.logging.MetricsLogger;
     34 import com.android.settings.R;
     35 import com.android.settings.search.Index;
     36 import com.android.settings.widget.SwitchBar;
     37 import com.android.settingslib.WirelessUtils;
     38 
     39 import java.util.concurrent.atomic.AtomicBoolean;
     40 
     41 public class WifiEnabler implements SwitchBar.OnSwitchChangeListener  {
     42     private Context mContext;
     43     private SwitchBar mSwitchBar;
     44     private boolean mListeningToOnSwitchChange = false;
     45     private AtomicBoolean mConnected = new AtomicBoolean(false);
     46 
     47     private final WifiManager mWifiManager;
     48     private boolean mStateMachineEvent;
     49     private final IntentFilter mIntentFilter;
     50     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
     51         @Override
     52         public void onReceive(Context context, Intent intent) {
     53             String action = intent.getAction();
     54             if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {
     55                 handleWifiStateChanged(intent.getIntExtra(
     56                         WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN));
     57             } else if (WifiManager.SUPPLICANT_STATE_CHANGED_ACTION.equals(action)) {
     58                 if (!mConnected.get()) {
     59                     handleStateChanged(WifiInfo.getDetailedStateOf((SupplicantState)
     60                             intent.getParcelableExtra(WifiManager.EXTRA_NEW_STATE)));
     61                 }
     62             } else if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)) {
     63                 NetworkInfo info = (NetworkInfo) intent.getParcelableExtra(
     64                         WifiManager.EXTRA_NETWORK_INFO);
     65                 mConnected.set(info.isConnected());
     66                 handleStateChanged(info.getDetailedState());
     67             }
     68         }
     69     };
     70 
     71     private static final String EVENT_DATA_IS_WIFI_ON = "is_wifi_on";
     72     private static final int EVENT_UPDATE_INDEX = 0;
     73 
     74     private Handler mHandler = new Handler() {
     75         @Override
     76         public void handleMessage(Message msg) {
     77             switch (msg.what) {
     78                 case EVENT_UPDATE_INDEX:
     79                     final boolean isWiFiOn = msg.getData().getBoolean(EVENT_DATA_IS_WIFI_ON);
     80                     Index.getInstance(mContext).updateFromClassNameResource(
     81                             WifiSettings.class.getName(), true, isWiFiOn);
     82                     break;
     83             }
     84         }
     85     };
     86 
     87     public WifiEnabler(Context context, SwitchBar switchBar) {
     88         mContext = context;
     89         mSwitchBar = switchBar;
     90 
     91         mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
     92 
     93         mIntentFilter = new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION);
     94         // The order matters! We really should not depend on this. :(
     95         mIntentFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
     96         mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
     97 
     98         setupSwitchBar();
     99     }
    100 
    101     public void setupSwitchBar() {
    102         final int state = mWifiManager.getWifiState();
    103         handleWifiStateChanged(state);
    104         if (!mListeningToOnSwitchChange) {
    105             mSwitchBar.addOnSwitchChangeListener(this);
    106             mListeningToOnSwitchChange = true;
    107         }
    108         mSwitchBar.show();
    109     }
    110 
    111     public void teardownSwitchBar() {
    112         if (mListeningToOnSwitchChange) {
    113             mSwitchBar.removeOnSwitchChangeListener(this);
    114             mListeningToOnSwitchChange = false;
    115         }
    116         mSwitchBar.hide();
    117     }
    118 
    119     public void resume(Context context) {
    120         mContext = context;
    121         // Wi-Fi state is sticky, so just let the receiver update UI
    122         mContext.registerReceiver(mReceiver, mIntentFilter);
    123         if (!mListeningToOnSwitchChange) {
    124             mSwitchBar.addOnSwitchChangeListener(this);
    125             mListeningToOnSwitchChange = true;
    126         }
    127     }
    128 
    129     public void pause() {
    130         mContext.unregisterReceiver(mReceiver);
    131         if (mListeningToOnSwitchChange) {
    132             mSwitchBar.removeOnSwitchChangeListener(this);
    133             mListeningToOnSwitchChange = false;
    134         }
    135     }
    136 
    137     private void handleWifiStateChanged(int state) {
    138         switch (state) {
    139             case WifiManager.WIFI_STATE_ENABLING:
    140                 mSwitchBar.setEnabled(false);
    141                 break;
    142             case WifiManager.WIFI_STATE_ENABLED:
    143                 setSwitchBarChecked(true);
    144                 mSwitchBar.setEnabled(true);
    145                 updateSearchIndex(true);
    146                 break;
    147             case WifiManager.WIFI_STATE_DISABLING:
    148                 mSwitchBar.setEnabled(false);
    149                 break;
    150             case WifiManager.WIFI_STATE_DISABLED:
    151                 setSwitchBarChecked(false);
    152                 mSwitchBar.setEnabled(true);
    153                 updateSearchIndex(false);
    154                 break;
    155             default:
    156                 setSwitchBarChecked(false);
    157                 mSwitchBar.setEnabled(true);
    158                 updateSearchIndex(false);
    159         }
    160     }
    161 
    162     private void updateSearchIndex(boolean isWiFiOn) {
    163         mHandler.removeMessages(EVENT_UPDATE_INDEX);
    164 
    165         Message msg = new Message();
    166         msg.what = EVENT_UPDATE_INDEX;
    167         msg.getData().putBoolean(EVENT_DATA_IS_WIFI_ON, isWiFiOn);
    168         mHandler.sendMessage(msg);
    169     }
    170 
    171     private void setSwitchBarChecked(boolean checked) {
    172         mStateMachineEvent = true;
    173         mSwitchBar.setChecked(checked);
    174         mStateMachineEvent = false;
    175     }
    176 
    177     private void handleStateChanged(@SuppressWarnings("unused") NetworkInfo.DetailedState state) {
    178         // After the refactoring from a CheckBoxPreference to a Switch, this method is useless since
    179         // there is nowhere to display a summary.
    180         // This code is kept in case a future change re-introduces an associated text.
    181         /*
    182         // WifiInfo is valid if and only if Wi-Fi is enabled.
    183         // Here we use the state of the switch as an optimization.
    184         if (state != null && mSwitch.isChecked()) {
    185             WifiInfo info = mWifiManager.getConnectionInfo();
    186             if (info != null) {
    187                 //setSummary(Summary.get(mContext, info.getSSID(), state));
    188             }
    189         }
    190         */
    191     }
    192 
    193     @Override
    194     public void onSwitchChanged(Switch switchView, boolean isChecked) {
    195         //Do nothing if called as a result of a state machine event
    196         if (mStateMachineEvent) {
    197             return;
    198         }
    199         // Show toast message if Wi-Fi is not allowed in airplane mode
    200         if (isChecked && !WirelessUtils.isRadioAllowed(mContext, Settings.Global.RADIO_WIFI)) {
    201             Toast.makeText(mContext, R.string.wifi_in_airplane_mode, Toast.LENGTH_SHORT).show();
    202             // Reset switch to off. No infinite check/listenenr loop.
    203             mSwitchBar.setChecked(false);
    204             return;
    205         }
    206 
    207         // Disable tethering if enabling Wifi
    208         int wifiApState = mWifiManager.getWifiApState();
    209         if (isChecked && ((wifiApState == WifiManager.WIFI_AP_STATE_ENABLING) ||
    210                 (wifiApState == WifiManager.WIFI_AP_STATE_ENABLED))) {
    211             mWifiManager.setWifiApEnabled(null, false);
    212         }
    213         MetricsLogger.action(mContext,
    214                 isChecked ? MetricsLogger.ACTION_WIFI_ON : MetricsLogger.ACTION_WIFI_OFF);
    215         if (!mWifiManager.setWifiEnabled(isChecked)) {
    216             // Error
    217             mSwitchBar.setEnabled(true);
    218             Toast.makeText(mContext, R.string.wifi_error, Toast.LENGTH_SHORT).show();
    219         }
    220     }
    221 }
    222