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
17package com.android.settings.wifi;
18
19import com.android.settings.R;
20import com.android.settings.WirelessSettings;
21
22import java.util.ArrayList;
23
24import android.app.AlertDialog;
25import android.content.BroadcastReceiver;
26import android.content.ContentResolver;
27import android.content.Context;
28import android.content.Intent;
29import android.content.IntentFilter;
30import android.net.ConnectivityManager;
31import android.net.NetworkInfo;
32import android.net.wifi.SupplicantState;
33import android.net.wifi.WifiConfiguration;
34import android.net.wifi.WifiInfo;
35import android.net.wifi.WifiManager;
36import android.preference.CheckBoxPreference;
37import android.provider.Settings;
38import android.text.TextUtils;
39import android.util.Log;
40import android.widget.Toast;
41
42public class WifiApEnabler {
43    private final Context mContext;
44    private final CheckBoxPreference mCheckBox;
45    private final CharSequence mOriginalSummary;
46
47    private WifiManager mWifiManager;
48    private final IntentFilter mIntentFilter;
49
50    ConnectivityManager mCm;
51    private String[] mWifiRegexs;
52
53    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
54        @Override
55        public void onReceive(Context context, Intent intent) {
56            String action = intent.getAction();
57            if (WifiManager.WIFI_AP_STATE_CHANGED_ACTION.equals(action)) {
58                handleWifiApStateChanged(intent.getIntExtra(
59                        WifiManager.EXTRA_WIFI_AP_STATE, WifiManager.WIFI_AP_STATE_FAILED));
60            } else if (ConnectivityManager.ACTION_TETHER_STATE_CHANGED.equals(action)) {
61                ArrayList<String> available = intent.getStringArrayListExtra(
62                        ConnectivityManager.EXTRA_AVAILABLE_TETHER);
63                ArrayList<String> active = intent.getStringArrayListExtra(
64                        ConnectivityManager.EXTRA_ACTIVE_TETHER);
65                ArrayList<String> errored = intent.getStringArrayListExtra(
66                        ConnectivityManager.EXTRA_ERRORED_TETHER);
67                updateTetherState(available.toArray(), active.toArray(), errored.toArray());
68            } else if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(action)) {
69                enableWifiCheckBox();
70            }
71
72        }
73    };
74
75    public WifiApEnabler(Context context, CheckBoxPreference checkBox) {
76        mContext = context;
77        mCheckBox = checkBox;
78        mOriginalSummary = checkBox.getSummary();
79        checkBox.setPersistent(false);
80
81        mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
82        mCm = (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
83
84        mWifiRegexs = mCm.getTetherableWifiRegexs();
85
86        mIntentFilter = new IntentFilter(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
87        mIntentFilter.addAction(ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
88        mIntentFilter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
89    }
90
91    public void resume() {
92        mContext.registerReceiver(mReceiver, mIntentFilter);
93        enableWifiCheckBox();
94    }
95
96    public void pause() {
97        mContext.unregisterReceiver(mReceiver);
98    }
99
100    private void enableWifiCheckBox() {
101        boolean isAirplaneMode = Settings.System.getInt(mContext.getContentResolver(),
102                Settings.System.AIRPLANE_MODE_ON, 0) != 0;
103        if(!isAirplaneMode) {
104            mCheckBox.setEnabled(true);
105        } else {
106            mCheckBox.setSummary(mOriginalSummary);
107            mCheckBox.setEnabled(false);
108        }
109    }
110
111    public void setSoftapEnabled(boolean enable) {
112        final ContentResolver cr = mContext.getContentResolver();
113        /**
114         * Disable Wifi if enabling tethering
115         */
116        int wifiState = mWifiManager.getWifiState();
117        if (enable && ((wifiState == WifiManager.WIFI_STATE_ENABLING) ||
118                    (wifiState == WifiManager.WIFI_STATE_ENABLED))) {
119            mWifiManager.setWifiEnabled(false);
120            Settings.Secure.putInt(cr, Settings.Secure.WIFI_SAVED_STATE, 1);
121        }
122
123        if (mWifiManager.setWifiApEnabled(null, enable)) {
124            /* Disable here, enabled on receiving success broadcast */
125            mCheckBox.setEnabled(false);
126        } else {
127            mCheckBox.setSummary(R.string.wifi_error);
128        }
129
130        /**
131         *  If needed, restore Wifi on tether disable
132         */
133        if (!enable) {
134            int wifiSavedState = 0;
135            try {
136                wifiSavedState = Settings.Secure.getInt(cr, Settings.Secure.WIFI_SAVED_STATE);
137            } catch (Settings.SettingNotFoundException e) {
138                ;
139            }
140            if (wifiSavedState == 1) {
141                mWifiManager.setWifiEnabled(true);
142                Settings.Secure.putInt(cr, Settings.Secure.WIFI_SAVED_STATE, 0);
143            }
144        }
145    }
146
147    public void updateConfigSummary(WifiConfiguration wifiConfig) {
148        String s = mContext.getString(
149                com.android.internal.R.string.wifi_tether_configure_ssid_default);
150        mCheckBox.setSummary(String.format(
151                    mContext.getString(R.string.wifi_tether_enabled_subtext),
152                    (wifiConfig == null) ? s : wifiConfig.SSID));
153    }
154
155    private void updateTetherState(Object[] available, Object[] tethered, Object[] errored) {
156        boolean wifiTethered = false;
157        boolean wifiErrored = false;
158
159        for (Object o : tethered) {
160            String s = (String)o;
161            for (String regex : mWifiRegexs) {
162                if (s.matches(regex)) wifiTethered = true;
163            }
164        }
165        for (Object o: errored) {
166            String s = (String)o;
167            for (String regex : mWifiRegexs) {
168                if (s.matches(regex)) wifiErrored = true;
169            }
170        }
171
172        if (wifiTethered) {
173            WifiConfiguration wifiConfig = mWifiManager.getWifiApConfiguration();
174            updateConfigSummary(wifiConfig);
175        } else if (wifiErrored) {
176            mCheckBox.setSummary(R.string.wifi_error);
177        }
178    }
179
180    private void handleWifiApStateChanged(int state) {
181        switch (state) {
182            case WifiManager.WIFI_AP_STATE_ENABLING:
183                mCheckBox.setSummary(R.string.wifi_starting);
184                mCheckBox.setEnabled(false);
185                break;
186            case WifiManager.WIFI_AP_STATE_ENABLED:
187                /**
188                 * Summary on enable is handled by tether
189                 * broadcast notice
190                 */
191                mCheckBox.setChecked(true);
192                /* Doesnt need the airplane check */
193                mCheckBox.setEnabled(true);
194                break;
195            case WifiManager.WIFI_AP_STATE_DISABLING:
196                mCheckBox.setSummary(R.string.wifi_stopping);
197                mCheckBox.setEnabled(false);
198                break;
199            case WifiManager.WIFI_AP_STATE_DISABLED:
200                mCheckBox.setChecked(false);
201                mCheckBox.setSummary(mOriginalSummary);
202                enableWifiCheckBox();
203                break;
204            default:
205                mCheckBox.setChecked(false);
206                mCheckBox.setSummary(R.string.wifi_error);
207                enableWifiCheckBox();
208        }
209    }
210}
211