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 android.content.BroadcastReceiver;
20import android.content.Context;
21import android.content.Intent;
22import android.content.IntentFilter;
23import android.net.ConnectivityManager;
24import android.net.wifi.WifiConfiguration;
25import android.net.wifi.WifiManager;
26import android.preference.SwitchPreference;
27import android.provider.Settings;
28
29import com.android.settings.R;
30import com.android.settingslib.TetherUtil;
31
32import java.util.ArrayList;
33
34public class WifiApEnabler {
35    private final Context mContext;
36    private final SwitchPreference mSwitch;
37    private final CharSequence mOriginalSummary;
38
39    private WifiManager mWifiManager;
40    private final IntentFilter mIntentFilter;
41
42    ConnectivityManager mCm;
43    private String[] mWifiRegexs;
44
45    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
46        @Override
47        public void onReceive(Context context, Intent intent) {
48            String action = intent.getAction();
49            if (WifiManager.WIFI_AP_STATE_CHANGED_ACTION.equals(action)) {
50                int state = intent.getIntExtra(
51                        WifiManager.EXTRA_WIFI_AP_STATE, WifiManager.WIFI_AP_STATE_FAILED);
52                if (state == WifiManager.WIFI_AP_STATE_FAILED) {
53                    int reason = intent.getIntExtra(WifiManager.EXTRA_WIFI_AP_FAILURE_REASON,
54                            WifiManager.SAP_START_FAILURE_GENERAL);
55                    handleWifiApStateChanged(state, reason);
56                } else {
57                    handleWifiApStateChanged(state, WifiManager.SAP_START_FAILURE_GENERAL);
58                }
59            } else if (ConnectivityManager.ACTION_TETHER_STATE_CHANGED.equals(action)) {
60                ArrayList<String> available = intent.getStringArrayListExtra(
61                        ConnectivityManager.EXTRA_AVAILABLE_TETHER);
62                ArrayList<String> active = intent.getStringArrayListExtra(
63                        ConnectivityManager.EXTRA_ACTIVE_TETHER);
64                ArrayList<String> errored = intent.getStringArrayListExtra(
65                        ConnectivityManager.EXTRA_ERRORED_TETHER);
66                updateTetherState(available.toArray(), active.toArray(), errored.toArray());
67            } else if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(action)) {
68                enableWifiSwitch();
69            }
70        }
71    };
72
73    public WifiApEnabler(Context context, SwitchPreference switchPreference) {
74        mContext = context;
75        mSwitch = switchPreference;
76        mOriginalSummary = switchPreference.getSummary();
77        switchPreference.setPersistent(false);
78
79        mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
80        mCm = (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
81
82        mWifiRegexs = mCm.getTetherableWifiRegexs();
83
84        mIntentFilter = new IntentFilter(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
85        mIntentFilter.addAction(ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
86        mIntentFilter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
87    }
88
89    public void resume() {
90        mContext.registerReceiver(mReceiver, mIntentFilter);
91        enableWifiSwitch();
92    }
93
94    public void pause() {
95        mContext.unregisterReceiver(mReceiver);
96    }
97
98    private void enableWifiSwitch() {
99        boolean isAirplaneMode = Settings.Global.getInt(mContext.getContentResolver(),
100                Settings.Global.AIRPLANE_MODE_ON, 0) != 0;
101        if(!isAirplaneMode) {
102            mSwitch.setEnabled(true);
103        } else {
104            mSwitch.setSummary(mOriginalSummary);
105            mSwitch.setEnabled(false);
106        }
107    }
108
109    public void setSoftapEnabled(boolean enable) {
110        if (TetherUtil.setWifiTethering(enable, mContext)) {
111            /* Disable here, enabled on receiving success broadcast */
112            mSwitch.setEnabled(false);
113        } else {
114            mSwitch.setSummary(R.string.wifi_error);
115        }
116
117    }
118
119    public void updateConfigSummary(WifiConfiguration wifiConfig) {
120        String s = mContext.getString(
121                com.android.internal.R.string.wifi_tether_configure_ssid_default);
122        mSwitch.setSummary(String.format(
123                    mContext.getString(R.string.wifi_tether_enabled_subtext),
124                    (wifiConfig == null) ? s : wifiConfig.SSID));
125    }
126
127    private void updateTetherState(Object[] available, Object[] tethered, Object[] errored) {
128        boolean wifiTethered = false;
129        boolean wifiErrored = false;
130
131        for (Object o : tethered) {
132            String s = (String)o;
133            for (String regex : mWifiRegexs) {
134                if (s.matches(regex)) wifiTethered = true;
135            }
136        }
137        for (Object o: errored) {
138            String s = (String)o;
139            for (String regex : mWifiRegexs) {
140                if (s.matches(regex)) wifiErrored = true;
141            }
142        }
143
144        if (wifiTethered) {
145            WifiConfiguration wifiConfig = mWifiManager.getWifiApConfiguration();
146            updateConfigSummary(wifiConfig);
147        } else if (wifiErrored) {
148            mSwitch.setSummary(R.string.wifi_error);
149        }
150    }
151
152    private void handleWifiApStateChanged(int state, int reason) {
153        switch (state) {
154            case WifiManager.WIFI_AP_STATE_ENABLING:
155                mSwitch.setSummary(R.string.wifi_tether_starting);
156                mSwitch.setEnabled(false);
157                break;
158            case WifiManager.WIFI_AP_STATE_ENABLED:
159                /**
160                 * Summary on enable is handled by tether
161                 * broadcast notice
162                 */
163                mSwitch.setChecked(true);
164                /* Doesnt need the airplane check */
165                mSwitch.setEnabled(true);
166                break;
167            case WifiManager.WIFI_AP_STATE_DISABLING:
168                mSwitch.setSummary(R.string.wifi_tether_stopping);
169                mSwitch.setChecked(false);
170                mSwitch.setEnabled(false);
171                break;
172            case WifiManager.WIFI_AP_STATE_DISABLED:
173                mSwitch.setChecked(false);
174                mSwitch.setSummary(mOriginalSummary);
175                enableWifiSwitch();
176                break;
177            default:
178                mSwitch.setChecked(false);
179                if (reason == WifiManager.SAP_START_FAILURE_NO_CHANNEL) {
180                    mSwitch.setSummary(R.string.wifi_sap_no_channel_error);
181                } else {
182                    mSwitch.setSummary(R.string.wifi_error);
183                }
184                enableWifiSwitch();
185        }
186    }
187}
188