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