Merge "Don't put credentials in results from externally accessible activities"
diff --git a/res/drawable-nodpi/grass_tile.jpg b/res/drawable-nodpi/grass_tile.jpg
new file mode 100644
index 0000000..7aef32c
--- /dev/null
+++ b/res/drawable-nodpi/grass_tile.jpg
Binary files differ
diff --git a/res/drawable-nodpi/illustration_wifi.jpg b/res/drawable-nodpi/illustration_wifi.jpg
new file mode 100644
index 0000000..0c03199
--- /dev/null
+++ b/res/drawable-nodpi/illustration_wifi.jpg
Binary files differ
diff --git a/res/layout/preference_inputmethod_widget.xml b/res/drawable/grass.xml
similarity index 63%
copy from res/layout/preference_inputmethod_widget.xml
copy to res/drawable/grass.xml
index ee573ad..2fb5bd9 100644
--- a/res/layout/preference_inputmethod_widget.xml
+++ b/res/drawable/grass.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
+<!--
+     Copyright (C) 2014 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -14,11 +15,6 @@
      limitations under the License.
 -->
 
-<CheckBox
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+android:id/checkbox"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
-    android:layout_gravity="center"
-    android:focusable="false"
-    android:clickable="false"/>
\ No newline at end of file
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/grass_tile"
+    android:tileMode="repeat" />
diff --git a/res/layout-land/setup_preference.xml b/res/layout-land/setup_preference.xml
new file mode 100644
index 0000000..e79f5c1
--- /dev/null
+++ b/res/layout-land/setup_preference.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (c) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/fragment"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+    <FrameLayout
+        android:id="@+id/title_area"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:background="@drawable/grass">
+
+        <TextView
+            android:id="@+id/title"
+            style="@style/SetupTitle"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/wifi_setup_wizard_title" />
+    </FrameLayout>
+
+    <TextView
+        android:id="@+id/wifi_required_info"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginBottom="6dip"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:text="@string/wifi_required_info_text"
+        android:visibility="gone" />
+
+    <ListView
+        android:id="@android:id/list"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1"
+        android:cacheColorHint="@android:color/transparent"
+        android:clipToPadding="false"
+        android:drawSelectorOnTop="false"
+        android:headerDividersEnabled="false"
+        android:scrollbarAlwaysDrawVerticalTrack="true" />
+
+    <fragment android:name="com.android.setupwizard.navigationbar.SetupWizardNavBar"
+        android:id="@+id/navigation_bar"
+        style="@style/setup_wizard_navbar_style" />
+
+</LinearLayout>
+
diff --git a/res/layout/preference_inputmethod.xml b/res/layout/preference_inputmethod.xml
deleted file mode 100644
index 9e3d5e3..0000000
--- a/res/layout/preference_inputmethod.xml
+++ /dev/null
@@ -1,99 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
-    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
-    android:minHeight="?android:attr/listPreferredItemHeight"
-    android:gravity="center_vertical">
-
-    <LinearLayout
-        android:id="@+id/inputmethod_pref"
-        android:layout_width="wrap_content"
-        android:layout_height="match_parent"
-        android:layout_weight="1"
-        android:gravity="center_vertical"
-        android:clickable="true"
-        android:focusable="true"
-        android:background="?android:attr/selectableItemBackground">
-
-        <LinearLayout
-            android:id="@android:id/widget_frame"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:gravity="center_vertical"
-            android:orientation="vertical" />
-
-        <RelativeLayout
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginStart="15dip"
-            android:layout_marginEnd="6dip"
-            android:layout_marginTop="6dip"
-            android:layout_marginBottom="6dip"
-            android:layout_weight="1">
-
-            <TextView
-                android:id="@+android:id/title"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:singleLine="true"
-                android:textAppearance="?android:attr/textAppearanceMedium"
-                android:ellipsize="marquee"
-                android:fadingEdge="horizontal"/>
-
-            <TextView
-                android:id="@android:id/summary"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_below="@android:id/title"
-                android:layout_alignStart="@android:id/title"
-                android:paddingBottom="3dip"
-                android:visibility="gone"
-                android:textAppearance="?android:attr/textAppearanceSmall"
-                android:textSize="13sp"
-                android:textColor="?android:attr/textColorSecondary"
-                android:focusable="false"
-                android:maxLines="4" />
-
-        </RelativeLayout>
-
-    </LinearLayout>
-
-    <View
-        android:layout_width="2dip"
-        android:layout_height="match_parent"
-        android:layout_marginTop="5dip"
-        android:layout_marginBottom="5dip"
-        android:background="@android:drawable/divider_horizontal_dark" />
-
-    <ImageView
-        android:id="@+id/inputmethod_settings"
-        android:layout_width="wrap_content"
-        android:layout_height="fill_parent"
-        android:paddingStart="15dip"
-        android:paddingEnd="?android:attr/scrollbarSize"
-        android:src="@drawable/ic_sysbar_quicksettings"
-        android:contentDescription="@string/input_method_settings_button"
-        android:layout_gravity="center"
-        android:clickable="true"
-        android:focusable="true"
-        android:background="?android:attr/selectableItemBackground" />
-
-</LinearLayout>
diff --git a/res/layout/preference_spellchecker.xml b/res/layout/preference_spellchecker.xml
index dd35cb3..6408976 100644
--- a/res/layout/preference_spellchecker.xml
+++ b/res/layout/preference_spellchecker.xml
@@ -13,9 +13,9 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
+
 <LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/pref_all"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:paddingStart="?android:attr/listPreferredItemPaddingStart"
@@ -33,16 +33,17 @@
         android:focusable="true"
         android:background="?android:attr/selectableItemBackground">
 
-        <RadioButton
-            android:id="@+id/pref_radio"
+        <LinearLayout
+            android:id="@android:id/widget_frame"
             android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:clickable="false"
-            android:focusable="false" />
+            android:layout_height="match_parent"
+            android:gravity="center_vertical"
+            android:orientation="vertical" />
 
         <RelativeLayout
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
+            android:layout_marginStart="15dip"
             android:layout_marginEnd="6dip"
             android:layout_marginTop="6dip"
             android:layout_marginBottom="6dip"
@@ -52,10 +53,10 @@
                 android:id="@+android:id/title"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:maxLines="2"
+                android:singleLine="true"
                 android:textAppearance="?android:attr/textAppearanceMedium"
                 android:ellipsize="marquee"
-                android:fadingEdge="horizontal" />
+                android:fadingEdge="horizontal"/>
 
             <TextView
                 android:id="@android:id/summary"
@@ -63,46 +64,19 @@
                 android:layout_height="wrap_content"
                 android:layout_below="@android:id/title"
                 android:layout_alignStart="@android:id/title"
+                android:paddingBottom="3dip"
                 android:visibility="gone"
                 android:textAppearance="?android:attr/textAppearanceSmall"
                 android:textSize="13sp"
                 android:textColor="?android:attr/textColorSecondary"
+                android:focusable="false"
                 android:maxLines="4" />
 
         </RelativeLayout>
 
     </LinearLayout>
 
-    <LinearLayout
-        android:id="@+id/pref_right_button1"
-        android:layout_width="wrap_content"
-        android:layout_height="match_parent"
-        android:gravity="center_vertical"
-        android:clickable="true"
-        android:focusable="true"
-        android:background="?android:attr/selectableItemBackground"
-        android:contentDescription="@string/spellchecker_quick_settings" >
-
-        <View
-            android:layout_width="2dip"
-            android:layout_height="match_parent"
-            android:layout_marginTop="5dip"
-            android:layout_marginBottom="5dip"
-            android:background="@android:drawable/divider_horizontal_dark" />
-
-        <ImageView
-            android:layout_width="40dip"
-            android:layout_height="fill_parent"
-            android:paddingStart="5dip"
-            android:paddingEnd="5dip"
-            android:src="@drawable/ic_sysbar_quicksettings"
-            android:layout_gravity="center"
-            android:contentDescription="@string/spellchecker_quick_settings" />
-
-    </LinearLayout>
-
     <View
-        android:id="@+id/pref_right_separator2"
         android:layout_width="2dip"
         android:layout_height="match_parent"
         android:layout_marginTop="5dip"
@@ -110,16 +84,16 @@
         android:background="@android:drawable/divider_horizontal_dark" />
 
     <ImageView
-        android:id="@+id/pref_right_button2"
-        android:layout_width="40dip"
+        android:id="@+id/pref_right_button"
+        android:layout_width="wrap_content"
         android:layout_height="fill_parent"
-        android:paddingStart="5dip"
-        android:paddingEnd="5dip"
-        android:src="@drawable/ic_menu_3d_globe"
-        android:layout_gravity="end"
+        android:paddingStart="15dip"
+        android:paddingEnd="?android:attr/scrollbarSize"
+        android:src="@drawable/ic_sysbar_quicksettings"
+        android:contentDescription="@string/input_method_settings_button"
+        android:layout_gravity="center"
         android:clickable="true"
         android:focusable="true"
-        android:background="?android:attr/selectableItemBackground"
-        android:contentDescription="@string/spellchecker_language" />
+        android:background="?android:attr/selectableItemBackground" />
 
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
diff --git a/res/layout/preference_inputmethod_widget.xml b/res/layout/preference_spellchecker_widget.xml
similarity index 78%
rename from res/layout/preference_inputmethod_widget.xml
rename to res/layout/preference_spellchecker_widget.xml
index ee573ad..e4971ec 100644
--- a/res/layout/preference_inputmethod_widget.xml
+++ b/res/layout/preference_spellchecker_widget.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
+<!-- Copyright (C) 2014 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -14,11 +14,10 @@
      limitations under the License.
 -->
 
-<CheckBox
+<RadioButton
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+android:id/checkbox"
+    android:id="@+id/pref_radio"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
-    android:layout_gravity="center"
-    android:focusable="false"
-    android:clickable="false"/>
\ No newline at end of file
+    android:clickable="false"
+    android:focusable="false" />
\ No newline at end of file
diff --git a/res/layout/setup_preference.xml b/res/layout/setup_preference.xml
index c5d686f..46829c0 100644
--- a/res/layout/setup_preference.xml
+++ b/res/layout/setup_preference.xml
@@ -16,142 +16,34 @@
 ** limitations under the License.
 */
 -->
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/fragment"
-    android:orientation="vertical"
+    android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:layout_width="match_parent">
-    <view
-        class="com.android.settings.widget.ProportionalOuterFrame"
+    android:orientation="vertical">
+
+    <TextView
+        android:id="@+id/wifi_required_info"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginBottom="6dip"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:text="@string/wifi_required_info_text"
+        android:visibility="gone" />
+
+    <com.android.settings.widget.StickyHeaderListView
+        android:id="@android:id/list"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
         android:layout_weight="1"
-        android:layout_height="match_parent"
-        android:layout_width="match_parent">
+        android:cacheColorHint="@android:color/transparent"
+        android:clipToPadding="false"
+        android:drawSelectorOnTop="false"
+        android:headerDividersEnabled="false"
+        android:scrollbarAlwaysDrawVerticalTrack="true" />
 
-        <RelativeLayout
-            android:id="@+id/title_area"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_alignParentTop="true"
-            android:gravity="bottom">
-
-            <LinearLayout
-                android:id="@+id/title_bar"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:gravity="bottom"
-                android:orientation="horizontal">
-                <TextView
-                    android:id="@+id/title"
-                    android:layout_width="0dip"
-                    android:layout_height="wrap_content"
-                    android:layout_weight="1.0"
-                    style="@style/SetupTitle"
-                    android:text="@string/wifi_setup_wizard_title"
-                    android:gravity="bottom" />
-
-                <ImageButton
-                    android:id="@+id/more"
-                    android:layout_width="@dimen/setup_button_size"
-                    android:layout_height="@dimen/setup_button_size"
-                    android:layout_marginStart="8dip"
-                    android:layout_marginEnd="8dip"
-                    android:layout_marginBottom="8dip"
-                    android:src="?attr/ic_menu_moreoverflow"
-                    android:background="?android:attr/actionBarItemBackground"
-                    android:contentDescription="@string/wifi_menu_more_options" />
-
-            </LinearLayout>
-
-            <!-- Divider -->
-            <View
-                android:id="@+id/top_divider"
-                style="@style/TopDivider"
-                android:layout_below="@id/title_bar" />
-
-        </RelativeLayout>
-
-        <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:layout_below="@id/title_area"
-            android:background="@android:color/transparent"
-            android:orientation="vertical" >
-
-            <TextView
-                android:id="@+id/wifi_required_info"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_marginBottom="6dip"
-                android:textAppearance="?android:attr/textAppearanceMedium"
-                android:text="@string/wifi_required_info_text"
-                android:visibility="gone" />
-
-            <ListView
-                android:id="@android:id/list"
-                android:layout_width="match_parent"
-                android:layout_height="0px"
-                android:layout_weight="1"
-                android:cacheColorHint="@android:color/transparent"
-                android:clipToPadding="false"
-                android:drawSelectorOnTop="false"
-                android:paddingTop="0dip"
-                android:scrollbarAlwaysDrawVerticalTrack="true" />
-
-            <TextView
-                android:id="@android:id/empty"
-                android:layout_width="match_parent"
-                android:layout_height="0px"
-                android:layout_weight="1"
-                android:gravity="center"
-                android:visibility="gone" />
-
-            <ImageView
-                android:id="@+id/divider"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/setup_item_margin"
-                android:background="@*android:drawable/list_divider_holo_dark" />
-
-            <LinearLayout
-                android:id="@+id/other_network"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_marginBottom="@dimen/setup_item_margin"
-                android:background="?android:attr/selectableItemBackground"
-                android:gravity="center_vertical"
-                android:minHeight="?android:attr/listPreferredItemHeight"
-                android:paddingEnd="?android:attr/scrollbarSize" >
-
-                <ImageView
-                    android:id="@+id/add_icon"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_gravity="center"
-                    android:src="?attr/ic_menu_add" />
-
-                <TextView
-                    android:id="@+id/other"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_marginBottom="6dip"
-                    android:layout_marginStart="15dip"
-                    android:layout_marginEnd="6dip"
-                    android:layout_marginTop="6dip"
-                    android:layout_weight="1"
-                    android:ellipsize="marquee"
-                    android:fadingEdge="horizontal"
-                    android:singleLine="true"
-                    android:textAppearance="?android:attr/textAppearanceMedium"
-                    android:text="@string/wifi_other_network" />
-
-            </LinearLayout>
-
-        </LinearLayout>
-    </view>
     <fragment android:name="com.android.setupwizard.navigationbar.SetupWizardNavBar"
         android:id="@+id/navigation_bar"
-        style="@style/setup_wizard_navbar_style"
-        android:layout_weight="0"
-        />
+        style="@style/setup_wizard_navbar_style" />
+
 </LinearLayout>
diff --git a/res/layout/setup_wifi_add_network.xml b/res/layout/setup_wifi_add_network.xml
new file mode 100644
index 0000000..c62f983
--- /dev/null
+++ b/res/layout/setup_wifi_add_network.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/other_network"
+    android:layout_width="match_parent"
+    android:layout_height="@dimen/setup_add_network_item_height"
+    android:background="?android:attr/selectableItemBackground"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart" >
+
+    <TextView
+        style="@style/SetupAddWifiNetwork"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:text="@string/wifi_other_network" />
+
+</LinearLayout>
diff --git a/res/layout/setup_wizard_header.xml b/res/layout/setup_wizard_header.xml
new file mode 100644
index 0000000..e2e2b0e
--- /dev/null
+++ b/res/layout/setup_wizard_header.xml
@@ -0,0 +1,35 @@
+<?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.
+-->
+
+<com.android.settings.widget.SetupWizardHeader
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/title_area"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:background="@drawable/grass"
+    android:foreground="@drawable/illustration_wifi"
+    android:tag="stickyContainer">
+
+    <TextView
+        android:id="@+id/title"
+        style="@style/SetupTitle"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:tag="sticky"
+        android:text="@string/wifi_setup_wizard_title"/>
+
+</com.android.settings.widget.SetupWizardHeader>
diff --git a/res/values-sw600dp/dimens.xml b/res/values-sw600dp/dimens.xml
index ffd6ac0..d35d973 100755
--- a/res/values-sw600dp/dimens.xml
+++ b/res/values-sw600dp/dimens.xml
@@ -24,12 +24,7 @@
     <dimen name="content_margin_left">16dip</dimen>
     <dimen name="description_margin_top">26dip</dimen>
     <dimen name="crypt_clock_size">120sp</dimen>
-    <dimen name="setup_title_size">60dp</dimen>
-    <item type="dimen" name="setup_title_height">20%</item>
-    <item type="dimen" name="setup_border_width">10%</item>
-    <dimen name="setup_margin_bottom">0dip</dimen>
-    <dimen name="setup_button_size">48dip</dimen>
-    <dimen name="setup_item_margin">32dip</dimen>
+    <dimen name="setup_title_size">24sp</dimen>
     <dimen name="appwidget_min_width">325dip</dimen>
     <dimen name="appwidget_min_height">50dip</dimen>
 
diff --git a/res/values/colors.xml b/res/values/colors.xml
index ed1b3d3..0b3ea39 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -39,6 +39,7 @@
     <color name="title_color">@android:color/holo_blue_light</color>
     <color name="setup_divider_color_dark">#33ffffff</color>
     <color name="setup_divider_color_light">#33000000</color>
+    <color name="setup_add_wifi_network_text_color">#ff009587</color>
 
     <color name="circle_avatar_frame_color">#ffffffff</color>
     <color name="circle_avatar_frame_shadow_color">#80000000</color>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 992e57f..969f575 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -38,12 +38,17 @@
 
     <dimen name="crypt_clock_size">100sp</dimen>
 
-    <item type="dimen" name="setup_title_height">15%</item>
-    <item type="dimen" name="setup_border_width">5%</item>
     <dimen name="setup_margin_bottom">0dip</dimen>
-    <dimen name="setup_title_size">25dp</dimen>
-    <dimen name="setup_button_size">32dip</dimen>
-    <dimen name="setup_item_margin">16dip</dimen>
+    <dimen name="setup_title_size">24sp</dimen>
+    <dimen name="setup_title_margin_bottom">16dp</dimen>
+    <!-- This is the extra spacing required to make the leading exactly 32sp -->
+    <dimen name="setup_title_line_spacing_extra">3.67sp</dimen>
+    <dimen name="setup_title_padding_bottom">2dp</dimen>
+    <dimen name="setup_title_padding_top">16dp</dimen>
+    <!-- Size of padding to give in the wifi list when there is no icon -->
+    <dimen name="setup_list_no_icon_padding">56dp</dimen>
+    <dimen name="setup_add_network_item_height">56dp</dimen>
+    <dimen name="setup_wizard_margin_sides">40dp</dimen>
 
     <dimen name="divider_height">3dip</dimen>
     <dimen name="divider_margin_top">6dip</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index b52f40d..afceaf2 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -44,7 +44,7 @@
 
     <!-- Category headings in left-pane header menu --> <skip />
     <!-- Settings main menu category heading. Wireless and networks (Wi-Fi, Bluetooth, data usage...). [CHAR LIMIT=40] -->
-    <string name="header_category_wireless_networks">Wireless &amp; Networks</string>
+    <string name="header_category_wireless_networks">Wireless &amp; networks</string>
     <!-- Settings main menu category heading. Device (Sound, display, battery, applications...). [CHAR LIMIT=40] -->
     <string name="header_category_device">Device</string>
     <!-- Settings main menu category heading. Personal (Accounts, security, language, backup...). [CHAR LIMIT=40] -->
@@ -265,6 +265,8 @@
     <!-- Bluetooth settings.  Message for disconnecting from all profiles of a bluetooth device. [CHAR LIMIT=NONE] -->
     <string name="bluetooth_disconnect_all_profiles">This will end your connection with:&lt;br>&lt;b><xliff:g id="device_name">%1$s</xliff:g>&lt;/b></string>
 
+    <!-- Bluetooth Visibility message.  This message informs the user that their device is now visible to other bluetooth devices.  [CHAR LIMIT=50] -->
+    <string name="bluetooth_is_visible_message"><xliff:g id="device_name">%1$s</xliff:g> is now visible to nearby devices.</string>
     <!-- Bluetooth broadcasting settings, option to enable/disable broadcasting -->
     <string name="bluetooth_broadcasting">Broadcasting</string>
     <!-- Bluetooth settings.  Dialog title to disable a single profile of a device. [CHAR LIMIT=40] -->
@@ -306,6 +308,8 @@
     <string name="bluetooth_notif_message">Touch to pair with <xliff:g id="device_name">%1$s</xliff:g>.</string>
     <!-- Bluetooth settings screen, menu to show the list of received files [CHAR LIMIT=30] -->
     <string name="bluetooth_show_received_files">Show received files</string>
+    <!-- Bluetooth settings screen, menu to show the list of email accounts to pull messages from [CHAR LIMIT=30] -->
+    <string name="bluetooth_show_message_access">Message access</string>
 
     <!-- Strings for BluetoothDevicePicker -->
     <string name="device_picker">Bluetooth device chooser</string>
@@ -316,6 +320,8 @@
     <!-- Strings for asking to the user whether to allow an app to enable bluetooth -->
     <string name="bluetooth_ask_enablement">An app wants to turn on Bluetooth.</string>
 
+    <!-- String for informing the user that bluetooth devices must be granted permission. [CHAR LIMIT=100] -->
+    <string name="bluetooth_message_access_notice">Bluetooth devices must ask for permission before accessing available accounts.</string>
     <!-- Strings for asking to the user whether to allow an app to enable discovery mode -->
     <string name="bluetooth_ask_discovery" product="tablet">An app wants to make your tablet visible to other Bluetooth devices for <xliff:g id="timeout">%1$d</xliff:g> seconds.</string>
     <!-- Strings for asking to the user whether to allow an app to enable discovery mode -->
@@ -1099,13 +1105,15 @@
     <!-- Bluetooth settings: The title of the preference (list item) that initiates a scan for devices -->
     <string name="bluetooth_preference_scan_title">Scan for devices</string>
     <!-- Bluetooth settings: The title of the action button that initiates a search for nearby devices [CHAR LIMIT=20] -->
-    <string name="bluetooth_search_for_devices">Search for devices</string>
+    <string name="bluetooth_search_for_devices">Refresh</string>
     <!-- Bluetooth settings: The title of the action button while a search for nearby devices is in progress [CHAR LIMIT=20] -->
     <string name="bluetooth_searching_for_devices">Searching\u2026</string>
     <!-- Bluetooth settings: The sub heading for device settings. [CHAR LIMIT=30] -->
     <string name="bluetooth_preference_device_settings">Device settings</string>
     <!-- Bluetooth settings: The sub heading for devices which have already been paired with this device. [CHAR LIMIT=40] -->
     <string name="bluetooth_preference_paired_devices">Paired devices</string>
+    <!-- Bluetooth settings: The sub heading for messaging accesses. [CHAR LIMIT=50] -->
+    <string name="bluetooth_message_access">Paired devices can view messages from</string>
     <!-- Bluetooth settings: The sub heading for available devices during and after scanning. [CHAR LIMIT=40] -->
     <string name="bluetooth_preference_found_devices">Available devices</string>
     <!-- Bluetooth settings.  Context menu item for a device.  Action will connect to all profiles on the device. -->
@@ -1375,7 +1383,7 @@
     <!-- Wifi Settings. text displayed when user has restriction DISALLOW_CONFIG_WIFI [CHAR LIMIT=NONE]-->
     <string name="wifi_empty_list_user_restricted">You don\'t have permission to change the Wi\u2011Fi network.</string>
     <!-- Wi-Fi settings. title for setup other network button [CHAR LIMIT=35]-->
-    <string name="wifi_other_network">Other network\u2026</string>
+    <string name="wifi_other_network">Add another network</string>
     <!-- Wi-Fi settings. content description for more button [CHAR LIMIT=50]-->
     <string name="wifi_more">More</string>
     <!-- Wi-Fi settings. wps menu title [CHAR LIMIT=25]-->
@@ -5130,8 +5138,32 @@
     <!-- Text used to identify the search results -->
     <string name="search_results_label">Results</string>
 
-    <!--Search Keywords-->
+    <!--Search Keywords [CHAR_LIMIT=NONE]-->
     <string name="keywords_wifi">wifi wi-fi network connection</string>
+    <string name="keywords_more_default_sms_app">text message</string>
+    <string name="keywords_more_mobile_networks">cellular cell carrier wireless</string>
+    <string name="keywords_display">screen touchscreen</string>
+    <string name="keywords_display_brightness_level">dim screen touchscreen</string>
+    <string name="keywords_display_auto_brightness">dim screen touchscreen</string>
+    <string name="keywords_display_wallpaper">background</string>
+    <string name="keywords_display_font_size">text size</string>
+    <string name="keywords_display_cast_screen">project</string>
+    <string name="keywords_storage">space disk hard drive</string>
+    <string name="keywords_battery">power</string>
+    <string name="keywords_spell_checker">spelling</string>
+    <string name="keywords_text_to_speech_output">rate language default speak speaking</string>
+    <string name="keywords_date_and_time">clock</string>
+    <string name="keywords_factory_data_reset">wipe delete</string>
+    <string name="keywords_printing">printer</string>
+    <string name="keywords_sounds_and_notifications">speaker beep</string>
+    <string name="keywords_sounds_and_notifications_interruptions">dont don\'t disturb interrupt interruption break</string>
+    <string name="keywords_app">RAM</string>
+    <string name="keywords_location">nearby location history reporting</string>
+    <string name="keywords_location_mode">accuracy</string>
+    <string name="keywords_accounts">account</string>
+    <string name="keywords_users">restriction restrict restricted</string>
+    <string name="keywords_keyboard_and_ime">text correction correct sound vibrate auto language gesture suggest suggestion theme offensive word type emoji</string>
+    <string name="keywords_search_voice">language hands-free hand free recognition offensive word audio history bluetooth headset</string>
 
     <!-- NFC Wi-Fi pairing/setup strings-->
 
@@ -5157,7 +5189,7 @@
     <!-- Sounds and Notification -->
 
     <!-- Sound & notification: Settings header. [CHAR LIMIT=20] -->
-    <string name="notification_settings">Sound &amp; Notification</string>
+    <string name="notification_settings">Sound &amp; notification</string>
 
     <!-- Sound & notification > Sound section: Title for the option managing media volume. [CHAR LIMIT=30] -->
     <string name="media_volume_option_title">Media volume</string>
@@ -5242,7 +5274,7 @@
     <!-- Sound & notification > Other sounds: Title for the option enabling haptic feedback on touch. [CHAR LIMIT=30] -->
     <string name="vibrate_on_touch_title">Vibrate on touch</string>
 
-    <!-- Sound & notification > Other sounds: Title for the option enabling dock audio media. [CHAR LIMIT=30] -->
+    <!-- Sound & notification > Other sounds: Title for the option enabling dock audio media. [CHAR LIMIT=50] -->
     <string name="dock_audio_media_title">Dock speaker plays</string>
 
     <!-- Sound & notification > Other sounds: Value for the dock audio media with value 0: disabled. [CHAR LIMIT=30] -->
@@ -5345,7 +5377,7 @@
     <!-- [CHAR LIMIT=40] Zen mode settings: Important category text -->
     <string name="zen_mode_important_category">Priority interruptions</string>
 
-    <!-- [CHAR LIMIT=40] Zen mode settings: Downtime category text -->
+    <!-- [CHAR LIMIT=60] Zen mode settings: Downtime category text -->
     <string name="zen_mode_downtime_category">Downtime (priority interruptions only)</string>
 
     <!-- [CHAR LIMIT=40] Zen mode settings: Downtime days option title -->
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 0f7e652..cea615e 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -152,11 +152,26 @@
     </style>
 
     <style name="SetupTitle">
-        <item name="android:fontFamily">sans-serif-light</item>
-        <item name="android:textSize">@dimen/setup_title_size</item>
-        <item name="android:textColor">@color/title_color</item>
+        <item name="android:layout_marginBottom">@dimen/setup_title_margin_bottom</item>
+        <item name="android:layout_marginEnd">@dimen/setup_wizard_margin_sides</item>
+        <item name="android:layout_marginStart">@dimen/setup_wizard_margin_sides</item>
         <item name="android:clickable">false</item>
+        <item name="android:fontFamily">sans-serif</item>
+        <item name="android:lineSpacingExtra">@dimen/setup_title_line_spacing_extra</item>
         <item name="android:longClickable">false</item>
+        <item name="android:textColor">@android:color/white</item>
+        <item name="android:textSize">@dimen/setup_title_size</item>
+        <item name="android:paddingBottom">@dimen/setup_title_padding_bottom</item>
+        <item name="android:paddingTop">@dimen/setup_title_padding_top</item>
+    </style>
+
+    <style name="SetupAddWifiNetwork">
+        <item name="android:fontFamily">sans-serif-medium</item>
+        <item name="android:gravity">start|center_vertical</item>
+        <item name="android:paddingStart">@dimen/setup_list_no_icon_padding</item>
+        <item name="android:textAllCaps">true</item>
+        <item name="android:textAppearance">@android:style/TextAppearance.Small</item>
+        <item name="android:textColor">@color/setup_add_wifi_network_text_color</item>
     </style>
 
     <style name="wifi_item">
diff --git a/res/values/themes.xml b/res/values/themes.xml
index 3583f84..4e80612 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -22,29 +22,35 @@
     <attr name="wifi_signal" format="reference" />
 
     <style name="SetupWizardWifiTheme" parent="android:Theme.Material.NoActionBar">
+        <item name="android:alertDialogTheme">@style/Theme.WifiDialog</item>
+        <item name="android:listPreferredItemPaddingEnd">@dimen/setup_wizard_margin_sides</item>
+        <item name="android:listPreferredItemPaddingStart">@dimen/setup_wizard_margin_sides</item>
+        <item name="android:windowBackground">?android:attr/colorBackground</item>
         <item name="android:windowSoftInputMode">adjustPan</item>
         <item name="@*android:preferencePanelStyle">@*android:style/PreferencePanel.Dialog</item>
-        <item name="android:alertDialogTheme">@style/Theme.WifiDialog</item>
         <item name="ic_menu_add">@drawable/ic_menu_add_dark</item>
         <item name="ic_menu_moreoverflow">@*android:drawable/ic_menu_moreoverflow_material</item>
         <item name="ic_wps">@drawable/ic_wps_dark</item>
         <item name="setup_divider_color">@color/setup_divider_color_dark</item>
-        <item name="wifi_signal">@drawable/wifi_signal_dark</item>
         <item name="switchBarMarginStart">0dip</item>
         <item name="switchBarMarginEnd">0dip</item>
+        <item name="wifi_signal">@drawable/wifi_signal_dark</item>
     </style>
 
     <style name="SetupWizardWifiTheme.Light" parent="android:Theme.Material.Light.NoActionBar">
+        <item name="android:alertDialogTheme">@style/Theme.Light.WifiDialog</item>
+        <item name="android:listPreferredItemPaddingEnd">@dimen/setup_wizard_margin_sides</item>
+        <item name="android:listPreferredItemPaddingStart">@dimen/setup_wizard_margin_sides</item>
+        <item name="android:windowBackground">?android:attr/colorBackground</item>
         <item name="android:windowSoftInputMode">adjustPan</item>
         <item name="@*android:preferencePanelStyle">@*android:style/PreferencePanel.Dialog</item>
-        <item name="android:alertDialogTheme">@style/Theme.Light.WifiDialog</item>
         <item name="ic_menu_add">@drawable/ic_menu_add_light</item>
         <item name="ic_menu_moreoverflow">@*android:drawable/ic_menu_moreoverflow_material</item>
         <item name="ic_wps">@drawable/ic_wps_light</item>
         <item name="setup_divider_color">@color/setup_divider_color_light</item>
-        <item name="wifi_signal">@drawable/wifi_signal_light</item>
         <item name="switchBarMarginStart">0dip</item>
         <item name="switchBarMarginEnd">0dip</item>
+        <item name="wifi_signal">@drawable/wifi_signal_light</item>
     </style>
 
     <style name="Theme.WifiDialog" parent="@*android:style/Theme.Material.Dialog.Alert">
diff --git a/res/xml/account_settings.xml b/res/xml/account_settings.xml
index 236a26d..7437b80 100644
--- a/res/xml/account_settings.xml
+++ b/res/xml/account_settings.xml
@@ -15,8 +15,10 @@
 -->
 
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+                  xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
         android:key="account"
-        android:title="@string/account_settings_title">
+        android:title="@string/account_settings_title"
+        settings:keywords="@string/keywords_accounts">
 
         <Preference
             android:key="add_account"
diff --git a/res/xml/bluetooth_message_access.xml b/res/xml/bluetooth_message_access.xml
new file mode 100644
index 0000000..d1da132
--- /dev/null
+++ b/res/xml/bluetooth_message_access.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+        android:title="@string/bluetooth_show_message_access">
+
+    <PreferenceCategory
+            android:key="accounts"
+            android:title="@string/bluetooth_message_access" />
+
+    <Preference
+            android:key="notice"
+            android:title=""
+            android:textAppearance="?android:attr/textAppearanceSmall"
+            android:textColor="?android:attr/colorForegroundInverse"
+            android:selectable="false"
+            android:summary="@string/bluetooth_message_access_notice" />
+
+</PreferenceScreen>
diff --git a/res/xml/date_time_prefs.xml b/res/xml/date_time_prefs.xml
index 1e7ac58..5bf3c9a 100644
--- a/res/xml/date_time_prefs.xml
+++ b/res/xml/date_time_prefs.xml
@@ -15,36 +15,46 @@
 -->
 
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
-        android:title="@string/date_and_time">
+                  xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
+        android:title="@string/date_and_time"
+        settings:keywords="@string/keywords_date_and_time">
+
     <CheckBoxPreference android:key="auto_time"
         android:title="@string/date_time_auto"
         android:summaryOn="@string/date_time_auto_summaryOn"
         android:summaryOff="@string/date_time_auto_summaryOff"
         />
+
     <CheckBoxPreference android:key="auto_zone"
         android:title="@string/zone_auto"
         android:summaryOn="@string/zone_auto_summaryOn"
         android:summaryOff="@string/zone_auto_summaryOff"
         />
+
     <Preference android:key="date"
         android:title="@string/date_time_set_date"
         android:summary="03/10/2008"
         />
+
     <Preference android:key="time"
         android:title="@string/date_time_set_time"
         android:summary="12:00am"
         />
+
     <PreferenceScreen
         android:fragment="com.android.settings.ZonePicker"
         android:key="timezone"
         android:title="@string/date_time_set_timezone"
         android:summary="GMT-8:00"
         />
+
     <CheckBoxPreference android:key="24 hour"
         android:title="@string/date_time_24hour"
         />
+
     <ListPreference
         android:key="date_format"
         android:title="@string/date_time_date_format"
         android:summary="mm/dd/yyyy"/>
+
 </PreferenceScreen>
diff --git a/res/xml/device_info_memory.xml b/res/xml/device_info_memory.xml
index e4ea1cc..38cc94a 100644
--- a/res/xml/device_info_memory.xml
+++ b/res/xml/device_info_memory.xml
@@ -15,7 +15,9 @@
 -->
 
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
-        android:title="@string/storage_settings">
+                  xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
+        android:title="@string/storage_settings"
+        settings:keywords="@string/keywords_storage">
 
 <!-- Preference categories are dynamically created based on the list of available storage volumes -->
 
diff --git a/res/xml/display_settings.xml b/res/xml/display_settings.xml
index 4a8211f..3c4f4af 100644
--- a/res/xml/display_settings.xml
+++ b/res/xml/display_settings.xml
@@ -15,23 +15,27 @@
 -->
 
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+                  xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
         android:title="@string/display_settings"
-        xmlns:settings="http://schemas.android.com/apk/res/com.android.settings">
+        settings:keywords="@string/keywords_display">
 
         <com.android.settings.BrightnessPreference
                 android:key="brightness"
                 android:title="@string/brightness"
+                settings:keywords="@string/keywords_display_brightness_level"
                 android:persistent="false"/>
 
         <CheckBoxPreference
                 android:key="auto_brightness"
                 android:title="@string/auto_brightness_title"
+                settings:keywords="@string/keywords_display_auto_brightness"
                 android:summary="@string/auto_brightness_summary"
                 android:persistent="false" />
 
         <PreferenceScreen
                 android:key="wallpaper"
                 android:title="@string/wallpaper_settings_title"
+                settings:keywords="@string/keywords_display_wallpaper"
                 android:fragment="com.android.settings.WallpaperTypeSettings" />
 
         <ListPreference
@@ -50,6 +54,7 @@
         <com.android.settings.WarnedListPreference
                 android:key="font_size"
                 android:title="@string/title_font_size"
+                settings:keywords="@string/keywords_display_font_size"
                 android:summary="@string/summary_font_size"
                 android:entries="@array/entries_font_size"
                 android:entryValues="@array/entryvalues_font_size"
@@ -58,6 +63,7 @@
         <PreferenceScreen
                 android:key="wifi_display"
                 android:title="@string/wifi_display_settings_title"
+                settings:keywords="@string/keywords_display_cast_screen"
                 android:fragment="com.android.settings.wfd.WifiDisplaySettings" />
 
 </PreferenceScreen>
diff --git a/res/xml/language_settings.xml b/res/xml/language_settings.xml
index d8e7603..b493a0f 100644
--- a/res/xml/language_settings.xml
+++ b/res/xml/language_settings.xml
@@ -15,33 +15,47 @@
 -->
 
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
+                  xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
+        android:key="language_keyboard_settings"
         android:title="@string/language_keyboard_settings_title">
 
     <PreferenceScreen
-            android:fragment="com.android.settings.LocalePicker"
             android:key="phone_language"
-            android:title="@string/phone_language"/>
+            android:title="@string/phone_language"
+            android:fragment="com.android.settings.LocalePicker"
+            />
 
-    <com.android.settings.inputmethod.SpellCheckersPreference
+    <!-- Spell checker preference title, summary and fragment will be set programmatically. -->
+    <!-- Note: Mark this as persistent="false" to remove unnecessarily saved shared preference.
+         See: InputMethodAndSubtypeUtil.removeUnnecessaryNonPersistentPreference. -->
+    <PreferenceScreen
             android:key="spellcheckers_settings"
-            android:title="@string/spellcheckers_settings_title"/>
+            android:title="@string/spellcheckers_settings_title"
+            settings:keywords="@string/keywords_spell_checker"
+            android:persistent="false"
+            />
 
     <!-- User dictionary preference title and fragment will be set programmatically. -->
     <PreferenceScreen
             android:key="key_user_dictionary_settings"
-            android:title="@string/user_dict_settings_title" />
+            android:title="@string/user_dict_settings_title"
+            />
 
     <PreferenceCategory
             android:key="keyboard_settings_category"
-            android:title="@string/keyboard_settings_category">
+            android:title="@string/keyboard_settings_category"
+            settings:keywords="@string/keywords_keyboard_and_ime">
+
         <!-- An intent for this preference will be populated programmatically. -->
         <PreferenceScreen
                 android:key="choose_input_methods"
-                android:title="@string/choose_input_methods" />
+                android:title="@string/choose_input_methods"
+                />
+
         <PreferenceScreen
                 android:key="current_input_method"
-                android:title="@string/current_input_method" />
+                android:title="@string/current_input_method"
+                />
         <!-- Enabled input method list will be populated programmatically here. -->
     </PreferenceCategory>
 
@@ -58,66 +72,93 @@
                 android:summaryOn="@string/auto_replace_summary"
                 android:summaryOff="@string/auto_replace_summary"
                 android:order="1000"
-                android:persistent="false"/>
+                android:persistent="false"
+                />
+
         <CheckBoxPreference
                 android:key="auto_caps"
                 android:title="@string/auto_caps"
                 android:summaryOn="@string/auto_caps_summary"
                 android:summaryOff="@string/auto_caps_summary"
                 android:order="1001"
-                android:persistent="false"/>
+                android:persistent="false"
+                />
+
         <CheckBoxPreference
                 android:key="auto_punctuate"
                 android:title="@string/auto_punctuate"
                 android:summaryOn="@string/auto_punctuate_summary"
                 android:summaryOff="@string/auto_punctuate_summary"
                 android:order="1002"
-                android:persistent="false"/>
+                android:persistent="false"
+                />
+
     </PreferenceCategory>
 
-    <PreferenceCategory android:key="voice_category"
+    <PreferenceCategory
+            android:key="voice_category"
             android:title="@string/voice_category" >
 
         <!-- entries, entryValues, and defaultValue will be populated programmatically. -->
         <ListPreference
                 android:key="voice_interactor"
                 android:title="@string/voice_interactor_title"
-                android:dialogTitle="@string/voice_interactor_title" />
+                android:dialogTitle="@string/voice_interactor_title"
+                />
 
         <!-- An intent for this preference will be populated programmatically. -->
-        <PreferenceScreen android:key="voice_interactor_settings"
-                android:title="@string/voice_interactor_settings_title" />
+        <PreferenceScreen
+                android:key="voice_interactor_settings"
+                android:title="@string/voice_interactor_settings_title"
+                />
 
         <!-- entries, entryValues, and defaultValue will be populated programmatically. -->
         <ListPreference
                 android:key="recognizer"
                 android:title="@string/recognizer_title"
-                android:dialogTitle="@string/recognizer_title" />
+                android:dialogTitle="@string/recognizer_title"
+                />
 
         <!-- An intent for this preference will be populated programmatically. -->
-        <PreferenceScreen android:key="recognizer_settings"
-                android:title="@string/recognizer_settings_title" />
+        <PreferenceScreen
+                android:key="recognizer_settings"
+                android:title="@string/recognizer_settings_title"
+                settings:keywords="@string/keywords_search_voice"
+                />
 
-        <PreferenceScreen android:key="tts_settings"
+        <PreferenceScreen
+                android:key="tts_settings"
+                android:title="@string/tts_settings_title"
+                settings:keywords="@string/keywords_text_to_speech_output"
                 android:fragment="com.android.settings.tts.TextToSpeechSettings"
-                android:title="@string/tts_settings_title" />
+                />
+
     </PreferenceCategory>
 
-    <PreferenceCategory android:key="pointer_settings_category"
+    <PreferenceCategory
+            android:key="pointer_settings_category"
             android:title="@string/pointer_settings_category">
+
         <com.android.settings.PointerSpeedPreference
                 android:key="pointer_speed"
                 android:title="@string/pointer_speed"
-                android:dialogTitle="@string/pointer_speed" />
+                android:dialogTitle="@string/pointer_speed"
+                />
+
     </PreferenceCategory>
 
-    <PreferenceCategory android:key="game_controller_settings_category"
+    <PreferenceCategory
+            android:key="game_controller_settings_category"
             android:title="@string/game_controller_settings_category">
+
         <CheckBoxPreference
                 android:key="vibrate_input_devices"
                 android:title="@string/vibrate_input_devices"
                 android:summaryOn="@string/vibrate_input_devices_summary"
                 android:summaryOff="@string/vibrate_input_devices_summary"
-                android:persistent="false"/>
+                android:persistent="false"
+                />
+
     </PreferenceCategory>
+
 </PreferenceScreen>
diff --git a/res/xml/location_settings.xml b/res/xml/location_settings.xml
index 83b80b1..994ddf1 100644
--- a/res/xml/location_settings.xml
+++ b/res/xml/location_settings.xml
@@ -15,10 +15,15 @@
 -->
 
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
-        android:title="@string/location_settings_title">
+                  xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
+        android:key="location_settings"
+        android:title="@string/location_settings_title"
+        settings:keywords="@string/keywords_location">
+
         <Preference
             android:key="location_mode"
             android:title="@string/location_mode_title"
+            settings:keywords="@string/keywords_location_mode"
             android:summary="@string/location_mode_location_off_title" />
 
         <PreferenceCategory
diff --git a/res/xml/notification_settings.xml b/res/xml/notification_settings.xml
index af9ab6c..f077e85 100644
--- a/res/xml/notification_settings.xml
+++ b/res/xml/notification_settings.xml
@@ -15,9 +15,10 @@
 -->
 
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+                  xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
         android:title="@string/notification_settings"
         android:key="notification_settings"
-        xmlns:settings="http://schemas.android.com/apk/res/com.android.settings">
+        settings:keywords="@string/keywords_sounds_and_notifications">
 
     <PreferenceCategory
         android:key="sound"
@@ -57,6 +58,7 @@
         <PreferenceScreen
                 android:key="zen_mode"
                 android:title="@string/zen_mode_settings_title"
+                settings:keywords="@string/keywords_sounds_and_notifications_interruptions"
                 android:fragment="com.android.settings.notification.ZenModeSettings" />
 
         <!-- Phone ringtone -->
diff --git a/res/xml/power_usage_summary.xml b/res/xml/power_usage_summary.xml
index 44e40bd..0622513 100644
--- a/res/xml/power_usage_summary.xml
+++ b/res/xml/power_usage_summary.xml
@@ -15,6 +15,8 @@
 -->
 
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+                  xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
         android:title="@string/power_usage_summary_title"
+        settings:keywords="@string/keywords_battery"
         android:key="app_list">
 </PreferenceScreen>
diff --git a/res/xml/print_settings.xml b/res/xml/print_settings.xml
index 8a29563..3a00f71 100644
--- a/res/xml/print_settings.xml
+++ b/res/xml/print_settings.xml
@@ -15,8 +15,9 @@
 -->
 
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
-        android:title="@string/print_settings_title">
+                  xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
+        android:title="@string/print_settings_title"
+        settings:keywords="@string/keywords_printing">
 
     <PreferenceCategory
             android:key="print_jobs_category"
diff --git a/res/xml/privacy_settings.xml b/res/xml/privacy_settings.xml
index 20aa68e..99fdc3f 100644
--- a/res/xml/privacy_settings.xml
+++ b/res/xml/privacy_settings.xml
@@ -15,16 +15,19 @@
 -->
 
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+                  xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
         android:title="@string/privacy_settings_title">
 
     <PreferenceCategory android:key="backup_category"
             android:title="@string/backup_section_title">
+
         <!-- Backup settings -->
         <CheckBoxPreference
                 android:key="backup_data"
                 android:title="@string/backup_data_title"
                 android:summary="@string/backup_data_summary"
                 android:persistent="false" />
+
         <PreferenceScreen
                 android:key="configure_account"
                 android:title="@string/backup_configure_account_title"
@@ -33,20 +36,25 @@
             <!-- the Intent declared here is always overwritten by a real one -->
             <intent android:action="dummy" />
         </PreferenceScreen>
+
         <CheckBoxPreference
                 android:key="auto_restore"
                 android:title="@string/auto_restore_title"
                 android:summary="@string/auto_restore_summary"
                 android:persistent="false" />
+
     </PreferenceCategory>
 
     <PreferenceCategory android:key="personal_data_category"
             android:title="@string/personal_data_section_title">
+
         <!-- Factory reset -->
         <PreferenceScreen
             android:title="@string/master_clear_title"
             android:summary="@string/master_clear_summary"
+            settings:keywords="@string/keywords_factory_data_reset"
             android:fragment="com.android.settings.MasterClear" />
+
     </PreferenceCategory>
 
 </PreferenceScreen>
diff --git a/res/xml/spellchecker_prefs.xml b/res/xml/spellchecker_prefs.xml
index 1de0493..666b0a9 100644
--- a/res/xml/spellchecker_prefs.xml
+++ b/res/xml/spellchecker_prefs.xml
@@ -14,7 +14,11 @@
      limitations under the License.
 -->
 
-<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
-        android:title="@string/spellcheckers_settings_title">
-
+<PreferenceScreen
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:title="@string/spellcheckers_settings_title">
+    <Preference
+        android:key="spellchecker_language"
+        android:title="@string/phone_language"
+        android:persistent="false" />
 </PreferenceScreen>
diff --git a/res/xml/wireless_settings.xml b/res/xml/wireless_settings.xml
index bf1523e..ac5a7be 100644
--- a/res/xml/wireless_settings.xml
+++ b/res/xml/wireless_settings.xml
@@ -15,7 +15,9 @@
 -->
 
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
-        android:title="@string/radio_controls_title">
+                  xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
+        android:title="wireless_settings"
+        android:key="@string/radio_controls_title">
 
     <CheckBoxPreference
         android:key="toggle_airplane"
@@ -26,6 +28,7 @@
     <com.android.settings.AppListPreference
         android:key="sms_application"
         android:title="@string/sms_application_title"
+        settings:keywords="@string/keywords_more_default_sms_app"
         android:summary="%s"
         android:persistent="false" />
 
@@ -53,6 +56,7 @@
     <PreferenceScreen
         android:key="mobile_network_settings"
         android:title="@string/network_settings_title"
+        settings:keywords="@string/keywords_more_mobile_networks"
         android:dependency="toggle_airplane">
         <intent
             android:action="android.intent.action.MAIN"
diff --git a/src/com/android/settings/DevelopmentSettings.java b/src/com/android/settings/DevelopmentSettings.java
index 4c2b90d..0e04298 100644
--- a/src/com/android/settings/DevelopmentSettings.java
+++ b/src/com/android/settings/DevelopmentSettings.java
@@ -290,6 +290,7 @@
         mEnableOemUnlock = findAndInitCheckboxPref(ENABLE_OEM_UNLOCK);
         if (!showEnableOemUnlockPreference()) {
             removePreference(mEnableOemUnlock);
+            mEnableOemUnlock = null;
         }
         mAllowMockLocation = findAndInitCheckboxPref(ALLOW_MOCK_LOCATION);
         mPassword = (PreferenceScreen) findPreference(LOCAL_BACKUP_PASSWORD);
@@ -510,7 +511,9 @@
                 Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0) != 0);
         updateCheckBox(mBtHciSnoopLog, Settings.Secure.getInt(cr,
                 Settings.Secure.BLUETOOTH_HCI_LOG, 0) != 0);
-        updateCheckBox(mEnableOemUnlock, Utils.isOemUnlockEnabled(getActivity()));
+        if (mEnableOemUnlock != null) {
+            updateCheckBox(mEnableOemUnlock, Utils.isOemUnlockEnabled(getActivity()));
+        }
         updateCheckBox(mAllowMockLocation, Settings.Secure.getInt(cr,
                 Settings.Secure.ALLOW_MOCK_LOCATION, 0) != 0);
         updateHdcpValues();
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index b0d3241..4675bb2 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -76,6 +76,7 @@
 import com.android.settings.applications.ManageApplications;
 import com.android.settings.applications.ProcessStatsUi;
 import com.android.settings.bluetooth.BluetoothSettings;
+import com.android.settings.bluetooth.MessageAccessSettings;
 import com.android.settings.dashboard.DashboardCategory;
 import com.android.settings.dashboard.DashboardSummary;
 import com.android.settings.dashboard.DashboardTile;
@@ -237,6 +238,7 @@
             AdvancedWifiSettings.class.getName(),
             SavedAccessPointsWifiSettings.class.getName(),
             BluetoothSettings.class.getName(),
+            MessageAccessSettings.class.getName(),
             TetherSettings.class.getName(),
             WifiP2pSettings.class.getName(),
             VpnSettings.class.getName(),
diff --git a/src/com/android/settings/accounts/AuthenticatorHelper.java b/src/com/android/settings/accounts/AuthenticatorHelper.java
index 1d79479..e74c8d5 100644
--- a/src/com/android/settings/accounts/AuthenticatorHelper.java
+++ b/src/com/android/settings/accounts/AuthenticatorHelper.java
@@ -102,7 +102,8 @@
         if (mTypeToAuthDescription.containsKey(accountType)) {
             try {
                 AuthenticatorDescription desc = mTypeToAuthDescription.get(accountType);
-                Context authContext = context.createPackageContext(desc.packageName, 0);
+                Context authContext = context.createPackageContextAsUser(desc.packageName, 0,
+                        mUserHandle);
                 icon = mUm.getBadgedDrawableForUser(
                         authContext.getResources().getDrawable(desc.iconId), mUserHandle);
                 synchronized (mAccTypeIconCache) {
@@ -128,7 +129,8 @@
         if (mTypeToAuthDescription.containsKey(accountType)) {
             try {
                 AuthenticatorDescription desc = mTypeToAuthDescription.get(accountType);
-                Context authContext = context.createPackageContext(desc.packageName, 0);
+                Context authContext = context.createPackageContextAsUser(desc.packageName, 0,
+                        mUserHandle);
                 label = authContext.getResources().getText(desc.labelId);
             } catch (PackageManager.NameNotFoundException e) {
                 Log.w(TAG, "No label name for account type " + accountType);
diff --git a/src/com/android/settings/bluetooth/BluetoothSettings.java b/src/com/android/settings/bluetooth/BluetoothSettings.java
index f329c3d..0bcac62 100755
--- a/src/com/android/settings/bluetooth/BluetoothSettings.java
+++ b/src/com/android/settings/bluetooth/BluetoothSettings.java
@@ -18,8 +18,6 @@
 
 import static android.os.UserManager.DISALLOW_CONFIG_BLUETOOTH;
 
-import android.app.ActionBar;
-import android.app.Activity;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
 import android.content.BroadcastReceiver;
@@ -33,12 +31,10 @@
 import android.preference.PreferenceGroup;
 import android.preference.PreferenceScreen;
 import android.util.Log;
-import android.view.Gravity;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
-import android.widget.Switch;
 import android.widget.TextView;
 
 import com.android.settings.R;
@@ -61,15 +57,14 @@
 
     private static final int MENU_ID_SCAN = Menu.FIRST;
     private static final int MENU_ID_RENAME_DEVICE = Menu.FIRST + 1;
-    private static final int MENU_ID_VISIBILITY_TIMEOUT = Menu.FIRST + 2;
-    private static final int MENU_ID_SHOW_RECEIVED = Menu.FIRST + 3;
+    private static final int MENU_ID_SHOW_RECEIVED = Menu.FIRST + 2;
+    private static final int MENU_ID_MESSAGE_ACCESS = Menu.FIRST + 3;
 
     /* Private intent to show the list of received files */
     private static final String BTOPP_ACTION_OPEN_RECEIVED_FILES =
             "android.btopp.intent.action.OPEN_RECEIVED_FILES";
 
     private BluetoothEnabler mBluetoothEnabler;
-    private BluetoothDiscoverableEnabler mDiscoverableEnabler;
 
     private PreferenceGroup mPairedDevicesCategory;
     private PreferenceGroup mAvailableDevicesCategory;
@@ -145,13 +140,13 @@
         }
         super.onResume();
 
-        if (mDiscoverableEnabler != null) {
-            mDiscoverableEnabler.resume(getActivity());
-        }
         getActivity().registerReceiver(mReceiver, mIntentFilter);
         if (mLocalAdapter != null) {
             updateContent(mLocalAdapter.getBluetoothState(), mActivityStarted);
         }
+
+        // Make the device visible to other devices.
+        mLocalAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
     }
 
     @Override
@@ -161,9 +156,9 @@
             mBluetoothEnabler.pause();
         }
         getActivity().unregisterReceiver(mReceiver);
-        if (mDiscoverableEnabler != null) {
-            mDiscoverableEnabler.pause();
-        }
+
+        // Make the device only visible to connected devices.
+        mLocalAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE);
     }
 
     @Override
@@ -182,11 +177,14 @@
         menu.add(Menu.NONE, MENU_ID_RENAME_DEVICE, 0, R.string.bluetooth_rename_device)
                 .setEnabled(bluetoothIsEnabled)
                 .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
-        menu.add(Menu.NONE, MENU_ID_VISIBILITY_TIMEOUT, 0, R.string.bluetooth_visibility_timeout)
-                .setEnabled(bluetoothIsEnabled)
-                .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
         menu.add(Menu.NONE, MENU_ID_SHOW_RECEIVED, 0, R.string.bluetooth_show_received_files)
                 .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
+        // Message Access API is still not finished, once completed we undo this check.
+        // Bug 16232864
+        if (android.os.SystemProperties.get("show_bluetooth_message_access").equals("true")){
+            menu.add(Menu.NONE, MENU_ID_MESSAGE_ACCESS, 0, R.string.bluetooth_show_message_access)
+                    .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
+        }
         super.onCreateOptionsMenu(menu, inflater);
     }
 
@@ -204,15 +202,18 @@
                         getFragmentManager(), "rename device");
                 return true;
 
-            case MENU_ID_VISIBILITY_TIMEOUT:
-                new BluetoothVisibilityTimeoutFragment().show(
-                        getFragmentManager(), "visibility timeout");
-                return true;
-
             case MENU_ID_SHOW_RECEIVED:
                 Intent intent = new Intent(BTOPP_ACTION_OPEN_RECEIVED_FILES);
                 getActivity().sendBroadcast(intent);
                 return true;
+
+            case MENU_ID_MESSAGE_ACCESS:
+                if (getActivity() instanceof SettingsActivity) {
+                    ((SettingsActivity) getActivity()).startPreferencePanel(
+                            MessageAccessSettings.class.getCanonicalName(), null,
+                            R.string.bluetooth_show_message_access, null, this, 0);
+                }
+                return true;
         }
         return super.onOptionsItemSelected(item);
     }
@@ -251,30 +252,6 @@
                 preferenceScreen.setOrderingAsAdded(true);
                 mDevicePreferenceMap.clear();
 
-                // This device
-                if (mMyDevicePreference == null) {
-                    mMyDevicePreference = new Preference(getActivity());
-                }
-                mMyDevicePreference.setTitle(mLocalAdapter.getName());
-                if (getResources().getBoolean(com.android.internal.R.bool.config_voice_capable)) {
-                    mMyDevicePreference.setIcon(R.drawable.ic_bt_cellphone);    // for phones
-                } else {
-                    mMyDevicePreference.setIcon(R.drawable.ic_bt_laptop);   // for tablets, etc.
-                }
-                mMyDevicePreference.setPersistent(false);
-                mMyDevicePreference.setEnabled(true);
-                preferenceScreen.addPreference(mMyDevicePreference);
-
-                if (!isRestrictedAndNotPinProtected()) {
-                    if (mDiscoverableEnabler == null) {
-                        mDiscoverableEnabler = new BluetoothDiscoverableEnabler(mLocalAdapter,
-                                mMyDevicePreference);
-                        mDiscoverableEnabler.resume(getActivity());
-                        LocalBluetoothManager.getInstance(getActivity()).setDiscoverableEnabler(
-                                mDiscoverableEnabler);
-                    }
-                }
-
                 // Paired devices category
                 if (mPairedDevicesCategory == null) {
                     mPairedDevicesCategory = new PreferenceCategory(getActivity());
@@ -286,13 +263,10 @@
                         BluetoothDeviceFilter.BONDED_DEVICE_FILTER);
                 int numberOfPairedDevices = mPairedDevicesCategory.getPreferenceCount();
 
-                if (mDiscoverableEnabler != null) {
-                    mDiscoverableEnabler.setNumberOfPairedDevices(numberOfPairedDevices);
-                }
-
                 // Available devices category
                 if (mAvailableDevicesCategory == null) {
                     mAvailableDevicesCategory = new BluetoothProgressCategory(getActivity());
+                    mAvailableDevicesCategory.setSelectable(false);
                 } else {
                     mAvailableDevicesCategory.removeAll();
                 }
@@ -320,6 +294,16 @@
                         }
                     }
                 }
+
+                if (mMyDevicePreference == null) {
+                    mMyDevicePreference = new Preference(getActivity());
+                }
+                mMyDevicePreference.setSummary(getResources().getString(
+                            R.string.bluetooth_is_visible_message, mLocalAdapter.getName()));
+                mMyDevicePreference.setSelectable(false);
+                mMyDevicePreference.setEnabled(false);
+                preferenceScreen.addPreference(mMyDevicePreference);
+
                 getActivity().invalidateOptionsMenu();
                 return; // not break
 
@@ -355,6 +339,7 @@
         getActivity().invalidateOptionsMenu();
     }
 
+    @Override
     public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) {
         setDeviceListGroup(getPreferenceScreen());
         removeAllDevices();
@@ -433,5 +418,4 @@
                 return result;
             }
         };
-
 }
diff --git a/src/com/android/settings/bluetooth/MessageAccessSettings.java b/src/com/android/settings/bluetooth/MessageAccessSettings.java
new file mode 100644
index 0000000..bef59c8
--- /dev/null
+++ b/src/com/android/settings/bluetooth/MessageAccessSettings.java
@@ -0,0 +1,166 @@
+/*
+ * 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.bluetooth;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.app.ActivityManagerNative;
+import android.content.Context;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.preference.SwitchPreference;
+import android.preference.Preference;
+import android.preference.PreferenceGroup;
+import android.preference.PreferenceScreen;
+import android.provider.SearchIndexableResource;
+import android.util.Log;
+
+import com.android.settings.accounts.AuthenticatorHelper;
+import com.android.settings.R;
+import com.android.settings.SettingsPreferenceFragment;
+import com.android.settings.Utils;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.search.Indexable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class MessageAccessSettings extends SettingsPreferenceFragment
+        implements AuthenticatorHelper.OnAccountsUpdateListener, Indexable {
+    private static final String TAG = "MessageAccessSettings";
+    private static final String GMAIL_PACKAGE_NAME = "com.google.android.gm";
+    private static final String EMAIL_PACKAGE_NAME = "com.google.android.email";
+
+    private Account[] mAccounts;
+    private UserHandle mUserHandle;
+    private PreferenceGroup mAvailableAccounts;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mUserHandle = Utils.getProfileToDisplay(ActivityManagerNative.getDefault(),
+                getActivity().getActivityToken(), savedInstanceState);
+
+        addPreferencesFromResource(R.xml.bluetooth_message_access);
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        initPreferences();
+    }
+
+    @Override
+    public void onAccountsUpdate(final UserHandle userHandle) {
+        mAccounts = AccountManager.get(getActivity()).getAccountsAsUser(
+                mUserHandle.getIdentifier());
+
+        final int mAccountsSize = mAccounts.length;
+        for (int i = 0; i < mAccountsSize; ++i){
+            Log.d(TAG, String.format("account.type = %s\n", mAccounts[i].type));
+        }
+    }
+
+    /**
+     * Retrieves the email icon for a given account's email preference
+     *
+     * @param accountPref The user's account to retrieve the icon from.
+     *
+     * @return The drawable representing the icon of the user's email preference
+     **/
+    private Drawable getIcon(AccountPreference accountPref){
+        Drawable icon = null;
+
+        // Currently only two types of icons are allowed.
+        final String packageName = accountPref.account.type.equals("com.google")
+                ? GMAIL_PACKAGE_NAME : EMAIL_PACKAGE_NAME;
+
+        try{
+            icon = getPackageManager().getApplicationIcon(packageName);
+        }catch(NameNotFoundException nnfe){
+            icon = null;
+        }
+
+        return icon;
+    }
+
+    private void initPreferences() {
+        final PreferenceScreen preferenceScreen = getPreferenceScreen();
+        mAvailableAccounts = (PreferenceGroup)preferenceScreen.findPreference("accounts");
+        mAccounts = AccountManager.get(getActivity()).getAccountsAsUser(
+                mUserHandle.getIdentifier());
+
+        final int mAccountsSize = mAccounts.length;
+        for (int i = 0; i < mAccountsSize; ++i){
+            AccountPreference accountPref = new AccountPreference(getActivity(), mAccounts[i]);
+            Drawable icon = getIcon(accountPref);
+            if (icon != null){
+                accountPref.setIcon(icon);
+            }
+            mAvailableAccounts.addPreference(accountPref);
+        }
+    }
+
+    private class AccountPreference extends SwitchPreference
+            implements Preference.OnPreferenceChangeListener{
+        private Account account;
+
+        AccountPreference(Context context, Account account){
+            super(context);
+            this.account = account;
+            setTitle(account.type);
+            setSummary(account.name);
+
+            setOnPreferenceChangeListener(this);
+        }
+
+        @Override
+        public boolean onPreferenceChange(Preference preference, Object val) {
+            if (preference instanceof AccountPreference){
+                final AccountPreference accountPref = (AccountPreference) preference;
+
+                if (((Boolean)val).booleanValue()){
+                    // Enable paired deviced to connect, fill in once API is available
+                    Log.w(TAG, String.format(
+                                "User has turned on '%s' for Bluetooth message access.",
+                                accountPref.account.name));
+                } else {
+                    // Disable paired deviced to connect, fill in once API is available
+                    Log.w(TAG, String.format(
+                                "User has turned off '%s' for Bluetooth message access.",
+                                accountPref.account.name));
+                }
+            }
+            return true;
+        }
+    }
+
+    public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+        new BaseSearchIndexProvider() {
+            @Override
+            public List<SearchIndexableResource> getXmlResourcesToIndex(
+                    Context context, boolean enabled) {
+                List<SearchIndexableResource> indexables = new ArrayList<SearchIndexableResource>();
+                SearchIndexableResource indexable = new SearchIndexableResource(context);
+                indexable.xmlResId = R.xml.bluetooth_message_access;
+                indexables.add(indexable);
+                return indexables;
+            }
+        };
+}
diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
index 1159a2c..70e9176 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
@@ -45,6 +45,8 @@
 import com.android.settings.SettingsActivity;
 
 import java.util.List;
+import java.util.ArrayList;
+import java.util.Collections;
 
 /**
  * Displays a list of apps and subsystems that consume power, ordered by how much power was
@@ -72,8 +74,10 @@
 
     private int mStatsType = BatteryStats.STATS_SINCE_CHARGED;
 
-    private static final int MIN_POWER_THRESHOLD = 5;
+    private static final int MIN_POWER_THRESHOLD_MILLI_AMP = 5;
     private static final int MAX_ITEMS_TO_LIST = 10;
+    private static final int MIN_AVERAGE_POWER_THRESHOLD_MILLI_AMP = 10;
+    private static final int SECONDS_IN_HOUR = 60 * 60;
 
     private BatteryStatsHelper mStatsHelper;
 
@@ -241,43 +245,52 @@
     private void refreshStats() {
         mAppListGroup.removeAll();
         mAppListGroup.setOrderingAsAdded(false);
-
-        mStatsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED, UserHandle.myUserId());
-
-        mHistPref = new BatteryHistoryPreference(
-                getActivity(), mStatsHelper.getStats(), mStatsHelper.getBatteryBroadcast());
+        mHistPref = new BatteryHistoryPreference(getActivity(), mStatsHelper.getStats(),
+                mStatsHelper.getBatteryBroadcast());
         mHistPref.setOrder(-1);
         mAppListGroup.addPreference(mHistPref);
-
-        if (mStatsHelper.getPowerProfile().getAveragePower(
-                PowerProfile.POWER_SCREEN_FULL) < 10) {
-            addNotAvailableMessage();
-            return;
-        }
         boolean addedSome = false;
-        final int dischargeAmount = mStatsHelper.getStats().getDischargeAmount(mStatsType);
-        List<BatterySipper> usageList = mStatsHelper.getUsageList();
-        for (int i=0; i<usageList.size(); i++) {
-            BatterySipper sipper = usageList.get(i);
-            if ((sipper.value*60*60) < MIN_POWER_THRESHOLD) continue;
-            final double percentOfTotal =
-                    ((sipper.value / mStatsHelper.getTotalPower()) * dischargeAmount);
-            if (((int)(percentOfTotal+.5)) < 1) continue;
-            BatteryEntry entry = new BatteryEntry(getActivity(), mHandler, mUm, sipper);
-            PowerGaugePreference pref =
-                    new PowerGaugePreference(getActivity(), entry.getIcon(), entry);
-            final double percentOfMax =
-                    (sipper.value * 100) / mStatsHelper.getMaxPower();
-            sipper.percent = percentOfTotal;
-            pref.setTitle(entry.getLabel());
-            pref.setOrder(i+1);
-            pref.setPercent(percentOfMax, percentOfTotal);
-            if (sipper.uidObj != null) {
-                pref.setKey(Integer.toString(sipper.uidObj.getUid()));
+
+        PowerProfile powerProfile = mStatsHelper.getPowerProfile();
+        final double averagePower = powerProfile.getAveragePower(PowerProfile.POWER_SCREEN_FULL);
+        if (averagePower >= MIN_AVERAGE_POWER_THRESHOLD_MILLI_AMP) {
+            final List<UserHandle> profiles = mUm.getUserProfiles();
+
+            mStatsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED, profiles);
+
+            final List<BatterySipper> usageList = mStatsHelper.getUsageList();
+
+            final int dischargeAmount = mStatsHelper.getStats().getDischargeAmount(mStatsType);
+            final int numSippers = usageList.size();
+            for (int i = 0; i < numSippers; i++) {
+                final BatterySipper sipper = usageList.get(i);
+                if ((sipper.value * SECONDS_IN_HOUR) < MIN_POWER_THRESHOLD_MILLI_AMP) {
+                    continue;
+                }
+                final double percentOfTotal =
+                        ((sipper.value / mStatsHelper.getTotalPower()) * dischargeAmount);
+                if (((int) (percentOfTotal + .5)) < 1) {
+                    continue;
+                }
+                final UserHandle userHandle = new UserHandle(UserHandle.getUserId(sipper.getUid()));
+                final BatteryEntry entry = new BatteryEntry(getActivity(), mHandler, mUm, sipper);
+                final PowerGaugePreference pref = new PowerGaugePreference(getActivity(),
+                        mUm.getBadgedDrawableForUser(entry.getIcon(), userHandle), entry);
+
+                final double percentOfMax = (sipper.value * 100) / mStatsHelper.getMaxPower();
+                sipper.percent = percentOfTotal;
+                pref.setTitle(entry.getLabel());
+                pref.setOrder(i + 1);
+                pref.setPercent(percentOfMax, percentOfTotal);
+                if (sipper.uidObj != null) {
+                    pref.setKey(Integer.toString(sipper.uidObj.getUid()));
+                }
+                addedSome = true;
+                mAppListGroup.addPreference(pref);
+                if (mAppListGroup.getPreferenceCount() > (MAX_ITEMS_TO_LIST + 1)) {
+                    break;
+                }
             }
-            addedSome = true;
-            mAppListGroup.addPreference(pref);
-            if (mAppListGroup.getPreferenceCount() > (MAX_ITEMS_TO_LIST+1)) break;
         }
         if (!addedSome) {
             addNotAvailableMessage();
diff --git a/src/com/android/settings/inputmethod/CheckBoxAndSettingsPreference.java b/src/com/android/settings/inputmethod/CheckBoxAndSettingsPreference.java
deleted file mode 100644
index c6208ed..0000000
--- a/src/com/android/settings/inputmethod/CheckBoxAndSettingsPreference.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (C) 2011 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.inputmethod;
-
-import com.android.settings.R;
-import com.android.settings.SettingsPreferenceFragment;
-import com.android.settings.Utils;
-
-import android.content.Context;
-import android.content.Intent;
-import android.preference.CheckBoxPreference;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-// TODO: Make this non-persistent.
-class CheckBoxAndSettingsPreference extends CheckBoxPreference {
-
-    private SettingsPreferenceFragment mFragment;
-    private TextView mTitleText;
-    private TextView mSummaryText;
-    private ImageView mSettingsButton;
-    private Intent mSettingsIntent;
-
-    public CheckBoxAndSettingsPreference(Context context) {
-        this(context, null);
-    }
-
-    public CheckBoxAndSettingsPreference(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public CheckBoxAndSettingsPreference(Context context, AttributeSet attrs, int defStyleAttr) {
-        this(context, attrs, defStyleAttr, 0);
-    }
-
-    public CheckBoxAndSettingsPreference(Context context, AttributeSet attrs, int defStyleAttr,
-            int defStyleRes) {
-        super(context, attrs, defStyleAttr, defStyleRes);
-
-        setLayoutResource(R.layout.preference_inputmethod);
-        setWidgetLayoutResource(R.layout.preference_inputmethod_widget);
-    }
-
-    @Override
-    protected void onBindView(View view) {
-        super.onBindView(view);
-        View textLayout = view.findViewById(R.id.inputmethod_pref);
-        textLayout.setOnClickListener(
-                new OnClickListener() {
-                    @Override
-                    public void onClick(View arg0) {
-                        onCheckBoxClicked();
-                    }
-                });
-
-        mSettingsButton = (ImageView) view.findViewById(R.id.inputmethod_settings);
-        mTitleText = (TextView)view.findViewById(android.R.id.title);
-        mSummaryText = (TextView)view.findViewById(android.R.id.summary);
-        mSettingsButton.setOnClickListener(
-                new OnClickListener() {
-                    @Override
-                    public void onClick(View clickedView) {
-                        onSettingsButtonClicked();
-                    }
-                });
-        enableSettingsButton();
-    }
-
-    @Override
-    public void setEnabled(boolean enabled) {
-        super.setEnabled(enabled);
-        enableSettingsButton();
-    }
-
-    public void setFragmentIntent(SettingsPreferenceFragment fragment, Intent intent) {
-        mFragment = fragment;
-        mSettingsIntent = intent;
-    }
-
-    protected void onCheckBoxClicked() {
-        if (isChecked()) {
-            setChecked(false);
-        } else {
-            setChecked(true);
-        }
-    }
-
-    protected void onSettingsButtonClicked() {
-        if (mFragment != null && mSettingsIntent != null) {
-            mFragment.startActivity(mSettingsIntent);
-        }
-    }
-
-    private void enableSettingsButton() {
-        if (mSettingsButton != null) {
-            if (mSettingsIntent == null) {
-                mSettingsButton.setVisibility(View.GONE);
-            } else {
-                final boolean checked = isChecked();
-                mSettingsButton.setEnabled(checked);
-                mSettingsButton.setClickable(checked);
-                mSettingsButton.setFocusable(checked);
-                if (!checked) {
-                    mSettingsButton.setAlpha(Utils.DISABLED_ALPHA);
-                }
-            }
-        }
-        if (mTitleText != null) {
-            mTitleText.setEnabled(true);
-        }
-        if (mSummaryText != null) {
-            mSummaryText.setEnabled(true);
-        }
-    }
-}
diff --git a/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java b/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java
index 073daa6..4166dbb 100644
--- a/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java
+++ b/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java
@@ -48,10 +48,11 @@
 import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodManager;
 import android.view.inputmethod.InputMethodSubtype;
+import android.view.textservice.SpellCheckerInfo;
+import android.view.textservice.TextServicesManager;
 
 import com.android.settings.R;
 import com.android.settings.Settings.KeyboardLayoutPickerActivity;
-import com.android.settings.Settings.SpellCheckersSettingsActivity;
 import com.android.settings.SettingsActivity;
 import com.android.settings.SettingsPreferenceFragment;
 import com.android.settings.SubSettings;
@@ -72,7 +73,8 @@
 public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment
         implements Preference.OnPreferenceChangeListener, InputManager.InputDeviceListener,
         KeyboardLayoutDialogFragment.OnSetupKeyboardLayoutsListener, Indexable,
-        InputMethodPreference.onSavePreferenceListener {
+        InputMethodPreference.OnSavePreferenceListener {
+    private static final String KEY_SPELL_CHECKERS = "spellcheckers_settings";
     private static final String KEY_PHONE_LANGUAGE = "phone_language";
     private static final String KEY_CHOOSE_INPUT_METHODS = "choose_input_methods";
     private static final String KEY_CURRENT_INPUT_METHOD = "current_input_method";
@@ -171,12 +173,17 @@
         updateInputDevices();
 
         // Spell Checker
-        final SpellCheckersPreference scp = ((SpellCheckersPreference)findPreference(
-                "spellcheckers_settings"));
-        if (scp != null) {
+        final Preference spellChecker = findPreference(KEY_SPELL_CHECKERS);
+        if (spellChecker != null) {
+            // Note: KEY_SPELL_CHECKERS preference is marked as persistent="false" in XML.
+            InputMethodAndSubtypeUtil.removeUnnecessaryNonPersistentPreference(spellChecker);
             final Intent intent = new Intent(Intent.ACTION_MAIN);
-            intent.setClass(activity, SpellCheckersSettingsActivity.class);
-            scp.setFragmentIntent(this, intent);
+            intent.setClass(activity, SubSettings.class);
+            intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT,
+                    SpellCheckersSettings.class.getName());
+            intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_TITLE_RESID,
+                    R.string.spellcheckers_settings_title);
+            spellChecker.setIntent(intent);
         }
 
         mHandler = new Handler();
@@ -239,6 +246,18 @@
         mSettingsObserver.resume();
         mIm.registerInputDeviceListener(this, null);
 
+        final Preference spellChecker = findPreference(KEY_SPELL_CHECKERS);
+        if (spellChecker != null) {
+            final TextServicesManager tsm = (TextServicesManager) getSystemService(
+                    Context.TEXT_SERVICES_MANAGER_SERVICE);
+            if (tsm.isSpellCheckerEnabled()) {
+                final SpellCheckerInfo sci = tsm.getCurrentSpellChecker();
+                spellChecker.setSummary(sci.loadLabel(getPackageManager()));
+            } else {
+                spellChecker.setSummary(R.string.switch_off_text);
+            }
+        }
+
         if (!mShowsOnlyFullImeAndKeyboardList) {
             if (mLanguagePref != null) {
                 String localeName = getLocaleName(getResources());
@@ -641,7 +660,7 @@
 
             // Spell checker.
             SearchIndexableRaw indexable = new SearchIndexableRaw(context);
-            indexable.key = "spellcheckers_settings";
+            indexable.key = KEY_SPELL_CHECKERS;
             indexable.title = context.getString(R.string.spellcheckers_settings_title);
             indexable.screenTitle = screenTitle;
             indexables.add(indexable);
diff --git a/src/com/android/settings/inputmethod/InputMethodAndSubtypeEnabler.java b/src/com/android/settings/inputmethod/InputMethodAndSubtypeEnabler.java
index 5a94e35..51f5e14 100644
--- a/src/com/android/settings/inputmethod/InputMethodAndSubtypeEnabler.java
+++ b/src/com/android/settings/inputmethod/InputMethodAndSubtypeEnabler.java
@@ -16,10 +16,6 @@
 
 package com.android.settings.inputmethod;
 
-import com.android.internal.inputmethod.InputMethodUtils;
-import com.android.settings.R;
-import com.android.settings.SettingsPreferenceFragment;
-
 import android.app.AlertDialog;
 import android.content.Context;
 import android.content.DialogInterface;
@@ -37,68 +33,63 @@
 import android.view.inputmethod.InputMethodManager;
 import android.view.inputmethod.InputMethodSubtype;
 
+import com.android.internal.inputmethod.InputMethodUtils;
+import com.android.settings.R;
+import com.android.settings.SettingsPreferenceFragment;
+
 import java.text.Collator;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.List;
-import java.util.Locale;
 
 public class InputMethodAndSubtypeEnabler extends SettingsPreferenceFragment {
-    private static final String TAG =InputMethodAndSubtypeEnabler.class.getSimpleName();
+    private static final String TAG = InputMethodAndSubtypeEnabler.class.getSimpleName();
     private AlertDialog mDialog = null;
     private boolean mHaveHardKeyboard;
     final private HashMap<String, List<Preference>> mInputMethodAndSubtypePrefsMap =
             new HashMap<>();
-    final private HashMap<String, CheckBoxPreference> mSubtypeAutoSelectionCBMap = new HashMap<>();
+    final private HashMap<String, CheckBoxPreference> mAutoSelectionPrefsMap = new HashMap<>();
     private InputMethodManager mImm;
-    private List<InputMethodInfo> mInputMethodProperties;
+    // TODO: Change mInputMethodInfoList to Map
+    private List<InputMethodInfo> mInputMethodInfoList;
     private String mInputMethodId;
-    private String mTitle;
-    private String mSystemLocale = "";
-    private Collator mCollator = Collator.getInstance();
 
     @Override
-    public void onCreate(Bundle icicle) {
+    public void onCreate(final Bundle icicle) {
         super.onCreate(icicle);
         mImm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
         final Configuration config = getResources().getConfiguration();
         mHaveHardKeyboard = (config.keyboard == Configuration.KEYBOARD_QWERTY);
 
-        final Bundle arguments = getArguments();
         // Input method id should be available from an Intent when this preference is launched as a
         // single Activity (see InputMethodAndSubtypeEnablerActivity). It should be available
         // from a preference argument when the preference is launched as a part of the other
         // Activity (like a right pane of 2-pane Settings app)
-        mInputMethodId = getActivity().getIntent().getStringExtra(
+        mInputMethodId = getStringExtraFromIntentOrArguments(
                 android.provider.Settings.EXTRA_INPUT_METHOD_ID);
-        if (mInputMethodId == null && (arguments != null)) {
-            final String inputMethodId =
-                    arguments.getString(android.provider.Settings.EXTRA_INPUT_METHOD_ID);
-            if (inputMethodId != null) {
-                mInputMethodId = inputMethodId;
-            }
-        }
-        mTitle = getActivity().getIntent().getStringExtra(Intent.EXTRA_TITLE);
-        if (mTitle == null && (arguments != null)) {
-            final String title = arguments.getString(Intent.EXTRA_TITLE);
-            if (title != null) {
-                mTitle = title;
-            }
-        }
 
-        final Locale locale = config.locale;
-        mSystemLocale = locale.toString();
-        mCollator = Collator.getInstance(locale);
-        onCreateIMM();
+        mInputMethodInfoList = mImm.getInputMethodList();
         setPreferenceScreen(createPreferenceHierarchy());
     }
 
+    private String getStringExtraFromIntentOrArguments(final String name) {
+        final Intent intent = getActivity().getIntent();
+        final String fromIntent = intent.getStringExtra(name);
+        if (fromIntent != null) {
+            return fromIntent;
+        }
+        final Bundle arguments = getArguments();
+        return (arguments == null) ? null : arguments.getString(name);
+    }
+
     @Override
-    public void onActivityCreated(Bundle icicle) {
+    public void onActivityCreated(final Bundle icicle) {
         super.onActivityCreated(icicle);
-        if (!TextUtils.isEmpty(mTitle)) {
-            getActivity().setTitle(mTitle);
+        final String title = getStringExtraFromIntentOrArguments(Intent.EXTRA_TITLE);
+        if (!TextUtils.isEmpty(title)) {
+            getActivity().setTitle(title);
         }
     }
 
@@ -110,7 +101,7 @@
         InputMethodSettingValuesWrapper
                 .getInstance(getActivity()).refreshAllInputMethodAndSubtypes();
         InputMethodAndSubtypeUtil.loadInputMethodSubtypeList(
-                this, getContentResolver(), mInputMethodProperties, mInputMethodAndSubtypePrefsMap);
+                this, getContentResolver(), mInputMethodInfoList, mInputMethodAndSubtypePrefsMap);
         updateAutoSelectionCB();
     }
 
@@ -120,18 +111,18 @@
         // Clear all subtypes of all IMEs to make sure
         clearImplicitlyEnabledSubtypes(null);
         InputMethodAndSubtypeUtil.saveInputMethodSubtypeList(this, getContentResolver(),
-                mInputMethodProperties, mHaveHardKeyboard);
+                mInputMethodInfoList, mHaveHardKeyboard);
     }
 
     @Override
-    public boolean onPreferenceTreeClick(
-            PreferenceScreen preferenceScreen, Preference preference) {
+    public boolean onPreferenceTreeClick(final PreferenceScreen preferenceScreen,
+            final Preference preference) {
 
         if (preference instanceof CheckBoxPreference) {
             final CheckBoxPreference chkPref = (CheckBoxPreference) preference;
 
-            for (String imiId: mSubtypeAutoSelectionCBMap.keySet()) {
-                if (mSubtypeAutoSelectionCBMap.get(imiId) == chkPref) {
+            for (final String imiId : mAutoSelectionPrefsMap.keySet()) {
+                if (mAutoSelectionPrefsMap.get(imiId) == chkPref) {
                     // We look for the first preference item in subtype enabler.
                     // The first item is used for turning on/off subtype auto selection.
                     // We are in the subtype enabler and trying selecting subtypes automatically.
@@ -143,14 +134,14 @@
             final String id = chkPref.getKey();
             if (chkPref.isChecked()) {
                 InputMethodInfo selImi = null;
-                final int N = mInputMethodProperties.size();
+                final int N = mInputMethodInfoList.size();
                 for (int i = 0; i < N; i++) {
-                    InputMethodInfo imi = mInputMethodProperties.get(i);
+                    final InputMethodInfo imi = mInputMethodInfoList.get(i);
                     if (id.equals(imi.getId())) {
                         selImi = imi;
                         if (InputMethodUtils.isSystemIme(imi)) {
                             InputMethodAndSubtypeUtil.setSubtypesPreferenceEnabled(
-                                    this, mInputMethodProperties, id, true);
+                                    this, mInputMethodInfoList, id, true);
                             // This is a built-in IME, so no need to warn.
                             return super.onPreferenceTreeClick(preferenceScreen, preference);
                         }
@@ -172,7 +163,7 @@
                                             chkPref.setChecked(true);
                                             InputMethodAndSubtypeUtil.setSubtypesPreferenceEnabled(
                                                     InputMethodAndSubtypeEnabler.this,
-                                                    mInputMethodProperties, id, true);
+                                                    mInputMethodInfoList, id, true);
                                         }
 
                             })
@@ -195,7 +186,7 @@
                 mDialog.show();
             } else {
                 InputMethodAndSubtypeUtil.setSubtypesPreferenceEnabled(
-                        this, mInputMethodProperties, id, false);
+                        this, mInputMethodInfoList, id, false);
                 updateAutoSelectionCB();
             }
         }
@@ -211,25 +202,19 @@
         }
     }
 
-    private void onCreateIMM() {
-        InputMethodManager imm = (InputMethodManager) getSystemService(
-                Context.INPUT_METHOD_SERVICE);
-
-        // TODO: Change mInputMethodProperties to Map
-        mInputMethodProperties = imm.getInputMethodList();
-    }
-
     private PreferenceScreen createPreferenceHierarchy() {
         // Root
         final PreferenceScreen root = getPreferenceManager().createPreferenceScreen(getActivity());
         final Context context = getActivity();
 
-        int N = (mInputMethodProperties == null ? 0 : mInputMethodProperties.size());
-
+        final Collator collator = Collator.getInstance();
+        final int N = (mInputMethodInfoList == null ? 0 : mInputMethodInfoList.size());
         for (int i = 0; i < N; ++i) {
-            final InputMethodInfo imi = mInputMethodProperties.get(i);
+            final InputMethodInfo imi = mInputMethodInfoList.get(i);
             final int subtypeCount = imi.getSubtypeCount();
-            if (subtypeCount <= 1) continue;
+            if (subtypeCount <= 1) {
+                continue;
+            }
             final String imiId = imi.getId();
             // Add this subtype to the list when no IME is specified or when the IME of this
             // subtype is the specified IME.
@@ -245,7 +230,7 @@
             keyboardSettingsCategory.setKey(imiId);
             // TODO: Use toggle Preference if images are ready.
             final CheckBoxPreference autoCB = new CheckBoxPreference(context);
-            mSubtypeAutoSelectionCBMap.put(imiId, autoCB);
+            mAutoSelectionPrefsMap.put(imiId, autoCB);
             keyboardSettingsCategory.addPreference(autoCB);
 
             final PreferenceCategory activeInputMethodsCategory = new PreferenceCategory(context);
@@ -258,22 +243,27 @@
             if (subtypeCount > 0) {
                 for (int j = 0; j < subtypeCount; ++j) {
                     final InputMethodSubtype subtype = imi.getSubtypeAt(j);
-                    final CharSequence subtypeLabel = subtype.getDisplayName(context,
-                            imi.getPackageName(), imi.getServiceInfo().applicationInfo);
                     if (subtype.overridesImplicitlyEnabledSubtype()) {
                         if (!isAutoSubtype) {
                             isAutoSubtype = true;
-                            autoSubtypeLabel = subtypeLabel;
+                            autoSubtypeLabel = subtype.getDisplayName(context,
+                                    imi.getPackageName(), imi.getServiceInfo().applicationInfo);
                         }
                     } else {
-                        final CheckBoxPreference chkbxPref = new SubtypeCheckBoxPreference(
-                                context, subtype.getLocale(), mSystemLocale, mCollator);
-                        chkbxPref.setKey(imiId + subtype.hashCode());
-                        chkbxPref.setTitle(subtypeLabel);
+                        final CheckBoxPreference chkbxPref = new InputMethodSubtypePreference(
+                                context, subtype, imi);
                         subtypePreferences.add(chkbxPref);
                     }
                 }
-                Collections.sort(subtypePreferences);
+                Collections.sort(subtypePreferences, new Comparator<Preference>() {
+                    @Override
+                    public int compare(Preference lhs, Preference rhs) {
+                        if (lhs instanceof InputMethodSubtypePreference) {
+                            return ((InputMethodSubtypePreference)lhs).compareTo(rhs, collator);
+                        }
+                        return lhs.compareTo(rhs);
+                    }
+                });
                 for (int j = 0; j < subtypePreferences.size(); ++j) {
                     activeInputMethodsCategory.addPreference(subtypePreferences.get(j));
                 }
@@ -296,9 +286,8 @@
     private boolean isNoSubtypesExplicitlySelected(String imiId) {
         boolean allSubtypesOff = true;
         final List<Preference> subtypePrefs = mInputMethodAndSubtypePrefsMap.get(imiId);
-        for (Preference subtypePref: subtypePrefs) {
-            if (subtypePref instanceof CheckBoxPreference
-                    && ((CheckBoxPreference)subtypePref).isChecked()) {
+        for (final Preference pref : subtypePrefs) {
+            if (pref instanceof CheckBoxPreference && ((CheckBoxPreference)pref).isChecked()) {
                 allSubtypesOff = false;
                 break;
             }
@@ -307,11 +296,13 @@
     }
 
     private void setSubtypeAutoSelectionEnabled(String imiId, boolean autoSelectionEnabled) {
-        CheckBoxPreference autoSelectionCB = mSubtypeAutoSelectionCBMap.get(imiId);
-        if (autoSelectionCB == null) return;
+        final CheckBoxPreference autoSelectionCB = mAutoSelectionPrefsMap.get(imiId);
+        if (autoSelectionCB == null) {
+            return;
+        }
         autoSelectionCB.setChecked(autoSelectionEnabled);
         final List<Preference> subtypePrefs = mInputMethodAndSubtypePrefsMap.get(imiId);
-        for (Preference subtypePref: subtypePrefs) {
+        for (final Preference subtypePref : subtypePrefs) {
             if (subtypePref instanceof CheckBoxPreference) {
                 // When autoSelectionEnabled is true, all subtype prefs need to be disabled with
                 // implicitly checked subtypes. In case of false, all subtype prefs need to be
@@ -323,8 +314,8 @@
             }
         }
         if (autoSelectionEnabled) {
-            InputMethodAndSubtypeUtil.saveInputMethodSubtypeList(this, getContentResolver(),
-                    mInputMethodProperties, mHaveHardKeyboard);
+            InputMethodAndSubtypeUtil.saveInputMethodSubtypeList(
+                    this, getContentResolver(), mInputMethodInfoList, mHaveHardKeyboard);
             setCheckedImplicitlyEnabledSubtypes(imiId);
         }
     }
@@ -339,23 +330,29 @@
 
     private void updateImplicitlyEnabledSubtypes(String targetImiId, boolean check) {
         // When targetImiId is null, apply to all subtypes of all IMEs
-        for (InputMethodInfo imi: mInputMethodProperties) {
-            String imiId = imi.getId();
-            if (targetImiId != null && !targetImiId.equals(imiId)) continue;
-            final CheckBoxPreference autoCB = mSubtypeAutoSelectionCBMap.get(imiId);
+        for (final InputMethodInfo imi : mInputMethodInfoList) {
+            final String imiId = imi.getId();
+            if (targetImiId != null && !targetImiId.equals(imiId)) {
+                continue;
+            }
+            final CheckBoxPreference autoCB = mAutoSelectionPrefsMap.get(imiId);
             // No need to update implicitly enabled subtypes when the user has unchecked the
             // "subtype auto selection".
-            if (autoCB == null || !autoCB.isChecked()) continue;
+            if (autoCB == null || !autoCB.isChecked()) {
+                continue;
+            }
             final List<Preference> subtypePrefs = mInputMethodAndSubtypePrefsMap.get(imiId);
             final List<InputMethodSubtype> implicitlyEnabledSubtypes =
                     mImm.getEnabledInputMethodSubtypeList(imi, true);
-            if (subtypePrefs == null || implicitlyEnabledSubtypes == null) continue;
-            for (Preference subtypePref: subtypePrefs) {
+            if (subtypePrefs == null || implicitlyEnabledSubtypes == null) {
+                continue;
+            }
+            for (final Preference subtypePref : subtypePrefs) {
                 if (subtypePref instanceof CheckBoxPreference) {
-                    CheckBoxPreference cb = (CheckBoxPreference)subtypePref;
+                    final CheckBoxPreference cb = (CheckBoxPreference)subtypePref;
                     cb.setChecked(false);
                     if (check) {
-                        for (InputMethodSubtype subtype: implicitlyEnabledSubtypes) {
+                        for (final InputMethodSubtype subtype : implicitlyEnabledSubtypes) {
                             String implicitlyEnabledSubtypePrefKey = imiId + subtype.hashCode();
                             if (cb.getKey().equals(implicitlyEnabledSubtypePrefKey)) {
                                 cb.setChecked(true);
@@ -369,63 +366,9 @@
     }
 
     private void updateAutoSelectionCB() {
-        for (String imiId: mInputMethodAndSubtypePrefsMap.keySet()) {
+        for (final String imiId : mInputMethodAndSubtypePrefsMap.keySet()) {
             setSubtypeAutoSelectionEnabled(imiId, isNoSubtypesExplicitlySelected(imiId));
         }
         setCheckedImplicitlyEnabledSubtypes(null);
     }
-
-    private static class SubtypeCheckBoxPreference extends CheckBoxPreference {
-        private final boolean mIsSystemLocale;
-        private final boolean mIsSystemLanguage;
-        private final Collator mCollator;
-
-        public SubtypeCheckBoxPreference(
-                Context context, String subtypeLocale, String systemLocale, Collator collator) {
-            super(context);
-            if (TextUtils.isEmpty(subtypeLocale)) {
-                mIsSystemLocale = false;
-                mIsSystemLanguage = false;
-            } else {
-                mIsSystemLocale = subtypeLocale.equals(systemLocale);
-                mIsSystemLanguage = mIsSystemLocale
-                        || subtypeLocale.startsWith(systemLocale.substring(0, 2));
-            }
-            mCollator = collator;
-        }
-
-        @Override
-        public int compareTo(Preference p) {
-            if (p instanceof SubtypeCheckBoxPreference) {
-                final SubtypeCheckBoxPreference pref = ((SubtypeCheckBoxPreference)p);
-                final CharSequence t0 = getTitle();
-                final CharSequence t1 = pref.getTitle();
-                if (TextUtils.equals(t0, t1)) {
-                    return 0;
-                }
-                if (mIsSystemLocale) {
-                    return -1;
-                }
-                if (pref.mIsSystemLocale) {
-                    return 1;
-                }
-                if (mIsSystemLanguage) {
-                    return -1;
-                }
-                if (pref.mIsSystemLanguage) {
-                    return 1;
-                }
-                if (TextUtils.isEmpty(t0)) {
-                    return 1;
-                }
-                if (TextUtils.isEmpty(t1)) {
-                    return -1;
-                }
-                return mCollator.compare(t0.toString(), t1.toString());
-            } else {
-                Log.w(TAG, "Illegal preference type.");
-                return super.compareTo(p);
-            }
-        }
-    }
 }
diff --git a/src/com/android/settings/inputmethod/InputMethodPreference.java b/src/com/android/settings/inputmethod/InputMethodPreference.java
index 1404875..a65e5e5 100755
--- a/src/com/android/settings/inputmethod/InputMethodPreference.java
+++ b/src/com/android/settings/inputmethod/InputMethodPreference.java
@@ -51,7 +51,7 @@
     private static final String TAG = InputMethodPreference.class.getSimpleName();
     private static final String EMPTY_TEXT = "";
 
-    interface onSavePreferenceListener {
+    interface OnSavePreferenceListener {
         /**
          * Called when this preference needs to be saved its state.
          *
@@ -66,7 +66,7 @@
 
     private final InputMethodInfo mImi;
     private final boolean mHasPriorityInSorting;
-    private final onSavePreferenceListener mOnSaveListener;
+    private final OnSavePreferenceListener mOnSaveListener;
     private final InputMethodSettingValuesWrapper mInputMethodSettingValues;
 
     private AlertDialog mDialog = null;
@@ -82,7 +82,7 @@
      *     to save the state to shared preference.
      */
     InputMethodPreference(final Context context, final InputMethodInfo imi,
-            final boolean isImeEnabler, final onSavePreferenceListener onSaveListener) {
+            final boolean isImeEnabler, final OnSavePreferenceListener onSaveListener) {
         super(context);
         setPersistent(false);
         mImi = imi;
@@ -231,6 +231,9 @@
     }
 
     int compareTo(final InputMethodPreference rhs, final Collator collator) {
+        if (this == rhs) {
+            return 0;
+        }
         if (mHasPriorityInSorting == rhs.mHasPriorityInSorting) {
             final CharSequence t0 = getTitle();
             final CharSequence t1 = rhs.getTitle();
diff --git a/src/com/android/settings/inputmethod/InputMethodSubtypePreference.java b/src/com/android/settings/inputmethod/InputMethodSubtypePreference.java
new file mode 100644
index 0000000..6ac202a
--- /dev/null
+++ b/src/com/android/settings/inputmethod/InputMethodSubtypePreference.java
@@ -0,0 +1,94 @@
+/*
+ * 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.inputmethod;
+
+import android.content.Context;
+import android.preference.CheckBoxPreference;
+import android.preference.Preference;
+import android.text.TextUtils;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.internal.inputmethod.InputMethodUtils;
+
+import java.text.Collator;
+import java.util.Locale;
+
+/**
+ * Input method subtype preference.
+ *
+ * This preference represents a subtype of an IME. It is used to enable or disable the subtype.
+ */
+//TODO: Make this non-persistent.
+class InputMethodSubtypePreference extends CheckBoxPreference {
+    private final boolean mIsSystemLocale;
+    private final boolean mIsSystemLanguage;
+
+    InputMethodSubtypePreference(final Context context, final InputMethodSubtype subtype,
+            final InputMethodInfo imi) {
+        super(context);
+        setKey(imi.getId() + subtype.hashCode());
+        final CharSequence subtypeLabel = subtype.getDisplayName(context,
+                imi.getPackageName(), imi.getServiceInfo().applicationInfo);
+        setTitle(subtypeLabel);
+        final String subtypeLocaleString = subtype.getLocale();
+        if (TextUtils.isEmpty(subtypeLocaleString)) {
+            mIsSystemLocale = false;
+            mIsSystemLanguage = false;
+        } else {
+            final Locale systemLocale = context.getResources().getConfiguration().locale;
+            mIsSystemLocale = subtypeLocaleString.equals(systemLocale.toString());
+            mIsSystemLanguage = mIsSystemLocale
+                    || InputMethodUtils.getLanguageFromLocaleString(subtypeLocaleString)
+                            .equals(systemLocale.getLanguage());
+        }
+    }
+
+    int compareTo(final Preference rhs, final Collator collator) {
+        if (this == rhs) {
+            return 0;
+        }
+        if (rhs instanceof InputMethodSubtypePreference) {
+            final InputMethodSubtypePreference pref = (InputMethodSubtypePreference) rhs;
+            final CharSequence t0 = getTitle();
+            final CharSequence t1 = rhs.getTitle();
+            if (TextUtils.equals(t0, t1)) {
+                return 0;
+            }
+            if (mIsSystemLocale) {
+                return -1;
+            }
+            if (pref.mIsSystemLocale) {
+                return 1;
+            }
+            if (mIsSystemLanguage) {
+                return -1;
+            }
+            if (pref.mIsSystemLanguage) {
+                return 1;
+            }
+            if (TextUtils.isEmpty(t0)) {
+                return 1;
+            }
+            if (TextUtils.isEmpty(t1)) {
+                return -1;
+            }
+            return collator.compare(t0.toString(), t1.toString());
+        }
+        return super.compareTo(rhs);
+    }
+}
diff --git a/src/com/android/settings/inputmethod/SingleSpellCheckerPreference.java b/src/com/android/settings/inputmethod/SingleSpellCheckerPreference.java
deleted file mode 100644
index 2dc90ec..0000000
--- a/src/com/android/settings/inputmethod/SingleSpellCheckerPreference.java
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * Copyright (C) 2011 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.inputmethod;
-
-import com.android.settings.R;
-import com.android.settings.Utils;
-
-import android.app.AlertDialog;
-import android.content.ActivityNotFoundException;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.res.Resources;
-import android.preference.Preference;
-import android.text.TextUtils;
-import android.util.Log;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.textservice.SpellCheckerInfo;
-import android.view.textservice.SpellCheckerSubtype;
-import android.view.textservice.TextServicesManager;
-import android.widget.ImageView;
-import android.widget.RadioButton;
-import android.widget.Toast;
-
-// TODO: Make this non-persistent.
-class SingleSpellCheckerPreference extends Preference {
-    private static final String TAG = SingleSpellCheckerPreference.class.getSimpleName();
-    private static final boolean DBG = false;
-
-    private final SpellCheckerInfo mSpellCheckerInfo;
-
-    private final SpellCheckersSettings mFragment;
-    private final Resources mRes;
-    private final TextServicesManager mTsm;
-    private AlertDialog mDialog = null;
-    private View mPrefAll;
-    private RadioButton mRadioButton;
-    private View mPrefLeftButton;
-    private View mSettingsButton;
-    private ImageView mSubtypeButton;
-    private Intent mSettingsIntent;
-    private boolean mSelected;
-
-    public SingleSpellCheckerPreference(SpellCheckersSettings fragment, SpellCheckerInfo sci,
-            TextServicesManager tsm) {
-        super(fragment.getActivity(), null, 0);
-        mFragment = fragment;
-        mRes = fragment.getActivity().getResources();
-        mTsm = tsm;
-        setLayoutResource(R.layout.preference_spellchecker);
-        mSpellCheckerInfo = sci;
-        mSelected = false;
-        final String settingsActivity = mSpellCheckerInfo.getSettingsActivity();
-        if (!TextUtils.isEmpty(settingsActivity)) {
-            mSettingsIntent = new Intent(Intent.ACTION_MAIN);
-            mSettingsIntent.setClassName(mSpellCheckerInfo.getPackageName(), settingsActivity);
-        } else {
-            mSettingsIntent = null;
-        }
-    }
-
-    @Override
-    protected void onBindView(View view) {
-        super.onBindView(view);
-        mPrefAll = view.findViewById(R.id.pref_all);
-        mRadioButton = (RadioButton)view.findViewById(R.id.pref_radio);
-        mPrefLeftButton = view.findViewById(R.id.pref_left_button);
-        mPrefLeftButton.setOnClickListener(
-                new OnClickListener() {
-                    @Override
-                    public void onClick(View arg0) {
-                        onLeftButtonClicked(arg0);
-                    }
-                });
-        mSubtypeButton = (ImageView)view.findViewById(R.id.pref_right_button2);
-        mSubtypeButton.setOnClickListener(
-                new OnClickListener() {
-                    @Override
-                    public void onClick(View arg0) {
-                        onSubtypeButtonClicked(arg0);
-                    }
-                });
-        mSettingsButton = view.findViewById(R.id.pref_right_button1);
-        mSettingsButton.setOnClickListener(
-                new OnClickListener() {
-                    @Override
-                    public void onClick(View arg0) {
-                        onSettingsButtonClicked(arg0);
-                    }
-                });
-        updateSelectedState(mSelected);
-    }
-
-    private void onLeftButtonClicked(View arg0) {
-        mFragment.onPreferenceClick(this);
-    }
-
-    public SpellCheckerInfo getSpellCheckerInfo() {
-        return mSpellCheckerInfo;
-    }
-
-    private void updateSelectedState(boolean selected) {
-        if (mPrefAll != null) {
-            mRadioButton.setChecked(selected);
-            enableButtons(selected);
-        }
-    }
-
-    public void setSelected(boolean selected) {
-        mSelected = selected;
-        updateSelectedState(selected);
-    }
-
-    private void onSubtypeButtonClicked(View arg0) {
-        if (mDialog != null && mDialog.isShowing()) {
-            mDialog.dismiss();
-        }
-        final AlertDialog.Builder builder = new AlertDialog.Builder(mFragment.getActivity());
-        builder.setTitle(R.string.phone_language);
-        final int size = mSpellCheckerInfo.getSubtypeCount();
-        final CharSequence[] items = new CharSequence[size + 1];
-        items[0] = mRes.getString(R.string.use_system_language_to_select_input_method_subtypes);
-        for (int i = 0; i < size; ++i) {
-            final SpellCheckerSubtype subtype = mSpellCheckerInfo.getSubtypeAt(i);
-            final CharSequence label = subtype.getDisplayName(
-                    mFragment.getActivity(), mSpellCheckerInfo.getPackageName(),
-                    mSpellCheckerInfo.getServiceInfo().applicationInfo);
-            items[i + 1] = label;
-        }
-        // default: "Use system language"
-        int checkedItem = 0;
-        // Allow no implicitly selected subtypes
-        final SpellCheckerSubtype currentScs = mTsm.getCurrentSpellCheckerSubtype(false);
-        if (currentScs != null) {
-            for (int i = 0; i < size; ++i) {
-                if (mSpellCheckerInfo.getSubtypeAt(i).equals(currentScs)) {
-                    checkedItem = i + 1;
-                    break;
-                }
-            }
-        }
-        builder.setSingleChoiceItems(items, checkedItem, new AlertDialog.OnClickListener() {
-            @Override
-            public void onClick(DialogInterface dialog, int which) {
-                if (which == 0) {
-                    mTsm.setSpellCheckerSubtype(null);
-                } else {
-                    mTsm.setSpellCheckerSubtype(mSpellCheckerInfo.getSubtypeAt(which - 1));
-                }
-                if (DBG) {
-                    final SpellCheckerSubtype subtype = mTsm.getCurrentSpellCheckerSubtype(true);
-                    Log.d(TAG, "Current spell check locale is "
-                            + subtype == null ? "null" : subtype.getLocale());
-                }
-                dialog.dismiss();
-            }
-        });
-        mDialog = builder.create();
-        mDialog.show();
-    }
-
-    private void onSettingsButtonClicked(View arg0) {
-        if (mFragment != null && mSettingsIntent != null) {
-            try {
-                mFragment.startActivity(mSettingsIntent);
-            } catch (ActivityNotFoundException e) {
-                final String msg = mFragment.getString(R.string.failed_to_open_app_settings_toast,
-                        mSpellCheckerInfo.loadLabel(mFragment.getActivity().getPackageManager()));
-                Toast.makeText(mFragment.getActivity(), msg, Toast.LENGTH_LONG).show();
-            }
-        }
-    }
-
-    private void enableButtons(boolean enabled) {
-        if (mSettingsButton != null) {
-            if (mSettingsIntent == null) {
-                mSettingsButton.setVisibility(View.GONE);
-            } else {
-                mSettingsButton.setEnabled(enabled);
-                mSettingsButton.setClickable(enabled);
-                mSettingsButton.setFocusable(enabled);
-                if (!enabled) {
-                    mSettingsButton.setAlpha(Utils.DISABLED_ALPHA);
-                }
-            }
-        }
-        if (mSubtypeButton != null) {
-            if (mSpellCheckerInfo.getSubtypeCount() <= 0) {
-                mSubtypeButton.setVisibility(View.GONE);
-            } else {
-                mSubtypeButton.setEnabled(enabled);
-                mSubtypeButton.setClickable(enabled);
-                mSubtypeButton.setFocusable(enabled);
-                if (!enabled) {
-                    mSubtypeButton.setAlpha(Utils.DISABLED_ALPHA);
-                }
-            }
-        }
-    }
-}
diff --git a/src/com/android/settings/inputmethod/SpellCheckerPreference.java b/src/com/android/settings/inputmethod/SpellCheckerPreference.java
new file mode 100644
index 0000000..3787803
--- /dev/null
+++ b/src/com/android/settings/inputmethod/SpellCheckerPreference.java
@@ -0,0 +1,151 @@
+/*
+ * 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.inputmethod;
+
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.Intent;
+import android.preference.Preference;
+import android.text.TextUtils;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.textservice.SpellCheckerInfo;
+import android.widget.RadioButton;
+import android.widget.Toast;
+
+import com.android.settings.R;
+import com.android.settings.Utils;
+
+/**
+ * Spell checker service preference.
+ *
+ * This preference represents a spell checker service. It is used for two purposes. 1) A radio
+ * button on the left side is used to choose the current spell checker service. 2) A settings
+ * icon on the right side is used to invoke the setting activity of the spell checker service.
+ */
+class SpellCheckerPreference extends Preference implements OnClickListener {
+    interface OnRadioButtonPreferenceListener {
+        /**
+         * Called when this preference needs to be saved its state.
+         *
+         * Note that this preference is non-persistent and needs explicitly to be saved its state.
+         * Because changing one IME state may change other IMEs' state, this is a place to update
+         * other IMEs' state as well.
+         *
+         * @param pref This preference.
+         */
+        public void onRadioButtonClicked(SpellCheckerPreference pref);
+    }
+
+    private final SpellCheckerInfo mSci;
+    private final OnRadioButtonPreferenceListener mOnRadioButtonListener;
+
+    private RadioButton mRadioButton;
+    private View mPrefLeftButton;
+    private View mSettingsButton;
+    private boolean mSelected;
+
+    public SpellCheckerPreference(final Context context, final SpellCheckerInfo sci,
+            final OnRadioButtonPreferenceListener onRadioButtonListener) {
+        super(context, null, 0);
+        setPersistent(false);
+        setLayoutResource(R.layout.preference_spellchecker);
+        setWidgetLayoutResource(R.layout.preference_spellchecker_widget);
+        mSci = sci;
+        mOnRadioButtonListener = onRadioButtonListener;
+        setKey(sci.getId());
+        setTitle(sci.loadLabel(context.getPackageManager()));
+        final String settingsActivity = mSci.getSettingsActivity();
+        if (TextUtils.isEmpty(settingsActivity)) {
+            setIntent(null);
+        } else {
+            final Intent intent = new Intent(Intent.ACTION_MAIN);
+            intent.setClassName(mSci.getPackageName(), settingsActivity);
+            setIntent(intent);
+        }
+    }
+
+    @Override
+    protected void onBindView(View view) {
+        super.onBindView(view);
+        mRadioButton = (RadioButton)view.findViewById(R.id.pref_radio);
+        mPrefLeftButton = view.findViewById(R.id.pref_left_button);
+        mPrefLeftButton.setOnClickListener(this);
+        mSettingsButton = view.findViewById(R.id.pref_right_button);
+        mSettingsButton.setOnClickListener(this);
+        updateSelectedState(mSelected);
+    }
+
+    @Override
+    public void onClick(final View v) {
+        if (v == mPrefLeftButton) {
+            mOnRadioButtonListener.onRadioButtonClicked(this);
+            return;
+        }
+        if (v == mSettingsButton) {
+            onSettingsButtonClicked();
+            return;
+        }
+    }
+
+    private void onSettingsButtonClicked() {
+        final Context context = getContext();
+        try {
+            final Intent intent = getIntent();
+            if (intent != null) {
+                // Invoke a settings activity of an spell checker.
+                context.startActivity(intent);
+            }
+        } catch (final ActivityNotFoundException e) {
+            final String message = context.getString(R.string.failed_to_open_app_settings_toast,
+                    mSci.loadLabel(context.getPackageManager()));
+            Toast.makeText(context, message, Toast.LENGTH_LONG).show();
+        }
+    }
+
+    public SpellCheckerInfo getSpellCheckerInfo() {
+        return mSci;
+    }
+
+    public void setSelected(final boolean selected) {
+        mSelected = selected;
+        updateSelectedState(selected);
+    }
+
+    private void updateSelectedState(final boolean selected) {
+        if (mRadioButton != null) {
+            mRadioButton.setChecked(selected);
+            enableSettingsButton(isEnabled() && selected);
+        }
+    }
+
+    private void enableSettingsButton(final boolean enabled) {
+        if (mSettingsButton == null) {
+            return;
+        }
+        if (getIntent() == null) {
+            mSettingsButton.setVisibility(View.GONE);
+        } else {
+            mSettingsButton.setEnabled(enabled);
+            mSettingsButton.setClickable(enabled);
+            mSettingsButton.setFocusable(enabled);
+            if (!enabled) {
+                mSettingsButton.setAlpha(Utils.DISABLED_ALPHA);
+            }
+        }
+    }
+}
diff --git a/src/com/android/settings/inputmethod/SpellCheckersPreference.java b/src/com/android/settings/inputmethod/SpellCheckersPreference.java
deleted file mode 100644
index 1482b6c..0000000
--- a/src/com/android/settings/inputmethod/SpellCheckersPreference.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2011 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.inputmethod;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.textservice.TextServicesManager;
-
-// TODO: Make this non-persistent.
-class SpellCheckersPreference extends CheckBoxAndSettingsPreference {
-    private TextServicesManager mTsm;
-
-    public SpellCheckersPreference(Context context) {
-        this(context, null);
-    }
-
-    public SpellCheckersPreference(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public SpellCheckersPreference(Context context, AttributeSet attrs, int defStyleAttr) {
-        this(context, attrs, defStyleAttr, 0);
-    }
-
-    public SpellCheckersPreference(Context context, AttributeSet attrs, int defStyleAttr,
-            int defStyleRes) {
-        super(context, attrs, defStyleAttr, defStyleRes);
-
-        mTsm = (TextServicesManager) context.getSystemService(
-                Context.TEXT_SERVICES_MANAGER_SERVICE);
-        setChecked(mTsm.isSpellCheckerEnabled());
-    }
-
-    @Override
-    protected void onCheckBoxClicked() {
-        super.onCheckBoxClicked();
-        final boolean checked = isChecked();
-        mTsm.setSpellCheckerEnabled(checked);
-    }
-}
diff --git a/src/com/android/settings/inputmethod/SpellCheckersSettings.java b/src/com/android/settings/inputmethod/SpellCheckersSettings.java
index 40d8619..5a8ccea 100644
--- a/src/com/android/settings/inputmethod/SpellCheckersSettings.java
+++ b/src/com/android/settings/inputmethod/SpellCheckersSettings.java
@@ -20,104 +20,201 @@
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
 import android.os.Bundle;
 import android.preference.Preference;
+import android.preference.Preference.OnPreferenceClickListener;
 import android.preference.PreferenceScreen;
 import android.util.Log;
 import android.view.textservice.SpellCheckerInfo;
+import android.view.textservice.SpellCheckerSubtype;
 import android.view.textservice.TextServicesManager;
+import android.widget.Switch;
 
 import com.android.settings.R;
+import com.android.settings.SettingsActivity;
 import com.android.settings.SettingsPreferenceFragment;
-
-import java.util.ArrayList;
+import com.android.settings.inputmethod.SpellCheckerPreference.OnRadioButtonPreferenceListener;
+import com.android.settings.widget.SwitchBar;
+import com.android.settings.widget.SwitchBar.OnSwitchChangeListener;
 
 public class SpellCheckersSettings extends SettingsPreferenceFragment
-        implements Preference.OnPreferenceClickListener {
+        implements OnSwitchChangeListener, OnPreferenceClickListener,
+        OnRadioButtonPreferenceListener {
     private static final String TAG = SpellCheckersSettings.class.getSimpleName();
     private static final boolean DBG = false;
 
+    private static final String KEY_SPELL_CHECKER_LANGUAGE = "spellchecker_language";
+    private static final int ITEM_ID_USE_SYSTEM_LANGUAGE = 0;
+
+    private SwitchBar mSwitchBar;
+    private Preference mSpellCheckerLanaguagePref;
     private AlertDialog mDialog = null;
     private SpellCheckerInfo mCurrentSci;
     private SpellCheckerInfo[] mEnabledScis;
     private TextServicesManager mTsm;
-    private final ArrayList<SingleSpellCheckerPreference> mSpellCheckers = new ArrayList<>();
 
     @Override
     public void onCreate(final Bundle icicle) {
         super.onCreate(icicle);
-        mTsm = (TextServicesManager) getSystemService(Context.TEXT_SERVICES_MANAGER_SERVICE);
+
         addPreferencesFromResource(R.xml.spellchecker_prefs);
-        updateScreen();
+        mSpellCheckerLanaguagePref = findPreference(KEY_SPELL_CHECKER_LANGUAGE);
+        mSpellCheckerLanaguagePref.setOnPreferenceClickListener(this);
+
+        mTsm = (TextServicesManager) getSystemService(Context.TEXT_SERVICES_MANAGER_SERVICE);
+        mCurrentSci = mTsm.getCurrentSpellChecker();
+        mEnabledScis = mTsm.getEnabledSpellCheckers();
+        populatePreferenceScreen();
     }
 
-    // Override the behavior of {@link PreferenceFragment}.
-    @Override
-    public boolean onPreferenceTreeClick(final PreferenceScreen screen,
-            final Preference preference) {
-        return false;
+    private void populatePreferenceScreen() {
+        final PreferenceScreen screen = getPreferenceScreen();
+        final Context context = getActivity();
+        final int count = (mEnabledScis == null) ? 0 : mEnabledScis.length;
+        for (int index = 0; index < count; ++index) {
+            final SpellCheckerInfo sci = mEnabledScis[index];
+            final SpellCheckerPreference pref = new SpellCheckerPreference(context, sci, this);
+            screen.addPreference(pref);
+            InputMethodAndSubtypeUtil.removeUnnecessaryNonPersistentPreference(pref);
+        }
     }
 
     @Override
     public void onResume() {
         super.onResume();
-        updateScreen();
+        mSwitchBar = ((SettingsActivity)getActivity()).getSwitchBar();
+        mSwitchBar.show();
+        mSwitchBar.addOnSwitchChangeListener(this);
+        updatePreferenceScreen();
     }
 
-    private void updateScreen() {
-        getPreferenceScreen().removeAll();
-        updateEnabledSpellCheckers();
+    @Override
+    public void onPause() {
+        super.onPause();
+        mSwitchBar.removeOnSwitchChangeListener(this);
     }
 
-    private void updateEnabledSpellCheckers() {
+    @Override
+    public void onSwitchChanged(final Switch switchView, final boolean isChecked) {
+        mTsm.setSpellCheckerEnabled(isChecked);
+        updatePreferenceScreen();
+    }
+
+    private void updatePreferenceScreen() {
         mCurrentSci = mTsm.getCurrentSpellChecker();
-        mEnabledScis = mTsm.getEnabledSpellCheckers();
-        if (mCurrentSci == null || mEnabledScis == null) {
-            return;
+        final boolean isSpellCheckerEnabled = mTsm.isSpellCheckerEnabled();
+        mSwitchBar.setChecked(isSpellCheckerEnabled);
+
+        final SpellCheckerSubtype currentScs = mTsm.getCurrentSpellCheckerSubtype(
+                false /* allowImplicitlySelectedSubtype */);
+        mSpellCheckerLanaguagePref.setSummary(getSpellCheckerSubtypeLabel(mCurrentSci, currentScs));
+
+        final PreferenceScreen screen = getPreferenceScreen();
+        final int count = screen.getPreferenceCount();
+        for (int index = 0; index < count; index++) {
+            final Preference preference = screen.getPreference(index);
+            preference.setEnabled(isSpellCheckerEnabled);
+            if (preference instanceof SpellCheckerPreference) {
+                final SpellCheckerPreference pref = (SpellCheckerPreference)preference;
+                final SpellCheckerInfo sci = pref.getSpellCheckerInfo();
+                pref.setSelected(mCurrentSci != null && mCurrentSci.getId().equals(sci.getId()));
+            }
         }
-        final PackageManager pm = getPackageManager();
-        mSpellCheckers.clear();
-        for (int i = 0; i < mEnabledScis.length; ++i) {
-            final SpellCheckerInfo sci = mEnabledScis[i];
-            final SingleSpellCheckerPreference scPref = new SingleSpellCheckerPreference(
-                    this, sci, mTsm);
-            mSpellCheckers.add(scPref);
-            scPref.setTitle(sci.loadLabel(pm));
-            scPref.setSelected(mCurrentSci != null && mCurrentSci.getId().equals(sci.getId()));
-            getPreferenceScreen().addPreference(scPref);
+    }
+
+    private CharSequence getSpellCheckerSubtypeLabel(final SpellCheckerInfo sci,
+            final SpellCheckerSubtype subtype) {
+        if (sci == null) {
+            return null;
         }
+        if (subtype == null) {
+            return getString(R.string.use_system_language_to_select_input_method_subtypes);
+        }
+        return subtype.getDisplayName(
+                getActivity(), sci.getPackageName(), sci.getServiceInfo().applicationInfo);
     }
 
     @Override
     public boolean onPreferenceClick(final Preference pref) {
-        for (final SingleSpellCheckerPreference scp : mSpellCheckers) {
-            if (pref.equals(scp)) {
-                if (isSystemApp(scp.getSpellCheckerInfo())) {
-                    changeCurrentSpellChecker(scp);
-                } else {
-                    showSecurityWarnDialog(scp);
-                }
-                return true;
-            }
+        if (pref == mSpellCheckerLanaguagePref) {
+            showChooseLanguageDialog();
+            return true;
         }
-        return true;
+        return false;
     }
 
-    private void showSecurityWarnDialog(final SingleSpellCheckerPreference scp) {
+    @Override
+    public void onRadioButtonClicked(final SpellCheckerPreference pref) {
+        final SpellCheckerInfo sci = pref.getSpellCheckerInfo();
+        final boolean isSystemApp =
+                (sci.getServiceInfo().applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
+        if (isSystemApp) {
+            changeCurrentSpellChecker(sci);
+        } else {
+            showSecurityWarnDialog(pref);
+        }
+    }
+
+    private static int convertSubtypeIndexToDialogItemId(final int index) { return index + 1; }
+    private static int convertDialogItemIdToSubtypeIndex(final int item) { return item - 1; }
+
+    private void showChooseLanguageDialog() {
         if (mDialog != null && mDialog.isShowing()) {
             mDialog.dismiss();
         }
+        final SpellCheckerInfo currentSci = mTsm.getCurrentSpellChecker();
+        final SpellCheckerSubtype currentScs = mTsm.getCurrentSpellCheckerSubtype(
+                false /* allowImplicitlySelectedSubtype */);
+        final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+        builder.setTitle(R.string.phone_language);
+        final int subtypeCount = currentSci.getSubtypeCount();
+        final CharSequence[] items = new CharSequence[subtypeCount + 1 /* default */ ];
+        items[ITEM_ID_USE_SYSTEM_LANGUAGE] = getSpellCheckerSubtypeLabel(currentSci, null);
+        int checkedItemId = ITEM_ID_USE_SYSTEM_LANGUAGE;
+        for (int index = 0; index < subtypeCount; ++index) {
+            final SpellCheckerSubtype subtype = currentSci.getSubtypeAt(index);
+            final int itemId = convertSubtypeIndexToDialogItemId(index);
+            items[itemId] = getSpellCheckerSubtypeLabel(currentSci, subtype);
+            if (subtype.equals(currentScs)) {
+                checkedItemId = itemId;
+            }
+        }
+        builder.setSingleChoiceItems(items, checkedItemId, new AlertDialog.OnClickListener() {
+            @Override
+            public void onClick(final DialogInterface dialog, final int item) {
+                if (item == ITEM_ID_USE_SYSTEM_LANGUAGE) {
+                    mTsm.setSpellCheckerSubtype(null);
+                } else {
+                    final int index = convertDialogItemIdToSubtypeIndex(item);
+                    mTsm.setSpellCheckerSubtype(currentSci.getSubtypeAt(index));
+                }
+                if (DBG) {
+                    final SpellCheckerSubtype subtype = mTsm.getCurrentSpellCheckerSubtype(
+                            true /* allowImplicitlySelectedSubtype */);
+                    Log.d(TAG, "Current spell check locale is "
+                            + subtype == null ? "null" : subtype.getLocale());
+                }
+                dialog.dismiss();
+                updatePreferenceScreen();
+            }
+        });
+        mDialog = builder.create();
+        mDialog.show();
+    }
+
+    private void showSecurityWarnDialog(final SpellCheckerPreference pref) {
+        if (mDialog != null && mDialog.isShowing()) {
+            mDialog.dismiss();
+        }
+        final SpellCheckerInfo sci = pref.getSpellCheckerInfo();
         final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
         builder.setTitle(android.R.string.dialog_alert_title);
-        final PackageManager pm = getPackageManager();
-        builder.setMessage(getString(R.string.spellchecker_security_warning,
-                scp.getSpellCheckerInfo().getServiceInfo().applicationInfo.loadLabel(pm)));
+        builder.setMessage(getString(R.string.spellchecker_security_warning, pref.getTitle()));
         builder.setCancelable(true);
         builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
             @Override
             public void onClick(final DialogInterface dialog, final int which) {
-                changeCurrentSpellChecker(scp);
+                changeCurrentSpellChecker(sci);
             }
         });
         builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
@@ -129,15 +226,11 @@
         mDialog.show();
     }
 
-    private void changeCurrentSpellChecker(final SingleSpellCheckerPreference scp) {
-        mTsm.setCurrentSpellChecker(scp.getSpellCheckerInfo());
+    private void changeCurrentSpellChecker(final SpellCheckerInfo sci) {
+        mTsm.setCurrentSpellChecker(sci);
         if (DBG) {
             Log.d(TAG, "Current spell check is " + mTsm.getCurrentSpellChecker().getId());
         }
-        updateScreen();
-    }
-
-    private static boolean isSystemApp(final SpellCheckerInfo sci) {
-        return (sci.getServiceInfo().applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
+        updatePreferenceScreen();
     }
 }
diff --git a/src/com/android/settings/search/Index.java b/src/com/android/settings/search/Index.java
index ed06e31..b2341f0 100644
--- a/src/com/android/settings/search/Index.java
+++ b/src/com/android/settings/search/Index.java
@@ -72,6 +72,7 @@
 import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_INTENT_TARGET_PACKAGE;
 import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_INTENT_TARGET_CLASS;
 import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_KEY;
+import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_USER_ID;
 
 import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_RANK;
 import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_RESID;
@@ -103,6 +104,7 @@
     public static final int COLUMN_INDEX_INTENT_ACTION_TARGET_CLASS = 11;
     public static final int COLUMN_INDEX_ENABLED = 12;
     public static final int COLUMN_INDEX_KEY = 13;
+    public static final int COLUMN_INDEX_USER_ID = 14;
 
     public static final String ENTRIES_SEPARATOR = "|";
 
@@ -126,7 +128,8 @@
 
     private static final String[] MATCH_COLUMNS_PRIMARY = {
             IndexColumns.DATA_TITLE,
-            IndexColumns.DATA_TITLE_NORMALIZED
+            IndexColumns.DATA_TITLE_NORMALIZED,
+            IndexColumns.DATA_KEYWORDS
     };
 
     private static final String[] MATCH_COLUMNS_SECONDARY = {
@@ -134,8 +137,7 @@
             IndexColumns.DATA_SUMMARY_ON_NORMALIZED,
             IndexColumns.DATA_SUMMARY_OFF,
             IndexColumns.DATA_SUMMARY_OFF_NORMALIZED,
-            IndexColumns.DATA_ENTRIES,
-            IndexColumns.DATA_KEYWORDS
+            IndexColumns.DATA_ENTRIES
     };
 
     // Max number of saved search queries (who will be used for proposing suggestions)
@@ -609,6 +611,7 @@
                             COLUMN_INDEX_RAW_INTENT_TARGET_CLASS);
 
                     final String key = cursor.getString(COLUMN_INDEX_RAW_KEY);
+                    final int userId = cursor.getInt(COLUMN_INDEX_RAW_USER_ID);
 
                     SearchIndexableRaw data = new SearchIndexableRaw(packageContext);
                     data.rank = rank;
@@ -625,6 +628,7 @@
                     data.intentTargetPackage = targetPackage;
                     data.intentTargetClass = targetClass;
                     data.key = key;
+                    data.userId = userId;
 
                     addIndexableData(data);
                 }
@@ -721,7 +725,8 @@
                 raw.intentTargetPackage,
                 raw.intentTargetClass,
                 raw.enabled,
-                raw.key);
+                raw.key,
+                raw.userId);
     }
 
     private void indexOneResource(SQLiteDatabase database, String localeStr,
@@ -819,7 +824,8 @@
 
                 updateOneRowWithFilteredData(database, localeStr, title, summary, null, null,
                         fragmentName, screenTitle, iconResId, rank,
-                        keywords, intentAction, intentTargetPackage, intentTargetClass, true, key);
+                        keywords, intentAction, intentTargetPackage, intentTargetClass, true,
+                        key, -1 /* default user id */);
             }
 
             while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
@@ -851,7 +857,7 @@
                     updateOneRowWithFilteredData(database, localeStr, title, summary, null, entries,
                             fragmentName, screenTitle, iconResId, rank,
                             keywords, intentAction, intentTargetPackage, intentTargetClass,
-                            true, key);
+                            true, key, -1 /* default user id */);
                 } else {
                     String summaryOn = getDataSummaryOn(context, attrs);
                     String summaryOff = getDataSummaryOff(context, attrs);
@@ -863,7 +869,7 @@
                     updateOneRowWithFilteredData(database, localeStr, title, summaryOn, summaryOff,
                             null, fragmentName, screenTitle, iconResId, rank,
                             keywords, intentAction, intentTargetPackage, intentTargetClass,
-                            true, key);
+                            true, key, -1 /* default user id */);
                 }
             }
 
@@ -915,7 +921,8 @@
                         raw.intentTargetPackage,
                         raw.intentTargetClass,
                         raw.enabled,
-                        raw.key);
+                        raw.key,
+                        raw.userId);
             }
         }
 
@@ -949,7 +956,7 @@
             String className,
             String screenTitle, int iconResId, int rank, String keywords,
             String intentAction, String intentTargetPackage, String intentTargetClass,
-            boolean enabled, String key) {
+            boolean enabled, String key, int userId) {
 
         final String updatedTitle = normalizeHyphen(title);
         final String updatedSummaryOn = normalizeHyphen(summaryOn);
@@ -963,7 +970,8 @@
                 updatedTitle, normalizedTitle, updatedSummaryOn, normalizedSummaryOn,
                 updatedSummaryOff, normalizedSummaryOff, entries,
                 className, screenTitle, iconResId,
-                rank, keywords, intentAction, intentTargetPackage, intentTargetClass, enabled, key);
+                rank, keywords, intentAction, intentTargetPackage, intentTargetClass, enabled,
+                key, userId);
     }
 
     private static String normalizeHyphen(String input) {
@@ -983,7 +991,7 @@
             String updatedSummaryOff, String normalizedSummaryOff, String entries,
             String className, String screenTitle, int iconResId, int rank, String keywords,
             String intentAction, String intentTargetPackage, String intentTargetClass,
-            boolean enabled, String key) {
+            boolean enabled, String key, int userId) {
 
         if (TextUtils.isEmpty(updatedTitle)) {
             return;
@@ -1009,6 +1017,7 @@
         values.put(IndexColumns.ICON, iconResId);
         values.put(IndexColumns.ENABLED, enabled);
         values.put(IndexColumns.DATA_KEY_REF, key);
+        values.put(IndexColumns.USER_ID, userId);
 
         database.replaceOrThrow(Tables.TABLE_PREFS_INDEX, null, values);
     }
diff --git a/src/com/android/settings/search/IndexDatabaseHelper.java b/src/com/android/settings/search/IndexDatabaseHelper.java
index b697c30..152cbf3 100644
--- a/src/com/android/settings/search/IndexDatabaseHelper.java
+++ b/src/com/android/settings/search/IndexDatabaseHelper.java
@@ -28,7 +28,7 @@
     private static final String TAG = "IndexDatabaseHelper";
 
     private static final String DATABASE_NAME = "search_index.db";
-    private static final int DATABASE_VERSION = 114;
+    private static final int DATABASE_VERSION = 115;
 
     public interface Tables {
         public static final String TABLE_PREFS_INDEX = "prefs_index";
@@ -56,6 +56,7 @@
         public static final String ICON = "icon";
         public static final String ENABLED = "enabled";
         public static final String DATA_KEY_REF = "data_key_reference";
+        public static final String USER_ID = "user_id";
     }
 
     public interface MetaColumns {
@@ -105,6 +106,8 @@
                     IndexColumns.ENABLED +
                     ", " +
                     IndexColumns.DATA_KEY_REF +
+                    ", " +
+                    IndexColumns.USER_ID +
                     ");";
 
     private static final String CREATE_META_TABLE =
diff --git a/src/com/android/settings/search/Ranking.java b/src/com/android/settings/search/Ranking.java
index 0d53d85..fbb6f99 100644
--- a/src/com/android/settings/search/Ranking.java
+++ b/src/com/android/settings/search/Ranking.java
@@ -30,6 +30,7 @@
 import com.android.settings.WirelessSettings;
 import com.android.settings.accessibility.AccessibilitySettings;
 import com.android.settings.bluetooth.BluetoothSettings;
+import com.android.settings.bluetooth.MessageAccessSettings;
 import com.android.settings.deviceinfo.Memory;
 import com.android.settings.fuelgauge.BatterySaverSettings;
 import com.android.settings.fuelgauge.PowerUsageSummary;
@@ -90,6 +91,7 @@
 
         // BT
         sRankMap.put(BluetoothSettings.class.getName(), RANK_BT);
+        sRankMap.put(MessageAccessSettings.class.getName(), RANK_BT);
 
         // DataUsage
         sRankMap.put(DataUsageSummary.class.getName(), RANK_DATA_USAGE);
diff --git a/src/com/android/settings/search/SearchIndexableResources.java b/src/com/android/settings/search/SearchIndexableResources.java
index 4e35a72..0a3ec2a 100644
--- a/src/com/android/settings/search/SearchIndexableResources.java
+++ b/src/com/android/settings/search/SearchIndexableResources.java
@@ -33,6 +33,7 @@
 import com.android.settings.WirelessSettings;
 import com.android.settings.accessibility.AccessibilitySettings;
 import com.android.settings.bluetooth.BluetoothSettings;
+import com.android.settings.bluetooth.MessageAccessSettings;
 import com.android.settings.deviceinfo.Memory;
 import com.android.settings.fuelgauge.BatterySaverSettings;
 import com.android.settings.fuelgauge.PowerUsageSummary;
@@ -87,6 +88,13 @@
                         BluetoothSettings.class.getName(),
                         R.drawable.ic_settings_bluetooth2));
 
+        sResMap.put(MessageAccessSettings.class.getName(),
+                new SearchIndexableResource(
+                        Ranking.getRankForClassName(MessageAccessSettings.class.getName()),
+                        NO_DATA_RES_ID,
+                        MessageAccessSettings.class.getName(),
+                        R.drawable.ic_settings_bluetooth2));
+
         sResMap.put(DataUsageSummary.class.getName(),
                 new SearchIndexableResource(
                         Ranking.getRankForClassName(DataUsageSummary.class.getName()),
diff --git a/src/com/android/settings/widget/ProportionalOuterFrame.java b/src/com/android/settings/widget/ProportionalOuterFrame.java
deleted file mode 100644
index d23d2c4..0000000
--- a/src/com/android/settings/widget/ProportionalOuterFrame.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2011 Google Inc.
- *
- * 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.widget;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.RelativeLayout;
-
-import com.android.settings.R;
-
-/**
- * Used as the outer frame of all setup wizard pages that need to adjust their margins based
- * on the total size of the available display. (e.g. side margins set to 10% of total width.)
- */
-public class ProportionalOuterFrame extends RelativeLayout {
-    public ProportionalOuterFrame(Context context) {
-        super(context);
-    }
-
-    public ProportionalOuterFrame(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    public ProportionalOuterFrame(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-    }
-
-    /**
-     * Set our margins and title area height proportionally to the available display size
-     */
-    @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        final int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
-        final int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
-        final Resources res = getContext().getResources();
-        final float titleHeight = res.getFraction(R.dimen.setup_title_height, 1, 1);
-        final float sideMargin = res.getFraction(R.dimen.setup_border_width, 1, 1);
-        final int bottom = res.getDimensionPixelSize(R.dimen.setup_margin_bottom);
-        setPaddingRelative((int) (parentWidth * sideMargin), 0,
-                (int) (parentWidth * sideMargin), bottom);
-        final View title = findViewById(R.id.title_area);
-        if (title != null) {
-            title.setMinimumHeight((int) (parentHeight * titleHeight));
-        }
-        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-    }
-}
diff --git a/src/com/android/settings/widget/SetupWizardHeader.java b/src/com/android/settings/widget/SetupWizardHeader.java
new file mode 100644
index 0000000..43c8676
--- /dev/null
+++ b/src/com/android/settings/widget/SetupWizardHeader.java
@@ -0,0 +1,135 @@
+/*
+ * 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.widget;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.widget.FrameLayout;
+
+/*
+ * Copied from com.google.android.setupwizard.util.SetupWizardHeader
+ */
+public class SetupWizardHeader extends FrameLayout {
+
+    // Size the baseline grid in pixels
+    private float mBaselineGridSize;
+    private Drawable mBackground;
+    private Drawable mForeground;
+    private int mForegroundHeight;
+    private float mScale = 1.0f;
+
+    public SetupWizardHeader(Context context) {
+        super(context);
+        init();
+    }
+
+    public SetupWizardHeader(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        initFromAttributes(context, attrs);
+    }
+
+    public SetupWizardHeader(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        initFromAttributes(context, attrs);
+    }
+
+    public SetupWizardHeader(Context context, AttributeSet attrs, int defStyleAttr,
+                             int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+        initFromAttributes(context, attrs);
+    }
+
+    private void initFromAttributes(Context context, AttributeSet attrs) {
+        TypedArray a = context.obtainStyledAttributes(attrs,
+                new int[] { android.R.attr.foreground });
+        setForeground(a.getDrawable(0));
+        init();
+    }
+
+    protected void init() {
+        // Number of pixels of the 8dp baseline grid as defined in material design specs
+        mBaselineGridSize = getResources().getDisplayMetrics().density * 8;
+        setWillNotDraw(false);
+    }
+
+    /**
+     * The background will be drawn to fill up the rest of the view. It will also be scaled by the
+     * same amount as the foreground so their textures look the same.
+     */
+    @Override
+    public void setBackground(Drawable background) {
+        mBackground = background;
+    }
+
+    /**
+     * Sets the drawable used as the illustration. THe drawable is expected to have intrinsic
+     * width and height defined and will be scaled to fit the width of the view.
+     */
+    public void setForeground(Drawable foreground) {
+        mForeground = foreground;
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        int illustrationHeight = MeasureSpec.getSize(widthMeasureSpec) / 2;
+        illustrationHeight -= illustrationHeight % mBaselineGridSize;
+        setPadding(0, illustrationHeight, 0, 0);
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        final int layoutWidth = right - left;
+        final int layoutHeight = bottom - top;
+        if (mForeground != null) {
+            // Scale the foreground to fill the width of the view
+            mScale = layoutWidth / (float) mForeground.getIntrinsicWidth();
+            mForegroundHeight = (int) (mForeground.getIntrinsicHeight() * mScale);
+            mForeground.setBounds(0, 0, layoutWidth, mForegroundHeight);
+        }
+        if (mBackground != null) {
+            // Scale the bounds by mScale to compensate for the scale done to the canvas before
+            // drawing.
+            mBackground.setBounds(0, 0, (int) (layoutWidth / mScale),
+                    (int) ((layoutHeight - mForegroundHeight) / mScale));
+        }
+        super.onLayout(changed, left, top, right, bottom);
+    }
+
+    @Override
+    public void onDraw(Canvas canvas) {
+        if (mBackground != null) {
+            // Draw the background filling parts not covered by the illustration
+            int saveCount = canvas.save();
+            canvas.translate(0, mForegroundHeight);
+            // Scale the background so its size matches the foreground
+            canvas.scale(mScale, mScale, 0, 0);
+            mBackground.draw(canvas);
+            canvas.restoreToCount(saveCount);
+        }
+        if (mForeground != null) {
+            // Draw the illustration
+            mForeground.draw(canvas);
+        }
+        super.onDraw(canvas);
+    }
+}
+
diff --git a/src/com/android/settings/widget/StickyHeaderListView.java b/src/com/android/settings/widget/StickyHeaderListView.java
new file mode 100644
index 0000000..f95f8f3
--- /dev/null
+++ b/src/com/android/settings/widget/StickyHeaderListView.java
@@ -0,0 +1,139 @@
+/*
+ * 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.widget;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.RectF;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.WindowInsets;
+import android.widget.ListView;
+
+/**
+ * This class provides sticky header functionality in a list view, to use with SetupWizardHeader.
+ * To use this, add a header tagged with "sticky", or a header tagged with "stickyContainer" and
+ * one of its child tagged as "sticky". The sticky container will be draw when the sticky element
+ * hits the top of the view.
+ *
+ * There are a few things to note:
+ * 1. The two supported scenarios are StickyHeaderListView -> Header (stickyContainer) -> sticky,
+ *    and StickyHeaderListView -> Header (sticky). The arrow (->) represents parent/child
+ *    relationship and must be immediate child.
+ * 2. The view does not work well with padding. b/16190933
+ * 3. If fitsSystemWindows is true, then this will offset the sticking position by the height of
+ *    the system decorations at the top of the screen.
+ *
+ * @see com.google.android.setupwizard.util.SetupWizardHeader
+ * @see com.google.android.setupwizard.util.StickyHeaderScrollView
+ *
+ * Copied from com.google.android.setupwizard.util.StickyHeaderListView
+ */
+public class StickyHeaderListView extends ListView {
+
+    private View mSticky;
+    private View mStickyContainer;
+    private boolean mDrawScrollBar;
+    private int mStatusBarInset = 0;
+    private RectF mStickyRect = new RectF();
+
+    public StickyHeaderListView(Context context) {
+        super(context);
+    }
+
+    public StickyHeaderListView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public StickyHeaderListView(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    public StickyHeaderListView(Context context, AttributeSet attrs, int defStyleAttr,
+                                int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        super.onLayout(changed, l, t, r, b);
+        if (mSticky == null) {
+            updateStickyView();
+        }
+    }
+
+    public void updateStickyView() {
+        mSticky = findViewWithTag("sticky");
+        mStickyContainer = findViewWithTag("stickyContainer");
+    }
+
+    @Override
+    public boolean dispatchTouchEvent(MotionEvent ev) {
+        if (mStickyRect.contains(ev.getX(), ev.getY())) {
+            ev.offsetLocation(-mStickyRect.left, -mStickyRect.top);
+            return mStickyContainer.dispatchTouchEvent(ev);
+        } else {
+            return super.dispatchTouchEvent(ev);
+        }
+    }
+
+    @Override
+    public void draw(Canvas canvas) {
+        mDrawScrollBar = false;
+        super.draw(canvas);
+        if (mSticky != null) {
+            final int saveCount = canvas.save();
+            // The view to draw when sticking to the top
+            final View drawTarget = mStickyContainer != null ? mStickyContainer : mSticky;
+            // The offset to draw the view at when sticky
+            final int drawOffset = mStickyContainer != null ? mSticky.getTop() : 0;
+            // Position of the draw target, relative to the outside of the scrollView
+            final int drawTop = drawTarget.getTop();
+            if (drawTop + drawOffset < mStatusBarInset || !drawTarget.isShown()) {
+                // ListView does not translate the canvas, so we can simply draw at the top
+                canvas.translate(0, -drawOffset + mStatusBarInset);
+                canvas.clipRect(0, 0, drawTarget.getWidth(), drawTarget.getHeight());
+                drawTarget.draw(canvas);
+                mStickyRect.set(0, -drawOffset + mStatusBarInset, drawTarget.getWidth(),
+                        drawTarget.getHeight() - drawOffset + mStatusBarInset);
+            } else {
+                mStickyRect.setEmpty();
+            }
+            canvas.restoreToCount(saveCount);
+        }
+        // Draw the scrollbars last so they are on top of the header
+        mDrawScrollBar = true;
+        onDrawScrollBars(canvas);
+    }
+
+    @Override
+    protected boolean isVerticalScrollBarHidden() {
+        return super.isVerticalScrollBarHidden() || !mDrawScrollBar;
+    }
+
+    @Override
+    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
+        if (getFitsSystemWindows()) {
+            mStatusBarInset = insets.getSystemWindowInsetTop();
+            insets.consumeSystemWindowInsets(false, true, false, false);
+        }
+        return insets;
+    }
+}
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index 0cb25c3..1237715 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -940,6 +940,7 @@
                 SearchIndexableRaw data = new SearchIndexableRaw(context);
                 data.title = res.getString(R.string.wifi_settings);
                 data.screenTitle = res.getString(R.string.wifi_settings);
+                data.keywords = res.getString(R.string.keywords_wifi);
                 result.add(data);
 
                 // Add available Wi-Fi access points
diff --git a/src/com/android/settings/wifi/WifiSettingsForSetupWizard.java b/src/com/android/settings/wifi/WifiSettingsForSetupWizard.java
index b64e781..888396d 100644
--- a/src/com/android/settings/wifi/WifiSettingsForSetupWizard.java
+++ b/src/com/android/settings/wifi/WifiSettingsForSetupWizard.java
@@ -34,8 +34,10 @@
 import android.view.View.OnClickListener;
 import android.view.ViewGroup;
 import android.widget.ImageButton;
+import android.widget.ListView;
 import android.widget.PopupMenu;
 import android.widget.PopupMenu.OnMenuItemClickListener;
+import android.widget.TextView;
 
 import com.android.settings.R;
 
@@ -88,7 +90,16 @@
             Bundle savedInstanceState) {
 
         final View view = inflater.inflate(R.layout.setup_preference, container, false);
-        final View other = view.findViewById(R.id.other_network);
+
+        final ListView list = (ListView) view.findViewById(android.R.id.list);
+        final View title = view.findViewById(R.id.title);
+        if (title == null) {
+            final View header = inflater.inflate(R.layout.setup_wizard_header, list, false);
+            list.addHeaderView(header);
+        }
+
+        final View other = inflater.inflate(R.layout.setup_wifi_add_network, list, false);
+        list.addFooterView(other, null, true);
         other.setOnClickListener(new OnClickListener() {
             @Override
             public void onClick(View v) {
@@ -97,29 +108,6 @@
                 }
             }
         });
-        final ImageButton b = (ImageButton) view.findViewById(R.id.more);
-        if (b != null) {
-            b.setOnClickListener(new OnClickListener() {
-                @Override
-                public void onClick(View v) {
-                    if (mWifiManager.isWifiEnabled()) {
-                        PopupMenu pm = new PopupMenu(inflater.getContext(), b);
-                        pm.inflate(R.menu.wifi_setup);
-                        pm.setOnMenuItemClickListener(new OnMenuItemClickListener() {
-                            @Override
-                            public boolean onMenuItemClick(MenuItem item) {
-                                if (R.id.wifi_wps == item.getItemId()) {
-                                    showDialog(WPS_PBC_DIALOG_ID);
-                                    return true;
-                                }
-                                return false;
-                            }
-                        });
-                        pm.show();
-                    }
-                }
-            });
-        }
 
         final Intent intent = getActivity().getIntent();
         if (intent.getBooleanExtra(EXTRA_SHOW_WIFI_REQUIRED_INFO, false)) {
@@ -206,5 +194,4 @@
                 .setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
         ta.recycle();
     }
-
 }