Home | History | Annotate | Download | only in connectivity
      1 /*
      2  * Copyright (C) 2016 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 
     17 package com.android.tv.settings.connectivity;
     18 
     19 import android.content.Context;
     20 import android.net.wifi.WifiConfiguration;
     21 import android.os.Bundle;
     22 import android.os.Handler;
     23 import android.os.SystemClock;
     24 import android.provider.Settings;
     25 import android.support.v7.preference.Preference;
     26 import android.support.v7.preference.PreferenceCategory;
     27 import android.support.v7.preference.PreferenceManager;
     28 import android.support.v7.preference.TwoStatePreference;
     29 
     30 import com.android.internal.logging.nano.MetricsProto;
     31 import com.android.settingslib.wifi.AccessPoint;
     32 import com.android.settingslib.wifi.AccessPointPreference;
     33 import com.android.tv.settings.R;
     34 import com.android.tv.settings.SettingsPreferenceFragment;
     35 
     36 import java.util.Collection;
     37 import java.util.HashSet;
     38 import java.util.Set;
     39 
     40 /**
     41  * Fragment for controlling network connectivity
     42  */
     43 public class NetworkFragment extends SettingsPreferenceFragment implements
     44         ConnectivityListener.Listener, ConnectivityListener.WifiNetworkListener,
     45         AccessPoint.AccessPointListener {
     46 
     47     private static final String KEY_WIFI_ENABLE = "wifi_enable";
     48     private static final String KEY_WIFI_LIST = "wifi_list";
     49     private static final String KEY_WIFI_COLLAPSE = "wifi_collapse";
     50     private static final String KEY_WIFI_OTHER = "wifi_other";
     51     private static final String KEY_WIFI_ADD = "wifi_add";
     52     private static final String KEY_WIFI_ALWAYS_SCAN = "wifi_always_scan";
     53     private static final String KEY_ETHERNET = "ethernet";
     54     private static final String KEY_ETHERNET_STATUS = "ethernet_status";
     55     private static final String KEY_ETHERNET_PROXY = "ethernet_proxy";
     56     private static final String KEY_ETHERNET_DHCP = "ethernet_dhcp";
     57 
     58     private static final int INITIAL_UPDATE_DELAY = 500;
     59 
     60     private ConnectivityListener mConnectivityListener;
     61     private AccessPointPreference.UserBadgeCache mUserBadgeCache;
     62 
     63     private TwoStatePreference mEnableWifiPref;
     64     private CollapsibleCategory mWifiNetworksCategory;
     65     private Preference mCollapsePref;
     66     private Preference mAddPref;
     67     private TwoStatePreference mAlwaysScan;
     68     private PreferenceCategory mEthernetCategory;
     69     private Preference mEthernetStatusPref;
     70     private Preference mEthernetProxyPref;
     71     private Preference mEthernetDhcpPref;
     72 
     73     private final Handler mHandler = new Handler();
     74     private long mNoWifiUpdateBeforeMillis;
     75     private Runnable mInitialUpdateWifiListRunnable = new Runnable() {
     76         @Override
     77         public void run() {
     78             mNoWifiUpdateBeforeMillis = 0;
     79             updateWifiList();
     80         }
     81     };
     82 
     83     public static NetworkFragment newInstance() {
     84         return new NetworkFragment();
     85     }
     86 
     87     @Override
     88     public void onCreate(Bundle savedInstanceState) {
     89         mConnectivityListener = new ConnectivityListener(getContext(), this, getLifecycle());
     90         mUserBadgeCache =
     91                 new AccessPointPreference.UserBadgeCache(getContext().getPackageManager());
     92         super.onCreate(savedInstanceState);
     93     }
     94 
     95     @Override
     96     public void onStart() {
     97         super.onStart();
     98         mConnectivityListener.setWifiListener(this);
     99         mNoWifiUpdateBeforeMillis = SystemClock.elapsedRealtime() + INITIAL_UPDATE_DELAY;
    100         updateWifiList();
    101     }
    102 
    103     @Override
    104     public void onResume() {
    105         super.onResume();
    106         // There doesn't seem to be an API to listen to everything this could cover, so
    107         // tickle it here and hope for the best.
    108         updateConnectivity();
    109     }
    110 
    111     @Override
    112     public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
    113         getPreferenceManager().setPreferenceComparisonCallback(
    114                 new PreferenceManager.SimplePreferenceComparisonCallback());
    115         setPreferencesFromResource(R.xml.network, null);
    116 
    117         mEnableWifiPref = (TwoStatePreference) findPreference(KEY_WIFI_ENABLE);
    118         mWifiNetworksCategory = (CollapsibleCategory) findPreference(KEY_WIFI_LIST);
    119         mCollapsePref = findPreference(KEY_WIFI_COLLAPSE);
    120         mAddPref = findPreference(KEY_WIFI_ADD);
    121         mAlwaysScan = (TwoStatePreference) findPreference(KEY_WIFI_ALWAYS_SCAN);
    122 
    123         mEthernetCategory = (PreferenceCategory) findPreference(KEY_ETHERNET);
    124         mEthernetStatusPref = findPreference(KEY_ETHERNET_STATUS);
    125         mEthernetProxyPref = findPreference(KEY_ETHERNET_PROXY);
    126         mEthernetProxyPref.setIntent(EditProxySettingsActivity.createIntent(getContext(),
    127                 WifiConfiguration.INVALID_NETWORK_ID));
    128         mEthernetDhcpPref = findPreference(KEY_ETHERNET_DHCP);
    129         mEthernetDhcpPref.setIntent(EditIpSettingsActivity.createIntent(getContext(),
    130                 WifiConfiguration.INVALID_NETWORK_ID));
    131     }
    132 
    133     @Override
    134     public boolean onPreferenceTreeClick(Preference preference) {
    135         if (preference.getKey() == null) {
    136             return super.onPreferenceTreeClick(preference);
    137         }
    138         switch (preference.getKey()) {
    139             case KEY_WIFI_ENABLE:
    140                 mConnectivityListener.setWifiEnabled(mEnableWifiPref.isChecked());
    141                 if (mMetricsFeatureProvider != null) {
    142                     if (mEnableWifiPref.isChecked()) {
    143                         mMetricsFeatureProvider.action(getContext(),
    144                                 MetricsProto.MetricsEvent.ACTION_WIFI_ON);
    145                     } else {
    146                         // Log if user was connected at the time of switching off.
    147                         mMetricsFeatureProvider.action(getContext(),
    148                                 MetricsProto.MetricsEvent.ACTION_WIFI_OFF,
    149                                 mConnectivityListener.isWifiConnected());
    150                     }
    151                 }
    152                 return true;
    153             case KEY_WIFI_COLLAPSE:
    154                 final boolean collapse = !mWifiNetworksCategory.isCollapsed();
    155                 mCollapsePref.setTitle(collapse
    156                         ? R.string.wifi_setting_see_all : R.string.wifi_setting_see_fewer);
    157                 mWifiNetworksCategory.setCollapsed(collapse);
    158                 return true;
    159             case KEY_WIFI_ALWAYS_SCAN:
    160                 Settings.Global.putInt(getActivity().getContentResolver(),
    161                         Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE,
    162                         mAlwaysScan.isChecked() ? 1 : 0);
    163                 return true;
    164             case KEY_ETHERNET_STATUS:
    165                 return true;
    166             case KEY_WIFI_ADD:
    167                 mMetricsFeatureProvider.action(getActivity(),
    168                         MetricsProto.MetricsEvent.ACTION_WIFI_ADD_NETWORK);
    169                 break;
    170         }
    171         return super.onPreferenceTreeClick(preference);
    172     }
    173 
    174     private void updateConnectivity() {
    175         if (!isAdded()) {
    176             return;
    177         }
    178 
    179         final boolean wifiEnabled = mConnectivityListener.isWifiEnabledOrEnabling();
    180         mEnableWifiPref.setChecked(wifiEnabled);
    181 
    182         mWifiNetworksCategory.setVisible(wifiEnabled);
    183         mCollapsePref.setVisible(wifiEnabled && mWifiNetworksCategory.shouldShowCollapsePref());
    184         mAddPref.setVisible(wifiEnabled);
    185 
    186         if (!wifiEnabled) {
    187             updateWifiList();
    188         }
    189 
    190         int scanAlwaysAvailable = 0;
    191         try {
    192             scanAlwaysAvailable = Settings.Global.getInt(getContext().getContentResolver(),
    193                     Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE);
    194         } catch (Settings.SettingNotFoundException e) {
    195             // Ignore
    196         }
    197         mAlwaysScan.setChecked(scanAlwaysAvailable == 1);
    198 
    199         final boolean ethernetAvailable = mConnectivityListener.isEthernetAvailable();
    200         mEthernetCategory.setVisible(ethernetAvailable);
    201         mEthernetStatusPref.setVisible(ethernetAvailable);
    202         mEthernetProxyPref.setVisible(ethernetAvailable);
    203         mEthernetDhcpPref.setVisible(ethernetAvailable);
    204 
    205         if (ethernetAvailable) {
    206             final boolean ethernetConnected =
    207                     mConnectivityListener.isEthernetConnected();
    208             mEthernetStatusPref.setTitle(ethernetConnected
    209                     ? R.string.connected : R.string.not_connected);
    210             mEthernetStatusPref.setSummary(mConnectivityListener.getEthernetIpAddress());
    211         }
    212     }
    213 
    214     private void updateWifiList() {
    215         if (!isAdded()) {
    216             return;
    217         }
    218 
    219         if (!mConnectivityListener.isWifiEnabledOrEnabling()) {
    220             mWifiNetworksCategory.removeAll();
    221             mNoWifiUpdateBeforeMillis = 0;
    222             return;
    223         }
    224 
    225         final long now = SystemClock.elapsedRealtime();
    226         if (mNoWifiUpdateBeforeMillis > now) {
    227             mHandler.removeCallbacks(mInitialUpdateWifiListRunnable);
    228             mHandler.postDelayed(mInitialUpdateWifiListRunnable,
    229                     mNoWifiUpdateBeforeMillis - now);
    230             return;
    231         }
    232 
    233         final int existingCount = mWifiNetworksCategory.getRealPreferenceCount();
    234         final Set<Preference> toRemove = new HashSet<>(existingCount);
    235         for (int i = 0; i < existingCount; i++) {
    236             toRemove.add(mWifiNetworksCategory.getPreference(i));
    237         }
    238 
    239         final Context themedContext = getPreferenceManager().getContext();
    240         final Collection<AccessPoint> accessPoints = mConnectivityListener.getAvailableNetworks();
    241         int index = 0;
    242         for (final AccessPoint accessPoint : accessPoints) {
    243             accessPoint.setListener(this);
    244             AccessPointPreference pref = (AccessPointPreference) accessPoint.getTag();
    245             if (pref == null) {
    246                 pref = new AccessPointPreference(accessPoint, themedContext, mUserBadgeCache,
    247                         false);
    248                 accessPoint.setTag(pref);
    249             } else {
    250                 toRemove.remove(pref);
    251             }
    252             if (accessPoint.isActive()) {
    253                 pref.setFragment(WifiDetailsFragment.class.getName());
    254                 WifiDetailsFragment.prepareArgs(pref.getExtras(), accessPoint);
    255                 pref.setIntent(null);
    256             } else {
    257                 pref.setFragment(null);
    258                 pref.setIntent(WifiConnectionActivity.createIntent(getContext(), accessPoint));
    259             }
    260             pref.setOrder(index++);
    261             // Double-adding is harmless
    262             mWifiNetworksCategory.addPreference(pref);
    263         }
    264 
    265         for (final Preference preference : toRemove) {
    266             mWifiNetworksCategory.removePreference(preference);
    267         }
    268 
    269         mCollapsePref.setVisible(mWifiNetworksCategory.shouldShowCollapsePref());
    270     }
    271 
    272     @Override
    273     public void onConnectivityChange() {
    274         updateConnectivity();
    275     }
    276 
    277     @Override
    278     public void onWifiListChanged() {
    279         updateWifiList();
    280     }
    281 
    282     @Override
    283     public void onAccessPointChanged(AccessPoint accessPoint) {
    284         ((AccessPointPreference) accessPoint.getTag()).refresh();
    285     }
    286 
    287     @Override
    288     public void onLevelChanged(AccessPoint accessPoint) {
    289         ((AccessPointPreference) accessPoint.getTag()).onLevelChanged();
    290     }
    291 
    292     @Override
    293     public int getMetricsCategory() {
    294         return MetricsProto.MetricsEvent.SETTINGS_NETWORK_CATEGORY;
    295     }
    296 }
    297