165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane/*
265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Copyright (C) 2014 The Android Open Source Project
365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane *
465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Licensed under the Apache License, Version 2.0 (the "License");
565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * you may not use this file except in compliance with the License.
665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * You may obtain a copy of the License at
765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane *
865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane *      http://www.apache.org/licenses/LICENSE-2.0
965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane *
1065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Unless required by applicable law or agreed to in writing, software
1165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * distributed under the License is distributed on an "AS IS" BASIS,
1265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * See the License for the specific language governing permissions and
1465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * limitations under the License.
1565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */
1665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
1765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lanepackage com.android.tv.settings.connectivity;
1865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
1965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.app.Activity;
2065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.content.Context;
2165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.content.Intent;
2265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.content.res.Resources;
2365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.net.IpConfiguration;
2465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.net.IpConfiguration.IpAssignment;
2565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.net.IpConfiguration.ProxySettings;
2665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.net.wifi.WifiConfiguration;
2765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.net.wifi.ScanResult;
2865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.net.wifi.WifiInfo;
2965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.net.wifi.WifiManager;
3065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.os.Bundle;
3165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.os.Handler;
3265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.os.SystemClock;
3365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.text.TextUtils;
3465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.util.Log;
3565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.util.Pair;
3665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
3765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport com.android.tv.settings.dialog.SettingsLayoutActivity;
3865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport com.android.tv.settings.dialog.Layout;
3965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport com.android.tv.settings.dialog.Layout.Header;
4065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport com.android.tv.settings.dialog.Layout.Action;
4165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport com.android.tv.settings.dialog.Layout.Status;
4265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport com.android.tv.settings.dialog.Layout.Static;
4365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport com.android.tv.settings.dialog.Layout.StringGetter;
4465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport com.android.tv.settings.dialog.Layout.LayoutGetter;
4565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport com.android.tv.settings.R;
4665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
4765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport java.util.ArrayList;
4865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport java.util.Collections;
4965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport java.util.HashMap;
5065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport java.util.List;
5165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
5265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane/**
5365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Activity to manage network settings.
5465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */
5565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lanepublic class NetworkActivity extends SettingsLayoutActivity implements
5665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        ConnectivityListener.Listener {
5765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
5801a5b81394670c6c5c2011673ed48c4fee1cf77bbulic    private static final boolean DEBUG = false;
5965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final String TAG = "NetworkActivity";
6065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final int REQUEST_CODE_ADVANCED_OPTIONS = 1;
6165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final int WIFI_REFRESH_INTERVAL_CAP_MILLIS = 15 * 1000;
6265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
6365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private ConnectivityListener mConnectivityListener;
6465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private Resources mRes;
6565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private Handler mHandler = new Handler();
6665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
6765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    @Override
6865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    protected void onCreate(Bundle savedInstanceState) {
6965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mRes = getResources();
7065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mConnectivityListener = new ConnectivityListener(this, this);
7165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mConnectivityListener.start();
7265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        super.onCreate(savedInstanceState);
7365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
7465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
7565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    @Override
7665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    protected void onDestroy(){
7765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        super.onDestroy();
7865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mConnectivityListener.stop();
7965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
8065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
8165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    @Override
8265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public void onConnectivityChange(Intent intent) {
8365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mEthernetConnectedDescription.refreshView();
8465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mWifiConnectedDescription.refreshView();
8565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
8665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
8765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    @Override
8865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public void onResume() {
8965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (mWifiShortListLayout != null) {
9065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mWifiShortListLayout.onWifiListInvalidated();
9165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
9265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (mWifiAllListLayout != null) {
9365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mWifiAllListLayout.onWifiListInvalidated();
9465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
9565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        super.onResume();
9665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
9765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
9865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    StringGetter mEthernetConnectedDescription = new StringGetter() {
9965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        private boolean lastIsEthernetConnected;
10065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        @Override
10165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        public String get() {
10265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            lastIsEthernetConnected =
10365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    mConnectivityListener.getConnectivityStatus().isEthernetConnected();
10465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            int resId = lastIsEthernetConnected ? R.string.connected : R.string.not_connected;
10565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return mRes.getString(resId);
10665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
10765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        @Override
10865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        public void refreshView() {
10965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            if (mConnectivityListener.getConnectivityStatus().isEthernetConnected() !=
11065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    lastIsEthernetConnected) {
11165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                super.refreshView();
11265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
11365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
11465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    };
11565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
11665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    StringGetter mWifiConnectedDescription = new StringGetter() {
11765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        private boolean lastIsWifiConnected;
11865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        @Override
11965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        public String get() {
12065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            lastIsWifiConnected = mConnectivityListener.getConnectivityStatus().isWifiConnected();
12165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            int resId = lastIsWifiConnected ? R.string.connected : R.string.not_connected;
12265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return mRes.getString(resId);
12365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
12465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        @Override
12565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        public void refreshView() {
12665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            if (mConnectivityListener.getConnectivityStatus().isWifiConnected() !=
12765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    lastIsWifiConnected) {
12865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                super.refreshView();
12965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
13065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
13165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    };
13265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
13365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    StringGetter mEthernetIPAddress = new StringGetter() {
13465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        public String get() {
13565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            ConnectivityListener.ConnectivityStatus status =
13665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    mConnectivityListener.getConnectivityStatus();
13765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            if (status.isEthernetConnected()) {
13865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                return mConnectivityListener.getEthernetIpAddress();
13965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            } else {
14065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                return "";
14165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
14265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
14365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    };
14465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
14565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    StringGetter mEthernetMacAddress = new StringGetter() {
14665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        public String get() {
14765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return mConnectivityListener.getEthernetMacAddress();
14865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
14965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    };
15065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
15165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    LayoutGetter mEthernetAdvancedLayout = new LayoutGetter() {
15265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        public Layout get() {
15365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            Layout layout = new Layout();
15465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            // Do not check Ethernet's availability here
15565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            // because it might not be active due to the invalid configuration.
15665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            IpConfiguration ipConfiguration = mConnectivityListener.getIpConfiguration();
15765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            if (ipConfiguration != null) {
15865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                int proxySettingsResourceId =
15965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    (ipConfiguration.getProxySettings() == ProxySettings.STATIC) ?
16065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        R.string.wifi_action_proxy_manual :
16165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        R.string.wifi_action_proxy_none;
16265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                int ipSettingsResourceId =
16365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    (ipConfiguration.getIpAssignment() == IpAssignment.STATIC) ?
16465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        R.string.wifi_action_static :
16565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        R.string.wifi_action_dhcp;
16665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                layout
16765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    .add(new Action.Builder(mRes, ACTION_ETHERNET_PROXY_SETTINGS)
16865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .title(R.string.title_wifi_proxy_settings)
16965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .description(proxySettingsResourceId).build())
17065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    .add(new Action.Builder(mRes, ACTION_ETHERNET_IP_SETTINGS)
17165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .title(R.string.title_wifi_ip_settings)
17265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .description(ipSettingsResourceId).build());
17365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            } else {
17465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                layout
17565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    .add(new Status.Builder(mRes)
17665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .title(R.string.title_internet_connection)
17765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .description(R.string.not_connected).build());
17865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
17965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return layout;
18065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
18165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    };
18265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
18365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    LayoutGetter mEthernetLayout = new LayoutGetter() {
18465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        public Layout get() {
18565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            boolean ethernetConnected =
18665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    mConnectivityListener.getConnectivityStatus().isEthernetConnected();
18765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            if (ethernetConnected) {
18865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                return new Layout()
18965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    .add(new Status.Builder(mRes).title(R.string.title_internet_connection)
19065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .description(R.string.connected).build())
19165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    .add(new Status.Builder(mRes)
19265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .title(R.string.title_ip_address)
19365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .description(mEthernetIPAddress)
19465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .build())
19565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    .add(new Status.Builder(mRes)
19665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .title(R.string.title_mac_address)
19765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .description(mEthernetMacAddress)
19865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .build())
19965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    .add(new Header.Builder(mRes)
20065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .title(R.string.wifi_action_advanced_options_title).build()
20165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        .add(mEthernetAdvancedLayout)
20265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                     );
20365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
20465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            } else {
20565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                return new Layout()
20665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    .add(new Status.Builder(mRes)
20765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .title(R.string.title_internet_connection)
20865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .description(R.string.not_connected)
20965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .build())
21065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    .add(new Header.Builder(mRes)
21165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .title(R.string.wifi_action_advanced_options_title).build()
21265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        .add(mEthernetAdvancedLayout)
21365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    );
21465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
21565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
21665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    };
21765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
21865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final int NUMBER_SIGNAL_LEVELS = 4;
21965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final int ACTION_WIFI_FORGET_NETWORK = 1;
22065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final int ACTION_WIFI_PROXY_SETTINGS = 4;
22165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final int ACTION_WIFI_IP_SETTINGS = 5;
22265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final int ACTION_ETHERNET_PROXY_SETTINGS = 6;
22365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final int ACTION_ETHERNET_IP_SETTINGS = 7;
22465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
22565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private final Context mContext = this;
22665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
22765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private int getCurrentNetworkIconResourceId(
22865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            ScanResult scanResult, int signalLevel) {
22965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        int resourceId = 0;
23065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (scanResult != null) {
23165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            WifiSecurity security = WifiSecurity.getSecurity(scanResult);
23265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            if (security.isOpen()) {
23365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                switch (signalLevel) {
23465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    case 0:
23565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        resourceId = R.drawable.ic_settings_wifi_active_1;
23665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        break;
23765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    case 1:
23865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        resourceId = R.drawable.ic_settings_wifi_active_2;
23965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        break;
24065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    case 2:
24165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        resourceId = R.drawable.ic_settings_wifi_active_3;
24265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        break;
24365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    case 3:
24465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        resourceId = R.drawable.ic_settings_wifi_active_4;
24565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        break;
24665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                }
24765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            } else {
24865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                switch (signalLevel) {
24965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    case 0:
25065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        resourceId = R.drawable.ic_settings_wifi_secure_active_1;
25165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        break;
25265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    case 1:
25365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        resourceId = R.drawable.ic_settings_wifi_secure_active_2;
25465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        break;
25565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    case 2:
25665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        resourceId = R.drawable.ic_settings_wifi_secure_active_3;
25765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        break;
25865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    case 3:
25965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        resourceId = R.drawable.ic_settings_wifi_secure_active_4;
26065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        break;
26165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                }
26265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
26365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
26465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return resourceId;
26565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
26665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
26765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private String getSignalStrength() {
26865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        String[] signalLevels = mRes.getStringArray(R.array.wifi_signal_strength);
26965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        int strength = mConnectivityListener.getWifiSignalStrength(signalLevels.length);
27065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return signalLevels[strength];
27165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
27265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
27365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    LayoutGetter mWifiInfoLayout = new LayoutGetter() {
27465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        public Layout get() {
27565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            Layout layout = new Layout();
27665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            ConnectivityListener.ConnectivityStatus status =
27765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    mConnectivityListener.getConnectivityStatus();
27865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            boolean isConnected = status.isWifiConnected();
27965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            if (isConnected) {
28065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                layout
28165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    .add(new Status.Builder(mRes)
28265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .title(R.string.title_internet_connection)
28365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .description(R.string.connected).build())
28465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    .add(new Status.Builder(mRes)
28565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .title(R.string.title_ip_address)
28665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .description(mConnectivityListener.getWifiIpAddress()).build())
28765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    .add(new Status.Builder(mRes)
28865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                             .title(R.string.title_mac_address)
28965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .description(mConnectivityListener.getWifiMacAddress()).build())
29065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    .add(new Status.Builder(mRes)
29165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                             .title(R.string.title_signal_strength)
29265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .description(getSignalStrength()).build());
29365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            } else {
29465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                layout
29565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    .add(new Status.Builder(mRes)
29665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .title(R.string.title_internet_connection)
29765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .description(R.string.not_connected).build());
29865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
29965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return layout;
30065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
30165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    };
30265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
30365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    LayoutGetter mWifiAdvancedLayout = new LayoutGetter() {
30465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        public Layout get() {
30565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            Layout layout = new Layout();
30665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            WifiConfiguration wifiConfiguration = mConnectivityListener.getWifiConfiguration();
30765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            if (wifiConfiguration != null) {
30865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                int proxySettingsResourceId =
30965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    (wifiConfiguration.getProxySettings() == ProxySettings.NONE) ?
31065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        R.string.wifi_action_proxy_none :
31165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        R.string.wifi_action_proxy_manual;
31265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                int ipSettingsResourceId =
31365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                   (wifiConfiguration.getIpAssignment() == IpAssignment.STATIC) ?
31465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        R.string.wifi_action_static :
31565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        R.string.wifi_action_dhcp;
31665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                layout
31765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    .add(new Action.Builder(mRes, ACTION_WIFI_PROXY_SETTINGS)
31865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .title(R.string.title_wifi_proxy_settings)
31965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .description(proxySettingsResourceId).build())
32065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    .add(new Action.Builder(mRes, ACTION_WIFI_IP_SETTINGS)
32165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .title(R.string.title_wifi_ip_settings)
32265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .description(ipSettingsResourceId).build());
32365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            } else {
32465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                layout
32565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    .add(new Status.Builder(mRes)
32665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .title(R.string.title_internet_connection)
32765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .description(R.string.not_connected).build());
32865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
32965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return layout;
33065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
33165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    };
33265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
33365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private void addWifiConnectedHeader(Layout layout, String SSID) {
33465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        layout
33565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            .add(new Header.Builder(mRes)
33665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    .title(SSID)
33765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    .description(R.string.connected).build()
33865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                .add(new Header.Builder(mRes)
33965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        .title(R.string.wifi_action_status_info).build()
34065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    .add(mWifiInfoLayout)
34165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                )
34265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                .add(new Header.Builder(mRes)
34365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        .title(R.string.wifi_action_advanced_options_title).build()
34465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    .add(mWifiAdvancedLayout)
34565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                )
34665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                .add(new Header.Builder(mRes)
34765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        .title(R.string.wifi_forget_network).build()
34865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    .add(new Action.Builder(mRes, ACTION_WIFI_FORGET_NETWORK)
34965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .title(R.string.title_ok).build())
35065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    .add(new Action.Builder(mRes, Action.ACTION_BACK)
35165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .title(R.string.title_cancel).build())
35265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                 )
35365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            );
35465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
35565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
35665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private class WifiListLayout extends LayoutGetter implements
35765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            ConnectivityListener.WifiNetworkListener {
35865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        private final boolean mTop3EntriesOnly;
35965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        private String mSelectedTitle;
36065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        private long mLastWifiRefresh = 0;
36165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
36265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        private final Runnable mRefreshViewRunnable = new Runnable() {
36365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            @Override
36465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            public void run() {
36565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                Layout.Node selected = getSelectedNode();
36665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                if (selected != null) {
36765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    mSelectedTitle = selected.getTitle();
36865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                }
36965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                refreshView();
37065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
37165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        };
37265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
37365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        WifiListLayout(boolean top3EntriesOnly) {
37465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mTop3EntriesOnly = top3EntriesOnly;
37565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
37665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
37765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        @Override
37865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        public Layout get() {
37965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mConnectivityListener.startScanningWifi(this);
38065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mLastWifiRefresh = SystemClock.elapsedRealtime();
38165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mHandler.removeCallbacks(mRefreshViewRunnable);
38265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return initAvailableWifiNetworks(mTop3EntriesOnly, mSelectedTitle).
38365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    setSelectedByTitle(mSelectedTitle);
38465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
38565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
38665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        @Override
38765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        public void onMovedOffScreen() {
38865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mHandler.removeCallbacks(mRefreshViewRunnable);
38965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mConnectivityListener.stopScanningWifi(this);
39065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
39165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
39265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        @Override
39365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        public void onWifiListChanged() {
39465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            long now = SystemClock.elapsedRealtime();
39565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            long millisToNextRefreshView =
39665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    WIFI_REFRESH_INTERVAL_CAP_MILLIS - now + mLastWifiRefresh;
39765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mHandler.removeCallbacks(mRefreshViewRunnable);
39865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mHandler.postDelayed(mRefreshViewRunnable, millisToNextRefreshView);
39965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
40065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
40165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        /**
40265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane         * Wifi network configuration has changed and an immediate refresh of the list of Wifi
40365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane         * networks is required.
40465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane         */
40565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        public void onWifiListInvalidated() {
40665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mLastWifiRefresh = 0;
40765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            onWifiListChanged();
40865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
40965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
41065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        /**
41165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane         * Create a list of available Wifi networks sorted by connection status (a connected Wifi
41265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane         * network is shown at the first position on the list) and signal strength, with the
41365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane         * provisio that the wireless network with SSID "mustHave" should be included in the list
41465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane         * even if it would be otherwise excluded.
41565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane         *
41665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane         * @param top3EntriesOnly Show only 3 entries in the list.
41765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane         * @param mustHave        Include this wifi network in the list even if it would otherwise
41865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane         *                        be excluded by virtue of inadequate signal strength.
41965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane         */
42065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        private Layout initAvailableWifiNetworks(boolean top3EntriesOnly, String mustHave) {
42165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            List<ScanResult> networks = mConnectivityListener.getAvailableNetworks();
42265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            Layout layout = new Layout();
42365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            if (networks.size() > 0) {
42465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                int maxItems = top3EntriesOnly ? 3 : Integer.MAX_VALUE;
42565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                // "networks" is already sorted by the signal strength and connection status.
42665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                // Generate a new list with size less than "maxItems" that ensures "mustHave" is
42765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                // included.
42865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                boolean haveMustHave = false;
42965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                List<ScanResult> displayList = new ArrayList<ScanResult>();
43065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                for (ScanResult scanResult : networks) {
43165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    if (!haveMustHave && TextUtils.equals(scanResult.SSID, mustHave)) {
43265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        haveMustHave = true;
43365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        if (displayList.size() == maxItems) {
43465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            displayList.remove(maxItems-1);
43565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        }
43665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        displayList.add(scanResult);
43765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    } else if (displayList.size() < maxItems) {
43865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        displayList.add(scanResult);
43965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    }
44065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    if (haveMustHave && displayList.size() == maxItems) {
44165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        break;
44265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    }
44365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                }
44465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
44565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                // If a network is connected, it will be the first on the list.
44665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                boolean isConnected =
44765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    mConnectivityListener.getConnectivityStatus().isWifiConnected();
44865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                for (ScanResult network : displayList) {
44965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    if (network != null) {
45065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        WifiSecurity security = WifiSecurity.getSecurity(network);
45165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
45265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        String networkDescription =
45365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            security.isOpen() ? "" : security.getName(mContext);
45465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        Intent intent =
45565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            WifiConnectionActivity.createIntent(mContext, network, security);
45665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        int signalLevel = WifiManager.calculateSignalLevel(
45765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                network.level, NUMBER_SIGNAL_LEVELS);
45865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        //TODO implement signal dependent list icon.
45965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        /*
46065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        int imageResourceId = getNetworkIconResourceId(network, signalLevel);
46165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        if (WifiConfigHelper.areSameNetwork(mWifiManager, network,
46265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                currentConnection)) {
46365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            networkDescription = getString(R.string.connected);
46465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            signalLevel = WifiManager.calculateSignalLevel(
46565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                    currentConnection.getRssi(), NUMBER_SIGNAL_LEVELS);
46665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            imageResourceId = getCurrentNetworkIconResourceId(network, signalLevel);
46765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        } */
46865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
46965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        if (isConnected) {
47065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            addWifiConnectedHeader(layout, network.SSID);
47165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        } else {
47265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            layout.add(new Action.Builder(mRes, intent)
47365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                    .title(network.SSID)
47465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                    .description(networkDescription).build());
47565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        }
47665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    }
47765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    isConnected = false;
47865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                }
47965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            } else {
48065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                layout.add(new Action.Builder(mRes, 0)
48165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                       .title(R.string.title_wifi_no_networks_available).build());
48265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
48365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return layout;
48465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
48565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    };
48665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
48765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private final WifiListLayout mWifiShortListLayout = new WifiListLayout(true);
48865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
48965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private final WifiListLayout mWifiAllListLayout = new WifiListLayout(false);
49065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
49165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    @Override
49265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public Layout createLayout() {
49365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return
49465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            new Layout()
49565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                .breadcrumb(getString(R.string.header_category_device))
49665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                .add(new Header.Builder(mRes)
497a40d3a1dd3127512097a7ae3d4c7bfb00f673815bulic                        .icon(R.drawable.ic_settings_wifi_4)
49865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        .title(R.string.connectivity_network)
49965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        .description(mWifiConnectedDescription)
50065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        .build()
50165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    .add(new Header.Builder(mRes).title(R.string.connectivity_wifi)
50201a5b81394670c6c5c2011673ed48c4fee1cf77bbulic                            .contentIconRes(R.drawable.ic_settings_wifi_4)
50365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .description(mWifiConnectedDescription).build()
50465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        .add(new Static.Builder(mRes)
50565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .title(R.string.wifi_setting_available_networks)
50665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .build())
50765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        .add(mWifiShortListLayout)
50865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        .add(new Header.Builder(mRes)
50965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .title(R.string.wifi_setting_see_all)
51065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .build()
51165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .add(mWifiAllListLayout)
51265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        )
51365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        .add(new Static.Builder(mRes)
51465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .title(R.string.wifi_setting_header_other_options)
51565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .build())
51665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        .add(new Action.Builder(mRes,
51765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                 new Intent(this, WpsConnectionActivity.class))
51865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .title(R.string.wifi_setting_other_options_wps)
51965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .build())
52065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        .add(new Action.Builder(mRes,
52165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                new Intent(this, AddWifiNetworkActivity.class))
52265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .title(R.string.wifi_setting_other_options_add_network)
52365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                .build())
52465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    )
52565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    .add(new Header.Builder(mRes)
52665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .title(R.string.connectivity_ethernet)
52701a5b81394670c6c5c2011673ed48c4fee1cf77bbulic                            .contentIconRes(R.drawable.ic_settings_ethernet)
52865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .description(mEthernetConnectedDescription)
52965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            .build()
53065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        .add(mEthernetLayout)
53165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                     )
53265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                 );
53365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
53465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
53565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    @Override
53665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
53765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (requestCode == REQUEST_CODE_ADVANCED_OPTIONS && resultCode == RESULT_OK) {
53865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            //TODO make sure view reflects model deltas
53965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        } else {
54065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            super.onActivityResult(requestCode, resultCode, data);
54165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
54265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
54365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
54465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    @Override
54501a5b81394670c6c5c2011673ed48c4fee1cf77bbulic    public void onActionFocused(Layout.LayoutRow item) {
54601a5b81394670c6c5c2011673ed48c4fee1cf77bbulic        int resId = item.getContentIconRes();
54701a5b81394670c6c5c2011673ed48c4fee1cf77bbulic        if (resId != 0) {
54801a5b81394670c6c5c2011673ed48c4fee1cf77bbulic            setIcon(resId);
54901a5b81394670c6c5c2011673ed48c4fee1cf77bbulic        }
55001a5b81394670c6c5c2011673ed48c4fee1cf77bbulic    }
55101a5b81394670c6c5c2011673ed48c4fee1cf77bbulic
55201a5b81394670c6c5c2011673ed48c4fee1cf77bbulic    @Override
55365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public void onActionClicked(Action action) {
55465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        switch (action.getId()) {
55565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            case Action.ACTION_INTENT:
55665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                startActivityForResult(action.getIntent(), REQUEST_CODE_ADVANCED_OPTIONS);
55765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                break;
55865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            case ACTION_WIFI_FORGET_NETWORK:
55965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                mConnectivityListener.forgetWifiNetwork();
56065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                goBackToTitle(mRes.getString(R.string.connectivity_wifi));
56165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                mWifiShortListLayout.onWifiListInvalidated();
56265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                mWifiAllListLayout.onWifiListInvalidated();
56365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                break;
56465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            case ACTION_WIFI_PROXY_SETTINGS: {
56565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                int networkId = mConnectivityListener.getWifiNetworkId();
56665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                if (networkId != -1) {
56765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    startActivityForResult(EditProxySettingsActivity.createIntent(this, networkId),
56865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            REQUEST_CODE_ADVANCED_OPTIONS);
56965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                }
57065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                break;
57165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
57265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            case ACTION_WIFI_IP_SETTINGS: {
57365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                int networkId = mConnectivityListener.getWifiNetworkId();
57465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                if (networkId != -1) {
57565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    startActivityForResult(EditIpSettingsActivity.createIntent(this, networkId),
57665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            REQUEST_CODE_ADVANCED_OPTIONS);
57765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                }
57865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                break;
57965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
58065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            case ACTION_ETHERNET_PROXY_SETTINGS: {
58165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                int networkId = WifiConfiguration.INVALID_NETWORK_ID;
58265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                startActivityForResult(EditProxySettingsActivity.createIntent(this, networkId),
58365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        REQUEST_CODE_ADVANCED_OPTIONS);
58465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                break;
58565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
58665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            case ACTION_ETHERNET_IP_SETTINGS: {
58765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                int networkId = WifiConfiguration.INVALID_NETWORK_ID;
58865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                startActivityForResult(EditIpSettingsActivity.createIntent(this, networkId),
58965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        REQUEST_CODE_ADVANCED_OPTIONS);
59065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                break;
59165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
59265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
59365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
59465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane}
595