Merge "Use a different wallpaper fragment title from the preference item."
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 69ec091..22b2226 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -270,6 +270,24 @@
                 android:value="com.android.settings.Settings$WirelessSettingsActivity" />
         </activity-alias>
 
+        <activity android:name="Settings$WifiP2pSettingsActivity"
+                android:clearTaskOnLaunch="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.VOICE_LAUNCH" />
+            </intent-filter>
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                android:value="com.android.settings.WifiP2pSettings" />
+            <meta-data android:name="com.android.settings.TOP_LEVEL_HEADER_ID"
+                android:resource="@id/wireless_settings" />
+            <meta-data android:name="com.android.settings.PARENT_FRAGMENT_TITLE"
+                android:resource="@string/wireless_networks_settings_title" />
+            <meta-data android:name="com.android.settings.PARENT_FRAGMENT_CLASS"
+                android:value="com.android.settings.Settings$WirelessSettingsActivity" />
+        </activity>
+
+
         <activity android:name="Settings$VpnSettingsActivity"
                 android:label="@string/vpn_settings_title"
                 android:clearTaskOnLaunch="true">
@@ -346,6 +364,26 @@
                 android:resource="@id/language_settings" />
         </activity>
 
+        <activity android:name="Settings$SpellCheckersSettingsActivity"
+                android:label="@string/spellcheckers_settings_title"
+                android:clearTaskOnLaunch="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <action android:name="com.android.settings.VOICE_INPUT_OUTPUT_SETTINGS" />
+                <category android:name="android.intent.category.VOICE_LAUNCH" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="com.android.settings.SHORTCUT" />
+            </intent-filter>
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                android:value="com.android.settings.inputmethod.SpellCheckersSettings" />
+            <meta-data android:name="com.android.settings.TOP_LEVEL_HEADER_ID"
+                android:resource="@id/language_settings" />
+            <meta-data android:name="com.android.settings.PARENT_FRAGMENT_TITLE"
+                android:resource="@string/language_keyboard_settings_title" />
+            <meta-data android:name="com.android.settings.PARENT_FRAGMENT_CLASS"
+                android:value="com.android.settings.Settings$InputMethodAndLanguageSettingsActivity" />
+        </activity>
+
         <activity android:name=".inputmethod.InputMethodAndSubtypeEnablerActivity"
                 android:label=""
                 android:clearTaskOnLaunch="true">
@@ -653,12 +691,15 @@
         </activity>
 
         <activity android:name="Settings$AccessibilitySettingsActivity"
-                android:label="@string/accessibility_settings_title">
+                android:label="@string/accessibility_settings_title"
+                android:configChanges="orientation|keyboardHidden|screenSize"
+                android:clearTaskOnLaunch="true">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <action android:name="android.settings.ACCESSIBILITY_SETTINGS" />
                 <category android:name="android.intent.category.DEFAULT" />
                 <category android:name="android.intent.category.VOICE_LAUNCH" />
+                <category android:name="com.android.settings.SHORTCUT" />
             </intent-filter>
             <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
                 android:value="com.android.settings.AccessibilitySettings" />
@@ -934,7 +975,7 @@
                 android:label="@string/accessibility_tutorial_title"
                 android:configChanges="orientation"
                 android:immersive="true"
-                android:theme="@android:style/Theme.Holo.NoActionBar">
+                android:theme="@style/Theme.AccessibilityTutorialActivity">
             <intent-filter>
                 <action android:name="android.settings.ACCESSIBILITY_TUTORIAL" />
                 <category android:name="android.intent.category.DEFAULT" />
diff --git a/res/layout/bluetooth_device_picker.xml b/res/layout/bluetooth_device_picker.xml
old mode 100644
new mode 100755
index c554ade..0a63e25
--- a/res/layout/bluetooth_device_picker.xml
+++ b/res/layout/bluetooth_device_picker.xml
@@ -16,7 +16,7 @@
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:orientation="vertical"
-    android:layout_width="600dip"
+    android:layout_width="match_parent"
     android:layout_height="match_parent">
 
     <fragment
diff --git a/res/layout/text_description_preference.xml b/res/layout/text_description_preference.xml
new file mode 100644
index 0000000..c5084034
--- /dev/null
+++ b/res/layout/text_description_preference.xml
@@ -0,0 +1,30 @@
+<?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:orientation="vertical" >
+
+    <TextView
+        android:id="@+id/summary"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textAppearance="?android:attr/textAppearanceSmall"
+        android:textColor="?android:attr/textColorSecondary"
+        android:padding="16dip" />
+
+</LinearLayout>
diff --git a/res/layout/wifi_p2p_dialog.xml b/res/layout/wifi_p2p_dialog.xml
new file mode 100644
index 0000000..7a86c1e
--- /dev/null
+++ b/res/layout/wifi_p2p_dialog.xml
@@ -0,0 +1,88 @@
+<?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.
+-->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+         android:layout_width="300sp"
+         android:layout_height="wrap_content">
+
+    <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:padding="8dip"
+            android:orientation="vertical">
+
+        <LinearLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="vertical" />
+
+            <TextView
+                    style="?android:attr/textAppearanceSmall"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_marginTop="8dip"
+                    android:text="@string/wifi_p2p_device_info" />
+
+            <TextView android:id="@+id/device_name"
+                    style="?android:attr/textAppearanceMedium"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_marginTop="8dip" />
+
+            <TextView android:id="@+id/device_address"
+                    style="?android:attr/textAppearanceMedium"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_marginTop="8dip" />
+
+            <TextView
+                    style="?android:attr/textAppearanceSmall"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_marginTop="8dip"
+                    android:text="@string/wifi_p2p_wps_setup" />
+
+            <Spinner android:id="@+id/wps_setup"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:prompt="@string/wifi_p2p_wps_setup"
+                    android:entries="@array/wifi_p2p_wps_setup" />
+
+           <LinearLayout android:id="@+id/wps_pin_entry"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="vertical"
+                android:visibility="gone">
+
+                <TextView
+                    style="@style/wifi_item_label"
+                    android:text="@string/wifi_p2p_wps_pin" />
+
+                <EditText android:id="@+id/wps_pin"
+                    style="@style/wifi_item_content"
+                    android:singleLine="true"
+                    android:inputType="textPassword" />
+            </LinearLayout>
+
+
+            <CheckBox android:id="@+id/persist_network"
+                    style="?android:attr/textAppearanceSmall"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:text="@string/wifi_p2p_persist_network" />
+
+   </LinearLayout>
+</ScrollView>
diff --git a/res/values-sw600dp/themes.xml b/res/values-sw600dp/themes.xml
new file mode 100644
index 0000000..22cf17e
--- /dev/null
+++ b/res/values-sw600dp/themes.xml
@@ -0,0 +1,21 @@
+<?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.
+-->
+
+<resources>
+
+    <style name="Theme.AccessibilityTutorialActivity" parent="@android:style/Theme.Holo.NoActionBar">
+    </style>
+</resources>
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index f2b939d..ed4ebbb 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -324,6 +324,28 @@
         <item>TTLS</item>
     </string-array>
 
+   <!-- Wi-Fi WPS setup for p2p connections.  -->
+   <!-- Note that adding/removing/moving the items will need wifi settings code change. -->
+    <string-array name="wifi_p2p_wps_setup">
+        <!-- Push button based configuration involves pushing a button on two connecting devices [CHAR LIMIT=30]-->
+        <item>Push button</item>
+        <!-- This involves entering a pin obtained from a peer device [CHAR LIMIT=30] -->
+        <item>Pin from peer device</item>
+        <!-- This involves generating a pin from this device [CHAR LIMIT=20] -->
+        <item>Pin from this device</item>
+    </string-array>
+
+    <!-- Match this with the order of WifiP2pDevice.Status -->
+    <!-- Wi-Fi p2p settings device status message -->
+    <string-array name="wifi_p2p_status">
+        <item>Connected</item>
+        <item>Invited</item>
+        <item>Failed</item>
+        <item>Available</item>
+        <item>Out of range</item>
+   </string-array>
+
+
     <!-- Bluetooth Settings -->
 
     <!-- Discoverable mode timeout options -->
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 282030f..0291fa2 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -290,9 +290,12 @@
     <string name="bluetooth_ask_enablement_and_lasting_discovery" product="tablet">"An application on your tablet is requesting permission to turn on Bluetooth and to make your tablet discoverable by other devices. Do you want to do this?"</string>
     <string name="bluetooth_ask_enablement_and_lasting_discovery" product="default">"An application on your phone is requesting permission to turn on Bluetooth and to make your phone discoverable by other devices. Do you want to do this?"</string>
 
-    <!-- Strings for msg to display to user while bluetooth is turning on -->
+    <!-- Strings for msg to display to user while bluetooth is turning on [CHAR LIMIT=60] -->
     <string name="bluetooth_turning_on">"Turning Bluetooth on\u2026"</string>
 
+    <!-- Strings for msg to display to user while bluetooth is turning off [CHAR LIMIT=60] -->
+    <string name="bluetooth_turning_off">"Turning Bluetooth off\u2026"</string>
+
     <!-- Strings for device profile auto connect setting -->
     <string name="bluetooth_auto_connect">Auto connect</string>
 
@@ -1272,6 +1275,23 @@
     <!-- Hint text for network prefix length -->
     <string name="wifi_network_prefix_length_hint" translatable="false">24</string>
 
+
+    <!-- Wi-Fi p2p / Wi-Fi Direct settings -->
+    <!-- Used in the 1st-level settings screen to launch Wi-fi Direct settings [CHAR LIMIT=25] -->
+    <string name="wifi_p2p_settings_title">Wi-Fi Direct</string>
+    <!-- Summary for Wi-fi Direct settings item in the 1st-level settings screen [CHAR LIMIT=50]-->
+    <string name="wifi_p2p_settings_summary">Setup peer-to-peer connectivity</string>
+    <string name="wifi_p2p_device_info">Device Information</string>
+    <string name="wifi_p2p_wps_setup">Wi-Fi Protected Setup</string>
+    <string name="wifi_p2p_wps_pin">Enter pin</string>
+    <string name="wifi_p2p_persist_network">Remember this connection</string>
+    <!-- Menu option to discover peers-->
+    <string name="wifi_p2p_menu_search">Search</string>
+    <!-- Menu option to create a group-->
+    <string name="wifi_p2p_menu_create_group">Create group</string>
+    <!-- Menu option to Wi-Fi p2p advanced settings -->
+    <string name="wifi_p2p_menu_advanced">Advanced</string>
+
     <!-- Wifi AP settings-->
     <!-- Label for wifi tether checkbox. Toggles Access Point on/off -->
     <string name="wifi_tether_checkbox_text">Portable Wi-Fi hotspot</string>
@@ -2644,78 +2664,73 @@
     <string name="accessibility_settings">Accessibility</string>
     <!-- Settings title for accessibility settings screen -->
     <string name="accessibility_settings_title">Accessibility settings</string>
-    <!-- Settings summary for accessibility settings [CHAR LIMIT=40] -->
-    <string name="accessibility_settings_summary">Manage accessibility options</string>
-    <!-- Setting Checkbox title for enabling accessibility large text [CHAR LIMIT=25] -->
-    <string name="toggle_large_text_title">Large text</string>
-    <!-- Setting accessibility services category [CHAR LIMIT=25] -->
-    <string name="accessibility_services_category">Accessibility services</string>
-    <!-- Setting Checkbox title for enabling accessibility services [CHAR LIMIT=40] -->
-    <string name="toggle_accessibility_title">Allow accessibility services</string>
-    <!-- Setting Checkbox title for enabling touch exploration mode [CHAR LIMIT=40] -->
-    <string name="accessibility_touch_exploration_title">Enable touch exploration mode</string>
-    <!-- Setting Checkbox summary for enabling touch exploration mode [CHAR LIMIT=65] -->
-    <string name="accessibility_touch_exploration_summary">Allows you to touch the screen to hear the contents under your finger.</string>
-    <!-- Warning message describing changes in interaction from enabling touch exploration mode
-         and suggesting that the user goes through a tutorial, displayed as a dialog message the
-         first time the user selects to enable touch exploration -->
-    <string name="accessibility_touch_exploration_warning">Touch exploration mode changes the way your
-        device handles touch input. Would you like to take a short tutorial on using touch exploration?</string>
-    <!-- Message for announcing the lack of installed accessibility services. -->
-    <string name="no_accessibility_services_summary">No installed accessibility services.</string>
+
+    <!--  Title for the accessibility preference category of accessibility services. [CHAR LIMIT=25] -->
+    <string name="accessibility_services_title">Services</string>
+
+    <!-- Title for the accessibility preference category of system related preferences. [CHAR LIMIT=25] -->
+    <string name="accessibility_system_title">System</string>
+    <!-- Title for the accessibility preference to enable large text. [CHAR LIMIT=35] -->
+    <string name="accessibility_toggle_large_text_title">Large text</string>
+    <!-- Title for the accessibility preference to power button to end a call. [CHAR LIMIT=35] -->
+    <string name="accessibility_power_button_ends_call_title">Power button ends call</string>
+    <!-- Title for accessibility preference to enable touch exploration mode. [CHAR LIMIT=35] -->
+    <string name="accessibility_touch_exploration_title">Explore by touch</string>
+    <!-- Summary for accessibility of the touch exploration mode. [CHAR LIMIT=NONE] -->
+    <string name="accessibility_touch_exploration_summary" >Allows exploring screen content and interacting with the device.\n\n
+        Touch the screen to receive feedback of the content under your finger.\n\n Tap on the last explored location to activate.\n\n
+        Use two fingers to drag. </string>
+    <!-- Title for accessibility preference to choose long-press delay i.e. timeout before it is detected. [CHAR LIMIT=35] -->
+    <string name="accessibility_long_press_timeout_title">Touch &amp; hold delay</string>
+    <!-- Title for accessibility preference to install accessibility scripts from Google. [CHAR LIMIT=35] -->
+    <string name="accessibility_script_injection_title">Install accessibility scripts</string>
+
+    <!-- Title for accessibility menu item to lauch a settings activity. [CHAR LIMIT=15] -->
+    <string name="accessibility_menu_item_settings">Settings</string>
+    <!-- Title for accessibility menu item to lauch a tutorial. [CHAR LIMIT=15] -->
+    <string name="accessibility_menu_item_tutorial">Tutorial</string>
+
+    <!-- Summary for the enabled state of an accessiblity serivce. [CHAR LIMIT=10] -->
+    <string name="accessibility_service_state_on">On</string>
+    <!-- Summary for the disabled state of an accessiblity serivce. [CHAR LIMIT=10] -->
+    <string name="accessibility_service_state_off">Off</string>
+
+    <!-- Summary for the allowed state of script injection. [CHAR LIMIT=15] -->
+    <string name="accessibility_script_injection_allowed">Allowed</string>
+    <!-- Summary for the disallowed state of script injection. [CHAR LIMIT=15] -->
+    <string name="accessibility_script_injection_disallowed">Disallowed</string>
+
+    <!-- Title for the dialog button to allow script injection. [CHAR LIMIT=15] -->
+    <string name="accessibility_script_injection_button_allow">Allow</string>
+    <!-- Title for the dialog button to disallow script injection. [CHAR LIMIT=15] -->
+    <string name="accessibility_script_injection_button_disallow">Don\'t Allow</string>
+
     <!-- Warning message about security implications of enabling an accessibility service,
-         displayed as a dialog message when the user selects to enable an accessibility service. -->
+         displayed as a dialog message when the user selects to enable an accessibility service. [CHAR LIMIT=NONE] -->
     <string name="accessibility_service_security_warning">This accessibility service may be able to collect
         all the text you type, including personal data credit card numbers except passwords.
         It may also log your user interface interactions. It comes from the application
         <xliff:g id="accessibility_service_name">%1$s</xliff:g>. Use this accessibility service?</string>
     <!-- Warning about disabling accessibility displayed as a dialog message when the user
-         selects to disable accessibility. This avoids accidental disabling. -->
+         selects to disable accessibility. This avoids accidental disabling. [CHAR LIMIT=NONE] -->
     <string name="accessibility_service_disable_warning">Disable accessibility?</string>
     <!-- Title for the prompt that lets users know that they have no accessibility related apps
-         installed and that they can install TalkBack from Market. -->
+         installed and that they can install TalkBack from Market. [CHAR LIMIT=50] -->
     <string name="accessibility_service_no_apps_title">No accessibility related applications found
         </string>
     <!-- Message for the prompt that lets users know that they have no accessibility related apps
-         installed and that they can install TalkBack from Market. -->
+         installed and that they can install TalkBack from Market. [CHAR LIMIT=NONE] -->
     <string name="accessibility_service_no_apps_message">You do not have any accessibility-related
         applications installed.\n\nYou can download a screen reader for your device from Android
         Market.\n\nClick "OK" to install the screen reader.</string>
-
-    <!-- Accessibility settings: Checkbox title for enabling download of accessibility scripts [CHAR LIMIT=40] -->
-    <string name="accessibility_script_injection_enabled">Download accessibility scripts</string>
-    <!-- Accessibility settings: Checkbox summary for enabling download of accessibility scripts [CHAR LIMIT=65] -->
-    <string name="accessibility_script_injection_enabled_summary">Allow applications to download accessibility scripts from Google</string>
     <!-- Warning message about security implications of downloading accessibility scripts,
-         displayed as a dialog message when the user selects to enable script downloading. [CHAR LIMIT="NONE"] -->
-    <string name="accessibility_script_injection_security_warning" product="tablet">Some applications can ask Google
-        to download scripts to your tablet that make their content more accessible. Are you sure you
-        want to allow Google to install accessibility scripts on your tablet?</string>
-    <!-- Warning message about security implications of downloading accessibility scripts,
-         displayed as a dialog message when the user selects to enable script downloading. [CHAR LIMIT="NONE"] -->
-    <string name="accessibility_script_injection_security_warning" product="default">Some applications can ask Google
-        to download scripts to your phone that make their content more accessible. Are you sure you
-        want to allow Google to install accessibility scripts on your phone?</string>
-    <!-- Accessibility settings: Power button category -->
-    <string name="accessibility_power_button_category">Power button</string>
-    <!-- Accessibility settings: checkbox title for power button behavior -->
-    <string name="accessibility_power_button_ends_call">Power button ends call</string>
-    <!-- Accessibility settings: power button behavior summary text -->
-    <string name="accessibility_power_button_ends_call_summary">During a call, pressing Power ends call instead of turning off screen</string>
-    <!-- Accessibility settings: touch exploration state -->
-    <string name="accessibility_touch_exploration_enabled">Touch exploration</string>
-
-    <!-- Accessibility settings: button for lauching settings for an accessibility service -->
-    <string name="settings_button">Settings</string>
-
-    <!-- Setting interaction category [CHAR LIMIT=35] -->
-    <string name="touchscreen_gestures_category">Touchscreen gestures</string>
-    <!-- Title for setting the long-press timeout [CHAR LIMIT=35] -->
-    <string name="long_press_timeout_selector_title">Touch &amp; hold delay</string>
-    <!-- Summary for setting the long-press timeout [CHAR LIMIT=85] -->
-    <string name="long_press_timeout_selector_summary">Delay until a touch is interpreted as a touch &amp; hold</string>
-    <!-- The default value for the long press timeout. -->
-    <string name="long_press_timeout_selector_default_value" translatable="false">500</string>
+         displayed as a dialog message when the user selects to enable script downloading. [CHAR LIMIT=NONE] -->
+    <string name="accessibility_script_injection_security_warning">Some applications can ask Google
+        to download scripts to your device that make their content more accessible. Are you sure you
+        want to allow Google to install accessibility scripts on your device?</string>
+    <!-- Warning message that the interaction model changes on enabling touch exploration. [CHAR LIMIT=NONE] -->
+    <string name="accessibility_touch_exploration_warning">Enabling explore by touch
+        changes the interation model. Enable explore by touch?</string>
 
     <!-- App Fuel Gauge strings -->
     <skip />
@@ -3205,6 +3220,13 @@
     <!-- Do not translate. This is a stub which will be removed soon. -->
     <string name="time_zone_auto_stub" translatable="false">Select Time Zone</string>
 
+    <!-- Content description of the enabled sync icon for accessibility. [CHAR LIMIT=NONE] -->
+    <string name="accessibility_sync_enabled">Sync enabled</string>
+    <!-- Content description of the disabled sync icon for accessibility. [CHAR LIMIT=NONE] -->
+    <string name="accessibility_sync_disabled">Sync disabled</string>
+    <!-- Content description of the disabled sync icon for accessibility. [CHAR LIMIT=NONE] -->
+    <string name="accessibility_sync_error">Sync error.</string>
+
     <!-- Account specific sync settings title [CHAR LIMIT=35] -->
     <string name="account_sync_settings_title">Sync settings</string>
     <!-- Message when sync is currently failing [CHAR LIMIT=100] -->
@@ -3573,4 +3595,6 @@
     <!-- Instruction for touch exploration tutorial lesson 2, displayed after the user has scrolled a large amount. -->
     <string name="accessibility_tutorial_lesson_2_text_4">You have completed the tutorial. To exit and return to the Talk As I Touch setting, find and tap the <xliff:g id="finish" example="Finish">%s</xliff:g> button.</string>
 
+    <!--  Title for spelling correction settings -->
+    <string name="spellcheckers_settings_title">Spelling correction</string>
 </resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index e9405fb..ffa7912 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -158,8 +158,8 @@
         <item name="android:layout">@layout/preference_inputmethod</item>
         <item name="android:widgetLayout">@layout/preference_inputmethod_widget</item>
     </style>
-    
-    <style name="AcessibilityTutorialButton">
+
+    <style name="AccessibilityTutorialButton">
         <item name="android:layout_width">150dip</item>
         <item name="android:layout_height">wrap_content</item>
         <item name="android:layout_margin">5dip</item>
diff --git a/res/values/themes.xml b/res/values/themes.xml
index b5f8f64..2103de1 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -19,4 +19,7 @@
     <style name="Theme.WifiDialog" parent="@*android:style/Theme.Holo.Dialog.Alert">
         <item name="android:windowSoftInputMode">adjustResize</item>
     </style>
+
+    <style name="Theme.AccessibilityTutorialActivity" parent="@android:style/Theme.Holo">
+    </style>
 </resources>
diff --git a/res/xml/accessibility_settings.xml b/res/xml/accessibility_settings.xml
index feb5fb1..78a857b 100644
--- a/res/xml/accessibility_settings.xml
+++ b/res/xml/accessibility_settings.xml
@@ -18,48 +18,48 @@
         xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
         android:title="@string/accessibility_settings_title">
 
-    <CheckBoxPreference
-            android:key="toggle_large_text_checkbox"
-            android:title="@string/toggle_large_text_title"
-            android:persistent="false"/>
-
-    <PreferenceCategory android:key="accessibility_services_category"
-            android:title="@string/accessibility_services_category">
-        <CheckBoxPreference
-                android:key="toggle_accessibility_service_checkbox"
-                android:title="@string/toggle_accessibility_title"
-                android:persistent="false"
-                android:order="-10000"/>
-        <CheckBoxPreference
-                android:key="toggle_accessibility_script_injection_checkbox"
-                android:title="@string/accessibility_script_injection_enabled"
-                android:summary="@string/accessibility_script_injection_enabled_summary"
-                android:persistent="false"
-                android:order="10000" />
+    <PreferenceCategory
+            android:key="services_category"
+            android:title="@string/accessibility_services_title">
     </PreferenceCategory>
 
-    <PreferenceCategory android:key="power_button_category"
-            android:title="@string/accessibility_power_button_category">
-        <CheckBoxPreference
-                android:key="power_button_ends_call"
-                android:title="@string/accessibility_power_button_ends_call"
-                android:summary="@string/accessibility_power_button_ends_call_summary"
-                android:persistent="false" />
-    </PreferenceCategory>
+    <PreferenceCategory
+            android:key="system_category"
+            android:title="@string/accessibility_system_title">
 
-    <PreferenceCategory android:key="touchscreen_gestures_category"
-            android:title="@string/touchscreen_gestures_category">
-        <ListPreference android:key="long_press_timeout_list_preference"
-                android:title="@string/long_press_timeout_selector_title"
-                android:summary="@string/long_press_timeout_selector_summary"
-                android:persistent="true"
+        <CheckBoxPreference
+                android:key="toggle_large_text_preference"
+                android:title="@string/accessibility_toggle_large_text_title"
+                android:persistent="false"/>
+
+        <CheckBoxPreference
+                android:key="toggle_power_button_ends_call_preference"
+                android:title="@string/accessibility_power_button_ends_call_title"
+                android:persistent="false">
+        </CheckBoxPreference>
+
+        <PreferenceScreen
+                android:key="toggle_touch_exploration_preference"
+                android:title="@string/accessibility_touch_exploration_title"
+                android:fragment="com.android.settings.AccessibilitySettings$ToggleTouchExplorationFragment" >
+                <extra android:name="title" android:value="@string/accessibility_touch_exploration_title" />
+                <extra android:name="summary" android:value="@string/accessibility_touch_exploration_summary" />
+                <extra android:name="warning_message" android:value="@string/accessibility_touch_exploration_warning" />
+                <extra android:name="settings_title" android:value="@string/accessibility_menu_item_tutorial" />
+                <extra android:name="settings_component_name" android:value="com.android.settings/com.android.settings.AccessibilityTutorialActivity" />
+        </PreferenceScreen>
+
+        <ListPreference android:key="select_long_press_timeout_preference"
+                android:title="@string/accessibility_long_press_timeout_title"
                 android:entries="@array/long_press_timeout_selector_titles"
                 android:entryValues="@array/long_press_timeout_selector_values"
-                android:defaultValue="@string/long_press_timeout_selector_default_value"/>
-        <CheckBoxPreference
-                android:key="touch_exploration_enabled"
-                android:title="@string/accessibility_touch_exploration_enabled"
+                android:persistent="true" />
+
+        <Preference
+                android:key="toggle_script_injection_preference"
+                android:title="@string/accessibility_script_injection_title"
                 android:persistent="false" />
+
     </PreferenceCategory>
 
 </PreferenceScreen>
diff --git a/res/xml/language_settings.xml b/res/xml/language_settings.xml
index fdf87fc..f696187 100644
--- a/res/xml/language_settings.xml
+++ b/res/xml/language_settings.xml
@@ -30,6 +30,10 @@
         <PreferenceScreen
                  android:key="key_user_dictionary_settings" />
 
+        <com.android.settings.inputmethod.SpellCheckersPreference
+                 android:key="spellcheckers_settings"
+                 android:title="@string/spellcheckers_settings_title"/>
+
     </PreferenceCategory>
 
     <PreferenceCategory android:key="keyboard_settings_category"
diff --git a/res/xml/spellchecker_prefs.xml b/res/xml/spellchecker_prefs.xml
new file mode 100644
index 0000000..1de0493
--- /dev/null
+++ b/res/xml/spellchecker_prefs.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+        android:title="@string/spellcheckers_settings_title">
+
+</PreferenceScreen>
diff --git a/res/xml/wifi_p2p_settings.xml b/res/xml/wifi_p2p_settings.xml
new file mode 100644
index 0000000..2b19ee9
--- /dev/null
+++ b/res/xml/wifi_p2p_settings.xml
@@ -0,0 +1,19 @@
+<?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.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+
+</PreferenceScreen>
diff --git a/res/xml/wireless_settings.xml b/res/xml/wireless_settings.xml
index c0e4a5a..1f72a93 100644
--- a/res/xml/wireless_settings.xml
+++ b/res/xml/wireless_settings.xml
@@ -45,6 +45,12 @@
         android:summary="@string/zeroclick_settings_summary" >
     </PreferenceScreen>
 
+    <PreferenceScreen
+        android:fragment="com.android.settings.WifiP2pSettings"
+        android:key="wifi_p2p_settings"
+        android:title="@string/wifi_p2p_settings_title"
+        android:summary="@string/wifi_p2p_settings_summary">
+    </PreferenceScreen>
 
     <PreferenceScreen
         android:key="mobile_network_settings"
diff --git a/src/com/android/settings/AccessibilitySettings.java b/src/com/android/settings/AccessibilitySettings.java
index 578268d..beef902 100644
--- a/src/com/android/settings/AccessibilitySettings.java
+++ b/src/com/android/settings/AccessibilitySettings.java
@@ -17,34 +17,50 @@
 package com.android.settings;
 
 import android.accessibilityservice.AccessibilityServiceInfo;
+import android.app.ActionBar;
+import android.app.Activity;
 import android.app.ActivityManagerNative;
 import android.app.AlertDialog;
 import android.app.Dialog;
-import android.app.Service;
+import android.content.ComponentName;
+import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.pm.ServiceInfo;
 import android.content.res.Configuration;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
 import android.os.RemoteException;
 import android.os.SystemProperties;
 import android.preference.CheckBoxPreference;
 import android.preference.ListPreference;
 import android.preference.Preference;
 import android.preference.PreferenceCategory;
-import android.preference.PreferenceGroup;
 import android.preference.PreferenceScreen;
 import android.provider.Settings;
 import android.text.TextUtils;
+import android.text.TextUtils.SimpleStringSplitter;
+import android.view.Gravity;
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
 import android.view.accessibility.AccessibilityManager;
+import android.widget.Switch;
+import android.widget.TextView;
 
+import com.android.internal.content.PackageMonitor;
+import com.android.settings.AccessibilitySettings.ToggleSwitch.OnBeforeCheckedChangeListener;
+
+import java.util.HashMap;
 import java.util.HashSet;
-import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 /**
  * Activity with the accessibility settings.
@@ -57,392 +73,335 @@
 
     private static final float LARGE_FONT_SCALE = 1.3f;
 
-    private static final String TOGGLE_LARGE_TEXT_CHECKBOX =
-        "toggle_large_text_checkbox";
+    // Timeout before we update the services if packages are added/removed since
+    // the AccessibilityManagerService has to do that processing first to generate
+    // the AccessibilityServiceInfo we need for proper presentation.
+    private static final long DELAY_UPDATE_SERVICES_PREFERENCES_MILLIS = 1000;
 
-    private static final String TOGGLE_ACCESSIBILITY_CHECKBOX =
-        "toggle_accessibility_service_checkbox";
+    private static final char ENABLED_ACCESSIBILITY_SERVICES_SEPARATOR = ':';
 
-    private static final String ACCESSIBILITY_SERVICES_CATEGORY =
-        "accessibility_services_category";
+    // Preference categories
+    private static final String SERVICES_CATEGORY = "services_category";
 
-    private static final String TOGGLE_ACCESSIBILITY_SCRIPT_INJECTION_CHECKBOX =
-        "toggle_accessibility_script_injection_checkbox";
+    // Preferences
+    private static final String TOGGLE_LARGE_TEXT_PREFERENCE = "toggle_large_text_preference";
+    private static final String TOGGLE_POWER_BUTTON_ENDS_CALL_PREFERENCE =
+        "toggle_power_button_ends_call_preference";
+    private static final String TOGGLE_TOUCH_EXPLORATION_PREFERENCE =
+        "toggle_touch_exploration_preference";
+    private static final String SELECT_LONG_PRESS_TIMEOUT_PREFERENCE =
+        "select_long_press_timeout_preference";
+    private static final String TOGGLE_SCRIPT_INJECTION_PREFERENCE =
+        "toggle_script_injection_preference";
 
-    private static final String POWER_BUTTON_CATEGORY =
-        "power_button_category";
+    // Extras passed to sub-fragments.
+    static final String EXTRA_PREFERENCE_KEY = "preference_key";
+    static final String EXTRA_CHECKED = "checked";
+    static final String EXTRA_TITLE = "title";
+    static final String EXTRA_SUMMARY = "summary";
+    static final String EXTRA_WARNING_MESSAGE = "warning_message";
+    static final String EXTRA_SETTINGS_TITLE = "settings_title";
+    static final String EXTRA_SETTINGS_COMPONENT_NAME = "settings_component_name";
 
-    private static final String POWER_BUTTON_ENDS_CALL_CHECKBOX =
-        "power_button_ends_call";
-
-    private static final String TOUCH_EXPLORATION_ENABLED_CHECKBOX =
-        "touch_exploration_enabled";
-
-    private static final String KEY_TOGGLE_ACCESSIBILITY_SERVICE_CHECKBOX =
-        "key_toggle_accessibility_service_checkbox";
-
-    private static final String KEY_LONG_PRESS_TIMEOUT_LIST_PREFERENCE =
-        "long_press_timeout_list_preference";
-
+    // Dialog IDs.
     private static final int DIALOG_ID_DISABLE_ACCESSIBILITY = 1;
     private static final int DIALOG_ID_ENABLE_SCRIPT_INJECTION = 2;
-    private static final int DIALOG_ID_ENABLE_ACCESSIBILITY_SERVICE = 3;
-    private static final int DIALOG_ID_NO_ACCESSIBILITY_SERVICES = 4;
+    private static final int DIALOG_ID_NO_ACCESSIBILITY_SERVICES = 3;
 
-    private CheckBoxPreference mToggleLargeTextCheckBox;
-    private CheckBoxPreference mToggleAccessibilityCheckBox;
-    private CheckBoxPreference mToggleScriptInjectionCheckBox;
-    private SettingsCheckBoxPreference mToggleAccessibilityServiceCheckBox;
+    // Auxiliary members.
+    private final SimpleStringSplitter mStringColonSplitter =
+        new SimpleStringSplitter(ENABLED_ACCESSIBILITY_SERVICES_SEPARATOR);
 
-    private PreferenceCategory mPowerButtonCategory;
-    private CheckBoxPreference mPowerButtonEndsCallCheckBox;
-    private CheckBoxPreference mTouchExplorationEnabledCheckBox;
-
-    private PreferenceGroup mAccessibilityServicesCategory;
-
-    private ListPreference mLongPressTimeoutListPreference;
+    private final Map<String, String> mLongPressTimeoutValuetoTitleMap =
+        new HashMap<String, String>();
 
     private final Configuration mCurConfig = new Configuration();
 
-    private Map<String, AccessibilityServiceInfo> mAccessibilityServices =
-        new LinkedHashMap<String, AccessibilityServiceInfo>();
+    private final PackageMonitor mSettingsPackageMonitor = new SettingsPackageMonitor();
 
-    private TextUtils.SimpleStringSplitter mStringColonSplitter =
-        new TextUtils.SimpleStringSplitter(':');
+    private final Handler mHandler = new Handler() {
+        @Override
+        public void dispatchMessage(Message msg) {
+            super.dispatchMessage(msg);
+            updateServicesPreferences();
+        }
+    };
+
+    // Preference controls.
+    private ToggleSwitch mToggleAccessibilitySwitch;
+
+    private PreferenceCategory mServicesCategory;
+
+    private CheckBoxPreference mToggleLargeTextPreference;
+    private CheckBoxPreference mTogglePowerButtonEndsCallPreference;
+    private Preference mTouchExplorationEnabledPreference;
+    private ListPreference mSelectLongPressTimeoutPreference;
+    private Preference mToggleScriptInjectionPreference;
 
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
-
         addPreferencesFromResource(R.xml.accessibility_settings);
-
-        mToggleLargeTextCheckBox = (CheckBoxPreference) findPreference(
-                TOGGLE_LARGE_TEXT_CHECKBOX);
-
-        mAccessibilityServicesCategory =
-            (PreferenceGroup) findPreference(ACCESSIBILITY_SERVICES_CATEGORY);
-
-        mToggleAccessibilityCheckBox = (CheckBoxPreference) findPreference(
-                TOGGLE_ACCESSIBILITY_CHECKBOX);
-
-        mToggleScriptInjectionCheckBox = (CheckBoxPreference) findPreference(
-                TOGGLE_ACCESSIBILITY_SCRIPT_INJECTION_CHECKBOX);
-
-        mPowerButtonCategory = (PreferenceCategory) findPreference(POWER_BUTTON_CATEGORY);
-        mPowerButtonEndsCallCheckBox = (CheckBoxPreference) findPreference(
-                POWER_BUTTON_ENDS_CALL_CHECKBOX);
-
-        mTouchExplorationEnabledCheckBox = (CheckBoxPreference) findPreference(
-                TOUCH_EXPLORATION_ENABLED_CHECKBOX);
-
-        mLongPressTimeoutListPreference = (ListPreference) findPreference(
-                KEY_LONG_PRESS_TIMEOUT_LIST_PREFERENCE);
-
-        // set the accessibility script injection category
-        boolean scriptInjectionEnabled = (Settings.Secure.getInt(getContentResolver(),
-                Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION, 0) == 1);
-        mToggleScriptInjectionCheckBox.setChecked(scriptInjectionEnabled);
-        mToggleScriptInjectionCheckBox.setEnabled(true);
-
-        if (KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_POWER)
-                && Utils.isVoiceCapable(getActivity())) {
-            int incallPowerBehavior = Settings.Secure.getInt(getContentResolver(),
-                    Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR,
-                    Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_DEFAULT);
-            // The checkbox is labeled "Power button ends call"; thus the in-call
-            // Power button behavior is INCALL_POWER_BUTTON_BEHAVIOR_HANGUP if
-            // checked, and INCALL_POWER_BUTTON_BEHAVIOR_SCREEN_OFF if unchecked.
-            boolean powerButtonCheckboxEnabled =
-                    (incallPowerBehavior == Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP);
-            mPowerButtonEndsCallCheckBox.setChecked(powerButtonCheckboxEnabled);
-            mPowerButtonEndsCallCheckBox.setEnabled(true);
-        } else {
-            // No POWER key on the current device or no voice capability;
-            // this entire category is irrelevant.
-            getPreferenceScreen().removePreference(mPowerButtonCategory);
-        }
-
-        boolean touchExplorationEnabled = (Settings.Secure.getInt(getContentResolver(),
-                Settings.Secure.TOUCH_EXPLORATION_REQUESTED, 0) == 1);
-        mTouchExplorationEnabledCheckBox.setChecked(touchExplorationEnabled);
-
-        mLongPressTimeoutListPreference.setOnPreferenceChangeListener(this);
+        installToggleAccessibilitySwitch();
+        findPreferences();
     }
 
     @Override
-    public void onActivityCreated(Bundle savedInstanceState) {
-        addAccessibilityServicePreferences();
-
-        final HashSet<String> enabled = new HashSet<String>();
-        String settingValue = Settings.Secure.getString(getContentResolver(),
-                Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
-        if (settingValue != null) {
-            TextUtils.SimpleStringSplitter splitter = mStringColonSplitter;
-            splitter.setString(settingValue);
-            while (splitter.hasNext()) {
-                enabled.add(splitter.next());
-            }
-        }
-
-        Map<String, AccessibilityServiceInfo> accessibilityServices = mAccessibilityServices;
-
-        for (String key : accessibilityServices.keySet()) {
-            CheckBoxPreference preference = (CheckBoxPreference) findPreference(key);
-            if (preference != null) {
-                preference.setChecked(enabled.contains(key));
-            }
-        }
-
-        int serviceState = Settings.Secure.getInt(getContentResolver(),
-            Settings.Secure.ACCESSIBILITY_ENABLED, 0);
-
-        if (!accessibilityServices.isEmpty()) {
-            if (serviceState == 1) {
-                mToggleAccessibilityCheckBox.setChecked(true);
-                if (savedInstanceState != null) {
-                    restoreInstanceState(savedInstanceState);
-                }
-            } else {
-                setAccessibilityServicePreferencesState(false);
-            }
-            mToggleAccessibilityCheckBox.setEnabled(true);
-        } else {
-            if (serviceState == 1) {
-                // no service and accessibility is enabled => disable
-                Settings.Secure.putInt(getContentResolver(),
-                    Settings.Secure.ACCESSIBILITY_ENABLED, 0);
-            }
-            mToggleAccessibilityCheckBox.setEnabled(false);
-            // Notify user that they do not have any accessibility apps
-            // installed and direct them to Market to get TalkBack
-            showDialog(DIALOG_ID_NO_ACCESSIBILITY_SERVICES);
-        }
-
-        readFontSizePreference();
-
-        super.onActivityCreated(savedInstanceState);
+    public void onResume() {
+        super.onResume();
+        updateServicesPreferences();
+        updateSystemPreferences();
+        updatePreferencesForAccessibilityState();
+        mSettingsPackageMonitor.register(getActivity(), false);
     }
 
     @Override
     public void onPause() {
         super.onPause();
-
-        persistEnabledAccessibilityServices();
-    }
-
-    @Override
-    public void onSaveInstanceState(Bundle outState) {
-        if (mToggleAccessibilityServiceCheckBox != null) {
-            outState.putString(KEY_TOGGLE_ACCESSIBILITY_SERVICE_CHECKBOX,
-                    mToggleAccessibilityServiceCheckBox.getKey());
-        }
+        mSettingsPackageMonitor.unregister();
     }
 
     public boolean onPreferenceChange(Preference preference, Object newValue) {
-        if (preference == mLongPressTimeoutListPreference) {
-            int intValue = Integer.parseInt((String) newValue);
+        if (preference == mSelectLongPressTimeoutPreference) {
+            final int intValue = Integer.parseInt((String) newValue);
             Settings.Secure.putInt(getContentResolver(),
-                Settings.Secure.LONG_PRESS_TIMEOUT, intValue);
+                    Settings.Secure.LONG_PRESS_TIMEOUT, intValue);
+            mSelectLongPressTimeoutPreference.setSummary(
+                    mLongPressTimeoutValuetoTitleMap.get(String.valueOf(intValue)));
             return true;
         }
         return false;
     }
 
-    /**
-     * Restores the instance state from <code>savedInstanceState</code>.
-     */
-    private void restoreInstanceState(Bundle savedInstanceState) {
-        String key = savedInstanceState.getString(KEY_TOGGLE_ACCESSIBILITY_SERVICE_CHECKBOX);
-        if (key != null) {
-            Preference preference = findPreference(key);
-            if (!(preference instanceof CheckBoxPreference)) {
-                throw new IllegalArgumentException(
-                        KEY_TOGGLE_ACCESSIBILITY_SERVICE_CHECKBOX
-                                + " must be mapped to an instance of a "
-                                + SettingsCheckBoxPreference.class.getName());
-            }
-            mToggleAccessibilityServiceCheckBox = (SettingsCheckBoxPreference) preference;
-        }
-    }
-
-    /**
-     * Sets the state of the preferences for enabling/disabling
-     * AccessibilityServices.
-     *
-     * @param isEnabled If to enable or disable the preferences.
-     */
-    private void setAccessibilityServicePreferencesState(boolean isEnabled) {
-        if (mAccessibilityServicesCategory == null) {
-            return;
-        }
-
-        int count = mAccessibilityServicesCategory.getPreferenceCount();
-        for (int i = 0; i < count; i++) {
-            Preference pref = mAccessibilityServicesCategory.getPreference(i);
-            if (pref != mToggleAccessibilityCheckBox) {
-                pref.setEnabled(isEnabled);
-            }
-        }
+    private void updatePreferencesForAccessibilityState() {
+        final boolean accessibilityEnabled = (Settings.Secure.getInt(getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_ENABLED, 0) == 1);
+        mServicesCategory.setEnabled(accessibilityEnabled);
+        mTouchExplorationEnabledPreference.setEnabled(accessibilityEnabled);
+        mToggleScriptInjectionPreference.setEnabled(accessibilityEnabled);
     }
 
     @Override
     public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
         final String key = preference.getKey();
-
-        if (TOGGLE_ACCESSIBILITY_CHECKBOX.equals(key)) {
-            handleEnableAccessibilityStateChange((CheckBoxPreference) preference);
-        } else if (TOGGLE_LARGE_TEXT_CHECKBOX.equals(key)) {
-            try {
-                mCurConfig.fontScale = mToggleLargeTextCheckBox.isChecked()
-                        ? LARGE_FONT_SCALE : 1;
-                ActivityManagerNative.getDefault().updatePersistentConfiguration(mCurConfig);
-            } catch (RemoteException e) {
-            }
-        } else if (POWER_BUTTON_ENDS_CALL_CHECKBOX.equals(key)) {
-            boolean isChecked = ((CheckBoxPreference) preference).isChecked();
-            // The checkbox is labeled "Power button ends call"; thus the in-call
-            // Power button behavior is INCALL_POWER_BUTTON_BEHAVIOR_HANGUP if
-            // checked, and INCALL_POWER_BUTTON_BEHAVIOR_SCREEN_OFF if unchecked.
-            Settings.Secure.putInt(getContentResolver(),
-                    Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR,
-                    (isChecked ? Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP
-                            : Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_SCREEN_OFF));
-        } else if (TOUCH_EXPLORATION_ENABLED_CHECKBOX.equals(key)) {
-            final int touchExplorationState = ((CheckBoxPreference) preference).isChecked() ? 1 : 0;
-            Settings.Secure.putInt(getContentResolver(),
-                    Settings.Secure.TOUCH_EXPLORATION_REQUESTED, touchExplorationState);
-        } else if (TOGGLE_ACCESSIBILITY_SCRIPT_INJECTION_CHECKBOX.equals(key)) {
-            handleToggleAccessibilityScriptInjection((CheckBoxPreference) preference);
-        } else if (preference instanceof CheckBoxPreference) {
-            handleEnableAccessibilityServiceStateChange((SettingsCheckBoxPreference) preference);
+        if (mToggleLargeTextPreference == preference) {
+            handleToggleLargeTextPreference((CheckBoxPreference) preference);
+            return true;
+        } else if (mTogglePowerButtonEndsCallPreference == preference) {
+            handleTogglePowerButtonEndsCallPreference((CheckBoxPreference) preference);
+            return true;
+        } else if (mToggleScriptInjectionPreference == preference) {
+            handleToggleAccessibilityScriptInjectionPreference(preference);
+            return true;
         }
-
         return super.onPreferenceTreeClick(preferenceScreen, preference);
     }
 
-    /**
-     * Handles the change of the accessibility enabled setting state.
-     *
-     * @param preference The preference for enabling/disabling accessibility.
-     */
-    private void handleEnableAccessibilityStateChange(CheckBoxPreference preference) {
-        if (preference.isChecked()) {
-            Settings.Secure.putInt(getContentResolver(),
-                Settings.Secure.ACCESSIBILITY_ENABLED, 1);
-            setAccessibilityServicePreferencesState(true);
-        } else {
-            // set right enabled state since the user may press back
-            preference.setChecked(true);
-            showDialog(DIALOG_ID_DISABLE_ACCESSIBILITY);
+    private void handleTogglePowerButtonEndsCallPreference(CheckBoxPreference preference) {
+        Settings.Secure.putInt(getContentResolver(),
+                Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR,
+                (preference.isChecked() ? Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP
+                        : Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_SCREEN_OFF));
+    }
+
+    private void handleToggleLargeTextPreference(CheckBoxPreference preference) {
+        try {
+            mCurConfig.fontScale = preference.isChecked() ? LARGE_FONT_SCALE : 1;
+            ActivityManagerNative.getDefault().updatePersistentConfiguration(mCurConfig);
+        } catch (RemoteException e) {
+            /* ignore */
         }
     }
 
-    /**
-     * Handles the change of the accessibility script injection setting state.
-     *
-     * @param preference The preference for enabling/disabling accessibility script injection.
-     */
-    private void handleToggleAccessibilityScriptInjection(CheckBoxPreference preference) {
-        if (preference.isChecked()) {
-            // set right enabled state since the user may press back
-            preference.setChecked(false);
+    private void handleToggleAccessibilityScriptInjectionPreference(Preference preference) {
+        String allowed = getString(R.string.accessibility_script_injection_disallowed);
+        if (preference.getSummary().equals(allowed)) {
+            // set right enabled state since the user may press back.
             showDialog(DIALOG_ID_ENABLE_SCRIPT_INJECTION);
         } else {
             Settings.Secure.putInt(getContentResolver(),
-                Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION, 0);
+                    Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION, 0);
+            mToggleScriptInjectionPreference.setSummary(
+                    getString(R.string.accessibility_script_injection_disallowed));
         }
     }
 
-    /**
-     * Handles the change of the preference for enabling/disabling an AccessibilityService.
-     *
-     * @param preference The preference.
-     */
-    private void handleEnableAccessibilityServiceStateChange(
-            SettingsCheckBoxPreference preference) {
-        if (preference.isChecked()) {
-            mToggleAccessibilityServiceCheckBox = preference;
-            // set right enabled state since the user may press back
-            preference.setChecked(false);
-            showDialog(DIALOG_ID_ENABLE_ACCESSIBILITY_SERVICE);
-        } else {
-            persistEnabledAccessibilityServices();
-        }
-    }
-
-    /**
-     * Persists the Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES setting.
-     * The AccessibilityManagerService watches this property and manages the
-     * AccessibilityServices.
-     */
-    private void persistEnabledAccessibilityServices() {
-        StringBuilder builder = new StringBuilder(256);
-
-        for (String key : mAccessibilityServices.keySet()) {
-            CheckBoxPreference preference = (CheckBoxPreference) findPreference(key);
-            if (preference.isChecked()) {
-                 builder.append(key);
-                 builder.append(':');
+    private void installToggleAccessibilitySwitch() {
+        mToggleAccessibilitySwitch = createActionBarToggleSwitch(getActivity());
+        final boolean checked = (Settings.Secure.getInt(getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_ENABLED, 0) == 1);
+        mToggleAccessibilitySwitch.setChecked(checked);
+        mToggleAccessibilitySwitch.setOnBeforeCheckedChangeListener(
+                new OnBeforeCheckedChangeListener() {
+            @Override
+            public boolean onBeforeCheckedChanged(ToggleSwitch toggleSwitch, boolean checked) {
+                if (!checked) {
+                    toggleSwitch.setCheckedNoBeforeCheckedChangeListener(true);
+                    showDialog(DIALOG_ID_DISABLE_ACCESSIBILITY);
+                    return true;
+                }
+                Settings.Secure.putInt(getContentResolver(),
+                        Settings.Secure.ACCESSIBILITY_ENABLED, 1);
+                updatePreferencesForAccessibilityState();
+                return false;
             }
-        }
-
-        Settings.Secure.putString(getContentResolver(),
-            Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, builder.toString());
+        });
     }
 
-    /**
-     * Adds {@link CheckBoxPreference} for enabling or disabling an accessibility services.
-     */
-    private void addAccessibilityServicePreferences() {
-        AccessibilityManager accessibilityManager =
-            (AccessibilityManager) getSystemService(Service.ACCESSIBILITY_SERVICE);
+    private void findPreferences() {
+        mServicesCategory = (PreferenceCategory) findPreference(SERVICES_CATEGORY);
+
+        mToggleLargeTextPreference = (CheckBoxPreference) findPreference(
+                TOGGLE_LARGE_TEXT_PREFERENCE);
+        mTogglePowerButtonEndsCallPreference = (CheckBoxPreference) findPreference(
+                TOGGLE_POWER_BUTTON_ENDS_CALL_PREFERENCE);
+        mTouchExplorationEnabledPreference = findPreference(TOGGLE_TOUCH_EXPLORATION_PREFERENCE);
+        mSelectLongPressTimeoutPreference = (ListPreference) findPreference(
+                SELECT_LONG_PRESS_TIMEOUT_PREFERENCE);
+        mSelectLongPressTimeoutPreference.setOnPreferenceChangeListener(this);
+        mToggleScriptInjectionPreference = findPreference(TOGGLE_SCRIPT_INJECTION_PREFERENCE);
+        mToggleScriptInjectionPreference.setOnPreferenceChangeListener(this);
+    }
+
+    private void updateServicesPreferences() {
+        mServicesCategory.removeAll();
+
+        AccessibilityManager accessibilityManager = AccessibilityManager.getInstance(getActivity());
 
         List<AccessibilityServiceInfo> installedServices =
             accessibilityManager.getInstalledAccessibilityServiceList();
 
-        for (int i = 0; i < mAccessibilityServicesCategory.getPreferenceCount(); i++) {
-            Preference pref = mAccessibilityServicesCategory.getPreference(i);
-            if (pref != mToggleAccessibilityCheckBox
-                    && pref != mToggleScriptInjectionCheckBox) {
-                mAccessibilityServicesCategory.removePreference(pref);
-                i--;
+        if (installedServices.isEmpty() && accessibilityManager.isEnabled()) {
+            // no service and accessibility is enabled => disable
+            Settings.Secure.putInt(getContentResolver(), Settings.Secure.ACCESSIBILITY_ENABLED, 0);
+            mToggleAccessibilitySwitch.setChecked(false);
+            mToggleAccessibilitySwitch.setEnabled(false);
+            // Notify user that they do not have any accessibility
+            // services installed and direct them to Market to get TalkBack.
+            showDialog(DIALOG_ID_NO_ACCESSIBILITY_SERVICES);
+            return;
+        }
+
+        Set<ComponentName> enabledComponentNames = new HashSet<ComponentName>();
+        String settingValue = Settings.Secure.getString(getContentResolver(),
+                Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
+        if (settingValue != null) {
+            SimpleStringSplitter splitter = mStringColonSplitter;
+            splitter.setString(settingValue);
+            while (splitter.hasNext()) {
+                enabledComponentNames.add(ComponentName.unflattenFromString(splitter.next()));
             }
         }
 
         for (int i = 0, count = installedServices.size(); i < count; ++i) {
-            AccessibilityServiceInfo accessibilityServiceInfo = installedServices.get(i);
-            String key = accessibilityServiceInfo.getId();
+            AccessibilityServiceInfo info = installedServices.get(i);
+            String key = info.getId();
 
-            if (mAccessibilityServices.put(key, accessibilityServiceInfo) == null) {
-                SettingsCheckBoxPreference preference = null;
-                Intent settingsIntent = null;
-                String settingsActivityName = accessibilityServiceInfo.getSettingsActivityName();
+            PreferenceScreen preference = getPreferenceManager().createPreferenceScreen(
+                    getActivity());
+            String title = info.getResolveInfo().loadLabel(getPackageManager()).toString();
 
-                if (!TextUtils.isEmpty(settingsActivityName)) {
-                    settingsIntent = new Intent(Intent.ACTION_MAIN);
-                    settingsIntent.setClassName(
-                            accessibilityServiceInfo.getResolveInfo().serviceInfo.packageName,
-                            settingsActivityName);
-                }
+            ServiceInfo serviceInfo = info.getResolveInfo().serviceInfo;
+            ComponentName componentName = new ComponentName(serviceInfo.packageName,
+                    serviceInfo.name);
 
-                preference = new SettingsCheckBoxPreference(getActivity(), settingsIntent);
-                preference.setKey(key);
-                preference.setOrder(i);
-                ServiceInfo serviceInfo = accessibilityServiceInfo.getResolveInfo().serviceInfo;
-                preference.setTitle(serviceInfo.loadLabel(getActivity().getPackageManager()));
-                mAccessibilityServicesCategory.addPreference(preference);
+            preference.setKey(componentName.flattenToString());
+
+            preference.setTitle(title);
+            final boolean enabled = enabledComponentNames.contains(componentName);
+            if (enabled) {
+                preference.setSummary(getString(R.string.accessibility_service_state_on));
+            } else {
+                preference.setSummary(getString(R.string.accessibility_service_state_off));
             }
+
+            preference.setOrder(i);
+            preference.setFragment(ToggleAccessibilityServiceFragment.class.getName());
+
+            Bundle extras = preference.getExtras();
+            extras.putString(EXTRA_PREFERENCE_KEY, preference.getKey());
+            extras.putBoolean(EXTRA_CHECKED, enabled);
+            extras.putString(EXTRA_TITLE, title);
+            extras.putString(EXTRA_SUMMARY, info.getDescription());
+            extras.putString(EXTRA_WARNING_MESSAGE, getString(
+                    R.string.accessibility_service_security_warning,
+                    info.getResolveInfo().loadLabel(getPackageManager())));
+
+            String settingsClassName = info.getSettingsActivityName();
+            if (!TextUtils.isEmpty(settingsClassName)) {
+                extras.putString(EXTRA_SETTINGS_TITLE,
+                        getString(R.string.accessibility_menu_item_settings));
+                extras.putString(EXTRA_SETTINGS_COMPONENT_NAME,
+                        new ComponentName(info.getResolveInfo().serviceInfo.packageName,
+                                settingsClassName).flattenToString());
+            }
+
+            mServicesCategory.addPreference(preference);
         }
     }
 
-    public void readFontSizePreference() {
+    public void updateSystemPreferences() {
+        // Large text.
         try {
-            mCurConfig.updateFrom(
-                ActivityManagerNative.getDefault().getConfiguration());
-        } catch (RemoteException e) {
+            mCurConfig.updateFrom(ActivityManagerNative.getDefault().getConfiguration());
+        } catch (RemoteException re) {
+            /* ignore */
         }
-        mToggleLargeTextCheckBox.setChecked(Float.compare(mCurConfig.fontScale,
+        mToggleLargeTextPreference.setChecked(Float.compare(mCurConfig.fontScale,
                 LARGE_FONT_SCALE) == 0);
+
+        // Power button ends call.
+        if (KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_POWER)
+                && Utils.isVoiceCapable(getActivity())) {
+              final int incallPowerBehavior = Settings.Secure.getInt(getContentResolver(),
+                      Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR,
+                      Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_DEFAULT);
+              final boolean powerButtonEndsCall =
+                  (incallPowerBehavior == Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP);
+              mTogglePowerButtonEndsCallPreference.setChecked(powerButtonEndsCall);
+        } else {
+              getPreferenceScreen().removePreference(mTogglePowerButtonEndsCallPreference);
+        }
+
+        // Touch exploration enabled.
+        final boolean touchExplorationEnabled = (Settings.Secure.getInt(getContentResolver(),
+                Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0) == 1);
+        if (touchExplorationEnabled) {
+            mTouchExplorationEnabledPreference.setSummary(
+                    getString(R.string.accessibility_service_state_on));
+            mTouchExplorationEnabledPreference.getExtras().putBoolean(EXTRA_CHECKED, true);
+        } else {
+            mTouchExplorationEnabledPreference.setSummary(
+                    getString(R.string.accessibility_service_state_off));
+            mTouchExplorationEnabledPreference.getExtras().putBoolean(EXTRA_CHECKED, false);
+        }
+
+        // Long press timeout.
+        if (mLongPressTimeoutValuetoTitleMap.isEmpty()) {
+            String[] timeoutValues = getResources().getStringArray(
+                    R.array.long_press_timeout_selector_values);
+            String[] timeoutTitles = getResources().getStringArray(
+                    R.array.long_press_timeout_selector_titles);
+            final int timeoutValueCount = timeoutValues.length;
+            for (int i = 0;i < timeoutValueCount; i++) {
+                mLongPressTimeoutValuetoTitleMap.put(timeoutValues[i], timeoutTitles[i]);
+            }
+        }
+        String longPressTimeout = String.valueOf(Settings.Secure.getInt(getContentResolver(),
+                Settings.Secure.LONG_PRESS_TIMEOUT, 0));
+        mSelectLongPressTimeoutPreference.setSummary(
+                mLongPressTimeoutValuetoTitleMap.get(longPressTimeout));
+
+        // Script injection.
+        final boolean scriptInjectionAllowed = (Settings.Secure.getInt(getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION, 0) == 1);
+        if (scriptInjectionAllowed) {
+            mToggleScriptInjectionPreference.setSummary(
+                    getString(R.string.accessibility_script_injection_allowed));
+        } else {
+            mToggleScriptInjectionPreference.setSummary(
+                    getString(R.string.accessibility_script_injection_disallowed));
+        }
     }
 
     @Override
@@ -460,11 +419,18 @@
                             public void onClick(DialogInterface dialog, int which) {
                                 Settings.Secure.putInt(getContentResolver(),
                                     Settings.Secure.ACCESSIBILITY_ENABLED, 0);
-                                mToggleAccessibilityCheckBox.setChecked(false);
-                                setAccessibilityServicePreferencesState(false);
+                                mToggleAccessibilitySwitch.setCheckedNoBeforeCheckedChangeListener(
+                                        false);
+                                updatePreferencesForAccessibilityState();
                             }
                     })
-                    .setNegativeButton(android.R.string.cancel, null)
+                    .setNegativeButton(android.R.string.cancel,
+                        new DialogInterface.OnClickListener() {
+                            public void onClick(DialogInterface dialog, int which) {
+                                mToggleAccessibilitySwitch.setCheckedNoBeforeCheckedChangeListener(
+                                        true);
+                            }
+                        })
                     .create();
             case DIALOG_ID_ENABLE_SCRIPT_INJECTION:
                 return new AlertDialog.Builder(getActivity())
@@ -473,35 +439,18 @@
                 .setMessage(getActivity().getString(
                         R.string.accessibility_script_injection_security_warning))
                 .setCancelable(true)
-                .setPositiveButton(android.R.string.ok,
+                .setPositiveButton(R.string.accessibility_script_injection_button_allow,
                     new DialogInterface.OnClickListener() {
                         public void onClick(DialogInterface dialog, int which) {
                             Settings.Secure.putInt(getContentResolver(),
                             Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION, 1);
-                            mToggleScriptInjectionCheckBox.setChecked(true);
+                            mToggleScriptInjectionPreference.setSummary(
+                                    getString(R.string.accessibility_script_injection_allowed));
                         }
                 })
-                .setNegativeButton(android.R.string.cancel, null)
+
+                .setNegativeButton(R.string.accessibility_script_injection_button_disallow, null)
                 .create();
-            case DIALOG_ID_ENABLE_ACCESSIBILITY_SERVICE:
-                return new AlertDialog.Builder(getActivity())
-                    .setTitle(android.R.string.dialog_alert_title)
-                    .setIcon(android.R.drawable.ic_dialog_alert)
-                    .setMessage(getResources().getString(
-                            R.string.accessibility_service_security_warning,
-                            mAccessibilityServices.get(mToggleAccessibilityServiceCheckBox.getKey())
-                            .getResolveInfo().serviceInfo.applicationInfo.loadLabel(
-                                    getActivity().getPackageManager())))
-                    .setCancelable(true)
-                    .setPositiveButton(android.R.string.ok,
-                            new DialogInterface.OnClickListener() {
-                                public void onClick(DialogInterface dialog, int which) {
-                                    mToggleAccessibilityServiceCheckBox.setChecked(true);
-                                    persistEnabledAccessibilityServices();
-                                }
-                    })
-                    .setNegativeButton(android.R.string.cancel, null)
-                    .create();
             case DIALOG_ID_NO_ACCESSIBILITY_SERVICES:
                 return new AlertDialog.Builder(getActivity())
                     .setTitle(R.string.accessibility_service_no_apps_title)
@@ -526,4 +475,264 @@
                 return null;
         }
     }
+
+    private class SettingsPackageMonitor extends PackageMonitor {
+
+        @Override
+        public void onPackageAdded(String packageName, int uid) {
+            Message message = mHandler.obtainMessage();
+            mHandler.sendMessageDelayed(message, DELAY_UPDATE_SERVICES_PREFERENCES_MILLIS);
+        }
+
+        @Override
+        public void onPackageAppeared(String packageName, int reason) {
+            Message message = mHandler.obtainMessage();
+            mHandler.sendMessageDelayed(message, DELAY_UPDATE_SERVICES_PREFERENCES_MILLIS);
+        }
+
+        @Override
+        public void onPackageDisappeared(String packageName, int reason) {
+            Message message = mHandler.obtainMessage();
+            mHandler.sendMessageDelayed(message, DELAY_UPDATE_SERVICES_PREFERENCES_MILLIS);
+        }
+
+        @Override
+        public void onPackageRemoved(String packageName, int uid) {
+            Message message = mHandler.obtainMessage();
+            mHandler.sendMessageDelayed(message, DELAY_UPDATE_SERVICES_PREFERENCES_MILLIS);
+        }
+    }
+
+    private static ToggleSwitch createActionBarToggleSwitch(Activity activity) {
+        ToggleSwitch toggleSwitch = new ToggleSwitch(activity);
+        final int padding = activity.getResources().getDimensionPixelSize(
+                R.dimen.action_bar_switch_padding);
+        toggleSwitch.setPadding(0, 0, padding, 0);
+        activity.getActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM,
+                ActionBar.DISPLAY_SHOW_CUSTOM);
+        activity.getActionBar().setCustomView(toggleSwitch,
+                new ActionBar.LayoutParams(ActionBar.LayoutParams.WRAP_CONTENT,
+                        ActionBar.LayoutParams.WRAP_CONTENT,
+                        Gravity.CENTER_VERTICAL | Gravity.RIGHT));
+        return toggleSwitch;
+    }
+
+    public static class ToggleSwitch extends Switch {
+
+        private OnBeforeCheckedChangeListener mOnBeforeListener;
+
+        public static interface OnBeforeCheckedChangeListener {
+            public boolean onBeforeCheckedChanged(ToggleSwitch toggleSwitch, boolean checked);
+        }
+
+        public ToggleSwitch(Context context) {
+            super(context);
+        }
+
+        public void setOnBeforeCheckedChangeListener(OnBeforeCheckedChangeListener listener) {
+            mOnBeforeListener = listener;
+        }
+
+        @Override
+        public void setChecked(boolean checked) {
+            if (mOnBeforeListener != null
+                    && mOnBeforeListener.onBeforeCheckedChanged(this, checked)) {
+                return;
+            }
+            super.setChecked(checked);
+        }
+
+        public void setCheckedNoBeforeCheckedChangeListener(boolean checked) {
+            super.setChecked(checked);
+        }
+    }
+
+    public static class ToggleAccessibilityServiceFragment extends TogglePreferenceFragment {
+        @Override
+        public void onPreferenceToggled(String preferenceKey, boolean enabled) {
+            String enabledServices = Settings.Secure.getString(getContentResolver(),
+                    Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
+            if (enabledServices == null) {
+                enabledServices = "";
+            }
+            final int length = enabledServices.length();
+            if (enabled) {
+                if (enabledServices.contains(preferenceKey)) {
+                    return;
+                }
+                if (length == 0) {
+                    enabledServices += preferenceKey;
+                    Settings.Secure.putString(getContentResolver(),
+                            Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, enabledServices);
+                } else if (length > 0) {
+                    enabledServices += ENABLED_ACCESSIBILITY_SERVICES_SEPARATOR + preferenceKey;
+                    Settings.Secure.putString(getContentResolver(),
+                            Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, enabledServices);
+                }
+            } else {
+                final int index = enabledServices.indexOf(preferenceKey);
+                if (index == 0) {
+                    enabledServices = enabledServices.replace(preferenceKey, "");
+                    Settings.Secure.putString(getContentResolver(),
+                            Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, enabledServices);
+                } else if (index > 0) {
+                    enabledServices = enabledServices.replace(
+                            ENABLED_ACCESSIBILITY_SERVICES_SEPARATOR + preferenceKey, "");
+                    Settings.Secure.putString(getContentResolver(),
+                            Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, enabledServices);
+                }
+            }
+        }
+    }
+
+    public static class ToggleTouchExplorationFragment extends TogglePreferenceFragment {
+        @Override
+        public void onPreferenceToggled(String preferenceKey, boolean enabled) {
+            Settings.Secure.putInt(getContentResolver(),
+                    Settings.Secure.TOUCH_EXPLORATION_ENABLED, enabled ? 1 : 0);
+        }
+    }
+
+    private abstract static class TogglePreferenceFragment extends SettingsPreferenceFragment
+            implements DialogInterface.OnClickListener {
+
+        private static final int DIALOG_ID_WARNING = 1;
+
+        private String mPreferenceKey;
+
+        private ToggleSwitch mToggleSwitch;
+
+        private CharSequence mWarningMessage;
+        private Preference mSummaryPreference;
+
+        private CharSequence mSettingsTitle;
+        private Intent mSettingsIntent;
+
+        @Override
+        public void onActivityCreated(Bundle savedInstanceState) {
+            installActionBarToggleSwitch();
+            processArguments();
+            getListView().setDivider(null);
+            getListView().setEnabled(false);
+            super.onActivityCreated(savedInstanceState);
+        }
+
+        @Override
+        public void onCreate(Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+            PreferenceScreen preferenceScreen = getPreferenceManager().createPreferenceScreen(
+                    getActivity());
+            setPreferenceScreen(preferenceScreen);
+            mSummaryPreference = new Preference(getActivity()) {
+                @Override
+                protected void onBindView(View view) {
+                    super.onBindView(view);
+                    TextView summaryView = (TextView) view.findViewById(R.id.summary);
+                    summaryView.setText(getSummary());
+                }
+            };
+            mSummaryPreference.setPersistent(false);
+            mSummaryPreference.setLayoutResource(R.layout.text_description_preference);
+            preferenceScreen.addPreference(mSummaryPreference);
+        }
+
+        public abstract void onPreferenceToggled(String preferenceKey, boolean value);
+
+        @Override
+        public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+            super.onCreateOptionsMenu(menu, inflater);
+            MenuItem menuItem = menu.add(mSettingsTitle);
+            menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
+            menuItem.setIntent(mSettingsIntent);
+        }
+
+        @Override
+        public Dialog onCreateDialog(int dialogId) {
+            switch (dialogId) {
+                case DIALOG_ID_WARNING:
+                    return new AlertDialog.Builder(getActivity())
+                        .setTitle(android.R.string.dialog_alert_title)
+                        .setIcon(android.R.drawable.ic_dialog_alert)
+                        .setMessage(mWarningMessage)
+                        .setCancelable(true)
+                        .setPositiveButton(android.R.string.ok, this)
+                        .setNegativeButton(android.R.string.cancel, this)
+                        .create();
+                default:
+                    throw new IllegalArgumentException();
+            }
+        }
+
+        @Override
+        public void onClick(DialogInterface dialog, int which) {
+            switch (which) {
+                case DialogInterface.BUTTON_POSITIVE:
+                    // OK, we got the user consent so set checked.
+                    mToggleSwitch.setCheckedNoBeforeCheckedChangeListener(true);
+                    onPreferenceToggled(mPreferenceKey, true);
+                    break;
+                case DialogInterface.BUTTON_NEGATIVE:
+                    onPreferenceToggled(mPreferenceKey, false);
+                    break;
+                default:
+                    throw new IllegalArgumentException();
+            }
+        }
+
+        private void installActionBarToggleSwitch() {
+            mToggleSwitch = createActionBarToggleSwitch(getActivity());
+            mToggleSwitch.setOnBeforeCheckedChangeListener(new OnBeforeCheckedChangeListener() {
+                @Override
+                public boolean onBeforeCheckedChanged(ToggleSwitch toggleSwitch, boolean checked) {
+                    if (checked) {
+                        if (!TextUtils.isEmpty(mWarningMessage)) {
+                            toggleSwitch.setCheckedNoBeforeCheckedChangeListener(false);
+                            showDialog(DIALOG_ID_WARNING);
+                            return true;
+                        }
+                        onPreferenceToggled(mPreferenceKey, true);
+                    } else {
+                        onPreferenceToggled(mPreferenceKey, false);
+                    }
+                    return false;
+                }
+            });
+        }
+
+        private void processArguments() {
+            Bundle arguments = getArguments();
+
+            // Key.
+            mPreferenceKey = arguments.getString(EXTRA_PREFERENCE_KEY);
+
+            // Enabled.
+            final boolean enabled = arguments.getBoolean(EXTRA_CHECKED);
+            mToggleSwitch.setCheckedNoBeforeCheckedChangeListener(enabled);
+
+            // Title.
+            String title = arguments.getString(EXTRA_TITLE);
+            getActivity().getActionBar().setTitle(arguments.getCharSequence(EXTRA_TITLE));
+
+            // Summary.
+            String summary = arguments.getString(EXTRA_SUMMARY);
+            mSummaryPreference.setSummary(summary);
+
+            // Settings title and intent.
+            String settingsTitle = arguments.getString(EXTRA_SETTINGS_TITLE);
+            String settingsComponentName = arguments.getString(EXTRA_SETTINGS_COMPONENT_NAME);
+            if (!TextUtils.isEmpty(settingsTitle) && !TextUtils.isEmpty(settingsComponentName)) {
+                Intent settingsIntent = new Intent(Intent.ACTION_MAIN).setComponent(
+                        ComponentName.unflattenFromString(settingsComponentName.toString()));
+                if (!getPackageManager().queryIntentActivities(settingsIntent, 0).isEmpty()) {
+                    mSettingsTitle = settingsTitle;
+                    mSettingsIntent = settingsIntent;
+                    setHasOptionsMenu(true);
+                }
+            }
+
+            // Waring message.
+            mWarningMessage = arguments.getCharSequence(
+                    AccessibilitySettings.EXTRA_WARNING_MESSAGE);
+        }
+    }
 }
diff --git a/src/com/android/settings/AccessibilityTutorialActivity.java b/src/com/android/settings/AccessibilityTutorialActivity.java
index 5e65dcd..21d0028 100644
--- a/src/com/android/settings/AccessibilityTutorialActivity.java
+++ b/src/com/android/settings/AccessibilityTutorialActivity.java
@@ -481,6 +481,7 @@
         private final Button mBack;
         private final Button mNext;
         private final Button mFinish;
+        private final int mTitleResId;
 
         /** Which bit flags have been set. */
         private long mFlags;
@@ -501,6 +502,7 @@
             super(context);
 
             mController = controller;
+            mTitleResId = titleResId;
 
             final View container = LayoutInflater.from(context).inflate(
                     R.layout.accessibility_tutorial_container, this, true);
@@ -521,8 +523,6 @@
                 title.setText(titleResId);
             }
 
-            controller.setTitle(titleResId);
-
             final ViewGroup contentHolder = (ViewGroup) container.findViewById(R.id.content);
             LayoutInflater.from(context).inflate(layoutResId, contentHolder, true);
         }
@@ -535,6 +535,7 @@
 
             mFlags = 0;
             mInstructions.setVisibility(View.GONE);
+            mController.setTitle(mTitleResId);
 
             onShown();
         }
diff --git a/src/com/android/settings/AccountPreference.java b/src/com/android/settings/AccountPreference.java
index f3d7d51..f76d5cb 100644
--- a/src/com/android/settings/AccountPreference.java
+++ b/src/com/android/settings/AccountPreference.java
@@ -71,6 +71,7 @@
         setSummary(getSyncStatusMessage(mStatus));
         mSyncStatusIcon = (ImageView) view.findViewById(R.id.syncStatusIcon);
         mSyncStatusIcon.setImageResource(getSyncStatusIcon(mStatus));
+        mSyncStatusIcon.setContentDescription(getSyncContentDescription(mStatus));
     }
 
     public void setProviderIcon(Drawable icon) {
@@ -126,6 +127,20 @@
         return res;
     }
 
+    private String getSyncContentDescription(int status) {
+        switch (status) {
+            case SYNC_ENABLED:
+                return getContext().getString(R.string.accessibility_sync_enabled);
+            case SYNC_DISABLED:
+                return getContext().getString(R.string.accessibility_sync_disabled);
+            case SYNC_ERROR:
+                return getContext().getString(R.string.accessibility_sync_error);
+            default:
+                Log.e(TAG, "Unknown sync status: " + status);
+                return getContext().getString(R.string.accessibility_sync_error);
+        }
+    }
+
     @Override
     public int compareTo(Preference other) {
         if (!(other instanceof AccountPreference)) {
diff --git a/src/com/android/settings/SecuritySettings.java b/src/com/android/settings/SecuritySettings.java
index 057e5de..9a83311 100644
--- a/src/com/android/settings/SecuritySettings.java
+++ b/src/com/android/settings/SecuritySettings.java
@@ -237,7 +237,7 @@
     private void updateLockAfterPreferenceSummary() {
         // Update summary message with current value
         long currentTimeout = Settings.Secure.getLong(getContentResolver(),
-                Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, 0);
+                Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, 5000);
         final CharSequence[] entries = mLockAfter.getEntries();
         final CharSequence[] values = mLockAfter.getEntryValues();
         int best = 0;
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index 456bdf6..ae7e24e 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -16,6 +16,11 @@
 
 package com.android.settings;
 
+import com.android.settings.accounts.AccountSyncSettings;
+import com.android.settings.bluetooth.BluetoothEnabler;
+import com.android.settings.fuelgauge.PowerUsageSummary;
+import com.android.settings.wifi.WifiEnabler;
+
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -39,11 +44,6 @@
 import android.widget.Switch;
 import android.widget.TextView;
 
-import com.android.settings.accounts.ManageAccountsSettings;
-import com.android.settings.bluetooth.BluetoothEnabler;
-import com.android.settings.fuelgauge.PowerUsageSummary;
-import com.android.settings.wifi.WifiEnabler;
-
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -83,7 +83,7 @@
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         final int theme = getIntent().getIntExtra(
-                EXTRA_THEME, android.R.style.Theme_Holo_SolidActionBar_SplitActionBarWhenNarrow);
+                EXTRA_THEME, android.R.style.Theme_Holo_SplitActionBarWhenNarrow);
         setTheme(theme);
 
         getMetaData();
@@ -291,8 +291,8 @@
         // some fragments would like a custom activity theme
         if (DataUsageSummary.class.getName().equals(fragmentName) ||
                 PowerUsageSummary.class.getName().equals(fragmentName) ||
-                UserDictionarySettings.class.getName().equals(fragmentName) ||
-                ManageAccountsSettings.class.getName().equals(fragmentName)) {
+                AccountSyncSettings.class.getName().equals(fragmentName) ||
+                UserDictionarySettings.class.getName().equals(fragmentName)) {
             intent.putExtra(EXTRA_THEME, android.R.style.Theme_Holo_SolidActionBar);
         }
 
@@ -572,8 +572,10 @@
     public static class DateTimeSettingsActivity extends Settings { /* empty */ }
     public static class StorageSettingsActivity extends Settings { /* empty */ }
     public static class WifiSettingsActivity extends Settings { /* empty */ }
+    public static class WifiP2pSettingsActivity extends Settings { /* empty */ }
     public static class InputMethodAndLanguageSettingsActivity extends Settings { /* empty */ }
     public static class InputMethodAndSubtypeEnablerActivity extends Settings { /* empty */ }
+    public static class SpellCheckersSettingsActivity extends Settings { /* empty */ }
     public static class LocalePickerActivity extends Settings { /* empty */ }
     public static class UserDictionarySettingsActivity extends Settings { /* empty */ }
     public static class SoundSettingsActivity extends Settings { /* empty */ }
diff --git a/src/com/android/settings/SettingsCheckBoxPreference.java b/src/com/android/settings/SettingsCheckBoxPreference.java
deleted file mode 100644
index 70b5ac1..0000000
--- a/src/com/android/settings/SettingsCheckBoxPreference.java
+++ /dev/null
@@ -1,92 +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;
-
-import android.content.Context;
-import android.content.Intent;
-import android.preference.CheckBoxPreference;
-import android.util.TypedValue;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.CheckBox;
-import android.widget.ImageView;
-
-/**
- * CheckBox preference that optionally shows an icon for launching a settings
- * {@link android.app.Activity}. The settings activity, if intent for launching
- * it was provided, can be stared only if the CheckBox in is checked.
- */
-public class SettingsCheckBoxPreference extends CheckBoxPreference {
-
-    // Integer.MIN_VALUE means not initalized
-    private static int sDimAlpha = Integer.MIN_VALUE;
-
-    private final Intent mSettingsIntent;
-
-    /**
-     * Creates a new instance. The constructor is checking whether the
-     * settings intent is resolved to an activity and acts accordingly.
-     *
-     * @param context Context for accessing resources.
-     * @param intent Intent to use as settings for the item represented by
-     *        this preference. Pass <code>null</code> if there is no associated 
-     *        settings activity.
-     */
-    public SettingsCheckBoxPreference(Context context, Intent intent) {
-        super(context);
-
-        if (sDimAlpha == Integer.MIN_VALUE) {
-            TypedValue outValue = new TypedValue();
-            context.getTheme().resolveAttribute(android.R.attr.disabledAlpha, outValue, true);
-            sDimAlpha = (int) (outValue.getFloat() * 255);
-        }
-
-        if (intent != null
-                && !context.getPackageManager().queryIntentActivities(intent, 0).isEmpty()) {
-            mSettingsIntent = intent;
-        } else {
-            mSettingsIntent = null;
-        }
-
-        setWidgetLayoutResource(R.layout.preference_settings_checkbox_widget);
-    }
-
-    @Override
-    protected void onBindView(View view) {
-        super.onBindView(view);
-        ImageView settingsButton = (ImageView) view.findViewById(R.id.settings_button);
-        if (mSettingsIntent != null) {
-            CheckBox checkbox = (CheckBox) view.findViewById(com.android.internal.R.id.checkbox);
-            if (checkbox.isChecked()) {
-                settingsButton.setOnClickListener(new OnClickListener() {
-                    public void onClick(View view) {
-                        getContext().startActivity(mSettingsIntent);
-                    }
-                });
-            }
-            settingsButton.setVisibility(View.VISIBLE);
-            if (checkbox.isChecked() && isEnabled()) {
-                settingsButton.setAlpha(255);
-            } else {
-                settingsButton.setAlpha(sDimAlpha);
-            }
-        } else {
-            settingsButton.setVisibility(View.GONE);
-            view.findViewById(R.id.divider).setVisibility(View.GONE);
-        }
-    }
-}
diff --git a/src/com/android/settings/TetherSettings.java b/src/com/android/settings/TetherSettings.java
index 1513d43..9991725 100644
--- a/src/com/android/settings/TetherSettings.java
+++ b/src/com/android/settings/TetherSettings.java
@@ -31,6 +31,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.res.AssetManager;
+import android.hardware.usb.UsbManager;
 import android.net.ConnectivityManager;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiManager;
@@ -95,6 +96,9 @@
     private WifiManager mWifiManager;
     private WifiConfiguration mWifiConfig = null;
 
+    private boolean mUsbConnected;
+    private boolean mMassStorageActive;
+
     private boolean mBluetoothEnableForTether;
 
     @Override
@@ -253,8 +257,14 @@
                 updateState(available.toArray(new String[available.size()]),
                         active.toArray(new String[active.size()]),
                         errored.toArray(new String[errored.size()]));
-            } else if (action.equals(Intent.ACTION_MEDIA_SHARED) ||
-                       action.equals(Intent.ACTION_MEDIA_UNSHARED)) {
+            } else if (action.equals(Intent.ACTION_MEDIA_SHARED)) {
+                mMassStorageActive = true;
+                updateState();
+            } else if (action.equals(Intent.ACTION_MEDIA_UNSHARED)) {
+                mMassStorageActive = false;
+                updateState();
+            } else if (action.equals(UsbManager.ACTION_USB_STATE)) {
+                mUsbConnected = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false);
                 updateState();
             } else if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
                 if (mBluetoothEnableForTether) {
@@ -285,11 +295,16 @@
 
         final Activity activity = getActivity();
 
+        mMassStorageActive = Environment.MEDIA_SHARED.equals(Environment.getExternalStorageState());
         mTetherChangeReceiver = new TetherChangeReceiver();
         IntentFilter filter = new IntentFilter(ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
         Intent intent = activity.registerReceiver(mTetherChangeReceiver, filter);
 
         filter = new IntentFilter();
+        filter.addAction(UsbManager.ACTION_USB_STATE);
+        activity.registerReceiver(mTetherChangeReceiver, filter);
+
+        filter = new IntentFilter();
         filter.addAction(Intent.ACTION_MEDIA_SHARED);
         filter.addAction(Intent.ACTION_MEDIA_UNSHARED);
         filter.addDataScheme("file");
@@ -334,14 +349,11 @@
             String[] errored) {
         ConnectivityManager cm =
                 (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
-        boolean usbAvailable = false;
+        boolean usbAvailable = mUsbConnected && !mMassStorageActive;
         int usbError = ConnectivityManager.TETHER_ERROR_NO_ERROR;
-        boolean massStorageActive =
-                Environment.MEDIA_SHARED.equals(Environment.getExternalStorageState());
         for (String s : available) {
             for (String regex : mUsbRegexs) {
                 if (s.matches(regex)) {
-                    usbAvailable = true;
                     if (usbError == ConnectivityManager.TETHER_ERROR_NO_ERROR) {
                         usbError = cm.getLastTetherError(s);
                     }
@@ -377,7 +389,7 @@
             mUsbTether.setSummary(R.string.usb_tethering_errored_subtext);
             mUsbTether.setEnabled(false);
             mUsbTether.setChecked(false);
-        } else if (massStorageActive) {
+        } else if (mMassStorageActive) {
             mUsbTether.setSummary(R.string.usb_tethering_storage_active_subtext);
             mUsbTether.setEnabled(false);
             mUsbTether.setChecked(false);
@@ -434,40 +446,18 @@
 
     @Override
     public boolean onPreferenceTreeClick(PreferenceScreen screen, Preference preference) {
+        ConnectivityManager cm =
+                (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
+
         if (preference == mUsbTether) {
             boolean newState = mUsbTether.isChecked();
 
-            ConnectivityManager cm =
-                    (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
-
-            if (newState) {
-                String[] available = cm.getTetherableIfaces();
-
-                String usbIface = findIface(available, mUsbRegexs);
-                if (usbIface == null) {
-                    updateState();
-                    return true;
-                }
-                if (cm.tether(usbIface) != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
-                    mUsbTether.setChecked(false);
-                    mUsbTether.setSummary(R.string.usb_tethering_errored_subtext);
-                    return true;
-                }
-                mUsbTether.setSummary("");
-            } else {
-                String [] tethered = cm.getTetheredIfaces();
-
-                String usbIface = findIface(tethered, mUsbRegexs);
-                if (usbIface == null) {
-                    updateState();
-                    return true;
-                }
-                if (cm.untether(usbIface) != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
-                    mUsbTether.setSummary(R.string.usb_tethering_errored_subtext);
-                    return true;
-                }
-                mUsbTether.setSummary("");
+            if (cm.setUsbTethering(newState) != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
+                mUsbTether.setChecked(false);
+                mUsbTether.setSummary(R.string.usb_tethering_errored_subtext);
+                return true;
             }
+            mUsbTether.setSummary("");
         } else if (preference == mBluetoothTether) {
             boolean bluetoothTetherState = mBluetoothTether.isChecked();
 
@@ -486,8 +476,6 @@
             } else {
                 boolean errored = false;
 
-                ConnectivityManager cm =
-                    (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
                 String [] tethered = cm.getTetheredIfaces();
                 String bluetoothIface = findIface(tethered, mBluetoothRegexs);
                 if (bluetoothIface != null &&
diff --git a/src/com/android/settings/WirelessSettings.java b/src/com/android/settings/WirelessSettings.java
index c07388e..beab491 100644
--- a/src/com/android/settings/WirelessSettings.java
+++ b/src/com/android/settings/WirelessSettings.java
@@ -21,6 +21,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.net.ConnectivityManager;
+import android.net.wifi.p2p.WifiP2pManager;
 import android.nfc.NfcAdapter;
 import android.os.Bundle;
 import android.os.SystemProperties;
@@ -28,6 +29,9 @@
 import android.preference.Preference;
 import android.preference.PreferenceScreen;
 import android.provider.Settings;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.Switch;
 
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.telephony.TelephonyProperties;
@@ -39,6 +43,7 @@
     private static final String KEY_TOGGLE_NFC = "toggle_nfc";
     private static final String KEY_ZEROCLICK_SETTINGS = "zeroclick_settings";
     private static final String KEY_VPN_SETTINGS = "vpn_settings";
+    private static final String KEY_WIFI_P2P_SETTINGS = "wifi_p2p_settings";
     private static final String KEY_TETHER_SETTINGS = "tether_settings";
     private static final String KEY_PROXY_SETTINGS = "proxy_settings";
     private static final String KEY_MOBILE_NETWORK_SETTINGS = "mobile_network_settings";
@@ -118,6 +123,11 @@
             getPreferenceScreen().removePreference(findPreference(KEY_MOBILE_NETWORK_SETTINGS));
         }
 
+        WifiP2pManager wifiP2p = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
+        if (!wifiP2p.isP2pSupported()) {
+            getPreferenceScreen().removePreference(findPreference(KEY_WIFI_P2P_SETTINGS));
+        }
+
         // Enable Proxy selector settings if allowed.
         Preference mGlobalProxy = findPreference(KEY_PROXY_SETTINGS);
         DevicePolicyManager mDPM = (DevicePolicyManager)
diff --git a/src/com/android/settings/accounts/AccountSyncSettings.java b/src/com/android/settings/accounts/AccountSyncSettings.java
index 547b0e1..e70cbad 100644
--- a/src/com/android/settings/accounts/AccountSyncSettings.java
+++ b/src/com/android/settings/accounts/AccountSyncSettings.java
@@ -236,10 +236,12 @@
                                        getString(R.string.sync_menu_sync_cancel))
                 .setIcon(com.android.internal.R.drawable.ic_menu_close_clear_cancel);
 
-        removeAccount.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS
-                | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
-        syncNow.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
-        syncCancel.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
+        removeAccount.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER |
+                MenuItem.SHOW_AS_ACTION_WITH_TEXT);
+        syncNow.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER |
+                MenuItem.SHOW_AS_ACTION_WITH_TEXT);
+        syncCancel.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER |
+                MenuItem.SHOW_AS_ACTION_WITH_TEXT);
     }
 
     @Override
diff --git a/src/com/android/settings/accounts/ManageAccountsSettings.java b/src/com/android/settings/accounts/ManageAccountsSettings.java
index 7d935f0..d9dea00 100644
--- a/src/com/android/settings/accounts/ManageAccountsSettings.java
+++ b/src/com/android/settings/accounts/ManageAccountsSettings.java
@@ -19,7 +19,6 @@
 import com.android.settings.AccountPreference;
 import com.android.settings.DialogCreatable;
 import com.android.settings.R;
-import com.google.android.collect.Maps;
 
 import android.accounts.Account;
 import android.accounts.AccountManager;
@@ -35,7 +34,6 @@
 import android.content.SyncAdapterType;
 import android.content.SyncInfo;
 import android.content.SyncStatusInfo;
-import android.content.pm.PackageManager;
 import android.graphics.drawable.Drawable;
 import android.net.ConnectivityManager;
 import android.os.Bundle;
@@ -201,6 +199,7 @@
         return null;
     }
 
+    @Override
     public void showDialog(int dialogId) {
         if (mDialogFragment != null) {
             Log.e(TAG, "Old dialog fragment not null!");
@@ -212,8 +211,7 @@
     @Override
     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
         MenuItem actionItem =
-                menu.add(0, MENU_ADD_ACCOUNT, 0, R.string.add_account_label)
-                .setIcon(R.drawable.ic_menu_add);
+                menu.add(0, MENU_ADD_ACCOUNT, 0, R.string.add_account_label);
         actionItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM
                 | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
     }
@@ -235,6 +233,7 @@
         connManager.setBackgroundDataSetting(enabled);
     }
 
+    @Override
     protected void onSyncStateUpdated() {
         // Catch any delayed delivery of update messages
         if (getActivity() == null) return;
@@ -342,6 +341,7 @@
         onSyncStateUpdated();
     }
 
+    @Override
     protected void onAuthDescriptionsUpdated() {
         // Update account icons for all account preference items
         for (int i = 0; i < mManageAccountsCategory.getPreferenceCount(); i++) {
diff --git a/src/com/android/settings/bluetooth/BluetoothDiscoverableEnabler.java b/src/com/android/settings/bluetooth/BluetoothDiscoverableEnabler.java
index 0ad8948..6b654b5 100644
--- a/src/com/android/settings/bluetooth/BluetoothDiscoverableEnabler.java
+++ b/src/com/android/settings/bluetooth/BluetoothDiscoverableEnabler.java
@@ -144,12 +144,24 @@
         if (getDiscoverableTimeout() == DISCOVERABLE_TIMEOUT_NEVER) {
             mDiscoveryPreference.setSummary(R.string.bluetooth_is_discoverable_always);
         } else {
-            String textTimeout = DateUtils.formatElapsedTime(timeout);
+            String textTimeout = formatTimeRemaining(timeout);
             mDiscoveryPreference.setSummary(mContext.getString(R.string.bluetooth_is_discoverable,
                     textTimeout));
         }
     }
 
+    private static String formatTimeRemaining(int timeout) {
+        StringBuilder sb = new StringBuilder(6);    // "mmm:ss"
+        int min = timeout / 60;
+        sb.append(min).append(':');
+        int sec = timeout - (min * 60);
+        if (sec < 10) {
+            sb.append('0');
+        }
+        sb.append(sec);
+        return sb.toString();
+    }
+
     void setDiscoverableTimeout(int index) {
         String timeoutValue;
         switch (index) {
diff --git a/src/com/android/settings/bluetooth/BluetoothFindNearby.java b/src/com/android/settings/bluetooth/BluetoothFindNearby.java
deleted file mode 100644
index 066f4f6..0000000
--- a/src/com/android/settings/bluetooth/BluetoothFindNearby.java
+++ /dev/null
@@ -1,71 +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.bluetooth;
-
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-
-import com.android.settings.R;
-
-/**
- * Fragment to scan and show the discoverable devices.
- */
-public final class BluetoothFindNearby extends DeviceListPreferenceFragment {
-
-    @Override
-    void addPreferencesForActivity() {
-        addPreferencesFromResource(R.xml.device_picker);
-    }
-
-    @Override
-    public void onResume() {
-        super.onResume();
-        if (mSelectedDevice != null) {
-            CachedBluetoothDeviceManager manager = mLocalManager.getCachedDeviceManager();
-            CachedBluetoothDevice device = manager.findDevice(mSelectedDevice);
-            if (device != null && device.getBondState() == BluetoothDevice.BOND_BONDED) {
-                // selected device was paired, so return from this screen
-                finish();
-                return;
-            }
-        }
-        mLocalAdapter.startScanning(true);
-    }
-
-    @Override
-    void onDevicePreferenceClick(BluetoothDevicePreference btPreference) {
-        mLocalAdapter.stopScanning();
-        super.onDevicePreferenceClick(btPreference);
-    }
-
-    public void onDeviceBondStateChanged(CachedBluetoothDevice
-            cachedDevice, int bondState) {
-        if (bondState == BluetoothDevice.BOND_BONDED) {
-            // return from scan screen after successful auto-pairing
-            finish();
-        }
-    }
-
-    @Override
-    public void onBluetoothStateChanged(int bluetoothState) {
-        super.onBluetoothStateChanged(bluetoothState);
-
-        if (bluetoothState == BluetoothAdapter.STATE_ON) {
-                mLocalAdapter.startScanning(false);
-        }
-    }
-}
diff --git a/src/com/android/settings/bluetooth/BluetoothSettings.java b/src/com/android/settings/bluetooth/BluetoothSettings.java
index ede218d..4b0db68 100644
--- a/src/com/android/settings/bluetooth/BluetoothSettings.java
+++ b/src/com/android/settings/bluetooth/BluetoothSettings.java
@@ -72,6 +72,8 @@
     private View mView;
     private TextView mEmptyView;
 
+    private final IntentFilter mIntentFilter;
+
     // accessed from inner class (not private to avoid thunks)
     Preference mMyDevicePreference;
 
@@ -79,21 +81,22 @@
         @Override
         public void onReceive(Context context, Intent intent) {
             String action = intent.getAction();
-            if (action.equals(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED) ||
-                    (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED) &&
-                            (intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
-                                    BluetoothAdapter.ERROR) == BluetoothAdapter.STATE_ON))) {
+            if (action.equals(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED)) {
                 updateDeviceName();
             }
         }
 
         private void updateDeviceName() {
-            if (mLocalAdapter != null && mLocalAdapter.isEnabled() && mMyDevicePreference != null) {
+            if (mLocalAdapter.isEnabled() && mMyDevicePreference != null) {
                 mMyDevicePreference.setTitle(mLocalAdapter.getName());
             }
         }
     };
 
+    public BluetoothSettings() {
+        mIntentFilter = new IntentFilter(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
+    }
+
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
             Bundle savedInstanceState) {
@@ -142,16 +145,12 @@
         super.onResume();
 
         mBluetoothEnabler.resume();
-        updateContent(mLocalAdapter.getBluetoothState());
-
         if (mDiscoverableEnabler != null) {
             mDiscoverableEnabler.resume();
         }
+        getActivity().registerReceiver(mReceiver, mIntentFilter);
 
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
-        filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
-        getActivity().registerReceiver(mReceiver, filter);
+        updateContent(mLocalAdapter.getBluetoothState());
     }
 
     @Override
@@ -174,8 +173,10 @@
                 .setEnabled(bluetoothIsEnabled && !isDiscovering)
                 .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
         menu.add(Menu.NONE, MENU_ID_RENAME_DEVICE, 0, R.string.bluetooth_rename_device)
-                .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
+                .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);
@@ -233,7 +234,6 @@
 
     private void updateContent(int bluetoothState) {
         final PreferenceScreen preferenceScreen = getPreferenceScreen();
-        getActivity().invalidateOptionsMenu();
         int messageId = 0;
 
         switch (bluetoothState) {
@@ -245,9 +245,7 @@
                 if (mMyDevicePreference == null) {
                     mMyDevicePreference = new Preference(getActivity());
                 }
-                if (mLocalAdapter != null) {
-                    mMyDevicePreference.setTitle(mLocalAdapter.getName());
-                }
+                mMyDevicePreference.setTitle(mLocalAdapter.getName());
                 mMyDevicePreference.setPersistent(false);
                 mMyDevicePreference.setEnabled(true);
                 preferenceScreen.addPreference(mMyDevicePreference);
@@ -255,6 +253,7 @@
                 if (mDiscoverableEnabler == null) {
                     mDiscoverableEnabler = new BluetoothDiscoverableEnabler(getActivity(),
                             mLocalAdapter, mMyDevicePreference);
+                    mDiscoverableEnabler.resume();
                 }
 
                 // Paired devices category
@@ -291,14 +290,12 @@
                     preferenceScreen.removePreference(mPairedDevicesCategory);
                     startScanning();
                 }
+                getActivity().invalidateOptionsMenu();
                 return; // not break
 
             case BluetoothAdapter.STATE_TURNING_OFF:
-                int preferenceCount = preferenceScreen.getPreferenceCount();
-                for (int i = 0; i < preferenceCount; i++) {
-                    preferenceScreen.getPreference(i).setEnabled(false);
-                }
-                return; // not break
+                messageId = R.string.bluetooth_turning_off;
+                break;
 
             case BluetoothAdapter.STATE_OFF:
                 messageId = R.string.bluetooth_empty_list_bluetooth_off;
@@ -312,6 +309,7 @@
         setDeviceListGroup(preferenceScreen);
         removeAllDevices();
         mEmptyView.setText(messageId);
+        getActivity().invalidateOptionsMenu();
     }
 
     @Override
diff --git a/src/com/android/settings/bluetooth/DeviceListPreferenceFragment.java b/src/com/android/settings/bluetooth/DeviceListPreferenceFragment.java
index 9783fd7..53bd33c 100644
--- a/src/com/android/settings/bluetooth/DeviceListPreferenceFragment.java
+++ b/src/com/android/settings/bluetooth/DeviceListPreferenceFragment.java
@@ -151,7 +151,6 @@
 
     public void onDeviceAdded(CachedBluetoothDevice cachedDevice) {
         if (mDevicePreferenceMap.get(cachedDevice) != null) {
-            Log.e(TAG, "Got onDeviceAdded, but cachedDevice already exists");
             return;
         }
 
diff --git a/src/com/android/settings/bluetooth/LocalBluetoothManager.java b/src/com/android/settings/bluetooth/LocalBluetoothManager.java
old mode 100644
new mode 100755
index 63b8b7c..a1edca1
--- a/src/com/android/settings/bluetooth/LocalBluetoothManager.java
+++ b/src/com/android/settings/bluetooth/LocalBluetoothManager.java
@@ -79,6 +79,10 @@
         return mContext;
     }
 
+    public Context getForegroundActivity() {
+        return mForegroundActivity;
+    }
+
     boolean isForegroundActivity() {
         return mForegroundActivity != null;
     }
diff --git a/src/com/android/settings/bluetooth/Utils.java b/src/com/android/settings/bluetooth/Utils.java
old mode 100644
new mode 100755
index 7d38e17..01e72e0
--- a/src/com/android/settings/bluetooth/Utils.java
+++ b/src/com/android/settings/bluetooth/Utils.java
@@ -89,11 +89,17 @@
 
     static void showError(Context context, String name, int messageResId) {
         String message = context.getString(messageResId, name);
-        new AlertDialog.Builder(context)
+        LocalBluetoothManager manager = LocalBluetoothManager.getInstance(context);
+        Context activity = manager.getForegroundActivity();
+        if(manager.isForegroundActivity()) {
+            new AlertDialog.Builder(activity)
                 .setIcon(android.R.drawable.ic_dialog_alert)
                 .setTitle(R.string.bluetooth_error_title)
                 .setMessage(message)
                 .setPositiveButton(android.R.string.ok, null)
                 .show();
+        } else {
+            Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
+        }
     }
 }
diff --git a/src/com/android/settings/inputmethod/CheckBoxAndSettingsPreference.java b/src/com/android/settings/inputmethod/CheckBoxAndSettingsPreference.java
new file mode 100644
index 0000000..f983f59
--- /dev/null
+++ b/src/com/android/settings/inputmethod/CheckBoxAndSettingsPreference.java
@@ -0,0 +1,118 @@
+/*
+ * 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 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;
+
+public class CheckBoxAndSettingsPreference extends CheckBoxPreference {
+    private static final float DISABLED_ALPHA = 0.4f;
+
+    private SettingsPreferenceFragment mFragment;
+    private TextView mTitleText;
+    private TextView mSummaryText;
+    private View mCheckBox;
+    private ImageView mSetingsButton;
+    private Intent mSettingsIntent;
+
+    public CheckBoxAndSettingsPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        setLayoutResource(R.layout.preference_inputmethod);
+        setWidgetLayoutResource(R.layout.preference_inputmethod_widget);
+    }
+
+    @Override
+    protected void onBindView(View view) {
+        super.onBindView(view);
+        mCheckBox = view.findViewById(R.id.inputmethod_pref);
+        mCheckBox.setOnClickListener(
+                new OnClickListener() {
+                    @Override
+                    public void onClick(View arg0) {
+                        onCheckBoxClicked(arg0);
+                    }
+                });
+        mSetingsButton = (ImageView)view.findViewById(R.id.inputmethod_settings);
+        mTitleText = (TextView)view.findViewById(android.R.id.title);
+        mSummaryText = (TextView)view.findViewById(android.R.id.summary);
+        mSetingsButton.setOnClickListener(
+                new OnClickListener() {
+                    @Override
+                    public void onClick(View arg0) {
+                        onSettingsButtonClicked(arg0);
+                    }
+                });
+        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(View view) {
+        if (isChecked()) {
+            setChecked(false);
+        } else {
+            setChecked(true);
+        }
+    }
+
+    protected void onSettingsButtonClicked(View arg0) {
+        if (mFragment != null && mSettingsIntent != null) {
+            mFragment.startActivity(mSettingsIntent);
+        }
+    }
+
+    private void enableSettingsButton() {
+        if (mSetingsButton != null) {
+            if (mSettingsIntent == null) {
+                mSetingsButton.setVisibility(View.GONE);
+            } else {
+                final boolean checked = isChecked();
+                mSetingsButton.setEnabled(checked);
+                mSetingsButton.setClickable(checked);
+                mSetingsButton.setFocusable(checked);
+                if (!checked) {
+                    mSetingsButton.setAlpha(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 e966ec7..699a4a6 100644
--- a/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java
+++ b/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java
@@ -17,6 +17,7 @@
 package com.android.settings.inputmethod;
 
 import com.android.settings.R;
+import com.android.settings.Settings.SpellCheckersSettingsActivity;
 import com.android.settings.SettingsPreferenceFragment;
 import com.android.settings.UserDictionarySettings;
 import com.android.settings.Utils;
@@ -112,6 +113,14 @@
         mImm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
         mImis = mImm.getInputMethodList();
         createImePreferenceHierarchy((PreferenceGroup)findPreference("keyboard_settings_category"));
+
+        final Intent intent = new Intent(Intent.ACTION_MAIN);
+        intent.setClass(getActivity(), SpellCheckersSettingsActivity.class);
+        final SpellCheckersPreference scp = ((SpellCheckersPreference)findPreference(
+                "spellcheckers_settings"));
+        if (scp != null) {
+            scp.setFragmentIntent(this, intent);
+        }
     }
 
     private void updateInputMethodSelectorSummary(int value) {
diff --git a/src/com/android/settings/inputmethod/InputMethodAndSubtypeEnabler.java b/src/com/android/settings/inputmethod/InputMethodAndSubtypeEnabler.java
index b5353d6..efed823 100644
--- a/src/com/android/settings/inputmethod/InputMethodAndSubtypeEnabler.java
+++ b/src/com/android/settings/inputmethod/InputMethodAndSubtypeEnabler.java
@@ -147,6 +147,7 @@
                             .setCancelable(true)
                             .setPositiveButton(android.R.string.ok,
                                     new DialogInterface.OnClickListener() {
+                                        @Override
                                         public void onClick(DialogInterface dialog, int which) {
                                             chkPref.setChecked(true);
                                             InputMethodAndSubtypeUtil.setSubtypesPreferenceEnabled(
@@ -157,6 +158,7 @@
                             })
                             .setNegativeButton(android.R.string.cancel,
                                     new DialogInterface.OnClickListener() {
+                                        @Override
                                         public void onClick(DialogInterface dialog, int which) {
                                         }
 
diff --git a/src/com/android/settings/inputmethod/SpellCheckerUtils.java b/src/com/android/settings/inputmethod/SpellCheckerUtils.java
new file mode 100644
index 0000000..fe761a6
--- /dev/null
+++ b/src/com/android/settings/inputmethod/SpellCheckerUtils.java
@@ -0,0 +1,47 @@
+/*
+ * 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.util.Log;
+import android.view.textservice.SpellCheckerInfo;
+import android.view.textservice.TextServicesManager;
+
+public class SpellCheckerUtils {
+    private static final String TAG = SpellCheckerUtils.class.getSimpleName();
+    private static final boolean DBG = false;
+    public static void setSpellCheckersEnabled(TextServicesManager tsm, boolean enable) {
+    }
+    public static boolean getSpellCheckersEnabled(TextServicesManager tsm) {
+        return true;
+    }
+    public static void setCurrentSpellChecker(TextServicesManager tsm, SpellCheckerInfo info) {
+    }
+    public static SpellCheckerInfo getCurrentSpellChecker(TextServicesManager tsm) {
+        final SpellCheckerInfo retval = tsm.getCurrentSpellChecker();
+        if (DBG) {
+            Log.d(TAG, "getCurrentSpellChecker: " + retval);
+        }
+        return retval;
+    }
+    public static SpellCheckerInfo[] getEnabledSpellCheckers(TextServicesManager tsm) {
+        final SpellCheckerInfo[] retval = tsm.getEnabledSpellCheckers();
+        if (DBG) {
+            Log.d(TAG, "get spell checkers: " + retval.length);
+        }
+        return retval;
+    }
+}
diff --git a/src/com/android/settings/inputmethod/SpellCheckersPreference.java b/src/com/android/settings/inputmethod/SpellCheckersPreference.java
new file mode 100644
index 0000000..7d2eec8
--- /dev/null
+++ b/src/com/android/settings/inputmethod/SpellCheckersPreference.java
@@ -0,0 +1,27 @@
+/*
+ * 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;
+
+public class SpellCheckersPreference extends CheckBoxAndSettingsPreference {
+
+    public SpellCheckersPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+}
diff --git a/src/com/android/settings/inputmethod/SpellCheckersSettings.java b/src/com/android/settings/inputmethod/SpellCheckersSettings.java
new file mode 100644
index 0000000..c8b3ca9
--- /dev/null
+++ b/src/com/android/settings/inputmethod/SpellCheckersSettings.java
@@ -0,0 +1,89 @@
+/*
+ * 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 android.content.Context;
+import android.os.Bundle;
+import android.preference.Preference;
+import android.preference.PreferenceScreen;
+import android.view.textservice.SpellCheckerInfo;
+import android.view.textservice.TextServicesManager;
+
+public class SpellCheckersSettings extends SettingsPreferenceFragment
+        implements Preference.OnPreferenceChangeListener {
+
+    private SpellCheckerInfo mCurrentSci;
+    private SpellCheckerInfo[] mEnabledScis;
+    private TextServicesManager mTsm;
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        mTsm = (TextServicesManager) getSystemService(Context.TEXT_SERVICES_MANAGER_SERVICE);
+        addPreferencesFromResource(R.xml.spellchecker_prefs);
+        updateScreen();
+    }
+
+    @Override
+    public boolean onPreferenceChange(Preference arg0, Object arg1) {
+        return false;
+    }
+
+    @Override
+    public boolean onPreferenceTreeClick(PreferenceScreen screen, Preference preference) {
+        return false;
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        updateScreen();
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        saveState();
+    }
+
+    private void saveState() {
+        SpellCheckerUtils.setCurrentSpellChecker(mTsm, mCurrentSci);
+    }
+
+    private void updateScreen() {
+        getPreferenceScreen().removeAll();
+        updateEnabledSpellCheckers();
+    }
+
+    private void updateEnabledSpellCheckers() {
+        mCurrentSci = SpellCheckerUtils.getCurrentSpellChecker(mTsm);
+        mEnabledScis = SpellCheckerUtils.getEnabledSpellCheckers(mTsm);
+        if (mCurrentSci == null || mEnabledScis == null) {
+            return;
+        }
+        // TODO: implement here
+        for (int i = 0; i < mEnabledScis.length; ++i) {
+            final SpellCheckerInfo sci = mEnabledScis[i];
+            final PreferenceScreen scs = new PreferenceScreen(getActivity(), null);
+            scs.setTitle(sci.getId());
+            getPreferenceScreen().addPreference(scs);
+        }
+    }
+}
diff --git a/src/com/android/settings/inputmethod/UserDictionaryList.java b/src/com/android/settings/inputmethod/UserDictionaryList.java
index e0afe48..232a6db 100644
--- a/src/com/android/settings/inputmethod/UserDictionaryList.java
+++ b/src/com/android/settings/inputmethod/UserDictionaryList.java
@@ -45,6 +45,7 @@
     }
 
     static Set<String> getUserDictionaryLocalesList(Activity activity) {
+        @SuppressWarnings("deprecation")
         final Cursor cursor = activity.managedQuery(UserDictionary.Words.CONTENT_URI,
                 new String[] { UserDictionary.Words.LOCALE },
                 null, null, null);
diff --git a/src/com/android/settings/wifi/WifiConfigController.java b/src/com/android/settings/wifi/WifiConfigController.java
index a8ce94f..897280f 100644
--- a/src/com/android/settings/wifi/WifiConfigController.java
+++ b/src/com/android/settings/wifi/WifiConfigController.java
@@ -90,8 +90,8 @@
     /* These values come from "wifi_network_setup" resource array */
     public static final int MANUAL = 0;
     public static final int WPS_PBC = 1;
-    public static final int WPS_PIN_FROM_ACCESS_POINT = 2;
-    public static final int WPS_PIN_FROM_DEVICE = 3;
+    public static final int WPS_KEYPAD = 2;
+    public static final int WPS_DISPLAY = 3;
 
     /* These values come from "wifi_proxy_settings" resource array */
     public static final int PROXY_NONE = 0;
@@ -473,11 +473,11 @@
             case WPS_PBC:
                 config.setup = Setup.PBC;
                 break;
-            case WPS_PIN_FROM_ACCESS_POINT:
-                config.setup = Setup.PIN_FROM_ACCESS_POINT;
+            case WPS_KEYPAD:
+                config.setup = Setup.KEYPAD;
                 break;
-            case WPS_PIN_FROM_DEVICE:
-                config.setup = Setup.PIN_FROM_DEVICE;
+            case WPS_DISPLAY:
+                config.setup = Setup.DISPLAY;
                 break;
             default:
                 config.setup = Setup.INVALID;
@@ -559,14 +559,14 @@
         int pos = mNetworkSetupSpinner.getSelectedItemPosition();
 
         /* Show pin text input if needed */
-        if (pos == WPS_PIN_FROM_ACCESS_POINT) {
+        if (pos == WPS_DISPLAY) {
             mView.findViewById(R.id.wps_fields).setVisibility(View.VISIBLE);
         } else {
             mView.findViewById(R.id.wps_fields).setVisibility(View.GONE);
         }
 
         /* show/hide manual security fields appropriately */
-        if ((pos == WPS_PIN_FROM_ACCESS_POINT) || (pos == WPS_PIN_FROM_DEVICE)
+        if ((pos == WPS_DISPLAY) || (pos == WPS_KEYPAD)
                 || (pos == WPS_PBC)) {
             mView.findViewById(R.id.security_fields).setVisibility(View.GONE);
         } else {
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index 74400d4..af83984 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -261,7 +261,6 @@
                     .setEnabled(wifiIsEnabled)
                     .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
             menu.add(Menu.NONE, MENU_ID_ADD_NETWORK, 0, R.string.wifi_add_network)
-                    //.setIcon(android.R.drawable.ic_menu_add)
                     .setEnabled(wifiIsEnabled)
                     .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
             menu.add(Menu.NONE, MENU_ID_ADVANCED, 0, R.string.wifi_menu_advanced)
@@ -683,8 +682,8 @@
         int networkSetup = configController.chosenNetworkSetupMethod();
         switch(networkSetup) {
             case WifiConfigController.WPS_PBC:
-            case WifiConfigController.WPS_PIN_FROM_ACCESS_POINT:
-            case WifiConfigController.WPS_PIN_FROM_DEVICE:
+            case WifiConfigController.WPS_DISPLAY:
+            case WifiConfigController.WPS_KEYPAD:
                 mWifiManager.startWps(configController.getWpsConfig());
                 break;
             case WifiConfigController.MANUAL:
diff --git a/src/com/android/settings/wifi/p2p/WifiP2pDialog.java b/src/com/android/settings/wifi/p2p/WifiP2pDialog.java
new file mode 100644
index 0000000..380fa13
--- /dev/null
+++ b/src/com/android/settings/wifi/p2p/WifiP2pDialog.java
@@ -0,0 +1,137 @@
+/*
+ * 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.wifi.p2p;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.net.wifi.WpsConfiguration;
+import android.net.wifi.WpsConfiguration.Setup;
+import android.net.wifi.p2p.WifiP2pConfig;
+import android.net.wifi.p2p.WifiP2pDevice;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.CheckBox;
+import android.widget.Spinner;
+import android.widget.TextView;
+
+import com.android.settings.R;
+
+/**
+ * Dialog to setup a p2p connection
+ */
+public class WifiP2pDialog extends AlertDialog implements AdapterView.OnItemSelectedListener {
+
+    static final int BUTTON_SUBMIT = DialogInterface.BUTTON_POSITIVE;
+
+    private final DialogInterface.OnClickListener mListener;
+
+    private View mView;
+    private TextView mDeviceName;
+    private TextView mDeviceAddress;
+
+    /* These values come from "wifi_p2p_wps_setup" resource array */
+    private static final int WPS_PBC = 0;
+    private static final int WPS_KEYPAD = 1;
+    private static final int WPS_DISPLAY = 2;
+
+    private int mWpsSetupIndex = WPS_PBC; //default is pbc
+
+    WifiP2pDevice mDevice;
+
+    public WifiP2pDialog(Context context, DialogInterface.OnClickListener listener,
+            WifiP2pDevice device) {
+        super(context);
+        mListener = listener;
+        mDevice = device;
+    }
+
+    public WifiP2pConfig getConfig() {
+        WifiP2pConfig config = new WifiP2pConfig();
+        config.deviceAddress = mDeviceAddress.getText().toString();
+        config.deviceName = mDeviceName.getText().toString();
+        config.wpsConfig = new WpsConfiguration();
+        switch (mWpsSetupIndex) {
+            case WPS_PBC:
+                config.wpsConfig.setup = Setup.PBC;
+                break;
+            case WPS_KEYPAD:
+                config.wpsConfig.setup = Setup.KEYPAD;
+                config.wpsConfig.pin = ((TextView) mView.findViewById(R.id.wps_pin)).
+                        getText().toString();
+                break;
+            case WPS_DISPLAY:
+                config.wpsConfig.setup = Setup.DISPLAY;
+                break;
+            default:
+                config.wpsConfig.setup = Setup.PBC;
+                break;
+        }
+        if (mDevice.isGroupOwner()) {
+            config.joinExistingGroup = true;
+        }
+        return config;
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+
+        mView = getLayoutInflater().inflate(R.layout.wifi_p2p_dialog, null);
+        Spinner mWpsSetup = ((Spinner) mView.findViewById(R.id.wps_setup));
+
+        setView(mView);
+        setInverseBackgroundForced(true);
+
+        Context context = getContext();
+
+        setTitle(R.string.wifi_p2p_settings_title);
+        mDeviceName = (TextView) mView.findViewById(R.id.device_name);
+        mDeviceAddress = (TextView) mView.findViewById(R.id.device_address);
+
+        setButton(BUTTON_SUBMIT, context.getString(R.string.wifi_connect), mListener);
+        setButton(DialogInterface.BUTTON_NEGATIVE,
+                    context.getString(R.string.wifi_cancel), mListener);
+
+        if (mDevice != null) {
+            mDeviceName.setText(mDevice.deviceName);
+            mDeviceAddress.setText(mDevice.deviceAddress);
+            mWpsSetup.setSelection(mWpsSetupIndex); //keep pbc as default
+       }
+
+        mWpsSetup.setOnItemSelectedListener(this);
+
+        super.onCreate(savedInstanceState);
+    }
+
+    @Override
+    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+        mWpsSetupIndex = position;
+
+        if (mWpsSetupIndex == WPS_KEYPAD) {
+            mView.findViewById(R.id.wps_pin_entry).setVisibility(View.VISIBLE);
+        } else {
+            mView.findViewById(R.id.wps_pin_entry).setVisibility(View.GONE);
+        }
+        return;
+    }
+
+    @Override
+    public void onNothingSelected(AdapterView<?> parent) {
+    }
+
+}
diff --git a/src/com/android/settings/wifi/p2p/WifiP2pEnabler.java b/src/com/android/settings/wifi/p2p/WifiP2pEnabler.java
new file mode 100644
index 0000000..fd79a58
--- /dev/null
+++ b/src/com/android/settings/wifi/p2p/WifiP2pEnabler.java
@@ -0,0 +1,144 @@
+/*
+ * 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.wifi.p2p;
+
+import com.android.settings.R;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.wifi.p2p.WifiP2pManager;
+import android.os.Handler;
+import android.os.Message;
+import android.preference.Preference;
+import android.provider.Settings;
+import android.util.Log;
+import android.widget.CompoundButton;
+import android.widget.Switch;
+
+/**
+ * WifiP2pEnabler is a helper to manage the Wifi p2p on/off
+ */
+public class WifiP2pEnabler implements CompoundButton.OnCheckedChangeListener {
+    private static final String TAG = "WifiP2pEnabler";
+
+    private final Context mContext;
+    private Switch mSwitch;
+    private int mWifiP2pState;
+    private final IntentFilter mIntentFilter;
+    private final Handler mHandler = new WifiP2pHandler();
+    private WifiP2pManager mWifiP2pManager;
+
+    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+
+            if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {
+                handleP2pStateChanged(intent.getIntExtra(
+                        WifiP2pManager.EXTRA_WIFI_STATE, WifiP2pManager.WIFI_P2P_STATE_DISABLED));
+            }
+        }
+    };
+
+    public WifiP2pEnabler(Context context, Switch switch_) {
+        mContext = context;
+        mSwitch = switch_;
+
+        mWifiP2pManager = (WifiP2pManager) context.getSystemService(Context.WIFI_P2P_SERVICE);
+        if (!mWifiP2pManager.connectHandler(mContext, mHandler)) {
+            //Failure to set up connection
+            Log.e(TAG, "Failed to set up connection with wifi p2p service");
+            mWifiP2pManager = null;
+            mSwitch.setEnabled(false);
+        }
+        mIntentFilter = new IntentFilter(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
+
+    }
+
+    public void resume() {
+        if (mWifiP2pManager == null) return;
+        mContext.registerReceiver(mReceiver, mIntentFilter);
+        mSwitch.setOnCheckedChangeListener(this);
+    }
+
+    public void pause() {
+        if (mWifiP2pManager == null) return;
+        mContext.unregisterReceiver(mReceiver);
+        mSwitch.setOnCheckedChangeListener(null);
+    }
+
+    public void setSwitch(Switch switch_) {
+        if (mSwitch == switch_) return;
+        mSwitch.setOnCheckedChangeListener(null);
+        mSwitch = switch_;
+        mSwitch.setOnCheckedChangeListener(this);
+
+        mSwitch.setChecked(mWifiP2pState == WifiP2pManager.WIFI_P2P_STATE_ENABLED);
+    }
+
+    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+
+        if (mWifiP2pManager == null) return;
+
+        if (isChecked) {
+            mWifiP2pManager.enableP2p();
+        } else {
+            mWifiP2pManager.disableP2p();
+        }
+    }
+
+    private void handleP2pStateChanged(int state) {
+        mSwitch.setEnabled(true);
+        switch (state) {
+            case WifiP2pManager.WIFI_P2P_STATE_ENABLED:
+                mWifiP2pState = WifiP2pManager.WIFI_P2P_STATE_ENABLED;
+                mSwitch.setChecked(true);
+                break;
+            case WifiP2pManager.WIFI_P2P_STATE_DISABLED:
+                mWifiP2pState = WifiP2pManager.WIFI_P2P_STATE_DISABLED;
+                mSwitch.setChecked(false);
+                break;
+            default:
+                mWifiP2pState = WifiP2pManager.WIFI_P2P_STATE_DISABLED;
+                Log.e(TAG,"Unhandled wifi state " + state);
+                break;
+        }
+    }
+
+    private class WifiP2pHandler extends Handler {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case WifiP2pManager.HANDLER_DISCONNECTION:
+                    //Failure to set up connection
+                    Log.e(TAG, "Lost connection with wifi p2p service");
+                    mWifiP2pManager = null;
+                    mSwitch.setEnabled(false);
+                    break;
+                case WifiP2pManager.ENABLE_P2P_FAILED:
+                    mSwitch.setEnabled(true);
+                    break;
+                default:
+                    //Ignore
+                    break;
+            }
+        }
+    }
+
+}
diff --git a/src/com/android/settings/wifi/p2p/WifiP2pPeer.java b/src/com/android/settings/wifi/p2p/WifiP2pPeer.java
new file mode 100644
index 0000000..35ae15a
--- /dev/null
+++ b/src/com/android/settings/wifi/p2p/WifiP2pPeer.java
@@ -0,0 +1,104 @@
+/*
+ * 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.wifi.p2p;
+
+import com.android.settings.R;
+
+import android.content.Context;
+import android.net.wifi.WifiManager;
+import android.net.wifi.p2p.WifiP2pManager;
+import android.net.wifi.p2p.WifiP2pDevice;
+import android.net.wifi.p2p.WifiP2pDevice.Status;
+import android.preference.Preference;
+import android.text.TextUtils;
+import android.view.View;
+import android.widget.ImageView;
+
+import java.util.Comparator;
+
+public class WifiP2pPeer extends Preference {
+
+    private static final int[] STATE_SECURED = {R.attr.state_encrypted};
+    public WifiP2pDevice device;
+
+    private int mRssi;
+    private ImageView mSignal;
+
+    private static final int SIGNAL_LEVELS = 4;
+
+    public WifiP2pPeer(Context context, WifiP2pDevice dev) {
+        super(context);
+        device = dev;
+        setWidgetLayoutResource(R.layout.preference_widget_wifi_signal);
+        mRssi = 60; //TODO: fix
+    }
+
+    @Override
+    protected void onBindView(View view) {
+        if (TextUtils.isEmpty(device.deviceName)) {
+            setTitle(device.deviceAddress);
+        } else {
+            setTitle(device.deviceName);
+        }
+        mSignal = (ImageView) view.findViewById(R.id.signal);
+        if (mRssi == Integer.MAX_VALUE) {
+            mSignal.setImageDrawable(null);
+        } else {
+            mSignal.setImageResource(R.drawable.wifi_signal);
+            mSignal.setImageState(STATE_SECURED,  true);
+        }
+        refresh();
+        super.onBindView(view);
+    }
+
+    @Override
+    public int compareTo(Preference preference) {
+        if (!(preference instanceof WifiP2pPeer)) {
+            return 1;
+        }
+        WifiP2pPeer other = (WifiP2pPeer) preference;
+
+        // devices go in the order of the status
+        if (device.status != other.device.status) {
+            return device.status.ordinal() < other.device.status.ordinal() ? -1 : 1;
+        }
+
+        // Sort by name/address
+        if (device.deviceName != null) {
+            return device.deviceName.compareToIgnoreCase(other.device.deviceName);
+        }
+
+        return device.deviceAddress.compareToIgnoreCase(other.device.deviceAddress);
+    }
+
+    int getLevel() {
+        if (mRssi == Integer.MAX_VALUE) {
+            return -1;
+        }
+        return WifiManager.calculateSignalLevel(mRssi, SIGNAL_LEVELS);
+    }
+
+    private void refresh() {
+        if (mSignal == null) {
+            return;
+        }
+        Context context = getContext();
+        mSignal.setImageLevel(getLevel());
+        String[] statusArray = context.getResources().getStringArray(R.array.wifi_p2p_status);
+        setSummary(statusArray[device.status.ordinal()]);
+    }
+}
diff --git a/src/com/android/settings/wifi/p2p/WifiP2pSettings.java b/src/com/android/settings/wifi/p2p/WifiP2pSettings.java
new file mode 100644
index 0000000..2e05595
--- /dev/null
+++ b/src/com/android/settings/wifi/p2p/WifiP2pSettings.java
@@ -0,0 +1,257 @@
+/*
+ * 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;
+
+import android.app.ActionBar;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.wifi.p2p.WifiP2pConfig;
+import android.net.wifi.p2p.WifiP2pDevice;
+import android.net.wifi.p2p.WifiP2pDeviceList;
+import android.net.wifi.p2p.WifiP2pManager;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.preference.Preference;
+import android.preference.PreferenceActivity;
+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.widget.Switch;
+
+import com.android.settings.wifi.p2p.WifiP2pDialog;
+import com.android.settings.wifi.p2p.WifiP2pEnabler;
+import com.android.settings.wifi.p2p.WifiP2pPeer;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Collection;
+
+/*
+ * Displays Wi-fi p2p settings UI
+ */
+public class WifiP2pSettings extends SettingsPreferenceFragment {
+
+    private static final String TAG = "WifiP2pSettings";
+    private static final int MENU_ID_SEARCH = Menu.FIRST;
+    private static final int MENU_ID_CREATE_GROUP = Menu.FIRST + 1;
+    private static final int MENU_ID_ADVANCED = Menu.FIRST +2;
+
+
+    private final IntentFilter mIntentFilter = new IntentFilter();
+    private final Handler mHandler = new WifiP2pHandler();
+    private WifiP2pManager mWifiP2pManager;
+    private WifiP2pEnabler mWifiP2pEnabler;
+    private WifiP2pDialog mConnectDialog;
+    private OnClickListener mConnectListener;
+    private OnClickListener mDisconnectListener;
+    private WifiP2pPeer mSelectedWifiPeer;
+
+    private static final int DIALOG_CONNECT     = 1;
+    private static final int DIALOG_DISCONNECT  = 2;
+
+    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+
+            if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {
+                //TODO: nothing right now
+            } else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {
+                if (mWifiP2pManager != null) mWifiP2pManager.requestPeers();
+            }
+        }
+    };
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        addPreferencesFromResource(R.xml.wifi_p2p_settings);
+
+        mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
+        mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
+
+        final Activity activity = getActivity();
+        mWifiP2pManager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
+        if (!mWifiP2pManager.connectHandler(activity, mHandler)) {
+            //Failure to set up connection
+            Log.e(TAG, "Failed to set up connection with wifi p2p service");
+            mWifiP2pManager = null;
+        }
+
+        Switch actionBarSwitch = new Switch(activity);
+
+        if (activity instanceof PreferenceActivity) {
+            PreferenceActivity preferenceActivity = (PreferenceActivity) activity;
+            if (preferenceActivity.onIsHidingHeaders() || !preferenceActivity.onIsMultiPane()) {
+                final int padding = activity.getResources().getDimensionPixelSize(
+                        R.dimen.action_bar_switch_padding);
+                actionBarSwitch.setPadding(0, 0, padding, 0);
+                activity.getActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM,
+                        ActionBar.DISPLAY_SHOW_CUSTOM);
+                activity.getActionBar().setCustomView(actionBarSwitch, new ActionBar.LayoutParams(
+                            ActionBar.LayoutParams.WRAP_CONTENT,
+                            ActionBar.LayoutParams.WRAP_CONTENT,
+                            Gravity.CENTER_VERTICAL | Gravity.RIGHT));
+            }
+        }
+
+        mWifiP2pEnabler = new WifiP2pEnabler(activity, actionBarSwitch);
+
+        //connect dialog listener
+        mConnectListener = new OnClickListener() {
+            @Override
+            public void onClick(DialogInterface dialog, int which) {
+                if (which == DialogInterface.BUTTON_POSITIVE) {
+                    WifiP2pConfig config = mConnectDialog.getConfig();
+                    if (mWifiP2pManager != null) {
+                        mWifiP2pManager.connect(config);
+                    }
+                }
+            }
+        };
+
+        //disconnect dialog listener
+        mDisconnectListener = new OnClickListener() {
+            @Override
+            public void onClick(DialogInterface dialog, int which) {
+                if (which == DialogInterface.BUTTON_POSITIVE) {
+                    if (mWifiP2pManager != null) {
+                        mWifiP2pManager.disconnect();
+                    }
+                }
+            }
+        };
+        setHasOptionsMenu(true);
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        getActivity().registerReceiver(mReceiver, mIntentFilter);
+        if (mWifiP2pEnabler != null) {
+            mWifiP2pEnabler.resume();
+        }
+        if (mWifiP2pManager != null) mWifiP2pManager.discoverPeers();
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        if (mWifiP2pEnabler != null) {
+            mWifiP2pEnabler.pause();
+        }
+        getActivity().unregisterReceiver(mReceiver);
+    }
+
+    @Override
+    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+        menu.add(Menu.NONE, MENU_ID_SEARCH, 0, R.string.wifi_p2p_menu_search)
+            .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
+        menu.add(Menu.NONE, MENU_ID_CREATE_GROUP, 0, R.string.wifi_p2p_menu_create_group)
+            .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
+        menu.add(Menu.NONE, MENU_ID_ADVANCED, 0, R.string.wifi_p2p_menu_advanced)
+            .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
+        super.onCreateOptionsMenu(menu, inflater);
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        switch (item.getItemId()) {
+            case MENU_ID_SEARCH:
+                mWifiP2pManager.discoverPeers();
+                return true;
+            case MENU_ID_CREATE_GROUP:
+                mWifiP2pManager.createGroup();
+                return true;
+            case MENU_ID_ADVANCED:
+                //TODO: add advanced settings for p2p
+                return true;
+        }
+        return super.onOptionsItemSelected(item);
+    }
+
+    @Override
+    public boolean onPreferenceTreeClick(PreferenceScreen screen, Preference preference) {
+        if (preference instanceof WifiP2pPeer) {
+            mSelectedWifiPeer = (WifiP2pPeer) preference;
+            if (mSelectedWifiPeer.device.status == WifiP2pDevice.Status.CONNECTED) {
+                showDialog(DIALOG_DISCONNECT);
+            } else {
+                showDialog(DIALOG_CONNECT);
+            }
+        }
+        return super.onPreferenceTreeClick(screen, preference);
+    }
+
+    @Override
+    public Dialog onCreateDialog(int id) {
+        if (id == DIALOG_CONNECT) {
+            mConnectDialog = new WifiP2pDialog(getActivity(), mConnectListener,
+                mSelectedWifiPeer.device);
+            return mConnectDialog;
+        } else if (id == DIALOG_DISCONNECT) {
+            AlertDialog dialog = new AlertDialog.Builder(getActivity())
+                .setTitle("Disconnect ?")
+                .setMessage("Do you want to disconnect ?")
+                .setPositiveButton(getActivity().getString(R.string.dlg_ok), mDisconnectListener)
+                .setNegativeButton(getActivity().getString(R.string.dlg_cancel), null)
+                .create();
+            return dialog;
+        }
+        return null;
+    }
+
+    private void updatePeers(WifiP2pDeviceList peers) {
+        final PreferenceScreen preferenceScreen = getPreferenceScreen();
+        preferenceScreen.removeAll();
+
+        for (WifiP2pDevice peer: peers.getDeviceList()) {
+            preferenceScreen.addPreference(new WifiP2pPeer(getActivity(), peer));
+        }
+    }
+
+    private class WifiP2pHandler extends Handler {
+        @Override
+        public void handleMessage(Message message) {
+            switch (message.what) {
+                case WifiP2pManager.HANDLER_DISCONNECTION:
+                    //Failure to set up connection
+                    Log.e(TAG, "Lost connection with wifi p2p service");
+                    mWifiP2pManager = null;
+                    break;
+                case WifiP2pManager.RESPONSE_PEERS:
+                    updatePeers(mWifiP2pManager.peersInResponse(message));
+                    break;
+                default:
+                    //Ignore
+                    break;
+            }
+        }
+    }
+
+}