Home | History | Annotate | Download | only in wifi
      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 
     17 package com.android.settings.wifi;
     18 
     19 import android.annotation.Nullable;
     20 import android.app.Activity;
     21 import android.app.Dialog;
     22 import android.content.Context;
     23 import android.content.res.Resources;
     24 import android.icu.text.Collator;
     25 import android.net.wifi.WifiManager;
     26 import android.os.Bundle;
     27 import android.provider.SearchIndexableResource;
     28 import android.support.v7.preference.Preference;
     29 import android.support.v7.preference.PreferenceScreen;
     30 import android.util.Log;
     31 
     32 import android.widget.Toast;
     33 import com.android.internal.logging.nano.MetricsProto;
     34 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
     35 import com.android.settings.R;
     36 import com.android.settings.SettingsPreferenceFragment;
     37 import com.android.settings.search.BaseSearchIndexProvider;
     38 import com.android.settings.search.Indexable;
     39 import com.android.settings.search.SearchIndexableRaw;
     40 import com.android.settingslib.wifi.AccessPoint;
     41 import com.android.settingslib.wifi.AccessPointPreference;
     42 import com.android.settingslib.wifi.WifiSavedConfigUtils;
     43 
     44 import java.util.ArrayList;
     45 import java.util.Arrays;
     46 import java.util.Collections;
     47 import java.util.Comparator;
     48 import java.util.List;
     49 
     50 /**
     51  * UI to manage saved networks/access points.
     52  * TODO(b/64806699): convert to {@link DashboardFragment} with {@link PreferenceController}s
     53  */
     54 public class SavedAccessPointsWifiSettings extends SettingsPreferenceFragment
     55         implements Indexable, WifiDialog.WifiDialogListener {
     56     private static final String TAG = "SavedAccessPointsWifiSettings";
     57     private static final Comparator<AccessPoint> SAVED_NETWORK_COMPARATOR =
     58             new Comparator<AccessPoint>() {
     59         final Collator mCollator = Collator.getInstance();
     60         @Override
     61         public int compare(AccessPoint ap1, AccessPoint ap2) {
     62             return mCollator.compare(
     63                     nullToEmpty(ap1.getConfigName()), nullToEmpty(ap2.getConfigName()));
     64         }
     65 
     66         private String nullToEmpty(String string) {
     67             return (string == null) ? "" : string;
     68         }
     69     };
     70 
     71     private final WifiManager.ActionListener mForgetListener = new WifiManager.ActionListener() {
     72         @Override
     73         public void onSuccess() {
     74             initPreferences();
     75         }
     76 
     77         @Override
     78         public void onFailure(int reason) {
     79             initPreferences();
     80         }
     81     };
     82 
     83     private final WifiManager.ActionListener mSaveListener = new WifiManager.ActionListener() {
     84         @Override
     85         public void onSuccess() {
     86             initPreferences();
     87         }
     88         @Override
     89         public void onFailure(int reason) {
     90             Activity activity = getActivity();
     91             if (activity != null) {
     92                 Toast.makeText(activity,
     93                     R.string.wifi_failed_save_message,
     94                     Toast.LENGTH_SHORT).show();
     95             }
     96         }
     97     };
     98 
     99     private WifiDialog mDialog;
    100     private WifiManager mWifiManager;
    101     private AccessPoint mDlgAccessPoint;
    102     private Bundle mAccessPointSavedState;
    103     private AccessPoint mSelectedAccessPoint;
    104     private Preference mAddNetworkPreference;
    105 
    106     private AccessPointPreference.UserBadgeCache mUserBadgeCache;
    107 
    108     // Instance state key
    109     private static final String SAVE_DIALOG_ACCESS_POINT_STATE = "wifi_ap_state";
    110 
    111     @Override
    112     public int getMetricsCategory() {
    113         return MetricsEvent.WIFI_SAVED_ACCESS_POINTS;
    114     }
    115 
    116     @Override
    117     public void onCreate(Bundle savedInstanceState) {
    118         super.onCreate(savedInstanceState);
    119         addPreferencesFromResource(R.xml.wifi_display_saved_access_points);
    120         mUserBadgeCache = new AccessPointPreference.UserBadgeCache(getPackageManager());
    121     }
    122 
    123     @Override
    124     public void onResume() {
    125         super.onResume();
    126         initPreferences();
    127     }
    128 
    129     @Override
    130     public void onActivityCreated(Bundle savedInstanceState) {
    131         super.onActivityCreated(savedInstanceState);
    132         mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
    133 
    134         if (savedInstanceState != null) {
    135             if (savedInstanceState.containsKey(SAVE_DIALOG_ACCESS_POINT_STATE)) {
    136                 mAccessPointSavedState =
    137                     savedInstanceState.getBundle(SAVE_DIALOG_ACCESS_POINT_STATE);
    138             }
    139         }
    140     }
    141 
    142     private void initPreferences() {
    143         PreferenceScreen preferenceScreen = getPreferenceScreen();
    144         final Context context = getPrefContext();
    145 
    146         final List<AccessPoint> accessPoints =
    147                 WifiSavedConfigUtils.getAllConfigs(context, mWifiManager);
    148         Collections.sort(accessPoints, SAVED_NETWORK_COMPARATOR);
    149         cacheRemoveAllPrefs(preferenceScreen);
    150 
    151         final int accessPointsSize = accessPoints.size();
    152         for (int i = 0; i < accessPointsSize; ++i) {
    153             AccessPoint ap = accessPoints.get(i);
    154             String key = AccessPointPreference.generatePreferenceKey(ap);
    155             LongPressAccessPointPreference preference =
    156                     (LongPressAccessPointPreference) getCachedPreference(key);
    157             if (preference == null) {
    158                 preference = new LongPressAccessPointPreference(
    159                         ap, context, mUserBadgeCache, true, this);
    160                 preference.setKey(key);
    161                 preference.setIcon(null);
    162                 preferenceScreen.addPreference(preference);
    163             }
    164             preference.setOrder(i);
    165         }
    166 
    167         removeCachedPrefs(preferenceScreen);
    168 
    169         if (mAddNetworkPreference == null) {
    170             mAddNetworkPreference = new Preference(getPrefContext());
    171             mAddNetworkPreference.setIcon(R.drawable.ic_menu_add_inset);
    172             mAddNetworkPreference.setTitle(R.string.wifi_add_network);
    173         }
    174         mAddNetworkPreference.setOrder(accessPointsSize);
    175         preferenceScreen.addPreference(mAddNetworkPreference);
    176 
    177         if(getPreferenceScreen().getPreferenceCount() < 1) {
    178             Log.w(TAG, "Saved networks activity loaded, but there are no saved networks!");
    179         }
    180     }
    181 
    182     private void showWifiDialog(@Nullable LongPressAccessPointPreference accessPoint) {
    183         if (mDialog != null) {
    184             removeDialog(WifiSettings.WIFI_DIALOG_ID);
    185             mDialog = null;
    186         }
    187 
    188         if (accessPoint != null) {
    189             // Save the access point and edit mode
    190             mDlgAccessPoint = accessPoint.getAccessPoint();
    191         } else {
    192             // No access point is selected. Clear saved state.
    193             mDlgAccessPoint = null;
    194             mAccessPointSavedState = null;
    195         }
    196 
    197         showDialog(WifiSettings.WIFI_DIALOG_ID);
    198     }
    199 
    200     @Override
    201     public Dialog onCreateDialog(int dialogId) {
    202         switch (dialogId) {
    203             case WifiSettings.WIFI_DIALOG_ID:
    204                 if (mDlgAccessPoint == null && mAccessPointSavedState == null) {
    205                     // Add new network
    206                     mDialog = WifiDialog.createFullscreen(getActivity(), this, null,
    207                             WifiConfigUiBase.MODE_CONNECT);
    208                 } else {
    209                     // Modify network
    210                     if (mDlgAccessPoint == null) {
    211                         // Restore AP from save state
    212                         mDlgAccessPoint = new AccessPoint(getActivity(), mAccessPointSavedState);
    213                         // Reset the saved access point data
    214                         mAccessPointSavedState = null;
    215                     }
    216                     mDialog = WifiDialog.createModal(getActivity(), this, mDlgAccessPoint,
    217                             WifiConfigUiBase.MODE_VIEW);
    218                 }
    219                 mSelectedAccessPoint = mDlgAccessPoint;
    220 
    221                 return mDialog;
    222         }
    223         return super.onCreateDialog(dialogId);
    224     }
    225 
    226     @Override
    227     public int getDialogMetricsCategory(int dialogId) {
    228         switch (dialogId) {
    229             case WifiSettings.WIFI_DIALOG_ID:
    230                 return MetricsProto.MetricsEvent.DIALOG_WIFI_SAVED_AP_EDIT;
    231             default:
    232                 return 0;
    233         }
    234     }
    235 
    236     @Override
    237     public void onSaveInstanceState(Bundle outState) {
    238         super.onSaveInstanceState(outState);
    239 
    240         // If the dialog is showing, save its state.
    241         if (mDialog != null && mDialog.isShowing()) {
    242             if (mDlgAccessPoint != null) {
    243                 mAccessPointSavedState = new Bundle();
    244                 mDlgAccessPoint.saveWifiState(mAccessPointSavedState);
    245                 outState.putBundle(SAVE_DIALOG_ACCESS_POINT_STATE, mAccessPointSavedState);
    246             }
    247         }
    248     }
    249 
    250     @Override
    251     public void onForget(WifiDialog dialog) {
    252         if (mSelectedAccessPoint != null) {
    253             if (mSelectedAccessPoint.isPasspointConfig()) {
    254                 try {
    255                     mWifiManager.removePasspointConfiguration(
    256                             mSelectedAccessPoint.getPasspointFqdn());
    257                 } catch (RuntimeException e) {
    258                     Log.e(TAG, "Failed to remove Passpoint configuration for "
    259                             + mSelectedAccessPoint.getConfigName());
    260                 }
    261                 initPreferences();
    262             } else {
    263                 // mForgetListener will call initPreferences upon completion
    264                 mWifiManager.forget(mSelectedAccessPoint.getConfig().networkId, mForgetListener);
    265             }
    266             mSelectedAccessPoint = null;
    267         }
    268     }
    269 
    270     @Override
    271     public void onSubmit(WifiDialog dialog) {
    272         mWifiManager.save(dialog.getController().getConfig(), mSaveListener);
    273     }
    274 
    275     @Override
    276     public boolean onPreferenceTreeClick(Preference preference) {
    277         if (preference instanceof LongPressAccessPointPreference) {
    278             showWifiDialog((LongPressAccessPointPreference) preference);
    279             return true;
    280         } else if (preference == mAddNetworkPreference) {
    281             showWifiDialog(null);
    282             return true;
    283         } else {
    284             return super.onPreferenceTreeClick(preference);
    285         }
    286     }
    287 
    288     /**
    289      * For search.
    290      */
    291     public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
    292         new BaseSearchIndexProvider() {
    293             @Override
    294             public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
    295                     boolean enabled) {
    296                 SearchIndexableResource sir = new SearchIndexableResource(context);
    297                 sir.xmlResId = R.xml.wifi_display_saved_access_points;
    298                 return Arrays.asList(sir);
    299             }
    300 
    301             @Override
    302             public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) {
    303                 final List<SearchIndexableRaw> result = new ArrayList<SearchIndexableRaw>();
    304                 final Resources res = context.getResources();
    305                 final String title = res.getString(R.string.wifi_saved_access_points_titlebar);
    306 
    307                 // Add fragment title
    308                 SearchIndexableRaw data = new SearchIndexableRaw(context);
    309                 data.title = title;
    310                 data.screenTitle = title;
    311                 data.enabled = enabled;
    312                 result.add(data);
    313 
    314                 // Add available Wi-Fi access points
    315                 final List<AccessPoint> accessPoints = WifiSavedConfigUtils.getAllConfigs(
    316                         context, context.getSystemService(WifiManager.class));
    317 
    318                 final int accessPointsSize = accessPoints.size();
    319                 for (int i = 0; i < accessPointsSize; ++i){
    320                     data = new SearchIndexableRaw(context);
    321                     data.title = accessPoints.get(i).getSsidStr();
    322                     data.screenTitle = title;
    323                     data.enabled = enabled;
    324                     result.add(data);
    325                 }
    326 
    327                 return result;
    328             }
    329         };
    330 }
    331