Settings - update for new UI (no more Drawer)

- follow the UX spec by no more using a Drawer
- the Dashboard is now a Fragment that contains the list of Headers
- the search results are also put into a Fragment that is replacing
the initial one (Dashboard or other) when expanding the SearchView
- use a SearchView for query input
- when tapping on a Header or a Search Result, re-launch Settings as
an Activity so that we are benefiting from the Activity stack for
UP affordance and BACK button
- manage UP affordance to show it only when needed
- move some Actions to the Menu in the ActionBar for allowing space
to the Search action and removing some clutter
- fix an issue with the Index and WiFiEnabler and their cached Context
that was not updated when there was a Configuration change
- simplify the SettingsActivity code by extracting some inner classes

Change-Id: I50b5f77bb44a7fade1886114dbbc820609a5e63d
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 9c9b237..00c959a 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -80,7 +80,6 @@
         <!-- Settings -->
 
         <activity android:name="Settings"
-                  android:uiOptions="splitActionBarWhenNarrow"
                 android:taskAffinity="com.android.settings"
                 android:label="@string/settings_label_launcher"
                 android:launchMode="singleTask">
diff --git a/res/layout/dashboard.xml b/res/layout/dashboard.xml
index 87bd973..8a29289 100644
--- a/res/layout/dashboard.xml
+++ b/res/layout/dashboard.xml
@@ -24,33 +24,10 @@
                   android:layout_gravity="center"
                   android:orientation="vertical">
 
-        <TextView android:id="@+id/dash_text"
+        <ListView android:id="@id/android:list"
                   android:layout_width="match_parent"
-                  android:layout_height="wrap_content"
-                  android:layout_gravity="center"
-                  android:text="@string/dashboard_wip"
-                  android:padding="16dp"
-                  android:layout_weight="0"
-                  android:background="#ffcccccc"
-                  android:textSize="16sp"
-                />
-
-        <EditText android:id="@+id/edittext_query"
-                  android:layout_width="match_parent"
-                  android:layout_height="wrap_content"
-                  android:hint="@string/query_hint_text"
-                  android:layout_weight="0"/>
-
-        <FrameLayout android:id="@+id/dashboard"
-                     android:layout_width="match_parent"
-                     android:layout_height="0dip"
-                     android:layout_weight="1">
-
-            <ListView android:id="@+id/list_results"
-                          android:layout_width="match_parent"
-                          android:layout_height="match_parent"/>
-
-        </FrameLayout>
+                  android:layout_height="match_parent"
+                  android:background="@color/background_drawer" />
 
     </LinearLayout>
 
diff --git a/res/layout/search_result.xml b/res/layout/search_result_item.xml
similarity index 100%
rename from res/layout/search_result.xml
rename to res/layout/search_result_item.xml
diff --git a/res/layout/search_results.xml b/res/layout/search_results.xml
new file mode 100644
index 0000000..a833404
--- /dev/null
+++ b/res/layout/search_results.xml
@@ -0,0 +1,33 @@
+<?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.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/dashboard"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <LinearLayout android:layout_width="match_parent"
+                  android:layout_height="match_parent"
+                  android:layout_gravity="center"
+                  android:orientation="vertical">
+
+        <ListView android:id="@+id/list_results"
+                      android:layout_width="match_parent"
+                      android:layout_height="match_parent"/>
+
+    </LinearLayout>
+
+</FrameLayout>
diff --git a/res/layout/settings_main.xml b/res/layout/settings_main.xml
index 8b98794..db732dc 100644
--- a/res/layout/settings_main.xml
+++ b/res/layout/settings_main.xml
@@ -17,65 +17,58 @@
 */
 -->
 
-<android.support.v4.widget.DrawerLayout
-        xmlns:android="http://schemas.android.com/apk/res/android"
-        android:id="@+id/drawer_layout"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent">
-
-    <LinearLayout
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
               android:orientation="vertical"
               android:layout_height="match_parent"
               android:layout_width="match_parent">
 
-        <android.preference.PreferenceFrameLayout android:id="@+id/prefs"
-            android:layout_width="match_parent"
+    <LinearLayout
+            android:orientation="vertical"
             android:layout_height="match_parent"
-            android:layout_weight="1"
-        />
+            android:layout_width="match_parent">
 
-        <RelativeLayout android:id="@+id/button_bar"
-                        android:layout_height="wrap_content"
-                        android:layout_width="match_parent"
-                        android:layout_weight="0"
-                        android:visibility="gone">
+        <android.preference.PreferenceFrameLayout
+                android:id="@+id/prefs"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_weight="1"
+                />
+    </LinearLayout>
 
-            <Button android:id="@+id/back_button"
+    <RelativeLayout android:id="@+id/button_bar"
+                    android:layout_height="wrap_content"
+                    android:layout_width="match_parent"
+                    android:layout_weight="0"
+                    android:visibility="gone">
+
+        <Button android:id="@+id/back_button"
+                android:layout_width="150dip"
+                android:layout_height="wrap_content"
+                android:layout_margin="5dip"
+                android:layout_alignParentStart="true"
+                android:text="@*android:string/back_button_label"
+                />
+        <LinearLayout
+                android:orientation="horizontal"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_alignParentEnd="true">
+
+            <Button android:id="@+id/skip_button"
                     android:layout_width="150dip"
                     android:layout_height="wrap_content"
                     android:layout_margin="5dip"
-                    android:layout_alignParentStart="true"
-                    android:text="@*android:string/back_button_label"
+                    android:text="@*android:string/skip_button_label"
+                    android:visibility="gone"
                     />
-            <LinearLayout
-                    android:orientation="horizontal"
-                    android:layout_width="wrap_content"
+
+            <Button android:id="@+id/next_button"
+                    android:layout_width="150dip"
                     android:layout_height="wrap_content"
-                    android:layout_alignParentEnd="true">
+                    android:layout_margin="5dip"
+                    android:text="@*android:string/next_button_label"
+                    />
+        </LinearLayout>
+    </RelativeLayout>
 
-                <Button android:id="@+id/skip_button"
-                        android:layout_width="150dip"
-                        android:layout_height="wrap_content"
-                        android:layout_margin="5dip"
-                        android:text="@*android:string/skip_button_label"
-                        android:visibility="gone"
-                        />
-
-                <Button android:id="@+id/next_button"
-                        android:layout_width="150dip"
-                        android:layout_height="wrap_content"
-                        android:layout_margin="5dip"
-                        android:text="@*android:string/next_button_label"
-                        />
-            </LinearLayout>
-        </RelativeLayout>
-
-    </LinearLayout>
-
-    <ListView android:id="@+id/headers_drawer"
-              android:layout_width="300dp"
-              android:layout_height="match_parent"
-              android:layout_gravity="start"
-              android:background="@color/background_drawer"/>
-
-</android.support.v4.widget.DrawerLayout>
+</LinearLayout>
diff --git a/res/menu/options_menu.xml b/res/menu/options_menu.xml
new file mode 100644
index 0000000..59e9cad
--- /dev/null
+++ b/res/menu/options_menu.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:id="@+id/search"
+        android:title="@string/search_menu"
+        android:icon="@*android:drawable/ic_search"
+        android:showAsAction="collapseActionView|ifRoom"
+        android:actionViewClass="android.widget.SearchView" />
+</menu>
\ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 1d6c751..62d5ca6 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -4988,20 +4988,17 @@
     <string name="enable_nfc">NFC is not enabled and is required for NFC Unlock. Please turn on NFC.</string>
     <string name="ok">NFC Settings</string>
 
-    <!--Drawer strings-->
-    <!-- Text to describe the "open drawer" action for accessibility purpose [CHAR LIMIT=50] -->
-    <string name="drawer_open">Open navigation drawer</string>
-    <!-- Text to describe the "close drawer" action for accessibility purpose [CHAR LIMIT=50] -->
-    <string name="drawer_close">Close navigation drawer</string>
-
     <!--Dashboard strings-->
-    <!-- Text to describe the dashboard entry into the Drawer [CHAR LIMIT=16] -->
-    <string name="dashboard_title">Overview</string>
-    <string name="dashboard_wip" translatable="false">Overview and Search are work in progress and Confidential\n\nDrag the Drawer on the left to see the settings list</string>
+    <!-- Text to describe the dashboard fragment title [CHAR LIMIT=16] -->
+    <string name="dashboard_title">Settings</string>
 
     <!-- Search strings -->
+    <!-- Text to describe the search results fragment title [CHAR LIMIT=16] -->
+    <string name="search_results_title">Settings</string>
     <!-- Text used as a search hint into the search box -->
-    <string name="query_hint_text">What are you looking for?</string>
+    <string name="search_menu">Search</string>
+    <!-- Text used as a search hint into the search box -->
+    <string name="query_hint_text">Search settings</string>
 
     <!--Search Keywords-->
     <string name="keywords_wifi">wifi wi-fi network connection</string>
diff --git a/res/xml/settings_headers.xml b/res/xml/settings_headers.xml
index c4b5eac..73665cd 100644
--- a/res/xml/settings_headers.xml
+++ b/res/xml/settings_headers.xml
@@ -17,14 +17,6 @@
 <preference-headers
         xmlns:android="http://schemas.android.com/apk/res/android">
 
-
-    <!-- Dashboard -->
-    <!--TODO: android:icon="@drawable/ic_settings_dashboard"-->
-    <header
-        android:id="@+id/dashboard"
-        android:fragment="com.android.settings.dashboard.DashboardSummary"
-        android:title="@string/dashboard_title" />
-
     <!-- WIRELESS and NETWORKS -->
     <header android:id="@+id/wireless_section"
             android:title="@string/header_category_wireless_networks" />
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index 0e6128c..c2b01cf 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -24,11 +24,10 @@
 import android.app.Fragment;
 import android.app.FragmentManager;
 import android.app.FragmentTransaction;
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.DialogFragment;
+import android.app.SearchManager;
 import android.app.admin.DevicePolicyManager;
 import android.content.BroadcastReceiver;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -38,17 +37,13 @@
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
 import android.content.res.Configuration;
-import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
-import android.graphics.drawable.Drawable;
 import android.nfc.NfcAdapter;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.INetworkManagementService;
 import android.os.Message;
-import android.os.Parcel;
-import android.os.Parcelable;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
@@ -57,28 +52,20 @@
 import android.preference.PreferenceFragment;
 import android.preference.PreferenceManager;
 import android.preference.PreferenceScreen;
-import android.support.v4.app.ActionBarDrawerToggle;
-import android.support.v4.widget.DrawerLayout;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.TypedValue;
 import android.util.Xml;
-import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
 import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-import android.widget.AbsListView;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
 import android.widget.Button;
-import android.widget.ImageButton;
-import android.widget.ImageView;
 import android.widget.ListView;
-import android.widget.Switch;
-import android.widget.TextView;
 
+import android.widget.SearchView;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.XmlUtils;
 import com.android.settings.accessibility.AccessibilitySettings;
@@ -86,11 +73,15 @@
 import com.android.settings.accounts.AccountSyncSettings;
 import com.android.settings.accounts.AuthenticatorHelper;
 import com.android.settings.accounts.ManageAccountsSettings;
+import com.android.settings.applications.InstalledAppDetails;
 import com.android.settings.applications.ManageApplications;
 import com.android.settings.applications.ProcessStatsUi;
-import com.android.settings.bluetooth.BluetoothEnabler;
 import com.android.settings.bluetooth.BluetoothSettings;
 import com.android.settings.dashboard.DashboardSummary;
+import com.android.settings.dashboard.Header;
+import com.android.settings.dashboard.HeaderAdapter;
+import com.android.settings.dashboard.NoHomeDialogFragment;
+import com.android.settings.dashboard.SearchResultsSummary;
 import com.android.settings.deviceinfo.Memory;
 import com.android.settings.deviceinfo.UsbSettings;
 import com.android.settings.fuelgauge.PowerUsageSummary;
@@ -109,7 +100,6 @@
 import com.android.settings.vpn2.VpnSettings;
 import com.android.settings.wfd.WifiDisplaySettings;
 import com.android.settings.wifi.AdvancedWifiSettings;
-import com.android.settings.wifi.WifiEnabler;
 import com.android.settings.wifi.WifiSettings;
 import com.android.settings.wifi.p2p.WifiP2pSettings;
 import org.xmlpull.v1.XmlPullParser;
@@ -122,16 +112,22 @@
 import java.util.HashMap;
 import java.util.List;
 
+import static com.android.settings.dashboard.Header.HEADER_ID_UNDEFINED;
+
 public class SettingsActivity extends Activity
         implements PreferenceManager.OnPreferenceTreeClickListener,
         PreferenceFragment.OnPreferenceStartFragmentCallback,
-        ButtonBarHandler, OnAccountsUpdateListener, FragmentManager.OnBackStackChangedListener {
+        ButtonBarHandler, OnAccountsUpdateListener, FragmentManager.OnBackStackChangedListener,
+        SearchView.OnQueryTextListener, SearchView.OnCloseListener,
+        MenuItem.OnActionExpandListener {
 
     private static final String LOG_TAG = "Settings";
 
     // Constants for state save/restore
-    private static final String SAVE_KEY_HEADERS_TAG = ":settings:headers";
-    private static final String SAVE_KEY_CURRENT_HEADER_TAG = ":settings:cur_header";
+    private static final String SAVE_KEY_HEADERS = ":settings:headers";
+    private static final String SAVE_KEY_CURRENT_HEADER = ":settings:cur_header";
+    private static final String SAVE_KEY_SEARCH_MENU_EXPANDED = ":settings:search_menu_expanded";
+    private static final String SAVE_KEY_SEARCH_QUERY = ":settings:search_query";
 
     /**
      * When starting this activity, the invoking Intent can contain this extra
@@ -180,7 +176,7 @@
      * this extra can also be specify to supply the title to be shown for
      * that fragment.
      */
-    protected static final String EXTRA_SHOW_FRAGMENT_TITLE = ":settings:show_fragment_title";
+    public static final String EXTRA_SHOW_FRAGMENT_TITLE = ":settings:show_fragment_title";
 
     private static final String META_DATA_KEY_HEADER_ID =
         "com.android.settings.TOP_LEVEL_HEADER_ID";
@@ -193,13 +189,10 @@
     private static boolean sShowNoHomeNotice = false;
 
     private String mFragmentClass;
-    private int mTopLevelHeaderId;
-    private Header mFirstHeader;
     private Header mSelectedHeader;
     private Header mCurrentHeader;
 
     private CharSequence mInitialTitle;
-    private Header mInitialHeader;
 
     // Show only these settings for restricted users
     private int[] SETTINGS_FOR_RESTRICTED = {
@@ -279,22 +272,19 @@
             TrustedCredentialsSettings.class.getName(),
             PaymentSettings.class.getName(),
             KeyboardLayoutPickerFragment.class.getName(),
-            DashboardSummary.class.getName(),
-            ZenModeSettings.class.getName()
+            ZenModeSettings.class.getName(),
+            NotificationSettings.class.getName(),
+            ChooseLockPassword.ChooseLockPasswordFragment.class.getName(),
+            ChooseLockPattern.ChooseLockPatternFragment.class.getName(),
+            InstalledAppDetails.class.getName()
     };
 
     private SharedPreferences mDevelopmentPreferences;
     private SharedPreferences.OnSharedPreferenceChangeListener mDevelopmentPreferencesListener;
 
-    // TODO: Update Call Settings based on airplane mode state.
-
-    protected HashMap<Integer, Integer> mHeaderIndexMap = new HashMap<Integer, Integer>();
-
     private AuthenticatorHelper mAuthenticatorHelper;
     private boolean mListeningToAccountUpdates;
 
-    private Button mNextButton;
-
     private boolean mBatteryPresent = true;
     private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {
 
@@ -312,14 +302,21 @@
         }
     };
 
+    private Button mNextButton;
+    private ActionBar mActionBar;
+
+    private SearchView mSearchView;
+    private MenuItem mSearchMenuItem;
+    private boolean mSearchMenuItemExpanded = false;
+    private boolean mIsShowingSearchResults = false;
+    private SearchResultsSummary mSearchResultsFragment;
+    private String mSearchQuery;
+
+    // Headers
+    protected HashMap<Integer, Integer> mHeaderIndexMap = new HashMap<Integer, Integer>();
     private final ArrayList<Header> mHeaders = new ArrayList<Header>();
     private HeaderAdapter mHeaderAdapter;
 
-    private DrawerLayout mDrawerLayout;
-    private ListView mDrawer;
-    private ActionBarDrawerToggle mDrawerToggle;
-    private ActionBar mActionBar;
-
     private static final int MSG_BUILD_HEADERS = 1;
     private Handler mHandler = new Handler() {
         @Override
@@ -329,17 +326,13 @@
                     mHeaders.clear();
                     onBuildHeaders(mHeaders);
                     mHeaderAdapter.notifyDataSetChanged();
-                    if (mCurrentHeader != null) {
-                        Header mappedHeader = findBestMatchingHeader(mCurrentHeader, mHeaders);
-                        if (mappedHeader != null) {
-                            setSelectedHeader(mappedHeader);
-                        }
-                    }
                 } break;
             }
         }
     };
 
+    private boolean mNeedToRevertToInitialFragment = false;
+
     @Override
     public boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref) {
         // Override the fragment title for Wallpaper settings
@@ -364,87 +357,6 @@
         return false;
     }
 
-    private class DrawerListener implements DrawerLayout.DrawerListener {
-        @Override
-        public void onDrawerOpened(View drawerView) {
-            mDrawerToggle.onDrawerOpened(drawerView);
-        }
-
-        @Override
-        public void onDrawerClosed(View drawerView) {
-            mDrawerToggle.onDrawerClosed(drawerView);
-            // Cannot process clicks when the App is finishing
-            if (isFinishing() || mSelectedHeader == null) {
-                return;
-            }
-            switchToHeader(mSelectedHeader, false, false);
-            mSelectedHeader = null;
-        }
-
-        @Override
-        public void onDrawerSlide(View drawerView, float slideOffset) {
-            mDrawerToggle.onDrawerSlide(drawerView, slideOffset);
-        }
-
-        @Override
-        public void onDrawerStateChanged(int newState) {
-            mDrawerToggle.onDrawerStateChanged(newState);
-        }
-    }
-
-    private class DrawerItemClickListener implements ListView.OnItemClickListener {
-        @Override
-        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
-            mDrawerLayout.closeDrawer(mDrawer);
-            onListItemClick((ListView)parent, view, position, id);
-        }
-    }
-
-    private Header findBestMatchingHeader(Header current, ArrayList<Header> from) {
-        ArrayList<Header> matches = new ArrayList<Header>();
-        for (int j=0; j<from.size(); j++) {
-            Header oh = from.get(j);
-            if (current == oh || (current.id != HEADER_ID_UNDEFINED && current.id == oh.id)) {
-                // Must be this one.
-                matches.clear();
-                matches.add(oh);
-                break;
-            }
-            if (current.fragment != null) {
-                if (current.fragment.equals(oh.fragment)) {
-                    matches.add(oh);
-                }
-            } else if (current.intent != null) {
-                if (current.intent.equals(oh.intent)) {
-                    matches.add(oh);
-                }
-            } else if (current.title != null) {
-                if (current.title.equals(oh.title)) {
-                    matches.add(oh);
-                }
-            }
-        }
-        final int NM = matches.size();
-        if (NM == 1) {
-            return matches.get(0);
-        } else if (NM > 1) {
-            for (int j=0; j<NM; j++) {
-                Header oh = matches.get(j);
-                if (current.fragmentArguments != null &&
-                        current.fragmentArguments.equals(oh.fragmentArguments)) {
-                    return oh;
-                }
-                if (current.extras != null && current.extras.equals(oh.extras)) {
-                    return oh;
-                }
-                if (current.title != null && current.title.equals(oh.title)) {
-                    return oh;
-                }
-            }
-        }
-        return null;
-    }
-
     private void invalidateHeaders() {
         if (!mHandler.hasMessages(MSG_BUILD_HEADERS)) {
             mHandler.sendEmptyMessage(MSG_BUILD_HEADERS);
@@ -452,30 +364,48 @@
     }
 
     @Override
-    protected void onPostCreate(Bundle savedInstanceState) {
-        super.onPostCreate(savedInstanceState);
-
-        // Sync the toggle state after onRestoreInstanceState has occurred.
-        mDrawerToggle.syncState();
-    }
-
-    @Override
     public void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
-        mDrawerToggle.onConfigurationChanged(newConfig);
         Index.getInstance(this).update();
     }
 
     @Override
-    public boolean onOptionsItemSelected(MenuItem item) {
-        if (mDrawerToggle.onOptionsItemSelected(item)) {
-            return true;
+    protected void onStart() {
+        super.onStart();
+
+        if (mNeedToRevertToInitialFragment) {
+            revertToInitialFragment();
         }
-        return super.onOptionsItemSelected(item);
     }
 
     @Override
-    protected void onCreate(Bundle savedInstanceState) {
+    public boolean onCreateOptionsMenu(Menu menu) {
+        MenuInflater inflater = getMenuInflater();
+        inflater.inflate(R.menu.options_menu, menu);
+
+        // Cache the search query (can be overriden by the OnQueryTextListener)
+        final String query = mSearchQuery;
+
+        // Associate searchable configuration with the SearchView
+        SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
+        mSearchView = (SearchView) menu.findItem(R.id.search).getActionView();
+
+        mSearchView.setOnQueryTextListener(this);
+        mSearchView.setOnCloseListener(this);
+
+        mSearchMenuItem = menu.findItem(R.id.search);
+        mSearchMenuItem.setOnActionExpandListener(this);
+
+        if (mSearchMenuItemExpanded) {
+            mSearchMenuItem.expandActionView();
+        }
+        mSearchView.setQuery(query, true /* submit */);
+
+        return true;
+    }
+
+    @Override
+    protected void onCreate(Bundle savedState) {
         if (getIntent().hasExtra(EXTRA_UI_OPTIONS)) {
             getWindow().setUiOptions(getIntent().getIntExtra(EXTRA_UI_OPTIONS, 0));
         }
@@ -489,78 +419,67 @@
         DevicePolicyManager dpm =
                 (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
 
-        mHeaderAdapter= new HeaderAdapter(this, mHeaders, mAuthenticatorHelper, dpm);
+        mHeaderAdapter = new HeaderAdapter(this, mHeaders, mAuthenticatorHelper, dpm);
 
         mDevelopmentPreferences = getSharedPreferences(DevelopmentSettings.PREF_FILE,
                 Context.MODE_PRIVATE);
 
         getMetaData();
 
-        super.onCreate(savedInstanceState);
+        super.onCreate(savedState);
 
         setContentView(R.layout.settings_main);
 
         getFragmentManager().addOnBackStackChangedListener(this);
 
-        mActionBar = getActionBar();
-        mActionBar.setDisplayHomeAsUpEnabled(true);
-        mActionBar.setHomeButtonEnabled(true);
+        boolean displayHomeAsUpEnabled = true;
 
-        mDrawer = (ListView) findViewById(R.id.headers_drawer);
-        mDrawer.setAdapter(mHeaderAdapter);
-        mDrawer.setOnItemClickListener(new DrawerItemClickListener());
-        mDrawer.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE);
+        String initialFragmentName = getIntent().getStringExtra(EXTRA_SHOW_FRAGMENT);
+        Bundle initialArguments = getIntent().getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS);
 
-        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
-        mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
-                R.drawable.ic_drawer, R.string.drawer_open, R.string.drawer_close);
+        if (savedState != null) {
+            mSearchMenuItemExpanded = savedState.getBoolean(SAVE_KEY_SEARCH_MENU_EXPANDED);
+            mSearchQuery = savedState.getString(SAVE_KEY_SEARCH_QUERY);
 
-        if (savedInstanceState != null) {
-            // We are restarting from a previous saved state; used that to
+                    // We are restarting from a previous saved state; used that to
             // initialize, instead of starting fresh.
             mInitialTitle = getTitle();
 
-            ArrayList<Header> headers =
-                    savedInstanceState.getParcelableArrayList(SAVE_KEY_HEADERS_TAG);
+            ArrayList<Header> headers = savedState.getParcelableArrayList(SAVE_KEY_HEADERS);
             if (headers != null) {
                 mHeaders.addAll(headers);
-                int curHeader = savedInstanceState.getInt(SAVE_KEY_CURRENT_HEADER_TAG,
-                        (int) HEADER_ID_UNDEFINED);
-                if (curHeader >= 0 && curHeader < mHeaders.size()) {
-                    setSelectedHeader(mHeaders.get(curHeader));
-                    mInitialHeader = mCurrentHeader;
-                }
                 setTitleFromBackStack();
             }
         } else {
-            String initialFragment = getIntent().getStringExtra(EXTRA_SHOW_FRAGMENT);
-            Bundle initialArguments = getIntent().getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS);
-
             // We need to build the Headers in all cases
             onBuildHeaders(mHeaders);
 
-            if (initialFragment != null) {
-                // If we are just showing a fragment, we want to run in
-                // new fragment mode, but don't need to compute and show
-                // the headers.
-                final int initialTitleResId = getIntent().getIntExtra(EXTRA_SHOW_FRAGMENT_TITLE, 0);
-                mInitialTitle = (initialTitleResId > 0) ? getText(initialTitleResId) : getTitle();
+            if (initialFragmentName != null) {
+                final ComponentName cn = getIntent().getComponent();
+                // No UP is we are launched thru a Settings shortcut
+                if (!cn.getClassName().equals(SubSettings.class.getName())) {
+                    displayHomeAsUpEnabled = false;
+                }
+                final String initialTitle = getIntent().getStringExtra(EXTRA_SHOW_FRAGMENT_TITLE);
+                mInitialTitle = (initialTitle != null) ? initialTitle : getTitle();
                 setTitle(mInitialTitle);
-                switchToHeaderInner(initialFragment, initialArguments, true, false, mInitialTitle);
-                setSelectedHeaderById(mTopLevelHeaderId);
-                mInitialHeader = mCurrentHeader;
+                switchToFragment( initialFragmentName, initialArguments, true, false,
+                        mInitialTitle, false);
             } else {
-                // If there are headers, then at this point we need to show
-                // them and, depending on the screen, we may also show in-line
-                // the currently selected preference fragment.
+                // No UP if we are displaying the Headers
+                displayHomeAsUpEnabled = false;
                 if (mHeaders.size() > 0) {
-                    mInitialHeader = onGetInitialHeader();
-                    mInitialTitle = getHeaderTitle(mInitialHeader);
-                    switchToHeader(mInitialHeader, false, true);
+                    mInitialTitle = getText(R.string.dashboard_title);
+                    switchToFragment(DashboardSummary.class.getName(), null, false, false,
+                            mInitialTitle, false);
                 }
             }
         }
 
+        mActionBar = getActionBar();
+        mActionBar.setHomeButtonEnabled(true);
+        mActionBar.setDisplayHomeAsUpEnabled(displayHomeAsUpEnabled);
+
         // see if we should show Back/Next buttons
         Intent intent = getIntent();
         if (intent.getBooleanExtra(EXTRA_PREFS_SHOW_BUTTON_BAR, false)) {
@@ -615,39 +534,11 @@
                 }
             }
         }
-
-        if (!onIsHidingHeaders()) {
-            highlightHeader(mTopLevelHeaderId);
-        }
-    }
-
-    public Header onGetInitialHeader() {
-        String fragmentClass = getStartingFragmentClass(super.getIntent());
-        if (fragmentClass != null) {
-            Header header = new Header();
-            header.fragment = fragmentClass;
-            header.title = getTitle();
-            header.fragmentArguments = getIntent().getExtras();
-            return header;
-        }
-
-        return mFirstHeader;
-    }
-
-    @Override
-    public void onBackPressed() {
-        if (mDrawerLayout.isDrawerOpen(mDrawer)) {
-            mDrawerLayout.closeDrawer(mDrawer);
-            return;
-        }
-        super.onBackPressed();
     }
 
     @Override
     public void onBackStackChanged() {
-        if (setTitleFromBackStack() == 0) {
-            setSelectedHeaderById(mInitialHeader.id);
-        }
+        setTitleFromBackStack();
     }
 
     private int setTitleFromBackStack() {
@@ -682,14 +573,16 @@
         super.onSaveInstanceState(outState);
 
         if (mHeaders.size() > 0) {
-            outState.putParcelableArrayList(SAVE_KEY_HEADERS_TAG, mHeaders);
+            outState.putParcelableArrayList(SAVE_KEY_HEADERS, mHeaders);
             if (mCurrentHeader != null) {
                 int index = mHeaders.indexOf(mCurrentHeader);
                 if (index >= 0) {
-                    outState.putInt(SAVE_KEY_CURRENT_HEADER_TAG, index);
+                    outState.putInt(SAVE_KEY_CURRENT_HEADER, index);
                 }
             }
         }
+        outState.putBoolean(SAVE_KEY_SEARCH_MENU_EXPANDED, mSearchMenuItem.isActionViewExpanded());
+        outState.putString(SAVE_KEY_SEARCH_QUERY, mSearchView.getQuery().toString());
     }
 
     @Override
@@ -709,16 +602,12 @@
         invalidateHeaders();
 
         registerReceiver(mBatteryInfoReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
-
-        mDrawerLayout.setDrawerListener(new DrawerListener());
     }
 
     @Override
     public void onPause() {
         super.onPause();
 
-        mDrawerLayout.setDrawerListener(null);
-
         unregisterReceiver(mBatteryInfoReceiver);
 
         mHeaderAdapter.pause();
@@ -746,133 +635,24 @@
         return false;
     }
 
-    private CharSequence getHeaderTitle(Header header) {
-        if (header == null || header.fragment == null) return getTitle();
-        final CharSequence title;
-        if (header.fragment.equals(DashboardSummary.class.getName())) {
-            title = getResources().getString(R.string.settings_label);
-        } else {
-            title = header.getTitle(getResources());
-        }
-        return title;
-    }
-
-    private void setSelectedHeaderById(long headerId) {
-        final int count = mHeaders.size();
-        for (int n = 0; n < count; n++) {
-            Header h = mHeaders.get(n);
-            if (h.id == headerId) {
-                setSelectedHeader(h);
-                return;
-            }
-        }
-    }
-
-    /**
-     * As the Headers can be rebuilt, their references can change, so use this method with caution!
-     */
-    private void setSelectedHeader(Header header) {
-        if (header == null) {
-            mCurrentHeader = null;
-            return;
-        }
-        // Update selected Header into Drawer only if it is not "Add Account"
-        if (header.id == R.id.account_add) {
-            mDrawer.clearChoices();
-            return;
-        }
-        mCurrentHeader = header;
-        int index = mHeaders.indexOf(header);
-        if (index >= 0) {
-            mDrawer.setItemChecked(index, true);
-        } else {
-            mDrawer.clearChoices();
-        }
-    }
-
-    private void highlightHeader(int id) {
-        if (id != 0) {
-            Integer index = mHeaderIndexMap.get(id);
-            if (index != null) {
-                mDrawer.setItemChecked(index, true);
-                if (mDrawer.getVisibility() == View.VISIBLE) {
-                    mDrawer.smoothScrollToPosition(index);
-                }
-            }
-        }
-    }
-
     /**
      * When in two-pane mode, switch to the fragment pane to show the given
      * preference fragment.
      *
      * @param header The new header to display.
-     * @param validate true means that the fragment's Header needs to be validated.
-     * @param initial true means that it is the initial Header.
      */
-    private void switchToHeader(Header header, boolean validate, boolean initial) {
+    private void onHeaderClick(Header header) {
         if (header == null) {
             return;
         }
-        // For switching to another Header it should be a different one
-        if (mCurrentHeader == null || header.id != mCurrentHeader.id) {
-            if (header.fragment != null) {
-                boolean addToBackStack;
-                if (initial) {
-                    addToBackStack = false;
-                } else {
-                    if (header.id != mInitialHeader.id) {
-                        addToBackStack = true;
-                    } else {
-                        addToBackStack = (mTopLevelHeaderId > 0);
-                    }
-                }
-                switchToHeaderInner(header.fragment, header.fragmentArguments, validate,
-                        addToBackStack, getHeaderTitle(header));
-                setSelectedHeader(header);
-            } else if (header.intent != null) {
-                setSelectedHeader(header);
-                startActivity(header.intent);
-            } else {
-                throw new IllegalStateException(
-                        "Can't switch to header that has no Fragment nor Intent");
-            }
-        }
-    }
-
-    /**
-     * Switch to a specific Header with taking care of validation, Title and BackStack
-     */
-    private void switchToHeaderInner(String fragmentName, Bundle args, boolean validate,
-                                     boolean addToBackStack, CharSequence title) {
-        getFragmentManager().popBackStack(BACK_STACK_PREFS,
-                FragmentManager.POP_BACK_STACK_INCLUSIVE);
-        if (validate && !isValidFragment(fragmentName)) {
-            throw new IllegalArgumentException("Invalid fragment for this activity: "
-                    + fragmentName);
-        }
-        Fragment f = Fragment.instantiate(this, fragmentName, args);
-        FragmentTransaction transaction = getFragmentManager().beginTransaction();
-        transaction.replace(R.id.prefs, f);
-        transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
-        if (addToBackStack) {
-            transaction.addToBackStack(BACK_STACK_PREFS);
-        }
-        if (title != null) {
-            transaction.setBreadCrumbTitle(title);
-        }
-        transaction.commitAllowingStateLoss();
-    }
-
-    @Override
-    public void onNewIntent(Intent intent) {
-        super.onNewIntent(intent);
-
-        // If it is not launched from history, then reset to top-level
-        if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) == 0) {
-            if (mDrawer != null) {
-                mDrawer.setSelectionFromTop(0, 0);
-            }
+        if (header.fragment != null) {
+            startWithFragment(header.fragment, header.fragmentArguments, null, 0,
+                    header.getTitle(getResources()));
+        } else if (header.intent != null) {
+            startActivity(header.intent);
+        } else {
+            throw new IllegalStateException(
+                    "Can't switch to header that has no Fragment nor Intent");
         }
     }
 
@@ -949,9 +729,8 @@
      * request code to be received with the resut.
      */
     public void startPreferencePanel(String fragmentClass, Bundle args, int titleRes,
-                                     CharSequence titleText, Fragment resultTo,
-                                     int resultRequestCode) {
-        startWithFragment(fragmentClass, args, resultTo, resultRequestCode, titleRes, titleText);
+            CharSequence titleText, Fragment resultTo, int resultRequestCode) {
+        switchToFragment(fragmentClass, args, resultTo, resultRequestCode, titleRes, titleText);
     }
 
     /**
@@ -987,7 +766,7 @@
     }
 
     /**
-     * Start a new fragment.
+     * Start a new fragment. Used by #startPreferencePanel.
      *
      * @param fragmentName The name of the fragment to display.
      * @param args Optional arguments to supply to the fragment.
@@ -1000,8 +779,8 @@
      *                 argument will be used as the title.
      * @param titleText string to display for the title of.
      */
-    private void startWithFragment(String fragmentName, Bundle args, Fragment resultTo,
-                                   int resultRequestCode, int titleRes, CharSequence titleText) {
+    private void switchToFragment(String fragmentName, Bundle args, Fragment resultTo,
+            int resultRequestCode, int titleRes, CharSequence titleText) {
         final CharSequence cs;
         if (titleRes != 0) {
             cs = getText(titleRes);
@@ -1022,6 +801,75 @@
     }
 
     /**
+     * Switch to a specific Fragment with taking care of validation, Title and BackStack
+     */
+    private Fragment switchToFragment(String fragmentName, Bundle args, boolean validate,
+            boolean addToBackStack, CharSequence title, boolean withTransition) {
+        if (validate && !isValidFragment(fragmentName)) {
+            throw new IllegalArgumentException("Invalid fragment for this activity: "
+                    + fragmentName);
+        }
+        Fragment f = Fragment.instantiate(this, fragmentName, args);
+        FragmentTransaction transaction = getFragmentManager().beginTransaction();
+        transaction.replace(R.id.prefs, f);
+        if (withTransition) {
+            transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
+        }
+        if (addToBackStack) {
+            transaction.addToBackStack(SettingsActivity.BACK_STACK_PREFS);
+        }
+        if (title != null) {
+            transaction.setBreadCrumbTitle(title);
+        }
+        transaction.commitAllowingStateLoss();
+        return f;
+    }
+
+    /**
+     * Start a new instance of this activity, showing only the given fragment.
+     * When launched in this mode, the given preference fragment will be instantiated and fill the
+     * entire activity.
+     *
+     * @param fragmentName The name of the fragment to display.
+     * @param args Optional arguments to supply to the fragment.
+     * @param resultTo Option fragment that should receive the result of
+     * the activity launch.
+     * @param resultRequestCode If resultTo is non-null, this is the request
+     * code in which to report the result.
+     * @param title String to display for the title of this set of preferences.
+     */
+    public void startWithFragment(String fragmentName, Bundle args,
+                                  Fragment resultTo, int resultRequestCode, CharSequence title) {
+        Intent intent = onBuildStartFragmentIntent(fragmentName, args, title);
+        if (resultTo == null) {
+            startActivity(intent);
+        } else {
+            resultTo.startActivityForResult(intent, resultRequestCode);
+        }
+    }
+
+    /**
+     * Build an Intent to launch a new activity showing the selected fragment.
+     * The implementation constructs an Intent that re-launches the current activity with the
+     * appropriate arguments to display the fragment.
+     *
+     * @param fragmentName The name of the fragment to display.
+     * @param args Optional arguments to supply to the fragment.
+     * @param title Optional title to show for this item.
+     * @return Returns an Intent that can be launched to display the given
+     * fragment.
+     */
+    public Intent onBuildStartFragmentIntent(String fragmentName, Bundle args, CharSequence title) {
+        Intent intent = new Intent(Intent.ACTION_MAIN);
+        intent.setClass(this, SubSettings.class);
+        intent.putExtra(EXTRA_SHOW_FRAGMENT, fragmentName);
+        intent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, args);
+        intent.putExtra(EXTRA_SHOW_FRAGMENT_TITLE, title);
+        intent.putExtra(EXTRA_NO_HEADERS, true);
+        return intent;
+    }
+
+    /**
      * Called when the activity needs its list of headers build.
      *
      * @param headers The list in which to place the headers.
@@ -1226,11 +1074,6 @@
 
             // Increment if the current one wasn't removed by the Utils code.
             if (i < target.size() && target.get(i) == header) {
-                // Hold on to the first header, when we need to reset to the top-level
-                if (mFirstHeader == null &&
-                        HeaderAdapter.getHeaderType(header) != HeaderAdapter.HEADER_TYPE_CATEGORY) {
-                    mFirstHeader = header;
-                }
                 mHeaderIndexMap.put(id, i);
                 i++;
             }
@@ -1336,7 +1179,6 @@
             ActivityInfo ai = getPackageManager().getActivityInfo(getComponentName(),
                     PackageManager.GET_META_DATA);
             if (ai == null || ai.metaData == null) return;
-            mTopLevelHeaderId = ai.metaData.getInt(META_DATA_KEY_HEADER_ID);
             mFragmentClass = ai.metaData.getString(META_DATA_KEY_FRAGMENT_CLASS);
         } catch (NameNotFoundException nnfe) {
             // No recovery
@@ -1353,261 +1195,19 @@
         return mNextButton;
     }
 
-    public static class NoHomeDialogFragment extends DialogFragment {
-        public static void show(Activity parent) {
-            final NoHomeDialogFragment dialog = new NoHomeDialogFragment();
-            dialog.show(parent.getFragmentManager(), null);
-        }
-
-        @Override
-        public Dialog onCreateDialog(Bundle savedInstanceState) {
-            return new AlertDialog.Builder(getActivity())
-                    .setMessage(R.string.only_one_home_message)
-                    .setPositiveButton(android.R.string.ok, null)
-                    .create();
-        }
+    public HeaderAdapter getHeaderAdapter() {
+        return mHeaderAdapter;
     }
 
-    private static class HeaderAdapter extends ArrayAdapter<Header> {
-        static final int HEADER_TYPE_CATEGORY = 0;
-        static final int HEADER_TYPE_NORMAL = 1;
-        static final int HEADER_TYPE_SWITCH = 2;
-        static final int HEADER_TYPE_BUTTON = 3;
-        private static final int HEADER_TYPE_COUNT = HEADER_TYPE_BUTTON + 1;
-
-        private final WifiEnabler mWifiEnabler;
-        private final BluetoothEnabler mBluetoothEnabler;
-        private AuthenticatorHelper mAuthHelper;
-        private DevicePolicyManager mDevicePolicyManager;
-
-        private static class HeaderViewHolder {
-            ImageView mIcon;
-            TextView mTitle;
-            TextView mSummary;
-            Switch mSwitch;
-            ImageButton mButton;
-            View mDivider;
-        }
-
-        private LayoutInflater mInflater;
-
-        static int getHeaderType(Header header) {
-            if (header.fragment == null && header.intent == null) {
-                return HEADER_TYPE_CATEGORY;
-            } else if (header.id == R.id.security_settings) {
-                return HEADER_TYPE_BUTTON;
-            } else {
-                return HEADER_TYPE_NORMAL;
-            }
-        }
-
-        @Override
-        public int getItemViewType(int position) {
-            Header header = getItem(position);
-            return getHeaderType(header);
-        }
-
-        @Override
-        public boolean areAllItemsEnabled() {
-            return false; // because of categories
-        }
-
-        @Override
-        public boolean isEnabled(int position) {
-            return getItemViewType(position) != HEADER_TYPE_CATEGORY;
-        }
-
-        @Override
-        public int getViewTypeCount() {
-            return HEADER_TYPE_COUNT;
-        }
-
-        @Override
-        public boolean hasStableIds() {
-            return true;
-        }
-
-        public HeaderAdapter(Context context, List<Header> objects,
-                AuthenticatorHelper authenticatorHelper, DevicePolicyManager dpm) {
-            super(context, 0, objects);
-
-            mAuthHelper = authenticatorHelper;
-            mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-
-            // Temp Switches provided as placeholder until the adapter replaces these with actual
-            // Switches inflated from their layouts. Must be done before adapter is set in super
-            mWifiEnabler = new WifiEnabler(context, new Switch(context));
-            mBluetoothEnabler = new BluetoothEnabler(context, new Switch(context));
-            mDevicePolicyManager = dpm;
-        }
-
-        @Override
-        public View getView(int position, View convertView, ViewGroup parent) {
-            HeaderViewHolder holder;
-            Header header = getItem(position);
-            int headerType = getHeaderType(header);
-            View view = null;
-
-            if (convertView == null) {
-                holder = new HeaderViewHolder();
-                switch (headerType) {
-                    case HEADER_TYPE_CATEGORY:
-                        view = new TextView(getContext(), null,
-                                android.R.attr.listSeparatorTextViewStyle);
-                        holder.mTitle = (TextView) view;
-                        break;
-
-                    case HEADER_TYPE_SWITCH:
-                        view = mInflater.inflate(R.layout.preference_header_switch_item, parent,
-                                false);
-                        holder.mIcon = (ImageView) view.findViewById(R.id.icon);
-                        holder.mTitle = (TextView)
-                                view.findViewById(com.android.internal.R.id.title);
-                        holder.mSummary = (TextView)
-                                view.findViewById(com.android.internal.R.id.summary);
-                        holder.mSwitch = (Switch) view.findViewById(R.id.switchWidget);
-                        break;
-
-                    case HEADER_TYPE_BUTTON:
-                        view = mInflater.inflate(R.layout.preference_header_button_item, parent,
-                                false);
-                        holder.mIcon = (ImageView) view.findViewById(R.id.icon);
-                        holder.mTitle = (TextView)
-                                view.findViewById(com.android.internal.R.id.title);
-                        holder.mSummary = (TextView)
-                                view.findViewById(com.android.internal.R.id.summary);
-                        holder.mButton = (ImageButton) view.findViewById(R.id.buttonWidget);
-                        holder.mDivider = view.findViewById(R.id.divider);
-                        break;
-
-                    case HEADER_TYPE_NORMAL:
-                        view = mInflater.inflate(
-                                R.layout.preference_header_item, parent,
-                                false);
-                        holder.mIcon = (ImageView) view.findViewById(R.id.icon);
-                        holder.mTitle = (TextView)
-                                view.findViewById(com.android.internal.R.id.title);
-                        holder.mSummary = (TextView)
-                                view.findViewById(com.android.internal.R.id.summary);
-                        break;
-                }
-                view.setTag(holder);
-            } else {
-                view = convertView;
-                holder = (HeaderViewHolder) view.getTag();
-            }
-
-            // All view fields must be updated every time, because the view may be recycled
-            switch (headerType) {
-                case HEADER_TYPE_CATEGORY:
-                    holder.mTitle.setText(header.getTitle(getContext().getResources()));
-                    break;
-
-                case HEADER_TYPE_SWITCH:
-                    // Would need a different treatment if the main menu had more switches
-                    if (header.id == R.id.wifi_settings) {
-                        mWifiEnabler.setSwitch(holder.mSwitch);
-                    } else {
-                        mBluetoothEnabler.setSwitch(holder.mSwitch);
-                    }
-                    updateCommonHeaderView(header, holder);
-                    break;
-
-                case HEADER_TYPE_BUTTON:
-                    if (header.id == R.id.security_settings) {
-                        boolean hasCert = DevicePolicyManager.hasAnyCaCertsInstalled();
-                        if (hasCert) {
-                            holder.mButton.setVisibility(View.VISIBLE);
-                            holder.mDivider.setVisibility(View.VISIBLE);
-                            boolean isManaged = mDevicePolicyManager.getDeviceOwner() != null;
-                            if (isManaged) {
-                                holder.mButton.setImageResource(R.drawable.ic_settings_about);
-                            } else {
-                                holder.mButton.setImageResource(
-                                        android.R.drawable.stat_notify_error);
-                            }
-                            holder.mButton.setOnClickListener(new OnClickListener() {
-                                @Override
-                                public void onClick(View v) {
-                                    Intent intent = new Intent(
-                                            android.provider.Settings.ACTION_MONITORING_CERT_INFO);
-                                    getContext().startActivity(intent);
-                                }
-                            });
-                        } else {
-                            holder.mButton.setVisibility(View.GONE);
-                            holder.mDivider.setVisibility(View.GONE);
-                        }
-                    }
-                    updateCommonHeaderView(header, holder);
-                    break;
-
-                case HEADER_TYPE_NORMAL:
-                    updateCommonHeaderView(header, holder);
-                    break;
-            }
-
-            return view;
-        }
-
-        private void updateCommonHeaderView(Header header, HeaderViewHolder holder) {
-                if (header.extras != null
-                        && header.extras.containsKey(ManageAccountsSettings.KEY_ACCOUNT_TYPE)) {
-                    String accType = header.extras.getString(
-                            ManageAccountsSettings.KEY_ACCOUNT_TYPE);
-                    Drawable icon = mAuthHelper.getDrawableForType(getContext(), accType);
-                    setHeaderIcon(holder, icon);
-                } else {
-                    if (header.iconRes > 0) {
-                        holder.mIcon.setImageResource(header.iconRes);
-                    } else {
-                        holder.mIcon.setImageDrawable(null);
-                    }
-                }
-                if (holder.mIcon != null) {
-                    if (header.iconRes > 0) {
-                        holder.mIcon.setBackgroundResource(R.color.background_drawer_icon);
-                    } else {
-                        holder.mIcon.setBackground(null);
-                    }
-                }
-                holder.mTitle.setText(header.getTitle(getContext().getResources()));
-                CharSequence summary = header.getSummary(getContext().getResources());
-                if (!TextUtils.isEmpty(summary)) {
-                    holder.mSummary.setVisibility(View.VISIBLE);
-                    holder.mSummary.setText(summary);
-                } else {
-                    holder.mSummary.setVisibility(View.GONE);
-                }
-            }
-
-        private void setHeaderIcon(HeaderViewHolder holder, Drawable icon) {
-            ViewGroup.LayoutParams lp = holder.mIcon.getLayoutParams();
-            lp.width = getContext().getResources().getDimensionPixelSize(
-                    R.dimen.header_icon_width);
-            lp.height = lp.width;
-            holder.mIcon.setLayoutParams(lp);
-            holder.mIcon.setImageDrawable(icon);
-        }
-
-        public void resume(Context context) {
-            mWifiEnabler.resume();
-            mBluetoothEnabler.resume(context);
-        }
-
-        public void pause() {
-            mWifiEnabler.pause();
-            mBluetoothEnabler.pause();
-        }
-    }
-
-    private void onListItemClick(ListView l, View v, int position, long id) {
+    public void onListItemClick(ListView l, View v, int position, long id) {
         if (!isResumed()) {
             return;
         }
         Object item = mHeaderAdapter.getItem(position);
         if (item instanceof Header) {
             mSelectedHeader = (Header) item;
+            onHeaderClick(mSelectedHeader);
+            revertToInitialFragment();
         }
     }
 
@@ -1628,156 +1228,68 @@
         sShowNoHomeNotice = true;
     }
 
-    /**
-     * Default value for {@link Header#id Header.id} indicating that no
-     * identifier value is set.  All other values (including those below -1)
-     * are valid.
-     */
-    private static final long HEADER_ID_UNDEFINED = -1;
+    @Override
+    public boolean onQueryTextSubmit(String query) {
+        switchToSearchResultsFragmentIfNeeded();
+        mSearchQuery = query;
+        return mSearchResultsFragment.onQueryTextSubmit(query);
+    }
 
-    /**
-     * Description of a single Header item that the user can select.
-     */
-    static final class Header implements Parcelable {
-        /**
-         * Identifier for this header, to correlate with a new list when
-         * it is updated.  The default value is
-         * {@link SettingsActivity#HEADER_ID_UNDEFINED}, meaning no id.
-         * @attr ref android.R.styleable#PreferenceHeader_id
-         */
-        public long id = HEADER_ID_UNDEFINED;
+    @Override
+    public boolean onQueryTextChange(String newText) {
+        mSearchQuery = newText;
+        return false;
+    }
 
-        /**
-         * Resource ID of title of the header that is shown to the user.
-         * @attr ref android.R.styleable#PreferenceHeader_title
-         */
-        public int titleRes;
+    @Override
+    public boolean onClose() {
+        return false;
+    }
 
-        /**
-         * Title of the header that is shown to the user.
-         * @attr ref android.R.styleable#PreferenceHeader_title
-         */
-        public CharSequence title;
-
-        /**
-         * Resource ID of optional summary describing what this header controls.
-         * @attr ref android.R.styleable#PreferenceHeader_summary
-         */
-        public int summaryRes;
-
-        /**
-         * Optional summary describing what this header controls.
-         * @attr ref android.R.styleable#PreferenceHeader_summary
-         */
-        public CharSequence summary;
-
-        /**
-         * Optional icon resource to show for this header.
-         * @attr ref android.R.styleable#PreferenceHeader_icon
-         */
-        public int iconRes;
-
-        /**
-         * Full class name of the fragment to display when this header is
-         * selected.
-         * @attr ref android.R.styleable#PreferenceHeader_fragment
-         */
-        public String fragment;
-
-        /**
-         * Optional arguments to supply to the fragment when it is
-         * instantiated.
-         */
-        public Bundle fragmentArguments;
-
-        /**
-         * Intent to launch when the preference is selected.
-         */
-        public Intent intent;
-
-        /**
-         * Optional additional data for use by subclasses of the activity
-         */
-        public Bundle extras;
-
-        public Header() {
-            // Empty
-        }
-
-        /**
-         * Return the currently set title.  If {@link #titleRes} is set,
-         * this resource is loaded from <var>res</var> and returned.  Otherwise
-         * {@link #title} is returned.
-         */
-        public CharSequence getTitle(Resources res) {
-            if (titleRes != 0) {
-                return res.getText(titleRes);
+    @Override
+    public boolean onMenuItemActionExpand(MenuItem item) {
+        if (item.getItemId() == mSearchMenuItem.getItemId()) {
+            if (mSearchResultsFragment == null) {
+                switchToSearchResultsFragmentIfNeeded();
             }
-            return title;
         }
+        return true;
+    }
 
-        /**
-         * Return the currently set summary.  If {@link #summaryRes} is set,
-         * this resource is loaded from <var>res</var> and returned.  Otherwise
-         * {@link #summary} is returned.
-         */
-        public CharSequence getSummary(Resources res) {
-            if (summaryRes != 0) {
-                return res.getText(summaryRes);
+    @Override
+    public boolean onMenuItemActionCollapse(MenuItem item) {
+        if (item.getItemId() == mSearchMenuItem.getItemId()) {
+            if (mIsShowingSearchResults) {
+                revertToInitialFragment();
             }
-            return summary;
         }
+        return true;
+    }
 
-        @Override
-        public int describeContents() {
-            return 0;
-        }
-
-        @Override
-        public void writeToParcel(Parcel dest, int flags) {
-            dest.writeLong(id);
-            dest.writeInt(titleRes);
-            TextUtils.writeToParcel(title, dest, flags);
-            dest.writeInt(summaryRes);
-            TextUtils.writeToParcel(summary, dest, flags);
-            dest.writeInt(iconRes);
-            dest.writeString(fragment);
-            dest.writeBundle(fragmentArguments);
-            if (intent != null) {
-                dest.writeInt(1);
-                intent.writeToParcel(dest, flags);
+    private void switchToSearchResultsFragmentIfNeeded() {
+        if (!mIsShowingSearchResults) {
+            Fragment current = getFragmentManager().findFragmentById(R.id.prefs);
+            if (current != null && current instanceof SearchResultsSummary) {
+                mSearchResultsFragment = (SearchResultsSummary) current;
             } else {
-                dest.writeInt(0);
+                String title = getString(R.string.search_results_title);
+                mSearchResultsFragment = (SearchResultsSummary) switchToFragment(
+                        SearchResultsSummary.class.getName(), null, false, true, title, true);
             }
-            dest.writeBundle(extras);
+            mIsShowingSearchResults = true;
         }
+    }
 
-        public void readFromParcel(Parcel in) {
-            id = in.readLong();
-            titleRes = in.readInt();
-            title = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
-            summaryRes = in.readInt();
-            summary = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
-            iconRes = in.readInt();
-            fragment = in.readString();
-            fragmentArguments = in.readBundle();
-            if (in.readInt() != 0) {
-                intent = Intent.CREATOR.createFromParcel(in);
-            }
-            extras = in.readBundle();
-        }
+    public void needToRevertToInitialFragment() {
+        mNeedToRevertToInitialFragment = true;
+    }
 
-        Header(Parcel in) {
-            readFromParcel(in);
-        }
-
-        public static final Creator<Header> CREATOR = new Creator<Header>() {
-            public Header createFromParcel(Parcel source) {
-                return new Header(source);
-            }
-            public Header[] newArray(int size) {
-                return new Header[size];
-            }
-        };
+    private void revertToInitialFragment() {
+        mNeedToRevertToInitialFragment = false;
+        getFragmentManager().popBackStack(SettingsActivity.BACK_STACK_PREFS,
+                FragmentManager.POP_BACK_STACK_INCLUSIVE);
+        mSearchResultsFragment = null;
+        mIsShowingSearchResults = false;
+        mSearchMenuItem.collapseActionView();
     }
 }
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index bf44835..1ae0829 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -55,6 +55,7 @@
 import android.view.ViewGroup;
 import android.widget.ListView;
 import android.widget.TabWidget;
+import com.android.settings.dashboard.Header;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -237,7 +238,7 @@
     }
 
     public static boolean updateHeaderToSpecificActivityFromMetaDataOrRemove(Context context,
-            List<SettingsActivity.Header> target, SettingsActivity.Header header) {
+            List<Header> target, Header header) {
 
         Intent intent = header.intent;
         if (intent != null) {
diff --git a/src/com/android/settings/bluetooth/BluetoothSettings.java b/src/com/android/settings/bluetooth/BluetoothSettings.java
index cc0371f..80f06b4 100755
--- a/src/com/android/settings/bluetooth/BluetoothSettings.java
+++ b/src/com/android/settings/bluetooth/BluetoothSettings.java
@@ -129,7 +129,7 @@
 
         final SettingsActivity activity = (SettingsActivity) getActivity();
 
-        if (!activity.onIsHidingHeaders()) {
+        if (activity.onIsHidingHeaders()) {
             activity.getActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM,
                     ActionBar.DISPLAY_SHOW_CUSTOM);
             activity.getActionBar().setCustomView(mSwitch, new ActionBar.LayoutParams(
@@ -198,7 +198,7 @@
             R.string.bluetooth_search_for_devices;
         menu.add(Menu.NONE, MENU_ID_SCAN, 0, textId)
                 .setEnabled(bluetoothIsEnabled && !isDiscovering)
-                .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
+                .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
         menu.add(Menu.NONE, MENU_ID_RENAME_DEVICE, 0, R.string.bluetooth_rename_device)
                 .setEnabled(bluetoothIsEnabled)
                 .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
diff --git a/src/com/android/settings/dashboard/DashboardSummary.java b/src/com/android/settings/dashboard/DashboardSummary.java
index b48e07e..f023dec 100644
--- a/src/com/android/settings/dashboard/DashboardSummary.java
+++ b/src/com/android/settings/dashboard/DashboardSummary.java
@@ -16,339 +16,35 @@
 
 package com.android.settings.dashboard;
 
-import android.app.Fragment;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
-import android.database.Cursor;
-import android.graphics.drawable.Drawable;
-import android.os.AsyncTask;
+import android.app.ListFragment;
 import android.os.Bundle;
-import android.text.Editable;
-import android.text.TextUtils;
-import android.text.TextWatcher;
-import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.inputmethod.InputMethodManager;
-import android.widget.AdapterView;
-import android.widget.BaseAdapter;
-import android.widget.EditText;
-import android.widget.ImageView;
+import android.widget.ListAdapter;
 import android.widget.ListView;
-import android.widget.TextView;
 import com.android.settings.R;
 import com.android.settings.SettingsActivity;
-import com.android.settings.search.Index;
 
-import java.util.HashMap;
-
-public class DashboardSummary extends Fragment {
-
+public class DashboardSummary extends ListFragment {
     private static final String LOG_TAG = "DashboardSummary";
 
-    private EditText mEditText;
-    private ListView mListView;
-
-    private SearchResultsAdapter mAdapter;
-    private Index mIndex;
-    private UpdateSearchResultsTask mUpdateSearchResultsTask;
-
-    /**
-     * A basic AsyncTask for updating the query results cursor
-     */
-    private class UpdateSearchResultsTask extends AsyncTask<String, Void, Cursor> {
-        @Override
-        protected Cursor doInBackground(String... params) {
-            return mIndex.search(params[0]);
-        }
-
-        @Override
-        protected void onPostExecute(Cursor cursor) {
-            if (!isCancelled()) {
-                setCursor(cursor);
-            } else if (cursor != null) {
-                cursor.close();
-            }
-        }
-    }
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        mIndex = Index.getInstance(getActivity());
-        mAdapter = new SearchResultsAdapter(getActivity());
-    }
-
-    @Override
-    public void onStop() {
-        super.onStop();
-
-        clearResults();
-    }
-
-    @Override
-    public void onStart() {
-        super.onStart();
-
-        updateSearchResults();
-    }
-
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
                              Bundle savedInstanceState) {
 
         final View view = inflater.inflate(R.layout.dashboard, container, false);
 
-        mEditText = (EditText)view.findViewById(R.id.edittext_query);
-        mEditText.addTextChangedListener(new TextWatcher() {
-            @Override
-            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
-            }
+        ListView listView = (ListView) view.findViewById(android.R.id.list);
 
-            @Override
-            public void onTextChanged(CharSequence s, int start, int before, int count) {
-                updateSearchResults();
-            }
-
-            @Override
-            public void afterTextChanged(Editable s) {
-            }
-        });
-        mEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
-            @Override
-            public void onFocusChange(View v, boolean hasFocus) {
-                if (!hasFocus) {
-                    closeSoftKeyboard();
-                }
-            }
-        });
-
-        mListView = (ListView) view.findViewById(R.id.list_results);
-        mListView.setAdapter(mAdapter);
-        mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
-            @Override
-            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
-                closeSoftKeyboard();
-
-                final Cursor cursor = mAdapter.mCursor;
-                cursor.moveToPosition(position);
-
-                final String className = cursor.getString(Index.COLUMN_INDEX_CLASS_NAME);
-                final String screenTitle = cursor.getString(Index.COLUMN_INDEX_SCREEN_TITLE);
-
-                final String action = cursor.getString(Index.COLUMN_INDEX_INTENT_ACTION);
-
-                if (TextUtils.isEmpty(action)) {
-                    ((SettingsActivity) getActivity()).startPreferencePanel(className, null, 0,
-                            screenTitle, null, 0);
-                } else {
-                    final Intent intent = new Intent(action);
-
-                    final String targetPackage = cursor.getString(
-                            Index.COLUMN_INDEX_INTENT_ACTION_TARGET_PACKAGE);
-                    final String targetClass = cursor.getString(
-                            Index.COLUMN_INDEX_INTENT_ACTION_TARGET_CLASS);
-                    if (!TextUtils.isEmpty(targetPackage) && !TextUtils.isEmpty(targetClass)) {
-                        final ComponentName component =
-                                new ComponentName(targetPackage, targetClass);
-                        intent.setComponent(component);
-                    }
-
-                    getActivity().startActivity(intent);
-                }
-            }
-        });
+        ListAdapter adapter = ((SettingsActivity) getActivity()).getHeaderAdapter();
+        listView.setAdapter(adapter);
 
         return view;
     }
 
-    private void closeSoftKeyboard() {
-        InputMethodManager imm = InputMethodManager.peekInstance();
-        if (imm != null && imm.isActive(mEditText)) {
-            imm.hideSoftInputFromWindow(mEditText.getWindowToken(), 0);
-        }
-    }
-
-    private void clearResults() {
-        if (mUpdateSearchResultsTask != null) {
-            mUpdateSearchResultsTask.cancel(false);
-            mUpdateSearchResultsTask = null;
-        }
-        setCursor(null);
-    }
-
-    private void setCursor(Cursor cursor) {
-        Cursor oldCursor = mAdapter.swapCursor(cursor);
-        if (oldCursor != null) {
-            oldCursor.close();
-        }
-    }
-
-    private String getFilteredQueryString() {
-        final CharSequence query = mEditText.getText().toString();
-        final StringBuilder filtered = new StringBuilder();
-        for (int n = 0; n < query.length(); n++) {
-            char c = query.charAt(n);
-            if (!Character.isLetterOrDigit(c) && !Character.isSpaceChar(c)) {
-                continue;
-            }
-            filtered.append(c);
-        }
-        return filtered.toString();
-    }
-
-    private void updateSearchResults() {
-        if (mUpdateSearchResultsTask != null) {
-            mUpdateSearchResultsTask.cancel(false);
-            mUpdateSearchResultsTask = null;
-        }
-        final String query = getFilteredQueryString();
-        if (TextUtils.isEmpty(query)) {
-            setCursor(null);
-        } else {
-            mUpdateSearchResultsTask = new UpdateSearchResultsTask();
-            mUpdateSearchResultsTask.execute(query);
-        }
-    }
-
-    private static class SearchResult {
-        public String title;
-        public String summary;
-        public int iconResId;
-        public Context context;
-
-        public SearchResult(Context context, String title, String summary, int iconResId) {
-            this.context = context;
-            this.title = title;
-            this.summary = summary;
-            this.iconResId = iconResId;
-        }
-    }
-
-    private static class SearchResultsAdapter extends BaseAdapter {
-
-        private Cursor mCursor;
-        private LayoutInflater mInflater;
-        private boolean mDataValid;
-        private Context mContext;
-        private HashMap<String, Context> mContextMap = new HashMap<String, Context>();
-
-        public SearchResultsAdapter(Context context) {
-            mContext = context;
-            mInflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-            mDataValid = false;
-        }
-
-        public Cursor swapCursor(Cursor newCursor) {
-            if (newCursor == mCursor) {
-                return null;
-            }
-            Cursor oldCursor = mCursor;
-            mCursor = newCursor;
-            if (newCursor != null) {
-                mDataValid = true;
-                notifyDataSetChanged();
-            } else {
-                mDataValid = false;
-                notifyDataSetInvalidated();
-            }
-            return oldCursor;
-        }
-
-        @Override
-        public int getCount() {
-            if (!mDataValid || mCursor == null || mCursor.isClosed()) return 0;
-            return mCursor.getCount();
-        }
-
-        @Override
-        public Object getItem(int position) {
-            if (mDataValid && mCursor.moveToPosition(position)) {
-                final String title = mCursor.getString(Index.COLUMN_INDEX_TITLE);
-                final String summary = mCursor.getString(Index.COLUMN_INDEX_SUMMARY);
-                final String iconResStr = mCursor.getString(Index.COLUMN_INDEX_ICON);
-                final String className = mCursor.getString(
-                        Index.COLUMN_INDEX_CLASS_NAME);
-                final String packageName = mCursor.getString(
-                        Index.COLUMN_INDEX_INTENT_ACTION_TARGET_PACKAGE);
-
-                Context packageContext;
-                if (TextUtils.isEmpty(className) && !TextUtils.isEmpty(packageName)) {
-                    packageContext = mContextMap.get(packageName);
-                    if (packageContext == null) {
-                        try {
-                            packageContext = mContext.createPackageContext(packageName, 0);
-                        } catch (PackageManager.NameNotFoundException e) {
-                            Log.e(LOG_TAG, "Cannot create Context for package: " + packageName);
-                            return null;
-                        }
-                        mContextMap.put(packageName, packageContext);
-                    }
-                } else {
-                    packageContext = mContext;
-                }
-                final int iconResId = TextUtils.isEmpty(iconResStr) ?
-                        R.drawable.empty_icon : Integer.parseInt(iconResStr);
-                return new SearchResult(packageContext, title, summary, iconResId);
-            }
-            return null;
-        }
-
-        @Override
-        public long getItemId(int position) {
-            return 0;
-        }
-
-        @Override
-        public View getView(int position, View convertView, ViewGroup parent) {
-            if (!mDataValid && convertView == null) {
-                throw new IllegalStateException(
-                        "this should only be called when the cursor is valid");
-            }
-            if (!mCursor.moveToPosition(position)) {
-                throw new IllegalStateException("couldn't move cursor to position " + position);
-            }
-
-            View view;
-            TextView textTitle;
-            TextView textSummary;
-            ImageView imageView;
-
-            if (convertView == null) {
-                view = mInflater.inflate(R.layout.search_result, parent, false);
-            } else {
-                view = convertView;
-            }
-            textTitle = (TextView) view.findViewById(R.id.title);
-            textSummary = (TextView) view.findViewById(R.id.summary);
-            imageView = (ImageView) view.findViewById(R.id.icon);
-
-            SearchResult result = (SearchResult) getItem(position);
-
-            textTitle.setText(result.title);
-            textSummary.setText(result.summary);
-            if (result.iconResId != R.drawable.empty_icon) {
-                final Context packageContext = result.context;
-                final Drawable drawable;
-                try {
-                    drawable = packageContext.getDrawable(result.iconResId);
-                    imageView.setImageDrawable(drawable);
-                } catch (Resources.NotFoundException nfe) {
-                    // Not much we can do except logging
-                    Log.e(LOG_TAG, "Cannot load Drawable for " + result.title);
-                }
-                imageView.setBackgroundResource(R.color.background_search_result_icon);
-            } else {
-                imageView.setImageDrawable(null);
-                imageView.setBackgroundResource(R.drawable.empty_icon);
-            }
-
-            return view;
-        }
+    @Override
+    public void onListItemClick(ListView l, View v, int position, long id) {
+        ((SettingsActivity) getActivity()).onListItemClick(l, v, position, id);
     }
 }
diff --git a/src/com/android/settings/dashboard/Header.java b/src/com/android/settings/dashboard/Header.java
new file mode 100644
index 0000000..86e55ac
--- /dev/null
+++ b/src/com/android/settings/dashboard/Header.java
@@ -0,0 +1,177 @@
+/*
+ * 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.dashboard;
+
+import android.content.Intent;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+/**
+ * Description of a single Header item that the user can select.
+ */
+public class Header implements Parcelable {
+    /**
+     * Default value for {@link Header#id Header.id} indicating that no
+     * identifier value is set.  All other values (including those below -1)
+     * are valid.
+     */
+    public static final long HEADER_ID_UNDEFINED = -1;
+
+    /**
+     * Identifier for this header, to correlate with a new list when
+     * it is updated.  The default value is
+     * {@link Header#HEADER_ID_UNDEFINED}, meaning no id.
+     * @attr ref android.R.styleable#PreferenceHeader_id
+     */
+    public long id = HEADER_ID_UNDEFINED;
+
+    /**
+     * Resource ID of title of the header that is shown to the user.
+     * @attr ref android.R.styleable#PreferenceHeader_title
+     */
+    public int titleRes;
+
+    /**
+     * Title of the header that is shown to the user.
+     * @attr ref android.R.styleable#PreferenceHeader_title
+     */
+    public CharSequence title;
+
+    /**
+     * Resource ID of optional summary describing what this header controls.
+     * @attr ref android.R.styleable#PreferenceHeader_summary
+     */
+    public int summaryRes;
+
+    /**
+     * Optional summary describing what this header controls.
+     * @attr ref android.R.styleable#PreferenceHeader_summary
+     */
+    public CharSequence summary;
+
+    /**
+     * Optional icon resource to show for this header.
+     * @attr ref android.R.styleable#PreferenceHeader_icon
+     */
+    public int iconRes;
+
+    /**
+     * Full class name of the fragment to display when this header is
+     * selected.
+     * @attr ref android.R.styleable#PreferenceHeader_fragment
+     */
+    public String fragment;
+
+    /**
+     * Optional arguments to supply to the fragment when it is
+     * instantiated.
+     */
+    public Bundle fragmentArguments;
+
+    /**
+     * Intent to launch when the preference is selected.
+     */
+    public Intent intent;
+
+    /**
+     * Optional additional data for use by subclasses of the activity
+     */
+    public Bundle extras;
+
+    public Header() {
+        // Empty
+    }
+
+    /**
+     * Return the currently set title.  If {@link #titleRes} is set,
+     * this resource is loaded from <var>res</var> and returned.  Otherwise
+     * {@link #title} is returned.
+     */
+    public CharSequence getTitle(Resources res) {
+        if (titleRes != 0) {
+            return res.getText(titleRes);
+        }
+        return title;
+    }
+
+    /**
+     * Return the currently set summary.  If {@link #summaryRes} is set,
+     * this resource is loaded from <var>res</var> and returned.  Otherwise
+     * {@link #summary} is returned.
+     */
+    public CharSequence getSummary(Resources res) {
+        if (summaryRes != 0) {
+            return res.getText(summaryRes);
+        }
+        return summary;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeLong(id);
+        dest.writeInt(titleRes);
+        TextUtils.writeToParcel(title, dest, flags);
+        dest.writeInt(summaryRes);
+        TextUtils.writeToParcel(summary, dest, flags);
+        dest.writeInt(iconRes);
+        dest.writeString(fragment);
+        dest.writeBundle(fragmentArguments);
+        if (intent != null) {
+            dest.writeInt(1);
+            intent.writeToParcel(dest, flags);
+        } else {
+            dest.writeInt(0);
+        }
+        dest.writeBundle(extras);
+    }
+
+    public void readFromParcel(Parcel in) {
+        id = in.readLong();
+        titleRes = in.readInt();
+        title = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+        summaryRes = in.readInt();
+        summary = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+        iconRes = in.readInt();
+        fragment = in.readString();
+        fragmentArguments = in.readBundle();
+        if (in.readInt() != 0) {
+            intent = Intent.CREATOR.createFromParcel(in);
+        }
+        extras = in.readBundle();
+    }
+
+    Header(Parcel in) {
+        readFromParcel(in);
+    }
+
+    public static final Creator<Header> CREATOR = new Creator<Header>() {
+        public Header createFromParcel(Parcel source) {
+            return new Header(source);
+        }
+        public Header[] newArray(int size) {
+            return new Header[size];
+        }
+    };
+}
diff --git a/src/com/android/settings/dashboard/HeaderAdapter.java b/src/com/android/settings/dashboard/HeaderAdapter.java
new file mode 100644
index 0000000..720f83b
--- /dev/null
+++ b/src/com/android/settings/dashboard/HeaderAdapter.java
@@ -0,0 +1,275 @@
+/*
+ * 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.dashboard;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.drawable.Drawable;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.Switch;
+import android.widget.TextView;
+import com.android.settings.R;
+import com.android.settings.accounts.AuthenticatorHelper;
+import com.android.settings.accounts.ManageAccountsSettings;
+import com.android.settings.bluetooth.BluetoothEnabler;
+import com.android.settings.wifi.WifiEnabler;
+
+import java.util.List;
+
+/**
+ * A basic ArrayAdapter for dealing with the Headers
+ */
+public class HeaderAdapter extends ArrayAdapter<Header> {
+    public static final int HEADER_TYPE_CATEGORY = 0;
+    public static final int HEADER_TYPE_NORMAL = 1;
+    public static final int HEADER_TYPE_SWITCH = 2;
+    public static final int HEADER_TYPE_BUTTON = 3;
+
+    private static final int HEADER_TYPE_COUNT = HEADER_TYPE_BUTTON + 1;
+
+    private final WifiEnabler mWifiEnabler;
+    private final BluetoothEnabler mBluetoothEnabler;
+    private AuthenticatorHelper mAuthHelper;
+    private DevicePolicyManager mDevicePolicyManager;
+
+    private static class HeaderViewHolder {
+        ImageView mIcon;
+        TextView mTitle;
+        TextView mSummary;
+        Switch mSwitch;
+        ImageButton mButton;
+        View mDivider;
+    }
+
+    private LayoutInflater mInflater;
+
+    public static int getHeaderType(Header header) {
+        if (header.fragment == null && header.intent == null) {
+            return HEADER_TYPE_CATEGORY;
+        } else if (header.id == R.id.security_settings) {
+            return HEADER_TYPE_BUTTON;
+        } else {
+            return HEADER_TYPE_NORMAL;
+        }
+    }
+
+    @Override
+    public int getItemViewType(int position) {
+        Header header = getItem(position);
+        return getHeaderType(header);
+    }
+
+    @Override
+    public boolean areAllItemsEnabled() {
+        return false; // because of categories
+    }
+
+    @Override
+    public boolean isEnabled(int position) {
+        return getItemViewType(position) != HEADER_TYPE_CATEGORY;
+    }
+
+    @Override
+    public int getViewTypeCount() {
+        return HEADER_TYPE_COUNT;
+    }
+
+    @Override
+    public boolean hasStableIds() {
+        return true;
+    }
+
+    public HeaderAdapter(Context context, List<Header> objects,
+                         AuthenticatorHelper authenticatorHelper, DevicePolicyManager dpm) {
+        super(context, 0, objects);
+
+        mAuthHelper = authenticatorHelper;
+        mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+        // Temp Switches provided as placeholder until the adapter replaces these with actual
+        // Switches inflated from their layouts. Must be done before adapter is set in super
+        mWifiEnabler = new WifiEnabler(context, new Switch(context));
+        mBluetoothEnabler = new BluetoothEnabler(context, new Switch(context));
+        mDevicePolicyManager = dpm;
+    }
+
+    @Override
+    public View getView(int position, View convertView, ViewGroup parent) {
+        HeaderViewHolder holder;
+        Header header = getItem(position);
+        int headerType = getHeaderType(header);
+        View view = null;
+
+        if (convertView == null) {
+            holder = new HeaderViewHolder();
+            switch (headerType) {
+                case HEADER_TYPE_CATEGORY:
+                    view = new TextView(getContext(), null,
+                            android.R.attr.listSeparatorTextViewStyle);
+                    holder.mTitle = (TextView) view;
+                    break;
+
+                case HEADER_TYPE_SWITCH:
+                    view = mInflater.inflate(R.layout.preference_header_switch_item, parent,
+                            false);
+                    holder.mIcon = (ImageView) view.findViewById(R.id.icon);
+                    holder.mTitle = (TextView)
+                            view.findViewById(com.android.internal.R.id.title);
+                    holder.mSummary = (TextView)
+                            view.findViewById(com.android.internal.R.id.summary);
+                    holder.mSwitch = (Switch) view.findViewById(R.id.switchWidget);
+                    break;
+
+                case HEADER_TYPE_BUTTON:
+                    view = mInflater.inflate(R.layout.preference_header_button_item, parent,
+                            false);
+                    holder.mIcon = (ImageView) view.findViewById(R.id.icon);
+                    holder.mTitle = (TextView)
+                            view.findViewById(com.android.internal.R.id.title);
+                    holder.mSummary = (TextView)
+                            view.findViewById(com.android.internal.R.id.summary);
+                    holder.mButton = (ImageButton) view.findViewById(R.id.buttonWidget);
+                    holder.mDivider = view.findViewById(R.id.divider);
+                    break;
+
+                case HEADER_TYPE_NORMAL:
+                    view = mInflater.inflate(
+                            R.layout.preference_header_item, parent,
+                            false);
+                    holder.mIcon = (ImageView) view.findViewById(R.id.icon);
+                    holder.mTitle = (TextView)
+                            view.findViewById(com.android.internal.R.id.title);
+                    holder.mSummary = (TextView)
+                            view.findViewById(com.android.internal.R.id.summary);
+                    break;
+            }
+            view.setTag(holder);
+        } else {
+            view = convertView;
+            holder = (HeaderViewHolder) view.getTag();
+        }
+
+        // All view fields must be updated every time, because the view may be recycled
+        switch (headerType) {
+            case HEADER_TYPE_CATEGORY:
+                holder.mTitle.setText(header.getTitle(getContext().getResources()));
+                break;
+
+            case HEADER_TYPE_SWITCH:
+                // Would need a different treatment if the main menu had more switches
+                if (header.id == R.id.wifi_settings) {
+                    mWifiEnabler.setSwitch(holder.mSwitch);
+                } else {
+                    mBluetoothEnabler.setSwitch(holder.mSwitch);
+                }
+                updateCommonHeaderView(header, holder);
+                break;
+
+            case HEADER_TYPE_BUTTON:
+                if (header.id == R.id.security_settings) {
+                    boolean hasCert = DevicePolicyManager.hasAnyCaCertsInstalled();
+                    if (hasCert) {
+                        holder.mButton.setVisibility(View.VISIBLE);
+                        holder.mDivider.setVisibility(View.VISIBLE);
+                        boolean isManaged = mDevicePolicyManager.getDeviceOwner() != null;
+                        if (isManaged) {
+                            holder.mButton.setImageResource(R.drawable.ic_settings_about);
+                        } else {
+                            holder.mButton.setImageResource(
+                                    android.R.drawable.stat_notify_error);
+                        }
+                        holder.mButton.setOnClickListener(new View.OnClickListener() {
+                            @Override
+                            public void onClick(View v) {
+                                Intent intent = new Intent(
+                                        android.provider.Settings.ACTION_MONITORING_CERT_INFO);
+                                getContext().startActivity(intent);
+                            }
+                        });
+                    } else {
+                        holder.mButton.setVisibility(View.GONE);
+                        holder.mDivider.setVisibility(View.GONE);
+                    }
+                }
+                updateCommonHeaderView(header, holder);
+                break;
+
+            case HEADER_TYPE_NORMAL:
+                updateCommonHeaderView(header, holder);
+                break;
+        }
+
+        return view;
+    }
+
+    private void updateCommonHeaderView(Header header, HeaderViewHolder holder) {
+        if (header.extras != null
+                && header.extras.containsKey(ManageAccountsSettings.KEY_ACCOUNT_TYPE)) {
+            String accType = header.extras.getString(
+                    ManageAccountsSettings.KEY_ACCOUNT_TYPE);
+            Drawable icon = mAuthHelper.getDrawableForType(getContext(), accType);
+            setHeaderIcon(holder, icon);
+        } else {
+            if (header.iconRes > 0) {
+                holder.mIcon.setImageResource(header.iconRes);
+            } else {
+                holder.mIcon.setImageDrawable(null);
+            }
+        }
+        if (holder.mIcon != null) {
+            if (header.iconRes > 0) {
+                holder.mIcon.setBackgroundResource(R.color.background_drawer_icon);
+            } else {
+                holder.mIcon.setBackground(null);
+            }
+        }
+        holder.mTitle.setText(header.getTitle(getContext().getResources()));
+        CharSequence summary = header.getSummary(getContext().getResources());
+        if (!TextUtils.isEmpty(summary)) {
+            holder.mSummary.setVisibility(View.VISIBLE);
+            holder.mSummary.setText(summary);
+        } else {
+            holder.mSummary.setVisibility(View.GONE);
+        }
+    }
+
+    private void setHeaderIcon(HeaderViewHolder holder, Drawable icon) {
+        ViewGroup.LayoutParams lp = holder.mIcon.getLayoutParams();
+        lp.width = getContext().getResources().getDimensionPixelSize(
+                R.dimen.header_icon_width);
+        lp.height = lp.width;
+        holder.mIcon.setLayoutParams(lp);
+        holder.mIcon.setImageDrawable(icon);
+    }
+
+    public void resume(Context context) {
+        mWifiEnabler.resume(context);
+        mBluetoothEnabler.resume(context);
+    }
+
+    public void pause() {
+        mWifiEnabler.pause();
+        mBluetoothEnabler.pause();
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/dashboard/NoHomeDialogFragment.java b/src/com/android/settings/dashboard/NoHomeDialogFragment.java
new file mode 100644
index 0000000..a795cc9
--- /dev/null
+++ b/src/com/android/settings/dashboard/NoHomeDialogFragment.java
@@ -0,0 +1,39 @@
+/*
+ * 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.dashboard;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.os.Bundle;
+import com.android.settings.R;
+
+public class NoHomeDialogFragment extends DialogFragment {
+    public static void show(Activity parent) {
+        final NoHomeDialogFragment dialog = new NoHomeDialogFragment();
+        dialog.show(parent.getFragmentManager(), null);
+    }
+
+    @Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        return new AlertDialog.Builder(getActivity())
+                .setMessage(R.string.only_one_home_message)
+                .setPositiveButton(android.R.string.ok, null)
+                .create();
+    }
+}
diff --git a/src/com/android/settings/dashboard/SearchResultsSummary.java b/src/com/android/settings/dashboard/SearchResultsSummary.java
new file mode 100644
index 0000000..992bb59
--- /dev/null
+++ b/src/com/android/settings/dashboard/SearchResultsSummary.java
@@ -0,0 +1,331 @@
+/*
+ * 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.dashboard;
+
+import android.app.Fragment;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.graphics.drawable.Drawable;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.TextView;
+import com.android.settings.R;
+import com.android.settings.SettingsActivity;
+import com.android.settings.search.Index;
+
+import java.util.HashMap;
+
+public class SearchResultsSummary extends Fragment {
+
+    private static final String LOG_TAG = "SearchResultsSummary";
+
+    private ListView mListView;
+
+    private SearchResultsAdapter mAdapter;
+    private UpdateSearchResultsTask mUpdateSearchResultsTask;
+
+    /**
+     * A basic AsyncTask for updating the query results cursor
+     */
+    private class UpdateSearchResultsTask extends AsyncTask<String, Void, Cursor> {
+        @Override
+        protected Cursor doInBackground(String... params) {
+            return Index.getInstance(getActivity()).search(params[0]);
+        }
+
+        @Override
+        protected void onPostExecute(Cursor cursor) {
+            if (!isCancelled()) {
+                setCursor(cursor);
+            } else if (cursor != null) {
+                cursor.close();
+            }
+        }
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        mAdapter = new SearchResultsAdapter(getActivity());
+    }
+
+    @Override
+    public void onStop() {
+        super.onStop();
+
+        clearResults();
+    }
+
+    @Override
+    public void onDestroy() {
+        mListView = null;
+        mAdapter = null;
+        mUpdateSearchResultsTask = null;
+
+        super.onDestroy();
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                             Bundle savedInstanceState) {
+
+        final View view = inflater.inflate(R.layout.search_results, container, false);
+
+        mListView = (ListView) view.findViewById(R.id.list_results);
+        mListView.setAdapter(mAdapter);
+        mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+            @Override
+            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+                final Cursor cursor = mAdapter.mCursor;
+                cursor.moveToPosition(position);
+
+                final String className = cursor.getString(Index.COLUMN_INDEX_CLASS_NAME);
+                final String screenTitle = cursor.getString(Index.COLUMN_INDEX_SCREEN_TITLE);
+
+                final String action = cursor.getString(Index.COLUMN_INDEX_INTENT_ACTION);
+
+                final SettingsActivity sa = (SettingsActivity) getActivity();
+
+                sa.needToRevertToInitialFragment();
+
+                if (TextUtils.isEmpty(action)) {
+                    sa.startWithFragment(className, null, null, 0, screenTitle);
+                } else {
+                    final Intent intent = new Intent(action);
+
+                    final String targetPackage = cursor.getString(
+                            Index.COLUMN_INDEX_INTENT_ACTION_TARGET_PACKAGE);
+                    final String targetClass = cursor.getString(
+                            Index.COLUMN_INDEX_INTENT_ACTION_TARGET_CLASS);
+                    if (!TextUtils.isEmpty(targetPackage) && !TextUtils.isEmpty(targetClass)) {
+                        final ComponentName component =
+                                new ComponentName(targetPackage, targetClass);
+                        intent.setComponent(component);
+                    }
+
+                    sa.startActivity(intent);
+                }
+            }
+        });
+
+        return view;
+    }
+
+    public boolean onQueryTextSubmit(String query) {
+        updateSearchResults(query);
+        return true;
+    }
+
+    public boolean onClose() {
+        clearResults();
+        return false;
+    }
+
+    private void clearResults() {
+        if (mUpdateSearchResultsTask != null) {
+            mUpdateSearchResultsTask.cancel(false);
+            mUpdateSearchResultsTask = null;
+        }
+        setCursor(null);
+    }
+
+    private void setCursor(Cursor cursor) {
+        if (mAdapter == null) {
+            return;
+        }
+        Cursor oldCursor = mAdapter.swapCursor(cursor);
+        if (oldCursor != null) {
+            oldCursor.close();
+        }
+    }
+
+    private String getFilteredQueryString(CharSequence query) {
+        final StringBuilder filtered = new StringBuilder();
+        for (int n = 0; n < query.length(); n++) {
+            char c = query.charAt(n);
+            if (!Character.isLetterOrDigit(c) && !Character.isSpaceChar(c)) {
+                continue;
+            }
+            filtered.append(c);
+        }
+        return filtered.toString();
+    }
+
+    private void updateSearchResults(CharSequence cs) {
+        if (mUpdateSearchResultsTask != null) {
+            mUpdateSearchResultsTask.cancel(false);
+            mUpdateSearchResultsTask = null;
+        }
+        final String query = getFilteredQueryString(cs);
+        if (TextUtils.isEmpty(query)) {
+            setCursor(null);
+        } else {
+            mUpdateSearchResultsTask = new UpdateSearchResultsTask();
+            mUpdateSearchResultsTask.execute(query);
+        }
+    }
+
+    private static class SearchResult {
+        public String title;
+        public String summary;
+        public int iconResId;
+        public Context context;
+
+        public SearchResult(Context context, String title, String summary, int iconResId) {
+            this.context = context;
+            this.title = title;
+            this.summary = summary;
+            this.iconResId = iconResId;
+        }
+    }
+
+    private static class SearchResultsAdapter extends BaseAdapter {
+
+        private Cursor mCursor;
+        private LayoutInflater mInflater;
+        private boolean mDataValid;
+        private Context mContext;
+        private HashMap<String, Context> mContextMap = new HashMap<String, Context>();
+
+        public SearchResultsAdapter(Context context) {
+            mContext = context;
+            mInflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+            mDataValid = false;
+        }
+
+        public Cursor swapCursor(Cursor newCursor) {
+            if (newCursor == mCursor) {
+                return null;
+            }
+            Cursor oldCursor = mCursor;
+            mCursor = newCursor;
+            if (newCursor != null) {
+                mDataValid = true;
+                notifyDataSetChanged();
+            } else {
+                mDataValid = false;
+                notifyDataSetInvalidated();
+            }
+            return oldCursor;
+        }
+
+        @Override
+        public int getCount() {
+            if (!mDataValid || mCursor == null || mCursor.isClosed()) return 0;
+            return mCursor.getCount();
+        }
+
+        @Override
+        public Object getItem(int position) {
+            if (mDataValid && mCursor.moveToPosition(position)) {
+                final String title = mCursor.getString(Index.COLUMN_INDEX_TITLE);
+                final String summary = mCursor.getString(Index.COLUMN_INDEX_SUMMARY);
+                final String iconResStr = mCursor.getString(Index.COLUMN_INDEX_ICON);
+                final String className = mCursor.getString(
+                        Index.COLUMN_INDEX_CLASS_NAME);
+                final String packageName = mCursor.getString(
+                        Index.COLUMN_INDEX_INTENT_ACTION_TARGET_PACKAGE);
+
+                Context packageContext;
+                if (TextUtils.isEmpty(className) && !TextUtils.isEmpty(packageName)) {
+                    packageContext = mContextMap.get(packageName);
+                    if (packageContext == null) {
+                        try {
+                            packageContext = mContext.createPackageContext(packageName, 0);
+                        } catch (PackageManager.NameNotFoundException e) {
+                            Log.e(LOG_TAG, "Cannot create Context for package: " + packageName);
+                            return null;
+                        }
+                        mContextMap.put(packageName, packageContext);
+                    }
+                } else {
+                    packageContext = mContext;
+                }
+                final int iconResId = TextUtils.isEmpty(iconResStr) ?
+                        R.drawable.empty_icon : Integer.parseInt(iconResStr);
+                return new SearchResult(packageContext, title, summary, iconResId);
+            }
+            return null;
+        }
+
+        @Override
+        public long getItemId(int position) {
+            return 0;
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            if (!mDataValid && convertView == null) {
+                throw new IllegalStateException(
+                        "this should only be called when the cursor is valid");
+            }
+            if (!mCursor.moveToPosition(position)) {
+                throw new IllegalStateException("couldn't move cursor to position " + position);
+            }
+
+            View view;
+            TextView textTitle;
+            TextView textSummary;
+            ImageView imageView;
+
+            if (convertView == null) {
+                view = mInflater.inflate(R.layout.search_result_item, parent, false);
+            } else {
+                view = convertView;
+            }
+            textTitle = (TextView) view.findViewById(R.id.title);
+            textSummary = (TextView) view.findViewById(R.id.summary);
+            imageView = (ImageView) view.findViewById(R.id.icon);
+
+            SearchResult result = (SearchResult) getItem(position);
+
+            textTitle.setText(result.title);
+            textSummary.setText(result.summary);
+            if (result.iconResId != R.drawable.empty_icon) {
+                final Context packageContext = result.context;
+                final Drawable drawable;
+                try {
+                    drawable = packageContext.getDrawable(result.iconResId);
+                    imageView.setImageDrawable(drawable);
+                } catch (Resources.NotFoundException nfe) {
+                    // Not much we can do except logging
+                    Log.e(LOG_TAG, "Cannot load Drawable for " + result.title);
+                }
+                imageView.setBackgroundResource(R.color.background_search_result_icon);
+            } else {
+                imageView.setImageDrawable(null);
+                imageView.setBackgroundResource(R.drawable.empty_icon);
+            }
+
+            return view;
+        }
+    }
+}
diff --git a/src/com/android/settings/search/Index.java b/src/com/android/settings/search/Index.java
index 1a6bfb9..6ac5196 100644
--- a/src/com/android/settings/search/Index.java
+++ b/src/com/android/settings/search/Index.java
@@ -96,7 +96,7 @@
     private static Index sInstance;
     private final AtomicBoolean mIsAvailable = new AtomicBoolean(false);
     private final UpdateData mDataToProcess = new UpdateData();
-    private final Context mContext;
+    private Context mContext;
 
     /**
      * A private class to describe the update data for the Index database
@@ -124,6 +124,8 @@
     public static Index getInstance(Context context) {
         if (sInstance == null) {
             sInstance = new Index(context);
+        } else {
+            sInstance.setContext(context);
         }
         return sInstance;
     }
@@ -132,6 +134,10 @@
         mContext = context;
     }
 
+    public void setContext(Context context) {
+        mContext = context;
+    }
+
     public boolean isAvailable() {
         return mIsAvailable.get();
     }
@@ -675,6 +681,17 @@
         return (data != null) ? data.toString() : null;
     }
 
+    private int getResId(Context context, AttributeSet set, int[] attrs, int resId) {
+        final TypedArray sa = context.obtainStyledAttributes(set, attrs);
+        final TypedValue tv = sa.peekValue(resId);
+
+        if (tv != null && tv.type == TypedValue.TYPE_STRING) {
+            return tv.resourceId;
+        } else {
+            return 0;
+        }
+   }
+
     /**
      * A private class for updating the Index database
      */
diff --git a/src/com/android/settings/wifi/WifiEnabler.java b/src/com/android/settings/wifi/WifiEnabler.java
index ad0ba56..e41429b 100644
--- a/src/com/android/settings/wifi/WifiEnabler.java
+++ b/src/com/android/settings/wifi/WifiEnabler.java
@@ -38,7 +38,7 @@
 import java.util.concurrent.atomic.AtomicBoolean;
 
 public class WifiEnabler implements CompoundButton.OnCheckedChangeListener  {
-    private final Context mContext;
+    private Context mContext;
     private Switch mSwitch;
     private AtomicBoolean mConnected = new AtomicBoolean(false);
 
@@ -77,7 +77,8 @@
         mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
     }
 
-    public void resume() {
+    public void resume(Context context) {
+        mContext = context;
         // Wi-Fi state is sticky, so just let the receiver update UI
         mContext.registerReceiver(mReceiver, mIntentFilter);
         mSwitch.setOnCheckedChangeListener(this);
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index 667feb3..21fecd3 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -416,7 +416,7 @@
 
             if (activity instanceof SettingsActivity) {
                 SettingsActivity sa = (SettingsActivity) activity;
-                addSwitch = !sa.onIsHidingHeaders();
+                addSwitch = sa.onIsHidingHeaders();
             } else if (activity instanceof WifiPickerActivity) {
                 PreferenceActivity pa = (PreferenceActivity) activity;
                 addSwitch = pa.onIsHidingHeaders();
@@ -458,12 +458,13 @@
 
     @Override
     public void onResume() {
+        final Activity activity = getActivity();
         super.onResume();
         if (mWifiEnabler != null) {
-            mWifiEnabler.resume();
+            mWifiEnabler.resume(activity);
         }
 
-        getActivity().registerReceiver(mReceiver, mFilter);
+        activity.registerReceiver(mReceiver, mFilter);
         updateAccessPoints();
     }
 
@@ -497,11 +498,11 @@
             menu.add(Menu.NONE, MENU_ID_WPS_PBC, 0, R.string.wifi_menu_wps_pbc)
                     .setIcon(ta.getDrawable(1))
                     .setEnabled(wifiIsEnabled)
-                    .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
+                    .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
             menu.add(Menu.NONE, MENU_ID_ADD_NETWORK, 0, R.string.wifi_add_network)
                     .setIcon(ta.getDrawable(0))
                     .setEnabled(wifiIsEnabled)
-                    .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
+                    .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)