1/*
2 * Copyright (C) 2014 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.tv.settings.connectivity;
18
19import android.content.Context;
20import android.content.Intent;
21import android.net.ConnectivityManager;
22import android.net.IpConfiguration.IpAssignment;
23import android.net.IpConfiguration.ProxySettings;
24import android.net.NetworkInfo;
25import android.net.Uri;
26import android.net.wifi.WifiConfiguration;
27import android.net.wifi.WifiInfo;
28import android.net.wifi.WifiManager;
29import android.os.Bundle;
30import android.os.Handler;
31import android.util.Log;
32
33import com.android.tv.settings.ActionBehavior;
34import com.android.tv.settings.ActionKey;
35import com.android.tv.settings.BaseSettingsActivity;
36import com.android.tv.settings.R;
37import com.android.tv.settings.dialog.old.Action;
38import com.android.tv.settings.dialog.old.ActionAdapter;
39import com.android.tv.settings.dialog.old.ContentFragment;
40
41/**
42 * Activity to view the status and modify the configuration of the currently
43 * connected wifi network.
44 */
45
46public class WifiConfigurationActivity extends BaseSettingsActivity
47        implements ActionAdapter.Listener, ConnectivityListener.Listener {
48
49    protected static final String TAG = "WifiConfigurationActivity";
50    private static final boolean DEBUG = false;
51
52    private static final int INET_CONDITION_THRESHOLD = 50;
53    private static final int REQUEST_CODE_ADVANCED_OPTIONS = 1;
54
55    private ConnectivityListener mConnectivityListener;
56    private ConnectivityStatusIconUriGetter mWifiStatusIconUriGetter;
57    private ConnectivityManager mConnectivityManager;
58    private WifiManager mWifiManager;
59    private boolean mInetConnected;
60    private Handler mHandler;
61
62    private final Runnable mMainRefreshView = new Runnable() {
63        @Override
64        public void run() {
65            updateView();
66        }
67    };
68
69    @Override
70    protected void onCreate(Bundle savedInstanceState) {
71        mConnectivityListener = new ConnectivityListener(this, this);
72        mWifiStatusIconUriGetter =
73            ConnectivityStatusIconUriGetter.createWifiStatusIconUriGetter(this);
74        mConnectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
75        mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
76        super.onCreate(savedInstanceState);
77        if (DEBUG) Log.d(TAG, "onCreate");
78        mHandler = new Handler();
79    }
80
81    @Override
82    protected void onResume() {
83        super.onResume();
84        if (DEBUG) Log.d(TAG, "onResume");
85        mConnectivityListener.start();
86    }
87
88    @Override
89    protected void onPause() {
90        mConnectivityListener.stop();
91        super.onPause();
92        if (DEBUG) Log.d(TAG, "onPause");
93    }
94
95    @Override
96    protected Object getInitialState() {
97        if (DEBUG) Log.d(TAG, "getInitialState");
98        return ActionType.CONECTIVITY_SETTINGS_MAIN;
99    }
100
101    @Override
102    public void onConnectivityChange(Intent intent) {
103        if (DEBUG) Log.d(TAG, "onConnectivityChange  intent " + intent);
104        String intentAction = intent.getAction();
105        boolean inetConnectedChanged = false;
106        if (intentAction.equals(ConnectivityManager.CONNECTIVITY_ACTION)
107                || intentAction.equals(ConnectivityManager.INET_CONDITION_ACTION)) {
108            int connectionStatus = intent.getIntExtra(ConnectivityManager.EXTRA_INET_CONDITION, 0);
109            boolean ic = connectionStatus > INET_CONDITION_THRESHOLD;
110            if (ic != mInetConnected) {
111                inetConnectedChanged = true;
112                mInetConnected = ic;
113            }
114            if (DEBUG) Log.d(TAG, "onConnectivityChange  mInetConnected " + mInetConnected);
115        }
116        if (inetConnectedChanged) {
117            mHandler.post(mMainRefreshView);
118        } else {
119            updateIconUriIfNecessary();
120        }
121    }
122
123    private void updateIconUriIfNecessary() {
124        if(mContentFragment instanceof ContentFragment) {
125            ContentFragment cf = (ContentFragment) mContentFragment;
126            Uri oldUri = cf.getIconResourceUri();
127            Uri newUri = Uri.parse(mWifiStatusIconUriGetter.getUri());
128            if (!oldUri.equals(newUri)) {
129                cf.setIcon(newUri);
130            }
131        }
132    }
133
134    private WifiInfo getWifiInfo() {
135        NetworkInfo networkInfo = mConnectivityManager.getActiveNetworkInfo();
136        if (networkInfo == null || networkInfo.getType() != ConnectivityManager.TYPE_WIFI) {
137            return null;
138        } else {
139            return mWifiManager.getConnectionInfo();
140        }
141    }
142
143    @Override
144    protected void refreshActionList() {
145        if (DEBUG) Log.d(TAG, "refreshActionList");
146        mActions.clear();
147        switch ((ActionType) mState) {
148            case CONECTIVITY_SETTINGS_MAIN:
149                mActions.add(ActionType.CONECTIVITY_SETTINGS_STATUS_INFO.toAction(mResources));
150                mActions.add(ActionType.CONECTIVITY_SETTINGS_ADVANCED_OPTIONS.toAction(mResources));
151                mActions.add(ActionType.CONECTIVITY_SETTINGS_FORGET_NETWORK.toAction(mResources));
152                break;
153            case CONECTIVITY_SETTINGS_STATUS_INFO: {
154                boolean isConnected = false;
155                WifiInfo wifiInfo = getWifiInfo();
156                if (wifiInfo != null) {
157                    NetworkInfo networkInfo = mConnectivityManager.getActiveNetworkInfo();
158                    if (networkInfo != null &&
159                        networkInfo.getType() == ConnectivityManager.TYPE_WIFI &&
160                        mInetConnected) {
161                        isConnected = true;
162                    }
163                }
164
165                if (!isConnected) {
166                    mActions.add(ActionType.CONECTIVITY_SETTINGS_CONNECTION.
167                                     toInfo(mResources, R.string.not_connected));
168                } else {
169                    // If we're on a wifi-network and the status is good...
170                    mActions.add(
171                        ActionType.CONECTIVITY_SETTINGS_CONNECTION.
172                            toInfo(mResources, R.string.connected));
173
174                    int ip = wifiInfo.getIpAddress();
175                    mActions.add(ActionType.CONECTIVITY_SETTINGS_IP_ADDRESS.
176                        toInfo(mResources,
177                                 String.format("%d.%d.%d.%d", (ip & 0xff), (ip >> 8 & 0xff),
178                                               (ip >> 16 & 0xff), (ip >> 24 & 0xff))));
179
180                    mActions.add(ActionType.CONECTIVITY_SETTINGS_MAC_ADDRESS.
181                        toInfo(mResources, wifiInfo.getMacAddress()));
182
183                    String[] signalLevels =
184                        getResources().getStringArray(R.array.wifi_signal_strength);
185                    int strength =
186                        WifiManager.
187                            calculateSignalLevel(wifiInfo.getRssi(), signalLevels.length);
188                    mActions.add(ActionType.CONECTIVITY_SETTINGS_SIGNAL_STRENGTH.
189                        toInfo(mResources, signalLevels[strength]));
190                }
191                break;
192            }
193            case CONECTIVITY_SETTINGS_ADVANCED_OPTIONS: {
194                WifiInfo wifiInfo = getWifiInfo();
195                if (wifiInfo != null) {
196                    WifiConfiguration wifiConfiguration =
197                        WifiConfigHelper.getWifiConfiguration(
198                            mWifiManager, wifiInfo.getNetworkId());
199                    if (wifiConfiguration != null) {
200                        int proxySettingsResourceId =
201                            (wifiConfiguration.getProxySettings() == ProxySettings.NONE) ?
202                                R.string.wifi_action_proxy_none :
203                                R.string.wifi_action_proxy_manual;
204                        mActions.add(ActionType.CONECTIVITY_SETTINGS_PROXY_SETTINGS.
205                                            toAction(mResources, proxySettingsResourceId));
206
207                        int ipSettingsResourceId =
208                           (wifiConfiguration.getIpAssignment() == IpAssignment.STATIC) ?
209                                R.string.wifi_action_static :
210                                R.string.wifi_action_dhcp;
211                        mActions.add(ActionType.CONECTIVITY_SETTINGS_IP_SETTINGS.
212                                            toAction(mResources, ipSettingsResourceId));
213                    }
214                } else {
215                    mActions.add(ActionType.CONECTIVITY_SETTINGS_CONNECTION.
216                                     toInfo(mResources, R.string.not_connected));
217                }
218                break;
219            }
220
221            case CONECTIVITY_SETTINGS_FORGET_NETWORK: {
222                String okKey =
223                    new ActionKey<>(
224                        ActionType.CONECTIVITY_SETTINGS_FORGET_NETWORK, ActionBehavior.OK).getKey();
225                mActions.add(
226                    new Action.Builder()
227                        .key(okKey)
228                        .title(getString(R.string.wifi_forget_network))
229                        .build());
230                String cancelKey =
231                    new ActionKey<>(
232                            ActionType.CONECTIVITY_SETTINGS_FORGET_NETWORK,
233                            ActionBehavior.CANCEL).getKey();
234                mActions.add(
235                    new Action.Builder()
236                        .key(cancelKey)
237                        .title(getString(R.string.settings_cancel))
238                        .build());
239                break;
240            }
241        }
242    }
243
244    private String getNetworkName() {
245        NetworkInfo networkInfo = mConnectivityManager.getActiveNetworkInfo();
246        String name = getString(R.string.connectivity_wifi);
247        if (networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
248            WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
249            if (wifiInfo != null) {
250                name = WifiInfo.removeDoubleQuotes(wifiInfo.getSSID());
251            }
252        }
253        return name;
254    }
255
256    @Override
257    protected void updateView() {
258        refreshActionList();
259        if (DEBUG) Log.d(TAG, "updateView  mState " + mState);
260        switch ((ActionType) mState) {
261            case CONECTIVITY_SETTINGS_MAIN: {
262                setView(getNetworkName(), null, null,
263                        Uri.parse(mWifiStatusIconUriGetter.getUri()));
264                break;
265            }
266            case CONECTIVITY_SETTINGS_STATUS_INFO: {
267                setView(getString(R.string.wifi_action_status_info), getNetworkName(), null,
268                        Uri.parse(mWifiStatusIconUriGetter.getUri()));
269                break;
270            }
271            case CONECTIVITY_SETTINGS_ADVANCED_OPTIONS: {
272                setView(getString(R.string.wifi_action_advanced_options_title),
273                        getNetworkName(), null, Uri.parse(mWifiStatusIconUriGetter.getUri()));
274                break;
275            }
276            case CONECTIVITY_SETTINGS_FORGET_NETWORK: {
277                setView(R.string.wifi_forget_network, getNetworkName(),
278                        R.string.wifi_forget_network_description,
279                        Uri.parse(mWifiStatusIconUriGetter.getUri()));
280                break;
281            }
282        }
283    }
284
285    @Override
286    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
287        if (requestCode == REQUEST_CODE_ADVANCED_OPTIONS && resultCode == RESULT_OK) {
288            updateView();
289        } else {
290            super.onActivityResult(requestCode, resultCode, data);
291        }
292    }
293
294    @Override
295    protected void setProperty(boolean enable) {
296    }
297
298    private int getNetworkId() {
299        WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
300        if (wifiInfo != null) {
301              return wifiInfo.getNetworkId();
302        }
303        return -1;
304    }
305
306    @Override
307    public void onActionClicked(Action action) {
308        if (DEBUG) Log.d(TAG, "onActionClicked " + action.getKey());
309
310        ActionKey<ActionType, ActionBehavior> actionKey =
311            new ActionKey<>(
312                ActionType.class, ActionBehavior.class, action.getKey());
313        final ActionType type = actionKey.getType();
314        final ActionBehavior behavior = actionKey.getBehavior();
315
316        switch (type) {
317            case CONECTIVITY_SETTINGS_STATUS_INFO:
318                switch (behavior) {
319                    case INIT:
320                        setState(type, true);
321                        break;
322                }
323                break;
324            case CONECTIVITY_SETTINGS_ADVANCED_OPTIONS:
325                switch (behavior) {
326                    case INIT:
327                        setState(type, true);
328                        break;
329                }
330                break;
331            case CONECTIVITY_SETTINGS_PROXY_SETTINGS:
332                switch (behavior) {
333                    case INIT: {
334                        int networkId = getNetworkId();
335                        if (networkId != -1) {
336                            startActivityForResult(
337                                EditProxySettingsActivity.createIntent(this, networkId),
338                                REQUEST_CODE_ADVANCED_OPTIONS);
339                        }
340                        break;
341                    }
342                }
343                break;
344            case CONECTIVITY_SETTINGS_IP_SETTINGS:
345                switch (behavior) {
346                    case INIT: {
347                        int networkId = getNetworkId();
348                        if (networkId != -1) {
349                            startActivityForResult(
350                                EditIpSettingsActivity.createIntent(this, networkId),
351                                REQUEST_CODE_ADVANCED_OPTIONS);
352                        }
353                        break;
354                    }
355                }
356                break;
357            case CONECTIVITY_SETTINGS_FORGET_NETWORK: {
358                switch (behavior) {
359                    case INIT:
360                        setState(type, true);
361                        break;
362                    case OK: {
363                        int networkId = getNetworkId();
364                        if (networkId != -1) {
365                            mWifiManager.forget(networkId, null);
366                        }
367                        setResult(RESULT_OK);
368                        finish();
369                        break;
370                    }
371                    case CANCEL:
372                        goBack();
373                        break;
374                }
375                break;
376            }
377        }
378    }
379}
380