Merge "Unify profile and device lock by setting the work lock on the device"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index ad783d3..4366b0b 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -573,14 +573,10 @@
         </activity>
 
         <activity android:name="Settings$InputMethodAndLanguageSettingsActivity"
-                android:label="@string/language_keyboard_settings_title"
-                android:icon="@drawable/ic_settings_language"
-                android:taskAffinity="com.android.settings"
-                android:parentActivityName="Settings">
-            <intent-filter android:priority="1">
-                <action android:name="android.settings.INPUT_METHOD_SETTINGS" />
-                <category android:name="android.intent.category.DEFAULT" />
-            </intent-filter>
+            android:label="@string/language_keyboard_settings_title"
+            android:icon="@drawable/ic_settings_language"
+            android:taskAffinity="com.android.settings"
+            android:parentActivityName="Settings">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.VOICE_LAUNCH" />
@@ -597,6 +593,16 @@
                 android:value="true" />
         </activity>
 
+        <activity android:name="Settings$AvailableVirtualKeyboardActivity"
+            android:label="@string/available_virtual_keyboard_category">
+            <intent-filter android:priority="1">
+                <action android:name="android.settings.INPUT_METHOD_SETTINGS" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                android:value="com.android.settings.inputmethod.AvailableVirtualKeyboardFragment" />
+        </activity>
+
         <activity android:name="Settings$ManageAssistActivity"
                 android:label="@string/assist_and_voice_input_title"
                 android:taskAffinity="com.android.settings"
@@ -1407,6 +1413,23 @@
                 android:value="true" />
         </activity>
 
+        <activity android:name=".accessibility.AccessibilitySettingsForSetupWizardActivity"
+                android:label="@string/vision_settings_title"
+                android:theme="@style/SetupWizardAccessibilityTheme"
+                android:taskAffinity="com.android.wizard"
+                android:configChanges="orientation|keyboardHidden|screenSize" >
+            <intent-filter android:priority="1">
+                <action android:name="android.settings.ACCESSIBILITY_SETTINGS_FOR_SUW" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+            <meta-data android:name="com.android.settings.category"
+                android:value="com.android.settings.category.system" />
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                android:value="com.android.settings.accessibility.AccessibilitySettingsForSetupWizard" />
+            <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
+                android:value="true" />
+        </activity>
+
         <activity android:name="Settings$AccessibilityDaltonizerSettingsActivity"
                 android:label="@string/accessibility_display_daltonizer_preference_title"
                 android:taskAffinity="com.android.settings"
diff --git a/res/layout/preference_button.xml b/res/layout/preference_button.xml
deleted file mode 100644
index 35e4255..0000000
--- a/res/layout/preference_button.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 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.
--->
-
-<!-- Layout for a ButtonPreference. -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:orientation="vertical"
-    android:paddingBottom="@dimen/accessibility_button_preference_padding_top_bottom"
-    android:paddingTop="@dimen/accessibility_button_preference_padding_top_bottom"
-    android:paddingStart="@dimen/accessibility_layout_margin_start_end"
-    android:paddingEnd="@dimen/accessibility_layout_margin_start_end"
-    android:focusable="true"
-    android:selectable="false"
-    android:persistent="false" >
-
-        <TextView xmlns:android="http://schemas.android.com/apk/res/android"
-            android:id="@+android:id/title"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:textAppearance="?android:attr/textAppearanceLarge"
-            android:selectable="true"
-            android:persistent="false"
-            android:gravity="left|center" />
-
-        <TextView xmlns:android="http://schemas.android.com/apk/res/android"
-            android:id="@+android:id/summary"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:textAppearance="?android:attr/textAppearanceSmall"
-            android:selectable="true"
-            android:persistent="false"
-            android:gravity="left|center" />
-
-</LinearLayout>
diff --git a/res/layout/preference_multiline_title.xml b/res/layout/preference_multiline_title.xml
new file mode 100644
index 0000000..f4e26fc
--- /dev/null
+++ b/res/layout/preference_multiline_title.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:minHeight="?android:attr/listPreferredItemHeightSmall"
+    android:gravity="center_vertical"
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+    android:background="?android:attr/selectableItemBackground">
+
+    <RelativeLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:paddingTop="16dip"
+        android:paddingBottom="16dip">
+
+        <TextView
+            android:id="@+android:id/title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textAppearance="@android:style/TextAppearance.Material.Subhead"
+            android:textColor="?android:attr/textColorPrimary"
+            android:ellipsize="marquee"
+            android:fadingEdge="horizontal" />
+
+        <TextView
+            android:id="@android:id/summary"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_below="@android:id/title"
+            android:layout_alignStart="@android:id/title"
+            android:visibility="gone"
+            android:textAlignment="viewStart"
+            android:textAppearance="@android:style/TextAppearance.Material.Body1"
+            android:textColor="?android:attr/textColorSecondary"
+            android:maxLines="10" />
+
+    </RelativeLayout>
+
+</LinearLayout>
diff --git a/res/layout/setup_redaction_interstitial.xml b/res/layout/setup_redaction_interstitial.xml
index 6eef9ce..58fd945 100644
--- a/res/layout/setup_redaction_interstitial.xml
+++ b/res/layout/setup_redaction_interstitial.xml
@@ -51,14 +51,14 @@
             android:layout_marginEnd="?android:attr/listPreferredItemPaddingEnd"
             android:checkedButton="@+id/redact_sensitive">
 
-            <RadioButton
+            <com.android.settings.RestrictedRadioButton
                 android:id="@+id/show_all"
                 style="@style/SuwRadioButton"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:text="@string/lock_screen_notifications_summary_show" />
 
-            <RadioButton
+            <com.android.settings.RestrictedRadioButton
                 android:id="@+id/redact_sensitive"
                 style="@style/SuwRadioButton"
                 android:layout_width="wrap_content"
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 8625ed7..60c15d7 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -104,4 +104,8 @@
     <color name="summary_default_start">#ff009587</color>
     <color name="summary_default_end">#ffced7db</color>
 
+    <!-- Accessibility SUW colors -->
+    <color name="material_blue_500">#4285F4</color>
+    <color name="material_blue_700">#3367D6</color>
+
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 9f3dddd..e4abbca 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -3528,6 +3528,25 @@
     <!-- Toast that settings for an application is failed to open. -->
     <string name="failed_to_open_app_settings_toast">Failed to open settings for <xliff:g id="spell_application_name">%1$s</xliff:g></string>
 
+    <!-- Title for the 'keyboard and input methods' preference category. [CHAR LIMIT=35] -->
+    <string name="keyboard_and_input_methods_category">Keyboard and input methods</string>
+    <!-- Title for the 'virtual keyboard' preference sub-screen. [CHAR LIMIT=35] -->
+    <string name="virtual_keyboard_category">Virtual keyboard</string>
+    <!-- Title for the 'physical keyboard' preference sub-screen. [CHAR LIMIT=35] -->
+    <string name="physical_keyboard_category">Physical keyboard</string>
+    <!-- Title for the 'available virtual keyboard' preference sub-screen. [CHAR LIMIT=35] -->
+    <string name="available_virtual_keyboard_category">Available virtual keyboard</string>
+    <!-- Title for the button to trigger the 'available virtual keyboard' preference sub-screen. [CHAR LIMIT=35] -->
+    <string name="add_virtual_keyboard">Add a virtual keyboard</string>
+    <!-- Title for the 'keyboard assistance' preference category. [CHAR LIMIT=35] -->
+    <string name="keyboard_assistance_category">Keyboard assistance</string>
+    <!-- Title for the 'show virtual keyboard' preference switch. [CHAR LIMIT=35] -->
+    <string name="show_ime">Show virtual keyboard</string>
+    <!-- Summary text for the 'add virtual keyboard' preference sub-screen. [CHAR LIMIT=100] -->
+    <string name="show_ime_summary">Keep it on screen while physical keyboard is active</string>
+    <!-- Title for the button to trigger the 'keyboard shortcuts helper' dialog. [CHAR LIMIT=35] -->
+    <string name="keyboard_shortcuts_helper">Keyboard shortcuts helper</string>
+
     <!-- On Language & input settings screen, heading. Inside the "Language & input settings" screen, this is the header for settings that relate to mouse and trackpad devices. [CHAR LIMIT=40] -->
     <string name="pointer_settings_category">Mouse/trackpad</string>
     <!-- On Language & input settings screen, setting summary.  Setting for mouse pointer speed. [CHAR LIMIT=35] -->
@@ -3699,10 +3718,14 @@
     <string name="accessibility_settings">Accessibility</string>
     <!-- Settings title for accessibility settings screen -->
     <string name="accessibility_settings_title">Accessibility settings</string>
-    <!-- Settings title for a brief version of Accessibility Settings, as displayed in Setup Wizard -->
-    <string name="accessibility_settings_for_setup_wizard_title">Guide me</string>
+    <!-- Settings title for a brief version of Vision-Related Accessibility Settings. Displayed in Setup Wizard only. [CHAR LIMIT=35] -->
+    <string name="vision_settings_title">Vision Settings</string>
+    <!-- Settings description for a brief version of Vision-Related Accessibility Settings. Tells the user that they can adjust these settings now to help them through the remainder of the Setup Wizard and that they can later be changed in Settings. Displayed in Setup Wizard only. [CHAR LIMIT=none] -->
+    <string name="vision_settings_description">Adjust these settings now to assist you through the remainder of the set up process. You can adjust them any time in device settings.</string>
     <!-- Title for the accessibility preference category of accessibility services. [CHAR LIMIT=25] -->
     <string name="accessibility_services_title">Services</string>
+    <!-- Summary for the Talkback Accessibility Service. Lets the user know that Talkback is a screenreader and that it is usually most helpful to blind and low vision users. [CHAR_LIMIT=none] -->
+    <string name="talkback_summary">Screenreader tool primarily for people with blindness and low vision</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 category of display related preferences. [CHAR LIMIT=25] -->
@@ -6729,7 +6752,7 @@
     <string name="camera_double_tap_power_gesture_desc">Quickly open camera without unlocking your screen</string>
 
     <!-- Title of setting that controls screen zoom (e.g. how large interface elements appear). [CHAR LIMIT=40] -->
-    <string name="screen_zoom_title">Screen zoom</string>
+    <string name="screen_zoom_title">Magnify display</string>
     <!-- Keywords for setting that controls screen zoom (e.g. how large interface elements appear). [CHAR LIMIT=NONE] -->
     <string name="screen_zoom_keywords">display density, screen zoom, scale, scaling</string>
     <!-- Summary of screen zoom setting screen. [CHAR LIMIT=NONE] -->
@@ -6865,10 +6888,13 @@
     <string name="suggestion_remove">Remove</string>
 
     <!-- Name of the setting to change the display's color temperature -->
-    <string name="color_temperature">Display color temperature</string>
+    <string name="color_temperature">Cool color temperature</string>
 
     <!-- Description of the setting to change the display's color temperature -->
-    <string name="color_temperature_desc">Enable cool temperature</string>
+    <string name="color_temperature_desc">Use cooler display colors</string>
+
+    <!-- Toast message letting the user know the color temperature setting is not immediate -->
+    <string name="color_temperature_toast">To apply color change, turn off screen</string>
 
     <!-- Label for category for data usage [CHAR LIMIT=30] -->
     <string name="usage">Usage</string>
diff --git a/res/values/themes.xml b/res/values/themes.xml
index 6288155..f3a9369 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -103,7 +103,6 @@
         <item name="@android:preferenceStyle">@style/Preference</item>
         <item name="@dropdownPreferenceStyle">@style/Preference.DropDown.Material</item>
         <item name="@android:preferenceFragmentStyle">@style/PreferenceFragmentStyle</item>
-
         <item name="apnPreferenceStyle">@style/ApnPreference</item>
     </style>
 
@@ -115,6 +114,14 @@
         <item name="android:layout">@layout/setup_preference</item>
     </style>
 
+    <!-- Accessibility portion of Setup Wizard -->
+    <style name="SetupWizardAccessibilityTheme" parent="Theme.SettingsBase">
+        <item name="android:colorPrimary">@color/material_blue_700</item>
+        <item name="android:colorPrimaryDark">@color/material_blue_700</item>
+        <item name="preferenceTheme">@style/PreferenceTheme</item>
+        <item name="switchBarTheme">@style/ThemeOverlay.SwitchBar.Settings</item>
+    </style>
+
     <!-- Theme with no local references, used by AccountPreferenceBase where we have to inflate
          layouts against a remote context using our local theme colors. Due to the implementation
          details of Theme, we can't reference any local resources and MUST instead use the values
diff --git a/res/xml/accessibility_settings.xml b/res/xml/accessibility_settings.xml
index c87912d..54a5a17 100644
--- a/res/xml/accessibility_settings.xml
+++ b/res/xml/accessibility_settings.xml
@@ -19,11 +19,6 @@
         android:title="@string/accessibility_settings"
         android:persistent="true">
 
-    <PreferenceScreen
-        android:key="accessibility_settings_for_setup_wizard"
-        android:title="@string/accessibility_settings_for_setup_wizard_title"
-        android:fragment="com.android.settings.accessibility.AccessibilitySettingsForSetupWizard" />
-
     <PreferenceCategory
             android:key="services_category"
             android:title="@string/accessibility_services_title">
diff --git a/res/xml/accessibility_settings_for_setup_wizard.xml b/res/xml/accessibility_settings_for_setup_wizard.xml
index f35d708..2317dc5 100644
--- a/res/xml/accessibility_settings_for_setup_wizard.xml
+++ b/res/xml/accessibility_settings_for_setup_wizard.xml
@@ -15,36 +15,34 @@
 -->
 
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
-        android:title="@string/accessibility_settings_title"
+        android:title="@string/vision_settings_title"
         android:persistent="true" >
 
     <Preference
-        android:fragment="com.android.settings.accessibility.ToggleScreenMagnificationPreferenceFragment"
-        android:key="screen_magnification_preference"
-        android:layout="@layout/preference_button"
-        android:title="@string/accessibility_screen_magnification_title" />
-
-    <Preference
-        android:key="font_size_preference"
-        android:layout="@layout/preference_button"
-        android:title="@string/title_font_size" />
+        android:key="vision_settings_summary"
+        android:title="@string/vision_settings_description"
+        android:layout="@layout/preference_multiline_title" />
 
     <com.android.settings.display.ScreenZoomPreference
         android:key="force_density_preference"
-        android:layout="@layout/preference_button"
-        settings:keywords="@string/screen_zoom_keywords"
         android:title="@string/screen_zoom_title"
         android:summary="%s" />
 
     <Preference
-        android:fragment="com.android.settings.accessibility.ToggleDaltonizerPreferenceFragment"
-        android:key="daltonizer_preference"
-        android:layout="@layout/preference_button"
-        android:title="@string/accessibility_display_daltonizer_preference_title" />
+        android:fragment="com.android.settings.accessibility.ToggleFontSizePreferenceFragment"
+        android:key="font_size_preference"
+        android:title="@string/title_font_size" />
+
+    <Preference
+        android:fragment=
+                "com.android.settings.accessibility.ToggleScreenMagnificationPreferenceFragment"
+        android:key="screen_magnification_preference"
+        android:title="@string/accessibility_screen_magnification_title"
+        android:summary="%s" />
 
     <Preference
         android:key="talkback_preference"
-        android:layout="@layout/preference_button" />
+        android:summary="@string/talkback_summary"
+        android:persistent="true" />
 
 </PreferenceScreen>
diff --git a/res/xml/language_settings.xml b/res/xml/language_settings.xml
index 83a0985..9cc0145 100644
--- a/res/xml/language_settings.xml
+++ b/res/xml/language_settings.xml
@@ -41,23 +41,34 @@
             />
 
     <PreferenceCategory
-            android:key="keyboard_settings_category"
-            android:title="@string/keyboard_settings_category">
-
+        android:title="@string/keyboard_and_input_methods_category">
         <PreferenceScreen
-                android:key="current_input_method"
-                android:title="@string/current_input_method"
-                />
-        <!-- Enabled input method list will be populated programmatically here. -->
+            android:title="@string/virtual_keyboard_category"
+            android:fragment="com.android.settings.inputmethod.VirtualKeyboardFragment" />
+        <PreferenceScreen
+            android:title="@string/physical_keyboard_category"
+            android:fragment="com.android.settings.inputmethod.PhysicalKeyboardFragment" />
     </PreferenceCategory>
 
-    <PreferenceCategory
-            android:key="hard_keyboard"
-            android:title="@string/builtin_keyboard_settings_title"
-            android:persistent="false">
-        <!-- Additional preference screens are inserted here programmatically
-             with low order values to set the key map of each attached keyboard. -->
-    </PreferenceCategory>
+    <!-- Temporarily disabled: -->
+    <!--<PreferenceCategory-->
+            <!--android:key="keyboard_settings_category"-->
+            <!--android:title="@string/keyboard_settings_category">-->
+
+        <!--<PreferenceScreen-->
+                <!--android:key="current_input_method"-->
+                <!--android:title="@string/current_input_method"-->
+                <!--/>-->
+        <!--&lt;!&ndash; Enabled input method list will be populated programmatically here. &ndash;&gt;-->
+    <!--</PreferenceCategory>-->
+
+    <!--<PreferenceCategory-->
+            <!--android:key="hard_keyboard"-->
+            <!--android:title="@string/builtin_keyboard_settings_title"-->
+            <!--android:persistent="false">-->
+        <!--&lt;!&ndash; Additional preference screens are inserted here programmatically-->
+             <!--with low order values to set the key map of each attached keyboard. &ndash;&gt;-->
+    <!--</PreferenceCategory>-->
 
     <PreferenceCategory
             android:key="voice_category"
diff --git a/res/xml/physical_keyboard_settings.xml b/res/xml/physical_keyboard_settings.xml
new file mode 100644
index 0000000..cbb95c2
--- /dev/null
+++ b/res/xml/physical_keyboard_settings.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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/physical_keyboard_category">
+    <!-- Additional preference screens are inserted here programmatically
+         with low order values to set the key map of each attached keyboard. -->
+    <PreferenceCategory
+        android:key="keyboard_assistance_category"
+        android:title="@string/keyboard_assistance_category">
+        <SwitchPreference
+            android:key="show_virtual_keyboard_switch"
+            android:title="@string/show_ime"
+            android:summary="@string/show_ime_summary"
+            android:defaultValue="false" />
+
+        <!-- TODO: Get summary text from UX -->
+        <Preference
+            android:key="keyboard_shortcuts_helper"
+            android:title="@string/keyboard_shortcuts_helper"
+            android:summary="@null" />
+    </PreferenceCategory>
+</PreferenceScreen>
diff --git a/res/xml/virtual_keyboard_settings.xml b/res/xml/virtual_keyboard_settings.xml
new file mode 100644
index 0000000..e5a5f38
--- /dev/null
+++ b/res/xml/virtual_keyboard_settings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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/virtual_keyboard_category">
+    <!-- Enabled input method list will be populated programmatically here. -->
+    <PreferenceScreen
+        android:key="add_virtual_keyboard_screen"
+        android:title="@string/add_virtual_keyboard"
+        android:fragment="com.android.settings.inputmethod.AvailableVirtualKeyboardFragment" />
+</PreferenceScreen>
diff --git a/src/com/android/settings/DevelopmentSettings.java b/src/com/android/settings/DevelopmentSettings.java
index b0a685c..e38efd0 100644
--- a/src/com/android/settings/DevelopmentSettings.java
+++ b/src/com/android/settings/DevelopmentSettings.java
@@ -76,6 +76,7 @@
 import android.webkit.WebViewProviderInfo;
 import android.widget.Switch;
 import android.widget.TextView;
+import android.widget.Toast;
 
 import com.android.internal.app.LocalePicker;
 import com.android.internal.logging.MetricsLogger;
@@ -1295,6 +1296,7 @@
         SystemProperties.set(COLOR_TEMPERATURE_PROPERTY,
                 mColorTemperaturePreference.isChecked() ? "1" : "0");
         pokeSystemProperties();
+        Toast.makeText(getActivity(), R.string.color_temperature_toast, Toast.LENGTH_LONG).show();
     }
 
     private void updateUSBAudioOptions() {
diff --git a/src/com/android/settings/InstrumentedFragment.java b/src/com/android/settings/InstrumentedFragment.java
index bb2f948..ea39cf3 100644
--- a/src/com/android/settings/InstrumentedFragment.java
+++ b/src/com/android/settings/InstrumentedFragment.java
@@ -38,6 +38,9 @@
     public static final int BILLING_CYCLE = UNDECLARED + 8;
     public static final int APP_DATA_USAGE = UNDECLARED + 9;
     public static final int USER_LOCALE_LIST = UNDECLARED + 10;
+    public static final int VIRTUAL_KEYBOARDS = UNDECLARED + 11;
+    public static final int PHYSICAL_KEYBOARDS = UNDECLARED + 12;
+    public static final int ENABLE_VIRTUAL_KEYBOARDS = UNDECLARED + 13;
 
     /**
      * Declare the view of this category.
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index edd0b4c..1c636b8 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -39,6 +39,7 @@
     public static class WifiSettingsActivity extends SettingsActivity { /* empty */ }
     public static class WifiP2pSettingsActivity extends SettingsActivity { /* empty */ }
     public static class InputMethodAndLanguageSettingsActivity extends SettingsActivity { /* empty */ }
+    public static class AvailableVirtualKeyboardActivity extends SettingsActivity { /* empty */ }
     public static class KeyboardLayoutPickerActivity extends SettingsActivity { /* empty */ }
     public static class InputMethodAndSubtypeEnablerActivity extends SettingsActivity { /* empty */ }
     public static class SpellCheckersSettingsActivity extends SettingsActivity { /* empty */ }
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index 88cfc74..dc134ff 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -53,6 +53,7 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.settings.Settings.WifiSettingsActivity;
 import com.android.settings.accessibility.AccessibilitySettings;
+import com.android.settings.accessibility.AccessibilitySettingsForSetupWizard;
 import com.android.settings.accessibility.CaptionPropertiesFragment;
 import com.android.settings.accounts.AccountSettings;
 import com.android.settings.accounts.AccountSyncSettings;
@@ -76,6 +77,7 @@
 import com.android.settings.fuelgauge.BatterySaverSettings;
 import com.android.settings.fuelgauge.PowerUsageDetail;
 import com.android.settings.fuelgauge.PowerUsageSummary;
+import com.android.settings.inputmethod.AvailableVirtualKeyboardFragment;
 import com.android.settings.inputmethod.InputMethodAndLanguageSettings;
 import com.android.settings.inputmethod.KeyboardLayoutPickerFragment;
 import com.android.settings.inputmethod.SpellCheckersSettings;
@@ -249,6 +251,7 @@
             DateTimeSettings.class.getName(),
             LocaleListEditor.class.getName(),
             InputMethodAndLanguageSettings.class.getName(),
+            AvailableVirtualKeyboardFragment.class.getName(),
             SpellCheckersSettings.class.getName(),
             UserDictionaryList.class.getName(),
             UserDictionarySettings.class.getName(),
@@ -265,6 +268,7 @@
             PrivacySettings.class.getName(),
             DeviceAdminSettings.class.getName(),
             AccessibilitySettings.class.getName(),
+            AccessibilitySettingsForSetupWizard.class.getName(),
             CaptionPropertiesFragment.class.getName(),
             com.android.settings.accessibility.ToggleDaltonizerPreferenceFragment.class.getName(),
             TextToSpeechSettings.class.getName(),
diff --git a/src/com/android/settings/SettingsPreferenceFragment.java b/src/com/android/settings/SettingsPreferenceFragment.java
index 2ba49ce..4f81a38 100644
--- a/src/com/android/settings/SettingsPreferenceFragment.java
+++ b/src/com/android/settings/SettingsPreferenceFragment.java
@@ -40,6 +40,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.Button;
+import com.android.settings.accessibility.AccessibilitySettingsForSetupWizardActivity;
 import com.android.settings.applications.LayoutPreference;
 import com.android.settings.widget.FloatingActionButton;
 
@@ -148,7 +149,8 @@
     @Override
     public void onActivityCreated(Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
-        if (!TextUtils.isEmpty(mHelpUri)) {
+        if (!TextUtils.isEmpty(mHelpUri)
+                && !(getActivity() instanceof AccessibilitySettingsForSetupWizardActivity)) {
             setHasOptionsMenu(true);
         }
     }
diff --git a/src/com/android/settings/UserCredentialsSettings.java b/src/com/android/settings/UserCredentialsSettings.java
index c440acf..e4ce267 100644
--- a/src/com/android/settings/UserCredentialsSettings.java
+++ b/src/com/android/settings/UserCredentialsSettings.java
@@ -17,10 +17,16 @@
 package com.android.settings;
 
 import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.app.Fragment;
+import android.app.FragmentManager;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.os.AsyncTask;
 import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
 import android.security.Credentials;
 import android.security.KeyStore;
 import android.view.LayoutInflater;
@@ -29,7 +35,6 @@
 import android.widget.AdapterView;
 import android.widget.AdapterView.OnItemClickListener;
 import android.widget.ArrayAdapter;
-import android.widget.ListAdapter;
 import android.widget.ListView;
 import android.widget.TextView;
 
@@ -56,7 +61,7 @@
     @Override
     public void onResume() {
         super.onResume();
-        new AliasLoader().execute();
+        refreshItems();
     }
 
     @Override
@@ -74,26 +79,62 @@
     @Override
     public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
         final Credential item = (Credential) parent.getItemAtPosition(position);
+        CredentialDialogFragment.show(this, item);
+    }
 
-        View root = getActivity().getLayoutInflater()
-                .inflate(R.layout.user_credential_dialog, null);
-        ViewGroup infoContainer = (ViewGroup) root.findViewById(R.id.credential_container);
-        infoContainer.addView(parent.getAdapter().getView(position, null, null));
+    protected void refreshItems() {
+        if (isAdded()) {
+            new AliasLoader().execute();
+        }
+    }
 
-        new AlertDialog.Builder(getActivity())
-                .setView(root)
-                .setTitle(R.string.user_credential_title)
-                .setPositiveButton(R.string.done, null)
-                .setNegativeButton(R.string.trusted_credentials_remove_label,
-                        new DialogInterface.OnClickListener() {
-                            @Override public void onClick(DialogInterface dialog, int id) {
-                                final KeyStore ks = KeyStore.getInstance();
-                                Credentials.deleteAllTypesForAlias(ks, item.alias);
-                                new AliasLoader().execute();
-                                dialog.dismiss();
-                            }
-                        })
-                .show();
+    public static class CredentialDialogFragment extends DialogFragment {
+        private static final String TAG = "CredentialDialogFragment";
+        private static final String ARG_CREDENTIAL = "credential";
+
+        public static void show(Fragment target, Credential item) {
+            final Bundle args = new Bundle();
+            args.putParcelable(ARG_CREDENTIAL, item);
+
+            final CredentialDialogFragment frag = new CredentialDialogFragment();
+            frag.setTargetFragment(target, /* requestCode */ -1);
+            frag.setArguments(args);
+            frag.show(target.getFragmentManager(), TAG);
+        }
+
+        @Override
+        public Dialog onCreateDialog(Bundle savedInstanceState) {
+            final Credential item = (Credential) getArguments().getParcelable(ARG_CREDENTIAL);
+            View root = getActivity().getLayoutInflater()
+                    .inflate(R.layout.user_credential_dialog, null);
+            ViewGroup infoContainer = (ViewGroup) root.findViewById(R.id.credential_container);
+            View view = new CredentialAdapter(getActivity(), R.layout.user_credential,
+                    new Credential[] {item}).getView(0, null, null);
+            infoContainer.addView(view);
+
+            return new AlertDialog.Builder(getActivity())
+                    .setView(root)
+                    .setTitle(R.string.user_credential_title)
+                    .setPositiveButton(R.string.done, null)
+                    .setNegativeButton(R.string.trusted_credentials_remove_label,
+                            new DialogInterface.OnClickListener() {
+                                @Override public void onClick(DialogInterface dialog, int id) {
+                                    final KeyStore ks = KeyStore.getInstance();
+                                    Credentials.deleteAllTypesForAlias(ks, item.alias);
+                                    dialog.dismiss();
+                                }
+                            })
+                    .create();
+        }
+
+        @Override
+        public void onDismiss(DialogInterface dialog) {
+            final Fragment target = getTargetFragment();
+            if (target instanceof UserCredentialsSettings) {
+                ((UserCredentialsSettings) target).refreshItems();
+            }
+            super.onDismiss(dialog);
+        }
     }
 
     /**
@@ -101,9 +142,9 @@
      * The credentials are stored in a {@link CredentialAdapter} attached to the main
      * {@link ListView} in the fragment.
      */
-    private class AliasLoader extends AsyncTask<Void, Void, ListAdapter> {
+    private class AliasLoader extends AsyncTask<Void, Void, SortedMap<String, Credential>> {
         @Override
-        protected ListAdapter doInBackground(Void... params) {
+        protected SortedMap<String, Credential> doInBackground(Void... params) {
             // Create a list of names for credential sets, ordered by name.
             SortedMap<String, Credential> credentials = new TreeMap<>();
             KeyStore keyStore = KeyStore.getInstance();
@@ -116,15 +157,14 @@
                     c.storedTypes.add(type);
                 }
             }
-
-            // Flatten to array so that the list can be presented via ArrayAdapter.
-            Credential[] results = credentials.values().toArray(new Credential[0]);
-            return new CredentialAdapter(getActivity(), R.layout.user_credential, results);
+            return credentials;
         }
 
         @Override
-        protected void onPostExecute(ListAdapter credentials) {
-            mListView.setAdapter(credentials);
+        protected void onPostExecute(SortedMap<String, Credential> credentials) {
+            // Convert the results to an array and present them using an ArrayAdapter.
+            mListView.setAdapter(new CredentialAdapter(getContext(), R.layout.user_credential,
+                    credentials.values().toArray(new Credential[0])));
         }
     }
 
@@ -154,8 +194,8 @@
         }
     }
 
-    private static class Credential {
-        private static enum Type {
+    static class Credential implements Parcelable {
+        static enum Type {
             CA_CERTIFICATE (Credentials.CA_CERTIFICATE),
             USER_CERTIFICATE (Credentials.USER_CERTIFICATE),
             USER_PRIVATE_KEY (Credentials.USER_PRIVATE_KEY),
@@ -183,10 +223,46 @@
          *   <li>{@link Credentials.USER_SECRET_KEY}</li>
          * </ul>
          */
-        final Set<Type> storedTypes = EnumSet.noneOf(Type.class);
+        final EnumSet<Type> storedTypes = EnumSet.noneOf(Type.class);
 
         Credential(final String alias) {
             this.alias = alias;
         }
+
+        Credential(Parcel in) {
+            this(in.readString());
+
+            long typeBits = in.readLong();
+            for (Type i : Type.values()) {
+                if ((typeBits & (1L << i.ordinal())) != 0L) {
+                    storedTypes.add(i);
+                }
+            }
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeString(alias);
+
+            long typeBits = 0;
+            for (Type i : storedTypes) {
+                typeBits |= 1L << i.ordinal();
+            }
+            out.writeLong(typeBits);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public static final Parcelable.Creator<Credential> CREATOR
+                = new Parcelable.Creator<Credential>() {
+            public Credential createFromParcel(Parcel in) {
+                return new Credential(in);
+            }
+
+            public Credential[] newArray(int size) {
+                return new Credential[size];
+            }
+        };
     }
 }
diff --git a/src/com/android/settings/accessibility/AccessibilitySettingsForSetupWizard.java b/src/com/android/settings/accessibility/AccessibilitySettingsForSetupWizard.java
index 7636fd9..6a984ac 100644
--- a/src/com/android/settings/accessibility/AccessibilitySettingsForSetupWizard.java
+++ b/src/com/android/settings/accessibility/AccessibilitySettingsForSetupWizard.java
@@ -16,15 +16,24 @@
 
 package com.android.settings.accessibility;
 
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.pm.ServiceInfo;
 import android.content.res.Resources;
 import android.os.Bundle;
 import android.provider.Settings;
 import android.support.v7.preference.Preference;
+import android.view.accessibility.AccessibilityManager;
+
 import com.android.internal.logging.MetricsLogger;
 import com.android.settings.DialogCreatable;
 import com.android.settings.R;
 import com.android.settings.SettingsPreferenceFragment;
 
+import java.util.List;
+
 /**
  * Activity with the accessibility settings specific to Setup Wizard.
  */
@@ -34,7 +43,6 @@
     // Preferences.
     private static final String DISPLAY_MAGNIFICATION_PREFERENCE =
             "screen_magnification_preference";
-    private static final String DISPLAY_DALTONIZER_PREFERENCE = "daltonizer_preference";
     private static final String TALKBACK_PREFERENCE = "talkback_preference";
     private static final String FONT_SIZE_PREFERENCE = "font_size_preference";
 
@@ -42,7 +50,6 @@
 
     // Preference controls.
     private Preference mDisplayMagnificationPreference;
-    private Preference mDisplayDaltonizerPreference;
     private Preference mFontSizePreference;
     private Preference mTalkbackPreference;
 
@@ -62,7 +69,6 @@
         addPreferencesFromResource(R.xml.accessibility_settings_for_setup_wizard);
 
         mDisplayMagnificationPreference = findPreference(DISPLAY_MAGNIFICATION_PREFERENCE);
-        mDisplayDaltonizerPreference = findPreference(DISPLAY_DALTONIZER_PREFERENCE);
         mFontSizePreference = findPreference(FONT_SIZE_PREFERENCE);
 
         mTalkbackPreference = findPreference(TALKBACK_PREFERENCE);
@@ -86,6 +92,43 @@
         return false;
     }
 
+    /**
+     * Returns a semicolon-delimited string containing a list of all the
+     * installed {@link AccessibilityService}s that provide at least one
+     * required feedback type.
+     *
+     * @param context The {@link android.app.Activity} context.
+     * @param requiredFeedbackTypes An integer mask containing the required
+     *            feedback types.
+     * @return A semicolon-delimited string containing a list of accessibility services.
+     */
+    private String getAccessibilityServicesFiltered(
+            Context context, int requiredFeedbackTypes) {
+        final AccessibilityManager manager = context.getSystemService(AccessibilityManager.class);
+        final List<AccessibilityServiceInfo> accessibilityServices = manager
+                .getInstalledAccessibilityServiceList();
+        final StringBuilder servicesToEnable = new StringBuilder();
+
+        for (AccessibilityServiceInfo accessibilityService : accessibilityServices) {
+            if ((accessibilityService.feedbackType & requiredFeedbackTypes) == 0) {
+                continue;
+            }
+
+            final ServiceInfo serviceInfo = accessibilityService.getResolveInfo().serviceInfo;
+            final ComponentName componentName = new ComponentName(serviceInfo.packageName,
+                    serviceInfo.name);
+
+            servicesToEnable.append(componentName.flattenToString());
+            servicesToEnable.append(':');
+        }
+
+        if (servicesToEnable.length() > 0) {
+            servicesToEnable.deleteCharAt(servicesToEnable.length() - 1);
+        }
+
+        return servicesToEnable.toString();
+    }
+
     @Override
     public boolean onPreferenceTreeClick(Preference preference) {
         if (mDisplayMagnificationPreference == preference) {
@@ -98,6 +141,32 @@
             extras.putBoolean(AccessibilitySettings.EXTRA_CHECKED,
                     Settings.Secure.getInt(getContentResolver(),
                     Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, 0) == 1);
+        } else if (mTalkbackPreference == preference) {
+            // Toggle Talkback. The tutorial will automatically start when Talkback is first
+            //  activated.
+            final ContentResolver resolver = getContentResolver();
+
+            final boolean enable =
+                    Settings.Secure.getInt(resolver, Settings.Secure.ACCESSIBILITY_ENABLED, 0) == 0;
+            final String servicesToEnable = getAccessibilityServicesFiltered(
+                    getActivity(), AccessibilityServiceInfo.FEEDBACK_SPOKEN);
+
+            // Enable all accessibility services with spoken feedback type.
+            Settings.Secure.putString(resolver, Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
+                    enable ? servicesToEnable : "");
+
+            // Allow the services we just enabled to toggle touch exploration.
+            Settings.Secure.putString(resolver,
+                    Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
+                    enable ? servicesToEnable : "");
+
+            // Enable touch exploration.
+            Settings.Secure.putInt(resolver, Settings.Secure.TOUCH_EXPLORATION_ENABLED,
+                    enable ? 1 : 0);
+
+            // Turn on accessibility mode last, since enabling accessibility with no
+            // services has no effect.
+            Settings.Secure.putInt(resolver, Settings.Secure.ACCESSIBILITY_ENABLED, enable ? 1 : 0);
         }
 
         return super.onPreferenceTreeClick(preference);
@@ -106,8 +175,6 @@
     private void updatePreferences() {
         updateFeatureSummary(Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED,
                 mDisplayMagnificationPreference);
-        updateFeatureSummary(Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED,
-                mDisplayDaltonizerPreference);
         updateFontSizeSummary(mFontSizePreference);
     }
 
diff --git a/src/com/android/settings/accessibility/AccessibilitySettingsForSetupWizardActivity.java b/src/com/android/settings/accessibility/AccessibilitySettingsForSetupWizardActivity.java
new file mode 100644
index 0000000..09961b7
--- /dev/null
+++ b/src/com/android/settings/accessibility/AccessibilitySettingsForSetupWizardActivity.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2015 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.accessibility;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuItem;
+
+import com.android.settings.R;
+import com.android.settings.SettingsActivity;
+
+public class AccessibilitySettingsForSetupWizardActivity extends SettingsActivity {
+
+      @Override
+      public boolean onCreateOptionsMenu(Menu menu) {
+          // Return true, so we get notified when items in the menu are clicked.
+          return true;
+      }
+
+      @Override
+      public boolean onOptionsItemSelected(MenuItem item) {
+          onBackPressed();
+          return true;
+      }
+
+      @Override
+      public void startPreferencePanel(String fragmentClass, Bundle args, int titleRes,
+              CharSequence titleText, Fragment resultTo, int resultRequestCode) {
+          startPreferenceFragment(Fragment.instantiate(this, fragmentClass, args), true);
+      }
+
+      @Override
+      public void openDrawer() {
+          // Do nothing.
+      }
+
+      @Override
+      public void closeDrawer() {
+          // Do nothing.
+      }
+}
diff --git a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java
index bee46c8..e1c4f7e 100644
--- a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java
@@ -99,7 +99,6 @@
     @Override
     public void onActivityCreated(Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
-        setHasOptionsMenu(true);
         installActionBarToggleSwitch();
     }
 
diff --git a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java
index 44355c6..45af2de 100644
--- a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java
@@ -16,6 +16,7 @@
 
 package com.android.settings.accessibility;
 
+import android.os.Bundle;
 import android.provider.Settings;
 
 import com.android.internal.logging.MetricsLogger;
@@ -24,10 +25,10 @@
 
 public class ToggleScreenMagnificationPreferenceFragment
         extends ToggleFeaturePreferenceFragment {
+
     @Override
     protected void onPreferenceToggled(String preferenceKey, boolean enabled) {
-        Settings.Secure.putInt(getContentResolver(),
-                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, enabled ? 1 : 0);
+        // Do nothing.
     }
 
     @Override
@@ -45,6 +46,30 @@
     }
 
     @Override
+    public void onResume() {
+        super.onResume();
+
+        // Temporarily enable Magnification on this screen if it's disabled.
+        if (Settings.Secure.getInt(getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, 0) == 0) {
+            setMagnificationEnabled(1);
+        }
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        if (!mToggleSwitch.isChecked()) {
+            setMagnificationEnabled(0);
+        }
+    }
+
+    private void setMagnificationEnabled(int enabled) {
+        Settings.Secure.putInt(getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, enabled);
+    }
+
+    @Override
     protected int getMetricsCategory() {
         return MetricsLogger.ACCESSIBILITY_TOGGLE_SCREEN_MAGNIFICATION;
     }
diff --git a/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragment.java b/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragment.java
new file mode 100644
index 0000000..2e4242a
--- /dev/null
+++ b/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragment.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2016 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.app.Activity;
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.os.Bundle;
+import android.support.v7.preference.PreferenceScreen;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodManager;
+
+import com.android.settings.R;
+import com.android.settings.InstrumentedFragment;
+import com.android.settings.SettingsPreferenceFragment;
+
+import java.text.Collator;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+public final class AvailableVirtualKeyboardFragment extends SettingsPreferenceFragment
+        implements InputMethodPreference.OnSavePreferenceListener {
+
+    private final ArrayList<InputMethodPreference> mInputMethodPreferenceList = new ArrayList<>();
+    private InputMethodSettingValuesWrapper mInputMethodSettingValues;
+    private InputMethodManager mImm;
+    private DevicePolicyManager mDpm;
+
+    @Override
+    public void onCreatePreferences(Bundle bundle, String s) {
+        Activity activity = getActivity();
+        PreferenceScreen screen = getPreferenceManager().createPreferenceScreen(activity);
+        screen.setTitle(activity.getString(R.string.available_virtual_keyboard_category));
+        setPreferenceScreen(screen);
+        mInputMethodSettingValues = InputMethodSettingValuesWrapper.getInstance(activity);
+        mImm = activity.getSystemService(InputMethodManager.class);
+        mDpm = activity.getSystemService(DevicePolicyManager.class);
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        // Refresh internal states in mInputMethodSettingValues to keep the latest
+        // "InputMethodInfo"s and "InputMethodSubtype"s
+        mInputMethodSettingValues.refreshAllInputMethodAndSubtypes();
+        updateInputMethodPreferenceViews();
+    }
+
+    @Override
+    public void onSaveInputMethodPreference(final InputMethodPreference pref) {
+        final boolean hasHardwareKeyboard = getResources().getConfiguration().keyboard
+                == Configuration.KEYBOARD_QWERTY;
+        InputMethodAndSubtypeUtil.saveInputMethodSubtypeList(this, getContentResolver(),
+                mImm.getInputMethodList(), hasHardwareKeyboard);
+        // Update input method settings and preference list.
+        mInputMethodSettingValues.refreshAllInputMethodAndSubtypes();
+        for (final InputMethodPreference p : mInputMethodPreferenceList) {
+            p.updatePreferenceViews();
+        }
+    }
+
+    @Override
+    protected int getMetricsCategory() {
+        return InstrumentedFragment.ENABLE_VIRTUAL_KEYBOARDS;
+    }
+
+    private void updateInputMethodPreferenceViews() {
+        mInputMethodSettingValues.refreshAllInputMethodAndSubtypes();
+        // Clear existing "InputMethodPreference"s
+        mInputMethodPreferenceList.clear();
+        List<String> permittedList = mDpm.getPermittedInputMethodsForCurrentUser();
+        final Context context = getPrefContext();
+        final List<InputMethodInfo> imis = mInputMethodSettingValues.getInputMethodList();
+        final int N = (imis == null ? 0 : imis.size());
+        for (int i = 0; i < N; ++i) {
+            final InputMethodInfo imi = imis.get(i);
+            final boolean isAllowedByOrganization = permittedList == null
+                    || permittedList.contains(imi.getPackageName());
+            final InputMethodPreference pref = new InputMethodPreference(
+                    context, imi, true, isAllowedByOrganization, this);
+            mInputMethodPreferenceList.add(pref);
+        }
+        final Collator collator = Collator.getInstance();
+        Collections.sort(mInputMethodPreferenceList, new Comparator<InputMethodPreference>() {
+            @Override
+            public int compare(InputMethodPreference lhs, InputMethodPreference rhs) {
+                return lhs.compareTo(rhs, collator);
+            }
+        });
+        getPreferenceScreen().removeAll();
+        for (int i = 0; i < N; ++i) {
+            final InputMethodPreference pref = mInputMethodPreferenceList.get(i);
+            pref.setOrder(i);
+            getPreferenceScreen().addPreference(pref);
+            InputMethodAndSubtypeUtil.removeUnnecessaryNonPersistentPreference(pref);
+            pref.updatePreferenceViews();
+        }
+    }
+}
diff --git a/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java b/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java
index 9022538..7564cc7 100644
--- a/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java
+++ b/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java
@@ -157,12 +157,16 @@
                 startingIntent.getAction());
         if (mShowsOnlyFullImeAndKeyboardList) {
             getPreferenceScreen().removeAll();
-            getPreferenceScreen().addPreference(mHardKeyboardCategory);
+            if (mHardKeyboardCategory != null) {
+                getPreferenceScreen().addPreference(mHardKeyboardCategory);
+            }
             if (SHOW_INPUT_METHOD_SWITCHER_SETTINGS) {
                 getPreferenceScreen().addPreference(mShowInputMethodSelectorPref);
             }
-            mKeyboardSettingsCategory.removeAll();
-            getPreferenceScreen().addPreference(mKeyboardSettingsCategory);
+            if (mKeyboardSettingsCategory != null) {
+                mKeyboardSettingsCategory.removeAll();
+                getPreferenceScreen().addPreference(mKeyboardSettingsCategory);
+            }
         }
 
         // Build hard keyboard and game controller preference categories.
@@ -376,6 +380,10 @@
     }
 
     private void updateInputMethodPreferenceViews() {
+        if (mKeyboardSettingsCategory == null) {
+            return;
+        }
+
         synchronized (mInputMethodPreferenceList) {
             // Clear existing "InputMethodPreference"s
             for (final InputMethodPreference pref : mInputMethodPreferenceList) {
@@ -510,6 +518,10 @@
     }
 
     private void updateHardKeyboards() {
+        if (mHardKeyboardCategory == null) {
+            return;
+        }
+
         mHardKeyboardPreferenceList.clear();
         final int[] devices = InputDevice.getDeviceIds();
         for (int i = 0; i < devices.length; i++) {
diff --git a/src/com/android/settings/inputmethod/KeyboardLayoutDialogFragment.java b/src/com/android/settings/inputmethod/KeyboardLayoutDialogFragment.java
index ad7a2b1..68ceeef 100644
--- a/src/com/android/settings/inputmethod/KeyboardLayoutDialogFragment.java
+++ b/src/com/android/settings/inputmethod/KeyboardLayoutDialogFragment.java
@@ -301,7 +301,7 @@
         }
     }
 
-    private static final class KeyboardLayoutLoader extends AsyncTaskLoader<Keyboards> {
+    static final class KeyboardLayoutLoader extends AsyncTaskLoader<Keyboards> {
         private final InputDeviceIdentifier mInputDeviceIdentifier;
 
         public KeyboardLayoutLoader(Context context, InputDeviceIdentifier inputDeviceIdentifier) {
diff --git a/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java b/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java
new file mode 100644
index 0000000..8f7d99e
--- /dev/null
+++ b/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java
@@ -0,0 +1,264 @@
+/*
+ * Copyright (C) 2016 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.app.Activity;
+import android.app.LoaderManager;
+import android.content.Intent;
+import android.content.Loader;
+import android.database.ContentObserver;
+import android.hardware.input.InputDeviceIdentifier;
+import android.hardware.input.InputManager;
+import android.hardware.input.KeyboardLayout;
+import android.os.Bundle;
+import android.os.Handler;
+import android.provider.Settings.Secure;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.Preference.OnPreferenceChangeListener;
+import android.support.v7.preference.PreferenceCategory;
+import android.support.v14.preference.SwitchPreference;
+import android.util.Pair;
+import android.view.InputDevice;
+import android.view.inputmethod.InputMethodInfo;
+import android.widget.Toast;
+
+import com.android.internal.inputmethod.InputMethodUtils;
+import com.android.internal.util.Preconditions;
+import com.android.settings.R;
+import com.android.settings.InstrumentedFragment;
+import com.android.settings.Settings;
+import com.android.settings.SettingsPreferenceFragment;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+
+public final class PhysicalKeyboardFragment extends SettingsPreferenceFragment
+        implements LoaderManager.LoaderCallbacks<KeyboardLayoutDialogFragment.Keyboards>,
+        InputManager.InputDeviceListener {
+
+    private static final int USER_SYSTEM = 0;
+    private static final String KEYBOARD_ASSISTANCE_CATEGORY = "keyboard_assistance_category";
+    private static final String SHOW_VIRTUAL_KEYBOARD_SWITCH = "show_virtual_keyboard_switch";
+    private static final String KEYBOARD_SHORTCUTS_HELPER = "keyboard_shortcuts_helper";
+
+    private final ArrayList<PreferenceCategory> mHardKeyboardPreferenceList = new ArrayList<>();
+    private final HashMap<Integer, Pair<InputDeviceIdentifier, PreferenceCategory>> mLoaderReference
+            = new HashMap<>();
+    private InputManager mIm;
+    private PreferenceCategory mKeyboardAssistanceCategory;
+    private SwitchPreference mShowVirtualKeyboardSwitch;
+    private InputMethodUtils.InputMethodSettings mSettings;
+
+    @Override
+    public void onCreatePreferences(Bundle bundle, String s) {
+        Activity activity = Preconditions.checkNotNull(getActivity());
+        addPreferencesFromResource(R.xml.physical_keyboard_settings);
+        mIm = Preconditions.checkNotNull(activity.getSystemService(InputManager.class));
+        mSettings = new InputMethodUtils.InputMethodSettings(
+                activity.getResources(),
+                getContentResolver(),
+                new HashMap<String, InputMethodInfo>(),
+                new ArrayList<InputMethodInfo>(),
+                USER_SYSTEM);
+        mKeyboardAssistanceCategory = Preconditions.checkNotNull(
+                (PreferenceCategory) findPreference(KEYBOARD_ASSISTANCE_CATEGORY));
+        mShowVirtualKeyboardSwitch = Preconditions.checkNotNull(
+                (SwitchPreference) mKeyboardAssistanceCategory.findPreference(
+                        SHOW_VIRTUAL_KEYBOARD_SWITCH));
+        findPreference(KEYBOARD_SHORTCUTS_HELPER).setOnPreferenceClickListener(
+                new Preference.OnPreferenceClickListener() {
+                    @Override
+                    public boolean onPreferenceClick(Preference preference) {
+                        toggleKeyboardShortcutsMenu();
+                        return true;
+                    }
+                });
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        updateHardKeyboards();
+        mIm.registerInputDeviceListener(this, null);
+        mShowVirtualKeyboardSwitch.setOnPreferenceChangeListener(
+                mShowVirtualKeyboardSwitchPreferenceChangeListener);
+        registerShowVirtualKeyboardSettingsObserver();
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        clearHardKeyboardsData();
+        mIm.unregisterInputDeviceListener(this);
+        mShowVirtualKeyboardSwitch.setOnPreferenceChangeListener(null);
+        unregisterShowVirtualKeyboardSettingsObserver();
+    }
+
+    @Override
+    public Loader<KeyboardLayoutDialogFragment.Keyboards> onCreateLoader(int id, Bundle args) {
+        InputDeviceIdentifier deviceId = mLoaderReference.get(id).first;
+        return new KeyboardLayoutDialogFragment.KeyboardLayoutLoader(
+                getActivity().getBaseContext(), deviceId);
+    }
+
+    @Override
+    public void onLoadFinished(
+            final Loader<KeyboardLayoutDialogFragment.Keyboards> loader,
+            KeyboardLayoutDialogFragment.Keyboards data) {
+        // TODO: Investigate why this is being called twice.
+        final InputDeviceIdentifier deviceId = mLoaderReference.get(loader.getId()).first;
+        final PreferenceCategory category = mLoaderReference.get(loader.getId()).second;
+        category.removeAll();
+        for (KeyboardLayout layout : data.keyboardLayouts) {
+            if (layout != null) {
+                Preference pref = new Preference(getPrefContext(), null);
+                pref.setTitle(layout.getLabel());
+                pref.setSummary(layout.getCollection());
+                pref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
+                    @Override
+                    public boolean onPreferenceClick(Preference preference) {
+                        showKeyboardLayoutScreen(deviceId);
+                        return true;
+                    }
+                });
+                category.addPreference(pref);
+            }
+        }
+    }
+
+    @Override
+    public void onLoaderReset(Loader<KeyboardLayoutDialogFragment.Keyboards> loader) {}
+
+    @Override
+    public void onInputDeviceAdded(int deviceId) {
+        updateHardKeyboards();
+    }
+
+    @Override
+    public void onInputDeviceRemoved(int deviceId) {
+        updateHardKeyboards();
+    }
+
+    @Override
+    public void onInputDeviceChanged(int deviceId) {
+        updateHardKeyboards();
+    }
+
+    @Override
+    protected int getMetricsCategory() {
+        return InstrumentedFragment.PHYSICAL_KEYBOARDS;
+    }
+
+    private void updateHardKeyboards() {
+        clearHardKeyboardsData();
+        final int[] devices = InputDevice.getDeviceIds();
+        for (int deviceIndex = 0; deviceIndex < devices.length; deviceIndex++) {
+            InputDevice device = InputDevice.getDevice(devices[deviceIndex]);
+            if (device != null
+                    && !device.isVirtual()
+                    && device.isFullKeyboard()) {
+                final InputDeviceIdentifier deviceId = device.getIdentifier();
+                final String keyboardLayoutDescriptor =
+                        mIm.getCurrentKeyboardLayoutForInputDevice(deviceId);
+                final KeyboardLayout keyboardLayout = keyboardLayoutDescriptor != null ?
+                        mIm.getKeyboardLayout(keyboardLayoutDescriptor) : null;
+
+                final PreferenceCategory category = new PreferenceCategory(getPrefContext(), null);
+                category.setTitle(device.getName());
+                if (keyboardLayout != null) {
+                    category.setSummary(keyboardLayout.toString());
+                } else {
+                    category.setSummary(R.string.keyboard_layout_default_label);
+                }
+                mLoaderReference.put(deviceIndex, new Pair(deviceId, category));
+                mHardKeyboardPreferenceList.add(category);
+            }
+        }
+
+        Collections.sort(mHardKeyboardPreferenceList);
+        final int count = mHardKeyboardPreferenceList.size();
+        for (int i = 0; i < count; i++) {
+            final PreferenceCategory category = mHardKeyboardPreferenceList.get(i);
+            category.setOrder(i);
+            getPreferenceScreen().addPreference(category);
+        }
+        mKeyboardAssistanceCategory.setOrder(count);
+        getPreferenceScreen().addPreference(mKeyboardAssistanceCategory);
+
+        for (int deviceIndex : mLoaderReference.keySet()) {
+            getLoaderManager().initLoader(deviceIndex, null, this);
+        }
+        updateShowVirtualKeyboardSwitch();
+    }
+
+    private void showKeyboardLayoutScreen(InputDeviceIdentifier inputDeviceIdentifier) {
+        final Intent intent = new Intent(Intent.ACTION_MAIN);
+        intent.setClass(getActivity(), Settings.KeyboardLayoutPickerActivity.class);
+        intent.putExtra(KeyboardLayoutPickerFragment.EXTRA_INPUT_DEVICE_IDENTIFIER,
+                inputDeviceIdentifier);
+        startActivity(intent);
+    }
+
+    private void clearHardKeyboardsData() {
+        getPreferenceScreen().removeAll();
+        for (int index = 0; index < mLoaderReference.size(); index++) {
+            getLoaderManager().destroyLoader(index);
+        }
+        mLoaderReference.clear();
+        mHardKeyboardPreferenceList.clear();
+    }
+
+    private void registerShowVirtualKeyboardSettingsObserver() {
+        unregisterShowVirtualKeyboardSettingsObserver();
+        getActivity().getContentResolver().registerContentObserver(
+                Secure.getUriFor(Secure.SHOW_IME_WITH_HARD_KEYBOARD),
+                false,
+                mContentObserver,
+                USER_SYSTEM);
+        updateShowVirtualKeyboardSwitch();
+    }
+
+    private void unregisterShowVirtualKeyboardSettingsObserver() {
+        getActivity().getContentResolver().unregisterContentObserver(mContentObserver);
+    }
+
+    private void updateShowVirtualKeyboardSwitch() {
+        mShowVirtualKeyboardSwitch.setChecked(mSettings.isShowImeWithHardKeyboardEnabled());
+    }
+
+    private void toggleKeyboardShortcutsMenu() {
+        // TODO: Implement.
+        Toast.makeText(getActivity(), "toggleKeyboardShortcutsMenu", Toast.LENGTH_SHORT).show();
+    }
+
+    private final OnPreferenceChangeListener mShowVirtualKeyboardSwitchPreferenceChangeListener =
+            new OnPreferenceChangeListener() {
+                @Override
+                public boolean onPreferenceChange(Preference preference, Object newValue) {
+                    mSettings.setShowImeWithHardKeyboard((Boolean) newValue);
+                    return false;
+                }
+            };
+
+    private final ContentObserver mContentObserver = new ContentObserver(new Handler(true)) {
+        @Override
+        public void onChange(boolean selfChange) {
+            updateShowVirtualKeyboardSwitch();
+        }
+    };
+}
diff --git a/src/com/android/settings/inputmethod/VirtualKeyboardFragment.java b/src/com/android/settings/inputmethod/VirtualKeyboardFragment.java
new file mode 100644
index 0000000..541c686
--- /dev/null
+++ b/src/com/android/settings/inputmethod/VirtualKeyboardFragment.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2016 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.app.Activity;
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.os.Bundle;
+import android.support.v7.preference.Preference;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodManager;
+
+import com.android.internal.util.Preconditions;
+import com.android.settings.R;
+import com.android.settings.InstrumentedFragment;
+import com.android.settings.SettingsPreferenceFragment;
+
+import java.text.Collator;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+public final class VirtualKeyboardFragment extends SettingsPreferenceFragment {
+
+    private static final String ADD_VIRTUAL_KEYBOARD_SCREEN = "add_virtual_keyboard_screen";
+
+    private final ArrayList<InputMethodPreference> mInputMethodPreferenceList = new ArrayList<>();
+    private InputMethodManager mImm;
+    private DevicePolicyManager mDpm;
+    private Preference mAddVirtualKeyboardScreen;
+
+    @Override
+    public void onCreatePreferences(Bundle bundle, String s) {
+        Activity activity = Preconditions.checkNotNull(getActivity());
+        addPreferencesFromResource(R.xml.virtual_keyboard_settings);
+        mImm = Preconditions.checkNotNull(activity.getSystemService(InputMethodManager.class));
+        mDpm = Preconditions.checkNotNull(activity.getSystemService(DevicePolicyManager.class));
+        mAddVirtualKeyboardScreen = Preconditions.checkNotNull(
+                findPreference(ADD_VIRTUAL_KEYBOARD_SCREEN));
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        // Refresh internal states in mInputMethodSettingValues to keep the latest
+        // "InputMethodInfo"s and "InputMethodSubtype"s
+        updateInputMethodPreferenceViews();
+    }
+
+    @Override
+    protected int getMetricsCategory() {
+        return InstrumentedFragment.VIRTUAL_KEYBOARDS;
+    }
+
+    private void updateInputMethodPreferenceViews() {
+        // Clear existing "InputMethodPreference"s
+        mInputMethodPreferenceList.clear();
+        List<String> permittedList = mDpm.getPermittedInputMethodsForCurrentUser();
+        final Context context = getPrefContext();
+        final List<InputMethodInfo> imis = mImm.getEnabledInputMethodList();
+        final int N = (imis == null ? 0 : imis.size());
+        for (int i = 0; i < N; ++i) {
+            final InputMethodInfo imi = imis.get(i);
+            final boolean isAllowedByOrganization = permittedList == null
+                    || permittedList.contains(imi.getPackageName());
+            final InputMethodPreference pref = new InputMethodPreference(
+                    context,
+                    imi,
+                    false,  /* isImeEnabler */
+                    isAllowedByOrganization,
+                    null  /* this can be null since isImeEnabler is false */);
+            mInputMethodPreferenceList.add(pref);
+        }
+        final Collator collator = Collator.getInstance();
+        Collections.sort(mInputMethodPreferenceList, new Comparator<InputMethodPreference>() {
+            @Override
+            public int compare(InputMethodPreference lhs, InputMethodPreference rhs) {
+                return lhs.compareTo(rhs, collator);
+            }
+        });
+        getPreferenceScreen().removeAll();
+        for (int i = 0; i < N; ++i) {
+            final InputMethodPreference pref = mInputMethodPreferenceList.get(i);
+            pref.setOrder(i);
+            getPreferenceScreen().addPreference(pref);
+            InputMethodAndSubtypeUtil.removeUnnecessaryNonPersistentPreference(pref);
+            pref.updatePreferenceViews();
+        }
+        mAddVirtualKeyboardScreen.setOrder(N);
+        getPreferenceScreen().addPreference(mAddVirtualKeyboardScreen);
+    }
+}
diff --git a/src/com/android/settings/users/EditUserPhotoController.java b/src/com/android/settings/users/EditUserPhotoController.java
index 1ca6928..0d327a0 100644
--- a/src/com/android/settings/users/EditUserPhotoController.java
+++ b/src/com/android/settings/users/EditUserPhotoController.java
@@ -32,6 +32,7 @@
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.AsyncTask;
+import android.os.UserManager;
 import android.provider.ContactsContract.DisplayPhoto;
 import android.provider.MediaStore;
 import android.support.v4.content.FileProvider;
@@ -95,6 +96,10 @@
                 showUpdatePhotoPopup();
             }
         });
+        final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+        if (um.hasUserRestriction(UserManager.DISALLOW_SET_USER_ICON)) {
+            mImageView.setEnabled(false);
+        }
         mNewUserPhotoBitmap = bitmap;
         mNewUserPhotoDrawable = drawable;
     }
diff --git a/tests/Android.mk b/tests/Android.mk
index 204b8c3..fd297e3 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -1,19 +1,5 @@
-LOCAL_PATH:= $(call my-dir)
+LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-LOCAL_CERTIFICATE := platform
-
-LOCAL_JAVA_LIBRARIES := android.test.runner bouncycastle
-
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-test mockito-target
-
-# Include all test java files.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := SettingsTests
-
-LOCAL_INSTRUMENTATION_FOR := Settings
-
-include $(BUILD_PACKAGE)
+# Include all makefiles in subdirectories
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/README b/tests/README
deleted file mode 100644
index 9af7c8a..0000000
--- a/tests/README
+++ /dev/null
@@ -1,17 +0,0 @@
-To build the tests you can use the following command at the root of your android source tree
-$ make SettingsTests
-
-The test apk then needs to be installed onto your test device via for example
-$ adb install -r out/target/product/shamu/data/app/SettingsTests/SettingsTests.apk
-
-To run all tests:
-$ adb shell am instrument -w com.android.settings.tests/android.support.test.runner.AndroidJUnitRunner
-
-To run all tests in a specific class:
-$ adb shell am instrument -w -e class com.android.managedprovisioning.<class> com.android.managedprovisioning.tests/android.test.InstrumentationTestRunner
-
-To run a specific test:
-$ adb shell am instrument -w -e class com.android.settings.<class> com.android.settings.tests/android.support.test.runner.AndroidJUnitRunner
-
-More general information can be found at
-http://developer.android.com/reference/android/support/test/runner/AndroidJUnitRunner.html
diff --git a/tests/app/Android.mk b/tests/app/Android.mk
new file mode 100644
index 0000000..bb31539
--- /dev/null
+++ b/tests/app/Android.mk
@@ -0,0 +1,17 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# We only want this apk build for tests.
+LOCAL_MODULE_TAGS := tests
+LOCAL_CERTIFICATE := platform
+
+LOCAL_JAVA_LIBRARIES := android.test.runner bouncycastle
+
+# Include all test java files.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := SettingsTests
+
+LOCAL_INSTRUMENTATION_FOR := Settings
+
+include $(BUILD_PACKAGE)
diff --git a/tests/AndroidManifest.xml b/tests/app/AndroidManifest.xml
similarity index 90%
rename from tests/AndroidManifest.xml
rename to tests/app/AndroidManifest.xml
index fe9520e..2ef96cf 100644
--- a/tests/AndroidManifest.xml
+++ b/tests/app/AndroidManifest.xml
@@ -51,9 +51,14 @@
         </activity>
     </application>
 
-    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+    <instrumentation android:name="android.test.InstrumentationTestRunner"
         android:targetPackage="com.android.settings"
-        android:label="Settings Test Cases">
+        android:label="Settings App Tests">
+    </instrumentation>
+
+    <instrumentation android:name="SettingsLaunchPerformance"
+        android:targetPackage="com.android.settings"
+        android:label="Settings Launch Performance">
     </instrumentation>
 
 </manifest>
diff --git a/tests/res/drawable-hdpi/ic_settings_applications.png b/tests/app/res/drawable-hdpi/ic_settings_applications.png
similarity index 100%
rename from tests/res/drawable-hdpi/ic_settings_applications.png
rename to tests/app/res/drawable-hdpi/ic_settings_applications.png
Binary files differ
diff --git a/tests/res/drawable-mdpi/ic_settings_applications.png b/tests/app/res/drawable-mdpi/ic_settings_applications.png
similarity index 100%
rename from tests/res/drawable-mdpi/ic_settings_applications.png
rename to tests/app/res/drawable-mdpi/ic_settings_applications.png
Binary files differ
diff --git a/tests/res/drawable-xhdpi/ic_settings_applications.png b/tests/app/res/drawable-xhdpi/ic_settings_applications.png
similarity index 100%
rename from tests/res/drawable-xhdpi/ic_settings_applications.png
rename to tests/app/res/drawable-xhdpi/ic_settings_applications.png
Binary files differ
diff --git a/tests/res/layout/bluetooth_request_permission_test.xml b/tests/app/res/layout/bluetooth_request_permission_test.xml
similarity index 100%
rename from tests/res/layout/bluetooth_request_permission_test.xml
rename to tests/app/res/layout/bluetooth_request_permission_test.xml
diff --git a/tests/res/layout/manufacturer_main.xml b/tests/app/res/layout/manufacturer_main.xml
similarity index 100%
rename from tests/res/layout/manufacturer_main.xml
rename to tests/app/res/layout/manufacturer_main.xml
diff --git a/tests/res/layout/operator_main.xml b/tests/app/res/layout/operator_main.xml
similarity index 100%
rename from tests/res/layout/operator_main.xml
rename to tests/app/res/layout/operator_main.xml
diff --git a/tests/res/values-af/strings.xml b/tests/app/res/values-af/strings.xml
similarity index 100%
rename from tests/res/values-af/strings.xml
rename to tests/app/res/values-af/strings.xml
diff --git a/tests/res/values-am/strings.xml b/tests/app/res/values-am/strings.xml
similarity index 100%
rename from tests/res/values-am/strings.xml
rename to tests/app/res/values-am/strings.xml
diff --git a/tests/res/values-ar/strings.xml b/tests/app/res/values-ar/strings.xml
similarity index 100%
rename from tests/res/values-ar/strings.xml
rename to tests/app/res/values-ar/strings.xml
diff --git a/tests/res/values-az-rAZ/strings.xml b/tests/app/res/values-az-rAZ/strings.xml
similarity index 100%
rename from tests/res/values-az-rAZ/strings.xml
rename to tests/app/res/values-az-rAZ/strings.xml
diff --git a/tests/res/values-b+sr+Latn/strings.xml b/tests/app/res/values-b+sr+Latn/strings.xml
similarity index 100%
rename from tests/res/values-b+sr+Latn/strings.xml
rename to tests/app/res/values-b+sr+Latn/strings.xml
diff --git a/tests/res/values-bg/strings.xml b/tests/app/res/values-bg/strings.xml
similarity index 100%
rename from tests/res/values-bg/strings.xml
rename to tests/app/res/values-bg/strings.xml
diff --git a/tests/res/values-bn-rBD/strings.xml b/tests/app/res/values-bn-rBD/strings.xml
similarity index 100%
rename from tests/res/values-bn-rBD/strings.xml
rename to tests/app/res/values-bn-rBD/strings.xml
diff --git a/tests/res/values-ca/strings.xml b/tests/app/res/values-ca/strings.xml
similarity index 100%
rename from tests/res/values-ca/strings.xml
rename to tests/app/res/values-ca/strings.xml
diff --git a/tests/res/values-cs/strings.xml b/tests/app/res/values-cs/strings.xml
similarity index 100%
rename from tests/res/values-cs/strings.xml
rename to tests/app/res/values-cs/strings.xml
diff --git a/tests/res/values-da/strings.xml b/tests/app/res/values-da/strings.xml
similarity index 100%
rename from tests/res/values-da/strings.xml
rename to tests/app/res/values-da/strings.xml
diff --git a/tests/res/values-de/strings.xml b/tests/app/res/values-de/strings.xml
similarity index 100%
rename from tests/res/values-de/strings.xml
rename to tests/app/res/values-de/strings.xml
diff --git a/tests/res/values-el/strings.xml b/tests/app/res/values-el/strings.xml
similarity index 100%
rename from tests/res/values-el/strings.xml
rename to tests/app/res/values-el/strings.xml
diff --git a/tests/res/values-en-rAU/strings.xml b/tests/app/res/values-en-rAU/strings.xml
similarity index 100%
rename from tests/res/values-en-rAU/strings.xml
rename to tests/app/res/values-en-rAU/strings.xml
diff --git a/tests/res/values-en-rGB/strings.xml b/tests/app/res/values-en-rGB/strings.xml
similarity index 100%
rename from tests/res/values-en-rGB/strings.xml
rename to tests/app/res/values-en-rGB/strings.xml
diff --git a/tests/res/values-en-rIN/strings.xml b/tests/app/res/values-en-rIN/strings.xml
similarity index 100%
rename from tests/res/values-en-rIN/strings.xml
rename to tests/app/res/values-en-rIN/strings.xml
diff --git a/tests/res/values-es-rUS/strings.xml b/tests/app/res/values-es-rUS/strings.xml
similarity index 100%
rename from tests/res/values-es-rUS/strings.xml
rename to tests/app/res/values-es-rUS/strings.xml
diff --git a/tests/res/values-es/strings.xml b/tests/app/res/values-es/strings.xml
similarity index 100%
rename from tests/res/values-es/strings.xml
rename to tests/app/res/values-es/strings.xml
diff --git a/tests/res/values-et-rEE/strings.xml b/tests/app/res/values-et-rEE/strings.xml
similarity index 100%
rename from tests/res/values-et-rEE/strings.xml
rename to tests/app/res/values-et-rEE/strings.xml
diff --git a/tests/res/values-eu-rES/strings.xml b/tests/app/res/values-eu-rES/strings.xml
similarity index 100%
rename from tests/res/values-eu-rES/strings.xml
rename to tests/app/res/values-eu-rES/strings.xml
diff --git a/tests/res/values-fa/strings.xml b/tests/app/res/values-fa/strings.xml
similarity index 100%
rename from tests/res/values-fa/strings.xml
rename to tests/app/res/values-fa/strings.xml
diff --git a/tests/res/values-fi/strings.xml b/tests/app/res/values-fi/strings.xml
similarity index 100%
rename from tests/res/values-fi/strings.xml
rename to tests/app/res/values-fi/strings.xml
diff --git a/tests/res/values-fr-rCA/strings.xml b/tests/app/res/values-fr-rCA/strings.xml
similarity index 100%
rename from tests/res/values-fr-rCA/strings.xml
rename to tests/app/res/values-fr-rCA/strings.xml
diff --git a/tests/res/values-fr/strings.xml b/tests/app/res/values-fr/strings.xml
similarity index 100%
rename from tests/res/values-fr/strings.xml
rename to tests/app/res/values-fr/strings.xml
diff --git a/tests/res/values-gl-rES/strings.xml b/tests/app/res/values-gl-rES/strings.xml
similarity index 100%
rename from tests/res/values-gl-rES/strings.xml
rename to tests/app/res/values-gl-rES/strings.xml
diff --git a/tests/res/values-gu-rIN/strings.xml b/tests/app/res/values-gu-rIN/strings.xml
similarity index 100%
rename from tests/res/values-gu-rIN/strings.xml
rename to tests/app/res/values-gu-rIN/strings.xml
diff --git a/tests/res/values-hi/strings.xml b/tests/app/res/values-hi/strings.xml
similarity index 100%
rename from tests/res/values-hi/strings.xml
rename to tests/app/res/values-hi/strings.xml
diff --git a/tests/res/values-hr/strings.xml b/tests/app/res/values-hr/strings.xml
similarity index 100%
rename from tests/res/values-hr/strings.xml
rename to tests/app/res/values-hr/strings.xml
diff --git a/tests/res/values-hu/strings.xml b/tests/app/res/values-hu/strings.xml
similarity index 100%
rename from tests/res/values-hu/strings.xml
rename to tests/app/res/values-hu/strings.xml
diff --git a/tests/res/values-hy-rAM/strings.xml b/tests/app/res/values-hy-rAM/strings.xml
similarity index 100%
rename from tests/res/values-hy-rAM/strings.xml
rename to tests/app/res/values-hy-rAM/strings.xml
diff --git a/tests/res/values-in/strings.xml b/tests/app/res/values-in/strings.xml
similarity index 100%
rename from tests/res/values-in/strings.xml
rename to tests/app/res/values-in/strings.xml
diff --git a/tests/res/values-is-rIS/strings.xml b/tests/app/res/values-is-rIS/strings.xml
similarity index 100%
rename from tests/res/values-is-rIS/strings.xml
rename to tests/app/res/values-is-rIS/strings.xml
diff --git a/tests/res/values-it/strings.xml b/tests/app/res/values-it/strings.xml
similarity index 100%
rename from tests/res/values-it/strings.xml
rename to tests/app/res/values-it/strings.xml
diff --git a/tests/res/values-iw/strings.xml b/tests/app/res/values-iw/strings.xml
similarity index 100%
rename from tests/res/values-iw/strings.xml
rename to tests/app/res/values-iw/strings.xml
diff --git a/tests/res/values-ja/strings.xml b/tests/app/res/values-ja/strings.xml
similarity index 100%
rename from tests/res/values-ja/strings.xml
rename to tests/app/res/values-ja/strings.xml
diff --git a/tests/res/values-ka-rGE/strings.xml b/tests/app/res/values-ka-rGE/strings.xml
similarity index 100%
rename from tests/res/values-ka-rGE/strings.xml
rename to tests/app/res/values-ka-rGE/strings.xml
diff --git a/tests/res/values-kk-rKZ/strings.xml b/tests/app/res/values-kk-rKZ/strings.xml
similarity index 100%
rename from tests/res/values-kk-rKZ/strings.xml
rename to tests/app/res/values-kk-rKZ/strings.xml
diff --git a/tests/res/values-km-rKH/strings.xml b/tests/app/res/values-km-rKH/strings.xml
similarity index 100%
rename from tests/res/values-km-rKH/strings.xml
rename to tests/app/res/values-km-rKH/strings.xml
diff --git a/tests/res/values-kn-rIN/strings.xml b/tests/app/res/values-kn-rIN/strings.xml
similarity index 100%
rename from tests/res/values-kn-rIN/strings.xml
rename to tests/app/res/values-kn-rIN/strings.xml
diff --git a/tests/res/values-ko/strings.xml b/tests/app/res/values-ko/strings.xml
similarity index 100%
rename from tests/res/values-ko/strings.xml
rename to tests/app/res/values-ko/strings.xml
diff --git a/tests/res/values-lo-rLA/strings.xml b/tests/app/res/values-lo-rLA/strings.xml
similarity index 100%
rename from tests/res/values-lo-rLA/strings.xml
rename to tests/app/res/values-lo-rLA/strings.xml
diff --git a/tests/res/values-lt/strings.xml b/tests/app/res/values-lt/strings.xml
similarity index 100%
rename from tests/res/values-lt/strings.xml
rename to tests/app/res/values-lt/strings.xml
diff --git a/tests/res/values-lv/strings.xml b/tests/app/res/values-lv/strings.xml
similarity index 100%
rename from tests/res/values-lv/strings.xml
rename to tests/app/res/values-lv/strings.xml
diff --git a/tests/res/values-mk-rMK/strings.xml b/tests/app/res/values-mk-rMK/strings.xml
similarity index 100%
rename from tests/res/values-mk-rMK/strings.xml
rename to tests/app/res/values-mk-rMK/strings.xml
diff --git a/tests/res/values-ml-rIN/strings.xml b/tests/app/res/values-ml-rIN/strings.xml
similarity index 100%
rename from tests/res/values-ml-rIN/strings.xml
rename to tests/app/res/values-ml-rIN/strings.xml
diff --git a/tests/res/values-mn-rMN/strings.xml b/tests/app/res/values-mn-rMN/strings.xml
similarity index 100%
rename from tests/res/values-mn-rMN/strings.xml
rename to tests/app/res/values-mn-rMN/strings.xml
diff --git a/tests/res/values-mr-rIN/strings.xml b/tests/app/res/values-mr-rIN/strings.xml
similarity index 100%
rename from tests/res/values-mr-rIN/strings.xml
rename to tests/app/res/values-mr-rIN/strings.xml
diff --git a/tests/res/values-ms-rMY/strings.xml b/tests/app/res/values-ms-rMY/strings.xml
similarity index 100%
rename from tests/res/values-ms-rMY/strings.xml
rename to tests/app/res/values-ms-rMY/strings.xml
diff --git a/tests/res/values-my-rMM/strings.xml b/tests/app/res/values-my-rMM/strings.xml
similarity index 100%
rename from tests/res/values-my-rMM/strings.xml
rename to tests/app/res/values-my-rMM/strings.xml
diff --git a/tests/res/values-nb/strings.xml b/tests/app/res/values-nb/strings.xml
similarity index 100%
rename from tests/res/values-nb/strings.xml
rename to tests/app/res/values-nb/strings.xml
diff --git a/tests/res/values-ne-rNP/strings.xml b/tests/app/res/values-ne-rNP/strings.xml
similarity index 100%
rename from tests/res/values-ne-rNP/strings.xml
rename to tests/app/res/values-ne-rNP/strings.xml
diff --git a/tests/res/values-nl/strings.xml b/tests/app/res/values-nl/strings.xml
similarity index 100%
rename from tests/res/values-nl/strings.xml
rename to tests/app/res/values-nl/strings.xml
diff --git a/tests/res/values-pa-rIN/strings.xml b/tests/app/res/values-pa-rIN/strings.xml
similarity index 100%
rename from tests/res/values-pa-rIN/strings.xml
rename to tests/app/res/values-pa-rIN/strings.xml
diff --git a/tests/res/values-pl/strings.xml b/tests/app/res/values-pl/strings.xml
similarity index 100%
rename from tests/res/values-pl/strings.xml
rename to tests/app/res/values-pl/strings.xml
diff --git a/tests/res/values-pt-rBR/strings.xml b/tests/app/res/values-pt-rBR/strings.xml
similarity index 100%
rename from tests/res/values-pt-rBR/strings.xml
rename to tests/app/res/values-pt-rBR/strings.xml
diff --git a/tests/res/values-pt-rPT/strings.xml b/tests/app/res/values-pt-rPT/strings.xml
similarity index 100%
rename from tests/res/values-pt-rPT/strings.xml
rename to tests/app/res/values-pt-rPT/strings.xml
diff --git a/tests/res/values-pt/strings.xml b/tests/app/res/values-pt/strings.xml
similarity index 100%
rename from tests/res/values-pt/strings.xml
rename to tests/app/res/values-pt/strings.xml
diff --git a/tests/res/values-ro/strings.xml b/tests/app/res/values-ro/strings.xml
similarity index 100%
rename from tests/res/values-ro/strings.xml
rename to tests/app/res/values-ro/strings.xml
diff --git a/tests/res/values-ru/strings.xml b/tests/app/res/values-ru/strings.xml
similarity index 100%
rename from tests/res/values-ru/strings.xml
rename to tests/app/res/values-ru/strings.xml
diff --git a/tests/res/values-si-rLK/strings.xml b/tests/app/res/values-si-rLK/strings.xml
similarity index 100%
rename from tests/res/values-si-rLK/strings.xml
rename to tests/app/res/values-si-rLK/strings.xml
diff --git a/tests/res/values-sk/strings.xml b/tests/app/res/values-sk/strings.xml
similarity index 100%
rename from tests/res/values-sk/strings.xml
rename to tests/app/res/values-sk/strings.xml
diff --git a/tests/res/values-sl/strings.xml b/tests/app/res/values-sl/strings.xml
similarity index 100%
rename from tests/res/values-sl/strings.xml
rename to tests/app/res/values-sl/strings.xml
diff --git a/tests/res/values-sq-rAL/strings.xml b/tests/app/res/values-sq-rAL/strings.xml
similarity index 100%
rename from tests/res/values-sq-rAL/strings.xml
rename to tests/app/res/values-sq-rAL/strings.xml
diff --git a/tests/res/values-sr/strings.xml b/tests/app/res/values-sr/strings.xml
similarity index 100%
rename from tests/res/values-sr/strings.xml
rename to tests/app/res/values-sr/strings.xml
diff --git a/tests/res/values-sv/strings.xml b/tests/app/res/values-sv/strings.xml
similarity index 100%
rename from tests/res/values-sv/strings.xml
rename to tests/app/res/values-sv/strings.xml
diff --git a/tests/res/values-sw/strings.xml b/tests/app/res/values-sw/strings.xml
similarity index 100%
rename from tests/res/values-sw/strings.xml
rename to tests/app/res/values-sw/strings.xml
diff --git a/tests/res/values-ta-rIN/strings.xml b/tests/app/res/values-ta-rIN/strings.xml
similarity index 100%
rename from tests/res/values-ta-rIN/strings.xml
rename to tests/app/res/values-ta-rIN/strings.xml
diff --git a/tests/res/values-te-rIN/strings.xml b/tests/app/res/values-te-rIN/strings.xml
similarity index 100%
rename from tests/res/values-te-rIN/strings.xml
rename to tests/app/res/values-te-rIN/strings.xml
diff --git a/tests/res/values-th/strings.xml b/tests/app/res/values-th/strings.xml
similarity index 100%
rename from tests/res/values-th/strings.xml
rename to tests/app/res/values-th/strings.xml
diff --git a/tests/res/values-tl/strings.xml b/tests/app/res/values-tl/strings.xml
similarity index 100%
rename from tests/res/values-tl/strings.xml
rename to tests/app/res/values-tl/strings.xml
diff --git a/tests/res/values-tr/strings.xml b/tests/app/res/values-tr/strings.xml
similarity index 100%
rename from tests/res/values-tr/strings.xml
rename to tests/app/res/values-tr/strings.xml
diff --git a/tests/res/values-uk/strings.xml b/tests/app/res/values-uk/strings.xml
similarity index 100%
rename from tests/res/values-uk/strings.xml
rename to tests/app/res/values-uk/strings.xml
diff --git a/tests/res/values-ur-rPK/strings.xml b/tests/app/res/values-ur-rPK/strings.xml
similarity index 100%
rename from tests/res/values-ur-rPK/strings.xml
rename to tests/app/res/values-ur-rPK/strings.xml
diff --git a/tests/res/values-uz-rUZ/strings.xml b/tests/app/res/values-uz-rUZ/strings.xml
similarity index 100%
rename from tests/res/values-uz-rUZ/strings.xml
rename to tests/app/res/values-uz-rUZ/strings.xml
diff --git a/tests/res/values-vi/strings.xml b/tests/app/res/values-vi/strings.xml
similarity index 100%
rename from tests/res/values-vi/strings.xml
rename to tests/app/res/values-vi/strings.xml
diff --git a/tests/res/values-zh-rCN/strings.xml b/tests/app/res/values-zh-rCN/strings.xml
similarity index 100%
rename from tests/res/values-zh-rCN/strings.xml
rename to tests/app/res/values-zh-rCN/strings.xml
diff --git a/tests/res/values-zh-rHK/strings.xml b/tests/app/res/values-zh-rHK/strings.xml
similarity index 100%
rename from tests/res/values-zh-rHK/strings.xml
rename to tests/app/res/values-zh-rHK/strings.xml
diff --git a/tests/res/values-zh-rTW/strings.xml b/tests/app/res/values-zh-rTW/strings.xml
similarity index 100%
rename from tests/res/values-zh-rTW/strings.xml
rename to tests/app/res/values-zh-rTW/strings.xml
diff --git a/tests/res/values-zu/strings.xml b/tests/app/res/values-zu/strings.xml
similarity index 100%
rename from tests/res/values-zu/strings.xml
rename to tests/app/res/values-zu/strings.xml
diff --git a/tests/res/values/strings.xml b/tests/app/res/values/strings.xml
similarity index 100%
rename from tests/res/values/strings.xml
rename to tests/app/res/values/strings.xml
diff --git a/tests/src/com/android/settings/SettingsHookTests.java b/tests/app/src/com/android/settings/SettingsHookTests.java
similarity index 100%
rename from tests/src/com/android/settings/SettingsHookTests.java
rename to tests/app/src/com/android/settings/SettingsHookTests.java
diff --git a/tests/src/com/android/settings/tests/BluetoothRequestPermissionTest.java b/tests/app/src/com/android/settings/tests/BluetoothRequestPermissionTest.java
similarity index 100%
rename from tests/src/com/android/settings/tests/BluetoothRequestPermissionTest.java
rename to tests/app/src/com/android/settings/tests/BluetoothRequestPermissionTest.java
diff --git a/tests/src/com/android/settings/tests/Manufacturer.java b/tests/app/src/com/android/settings/tests/Manufacturer.java
similarity index 100%
rename from tests/src/com/android/settings/tests/Manufacturer.java
rename to tests/app/src/com/android/settings/tests/Manufacturer.java
diff --git a/tests/src/com/android/settings/tests/Operator.java b/tests/app/src/com/android/settings/tests/Operator.java
similarity index 100%
rename from tests/src/com/android/settings/tests/Operator.java
rename to tests/app/src/com/android/settings/tests/Operator.java
diff --git a/tests/src/com/android/settings/tests/SettingsLaunchPerformance.java b/tests/app/src/com/android/settings/tests/SettingsLaunchPerformance.java
similarity index 100%
rename from tests/src/com/android/settings/tests/SettingsLaunchPerformance.java
rename to tests/app/src/com/android/settings/tests/SettingsLaunchPerformance.java
diff --git a/tests/src/com/android/settings/vpn2/CertInstallerHelper.java b/tests/app/src/com/android/settings/vpn2/CertInstallerHelper.java
similarity index 100%
rename from tests/src/com/android/settings/vpn2/CertInstallerHelper.java
rename to tests/app/src/com/android/settings/vpn2/CertInstallerHelper.java
diff --git a/tests/src/com/android/settings/vpn2/VpnInfo.java b/tests/app/src/com/android/settings/vpn2/VpnInfo.java
similarity index 100%
rename from tests/src/com/android/settings/vpn2/VpnInfo.java
rename to tests/app/src/com/android/settings/vpn2/VpnInfo.java
diff --git a/tests/src/com/android/settings/vpn2/VpnProfileParser.java b/tests/app/src/com/android/settings/vpn2/VpnProfileParser.java
similarity index 100%
rename from tests/src/com/android/settings/vpn2/VpnProfileParser.java
rename to tests/app/src/com/android/settings/vpn2/VpnProfileParser.java
diff --git a/tests/src/com/android/settings/vpn2/VpnTests.java b/tests/app/src/com/android/settings/vpn2/VpnTests.java
similarity index 100%
rename from tests/src/com/android/settings/vpn2/VpnTests.java
rename to tests/app/src/com/android/settings/vpn2/VpnTests.java
diff --git a/tests/src/com/android/settings/UserCredentialsTests.java b/tests/src/com/android/settings/UserCredentialsTests.java
new file mode 100644
index 0000000..da1e58b
--- /dev/null
+++ b/tests/src/com/android/settings/UserCredentialsTests.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2016 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.os.Parcel;
+import android.test.InstrumentationTestCase;
+import android.test.InstrumentationTestRunner;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import static com.android.settings.UserCredentialsSettings.Credential;
+
+/**
+ * User credentials settings fragment tests
+ *
+ * To run the test, use command:
+ * adb shell am instrument -e class com.android.settings.security.UserCredentialsTests
+ * -w com.android.settings.tests/android.test.InstrumentationTestRunner
+ *
+ */
+public class UserCredentialsTests extends InstrumentationTestCase {
+    private static final String TAG = "UserCredentialsTests";
+
+    public void testCredentialIsParcelable() {
+        final String alias = "credential-test-alias";
+        Credential c = new Credential(alias);
+
+        c.storedTypes.add(Credential.Type.CA_CERTIFICATE);
+        c.storedTypes.add(Credential.Type.USER_SECRET_KEY);
+
+        Parcel p = Parcel.obtain();
+        c.writeToParcel(p, /* flags */ 0);
+        p.setDataPosition(0);
+
+        Credential r = Credential.CREATOR.createFromParcel(p);
+        assertEquals(c.alias, r.alias);
+        assertEquals(c.storedTypes, r.storedTypes);
+    }
+}
diff --git a/tests/unit/Android.mk b/tests/unit/Android.mk
new file mode 100644
index 0000000..3ba4606
--- /dev/null
+++ b/tests/unit/Android.mk
@@ -0,0 +1,19 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# We only want this apk build for tests.
+LOCAL_MODULE_TAGS := tests
+LOCAL_CERTIFICATE := platform
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test mockito-target
+
+# Include all test java files.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := SettingsUnitTests
+
+LOCAL_INSTRUMENTATION_FOR := Settings
+
+include $(BUILD_PACKAGE)
diff --git a/tests/unit/AndroidManifest.xml b/tests/unit/AndroidManifest.xml
new file mode 100644
index 0000000..c4cae0c
--- /dev/null
+++ b/tests/unit/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.settings.tests.unit">
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+        android:targetPackage="com.android.settings"
+        android:label="Settings Test Cases">
+    </instrumentation>
+
+</manifest>
diff --git a/tests/unit/README b/tests/unit/README
new file mode 100644
index 0000000..5184b07
--- /dev/null
+++ b/tests/unit/README
@@ -0,0 +1,17 @@
+To build the tests you can use the following command at the root of your android source tree
+$ make SettingsUnitTests
+
+The test apk then needs to be installed onto your test device via for example
+$ adb install -r out/target/product/shamu/data/app/SettingsUnitTests/SettingsUnitTests.apk
+
+To run all tests:
+$ adb shell am instrument -w com.android.settings.tests.unit/android.support.test.runner.AndroidJUnitRunner
+
+To run all tests in a specific class:
+$ adb shell am instrument -w -e class com.android.settings.<class> com.android.settings.tests.unit/android.support.test.runner.AndroidJUnitRunner
+
+To run a specific test:
+$ adb shell am instrument -w -e class com.android.settings.<class>#<test> com.android.settings.tests.unit/android.support.test.runner.AndroidJUnitRunner
+
+More general information can be found at
+http://developer.android.com/reference/android/support/test/runner/AndroidJUnitRunner.html
diff --git a/tests/src/com/android/settings/DeviceInfoSettingsTest.java b/tests/unit/src/com/android/settings/DeviceInfoSettingsTest.java
similarity index 96%
rename from tests/src/com/android/settings/DeviceInfoSettingsTest.java
rename to tests/unit/src/com/android/settings/DeviceInfoSettingsTest.java
index abd4d76..cec3f74 100644
--- a/tests/src/com/android/settings/DeviceInfoSettingsTest.java
+++ b/tests/unit/src/com/android/settings/DeviceInfoSettingsTest.java
@@ -17,17 +17,20 @@
 package com.android.settings;
 
 import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.settingslib.DeviceInfoUtils;
 
 public class DeviceInfoSettingsTest extends AndroidTestCase {
 
+    @SmallTest
     public void testGetFormattedKernelVersion() throws Exception {
         if ("Unavailable".equals(DeviceInfoUtils.getFormattedKernelVersion())) {
             fail("formatKernelVersion can't cope with this device's /proc/version");
         }
     }
 
+    @SmallTest
     public void testFormatKernelVersion() throws Exception {
         assertEquals("Unavailable", DeviceInfoUtils.formatKernelVersion(""));
         assertEquals("2.6.38.8-gg784\n" +
diff --git a/tests/src/com/android/settings/UtilsTests.java b/tests/unit/src/com/android/settings/UtilsTest.java
similarity index 97%
rename from tests/src/com/android/settings/UtilsTests.java
rename to tests/unit/src/com/android/settings/UtilsTest.java
index 9d4a5b8..20e7013 100644
--- a/tests/src/com/android/settings/UtilsTests.java
+++ b/tests/unit/src/com/android/settings/UtilsTest.java
@@ -33,7 +33,7 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-public class UtilsTests extends AndroidTestCase {
+public class UtilsTest extends AndroidTestCase {
     private static final int TEST_PRIMARY_USER_ID = 10;
     private static final int TEST_MANAGED_PROFILE_ID = 11;
 
diff --git a/tests/src/com/android/settings/bluetooth/Utf8ByteLengthFilterTest.java b/tests/unit/src/com/android/settings/bluetooth/Utf8ByteLengthFilterTest.java
similarity index 97%
rename from tests/src/com/android/settings/bluetooth/Utf8ByteLengthFilterTest.java
rename to tests/unit/src/com/android/settings/bluetooth/Utf8ByteLengthFilterTest.java
index ecbd947..220211a 100644
--- a/tests/src/com/android/settings/bluetooth/Utf8ByteLengthFilterTest.java
+++ b/tests/unit/src/com/android/settings/bluetooth/Utf8ByteLengthFilterTest.java
@@ -17,6 +17,7 @@
 package com.android.settings.bluetooth;
 
 import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
 import android.text.InputFilter;
 import android.text.SpannableStringBuilder;
 
@@ -24,6 +25,7 @@
 
 public class Utf8ByteLengthFilterTest extends AndroidTestCase {
 
+    @SmallTest
     public void testFilter() {
         // Define the variables
         CharSequence source;