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.app.Dialog; 20 import android.content.Context; 21 import android.content.res.Resources; 22 import android.icu.text.Collator; 23 import android.net.wifi.WifiConfiguration; 24 import android.net.wifi.WifiManager; 25 import android.net.wifi.hotspot2.PasspointConfiguration; 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 com.android.internal.logging.nano.MetricsProto; 33 import com.android.internal.logging.nano.MetricsProto.MetricsEvent; 34 import com.android.settings.R; 35 import com.android.settings.SettingsPreferenceFragment; 36 import com.android.settings.search.BaseSearchIndexProvider; 37 import com.android.settings.search.Indexable; 38 import com.android.settings.search.SearchIndexableRaw; 39 import com.android.settingslib.wifi.AccessPoint; 40 import com.android.settingslib.wifi.AccessPointPreference; 41 import com.android.settingslib.wifi.WifiSavedConfigUtils; 42 43 import java.util.ArrayList; 44 import java.util.Arrays; 45 import java.util.Collections; 46 import java.util.Comparator; 47 import java.util.List; 48 49 /** 50 * UI to manage saved networks/access points. 51 */ 52 public class SavedAccessPointsWifiSettings extends SettingsPreferenceFragment 53 implements Indexable, WifiDialog.WifiDialogListener { 54 private static final String TAG = "SavedAccessPointsWifiSettings"; 55 private static final Comparator<AccessPoint> SAVED_NETWORK_COMPARATOR = 56 new Comparator<AccessPoint>() { 57 final Collator mCollator = Collator.getInstance(); 58 @Override 59 public int compare(AccessPoint ap1, AccessPoint ap2) { 60 return mCollator.compare( 61 nullToEmpty(ap1.getConfigName()), nullToEmpty(ap2.getConfigName())); 62 } 63 64 private String nullToEmpty(String string) { 65 return (string == null) ? "" : string; 66 } 67 }; 68 69 private final WifiManager.ActionListener mForgetListener = new WifiManager.ActionListener() { 70 @Override 71 public void onSuccess() { 72 initPreferences(); 73 } 74 75 @Override 76 public void onFailure(int reason) { 77 initPreferences(); 78 } 79 }; 80 81 private WifiDialog mDialog; 82 private WifiManager mWifiManager; 83 private AccessPoint mDlgAccessPoint; 84 private Bundle mAccessPointSavedState; 85 private AccessPoint mSelectedAccessPoint; 86 87 private AccessPointPreference.UserBadgeCache mUserBadgeCache; 88 89 // Instance state key 90 private static final String SAVE_DIALOG_ACCESS_POINT_STATE = "wifi_ap_state"; 91 92 @Override getMetricsCategory()93 public int getMetricsCategory() { 94 return MetricsEvent.WIFI_SAVED_ACCESS_POINTS; 95 } 96 97 @Override onCreate(Bundle savedInstanceState)98 public void onCreate(Bundle savedInstanceState) { 99 super.onCreate(savedInstanceState); 100 addPreferencesFromResource(R.xml.wifi_display_saved_access_points); 101 mUserBadgeCache = new AccessPointPreference.UserBadgeCache(getPackageManager()); 102 } 103 104 @Override onResume()105 public void onResume() { 106 super.onResume(); 107 initPreferences(); 108 } 109 110 @Override onActivityCreated(Bundle savedInstanceState)111 public void onActivityCreated(Bundle savedInstanceState) { 112 super.onActivityCreated(savedInstanceState); 113 mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE); 114 115 if (savedInstanceState != null) { 116 if (savedInstanceState.containsKey(SAVE_DIALOG_ACCESS_POINT_STATE)) { 117 mAccessPointSavedState = 118 savedInstanceState.getBundle(SAVE_DIALOG_ACCESS_POINT_STATE); 119 } 120 } 121 } 122 initPreferences()123 private void initPreferences() { 124 PreferenceScreen preferenceScreen = getPreferenceScreen(); 125 final Context context = getPrefContext(); 126 127 final List<AccessPoint> accessPoints = 128 WifiSavedConfigUtils.getAllConfigs(context, mWifiManager); 129 Collections.sort(accessPoints, SAVED_NETWORK_COMPARATOR); 130 preferenceScreen.removeAll(); 131 132 final int accessPointsSize = accessPoints.size(); 133 for (int i = 0; i < accessPointsSize; ++i){ 134 LongPressAccessPointPreference preference = 135 new LongPressAccessPointPreference(accessPoints.get(i), context, 136 mUserBadgeCache, true, this); 137 preference.setIcon(null); 138 preferenceScreen.addPreference(preference); 139 } 140 141 if(getPreferenceScreen().getPreferenceCount() < 1) { 142 Log.w(TAG, "Saved networks activity loaded, but there are no saved networks!"); 143 } 144 } 145 showDialog(LongPressAccessPointPreference accessPoint, boolean edit)146 private void showDialog(LongPressAccessPointPreference accessPoint, boolean edit) { 147 if (mDialog != null) { 148 removeDialog(WifiSettings.WIFI_DIALOG_ID); 149 mDialog = null; 150 } 151 152 // Save the access point and edit mode 153 mDlgAccessPoint = accessPoint.getAccessPoint(); 154 155 showDialog(WifiSettings.WIFI_DIALOG_ID); 156 } 157 158 @Override onCreateDialog(int dialogId)159 public Dialog onCreateDialog(int dialogId) { 160 switch (dialogId) { 161 case WifiSettings.WIFI_DIALOG_ID: 162 if (mDlgAccessPoint == null) { // For re-launch from saved state 163 mDlgAccessPoint = new AccessPoint(getActivity(), mAccessPointSavedState); 164 // Reset the saved access point data 165 mAccessPointSavedState = null; 166 } 167 mSelectedAccessPoint = mDlgAccessPoint; 168 169 mDialog = new WifiDialog(getActivity(), this, mDlgAccessPoint, 170 WifiConfigUiBase.MODE_VIEW, true /* hide the submit button */); 171 return mDialog; 172 173 } 174 return super.onCreateDialog(dialogId); 175 } 176 177 @Override getDialogMetricsCategory(int dialogId)178 public int getDialogMetricsCategory(int dialogId) { 179 switch (dialogId) { 180 case WifiSettings.WIFI_DIALOG_ID: 181 return MetricsProto.MetricsEvent.DIALOG_WIFI_SAVED_AP_EDIT; 182 default: 183 return 0; 184 } 185 } 186 187 @Override onSaveInstanceState(Bundle outState)188 public void onSaveInstanceState(Bundle outState) { 189 super.onSaveInstanceState(outState); 190 191 // If the dialog is showing, save its state. 192 if (mDialog != null && mDialog.isShowing()) { 193 if (mDlgAccessPoint != null) { 194 mAccessPointSavedState = new Bundle(); 195 mDlgAccessPoint.saveWifiState(mAccessPointSavedState); 196 outState.putBundle(SAVE_DIALOG_ACCESS_POINT_STATE, mAccessPointSavedState); 197 } 198 } 199 } 200 201 @Override onForget(WifiDialog dialog)202 public void onForget(WifiDialog dialog) { 203 if (mSelectedAccessPoint != null) { 204 if (mSelectedAccessPoint.isPasspointConfig()) { 205 try { 206 mWifiManager.removePasspointConfiguration( 207 mSelectedAccessPoint.getPasspointFqdn()); 208 } catch (RuntimeException e) { 209 Log.e(TAG, "Failed to remove Passpoint configuration for " 210 + mSelectedAccessPoint.getConfigName()); 211 } 212 initPreferences(); 213 } else { 214 // mForgetListener will call initPreferences upon completion 215 mWifiManager.forget(mSelectedAccessPoint.getConfig().networkId, mForgetListener); 216 } 217 mSelectedAccessPoint = null; 218 } 219 } 220 221 @Override onSubmit(WifiDialog dialog)222 public void onSubmit(WifiDialog dialog) { 223 // Ignored 224 } 225 226 @Override onPreferenceTreeClick(Preference preference)227 public boolean onPreferenceTreeClick(Preference preference) { 228 if (preference instanceof LongPressAccessPointPreference) { 229 showDialog((LongPressAccessPointPreference) preference, false); 230 return true; 231 } else{ 232 return super.onPreferenceTreeClick(preference); 233 } 234 } 235 236 /** 237 * For search. 238 */ 239 public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = 240 new BaseSearchIndexProvider() { 241 @Override 242 public List<SearchIndexableResource> getXmlResourcesToIndex(Context context, 243 boolean enabled) { 244 SearchIndexableResource sir = new SearchIndexableResource(context); 245 sir.xmlResId = R.xml.wifi_display_saved_access_points; 246 return Arrays.asList(sir); 247 } 248 249 @Override 250 public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) { 251 final List<SearchIndexableRaw> result = new ArrayList<SearchIndexableRaw>(); 252 final Resources res = context.getResources(); 253 final String title = res.getString(R.string.wifi_saved_access_points_titlebar); 254 255 // Add fragment title 256 SearchIndexableRaw data = new SearchIndexableRaw(context); 257 data.title = title; 258 data.screenTitle = title; 259 data.enabled = enabled; 260 result.add(data); 261 262 // Add available Wi-Fi access points 263 final List<AccessPoint> accessPoints = WifiSavedConfigUtils.getAllConfigs( 264 context, context.getSystemService(WifiManager.class)); 265 266 final int accessPointsSize = accessPoints.size(); 267 for (int i = 0; i < accessPointsSize; ++i){ 268 data = new SearchIndexableRaw(context); 269 data.title = accessPoints.get(i).getSsidStr(); 270 data.screenTitle = title; 271 data.enabled = enabled; 272 result.add(data); 273 } 274 275 return result; 276 } 277 }; 278 } 279