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