Merge "b/16154604 removing the settings link from the trust agent menu."
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 0ec6098..b645f9f 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -205,6 +205,22 @@
                 android:resource="@id/wifi_settings" />
         </activity>
 
+        <activity android:name="Settings$SavedAccessPointsSettingsActivity"
+                android:taskAffinity="com.android.settings"
+                android:label="@string/wifi_saved_access_points_label"
+                android:configChanges="orientation|keyboardHidden|screenSize"
+                android:parentActivityName="Settings$WifiSettingsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <action android:name="android.settings.WIFI_IF_SETTINGS" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                android:value="com.android.settings.wifi.SavedAccessPointsSettings" />
+            <meta-data android:name="com.android.settings.TOP_LEVEL_HEADER_ID"
+                android:resource="@id/wifi_settings" />
+        </activity>
+
         <activity android:name=".wifi.WifiInfo"
                 android:theme="@style/Theme.SubSettingsDialogWhenLarge"
                 android:taskAffinity="com.android.settings"
diff --git a/res/layout/wifi_advance_layout.xml b/res/layout/wifi_advance_layout.xml
new file mode 100644
index 0000000..b4a257a
--- /dev/null
+++ b/res/layout/wifi_advance_layout.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:minHeight="48dip"
+    android:gravity="center_vertical"
+    android:background="?android:attr/selectableItemBackground">
+
+    <RelativeLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:paddingTop="6dip"
+        android:paddingBottom="6dip">
+
+        <TextView
+            android:id="@+android:id/title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:paddingStart="16dip"
+            android:paddingEnd="16dip"
+            android:singleLine="true"
+            android:textAppearance="?android:attr/textAppearanceSmall"
+            android:ellipsize="marquee"
+            android:fadingEdge="horizontal" />
+
+        <TextView
+            android:id="@android:id/summary"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_below="@android:id/title"
+            android:layout_alignStart="@android:id/title"
+            android:paddingStart="16dip"
+            android:layout_marginEnd="16dip"
+            android:visibility="gone"
+            android:textAppearance="?android:attr/textAppearanceSmall"
+            android:textColor="?android:attr/textColorSecondary"
+            android:maxLines="4" />
+
+    </RelativeLayout>
+
+    <LinearLayout
+        android:id="@android:id/widget_frame"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:gravity="center_vertical"
+        android:orientation="vertical" />
+
+</LinearLayout>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 611801c..bf975e2 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1539,7 +1539,9 @@
     <string name="wifi_connect_failed_message" product="default">The phone was unable to connect to this Wi\u2011Fi network.</string>
 
     <!-- Wi-Fi Advanced Settings --> <skip />
-    <!-- Wi-Fi settings screen, advanced, settings section.  This is a header shown above advanced wifi settings. -->
+    <!-- Wi-Fi settings screen, Saved networks, settings section.  This is a header shown above Saved networks wifi settings. [CHAR LIMIT=30] -->
+    <string name="wifi_saved_access_points_titlebar">Saved networks</string>
+    <!-- Wi-Fi settings screen, advanced, settings section.  This is a header shown above advanced wifi settings. [CHAR LIMIT=30] -->
     <string name="wifi_advanced_titlebar">Advanced Wi\u2011Fi</string>
     <!-- Wi-Fi settings screen, setting title for setting the band [CHAR LIMIT=50]-->
     <string name="wifi_setting_frequency_band_title">Wi\u2011Fi frequency band</string>
@@ -1553,7 +1555,9 @@
     <!-- Wi-Fi settings screen, advanced, title of the item to show the Wi-Fi device's current IP address. -->
     <string name="wifi_advanced_ip_address_title">IP address</string>
 
-    <!-- Wifi Advanced settings.  Used as a label under the shortcut icon that goes to Wifi advanced settings. [CHAR LIMIT=20]-->
+    <!-- Wifi saved access points.  Used as a label under the shortcut icon that goes to Wifi saved access points. [CHAR LIMIT=20] -->
+    <string name="wifi_saved_access_points_label">Saved networks</string>
+    <!-- Wifi Advanced settings.  Used as a label under the shortcut icon that goes to Wifi advanced settings. [CHAR LIMIT=20] -->
     <string name="wifi_advanced_settings_label">IP settings</string>
     <!-- Menu item to save the IP settings -->
     <string name="wifi_ip_settings_menu_save">Save</string>
@@ -3625,6 +3629,8 @@
 
     <!-- Label for power consumed by the screen -->
     <string name="power_screen">Screen</string>
+    <!-- Label for power consumed by the flashlight -->
+    <string name="power_flashlight">Flashlight</string>
     <!-- Label for power consumed by Wi-Fi -->
     <string name="power_wifi">Wi\u2011Fi</string>
     <!-- Label for power consumed by Bluetooth -->
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 6d2fdd7..0f7e652 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -238,11 +238,6 @@
         <item name="android:singleLine">true</item>
     </style>
 
-    <style name="InputMethodPreferenceStyle">
-        <item name="android:layout">@layout/preference_inputmethod</item>
-        <item name="android:widgetLayout">@layout/preference_inputmethod_widget</item>
-    </style>
-
     <style name="TextAppearance.PagerTabs" parent="@android:style/TextAppearance.Material.Small">
         <item name="android:textAllCaps">true</item>
         <item name="android:textStyle">bold</item>
diff --git a/res/xml/wifi_advanced_settings.xml b/res/xml/wifi_advanced_settings.xml
index efa94b2..118f691 100644
--- a/res/xml/wifi_advanced_settings.xml
+++ b/res/xml/wifi_advanced_settings.xml
@@ -68,20 +68,25 @@
             android:title="@string/wifi_menu_wps_pbc"
             android:persistent="false" />
 
+    <Preference
+            android:key="wps_pin_entry"
+            android:title="@string/wifi_menu_wps_pin"
+            android:persistent="false" />
+
     <CheckBoxPreference
             android:key="suspend_optimizations"
             android:title="@string/wifi_suspend_optimizations"
             android:summary="@string/wifi_suspend_optimizations_summary"
             android:persistent="false" />
-    
-    <Preference android:key="mac_address" 
-        style="?android:attr/preferenceInformationStyle" 
-        android:title="@string/wifi_advanced_mac_address_title"
-        />
-    
-    <Preference android:key="current_ip_address"
-        style="?android:attr/preferenceInformationStyle"
-        android:title="@string/wifi_advanced_ip_address_title"
-        />
+
+    <Preference
+            android:key="mac_address"
+            android:title="@string/wifi_advanced_mac_address_title"
+            android:layout="@layout/wifi_advance_layout" />
+
+    <Preference
+            android:key="current_ip_address"
+            android:title="@string/wifi_advanced_ip_address_title"
+            android:layout="@layout/wifi_advance_layout" />
 
 </PreferenceScreen>   
diff --git a/res/xml/wifi_display_saved_access_points.xml b/res/xml/wifi_display_saved_access_points.xml
new file mode 100644
index 0000000..2be31d2
--- /dev/null
+++ b/res/xml/wifi_display_saved_access_points.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+    android:title="@string/wifi_display_settings_title">
+
+</PreferenceScreen>
diff --git a/res/xml/wifi_display_settings.xml b/res/xml/wifi_display_settings.xml
index 2b32106..81fb701 100644
--- a/res/xml/wifi_display_settings.xml
+++ b/res/xml/wifi_display_settings.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
+<!-- Copyright (C) 2014 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -14,8 +14,7 @@
      limitations under the License.
 -->
 
-<PreferenceScreen
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:title="@string/wifi_display_settings_title" >
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+    android:title="@string/wifi_saved_access_points_titlebar">
 
 </PreferenceScreen>
diff --git a/src/com/android/settings/CryptKeeper.java b/src/com/android/settings/CryptKeeper.java
index e9fed4f..151927d 100644
--- a/src/com/android/settings/CryptKeeper.java
+++ b/src/com/android/settings/CryptKeeper.java
@@ -209,6 +209,7 @@
                         final InputMethodManager imm = (InputMethodManager) getSystemService(
                                                   Context.INPUT_METHOD_SERVICE);
                         imm.showSoftInput(mPasswordEntry, 0);
+                        setBackFunctionality(true);
                     }
                     if (mLockPatternView != null) {
                         mLockPatternView.setEnabled(true);
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index 33bdedf..ada1b0d 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -73,6 +73,7 @@
     public static class DeviceAdminSettingsActivity extends SettingsActivity { /* empty */ }
     public static class DataUsageSummaryActivity extends SettingsActivity { /* empty */ }
     public static class AdvancedWifiSettingsActivity extends SettingsActivity { /* empty */ }
+    public static class SavedAccessPointsSettingsActivity extends SettingsActivity { /* empty */ }
     public static class TextToSpeechSettingsActivity extends SettingsActivity { /* empty */ }
     public static class AndroidBeamSettingsActivity extends SettingsActivity { /* empty */ }
     public static class WifiDisplaySettingsActivity extends SettingsActivity { /* empty */ }
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index 1b2a48c..b0d3241 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -107,6 +107,7 @@
 import com.android.settings.wfd.WifiDisplaySettings;
 import com.android.settings.widget.SwitchBar;
 import com.android.settings.wifi.AdvancedWifiSettings;
+import com.android.settings.wifi.SavedAccessPointsWifiSettings;
 import com.android.settings.wifi.WifiSettings;
 import com.android.settings.wifi.p2p.WifiP2pSettings;
 
@@ -234,6 +235,7 @@
             WirelessSettings.class.getName(),
             WifiSettings.class.getName(),
             AdvancedWifiSettings.class.getName(),
+            SavedAccessPointsWifiSettings.class.getName(),
             BluetoothSettings.class.getName(),
             TetherSettings.class.getName(),
             WifiP2pSettings.class.getName(),
diff --git a/src/com/android/settings/fuelgauge/BatteryEntry.java b/src/com/android/settings/fuelgauge/BatteryEntry.java
index c2bf127..e527276 100644
--- a/src/com/android/settings/fuelgauge/BatteryEntry.java
+++ b/src/com/android/settings/fuelgauge/BatteryEntry.java
@@ -150,6 +150,10 @@
                 name = context.getResources().getString(R.string.power_screen);
                 iconId = R.drawable.ic_settings_display;
                 break;
+            case FLASHLIGHT:
+                name = context.getResources().getString(R.string.power_flashlight);
+                iconId = R.drawable.ic_settings_display;
+                break;
             case APP:
                 name = sipper.packageWithHighestDrain;
                 break;
diff --git a/src/com/android/settings/fuelgauge/BatteryHistoryChart.java b/src/com/android/settings/fuelgauge/BatteryHistoryChart.java
index daff7ea..60e73f5 100644
--- a/src/com/android/settings/fuelgauge/BatteryHistoryChart.java
+++ b/src/com/android/settings/fuelgauge/BatteryHistoryChart.java
@@ -17,6 +17,7 @@
 package com.android.settings.fuelgauge;
 
 import android.content.Intent;
+import android.graphics.Bitmap;
 import android.graphics.DashPathEffect;
 import android.os.BatteryManager;
 import android.provider.Settings;
@@ -219,6 +220,9 @@
     final ArrayList<TimeLabel> mTimeLabels = new ArrayList<TimeLabel>();
     final ArrayList<DateLabel> mDateLabels = new ArrayList<DateLabel>();
 
+    Bitmap mBitmap;
+    Canvas mCanvas;
+
     static class TextAttrs {
         ColorStateList textColor = null;
         int textSize = 15;
@@ -339,6 +343,8 @@
     public BatteryHistoryChart(Context context, AttributeSet attrs) {
         super(context, attrs);
 
+        if (DEBUG) Log.d(TAG, "New BatteryHistoryChart!");
+
         mBatteryWarnLevel = mContext.getResources().getInteger(
                 com.android.internal.R.integer.config_lowBatteryWarningLevel);
         mBatteryCriticalLevel = mContext.getResources().getInteger(
@@ -468,6 +474,8 @@
         mStats = stats;
         mBatteryBroadcast = broadcast;
 
+        if (DEBUG) Log.d(TAG, "Setting stats...");
+
         final long elapsedRealtimeUs = SystemClock.elapsedRealtime() * 1000;
 
         long uSecTime = mStats.computeBatteryRealtime(elapsedRealtimeUs,
@@ -687,8 +695,12 @@
             return;
         }
 
+        if (DEBUG) Log.d(TAG, "Rebuilding chart for: " + w + "x" + h);
+
         mLastWidth = w;
         mLastHeight = h;
+        mBitmap = null;
+        mCanvas = null;
 
         int textHeight = mTextDescent - mTextAscent;
         if (h > ((textHeight*10)+mChartMinHeight)) {
@@ -1025,6 +1037,13 @@
                 endRoundTime = calEnd.getTimeInMillis();
                 if (startRoundTime < endRoundTime) {
                     addDateLabel(calStart, mLevelLeft, mLevelRight, isDayFirst);
+                    Calendar calMid = Calendar.getInstance();
+                    calMid.setTimeInMillis(startRoundTime + ((endRoundTime - startRoundTime) / 2));
+                    calMid.set(Calendar.HOUR_OF_DAY, 0);
+                    long calMidMillis = calMid.getTimeInMillis();
+                    if (calMidMillis > startRoundTime && calMidMillis < endRoundTime) {
+                        addDateLabel(calMid, mLevelLeft, mLevelRight, isDayFirst);
+                    }
                 }
                 addDateLabel(calEnd, mLevelLeft, mLevelRight, isDayFirst);
             }
@@ -1067,8 +1086,27 @@
         final int width = getWidth();
         final int height = getHeight();
 
-        if (DEBUG) Log.d(TAG, "onDraw: " + width + "x" + height);
+        //buildBitmap(width, height);
 
+        if (DEBUG) Log.d(TAG, "onDraw: " + width + "x" + height);
+        //canvas.drawBitmap(mBitmap, 0, 0, null);
+        drawChart(canvas, width, height);
+    }
+
+    void buildBitmap(int width, int height) {
+        if (mBitmap != null && width == mBitmap.getWidth() && height == mBitmap.getHeight()) {
+            return;
+        }
+
+        if (DEBUG) Log.d(TAG, "buildBitmap: " + width + "x" + height);
+
+        mBitmap = Bitmap.createBitmap(getResources().getDisplayMetrics(), width, height,
+                Bitmap.Config.ARGB_8888);
+        mCanvas = new Canvas(mBitmap);
+        drawChart(mCanvas, width, height);
+    }
+
+    void drawChart(Canvas canvas, int width, int height) {
         final boolean layoutRtl = isLayoutRtl();
         final int textStartX = layoutRtl ? width : 0;
         final int textEndX = layoutRtl ? 0 : width;
diff --git a/src/com/android/settings/inputmethod/CheckBoxAndSettingsPreference.java b/src/com/android/settings/inputmethod/CheckBoxAndSettingsPreference.java
index 375bee7..c6208ed 100644
--- a/src/com/android/settings/inputmethod/CheckBoxAndSettingsPreference.java
+++ b/src/com/android/settings/inputmethod/CheckBoxAndSettingsPreference.java
@@ -29,7 +29,8 @@
 import android.widget.ImageView;
 import android.widget.TextView;
 
-public class CheckBoxAndSettingsPreference extends CheckBoxPreference {
+// TODO: Make this non-persistent.
+class CheckBoxAndSettingsPreference extends CheckBoxPreference {
 
     private SettingsPreferenceFragment mFragment;
     private TextView mTitleText;
diff --git a/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java b/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java
index 54a5698..0f9ae19 100644
--- a/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java
+++ b/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java
@@ -70,7 +70,6 @@
 public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment
         implements Preference.OnPreferenceChangeListener, InputManager.InputDeviceListener,
         KeyboardLayoutDialogFragment.OnSetupKeyboardLayoutsListener, Indexable {
-
     private static final String KEY_PHONE_LANGUAGE = "phone_language";
     private static final String KEY_CURRENT_INPUT_METHOD = "current_input_method";
     private static final String KEY_INPUT_METHOD_SELECTOR = "input_method_selector";
@@ -92,10 +91,8 @@
     private PreferenceCategory mHardKeyboardCategory;
     private PreferenceCategory mGameControllerCategory;
     private Preference mLanguagePref;
-    private final ArrayList<InputMethodPreference> mInputMethodPreferenceList =
-            new ArrayList<InputMethodPreference>();
-    private final ArrayList<PreferenceScreen> mHardKeyboardPreferenceList =
-            new ArrayList<PreferenceScreen>();
+    private final ArrayList<InputMethodPreference> mInputMethodPreferenceList = new ArrayList<>();
+    private final ArrayList<PreferenceScreen> mHardKeyboardPreferenceList = new ArrayList<>();
     private InputManager mIm;
     private InputMethodManager mImm;
     private boolean mIsOnlyImeSettings;
@@ -467,7 +464,7 @@
             final CharSequence curIme =
                     mInputMethodSettingValues.getCurrentInputMethodName(context);
             if (!TextUtils.isEmpty(curIme)) {
-                synchronized(this) {
+                synchronized (this) {
                     curPref.setSummary(curIme);
                 }
             }
@@ -488,8 +485,7 @@
         }
 
         // Add a check box for enabling/disabling IME
-        final InputMethodPreference pref =
-                new InputMethodPreference(this, intent, mImm, imi);
+        final InputMethodPreference pref = new InputMethodPreference(this, intent, mImm, imi);
         pref.setKey(imi.getId());
         pref.setTitle(label);
         return pref;
@@ -557,8 +553,8 @@
     }
 
     private void showKeyboardLayoutDialog(InputDeviceIdentifier inputDeviceIdentifier) {
-        KeyboardLayoutDialogFragment fragment =
-                new KeyboardLayoutDialogFragment(inputDeviceIdentifier);
+        KeyboardLayoutDialogFragment fragment = new KeyboardLayoutDialogFragment(
+                inputDeviceIdentifier);
         fragment.setTargetFragment(this, 0);
         fragment.show(getActivity().getFragmentManager(), "keyboardLayout");
     }
@@ -638,7 +634,7 @@
             new BaseSearchIndexProvider() {
         @Override
         public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) {
-            List<SearchIndexableRaw> indexables = new ArrayList<SearchIndexableRaw>();
+            List<SearchIndexableRaw> indexables = new ArrayList<>();
 
             Resources resources = context.getResources();
             String screenTitle = context.getString(R.string.language_keyboard_settings_title);
diff --git a/src/com/android/settings/inputmethod/InputMethodAndSubtypeEnabler.java b/src/com/android/settings/inputmethod/InputMethodAndSubtypeEnabler.java
index 3351e63..5a94e35 100644
--- a/src/com/android/settings/inputmethod/InputMethodAndSubtypeEnabler.java
+++ b/src/com/android/settings/inputmethod/InputMethodAndSubtypeEnabler.java
@@ -40,7 +40,6 @@
 import java.text.Collator;
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.Comparator;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
@@ -50,9 +49,8 @@
     private AlertDialog mDialog = null;
     private boolean mHaveHardKeyboard;
     final private HashMap<String, List<Preference>> mInputMethodAndSubtypePrefsMap =
-            new HashMap<String, List<Preference>>();
-    final private HashMap<String, CheckBoxPreference> mSubtypeAutoSelectionCBMap =
-            new HashMap<String, CheckBoxPreference>();
+            new HashMap<>();
+    final private HashMap<String, CheckBoxPreference> mSubtypeAutoSelectionCBMap = new HashMap<>();
     private InputMethodManager mImm;
     private List<InputMethodInfo> mInputMethodProperties;
     private String mInputMethodId;
@@ -256,7 +254,7 @@
 
             boolean isAutoSubtype = false;
             CharSequence autoSubtypeLabel = null;
-            final ArrayList<Preference> subtypePreferences = new ArrayList<Preference>();
+            final ArrayList<Preference> subtypePreferences = new ArrayList<>();
             if (subtypeCount > 0) {
                 for (int j = 0; j < subtypeCount; ++j) {
                     final InputMethodSubtype subtype = imi.getSubtypeAt(j);
diff --git a/src/com/android/settings/inputmethod/InputMethodAndSubtypeEnablerActivity.java b/src/com/android/settings/inputmethod/InputMethodAndSubtypeEnablerActivity.java
index da95b47..b664540 100644
--- a/src/com/android/settings/inputmethod/InputMethodAndSubtypeEnablerActivity.java
+++ b/src/com/android/settings/inputmethod/InputMethodAndSubtypeEnablerActivity.java
@@ -20,19 +20,19 @@
 import com.android.settings.SettingsActivity;
 
 public class InputMethodAndSubtypeEnablerActivity extends SettingsActivity {
+    private static final String FRAGMENT_NAME = InputMethodAndSubtypeEnabler.class.getName();
+
     @Override
     public Intent getIntent() {
         final Intent modIntent = new Intent(super.getIntent());
         if (!modIntent.hasExtra(EXTRA_SHOW_FRAGMENT)) {
-            modIntent.putExtra(EXTRA_SHOW_FRAGMENT, InputMethodAndSubtypeEnabler.class.getName());
+            modIntent.putExtra(EXTRA_SHOW_FRAGMENT, FRAGMENT_NAME);
         }
         return modIntent;
     }
 
     @Override
     protected boolean isValidFragment(String fragmentName) {
-        if (InputMethodAndSubtypeEnabler.class.getName().equals(fragmentName)) return true;
-        return false;
+        return FRAGMENT_NAME.equals(fragmentName);
     }
-
 }
diff --git a/src/com/android/settings/inputmethod/InputMethodAndSubtypeUtil.java b/src/com/android/settings/inputmethod/InputMethodAndSubtypeUtil.java
index 561302a..bf3a601 100644
--- a/src/com/android/settings/inputmethod/InputMethodAndSubtypeUtil.java
+++ b/src/com/android/settings/inputmethod/InputMethodAndSubtypeUtil.java
@@ -35,7 +35,8 @@
 import java.util.List;
 import java.util.Map;
 
-public class InputMethodAndSubtypeUtil {
+// TODO: Consolidate this with {@link InputMethodSettingValuesWrapper}.
+class InputMethodAndSubtypeUtil {
 
     private static final boolean DEBUG = false;
     static final String TAG = "InputMethdAndSubtypeUtil";
@@ -50,8 +51,8 @@
     private static final TextUtils.SimpleStringSplitter sStringInputMethodSubtypeSplitter
             = new TextUtils.SimpleStringSplitter(INPUT_METHOD_SUBTYPE_SEPARATER);
 
-    private static void buildEnabledInputMethodsString(
-            StringBuilder builder, String imi, HashSet<String> subtypes) {
+    private static void buildEnabledInputMethodsString(StringBuilder builder, String imi,
+            HashSet<String> subtypes) {
         builder.append(imi);
         // Inputmethod and subtypes are saved in the settings as follows:
         // ime0;subtype0;subtype1:ime1;subtype0:ime2:ime3;subtype0;subtype1
@@ -60,8 +61,8 @@
         }
     }
 
-    public static void buildInputMethodsAndSubtypesString(
-            StringBuilder builder, HashMap<String, HashSet<String>> imsList) {
+    private static void buildInputMethodsAndSubtypesString(StringBuilder builder,
+            HashMap<String, HashSet<String>> imsList) {
         boolean needsAppendSeparator = false;
         for (String imi: imsList.keySet()) {
             if (needsAppendSeparator) {
@@ -73,8 +74,8 @@
         }
     }
 
-    public static void buildDisabledSystemInputMethods(
-            StringBuilder builder, HashSet<String> imes) {
+    private static void buildDisabledSystemInputMethods(StringBuilder builder,
+            HashSet<String> imes) {
         boolean needsAppendSeparator = false;
         for (String ime: imes) {
             if (needsAppendSeparator) {
@@ -108,8 +109,7 @@
             ContentResolver resolver) {
         final String enabledInputMethodsStr = Settings.Secure.getString(
                 resolver, Settings.Secure.ENABLED_INPUT_METHODS);
-        HashMap<String, HashSet<String>> imsList
-                = new HashMap<String, HashSet<String>>();
+        HashMap<String, HashSet<String>> imsList = new HashMap<>();
         if (DEBUG) {
             Log.d(TAG, "--- Load enabled input methods: " + enabledInputMethodsStr);
         }
@@ -122,7 +122,7 @@
             String nextImsStr = sStringInputMethodSplitter.next();
             sStringInputMethodSubtypeSplitter.setString(nextImsStr);
             if (sStringInputMethodSubtypeSplitter.hasNext()) {
-                HashSet<String> subtypeHashes = new HashSet<String>();
+                HashSet<String> subtypeHashes = new HashSet<>();
                 // The first element is ime id.
                 String imeId = sStringInputMethodSubtypeSplitter.next();
                 while (sStringInputMethodSubtypeSplitter.hasNext()) {
@@ -135,7 +135,7 @@
     }
 
     private static HashSet<String> getDisabledSystemIMEs(ContentResolver resolver) {
-        HashSet<String> set = new HashSet<String>();
+        HashSet<String> set = new HashSet<>();
         String disabledIMEsStr = Settings.Secure.getString(
                 resolver, Settings.Secure.DISABLED_SYSTEM_INPUT_METHODS);
         if (TextUtils.isEmpty(disabledIMEsStr)) {
@@ -148,7 +148,7 @@
         return set;
     }
 
-    public static void saveInputMethodSubtypeList(SettingsPreferenceFragment context,
+    static void saveInputMethodSubtypeList(SettingsPreferenceFragment context,
             ContentResolver resolver, List<InputMethodInfo> inputMethodInfos,
             boolean hasHardKeyboard) {
         String currentInputMethodId = Settings.Secure.getString(resolver,
@@ -158,7 +158,6 @@
                 getEnabledInputMethodsAndSubtypeList(resolver);
         HashSet<String> disabledSystemIMEs = getDisabledSystemIMEs(resolver);
 
-        final int imiCount = inputMethodInfos.size();
         boolean needsToResetSelectedSubtype = false;
         for (InputMethodInfo imi : inputMethodInfos) {
             final String imiId = imi.getId();
@@ -273,9 +272,8 @@
                 currentInputMethodId != null ? currentInputMethodId : "");
     }
 
-    public static void loadInputMethodSubtypeList(
-            SettingsPreferenceFragment context, ContentResolver resolver,
-            List<InputMethodInfo> inputMethodInfos,
+    static void loadInputMethodSubtypeList(SettingsPreferenceFragment context,
+            ContentResolver resolver, List<InputMethodInfo> inputMethodInfos,
             final Map<String, List<Preference>> inputMethodPrefsMap) {
         HashMap<String, HashSet<String>> enabledSubtypes =
                 getEnabledInputMethodsAndSubtypeList(resolver);
@@ -298,7 +296,7 @@
         updateSubtypesPreferenceChecked(context, inputMethodInfos, enabledSubtypes);
     }
 
-    public static void setSubtypesPreferenceEnabled(SettingsPreferenceFragment context,
+    static void setSubtypesPreferenceEnabled(SettingsPreferenceFragment context,
             List<InputMethodInfo> inputMethodProperties, String id, boolean enabled) {
         PreferenceScreen preferenceScreen = context.getPreferenceScreen();
         for (InputMethodInfo imi : inputMethodProperties) {
@@ -316,7 +314,7 @@
         }
     }
 
-    public static void updateSubtypesPreferenceChecked(SettingsPreferenceFragment context,
+    private static void updateSubtypesPreferenceChecked(SettingsPreferenceFragment context,
             List<InputMethodInfo> inputMethodProperties,
             HashMap<String, HashSet<String>> enabledSubtypes) {
         PreferenceScreen preferenceScreen = context.getPreferenceScreen();
diff --git a/src/com/android/settings/inputmethod/InputMethodPreference.java b/src/com/android/settings/inputmethod/InputMethodPreference.java
index e04f2c7..87a0a77 100644
--- a/src/com/android/settings/inputmethod/InputMethodPreference.java
+++ b/src/com/android/settings/inputmethod/InputMethodPreference.java
@@ -47,7 +47,8 @@
 import java.text.Collator;
 import java.util.List;
 
-public class InputMethodPreference extends CheckBoxPreference {
+// TODO: Make this non-persistent.
+class InputMethodPreference extends CheckBoxPreference {
     private static final String TAG = InputMethodPreference.class.getSimpleName();
     private final SettingsPreferenceFragment mFragment;
     private final InputMethodInfo mImi;
@@ -84,7 +85,7 @@
 
     public InputMethodPreference(SettingsPreferenceFragment fragment, Intent settingsIntent,
             InputMethodManager imm, InputMethodInfo imi) {
-        super(fragment.getActivity(), null, R.style.InputMethodPreferenceStyle);
+        super(fragment.getActivity());
         setLayoutResource(R.layout.preference_inputmethod);
         setWidgetLayoutResource(R.layout.preference_inputmethod_widget);
         mFragment = fragment;
diff --git a/src/com/android/settings/inputmethod/InputMethodSettingValuesWrapper.java b/src/com/android/settings/inputmethod/InputMethodSettingValuesWrapper.java
index ccba143..bf63487 100644
--- a/src/com/android/settings/inputmethod/InputMethodSettingValuesWrapper.java
+++ b/src/com/android/settings/inputmethod/InputMethodSettingValuesWrapper.java
@@ -39,22 +39,20 @@
  * manually on some events when "InputMethodInfo"s and "InputMethodSubtype"s can be
  * changed.
  */
-public class InputMethodSettingValuesWrapper {
+// TODO: Consolidate this with {@link InputMethodAndSubtypeUtil}.
+class InputMethodSettingValuesWrapper {
     private static final String TAG = InputMethodSettingValuesWrapper.class.getSimpleName();
-    private static final Locale ENGLISH_LOCALE = new Locale("en");
 
     private static volatile InputMethodSettingValuesWrapper sInstance;
-    private final ArrayList<InputMethodInfo> mMethodList = new ArrayList<InputMethodInfo>();
-    private final HashMap<String, InputMethodInfo> mMethodMap =
-            new HashMap<String, InputMethodInfo>();
+    private final ArrayList<InputMethodInfo> mMethodList = new ArrayList<>();
+    private final HashMap<String, InputMethodInfo> mMethodMap = new HashMap<>();
     private final InputMethodSettings mSettings;
     private final InputMethodManager mImm;
-    private final HashSet<InputMethodInfo> mAsciiCapableEnabledImis =
-            new HashSet<InputMethodInfo>();
+    private final HashSet<InputMethodInfo> mAsciiCapableEnabledImis = new HashSet<>();
 
-    public static InputMethodSettingValuesWrapper getInstance(Context context) {
+    static InputMethodSettingValuesWrapper getInstance(Context context) {
         if (sInstance == null) {
-            synchronized(TAG) {
+            synchronized (TAG) {
                 if (sInstance == null) {
                     sInstance = new InputMethodSettingValuesWrapper(context);
                 }
@@ -74,14 +72,13 @@
 
     // Ensure singleton
     private InputMethodSettingValuesWrapper(Context context) {
-        mSettings =
-                new InputMethodSettings(context.getResources(), context.getContentResolver(),
-                        mMethodMap, mMethodList, getDefaultCurrentUserId());
+        mSettings = new InputMethodSettings(context.getResources(), context.getContentResolver(),
+                mMethodMap, mMethodList, getDefaultCurrentUserId());
         mImm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
         refreshAllInputMethodAndSubtypes();
     }
 
-    public void refreshAllInputMethodAndSubtypes() {
+    void refreshAllInputMethodAndSubtypes() {
         synchronized (mMethodMap) {
             mMethodList.clear();
             mMethodMap.clear();
@@ -113,13 +110,13 @@
         }
     }
 
-    public List<InputMethodInfo> getInputMethodList() {
+    List<InputMethodInfo> getInputMethodList() {
         synchronized (mMethodMap) {
             return mMethodList;
         }
     }
 
-    public CharSequence getCurrentInputMethodName(Context context) {
+    CharSequence getCurrentInputMethodName(Context context) {
         synchronized (mMethodMap) {
             final InputMethodInfo imi = mMethodMap.get(mSettings.getSelectedInputMethod());
             if (imi == null) {
@@ -131,7 +128,7 @@
         }
     }
 
-    public boolean isAlwaysCheckedIme(InputMethodInfo imi, Context context) {
+    boolean isAlwaysCheckedIme(InputMethodInfo imi, Context context) {
         final boolean isEnabled = isEnabledImi(imi);
         synchronized (mMethodMap) {
             if (mSettings.getEnabledInputMethodListLocked().size() <= 1 && isEnabled) {
@@ -158,7 +155,7 @@
     private int getEnabledValidSystemNonAuxAsciiCapableImeCount(Context context) {
         int count = 0;
         final List<InputMethodInfo> enabledImis;
-        synchronized(mMethodMap) {
+        synchronized (mMethodMap) {
             enabledImis = mSettings.getEnabledInputMethodListLocked();
         }
         for (final InputMethodInfo imi : enabledImis) {
@@ -174,7 +171,7 @@
 
     private boolean isEnabledImi(InputMethodInfo imi) {
         final List<InputMethodInfo> enabledImis;
-        synchronized(mMethodMap) {
+        synchronized (mMethodMap) {
             enabledImis = mSettings.getEnabledInputMethodListLocked();
         }
         for (final InputMethodInfo tempImi : enabledImis) {
@@ -185,8 +182,7 @@
         return false;
     }
 
-    public boolean isValidSystemNonAuxAsciiCapableIme(InputMethodInfo imi,
-            Context context) {
+    boolean isValidSystemNonAuxAsciiCapableIme(InputMethodInfo imi, Context context) {
         if (imi.isAuxiliaryIme()) {
             return false;
         }
@@ -196,7 +192,7 @@
         if (mAsciiCapableEnabledImis.isEmpty()) {
             Log.w(TAG, "ascii capable subtype enabled imi not found. Fall back to English"
                     + " Keyboard subtype.");
-            return InputMethodUtils.containsSubtypeOf(imi, ENGLISH_LOCALE.getLanguage(),
+            return InputMethodUtils.containsSubtypeOf(imi, Locale.ENGLISH.getLanguage(),
                     InputMethodUtils.SUBTYPE_MODE_KEYBOARD);
         }
         return mAsciiCapableEnabledImis.contains(imi);
diff --git a/src/com/android/settings/inputmethod/SingleSpellCheckerPreference.java b/src/com/android/settings/inputmethod/SingleSpellCheckerPreference.java
index bc79b42..2dc90ec 100644
--- a/src/com/android/settings/inputmethod/SingleSpellCheckerPreference.java
+++ b/src/com/android/settings/inputmethod/SingleSpellCheckerPreference.java
@@ -34,10 +34,10 @@
 import android.view.textservice.TextServicesManager;
 import android.widget.ImageView;
 import android.widget.RadioButton;
-import android.widget.TextView;
 import android.widget.Toast;
 
-public class SingleSpellCheckerPreference extends Preference {
+// TODO: Make this non-persistent.
+class SingleSpellCheckerPreference extends Preference {
     private static final String TAG = SingleSpellCheckerPreference.class.getSimpleName();
     private static final boolean DBG = false;
 
@@ -47,8 +47,6 @@
     private final Resources mRes;
     private final TextServicesManager mTsm;
     private AlertDialog mDialog = null;
-    private TextView mTitleText;
-    private TextView mSummaryText;
     private View mPrefAll;
     private RadioButton mRadioButton;
     private View mPrefLeftButton;
@@ -88,8 +86,6 @@
                         onLeftButtonClicked(arg0);
                     }
                 });
-        mTitleText = (TextView)view.findViewById(android.R.id.title);
-        mSummaryText = (TextView)view.findViewById(android.R.id.summary);
         mSubtypeButton = (ImageView)view.findViewById(R.id.pref_right_button2);
         mSubtypeButton.setOnClickListener(
                 new OnClickListener() {
diff --git a/src/com/android/settings/inputmethod/SpellCheckersPreference.java b/src/com/android/settings/inputmethod/SpellCheckersPreference.java
index 9e68604..1482b6c 100644
--- a/src/com/android/settings/inputmethod/SpellCheckersPreference.java
+++ b/src/com/android/settings/inputmethod/SpellCheckersPreference.java
@@ -20,7 +20,8 @@
 import android.util.AttributeSet;
 import android.view.textservice.TextServicesManager;
 
-public class SpellCheckersPreference extends CheckBoxAndSettingsPreference {
+// TODO: Make this non-persistent.
+class SpellCheckersPreference extends CheckBoxAndSettingsPreference {
     private TextServicesManager mTsm;
 
     public SpellCheckersPreference(Context context) {
diff --git a/src/com/android/settings/search/Index.java b/src/com/android/settings/search/Index.java
index 9723fbf..ed06e31 100644
--- a/src/com/android/settings/search/Index.java
+++ b/src/com/android/settings/search/Index.java
@@ -28,6 +28,7 @@
 import android.content.res.XmlResourceParser;
 import android.database.Cursor;
 import android.database.DatabaseUtils;
+import android.database.MergeCursor;
 import android.database.sqlite.SQLiteDatabase;
 import android.net.Uri;
 import android.os.AsyncTask;
@@ -123,9 +124,12 @@
             IndexColumns.DATA_KEY_REF             // 13
     };
 
-    private static final String[] MATCH_COLUMNS = {
+    private static final String[] MATCH_COLUMNS_PRIMARY = {
             IndexColumns.DATA_TITLE,
-            IndexColumns.DATA_TITLE_NORMALIZED,
+            IndexColumns.DATA_TITLE_NORMALIZED
+    };
+
+    private static final String[] MATCH_COLUMNS_SECONDARY = {
             IndexColumns.DATA_SUMMARY_ON,
             IndexColumns.DATA_SUMMARY_ON_NORMALIZED,
             IndexColumns.DATA_SUMMARY_OFF,
@@ -214,9 +218,24 @@
     }
 
     public Cursor search(String query) {
-        final String sql = buildSearchSQL(query);
-        Log.d(LOG_TAG, "Search query: " + sql);
-        return getReadableDatabase().rawQuery(sql, null);
+        final SQLiteDatabase database = getReadableDatabase();
+        final Cursor[] cursors = new Cursor[2];
+
+        final String primarySql = buildSearchSQL(query, MATCH_COLUMNS_PRIMARY, true);
+        Log.d(LOG_TAG, "Search primary query: " + primarySql);
+        cursors[0] = database.rawQuery(primarySql, null);
+
+        // We need to use an EXCEPT operator as negate MATCH queries do not work.
+        StringBuilder sql = new StringBuilder(
+                buildSearchSQL(query, MATCH_COLUMNS_SECONDARY, false));
+        sql.append(" EXCEPT ");
+        sql.append(primarySql);
+
+        final String secondarySql = sql.toString();
+        Log.d(LOG_TAG, "Search secondary query: " + secondarySql);
+        cursors[1] = database.rawQuery(secondarySql, null);
+
+        return new MergeCursor(cursors);
     }
 
     public Cursor getSuggestions(String query) {
@@ -422,7 +441,7 @@
         }
     }
 
-    public boolean updateFromRemoteProvider(String packageName, String authority) {
+    private boolean updateFromRemoteProvider(String packageName, String authority) {
         if (!addIndexablesFromRemoteProvider(packageName, authority)) {
             return false;
         }
@@ -615,11 +634,13 @@
         }
     }
 
-    private String buildSearchSQL(String query) {
+    private String buildSearchSQL(String query, String[] colums, boolean withOrderBy) {
         StringBuilder sb = new StringBuilder();
-        sb.append(buildSearchSQLForColumn(query, MATCH_COLUMNS));
-        sb.append(" ORDER BY ");
-        sb.append(IndexColumns.DATA_RANK);
+        sb.append(buildSearchSQLForColumn(query, colums));
+        if (withOrderBy) {
+            sb.append(" ORDER BY ");
+            sb.append(IndexColumns.DATA_RANK);
+        }
         return sb.toString();
     }
 
@@ -1215,7 +1236,7 @@
     }
 
     /**
-     * A basic AsynTask for saving a Search query into the database
+     * A basic AsyncTask for saving a Search query into the database
      */
     private class SaveSearchQueryTask extends AsyncTask<String, Void, Long> {
 
diff --git a/src/com/android/settings/search/Ranking.java b/src/com/android/settings/search/Ranking.java
index 8115cb5..0d53d85 100644
--- a/src/com/android/settings/search/Ranking.java
+++ b/src/com/android/settings/search/Ranking.java
@@ -42,6 +42,7 @@
 import com.android.settings.print.PrintSettingsFragment;
 import com.android.settings.users.UserSettings;
 import com.android.settings.wifi.AdvancedWifiSettings;
+import com.android.settings.wifi.SavedAccessPointsWifiSettings;
 import com.android.settings.wifi.WifiSettings;
 
 import java.util.HashMap;
@@ -85,6 +86,7 @@
         // Wi-Fi
         sRankMap.put(WifiSettings.class.getName(), RANK_WIFI);
         sRankMap.put(AdvancedWifiSettings.class.getName(), RANK_WIFI);
+        sRankMap.put(SavedAccessPointsWifiSettings.class.getName(), RANK_WIFI);
 
         // BT
         sRankMap.put(BluetoothSettings.class.getName(), RANK_BT);
diff --git a/src/com/android/settings/search/SearchIndexableResources.java b/src/com/android/settings/search/SearchIndexableResources.java
index e78d9b8..287d78f 100644
--- a/src/com/android/settings/search/SearchIndexableResources.java
+++ b/src/com/android/settings/search/SearchIndexableResources.java
@@ -45,6 +45,7 @@
 import com.android.settings.print.PrintSettingsFragment;
 import com.android.settings.users.UserSettings;
 import com.android.settings.wifi.AdvancedWifiSettings;
+import com.android.settings.wifi.SavedAccessPointsWifiSettings;
 import com.android.settings.wifi.WifiSettings;
 
 import java.util.Collection;
@@ -72,6 +73,13 @@
                         AdvancedWifiSettings.class.getName(),
                         R.drawable.ic_settings_wireless));
 
+        sResMap.put(SavedAccessPointsWifiSettings.class.getName(),
+                new SearchIndexableResource(
+                        Ranking.getRankForClassName(SavedAccessPointsWifiSettings.class.getName()),
+                        R.xml.wifi_display_saved_access_points,
+                        SavedAccessPointsWifiSettings.class.getName(),
+                        R.drawable.ic_settings_wireless));
+
         sResMap.put(BluetoothSettings.class.getName(),
                 new SearchIndexableResource(
                         Ranking.getRankForClassName(BluetoothSettings.class.getName()),
diff --git a/src/com/android/settings/wifi/AccessPoint.java b/src/com/android/settings/wifi/AccessPoint.java
index 0fe5f81..811371a 100644
--- a/src/com/android/settings/wifi/AccessPoint.java
+++ b/src/com/android/settings/wifi/AccessPoint.java
@@ -32,6 +32,7 @@
 import android.util.LruCache;
 import android.view.View;
 import android.widget.ImageView;
+import android.widget.TextView;
 
 import java.util.Map;
 
@@ -59,7 +60,8 @@
      */
     public static final int HIGHER_FREQ_5GHZ = 5900;
 
-    /** Experimental: we should be able to show the user the list of BSSIDs and bands
+    /**
+     * Experimental: we should be able to show the user the list of BSSIDs and bands
      *  for that SSID.
      *  For now this data is used only with Verbose Logging so as to show the band and number
      *  of BSSIDs on which that network is seen.
@@ -79,7 +81,9 @@
 
     private static int[] wifi_signal_attributes = { R.attr.wifi_signal };
 
-    /** These values are matched in string arrays -- changes must be kept in sync */
+    /**
+     * These values are matched in string arrays -- changes must be kept in sync
+     */
     static final int SECURITY_NONE = 0;
     static final int SECURITY_WEP = 1;
     static final int SECURITY_PSK = 2;
@@ -97,6 +101,7 @@
     int security;
     int networkId = -1;
     boolean wpsAvailable = false;
+    boolean showSummary = true;
 
     PskType pskType = PskType.UNKNOWN;
 
@@ -246,6 +251,11 @@
     protected void onBindView(View view) {
         super.onBindView(view);
         updateIcon(getLevel(), getContext());
+
+        final TextView summaryView = (TextView) view.findViewById(
+                com.android.internal.R.id.summary);
+        summaryView.setVisibility(showSummary ? View.VISIBLE : View.GONE);
+
         notifyChanged();
     }
 
@@ -396,7 +406,18 @@
         return "\"" + string + "\"";
     }
 
-    /** visibility status of the WifiConfiguration
+    /**
+     * Shows or Hides the Summary of an AccessPoint.
+     *
+     * @param showSummary true will show the summary, false will hide the summary
+     */
+    public void setShowSummary(boolean showSummary){
+        this.showSummary = showSummary;
+    }
+
+    /**
+     * Returns the visibility status of the WifiConfiguration.
+     *
      * @return autojoin debugging information
      * TODO: use a string formatter
      * ["rssi 5Ghz", "num results on 5GHz" / "rssi 5Ghz", "num results on 5GHz"]
@@ -430,11 +451,15 @@
             int rssi24 = WifiConfiguration.INVALID_RSSI;
             int num5 = 0;
             int num24 = 0;
+            int numBlackListed = 0;
             Map<String, ScanResult> list = mScanResultCache.snapshot();
             for (ScanResult result : list.values()) {
                 if (result.seen == 0)
                     continue;
 
+                if (result.status != ScanResult.ENABLED)
+                    numBlackListed++;
+
                 if (result.frequency > LOWER_FREQ_5GHZ
                         && result.frequency < HIGHER_FREQ_5GHZ) {
                     //strictly speaking: [4915, 5825]
@@ -474,6 +499,8 @@
                 visibility.append(",");
                 visibility.append(Integer.toString(num5));
             }
+            if (numBlackListed > 0)
+                visibility.append("!");
             visibility.append("]");
         } else {
             if (mRssi != Integer.MAX_VALUE) {
@@ -489,7 +516,9 @@
         return visibility.toString();
     }
 
-    /** Updates the title and summary; may indirectly call notifyChanged()  */
+    /**
+     * Updates the title and summary; may indirectly call notifyChanged().
+     */
     private void refresh() {
         setTitle(ssid);
 
diff --git a/src/com/android/settings/wifi/AdvancedWifiSettings.java b/src/com/android/settings/wifi/AdvancedWifiSettings.java
index aa4c185..b7316d0 100644
--- a/src/com/android/settings/wifi/AdvancedWifiSettings.java
+++ b/src/com/android/settings/wifi/AdvancedWifiSettings.java
@@ -54,6 +54,7 @@
     private static final String KEY_INSTALL_CREDENTIALS = "install_credentials";
     private static final String KEY_WIFI_DIRECT = "wifi_direct";
     private static final String KEY_WPS_PUSH = "wps_push_button";
+    private static final String KEY_WPS_PIN = "wps_pin_entry";
     private static final String KEY_SUSPEND_OPTIMIZATIONS = "suspend_optimizations";
 
     private WifiManager mWifiManager;
@@ -147,6 +148,16 @@
                 }
         });
 
+        // WpsDialog: Create the dialog like WifiSettings does.
+        Preference wpsPinPref = findPreference(KEY_WPS_PIN);
+        wpsPinPref.setOnPreferenceClickListener(new OnPreferenceClickListener(){
+                public boolean onPreferenceClick(Preference arg0) {
+                    WpsDialog wpsDialog = new WpsDialog(getActivity(), WpsInfo.DISPLAY);
+                    wpsDialog.show();
+                    return true;
+                }
+        });
+
         CheckBoxPreference suspendOptimizations =
             (CheckBoxPreference) findPreference(KEY_SUSPEND_OPTIMIZATIONS);
         suspendOptimizations.setChecked(Global.getInt(getContentResolver(),
@@ -275,11 +286,13 @@
         String macAddress = wifiInfo == null ? null : wifiInfo.getMacAddress();
         wifiMacAddressPref.setSummary(!TextUtils.isEmpty(macAddress) ? macAddress
                 : getActivity().getString(R.string.status_unavailable));
+        wifiMacAddressPref.setSelectable(false);
 
         Preference wifiIpAddressPref = findPreference(KEY_CURRENT_IP_ADDRESS);
         String ipAddress = Utils.getWifiIpAddresses(getActivity());
         wifiIpAddressPref.setSummary(ipAddress == null ?
                 getActivity().getString(R.string.status_unavailable) : ipAddress);
+        wifiIpAddressPref.setSelectable(false);
     }
 
 }
diff --git a/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java b/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java
new file mode 100644
index 0000000..6e82c66
--- /dev/null
+++ b/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.wifi;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.res.Resources;
+import android.net.wifi.ScanResult;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiManager;
+import android.os.Bundle;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceClickListener;
+import android.preference.PreferenceScreen;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.search.Indexable;
+import com.android.settings.search.SearchIndexableRaw;
+import android.util.Log;
+
+import com.android.settings.R;
+import com.android.settings.SettingsPreferenceFragment;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * UI to manage saved networks/access points.
+ */
+public class SavedAccessPointsWifiSettings extends SettingsPreferenceFragment
+        implements DialogInterface.OnClickListener, Indexable {
+    private static final String TAG = "SavedAccessPointsWifiSettings";
+
+    private WifiDialog mDialog;
+    private WifiManager mWifiManager;
+    private AccessPoint mDlgAccessPoint;
+    private Bundle mAccessPointSavedState;
+    private AccessPoint mSelectedAccessPoint;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        addPreferencesFromResource(R.xml.wifi_display_saved_access_points);
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        initPreferences();
+    }
+
+    @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+        mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
+    }
+
+    private void initPreferences() {
+        PreferenceScreen preferenceScreen = getPreferenceScreen();
+        final Context context = getActivity();
+
+        mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+        final List<AccessPoint> accessPoints = constructSavedAccessPoints(context, mWifiManager);
+
+        preferenceScreen.removeAll();
+
+        final int accessPointsSize = accessPoints.size();
+        for (int i = 0; i < accessPointsSize; ++i){
+            preferenceScreen.addPreference(accessPoints.get(i));
+        }
+
+        if(getPreferenceScreen().getPreferenceCount() < 1) {
+            Log.w(TAG, "Saved networks activity loaded, but there are no saved networks!");
+        }
+    }
+
+    private static List<AccessPoint> constructSavedAccessPoints(Context context,
+            WifiManager wifiManager){
+        List<AccessPoint> accessPoints = new ArrayList<AccessPoint>();
+        Map<String, List<ScanResult>> resultsMap = new HashMap<String, List<ScanResult>>();
+
+        final List<WifiConfiguration> configs = wifiManager.getConfiguredNetworks();
+        final List<ScanResult> scanResults = wifiManager.getScanResults();
+
+        if (configs != null) {
+            //Construct a Map for quick searching of a wifi network via ssid.
+            final int scanResultsSize = scanResults.size();
+            for (int i = 0; i < scanResultsSize; ++i){
+                final ScanResult result = scanResults.get(i);
+                List<ScanResult> res = resultsMap.get(result.SSID);
+
+                if(res == null){
+                    res = new ArrayList<ScanResult>();
+                    resultsMap.put(result.SSID, res);
+                }
+
+                res.add(result);
+            }
+
+            final int configsSize = configs.size();
+            for (int i = 0; i < configsSize; ++i){
+                AccessPoint accessPoint = new AccessPoint(context, configs.get(i));
+                final List<ScanResult> results = resultsMap.get(accessPoint.ssid);
+
+                accessPoint.setShowSummary(false);
+                if(results != null){
+                    final int resultsSize = results.size();
+                    for (int j = 0; j < resultsSize; ++j){
+                        accessPoint.update(results.get(j));
+                    }
+                }
+
+                accessPoints.add(accessPoint);
+            }
+        }
+
+        return accessPoints;
+    }
+
+    private void showDialog(AccessPoint accessPoint, boolean edit) {
+        if (mDialog != null) {
+            removeDialog(WifiSettings.WIFI_DIALOG_ID);
+            mDialog = null;
+        }
+
+        // Save the access point and edit mode
+        mDlgAccessPoint = accessPoint;
+
+        showDialog(WifiSettings.WIFI_DIALOG_ID);
+    }
+
+    @Override
+    public Dialog onCreateDialog(int dialogId) {
+        switch (dialogId) {
+            case WifiSettings.WIFI_DIALOG_ID:
+                mSelectedAccessPoint = mDlgAccessPoint;
+                mDialog = new WifiDialog(getActivity(), this, mDlgAccessPoint, false);
+                return mDialog;
+
+        }
+        return super.onCreateDialog(dialogId);
+    }
+
+    @Override
+    public void onClick(DialogInterface dialogInterface, int button) {
+        if (button == WifiDialog.BUTTON_FORGET && mSelectedAccessPoint != null) {
+            mWifiManager.forget(mSelectedAccessPoint.networkId, null);
+            getPreferenceScreen().removePreference(mSelectedAccessPoint);
+            mSelectedAccessPoint = null;
+        }
+    }
+
+    @Override
+    public boolean onPreferenceTreeClick(PreferenceScreen screen, Preference preference) {
+        if (preference instanceof AccessPoint) {
+            showDialog((AccessPoint) preference, false);
+            return true;
+        } else{
+            return super.onPreferenceTreeClick(screen, preference);
+        }
+    }
+
+    /**
+     * For search.
+     */
+    public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+        new BaseSearchIndexProvider() {
+            @Override
+            public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) {
+                final List<SearchIndexableRaw> result = new ArrayList<SearchIndexableRaw>();
+                final Resources res = context.getResources();
+                final String title = res.getString(R.string.wifi_saved_access_points_titlebar);
+
+                // Add fragment title
+                SearchIndexableRaw data = new SearchIndexableRaw(context);
+                data.title = title;
+                data.screenTitle = title;
+                data.enabled = enabled;
+                result.add(data);
+
+                // Add available Wi-Fi access points
+                WifiManager wifiManager =
+                        (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+                final List<AccessPoint> accessPoints =
+                        constructSavedAccessPoints(context, wifiManager);
+
+                final int accessPointsSize = accessPoints.size();
+                for (int i = 0; i < accessPointsSize; ++i){
+                    data = new SearchIndexableRaw(context);
+                    data.title = accessPoints.get(i).getTitle().toString();
+                    data.screenTitle = title;
+                    data.enabled = enabled;
+                    result.add(data);
+                }
+
+                return result;
+            }
+        };
+}
diff --git a/src/com/android/settings/wifi/WifiPickerActivity.java b/src/com/android/settings/wifi/WifiPickerActivity.java
index eec9963..b306466 100644
--- a/src/com/android/settings/wifi/WifiPickerActivity.java
+++ b/src/com/android/settings/wifi/WifiPickerActivity.java
@@ -39,6 +39,7 @@
     protected boolean isValidFragment(String fragmentName) {
         if (WifiSettings.class.getName().equals(fragmentName)
                 || WifiP2pSettings.class.getName().equals(fragmentName)
+                || SavedAccessPointsWifiSettings.class.getName().equals(fragmentName)
                 || AdvancedWifiSettings.class.getName().equals(fragmentName)) return true;
         return false;
     }
@@ -46,4 +47,4 @@
     /* package */ Class<? extends PreferenceFragment> getWifiSettingsClass() {
         return WifiSettings.class;
     }
-}
\ No newline at end of file
+}
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index a7f291d..0cb25c3 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -84,7 +84,7 @@
     private static final String TAG = "WifiSettings";
     /* package */ static final int MENU_ID_WPS_PBC = Menu.FIRST;
     private static final int MENU_ID_WPS_PIN = Menu.FIRST + 1;
-    private static final int MENU_ID_P2P = Menu.FIRST + 2;
+    private static final int MENU_ID_SAVED_NETWORK = Menu.FIRST + 2;
     /* package */ static final int MENU_ID_ADD_NETWORK = Menu.FIRST + 3;
     private static final int MENU_ID_ADVANCED = Menu.FIRST + 4;
     private static final int MENU_ID_SCAN = Menu.FIRST + 5;
@@ -93,7 +93,7 @@
     private static final int MENU_ID_MODIFY = Menu.FIRST + 8;
     private static final int MENU_ID_WRITE_NFC = Menu.FIRST + 9;
 
-    private static final int WIFI_DIALOG_ID = 1;
+    public static final int WIFI_DIALOG_ID = 1;
     /* package */ static final int WPS_PBC_DIALOG_ID = 2;
     private static final int WPS_PIN_DIALOG_ID = 3;
     private static final int WRITE_NFC_DIALOG_ID = 6;
@@ -105,6 +105,8 @@
     private static final String SAVE_DIALOG_EDIT_MODE = "edit_mode";
     private static final String SAVE_DIALOG_ACCESS_POINT_STATE = "wifi_ap_state";
 
+    private static boolean savedNetworksExist;
+
     private final IntentFilter mFilter;
     private final BroadcastReceiver mReceiver;
     private final Scanner mScanner;
@@ -320,15 +322,16 @@
                 .setIcon(ta.getDrawable(0))
                 .setEnabled(wifiIsEnabled)
                 .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
-        menu.add(Menu.NONE, MENU_ID_SCAN, 0, R.string.wifi_menu_scan)
-                //.setIcon(R.drawable.ic_menu_scan_network)
-                .setEnabled(wifiIsEnabled)
-                .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
-        menu.add(Menu.NONE, MENU_ID_WPS_PIN, 0, R.string.wifi_menu_wps_pin)
-                .setEnabled(wifiIsEnabled)
-                .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
+        if (savedNetworksExist){
+            menu.add(Menu.NONE, MENU_ID_SAVED_NETWORK, 0, R.string.wifi_saved_access_points_label)
+                    .setIcon(ta.getDrawable(0))
+                    .setEnabled(wifiIsEnabled)
+                    .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
+        }
+        menu.add(Menu.NONE, MENU_ID_SCAN, 0, R.string.menu_stats_refresh)
+               .setEnabled(wifiIsEnabled)
+               .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
         menu.add(Menu.NONE, MENU_ID_ADVANCED, 0, R.string.wifi_menu_advanced)
-                //.setIcon(android.R.drawable.ic_menu_manage)
                 .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
         ta.recycle();
     }
@@ -357,6 +360,7 @@
             case MENU_ID_WPS_PBC:
                 showDialog(WPS_PBC_DIALOG_ID);
                 return true;
+                /*
             case MENU_ID_P2P:
                 if (getActivity() instanceof SettingsActivity) {
                     ((SettingsActivity) getActivity()).startPreferencePanel(
@@ -369,6 +373,7 @@
                             R.string.wifi_p2p_settings_title, -1, null);
                 }
                 return true;
+                */
             case MENU_ID_WPS_PIN:
                 showDialog(WPS_PIN_DIALOG_ID);
                 return true;
@@ -382,16 +387,26 @@
                     onAddNetworkPressed();
                 }
                 return true;
+            case MENU_ID_SAVED_NETWORK:
+                if (getActivity() instanceof SettingsActivity) {
+                    ((SettingsActivity) getActivity()).startPreferencePanel(
+                            SavedAccessPointsWifiSettings.class.getCanonicalName(), null,
+                            R.string.wifi_saved_access_points_titlebar, null, this, 0);
+                } else {
+                    startFragment(this, SavedAccessPointsWifiSettings.class.getCanonicalName(),
+                            R.string.wifi_saved_access_points_titlebar,
+                            -1 /* Do not request a result */, null);
+                }
+                return true;
             case MENU_ID_ADVANCED:
                 if (getActivity() instanceof SettingsActivity) {
                     ((SettingsActivity) getActivity()).startPreferencePanel(
-                            AdvancedWifiSettings.class.getCanonicalName(),
-                            null,
-                            R.string.wifi_advanced_titlebar, null,
-                            this, 0);
+                            AdvancedWifiSettings.class.getCanonicalName(), null,
+                            R.string.wifi_advanced_titlebar, null, this, 0);
                 } else {
                     startFragment(this, AdvancedWifiSettings.class.getCanonicalName(),
-                            R.string.wifi_advanced_titlebar, -1, null);
+                            R.string.wifi_advanced_titlebar, -1 /* Do not request a results */,
+                            null);
                 }
                 return true;
         }
@@ -468,6 +483,10 @@
             if (mSelectedAccessPoint.security == AccessPoint.SECURITY_NONE &&
                     mSelectedAccessPoint.networkId == INVALID_NETWORK_ID) {
                 mSelectedAccessPoint.generateOpenNetworkConfig();
+                if (!savedNetworksExist){
+                    savedNetworksExist = true;
+                    getActivity().invalidateOptionsMenu();
+                }
                 mWifiManager.connect(mSelectedAccessPoint.getConfig(), mConnectListener);
             } else {
                 showDialog(mSelectedAccessPoint, false);
@@ -606,6 +625,7 @@
 
         final List<WifiConfiguration> configs = wifiManager.getConfiguredNetworks();
         if (configs != null) {
+            savedNetworksExist = (configs.size() > 0);
             for (WifiConfiguration config : configs) {
                 AccessPoint accessPoint = new AccessPoint(context, config);
                 if (lastInfo != null && lastState != null) {