Merge "Suppress some search results" into oc-mr1-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index d553573..9c71c4f 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -798,7 +798,7 @@
 
         <activity android:name=".support.NewDeviceIntroSuggestionActivity"
                   android:label="@string/new_device_suggestion_title"
-                  android:icon="@drawable/ic_new_releases_24dp"
+                  android:icon="@drawable/ic_new_device_suggestion_24dp"
                   android:theme="@android:style/Theme.NoDisplay">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
diff --git a/res/drawable-nodpi/fingerprint_enroll_introduction.png b/res/drawable-nodpi/fingerprint_enroll_introduction.png
new file mode 100644
index 0000000..268ca43
--- /dev/null
+++ b/res/drawable-nodpi/fingerprint_enroll_introduction.png
Binary files differ
diff --git a/res/drawable/ic_new_releases_24dp.xml b/res/drawable/ic_new_device_suggestion_24dp.xml
similarity index 100%
rename from res/drawable/ic_new_releases_24dp.xml
rename to res/drawable/ic_new_device_suggestion_24dp.xml
diff --git a/res/layout/choose_lock_password.xml b/res/layout/choose_lock_password.xml
index 7ce3034..f1b631e 100644
--- a/res/layout/choose_lock_password.xml
+++ b/res/layout/choose_lock_password.xml
@@ -21,7 +21,7 @@
     android:layout_height="match_parent"
     android:icon="@drawable/ic_lock"
     settings:suwFooter="@layout/choose_lock_password_footer"
-    settings:suwHeaderText="@string/lockpassword_choose_your_password_header">
+    settings:suwHeaderText="@string/lockpassword_choose_your_screen_lock_header">
 
     <LinearLayout
         style="@style/SuwContentFrame"
@@ -33,11 +33,11 @@
         android:orientation="vertical">
 
         <TextView
-            android:id="@+id/fingerprint_backup_message"
+            android:id="@+id/message"
             style="@style/SuwDescription.Glif"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:visibility="gone" />
+            android:minLines="2"/>
 
         <LinearLayout
             android:id="@+id/password_container"
diff --git a/res/layout/fingerprint_enroll_introduction.xml b/res/layout/fingerprint_enroll_introduction.xml
index 4f73395..4228f42 100644
--- a/res/layout/fingerprint_enroll_introduction.xml
+++ b/res/layout/fingerprint_enroll_introduction.xml
@@ -45,6 +45,20 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content" />
 
+        <com.android.setupwizardlib.view.FillContentLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_weight="1">
+
+            <ImageView
+                style="@style/SuwContentIllustration"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:contentDescription="@null"
+                android:src="@drawable/fingerprint_enroll_introduction" />
+
+        </com.android.setupwizardlib.view.FillContentLayout>
+
     </LinearLayout>
 
 </com.android.setupwizardlib.GlifLayout>
diff --git a/res/layout/setup_choose_lock_generic_fingerprint_header.xml b/res/layout/setup_choose_lock_generic_fingerprint_header.xml
index 4c696f3..ec5d750 100644
--- a/res/layout/setup_choose_lock_generic_fingerprint_header.xml
+++ b/res/layout/setup_choose_lock_generic_fingerprint_header.xml
@@ -23,4 +23,4 @@
     android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
     android:paddingTop="@dimen/suw_description_glif_margin_top"
     android:paddingBottom="@dimen/suw_description_glif_margin_bottom_lists"
-    android:text="@string/setup_lock_settings_picker_fingerprint_message" />
+    android:text="@string/lock_settings_picker_fingerprint_added_security_message" />
diff --git a/res/values-mcc262-mnc02/strings.xml b/res/values-mcc262-mnc02/strings.xml
index 17f9272..280f59e 100644
--- a/res/values-mcc262-mnc02/strings.xml
+++ b/res/values-mcc262-mnc02/strings.xml
@@ -16,4 +16,6 @@
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <!-- Wi-Fi Calling settings. Additional text displayed when Wi-Fi Calling is off. Default empty. [CHAR LIMIT=NONE] -->
     <string name="wifi_calling_off_explanation_2">\n\nYou can\u2019t make emergency calls through Wi-Fi calling. If you try to make an emergency call, your device will automatically use the mobile network. Emergency calls can only be made in areas with mobile network coverage.</string>
+    <!-- Do not translate. Wireless networks, item title to go into the WFC settings [CHAR LIMIT=30] -->
+    <string name="wifi_calling_settings_title">"Wi-Fi calling"</string>
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 14884a2..6366b9e 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -835,9 +835,9 @@
     <!-- Button text to continue to the next screen from the introduction (this string variant is used while in setup wizard) [CHAR LIMIT=22] -->
     <string name="security_settings_fingerprint_enroll_introduction_continue_setup">Next</string>
     <!-- Title of dialog shown when the user tries to skip setting up fingerprint after adding lock screen during initial setup. [CHAR LIMIT=30] -->
-    <string name="fingerprint_enroll_skip_after_adding_lock_title">Skip fingerprint setup?</string>
+    <string name="setup_fingerprint_enroll_skip_title">Skip fingerprint?</string>
     <!-- Body text of dialog shown when the user tries to skip setting up fingerprint after adding lock screen during initial setup [CHAR LIMIT=NONE] -->
-    <string name="fingerprint_enroll_skip_after_adding_lock_text">You\u2019ve chosen to use your fingerprint as one way to unlock your phone. If you skip now, you\u2019ll need to set this up later. Setup takes only a minute or so.</string>
+    <string name="setup_fingerprint_enroll_skip_after_adding_lock_text">Fingerprint setup only takes a minute or two. If you skip this, you can add your fingerprint later in settings.</string>
     <!-- Title of dialog shown when the user tries to skip setting up a screen lock, warning them of potential consequences of not doing so [CHAR LIMIT=30]-->
     <string name="lock_screen_intro_skip_title">Skip screen lock?</string>
     <!-- Dialog text shown when the user tries to skip setting up a screen lock, warning them of potential consequences of not doing so, including loss of factory reset protection. (tablet) [CHAR LIMIT=NONE] -->
@@ -1105,8 +1105,8 @@
     <!--  Title for security picker in setup wizard to choose the unlock method: None/Pattern/PIN/Password (phone) [CHAR LIMIT=22] -->
     <string name="setup_lock_settings_picker_title" product="default">Protect your phone</string>
 
-    <!-- Title for screen in setup wizard, prompting user to choose the their backup screen lock method [CHAR LIMIT=NONE] -->
-    <string name="setup_lock_settings_picker_fingerprint_message">For added security, set up a backup screen lock.</string>
+    <!-- Message shown when setting up screen lock, prompting user to choose the their backup screen lock method [CHAR LIMIT=NONE] -->
+    <string name="lock_settings_picker_fingerprint_added_security_message">For added security, set up a backup screen lock.</string>
 
     <!-- Description text for screen in setup wizard asking user to set up screen lock, explaining to the user how setting up a screen lock protect them from losing data. (tablet) [CHAR LIMIT=NONE] -->
     <string name="setup_lock_settings_picker_message" product="tablet">Prevent others from using this tablet without your permission by activating device protection features. Choose the screen lock you want to use.</string>
@@ -1381,7 +1381,7 @@
     <!-- Label for ChoosePassword/PIN OK button -->
     <string name="lockpassword_cancel_label">Cancel</string>
 
-    <!-- Label for ChoosePassword/PIN OK button -->
+    <!-- Label for ChoosePassword/PIN Clear button that clears all text entered by the user so far. -->
     <string name="lockpassword_clear_label">Clear</string>
 
     <!-- Label for LockPatternTutorial Cancel button -->
@@ -3427,24 +3427,26 @@
     <string name="settings_safetylegal_activity_loading">Loading\u2026</string>
 
     <!-- Lock Pattern settings -->
-    <!-- Header on first screen of choose password/PIN flow [CHAR LIMIT=30] -->
-    <string name="lockpassword_choose_your_password_header">Choose your password</string>
+    <!-- Header on first screen of choose password/PIN flow [CHAR LIMIT=40] -->
+    <string name="lockpassword_choose_your_screen_lock_header">Set a screen lock</string>
+    <!-- Message on first screen of choose password flow [CHAR LIMIT=NONE] -->
+    <string name="lockpassword_choose_your_password_message">For security, set a password</string>
     <!-- Header on first screen of choose password/PIN as backup for fingerprint flow [CHAR LIMIT=30] -->
     <string name="lockpassword_choose_your_password_header_for_fingerprint">To use fingerprint, set password</string>
     <!-- Header on first screen of choose pattern flow [CHAR LIMIT=30] -->
     <string name="lockpassword_choose_your_pattern_header">Choose your pattern</string>
     <!-- Header on first screen of choose pattern as backup for fingerprint flow [CHAR LIMIT=30] -->
     <string name="lockpassword_choose_your_pattern_header_for_fingerprint">To use fingerprint, set pattern</string>
-    <!-- Header on first screen of choose password/PIN flow [CHAR LIMIT=30] -->
-    <string name="lockpassword_choose_your_pin_header">Choose your PIN</string>
+    <!-- Message on first screen of choose PIN flow [CHAR LIMIT=NONE] -->
+    <string name="lockpassword_choose_your_pin_message">For security, set a PIN</string>
     <!-- Header on first screen of choose password/PIN as backup for fingerprint flow [CHAR LIMIT=30] -->
     <string name="lockpassword_choose_your_pin_header_for_fingerprint">To use fingerprint, set PIN</string>
-    <!-- Header on password confirm screen [CHAR LIMIT=30] -->
-    <string name="lockpassword_confirm_your_password_header">Confirm your password</string>
+    <!-- Header on password confirm screen [CHAR LIMIT=40] -->
+    <string name="lockpassword_confirm_your_password_header">Re-enter your password</string>
     <!-- Header on pattern confirm screen [CHAR LIMIT=30] -->
     <string name="lockpassword_confirm_your_pattern_header">Confirm your pattern</string>
-    <!-- Header on password confirm screen [CHAR LIMIT=30] -->
-    <string name="lockpassword_confirm_your_pin_header">Confirm your PIN</string>
+    <!-- Header on password confirm screen [CHAR LIMIT=40] -->
+    <string name="lockpassword_confirm_your_pin_header">Re-enter your PIN</string>
     <!-- Header on password confirm screen if second password doesn't match the first. [CHAR LIMIT=30] -->
     <string name="lockpassword_confirm_passwords_dont_match">Passwords don\u2019t match</string>
     <!-- Header on pin confirm screen if second pin doesn't match the first. [CHAR LIMIT=30]-->
@@ -8780,8 +8782,8 @@
     <!-- Section title for the Web Action preference [CHAR LIMIT=60] -->
     <string name="web_action_section_title">Instant apps</string>
 
-    <!-- Preference label for an tappable preference that will open the account chooser for instant apps. [CHAR LIMIT=60] -->
-    <string name="instant_apps_account">Instant apps account</string>
+    <!-- Preference label for an tappable preference that will open the instant apps settings. [CHAR LIMIT=60] -->
+    <string name="instant_apps_settings">Instant Apps preferences</string>
 
     <!-- Section title for the Domain URL app preference list [CHAR LIMIT=60]-->
     <string name="domain_url_section_title">Installed apps</string>
@@ -9029,7 +9031,13 @@
     <string name="new_device_suggestion_title">What\'s new and exciting?</string>
 
     <!-- Summary label for new device suggestion, which is displayed in Settings homepage [CHAR LIMIT=100] -->
-    <string name="new_device_suggestion_summary">Check out the top 5 features</string>
+    <string name="new_device_suggestion_summary" product="default">Take a tour of your new phone</string>
+
+    <!-- Summary label for new device suggestion, which is displayed in Settings homepage [CHAR LIMIT=100] -->
+    <string name="new_device_suggestion_summary" product="tablet">Take a tour of your new tablet</string>
+
+    <!-- Summary label for new device suggestion, which is displayed in Settings homepage [CHAR LIMIT=100] -->
+    <string name="new_device_suggestion_summary" product="device">Take a tour of your new device</string>
 
     <!-- The divider symbol between different parts of the notification header including spaces. not translatable [CHAR LIMIT=3] -->
     <string name="notification_header_divider_symbol_with_spaces" translatable="false">" • "</string>
diff --git a/res/values/themes.xml b/res/values/themes.xml
index 1a8f3de..2610e08 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -25,7 +25,6 @@
     <style name="GlifTheme" parent="SuwThemeGlif">
         <!-- For all Alert Dialogs -->
         <item name="android:alertDialogTheme">@style/ThemeOverlay.AlertDialog</item>
-        <item name="android:colorPrimary">@color/suw_color_accent_dark</item>
         <item name="android:windowBackground">?android:attr/colorBackground</item>
         <item name="*android:preferencePanelStyle">@*android:style/PreferencePanel.Dialog</item>
         <item name="fingerprint_layout_theme">@style/FingerprintLayoutTheme</item>
@@ -46,7 +45,6 @@
     <style name="GlifTheme.Light" parent="SuwThemeGlif.Light">
         <!-- For all Alert Dialogs -->
         <item name="android:alertDialogTheme">@style/ThemeOverlay.AlertDialog</item>
-        <item name="android:colorPrimary">@color/suw_color_accent_light</item>
         <item name="android:windowBackground">?android:attr/colorBackground</item>
         <item name="*android:preferencePanelStyle">@*android:style/PreferencePanel.Dialog</item>
         <item name="fingerprint_layout_theme">@style/FingerprintLayoutTheme</item>
@@ -66,7 +64,6 @@
     <style name="GlifV2Theme" parent="SuwThemeGlifV2">
         <!-- For all Alert Dialogs -->
         <item name="android:alertDialogTheme">@style/ThemeOverlay.AlertDialog</item>
-        <item name="android:colorPrimary">@color/suw_color_accent_dark</item>
         <item name="android:windowBackground">?android:attr/colorBackground</item>
         <item name="*android:preferencePanelStyle">@*android:style/PreferencePanel.Dialog</item>
         <item name="fingerprint_layout_theme">@style/FingerprintLayoutTheme</item>
@@ -87,7 +84,6 @@
     <style name="GlifV2Theme.Light" parent="SuwThemeGlifV2.Light">
         <!-- For all Alert Dialogs -->
         <item name="android:alertDialogTheme">@style/ThemeOverlay.AlertDialog</item>
-        <item name="android:colorPrimary">@color/suw_color_accent_light</item>
         <item name="android:windowBackground">?android:attr/colorBackground</item>
         <item name="*android:preferencePanelStyle">@*android:style/PreferencePanel.Dialog</item>
         <item name="fingerprint_layout_theme">@style/FingerprintLayoutTheme</item>
diff --git a/res/xml/available_virtual_keyboard.xml b/res/xml/available_virtual_keyboard.xml
new file mode 100644
index 0000000..9a0b3c6
--- /dev/null
+++ b/res/xml/available_virtual_keyboard.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2017 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:key="available_virtual_keyboard_page"
+    android:title="@string/add_virtual_keyboard">
+
+</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/security_settings_password_sub.xml b/res/xml/security_settings_password_sub.xml
index 46c4999..c0287c0 100644
--- a/res/xml/security_settings_password_sub.xml
+++ b/res/xml/security_settings_password_sub.xml
@@ -22,7 +22,7 @@
     <com.android.settings.TimeoutListPreference
         android:key="lock_after_timeout"
         android:title="@string/lock_after_timeout"
-        android:summary="@string/lock_after_timeout_summary"
+        android:summary="@string/summary_placeholder"
         android:entries="@array/lock_after_timeout_entries"
         android:entryValues="@array/lock_after_timeout_values" />
 
@@ -32,7 +32,6 @@
 
     <com.android.settingslib.RestrictedPreference
         android:key="owner_info_settings"
-        android:title="@string/owner_info_settings_title"
-        android:summary="@string/owner_info_settings_summary" />
+        android:title="@string/owner_info_settings_title" />
 
 </PreferenceScreen>
diff --git a/res/xml/security_settings_pin_sub.xml b/res/xml/security_settings_pin_sub.xml
index 46c4999..c0287c0 100644
--- a/res/xml/security_settings_pin_sub.xml
+++ b/res/xml/security_settings_pin_sub.xml
@@ -22,7 +22,7 @@
     <com.android.settings.TimeoutListPreference
         android:key="lock_after_timeout"
         android:title="@string/lock_after_timeout"
-        android:summary="@string/lock_after_timeout_summary"
+        android:summary="@string/summary_placeholder"
         android:entries="@array/lock_after_timeout_entries"
         android:entryValues="@array/lock_after_timeout_values" />
 
@@ -32,7 +32,6 @@
 
     <com.android.settingslib.RestrictedPreference
         android:key="owner_info_settings"
-        android:title="@string/owner_info_settings_title"
-        android:summary="@string/owner_info_settings_summary" />
+        android:title="@string/owner_info_settings_title" />
 
 </PreferenceScreen>
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index f120b7f..609120d 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -59,7 +59,6 @@
 import com.android.settings.dashboard.DashboardSummary;
 import com.android.settings.development.DevelopmentSettings;
 import com.android.settings.overlay.FeatureFactory;
-import com.android.settings.search.DynamicIndexableContentMonitor;
 import com.android.settings.search.SearchActivity;
 import com.android.settings.wfd.WifiDisplaySettings;
 import com.android.settings.widget.SwitchBar;
@@ -76,8 +75,6 @@
 
     private static final String LOG_TAG = "Settings";
 
-    public static final int LOADER_ID_INDEXABLE_CONTENT_MONITOR = 1;
-
     // Constants for state save/restore
     private static final String SAVE_KEY_CATEGORIES = ":settings:categories";
     @VisibleForTesting
@@ -183,8 +180,6 @@
         }
     };
 
-    private DynamicIndexableContentMonitor mDynamicIndexableContentMonitor;
-
     private SwitchBar mSwitchBar;
 
     private Button mNextButton;
@@ -535,10 +530,6 @@
                 mDevelopmentPreferencesListener);
 
         registerReceiver(mBatteryInfoReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
-        if (mDynamicIndexableContentMonitor == null) {
-            mDynamicIndexableContentMonitor = new DynamicIndexableContentMonitor();
-        }
-        mDynamicIndexableContentMonitor.register(this, LOADER_ID_INDEXABLE_CONTENT_MONITOR);
 
         updateTilesList();
     }
@@ -550,9 +541,6 @@
                 mDevelopmentPreferencesListener);
         mDevelopmentPreferencesListener = null;
         unregisterReceiver(mBatteryInfoReceiver);
-        if (mDynamicIndexableContentMonitor != null) {
-            mDynamicIndexableContentMonitor.unregister(this, LOADER_ID_INDEXABLE_CONTENT_MONITOR);
-        }
     }
 
     @Override
diff --git a/src/com/android/settings/applications/ManageDomainUrls.java b/src/com/android/settings/applications/ManageDomainUrls.java
index 2149fbd..1d325ce 100644
--- a/src/com/android/settings/applications/ManageDomainUrls.java
+++ b/src/com/android/settings/applications/ManageDomainUrls.java
@@ -141,7 +141,7 @@
                     final Intent launchIntent = instantAppSettingsIntent;
                     // TODO: Make this button actually launch the account chooser.
                     mInstantAppAccountPreference = new Preference(getPrefContext());
-                    mInstantAppAccountPreference.setTitle(R.string.instant_apps_account);
+                    mInstantAppAccountPreference.setTitle(R.string.instant_apps_settings);
                     mInstantAppAccountPreference.setOnPreferenceClickListener(pref -> {
                         startActivity(launchIntent);
                         return true;
diff --git a/src/com/android/settings/applications/assist/ManageAssist.java b/src/com/android/settings/applications/assist/ManageAssist.java
index eb14ea1..4126aaf 100644
--- a/src/com/android/settings/applications/assist/ManageAssist.java
+++ b/src/com/android/settings/applications/assist/ManageAssist.java
@@ -22,7 +22,7 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settings.R;
 import com.android.settings.dashboard.DashboardFragment;
-import com.android.settings.gestures.AssistGesturePreferenceController;
+import com.android.settings.gestures.AssistGestureSettingsPreferenceController;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.search.Indexable;
 import com.android.settingslib.core.AbstractPreferenceController;
@@ -73,8 +73,8 @@
         final List<AbstractPreferenceController> controllers = new ArrayList<>();
         controllers.add(new DefaultAssistPreferenceController(context, "default_assist",
                 true /* showSetting */));
-        controllers.add(new AssistGesturePreferenceController(context, lifecycle, KEY_ASSIST,
-                true /* assistOnly */));
+        controllers.add(new AssistGestureSettingsPreferenceController(context, lifecycle,
+                KEY_ASSIST, true /* assistOnly */));
         controllers.add(new AssistContextPreferenceController(context, lifecycle));
         controllers.add(new AssistScreenshotPreferenceController(context, lifecycle));
         controllers.add(new AssistFlashScreenPreferenceController(context, lifecycle));
diff --git a/src/com/android/settings/bluetooth/AlwaysDiscoverable.java b/src/com/android/settings/bluetooth/AlwaysDiscoverable.java
new file mode 100644
index 0000000..5d7cbd5
--- /dev/null
+++ b/src/com/android/settings/bluetooth/AlwaysDiscoverable.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.bluetooth;
+
+import android.bluetooth.BluetoothAdapter;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Handler;
+import android.support.annotation.VisibleForTesting;
+import android.util.Log;
+
+import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
+
+import java.util.Timer;
+import java.util.TimerTask;
+
+/** Helper class, intended to be used by an Activity, to keep the local Bluetooth adapter in
+ *  discoverable mode indefinitely. By default setting the scan mode to
+ *  BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE will time out after some time, but some
+ *  Bluetooth settings pages would like to keep the device discoverable as long as the page is
+ *  visible. */
+public class AlwaysDiscoverable extends BroadcastReceiver {
+    private static final String TAG = "AlwaysDiscoverable";
+
+    private Context mContext;
+    private LocalBluetoothAdapter mLocalAdapter;
+    private IntentFilter mIntentFilter;
+
+    @VisibleForTesting
+    boolean mStarted;
+
+    public AlwaysDiscoverable(Context context, LocalBluetoothAdapter localAdapter) {
+        mContext = context;
+        mLocalAdapter = localAdapter;
+        mIntentFilter = new IntentFilter();
+        mIntentFilter.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
+    }
+
+    /** After calling start(), consumers should make a matching call to stop() when they no longer
+     * wish to enforce discoverable mode. */
+    public void start() {
+        if (mStarted) {
+            return;
+        }
+        mContext.registerReceiver(this, mIntentFilter);
+        mStarted = true;
+        if (mLocalAdapter.getScanMode() != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
+            mLocalAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
+        }
+    }
+
+    public void stop() {
+        if (!mStarted) {
+            return;
+        }
+        mContext.unregisterReceiver(this);
+        mStarted = false;
+        mLocalAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE);
+    }
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        String action = intent.getAction();
+        if (action != BluetoothAdapter.ACTION_SCAN_MODE_CHANGED) {
+            return;
+        }
+        if (mLocalAdapter.getScanMode() != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
+            mLocalAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
+        }
+    }
+}
diff --git a/src/com/android/settings/bluetooth/BluetoothPairingDetail.java b/src/com/android/settings/bluetooth/BluetoothPairingDetail.java
index 5cc1060..60011f9 100644
--- a/src/com/android/settings/bluetooth/BluetoothPairingDetail.java
+++ b/src/com/android/settings/bluetooth/BluetoothPairingDetail.java
@@ -53,6 +53,8 @@
     BluetoothProgressCategory mAvailableDevicesCategory;
     @VisibleForTesting
     FooterPreference mFooterPreference;
+    @VisibleForTesting
+    AlwaysDiscoverable mAlwaysDiscoverable;
 
     private boolean mInitialScanStarted;
 
@@ -64,6 +66,7 @@
     public void onActivityCreated(Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
         mInitialScanStarted = false;
+        mAlwaysDiscoverable = new AlwaysDiscoverable(getContext(), mLocalAdapter);
     }
 
     @Override
@@ -79,7 +82,7 @@
         super.onStop();
 
         // Make the device only visible to connected devices.
-        mLocalAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE);
+        mAlwaysDiscoverable.stop();
         disableScanning();
     }
 
@@ -132,9 +135,7 @@
                         R.string.bluetooth_preference_found_devices,
                         BluetoothDeviceFilter.UNBONDED_DEVICE_FILTER, mInitialScanStarted);
                 updateFooterPreference(mFooterPreference);
-                // mLocalAdapter.setScanMode is internally synchronized so it is okay for multiple
-                // threads to execute.
-                mLocalAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
+                mAlwaysDiscoverable.start();
                 enableScanning();
                 break;
 
diff --git a/src/com/android/settings/bluetooth/BluetoothPairingDialogFragment.java b/src/com/android/settings/bluetooth/BluetoothPairingDialogFragment.java
index f95ce46..1aac0ff 100644
--- a/src/com/android/settings/bluetooth/BluetoothPairingDialogFragment.java
+++ b/src/com/android/settings/bluetooth/BluetoothPairingDialogFragment.java
@@ -25,6 +25,7 @@
 import android.text.InputFilter;
 import android.text.InputFilter.LengthFilter;
 import android.text.InputType;
+import android.text.TextUtils;
 import android.text.TextWatcher;
 import android.util.Log;
 import android.view.View;
@@ -34,6 +35,7 @@
 import android.widget.EditText;
 import android.widget.TextView;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settings.R;
 import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
@@ -186,6 +188,19 @@
     }
 
     /**
+     * Helper method to return the text of the pin entry field - this exists primarily to help us
+     * simulate having existing text when the dialog is recreated, for example after a screen
+     * rotation.
+     */
+    @VisibleForTesting
+    CharSequence getPairingViewText() {
+        if (mPairingView != null) {
+            return mPairingView.getText();
+        }
+        return null;
+    }
+
+    /**
      * Returns a dialog with UI elements that allow a user to provide input.
      */
     private AlertDialog createUserEntryDialog() {
@@ -196,7 +211,9 @@
         mBuilder.setNegativeButton(getString(android.R.string.cancel), this);
         AlertDialog dialog = mBuilder.create();
         dialog.setOnShowListener(d -> {
-            mDialog.getButton(Dialog.BUTTON_POSITIVE).setEnabled(false);
+            if (TextUtils.isEmpty(getPairingViewText())) {
+                mDialog.getButton(Dialog.BUTTON_POSITIVE).setEnabled(false);
+            }
             if (mPairingView != null && mPairingView.requestFocus()) {
                 InputMethodManager imm = (InputMethodManager)
                         getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
diff --git a/src/com/android/settings/bluetooth/BluetoothSettings.java b/src/com/android/settings/bluetooth/BluetoothSettings.java
index adfb721..bd86c4b 100644
--- a/src/com/android/settings/bluetooth/BluetoothSettings.java
+++ b/src/com/android/settings/bluetooth/BluetoothSettings.java
@@ -80,6 +80,7 @@
     FooterPreference mFooterPreference;
     private Preference mPairingPreference;
     private BluetoothEnabler mBluetoothEnabler;
+    private AlwaysDiscoverable mAlwaysDiscoverable;
 
     private SwitchBar mSwitchBar;
 
@@ -111,6 +112,9 @@
                 mMetricsFeatureProvider, Utils.getLocalBtManager(activity),
                 MetricsEvent.ACTION_BLUETOOTH_TOGGLE);
         mBluetoothEnabler.setupSwitchController();
+        if (mLocalAdapter != null) {
+            mAlwaysDiscoverable = new AlwaysDiscoverable(getContext(), mLocalAdapter);
+        }
     }
 
     @Override
@@ -157,7 +161,9 @@
         }
 
         // Make the device only visible to connected devices.
-        mLocalAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE);
+        if (mAlwaysDiscoverable != null) {
+            mAlwaysDiscoverable.stop();
+        }
 
         if (isUiRestricted()) {
             return;
@@ -188,7 +194,9 @@
                 mPairedDevicesCategory.addPreference(mPairingPreference);
                 updateFooterPreference(mFooterPreference);
 
-                mLocalAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
+                if (mAlwaysDiscoverable != null) {
+                    mAlwaysDiscoverable.start();
+                }
                 return; // not break
 
             case BluetoothAdapter.STATE_TURNING_OFF:
diff --git a/src/com/android/settings/core/instrumentation/SharedPreferencesLogger.java b/src/com/android/settings/core/instrumentation/SharedPreferencesLogger.java
index b4e6158..dee40c0 100644
--- a/src/com/android/settings/core/instrumentation/SharedPreferencesLogger.java
+++ b/src/com/android/settings/core/instrumentation/SharedPreferencesLogger.java
@@ -120,19 +120,29 @@
 
         final Pair<Integer, Object> valueData;
         if (value instanceof Long) {
-            valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_LONG_VALUE,
-                    value);
+            final Long longVal = (Long) value;
+            final int intVal;
+            if (longVal > Integer.MAX_VALUE) {
+                intVal = Integer.MAX_VALUE;
+            } else if (longVal < Integer.MIN_VALUE) {
+                intVal = Integer.MIN_VALUE;
+            } else {
+                intVal = longVal.intValue();
+            }
+            valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE,
+                    intVal);
         } else if (value instanceof Integer) {
-            valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_LONG_VALUE,
-                    ((Integer) value).longValue());
+            valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE,
+                    value);
         } else if (value instanceof Boolean) {
-            valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_LONG_VALUE,
-                    (Boolean) value ? 1L : 0L);
+            valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE,
+                    (Boolean) value ? 1 : 0);
         } else if (value instanceof Float) {
             valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_FLOAT_VALUE,
                     value);
         } else if (value instanceof String) {
-            valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_VALUE, value);
+            Log.d(LOG_TAG, "Tried to log string preference " + prefKey + " = " + value);
+            valueData = null;
         } else {
             Log.w(LOG_TAG, "Tried to log unloggable object" + value);
             valueData = null;
diff --git a/src/com/android/settings/fingerprint/FingerprintSettings.java b/src/com/android/settings/fingerprint/FingerprintSettings.java
index 4eddcb1..7ebf294 100644
--- a/src/com/android/settings/fingerprint/FingerprintSettings.java
+++ b/src/com/android/settings/fingerprint/FingerprintSettings.java
@@ -129,7 +129,6 @@
 
     public static class FingerprintSettingsFragment extends SettingsPreferenceFragment
             implements OnPreferenceChangeListener, FingerprintPreference.OnDeleteClickListener {
-        private static final int MAX_RETRY_ATTEMPTS = 20;
         private static final int RESET_HIGHLIGHT_DELAY_MS = 500;
 
         private static final String TAG = "FingerprintSettings";
@@ -284,6 +283,11 @@
             if (mRemovalSidecar.inProgress()) {
                 return;
             }
+            // Don't start authentication if ChooseLockGeneric is showing, otherwise if the user
+            // is in FP lockout, a toast will show on top
+            if (mLaunchedConfirm) {
+                return;
+            }
             if (!mInFingerprintLockout) {
                 mFingerprintCancel = new CancellationSignal();
                 mFingerprintManager.authenticate(null, mFingerprintCancel, 0 /* flags */,
@@ -432,6 +436,7 @@
         @Override
         public void onResume() {
             super.onResume();
+            mInFingerprintLockout = false;
             // Make sure we reload the preference hierarchy since fingerprints may be added,
             // deleted or renamed.
             updatePreferences();
@@ -545,6 +550,7 @@
             super.onActivityResult(requestCode, resultCode, data);
             if (requestCode == CHOOSE_LOCK_GENERIC_REQUEST
                     || requestCode == CONFIRM_REQUEST) {
+                mLaunchedConfirm = false;
                 if (resultCode == RESULT_FINISHED || resultCode == RESULT_OK) {
                     // The lock pin/pattern/password was set. Start enrolling!
                     if (data != null) {
diff --git a/src/com/android/settings/fingerprint/SetupFingerprintEnrollFindSensor.java b/src/com/android/settings/fingerprint/SetupFingerprintEnrollFindSensor.java
index 85e3417..2137130 100644
--- a/src/com/android/settings/fingerprint/SetupFingerprintEnrollFindSensor.java
+++ b/src/com/android/settings/fingerprint/SetupFingerprintEnrollFindSensor.java
@@ -78,10 +78,10 @@
         @NonNull
         public AlertDialog.Builder onCreateDialogBuilder() {
             return new AlertDialog.Builder(getContext())
-                    .setTitle(R.string.fingerprint_enroll_skip_after_adding_lock_title)
+                    .setTitle(R.string.setup_fingerprint_enroll_skip_title)
                     .setPositiveButton(R.string.skip_anyway_button_label, this)
                     .setNegativeButton(R.string.go_back_button_label, this)
-                    .setMessage(R.string.fingerprint_enroll_skip_after_adding_lock_text);
+                    .setMessage(R.string.setup_fingerprint_enroll_skip_after_adding_lock_text);
         }
 
         @Override
diff --git a/src/com/android/settings/gestures/AssistGestureSettings.java b/src/com/android/settings/gestures/AssistGestureSettings.java
index 3066baf..8878f47 100644
--- a/src/com/android/settings/gestures/AssistGestureSettings.java
+++ b/src/com/android/settings/gestures/AssistGestureSettings.java
@@ -35,8 +35,6 @@
 
     private static final String TAG = "AssistGesture";
 
-    private static final String KEY_ASSIST = "gesture_assist";
-
     @Override
     public int getMetricsCategory() {
         return MetricsProto.MetricsEvent.SETTINGS_ASSIST_GESTURE;
@@ -60,8 +58,6 @@
     private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
             Lifecycle lifecycle) {
         final List<AbstractPreferenceController> controllers = new ArrayList<>();
-        controllers.add(new AssistGesturePreferenceController(context, lifecycle, KEY_ASSIST,
-                false /* assistOnly */));
         controllers.addAll(FeatureFactory.getFactory(context).getAssistGestureFeatureProvider()
                 .getControllers(context, lifecycle));
 
@@ -86,8 +82,8 @@
 
                 @Override
                 protected boolean isPageSearchEnabled(Context context) {
-                    return new AssistGesturePreferenceController(context, null /* lifecycle */,
-                            null /* key */, false /* assistOnly */)
+                    return new AssistGestureSettingsPreferenceController(context,
+                            null /* lifecycle */, null /* key */, false /* assistOnly */)
                             .isAvailable();
                 }
             };
diff --git a/src/com/android/settings/gestures/AssistGesturePreferenceController.java b/src/com/android/settings/gestures/AssistGestureSettingsPreferenceController.java
similarity index 72%
rename from src/com/android/settings/gestures/AssistGesturePreferenceController.java
rename to src/com/android/settings/gestures/AssistGestureSettingsPreferenceController.java
index b91f230..bf6ee8c 100644
--- a/src/com/android/settings/gestures/AssistGesturePreferenceController.java
+++ b/src/com/android/settings/gestures/AssistGestureSettingsPreferenceController.java
@@ -16,6 +16,9 @@
 
 package com.android.settings.gestures;
 
+import static android.provider.Settings.Secure.ASSIST_GESTURE_ENABLED;
+import static android.provider.Settings.Secure.ASSIST_GESTURE_SILENCE_ALERTS_ENABLED;
+
 import android.content.Context;
 import android.content.Intent;
 import android.provider.Settings;
@@ -32,19 +35,17 @@
 import com.android.settingslib.core.lifecycle.Lifecycle;
 import com.android.settingslib.core.lifecycle.events.OnResume;
 
-import static android.provider.Settings.Secure.ASSIST_GESTURE_ENABLED;
-
-public class AssistGesturePreferenceController extends GesturePreferenceController
+public class AssistGestureSettingsPreferenceController extends GesturePreferenceController
         implements OnResume {
 
-    private final int ON = 1;
-    private final int OFF = 0;
-
     private static final String PREF_KEY_VIDEO = "gesture_assist_video";
+
+    private static final String SECURE_KEY_ASSIST = ASSIST_GESTURE_ENABLED;
+    private static final String SECURE_KEY_SILENCE = ASSIST_GESTURE_SILENCE_ALERTS_ENABLED;
+    private static final int ON = 1;
+    private static final int OFF = 0;
+
     private final String mAssistGesturePrefKey;
-
-    private final String SECURE_KEY = ASSIST_GESTURE_ENABLED;
-
     private final AssistGestureFeatureProvider mFeatureProvider;
     private boolean mWasAvailable;
 
@@ -54,8 +55,8 @@
     @VisibleForTesting
     boolean mAssistOnly;
 
-    public AssistGesturePreferenceController(Context context, Lifecycle lifecycle, String key,
-            boolean assistOnly) {
+    public AssistGestureSettingsPreferenceController(Context context, Lifecycle lifecycle,
+            String key, boolean assistOnly) {
         super(context, lifecycle);
         mFeatureProvider = FeatureFactory.getFactory(context).getAssistGestureFeatureProvider();
         mWasAvailable = isAvailable();
@@ -76,14 +77,6 @@
     public void displayPreference(PreferenceScreen screen) {
         mScreen = screen;
         mPreference = screen.findPreference(getPreferenceKey());
-        if (!mFeatureProvider.isSensorAvailable(mContext)) {
-            removePreference(mScreen, getPreferenceKey());
-            return;
-        }
-        if (!mFeatureProvider.isSupported(mContext)) {
-            mScreen.removePreference(mPreference);
-            return;
-        }
         // Call super last or AbstractPreferenceController might remove the preference from the
         // screen (if !isAvailable()) before we can save a reference to it.
         super.displayPreference(screen);
@@ -91,14 +84,6 @@
 
     @Override
     public void onResume() {
-        // This check must be done in case the user disables Assistant while still on the settings
-        // page. This check is slightly different than isAvailable() in some cases due to this
-        // setting being in multiple places that require different behavior
-        if (mScreen != null && !mFeatureProvider.isSupported(mContext)) {
-            mScreen.removePreference(mPreference);
-            mWasAvailable = false;
-            return;
-        }
         if (mWasAvailable != isAvailable()) {
             // Only update the preference visibility if the availability has changed -- otherwise
             // the preference may be incorrectly added to screens with collapsed sections.
@@ -112,7 +97,7 @@
             return;
         }
 
-        if (mFeatureProvider.isSupported(mContext)) {
+        if (isAvailable()) {
             if (mScreen.findPreference(getPreferenceKey()) == null) {
                 mScreen.addPreference(mPreference);
             }
@@ -121,15 +106,22 @@
         }
     }
 
+    private boolean isAssistGestureEnabled() {
+        return Settings.Secure.getInt(mContext.getContentResolver(),
+                SECURE_KEY_ASSIST, ON) != 0;
+    }
+
+    private boolean isSilenceGestureEnabled() {
+        return Settings.Secure.getInt(mContext.getContentResolver(),
+                SECURE_KEY_SILENCE, ON) != 0;
+    }
+
     @Override
     public void updateState(Preference preference) {
-        boolean isEnabled = isSwitchPrefEnabled() && mFeatureProvider.isSupported(mContext);
+        boolean isEnabled = isAssistGestureEnabled() && mFeatureProvider.isSupported(mContext);
 
         if (!mAssistOnly) {
-            boolean assistGestureSilenceEnabled = Settings.Secure.getInt(
-                    mContext.getContentResolver(),
-                    Settings.Secure.ASSIST_GESTURE_SILENCE_ALERTS_ENABLED, 1) != 0;
-            isEnabled = isEnabled || assistGestureSilenceEnabled;
+            isEnabled = isEnabled || isSilenceGestureEnabled();
         }
 
         if (preference != null) {
@@ -146,7 +138,8 @@
     @Override
     public boolean onPreferenceChange(Preference preference, Object newValue) {
         final boolean enabled = (boolean) newValue;
-        Settings.Secure.putInt(mContext.getContentResolver(), SECURE_KEY, enabled ? ON : OFF);
+        Settings.Secure.putInt(mContext.getContentResolver(), SECURE_KEY_ASSIST,
+                enabled ? ON : OFF);
         updateState(preference);
         return true;
     }
@@ -163,9 +156,8 @@
 
     @Override
     protected boolean isSwitchPrefEnabled() {
-        final int assistGestureEnabled = Settings.Secure.getInt(mContext.getContentResolver(),
-                SECURE_KEY, ON);
-        return assistGestureEnabled != 0;
+        // Does nothing
+        return true;
     }
 
     @Override
@@ -174,7 +166,7 @@
                 AssistGestureSettings.class.getName(), mAssistGesturePrefKey,
                 mContext.getString(R.string.display_settings));
 
-        return new InlineSwitchPayload(SECURE_KEY, ResultPayload.SettingsSource.SECURE,
+        return new InlineSwitchPayload(SECURE_KEY_ASSIST, ResultPayload.SettingsSource.SECURE,
                 ON /* onValue */, intent, isAvailable(), ON /* defaultValue */);
     }
 }
diff --git a/src/com/android/settings/gestures/GestureSettings.java b/src/com/android/settings/gestures/GestureSettings.java
index 805c4a1..4d38b09 100644
--- a/src/com/android/settings/gestures/GestureSettings.java
+++ b/src/com/android/settings/gestures/GestureSettings.java
@@ -75,8 +75,8 @@
             @NonNull Context context, @Nullable Lifecycle lifecycle,
             @NonNull AmbientDisplayConfiguration ambientDisplayConfiguration) {
         final List<AbstractPreferenceController> controllers = new ArrayList<>();
-        controllers.add(new AssistGesturePreferenceController(context, lifecycle, KEY_ASSIST,
-                false /* assistOnly */));
+        controllers.add(new AssistGestureSettingsPreferenceController(context, lifecycle,
+                KEY_ASSIST, false /* assistOnly */));
         controllers.add(new SwipeToNotificationPreferenceController(context, lifecycle,
                 KEY_SWIPE_DOWN));
         controllers.add(new DoubleTwistPreferenceController(context, lifecycle, KEY_DOUBLE_TWIST));
diff --git a/src/com/android/settings/gestures/SwipeToNotificationPreferenceController.java b/src/com/android/settings/gestures/SwipeToNotificationPreferenceController.java
index 3b5dbba..6f334a5 100644
--- a/src/com/android/settings/gestures/SwipeToNotificationPreferenceController.java
+++ b/src/com/android/settings/gestures/SwipeToNotificationPreferenceController.java
@@ -17,29 +17,24 @@
 package com.android.settings.gestures;
 
 import android.content.Context;
-import android.content.Intent;
 import android.content.SharedPreferences;
 import android.provider.Settings;
 import android.support.v7.preference.Preference;
 
-import com.android.settings.R;
 import com.android.settings.Utils;
-import com.android.settings.search.DatabaseIndexingUtils;
-import com.android.settings.search.InlineSwitchPayload;
-import com.android.settings.search.ResultPayload;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
 import static android.provider.Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED;
 
 public class SwipeToNotificationPreferenceController extends GesturePreferenceController {
 
-    private final int ON = 1;
-    private final int OFF = 0;
+    private static final int ON = 1;
+    private static final int OFF = 0;
 
     private static final String PREF_KEY_VIDEO = "gesture_swipe_down_fingerprint_video";
     private final String mSwipeDownFingerPrefKey;
 
-    private final String SECURE_KEY = SYSTEM_NAVIGATION_KEYS_ENABLED;
+    private static final String SECURE_KEY = SYSTEM_NAVIGATION_KEYS_ENABLED;
 
     public SwipeToNotificationPreferenceController(Context context, Lifecycle lifecycle,
             String key) {
@@ -70,28 +65,30 @@
 
     @Override
     public boolean isAvailable() {
-        return isGestureAvailable(mContext);
+        return SwipeToNotificationPreferenceController.isAvailable(mContext);
     }
 
     @Override
     public boolean onPreferenceChange(Preference preference, Object newValue) {
-        Settings.Secure.putInt(mContext.getContentResolver(), SECURE_KEY,
-                (boolean) newValue ? ON : OFF);
+        setSwipeToNotification(mContext, (boolean) newValue);
         return true;
     }
 
     @Override
     protected boolean isSwitchPrefEnabled() {
-        return Settings.Secure.getInt(mContext.getContentResolver(), SECURE_KEY, OFF) == ON;
+        return isSwipeToNotificationOn(mContext);
     }
 
-    @Override
-    public ResultPayload getResultPayload() {
-        final Intent intent = DatabaseIndexingUtils.buildSubsettingIntent(mContext,
-                SwipeToNotificationSettings.class.getName(), mSwipeDownFingerPrefKey,
-                mContext.getString(R.string.display_settings));
+    public static boolean isSwipeToNotificationOn(Context context) {
+        return Settings.Secure.getInt(context.getContentResolver(), SECURE_KEY, OFF) == ON;
+    }
 
-        return new InlineSwitchPayload(SECURE_KEY, ResultPayload.SettingsSource.SECURE,
-                ON /* onValue */, intent, isAvailable(), OFF /* defaultValue */);
+    public static boolean setSwipeToNotification(Context context, boolean isEnabled) {
+        return Settings.Secure.putInt(
+                context.getContentResolver(), SECURE_KEY, isEnabled ? ON : OFF);
+    }
+
+    public static boolean isAvailable(Context context) {
+        return isGestureAvailable(context);
     }
 }
diff --git a/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragment.java b/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragment.java
index a7862ae..48b0b4a 100644
--- a/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragment.java
+++ b/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragment.java
@@ -21,7 +21,6 @@
 import android.annotation.Nullable;
 import android.app.Activity;
 import android.app.admin.DevicePolicyManager;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
@@ -31,17 +30,15 @@
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
-import android.support.v7.preference.PreferenceScreen;
+import android.provider.SearchIndexableResource;
 import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodManager;
-import android.view.inputmethod.InputMethodSubtype;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settings.R;
 import com.android.settings.SettingsPreferenceFragment;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.search.Indexable;
-import com.android.settings.search.SearchIndexableRaw;
 import com.android.settingslib.inputmethod.InputMethodAndSubtypeUtil;
 import com.android.settingslib.inputmethod.InputMethodPreference;
 import com.android.settingslib.inputmethod.InputMethodSettingValuesWrapper;
@@ -60,10 +57,9 @@
 
     @Override
     public void onCreatePreferences(Bundle bundle, String s) {
+        addPreferencesFromResource(R.xml.available_virtual_keyboard);
         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);
@@ -105,7 +101,7 @@
         }
         try {
             return packageManager.getDrawable(packageName, resId, applicationInfo);
-        } catch (Exception e){
+        } catch (Exception e) {
             return null;
         }
     }
@@ -172,48 +168,16 @@
         }
     }
 
-    private static List<InputMethodSubtype> getAllSubtypesOf(final InputMethodInfo imi) {
-        final int subtypeCount = imi.getSubtypeCount();
-        final List<InputMethodSubtype> allSubtypes = new ArrayList<>(subtypeCount);
-        for (int index = 0; index < subtypeCount; index++) {
-            allSubtypes.add(imi.getSubtypeAt(index));
-        }
-        return allSubtypes;
-    }
-
-    static List<SearchIndexableRaw> buildSearchIndexOfInputMethods(final Context context,
-            final List<InputMethodInfo> inputMethods, final String screenTitle) {
-        final List<SearchIndexableRaw> indexes = new ArrayList<>();
-        for (int i = 0; i < inputMethods.size(); i++) {
-            final InputMethodInfo imi = inputMethods.get(i);
-            final ServiceInfo serviceInfo = imi.getServiceInfo();
-            final SearchIndexableRaw index = new SearchIndexableRaw(context);
-            index.key = new ComponentName(serviceInfo.packageName, serviceInfo.name)
-                    .flattenToString();
-            index.title = imi.loadLabel(context.getPackageManager()).toString();
-            index.summaryOn = index.summaryOff = InputMethodAndSubtypeUtil
-                    .getSubtypeLocaleNameListAsSentence(getAllSubtypesOf(imi), context, imi);
-            index.screenTitle = screenTitle;
-            indexes.add(index);
-        }
-        return indexes;
-    }
-
-    public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+    public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
             new BaseSearchIndexProvider() {
-        @Override
-        public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) {
-            final InputMethodManager imm = context.getSystemService(InputMethodManager.class);
-            final List<InputMethodInfo> enabledInputMethods = imm.getEnabledInputMethodList();
-            final List<InputMethodInfo> disabledInputMethods = new ArrayList<>();
-            for (final InputMethodInfo imi : imm.getInputMethodList()) {
-                if (!enabledInputMethods.contains(imi)) {
-                    disabledInputMethods.add(imi);
+                @Override
+                public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
+                        boolean enabled) {
+                    List<SearchIndexableResource> res = new ArrayList<>();
+                    SearchIndexableResource index = new SearchIndexableResource(context);
+                    index.xmlResId = R.xml.available_virtual_keyboard;
+                    res.add(index);
+                    return res;
                 }
-            }
-            final String screenTitle = context.getString(
-                    R.string.available_virtual_keyboard_category);
-            return buildSearchIndexOfInputMethods(context, disabledInputMethods, screenTitle);
-        }
-    };
+            };
 }
diff --git a/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java b/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java
index 42eff15..83d501d 100644
--- a/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java
+++ b/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java
@@ -31,6 +31,7 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.UserHandle;
+import android.provider.SearchIndexableResource;
 import android.provider.Settings.Secure;
 import android.support.v14.preference.SwitchPreference;
 import android.support.v7.preference.Preference;
@@ -51,11 +52,11 @@
 import com.android.settings.SettingsPreferenceFragment;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.search.Indexable;
-import com.android.settings.search.SearchIndexableRaw;
 import com.android.settingslib.inputmethod.InputMethodAndSubtypeUtil;
 
 import java.text.Collator;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -288,6 +289,7 @@
         final PhysicalKeyboardFragment mPhysicalKeyboardFragment;
         @NonNull
         final List<HardKeyboardDeviceInfo> mHardKeyboards;
+
         public Callbacks(
                 @NonNull Context context,
                 @NonNull PhysicalKeyboardFragment physicalKeyboardFragment,
@@ -532,43 +534,14 @@
         }
     }
 
-    public static List<InputDevice> getPhysicalFullKeyboards() {
-        List<InputDevice> keyboards = null;
-        for (final int deviceId : InputDevice.getDeviceIds()) {
-            final InputDevice device = InputDevice.getDevice(deviceId);
-            if (device != null && !device.isVirtual() && device.isFullKeyboard()) {
-                if (keyboards == null) keyboards = new ArrayList<>();
-                keyboards.add(device);
-            }
-        }
-        return (keyboards == null) ? Collections.emptyList() : keyboards;
-    }
-
     public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
             new BaseSearchIndexProvider() {
-        @Override
-        public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) {
-            final InputManager inputManager = (InputManager) context.getSystemService(
-                    Context.INPUT_SERVICE);
-            final String screenTitle = context.getString(R.string.physical_keyboard_title);
-            final List<SearchIndexableRaw> indexes = new ArrayList<>();
-            for (final InputDevice device : getPhysicalFullKeyboards()) {
-                final String keyboardLayoutDescriptor = inputManager
-                        .getCurrentKeyboardLayoutForInputDevice(device.getIdentifier());
-                final KeyboardLayout keyboardLayout = (keyboardLayoutDescriptor != null)
-                        ? inputManager.getKeyboardLayout(keyboardLayoutDescriptor) : null;
-                final String summary = (keyboardLayout != null)
-                        ? keyboardLayout.toString()
-                        : context.getString(R.string.keyboard_layout_default_label);
-                final SearchIndexableRaw index = new SearchIndexableRaw(context);
-                index.key = device.getName();
-                index.title = device.getName();
-                index.summaryOn = summary;
-                index.summaryOff = summary;
-                index.screenTitle = screenTitle;
-                indexes.add(index);
-            }
-            return indexes;
-        }
-    };
+                @Override
+                public List<SearchIndexableResource> getXmlResourcesToIndex(
+                        Context context, boolean enabled) {
+                    final SearchIndexableResource sir = new SearchIndexableResource(context);
+                    sir.xmlResId = R.xml.physical_keyboard_settings;
+                    return Arrays.asList(sir);
+                }
+            };
 }
diff --git a/src/com/android/settings/inputmethod/VirtualKeyboardFragment.java b/src/com/android/settings/inputmethod/VirtualKeyboardFragment.java
index 7b7c599..fbe9690 100644
--- a/src/com/android/settings/inputmethod/VirtualKeyboardFragment.java
+++ b/src/com/android/settings/inputmethod/VirtualKeyboardFragment.java
@@ -23,6 +23,7 @@
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
+import android.provider.SearchIndexableResource;
 import android.support.v7.preference.Preference;
 import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodManager;
@@ -33,14 +34,12 @@
 import com.android.settings.SettingsPreferenceFragment;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.search.Indexable;
-import com.android.settings.search.SearchIndexableRaw;
 import com.android.settingslib.inputmethod.InputMethodAndSubtypeUtil;
 import com.android.settingslib.inputmethod.InputMethodPreference;
 
 import java.text.Collator;
 import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
+import java.util.Arrays;
 import java.util.List;
 
 public final class VirtualKeyboardFragment extends SettingsPreferenceFragment implements Indexable {
@@ -121,13 +120,19 @@
 
     public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
             new BaseSearchIndexProvider() {
-        @Override
-        public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) {
-            final InputMethodManager imm = context.getSystemService(InputMethodManager.class);
-            final List<InputMethodInfo> enabledInputMethods = imm.getEnabledInputMethodList();
-            final String screenTitle = context.getString(R.string.virtual_keyboard_category);
-            return AvailableVirtualKeyboardFragment
-                    .buildSearchIndexOfInputMethods(context, enabledInputMethods, screenTitle);
-        }
-    };
+                @Override
+                public List<SearchIndexableResource> getXmlResourcesToIndex(
+                        Context context, boolean enabled) {
+                    final SearchIndexableResource sir = new SearchIndexableResource(context);
+                    sir.xmlResId = R.xml.virtual_keyboard_settings;
+                    return Arrays.asList(sir);
+                }
+
+                @Override
+                public List<String> getNonIndexableKeys(Context context) {
+                    final List<String> keys = super.getNonIndexableKeys(context);
+                    keys.add("add_virtual_keyboard_screen");
+                    return keys;
+                }
+            };
 }
diff --git a/src/com/android/settings/language/LanguageAndInputSettings.java b/src/com/android/settings/language/LanguageAndInputSettings.java
index fbcb02f..4affc6e 100644
--- a/src/com/android/settings/language/LanguageAndInputSettings.java
+++ b/src/com/android/settings/language/LanguageAndInputSettings.java
@@ -52,6 +52,7 @@
     private static final String TAG = "LangAndInputSettings";
 
     private static final String KEY_TEXT_TO_SPEECH = "tts_settings_summary";
+    private static final String KEY_PHYSICAL_KEYBOARD = "physical_keyboard_pref";
 
     @Override
     public int getMetricsCategory() {
@@ -174,6 +175,7 @@
                     List<String> keys = super.getNonIndexableKeys(context);
                     // Duplicates in summary and details pages.
                     keys.add(KEY_TEXT_TO_SPEECH);
+                    keys.add(KEY_PHYSICAL_KEYBOARD);
 
                     return keys;
                 }
diff --git a/src/com/android/settings/network/MobileNetworkPreferenceController.java b/src/com/android/settings/network/MobileNetworkPreferenceController.java
index d8b7745..6e2c2d5 100644
--- a/src/com/android/settings/network/MobileNetworkPreferenceController.java
+++ b/src/com/android/settings/network/MobileNetworkPreferenceController.java
@@ -33,7 +33,6 @@
 
 import static android.os.UserHandle.myUserId;
 import static android.os.UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS;
-import static com.android.settingslib.RestrictedLockUtils.hasBaseUserRestriction;
 
 public class MobileNetworkPreferenceController extends AbstractPreferenceController
         implements PreferenceControllerMixin, LifecycleObserver, OnResume, OnPause {
@@ -42,22 +41,30 @@
 
     private final boolean mIsSecondaryUser;
     private final TelephonyManager mTelephonyManager;
+    private final UserManager mUserManager;
     private Preference mPreference;
     @VisibleForTesting
     PhoneStateListener mPhoneStateListener;
 
     public MobileNetworkPreferenceController(Context context) {
         super(context);
-        UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+        mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
         mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
-        mIsSecondaryUser = !userManager.isAdminUser();
+        mIsSecondaryUser = !mUserManager.isAdminUser();
     }
 
     @Override
     public boolean isAvailable() {
-        return !mIsSecondaryUser
-                && !Utils.isWifiOnly(mContext)
-                && !hasBaseUserRestriction(mContext, DISALLOW_CONFIG_MOBILE_NETWORKS, myUserId());
+        return !isUserRestricted() && !Utils.isWifiOnly(mContext);
+    }
+
+    public boolean isUserRestricted() {
+        final RestrictedLockUtilsWrapper wrapper = new RestrictedLockUtilsWrapper();
+        return mIsSecondaryUser ||
+                wrapper.hasBaseUserRestriction(
+                        mContext,
+                        DISALLOW_CONFIG_MOBILE_NETWORKS,
+                        myUserId());
     }
 
     @Override
diff --git a/src/com/android/settings/network/RestrictedLockUtilsWrapper.java b/src/com/android/settings/network/RestrictedLockUtilsWrapper.java
new file mode 100644
index 0000000..de5b808
--- /dev/null
+++ b/src/com/android/settings/network/RestrictedLockUtilsWrapper.java
@@ -0,0 +1,15 @@
+package com.android.settings.network;
+
+import android.content.Context;
+import com.android.settingslib.RestrictedLockUtils;
+
+/**
+ * Wrapper class needed to be able to test classes which use RestrictedLockUtils methods.
+ * Unfortunately there is no way to deal with this until robolectric is updated due to the fact
+ * that it is a static method and it uses new API's.
+ */
+public class RestrictedLockUtilsWrapper {
+    public boolean hasBaseUserRestriction(Context context, String userRestriction, int userId) {
+        return RestrictedLockUtils.hasBaseUserRestriction(context, userRestriction, userId);
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/nfc/NfcEnabler.java b/src/com/android/settings/nfc/NfcEnabler.java
index 5bda1ad..14ee779 100644
--- a/src/com/android/settings/nfc/NfcEnabler.java
+++ b/src/com/android/settings/nfc/NfcEnabler.java
@@ -98,6 +98,7 @@
         // Turn NFC on/off
 
         final boolean desiredState = (Boolean) value;
+        mSwitch.setChecked(desiredState);
         mSwitch.setEnabled(false);
 
         if (desiredState) {
diff --git a/src/com/android/settings/nfc/NfcPaymentPreference.java b/src/com/android/settings/nfc/NfcPaymentPreference.java
index 239377d..a3f7466 100644
--- a/src/com/android/settings/nfc/NfcPaymentPreference.java
+++ b/src/com/android/settings/nfc/NfcPaymentPreference.java
@@ -18,6 +18,7 @@
 import android.app.AlertDialog;
 import android.content.ActivityNotFoundException;
 import android.content.Context;
+import android.app.Dialog;
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.support.v7.preference.PreferenceViewHolder;
@@ -209,7 +210,9 @@
             if (!appInfo.isDefault) {
                 mPaymentBackend.setDefaultPaymentApp(appInfo.componentName);
             }
-            getDialog().dismiss();
+            Dialog dialog = getDialog();
+            if (dialog != null)
+                dialog.dismiss();
         }
     }
 }
diff --git a/src/com/android/settings/notification/ChannelNotificationSettings.java b/src/com/android/settings/notification/ChannelNotificationSettings.java
index fa6c8ee..2f95dd2 100644
--- a/src/com/android/settings/notification/ChannelNotificationSettings.java
+++ b/src/com/android/settings/notification/ChannelNotificationSettings.java
@@ -351,7 +351,9 @@
         if (mRingtone != null) {
             mRingtone.onActivityResult(requestCode, resultCode, data);
         }
-        mImportance.setSummary(getImportanceSummary(mChannel.getImportance()));
+        if (mChannel != null) {
+            mImportance.setSummary(getImportanceSummary(mChannel.getImportance()));
+        }
     }
 
     boolean canPulseLight() {
diff --git a/src/com/android/settings/notification/VolumeSeekBarPreference.java b/src/com/android/settings/notification/VolumeSeekBarPreference.java
index 1428116..89f1e27 100644
--- a/src/com/android/settings/notification/VolumeSeekBarPreference.java
+++ b/src/com/android/settings/notification/VolumeSeekBarPreference.java
@@ -21,6 +21,7 @@
 import android.media.AudioManager;
 import android.net.Uri;
 import android.preference.SeekBarVolumizer;
+import android.support.annotation.VisibleForTesting;
 import android.support.v7.preference.PreferenceViewHolder;
 import android.text.TextUtils;
 import android.util.AttributeSet;
@@ -51,30 +52,38 @@
     private int mIconResId;
     private int mMuteIconResId;
     private boolean mStopped;
+    @VisibleForTesting
+    AudioManager mAudioManager;
 
     public VolumeSeekBarPreference(Context context, AttributeSet attrs, int defStyleAttr,
             int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
         setLayoutResource(R.layout.preference_volume_slider);
+        mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
     }
 
     public VolumeSeekBarPreference(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
         setLayoutResource(R.layout.preference_volume_slider);
+        mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
     }
 
     public VolumeSeekBarPreference(Context context, AttributeSet attrs) {
         super(context, attrs);
         setLayoutResource(R.layout.preference_volume_slider);
+        mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
     }
 
     public VolumeSeekBarPreference(Context context) {
         super(context);
         setLayoutResource(R.layout.preference_volume_slider);
+        mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
     }
 
     public void setStream(int stream) {
         mStream = stream;
+        setMax(mAudioManager.getStreamMaxVolume(mStream));
+        setProgress(mAudioManager.getStreamVolume(mStream));
     }
 
     public void setCallback(Callback callback) {
diff --git a/src/com/android/settings/password/ChooseLockGeneric.java b/src/com/android/settings/password/ChooseLockGeneric.java
index 4d20bcf..5126727 100644
--- a/src/com/android/settings/password/ChooseLockGeneric.java
+++ b/src/com/android/settings/password/ChooseLockGeneric.java
@@ -219,7 +219,7 @@
             mManagedPasswordProvider = ManagedLockPasswordProvider.get(getActivity(), mUserId);
 
             if (mPasswordConfirmed) {
-                updatePreferencesOrFinish();
+                updatePreferencesOrFinish(savedInstanceState != null);
                 if (mForChangeCredRequiredForBoot) {
                     maybeEnableEncryption(mLockPatternUtils.getKeyguardStoredPasswordQuality(
                             mUserId), false);
@@ -234,7 +234,7 @@
                         || !helper.launchConfirmationActivity(CONFIRM_EXISTING_REQUEST,
                         getString(R.string.unlock_set_unlock_launch_picker_title), true, mUserId)) {
                     mPasswordConfirmed = true; // no password set, so no need to confirm
-                    updatePreferencesOrFinish();
+                    updatePreferencesOrFinish(savedInstanceState != null);
                 } else {
                     mWaitingForConfirmation = true;
                 }
@@ -332,7 +332,7 @@
             if (requestCode == CONFIRM_EXISTING_REQUEST && resultCode == Activity.RESULT_OK) {
                 mPasswordConfirmed = true;
                 mUserPassword = data.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
-                updatePreferencesOrFinish();
+                updatePreferencesOrFinish(false /* isRecreatingActivity */);
                 if (mForChangeCredRequiredForBoot) {
                     if (!TextUtils.isEmpty(mUserPassword)) {
                         maybeEnableEncryption(
@@ -395,7 +395,7 @@
             outState.putBoolean(ENCRYPT_REQUESTED_DISABLED, mEncryptionRequestDisabled);
         }
 
-        private void updatePreferencesOrFinish() {
+        private void updatePreferencesOrFinish(boolean isRecreatingActivity) {
             Intent intent = getActivity().getIntent();
             int quality = intent.getIntExtra(LockPatternUtils.PASSWORD_TYPE_KEY, -1);
             if (quality == -1) {
@@ -413,7 +413,8 @@
                 updatePreferenceText();
                 updateCurrentPreference();
                 updatePreferenceSummaryIfNeeded();
-            } else {
+            } else if (!isRecreatingActivity) {
+                // Don't start the activity again if we are recreated for configuration change
                 updateUnlockMethodAndFinish(quality, false, true /* chooseLockSkipped */);
             }
         }
diff --git a/src/com/android/settings/password/ChooseLockPassword.java b/src/com/android/settings/password/ChooseLockPassword.java
index e013b8b..d890956 100644
--- a/src/com/android/settings/password/ChooseLockPassword.java
+++ b/src/com/android/settings/password/ChooseLockPassword.java
@@ -162,7 +162,7 @@
                 .getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false);
         CharSequence msg = getText(forFingerprint
                 ? R.string.lockpassword_choose_your_password_header_for_fingerprint
-                : R.string.lockpassword_choose_your_password_header);
+                : R.string.lockpassword_choose_your_screen_lock_header);
         setTitle(msg);
         LinearLayout layout = (LinearLayout) findViewById(R.id.content_parent);
         layout.setFitsSystemWindows(false);
@@ -213,6 +213,7 @@
         protected Button mCancelButton;
         private Button mClearButton;
         private Button mNextButton;
+        private TextView mMessage;
 
         private TextChangedHandler mTextChangedHandler;
 
@@ -247,10 +248,14 @@
         protected enum Stage {
 
             Introduction(
-                    R.string.lockpassword_choose_your_password_header,
+                    R.string.lockpassword_choose_your_screen_lock_header,
                     R.string.lockpassword_choose_your_password_header_for_fingerprint,
-                    R.string.lockpassword_choose_your_pin_header,
+                    R.string.lockpassword_choose_your_screen_lock_header,
                     R.string.lockpassword_choose_your_pin_header_for_fingerprint,
+                    R.string.lockpassword_choose_your_password_message,
+                    R.string.lock_settings_picker_fingerprint_added_security_message,
+                    R.string.lockpassword_choose_your_pin_message,
+                    R.string.lock_settings_picker_fingerprint_added_security_message,
                     R.string.next_label),
 
             NeedToConfirm(
@@ -258,6 +263,10 @@
                     R.string.lockpassword_confirm_your_password_header,
                     R.string.lockpassword_confirm_your_pin_header,
                     R.string.lockpassword_confirm_your_pin_header,
+                    0,
+                    0,
+                    0,
+                    0,
                     R.string.lockpassword_ok_label),
 
             ConfirmWrong(
@@ -265,14 +274,25 @@
                     R.string.lockpassword_confirm_passwords_dont_match,
                     R.string.lockpassword_confirm_pins_dont_match,
                     R.string.lockpassword_confirm_pins_dont_match,
+                    0,
+                    0,
+                    0,
+                    0,
                     R.string.next_label);
 
             Stage(int hintInAlpha, int hintInAlphaForFingerprint,
-                    int hintInNumeric, int hintInNumericForFingerprint, int nextButtonText) {
+                    int hintInNumeric, int hintInNumericForFingerprint,
+                    int messageInAlpha, int messageInAlphaForFingerprint,
+                    int messageInNumeric, int messageInNumericForFingerprint,
+                    int nextButtonText) {
                 this.alphaHint = hintInAlpha;
                 this.alphaHintForFingerprint = hintInAlphaForFingerprint;
                 this.numericHint = hintInNumeric;
                 this.numericHintForFingerprint = hintInNumericForFingerprint;
+                this.alphaMessage = messageInAlpha;
+                this.alphaMessageForFingerprint = messageInAlphaForFingerprint;
+                this.numericMessage = messageInNumeric;
+                this.numericMessageForFingerprint = messageInNumericForFingerprint;
                 this.buttonText = nextButtonText;
             }
 
@@ -280,6 +300,10 @@
             public final int alphaHintForFingerprint;
             public final int numericHint;
             public final int numericHintForFingerprint;
+            public final int alphaMessage;
+            public final int alphaMessageForFingerprint;
+            public final int numericMessage;
+            public final int numericMessageForFingerprint;
             public final int buttonText;
 
             public @StringRes int getHint(boolean isAlpha, boolean isFingerprint) {
@@ -289,6 +313,14 @@
                     return isFingerprint ? numericHintForFingerprint : numericHint;
                 }
             }
+
+            public @StringRes int getMessage(boolean isAlpha, boolean isFingerprint) {
+                if (isAlpha) {
+                    return isFingerprint ? alphaMessageForFingerprint : alphaMessage;
+                } else {
+                    return isFingerprint ? numericMessageForFingerprint : numericMessage;
+                }
+            }
         }
 
         // required constructor for fragments
@@ -351,14 +383,9 @@
             mClearButton = view.findViewById(R.id.clear_button);
             mClearButton.setOnClickListener(this);
 
+
+            mMessage = view.findViewById(R.id.message);
             if (mForFingerprint) {
-                TextView fingerprintBackupMessage =
-                        view.findViewById(R.id.fingerprint_backup_message);
-                if (fingerprintBackupMessage != null) {
-                    fingerprintBackupMessage.setVisibility(View.VISIBLE);
-                    fingerprintBackupMessage
-                            .setText(R.string.setup_lock_settings_picker_fingerprint_message);
-                }
                 mLayout.setIcon(getActivity().getDrawable(R.drawable.ic_fingerprint_header));
             }
 
@@ -848,6 +875,13 @@
                 setNextEnabled(canInput && length > 0);
                 mClearButton.setEnabled(canInput && length > 0);
             }
+            int message = mUiStage.getMessage(mIsAlphaMode, mForFingerprint);
+            if (message != 0) {
+                mMessage.setVisibility(View.VISIBLE);
+                mMessage.setText(message);
+            } else {
+                mMessage.setVisibility(View.INVISIBLE);
+            }
 
             mClearButton.setVisibility(toVisibility(mUiStage != Stage.Introduction));
             mCancelButton.setVisibility(toVisibility(mUiStage == Stage.Introduction));
diff --git a/src/com/android/settings/search/DynamicIndexableContentMonitor.java b/src/com/android/settings/search/DynamicIndexableContentMonitor.java
deleted file mode 100644
index a0e3c02..0000000
--- a/src/com/android/settings/search/DynamicIndexableContentMonitor.java
+++ /dev/null
@@ -1,415 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.search;
-
-import android.accessibilityservice.AccessibilityService;
-import android.app.Activity;
-import android.app.LoaderManager;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.Loader;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.pm.ServiceInfo;
-import android.database.ContentObserver;
-import android.hardware.input.InputManager;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.print.PrintManager;
-import android.print.PrintServicesLoader;
-import android.printservice.PrintServiceInfo;
-import android.provider.Settings;
-import android.provider.UserDictionary;
-import android.support.annotation.Nullable;
-import android.support.annotation.VisibleForTesting;
-import android.util.Log;
-import android.view.inputmethod.InputMethod;
-import android.view.inputmethod.InputMethodInfo;
-import android.view.inputmethod.InputMethodManager;
-
-import com.android.internal.content.PackageMonitor;
-import com.android.settings.inputmethod.AvailableVirtualKeyboardFragment;
-import com.android.settings.inputmethod.PhysicalKeyboardFragment;
-import com.android.settings.inputmethod.VirtualKeyboardFragment;
-import com.android.settings.language.LanguageAndInputSettings;
-import com.android.settings.overlay.FeatureFactory;
-import com.android.settings.print.PrintSettingsFragment;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public final class DynamicIndexableContentMonitor implements
-        LoaderManager.LoaderCallbacks<List<PrintServiceInfo>> {
-    // Shorten the class name because log TAG can be at most 23 chars.
-    private static final String TAG = "DynamicContentMonitor";
-
-    private static final long DELAY_PROCESS_PACKAGE_CHANGE = 2000;
-    // A PackageMonitor shared among Settings activities.
-    private static final PackageChangeMonitor PACKAGE_CHANGE_MONITOR = new PackageChangeMonitor();
-
-    // Null if not initialized.
-    @Nullable private DatabaseIndexingManager mIndexManager;
-    private Context mContext;
-    private boolean mHasFeaturePrinting;
-
-    @VisibleForTesting
-    static Intent getAccessibilityServiceIntent(String packageName) {
-        final Intent intent = new Intent(AccessibilityService.SERVICE_INTERFACE);
-        intent.setPackage(packageName);
-        return intent;
-    }
-
-    @VisibleForTesting
-    static Intent getIMEServiceIntent(String packageName) {
-        final Intent intent = new Intent(InputMethod.SERVICE_INTERFACE);
-        intent.setPackage(packageName);
-        return intent;
-    }
-
-    @VisibleForTesting
-    static void resetForTesting() {
-        InputDevicesMonitor.getInstance().resetForTesting();
-        InputMethodServicesMonitor.getInstance().resetForTesting();
-    }
-
-    /**
-     * This instance holds a set of content monitor singleton objects.
-     *
-     * This object is created every time a sub-settings that extends {@code SettingsActivity}
-     * is created.
-     */
-    public DynamicIndexableContentMonitor() {}
-
-    /**
-     * Creates and initializes a set of content monitor singleton objects if not yet exist.
-     * Also starts loading the list of print services.
-     * <code>mIndex</code> has non-null value after successfully initialized.
-     *
-     * @param activity used to get {@link LoaderManager}.
-     * @param loaderId id for loading print services.
-     */
-    public void register(Activity activity, int loaderId) {
-        final boolean isUserUnlocked = activity
-                .getSystemService(UserManager.class)
-                .isUserUnlocked();
-        register(activity, loaderId, FeatureFactory.getFactory(activity)
-                        .getSearchFeatureProvider().getIndexingManager(activity), isUserUnlocked);
-    }
-
-    /**
-     * For testing to inject {@link DatabaseIndexingManager} object.
-     * Also because currently Robolectric doesn't support API 24, we can not test code that calls
-     * {@link UserManager#isUserUnlocked()}.
-     */
-    @VisibleForTesting
-    void register(Activity activity, int loaderId, DatabaseIndexingManager indexManager,
-                  boolean isUserUnlocked) {
-        if (!isUserUnlocked) {
-            Log.w(TAG, "Skipping content monitoring because user is locked");
-            return;
-        }
-        final Context context = activity.getApplicationContext();
-        mContext = context;
-        mIndexManager = indexManager;
-
-        PACKAGE_CHANGE_MONITOR.registerMonitor(context);
-        mHasFeaturePrinting = context.getPackageManager()
-                .hasSystemFeature(PackageManager.FEATURE_PRINTING);
-        if (mHasFeaturePrinting) {
-            activity.getLoaderManager().initLoader(loaderId, null /* args */, this /* callbacks */);
-        }
-
-        // Watch for input device changes.
-        InputDevicesMonitor.getInstance().initialize(context, mIndexManager);
-
-        // Start tracking packages.
-        InputMethodServicesMonitor.getInstance().initialize(context, mIndexManager);
-    }
-
-    /**
-     * Aborts loading the list of print services.
-     * Note that a set of content monitor singletons keep alive while Settings app is running.
-     *
-     * @param activity user to get {@link LoaderManager}.
-     * @param loaderId id for loading print services.
-     */
-    public void unregister(Activity activity, int loaderId) {
-        if (mIndexManager == null) return;
-
-        PACKAGE_CHANGE_MONITOR.unregisterMonitor();
-        if (mHasFeaturePrinting) {
-            activity.getLoaderManager().destroyLoader(loaderId);
-        }
-    }
-
-    @Override
-    public Loader<List<PrintServiceInfo>> onCreateLoader(int id, Bundle args) {
-        return new PrintServicesLoader(
-                (PrintManager) mContext.getSystemService(Context.PRINT_SERVICE), mContext,
-                PrintManager.ALL_SERVICES);
-    }
-
-    @Override
-    public void onLoadFinished(Loader<List<PrintServiceInfo>> loader,
-            List<PrintServiceInfo> services) {
-        mIndexManager.updateFromClassNameResource(PrintSettingsFragment.class.getName(),
-                true /* includeInSearchResults */);
-    }
-
-    @Override
-    public void onLoaderReset(Loader<List<PrintServiceInfo>> loader) {
-        // nothing to do
-    }
-
-    // A singleton that monitors input devices changes and updates indexes of physical keyboards.
-    private static class InputDevicesMonitor implements InputManager.InputDeviceListener {
-
-        // Null if not initialized.
-        @Nullable private DatabaseIndexingManager mIndexManager;
-        private InputManager mInputManager;
-
-        private InputDevicesMonitor() {}
-
-        private static class SingletonHolder {
-            private static final InputDevicesMonitor INSTANCE = new InputDevicesMonitor();
-        }
-
-        static InputDevicesMonitor getInstance() {
-            return SingletonHolder.INSTANCE;
-        }
-
-        @VisibleForTesting
-        synchronized void resetForTesting() {
-            if (mIndexManager != null) {
-                mInputManager.unregisterInputDeviceListener(this /* listener */);
-            }
-            mIndexManager = null;
-        }
-
-        synchronized void initialize(Context context, DatabaseIndexingManager indexManager) {
-            if (mIndexManager != null) return;
-            mIndexManager = indexManager;
-            mInputManager = (InputManager) context.getSystemService(Context.INPUT_SERVICE);
-            buildIndex();
-
-            // Watch for input device changes.
-            mInputManager.registerInputDeviceListener(this /* listener */, null /* handler */);
-        }
-
-        private void buildIndex() {
-            mIndexManager.updateFromClassNameResource(PhysicalKeyboardFragment.class.getName(),
-                    true /* includeInSearchResults */);
-        }
-
-        @Override
-        public void onInputDeviceAdded(int deviceId) {
-            buildIndex();
-        }
-
-        @Override
-        public void onInputDeviceRemoved(int deviceId) {
-            buildIndex();
-        }
-
-        @Override
-        public void onInputDeviceChanged(int deviceId) {
-            buildIndex();
-        }
-    }
-
-    // A singleton that monitors package installing, uninstalling, enabling, and disabling.
-    // Then updates indexes of accessibility services and input methods.
-    private static class PackageChangeMonitor extends PackageMonitor {
-        private static final String TAG = PackageChangeMonitor.class.getSimpleName();
-
-        // Null if not initialized. Guarded by {@link #mLock}.
-        @Nullable private PackageManager mPackageManager;
-        private final Object mLock = new Object();
-
-        public void registerMonitor(Context context) {
-            synchronized (mLock) {
-                if (mPackageManager != null) {
-                    return;
-                }
-                mPackageManager = context.getPackageManager();
-
-                // Start tracking packages. Use background thread for monitoring. Note that no need
-                // to unregister this monitor. This should be alive while Settings app is running.
-                super.register(context, null /* thread */, UserHandle.CURRENT, false);
-            }
-        }
-
-        public void unregisterMonitor() {
-            synchronized (mLock) {
-                if (mPackageManager == null) {
-                    return;
-                }
-                super.unregister();
-                mPackageManager = null;
-            }
-        }
-
-        // Covers installed, appeared external storage with the package, upgraded.
-        @Override
-        public void onPackageAppeared(String packageName, int reason) {
-            postPackageAvailable(packageName);
-        }
-
-        // Covers uninstalled, removed external storage with the package.
-        @Override
-        public void onPackageDisappeared(String packageName, int reason) {
-            postPackageUnavailable(packageName);
-        }
-
-        // Covers enabled, disabled.
-        @Override
-        public void onPackageModified(String packageName) {
-            try {
-                final int state = mPackageManager.getApplicationEnabledSetting(packageName);
-                if (state == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
-                        || state == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
-                    postPackageAvailable(packageName);
-                } else {
-                    postPackageUnavailable(packageName);
-                }
-            } catch (IllegalArgumentException e) {
-                Log.e(TAG, "Package does not exist: " + packageName, e);
-            }
-        }
-
-        private void postPackageAvailable(final String packageName) {
-            getRegisteredHandler().postDelayed(() -> {
-                InputMethodServicesMonitor.getInstance().onPackageAvailable(packageName);
-            }, DELAY_PROCESS_PACKAGE_CHANGE);
-        }
-
-        private void postPackageUnavailable(final String packageName) {
-            getRegisteredHandler().postDelayed(() -> {
-                InputMethodServicesMonitor.getInstance().onPackageUnavailable(packageName);
-            }, DELAY_PROCESS_PACKAGE_CHANGE);
-        }
-    }
-
-    // A singleton that holds list of available input methods and updates search index.
-    // Also it monitors user dictionary changes and updates search index.
-    private static class InputMethodServicesMonitor extends ContentObserver {
-
-        private static final Uri ENABLED_INPUT_METHODS_CONTENT_URI =
-                Settings.Secure.getUriFor(Settings.Secure.ENABLED_INPUT_METHODS);
-
-        // Null if not initialized.
-        @Nullable private DatabaseIndexingManager mIndexManager;
-        private PackageManager mPackageManager;
-        private ContentResolver mContentResolver;
-        private final List<String> mInputMethodServices = new ArrayList<>();
-
-        private InputMethodServicesMonitor() {
-            // No need for handler because {@link #onChange(boolean,Uri)} is short and quick.
-            super(null /* handler */);
-        }
-
-        private static class SingletonHolder {
-            private static final InputMethodServicesMonitor INSTANCE =
-                    new InputMethodServicesMonitor();
-        }
-
-        static InputMethodServicesMonitor getInstance() {
-            return SingletonHolder.INSTANCE;
-        }
-
-        @VisibleForTesting
-        synchronized void resetForTesting() {
-            if (mIndexManager != null) {
-                mContentResolver.unregisterContentObserver(this /* observer */);
-            }
-            mIndexManager = null;
-        }
-
-        synchronized void initialize(Context context, DatabaseIndexingManager indexManager) {
-            final boolean hasFeatureIme = context.getPackageManager()
-                    .hasSystemFeature(PackageManager.FEATURE_INPUT_METHODS);
-            if (!hasFeatureIme) return;
-
-            if (mIndexManager != null) return;
-            mIndexManager = indexManager;
-            mPackageManager = context.getPackageManager();
-            mContentResolver = context.getContentResolver();
-            mInputMethodServices.clear();
-            // Build index of {@link UserDictionary}.
-            buildIndex(LanguageAndInputSettings.class);
-            // Build index of IMEs.
-            buildIndex(VirtualKeyboardFragment.class);
-            buildIndex(AvailableVirtualKeyboardFragment.class);
-
-            // Cache IME service packages to know when they go away.
-            final InputMethodManager inputMethodManager = (InputMethodManager) context
-                    .getSystemService(Context.INPUT_METHOD_SERVICE);
-            for (final InputMethodInfo inputMethod : inputMethodManager.getInputMethodList()) {
-                ServiceInfo serviceInfo = inputMethod.getServiceInfo();
-                if (serviceInfo != null) {
-                    mInputMethodServices.add(serviceInfo.packageName);
-                }
-            }
-
-            // TODO: Implements by JobScheduler with TriggerContentUri parameters.
-            // Watch for related content URIs.
-            mContentResolver.registerContentObserver(UserDictionary.Words.CONTENT_URI,
-                    true /* notifyForDescendants */, this /* observer */);
-            // Watch for changing enabled IMEs.
-            mContentResolver.registerContentObserver(ENABLED_INPUT_METHODS_CONTENT_URI,
-                    false /* notifyForDescendants */, this /* observer */);
-        }
-
-        private void buildIndex(Class<?> indexClass) {
-            mIndexManager.updateFromClassNameResource(indexClass.getName(),
-                    true /* includeInSearchResults */);
-        }
-
-        synchronized void onPackageAvailable(String packageName) {
-            if (mIndexManager == null) return;
-            if (mInputMethodServices.contains(packageName)) return;
-
-            final Intent intent = getIMEServiceIntent(packageName);
-            final List<ResolveInfo> services = mPackageManager
-                    .queryIntentServices(intent, 0 /* flags */);
-            if (services == null || services.isEmpty()) return;
-            mInputMethodServices.add(packageName);
-            buildIndex(VirtualKeyboardFragment.class);
-            buildIndex(AvailableVirtualKeyboardFragment.class);
-        }
-
-        synchronized void onPackageUnavailable(String packageName) {
-            if (mIndexManager == null) return;
-            if (!mInputMethodServices.remove(packageName)) return;
-            buildIndex(VirtualKeyboardFragment.class);
-            buildIndex(AvailableVirtualKeyboardFragment.class);
-        }
-
-        @Override
-        public void onChange(boolean selfChange, Uri uri) {
-            if (ENABLED_INPUT_METHODS_CONTENT_URI.equals(uri)) {
-                buildIndex(VirtualKeyboardFragment.class);
-                buildIndex(AvailableVirtualKeyboardFragment.class);
-            } else if (UserDictionary.Words.CONTENT_URI.equals(uri)) {
-                buildIndex(LanguageAndInputSettings.class);
-            }
-        }
-    }
-}
diff --git a/src/com/android/settings/search/InputDeviceResultLoader.java b/src/com/android/settings/search/InputDeviceResultLoader.java
new file mode 100644
index 0000000..61e1ad1
--- /dev/null
+++ b/src/com/android/settings/search/InputDeviceResultLoader.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2017 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.search;
+
+import static android.content.Context.INPUT_METHOD_SERVICE;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ServiceInfo;
+import android.hardware.input.InputManager;
+import android.hardware.input.KeyboardLayout;
+import android.support.annotation.VisibleForTesting;
+import android.view.InputDevice;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.settings.R;
+import com.android.settings.dashboard.SiteMapManager;
+import com.android.settings.inputmethod.AvailableVirtualKeyboardFragment;
+import com.android.settings.inputmethod.PhysicalKeyboardFragment;
+import com.android.settings.utils.AsyncLoader;
+import com.android.settingslib.inputmethod.InputMethodAndSubtypeUtil;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * Search result for input devices (physical/virtual keyboard, game controllers, etc)
+ */
+public class InputDeviceResultLoader extends AsyncLoader<Set<? extends SearchResult>> {
+    private static final int NAME_NO_MATCH = -1;
+
+    @VisibleForTesting
+    static final String PHYSICAL_KEYBOARD_FRAGMENT = PhysicalKeyboardFragment.class.getName();
+    @VisibleForTesting
+    static final String VIRTUAL_KEYBOARD_FRAGMENT =
+            AvailableVirtualKeyboardFragment.class.getName();
+
+    private final SiteMapManager mSiteMapManager;
+    private final InputManager mInputManager;
+    private final InputMethodManager mImm;
+    private final PackageManager mPackageManager;
+    @VisibleForTesting
+    final String mQuery;
+
+    private List<String> mPhysicalKeyboardBreadcrumb;
+    private List<String> mVirtualKeyboardBreadcrumb;
+
+    public InputDeviceResultLoader(Context context, String query, SiteMapManager mapManager) {
+        super(context);
+        mQuery = query;
+        mSiteMapManager = mapManager;
+        mInputManager = (InputManager) context.getSystemService(Context.INPUT_SERVICE);
+        mImm = (InputMethodManager) context.getSystemService(INPUT_METHOD_SERVICE);
+        mPackageManager = context.getPackageManager();
+    }
+
+    @Override
+    protected void onDiscardResult(Set<? extends SearchResult> result) {
+    }
+
+    @Override
+    public Set<? extends SearchResult> loadInBackground() {
+        final Set<SearchResult> results = new HashSet<>();
+        results.addAll(buildPhysicalKeyboardSearchResults());
+        results.addAll(buildVirtualKeyboardSearchResults());
+        return results;
+    }
+
+    private Set<SearchResult> buildPhysicalKeyboardSearchResults() {
+        final Set<SearchResult> results = new HashSet<>();
+        final Context context = getContext();
+        final String screenTitle = context.getString(R.string.physical_keyboard_title);
+
+        for (final InputDevice device : getPhysicalFullKeyboards()) {
+            final String deviceName = device.getName();
+            final int wordDiff = InstalledAppResultLoader.getWordDifference(deviceName, mQuery);
+            if (wordDiff == NAME_NO_MATCH) {
+                continue;
+            }
+            final String keyboardLayoutDescriptor = mInputManager
+                    .getCurrentKeyboardLayoutForInputDevice(device.getIdentifier());
+            final KeyboardLayout keyboardLayout = (keyboardLayoutDescriptor != null)
+                    ? mInputManager.getKeyboardLayout(keyboardLayoutDescriptor) : null;
+            final String summary = (keyboardLayout != null)
+                    ? keyboardLayout.toString()
+                    : context.getString(R.string.keyboard_layout_default_label);
+            final String key = deviceName;
+
+            final Intent intent = DatabaseIndexingUtils.buildSubsettingIntent(context,
+                    PHYSICAL_KEYBOARD_FRAGMENT, key, screenTitle);
+            results.add(new SearchResult.Builder()
+                    .setTitle(deviceName)
+                    .setPayload(new ResultPayload(intent))
+                    .setStableId(Objects.hash(PHYSICAL_KEYBOARD_FRAGMENT, key))
+                    .setSummary(summary)
+                    .setRank(wordDiff)
+                    .addBreadcrumbs(getPhysicalKeyboardBreadCrumb())
+                    .build());
+        }
+        return results;
+    }
+
+    private Set<SearchResult> buildVirtualKeyboardSearchResults() {
+        final Set<SearchResult> results = new HashSet<>();
+        final Context context = getContext();
+        final String screenTitle = context.getString(R.string.add_virtual_keyboard);
+        final List<InputMethodInfo> inputMethods = mImm.getInputMethodList();
+        for (InputMethodInfo info : inputMethods) {
+            final String title = info.loadLabel(mPackageManager).toString();
+            final String summary = InputMethodAndSubtypeUtil
+                    .getSubtypeLocaleNameListAsSentence(getAllSubtypesOf(info), context, info);
+            int wordDiff = InstalledAppResultLoader.getWordDifference(title, mQuery);
+            if (wordDiff == NAME_NO_MATCH) {
+                wordDiff = InstalledAppResultLoader.getWordDifference(summary, mQuery);
+            }
+            if (wordDiff == NAME_NO_MATCH) {
+                continue;
+            }
+            final ServiceInfo serviceInfo = info.getServiceInfo();
+            final String key = new ComponentName(serviceInfo.packageName, serviceInfo.name)
+                    .flattenToString();
+            final Intent intent = DatabaseIndexingUtils.buildSubsettingIntent(context,
+                    VIRTUAL_KEYBOARD_FRAGMENT, key, screenTitle);
+            results.add(new SearchResult.Builder()
+                    .setTitle(title)
+                    .setSummary(summary)
+                    .setRank(wordDiff)
+                    .setStableId(Objects.hash(VIRTUAL_KEYBOARD_FRAGMENT, key))
+                    .addBreadcrumbs(getVirtualKeyboardBreadCrumb())
+                    .setPayload(new ResultPayload(intent))
+                    .build());
+        }
+        return results;
+    }
+
+    private List<String> getPhysicalKeyboardBreadCrumb() {
+        if (mPhysicalKeyboardBreadcrumb == null || mPhysicalKeyboardBreadcrumb.isEmpty()) {
+            final Context context = getContext();
+            mPhysicalKeyboardBreadcrumb = mSiteMapManager.buildBreadCrumb(
+                    context, PHYSICAL_KEYBOARD_FRAGMENT,
+                    context.getString(R.string.physical_keyboard_title));
+        }
+        return mPhysicalKeyboardBreadcrumb;
+    }
+
+
+    private List<String> getVirtualKeyboardBreadCrumb() {
+        if (mVirtualKeyboardBreadcrumb == null || mVirtualKeyboardBreadcrumb.isEmpty()) {
+            final Context context = getContext();
+            mVirtualKeyboardBreadcrumb = mSiteMapManager.buildBreadCrumb(
+                    context, VIRTUAL_KEYBOARD_FRAGMENT,
+                    context.getString(R.string.add_virtual_keyboard));
+        }
+        return mVirtualKeyboardBreadcrumb;
+    }
+
+    private List<InputDevice> getPhysicalFullKeyboards() {
+        final List<InputDevice> keyboards = new ArrayList<>();
+        final int[] deviceIds = InputDevice.getDeviceIds();
+        if (deviceIds != null) {
+            for (int deviceId : deviceIds) {
+                final InputDevice device = InputDevice.getDevice(deviceId);
+                if (device != null && !device.isVirtual() && device.isFullKeyboard()) {
+                    keyboards.add(device);
+                }
+            }
+        }
+        return keyboards;
+    }
+
+    private static List<InputMethodSubtype> getAllSubtypesOf(final InputMethodInfo imi) {
+        final int subtypeCount = imi.getSubtypeCount();
+        final List<InputMethodSubtype> allSubtypes = new ArrayList<>(subtypeCount);
+        for (int index = 0; index < subtypeCount; index++) {
+            allSubtypes.add(imi.getSubtypeAt(index));
+        }
+        return allSubtypes;
+    }
+}
diff --git a/src/com/android/settings/search/SearchFeatureProvider.java b/src/com/android/settings/search/SearchFeatureProvider.java
index 7e0e086..900cefc 100644
--- a/src/com/android/settings/search/SearchFeatureProvider.java
+++ b/src/com/android/settings/search/SearchFeatureProvider.java
@@ -49,6 +49,11 @@
             String query);
 
     /**
+     * Returns a new loader to search input devices.
+     */
+    InputDeviceResultLoader getInputDeviceResultLoader(Context context, String query);
+
+    /**
      * Returns a new loader to get all recently saved queries search terms.
      */
     SavedQueryLoader getSavedQueryLoader(Context context);
diff --git a/src/com/android/settings/search/SearchFeatureProviderImpl.java b/src/com/android/settings/search/SearchFeatureProviderImpl.java
index b90547e..400cf8f 100644
--- a/src/com/android/settings/search/SearchFeatureProviderImpl.java
+++ b/src/com/android/settings/search/SearchFeatureProviderImpl.java
@@ -62,6 +62,11 @@
     }
 
     @Override
+    public InputDeviceResultLoader getInputDeviceResultLoader(Context context, String query) {
+        return new InputDeviceResultLoader(context, cleanQuery(query), getSiteMapManager());
+    }
+
+    @Override
     public SavedQueryLoader getSavedQueryLoader(Context context) {
         return new SavedQueryLoader(context);
     }
diff --git a/src/com/android/settings/search/SearchFragment.java b/src/com/android/settings/search/SearchFragment.java
index fb89d6e..ccc4d61 100644
--- a/src/com/android/settings/search/SearchFragment.java
+++ b/src/com/android/settings/search/SearchFragment.java
@@ -84,8 +84,10 @@
     static final int LOADER_ID_INSTALLED_APPS = 2;
     @VisibleForTesting
     static final int LOADER_ID_ACCESSIBILITY_SERVICES = 3;
+    @VisibleForTesting
+    static final int LOADER_ID_INPUT_DEVICES = 4;
 
-    private static final int NUM_QUERY_LOADERS = 3;
+    private static final int NUM_QUERY_LOADERS = 4;
 
     @VisibleForTesting
     AtomicInteger mUnfinishedLoadersCount = new AtomicInteger(NUM_QUERY_LOADERS);
@@ -284,6 +286,7 @@
             loaderManager.destroyLoader(LOADER_ID_DATABASE);
             loaderManager.destroyLoader(LOADER_ID_INSTALLED_APPS);
             loaderManager.destroyLoader(LOADER_ID_ACCESSIBILITY_SERVICES);
+            loaderManager.destroyLoader(LOADER_ID_INPUT_DEVICES);
             mShowingSavedQuery = true;
             mSavedQueryController.loadSavedQueries();
             mSearchFeatureProvider.hideFeedbackButton();
@@ -314,6 +317,8 @@
                 return mSearchFeatureProvider.getInstalledAppSearchLoader(activity, mQuery);
             case LOADER_ID_ACCESSIBILITY_SERVICES:
                 return mSearchFeatureProvider.getAccessibilityServiceResultLoader(activity, mQuery);
+            case LOADER_ID_INPUT_DEVICES:
+                return mSearchFeatureProvider.getInputDeviceResultLoader(activity, mQuery);
             default:
                 return null;
         }
@@ -351,6 +356,8 @@
                     LOADER_ID_INSTALLED_APPS, null /* args */, this /* callback */);
             loaderManager.initLoader(
                     LOADER_ID_ACCESSIBILITY_SERVICES, null /* args */, this /* callback */);
+            loaderManager.initLoader(
+                    LOADER_ID_INPUT_DEVICES, null /* args */, this /* callback */);
         }
 
         requery();
@@ -392,6 +399,8 @@
         loaderManager.restartLoader(LOADER_ID_INSTALLED_APPS, null /* args */, this /* callback */);
         loaderManager.restartLoader(LOADER_ID_ACCESSIBILITY_SERVICES, null /* args */,
                 this /* callback */);
+        loaderManager.restartLoader(LOADER_ID_INPUT_DEVICES, null /* args */,
+                this /* callback */);
     }
 
     public String getQuery() {
diff --git a/src/com/android/settings/search/SearchResultsAdapter.java b/src/com/android/settings/search/SearchResultsAdapter.java
index 6c58a0d..7b886a4 100644
--- a/src/com/android/settings/search/SearchResultsAdapter.java
+++ b/src/com/android/settings/search/SearchResultsAdapter.java
@@ -57,7 +57,9 @@
     @VisibleForTesting
     static final String APP_RESULTS_LOADER_KEY = InstalledAppResultLoader.class.getName();
     @VisibleForTesting
-    static final String ACCESSIBLITY_LOADER_KEY = AccessibilityServiceResultLoader.class.getName();
+    static final String ACCESSIBILITY_LOADER_KEY = AccessibilityServiceResultLoader.class.getName();
+    @VisibleForTesting
+    static final String INPUT_DEVICE_LOADER_KEY = InputDeviceResultLoader.class.getName();
 
     @VisibleForTesting
     static final int MSG_RANKING_TIMED_OUT = 1;
@@ -265,17 +267,21 @@
         List<? extends SearchResult> installedAppResults =
                 getSortedLoadedResults(APP_RESULTS_LOADER_KEY);
         List<? extends SearchResult> accessibilityResults =
-                getSortedLoadedResults(ACCESSIBLITY_LOADER_KEY);
+                getSortedLoadedResults(ACCESSIBILITY_LOADER_KEY);
+        List<? extends SearchResult> inputDeviceResults =
+                getSortedLoadedResults(INPUT_DEVICE_LOADER_KEY);
 
         int dbSize = databaseResults.size();
         int appSize = installedAppResults.size();
         int a11ySize = accessibilityResults.size();
-
+        int inputDeviceSize = inputDeviceResults.size();
         int dbIndex = 0;
         int appIndex = 0;
         int a11yIndex = 0;
+        int inputDeviceIndex = 0;
         int rank = SearchResult.TOP_RANK;
 
+        // TODO: We need a helper method to do k-way merge.
         mStaticallyRankedSearchResults.clear();
         while (rank <= SearchResult.BOTTOM_RANK) {
             while ((dbIndex < dbSize) && (databaseResults.get(dbIndex).rank == rank)) {
@@ -287,6 +293,10 @@
             while ((a11yIndex < a11ySize) && (accessibilityResults.get(a11yIndex).rank == rank)) {
                 mStaticallyRankedSearchResults.add(accessibilityResults.get(a11yIndex++));
             }
+            while (inputDeviceIndex < inputDeviceSize
+                    && inputDeviceResults.get(inputDeviceIndex).rank == rank) {
+                mStaticallyRankedSearchResults.add(inputDeviceResults.get(inputDeviceIndex++));
+            }
             rank++;
         }
 
@@ -299,6 +309,9 @@
         while(a11yIndex < a11ySize) {
             mStaticallyRankedSearchResults.add(accessibilityResults.get(a11yIndex++));
         }
+        while (inputDeviceIndex < inputDeviceSize) {
+            mStaticallyRankedSearchResults.add(inputDeviceResults.get(inputDeviceIndex++));
+        }
     }
 
     private void updateSearchResults() {
@@ -332,12 +345,16 @@
         List<? extends SearchResult> installedAppResults =
                 getSortedLoadedResults(APP_RESULTS_LOADER_KEY);
         List<? extends SearchResult> accessibilityResults =
-                getSortedLoadedResults(ACCESSIBLITY_LOADER_KEY);
+                getSortedLoadedResults(ACCESSIBILITY_LOADER_KEY);
+        List<? extends SearchResult> inputDeviceResults =
+                getSortedLoadedResults(INPUT_DEVICE_LOADER_KEY);
         int dbSize = databaseResults.size();
         int appSize = installedAppResults.size();
         int a11ySize = accessibilityResults.size();
+        int inputDeviceSize = inputDeviceResults.size();
 
-        final List<SearchResult> asyncRankingResults = new ArrayList<>(dbSize + appSize + a11ySize);
+        final List<SearchResult> asyncRankingResults = new ArrayList<>(
+                dbSize + appSize + a11ySize + inputDeviceSize);
         TreeSet<SearchResult> dbResultsSortedByScores = new TreeSet<>(
                 new Comparator<SearchResult>() {
                     @Override
@@ -358,13 +375,13 @@
         // Other results are not ranked by async ranking and appended at the end of the list.
         asyncRankingResults.addAll(installedAppResults);
         asyncRankingResults.addAll(accessibilityResults);
+        asyncRankingResults.addAll(inputDeviceResults);
         return asyncRankingResults;
     }
 
     @VisibleForTesting
     Set<? extends SearchResult> getUnsortedLoadedResults(String loaderKey) {
-        return mResultsMap.containsKey(loaderKey) ?
-                mResultsMap.get(loaderKey) : new HashSet<SearchResult>();
+        return mResultsMap.containsKey(loaderKey) ? mResultsMap.get(loaderKey) : new HashSet<>();
     }
 
     @VisibleForTesting
diff --git a/tests/robotests/src/com/android/settings/SetupChooseLockPatternTest.java b/tests/robotests/src/com/android/settings/SetupChooseLockPatternTest.java
index 78bc7d1..69a1351 100644
--- a/tests/robotests/src/com/android/settings/SetupChooseLockPatternTest.java
+++ b/tests/robotests/src/com/android/settings/SetupChooseLockPatternTest.java
@@ -30,7 +30,6 @@
 import com.android.settings.password.SetupChooseLockPattern;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.testutils.shadow.SettingsShadowResources;
-import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
 import com.android.settings.testutils.shadow.ShadowEventLogWriter;
 import com.android.settings.testutils.shadow.ShadowUtils;
 
@@ -49,7 +48,6 @@
         shadows = {
                 SettingsShadowResources.class,
                 SettingsShadowResources.SettingsShadowTheme.class,
-                ShadowDynamicIndexableContentMonitor.class,
                 ShadowEventLogWriter.class,
                 ShadowUtils.class
         })
diff --git a/tests/robotests/src/com/android/settings/applications/ManageApplicationsTest.java b/tests/robotests/src/com/android/settings/applications/ManageApplicationsTest.java
index 92aa675..8ed7284 100644
--- a/tests/robotests/src/com/android/settings/applications/ManageApplicationsTest.java
+++ b/tests/robotests/src/com/android/settings/applications/ManageApplicationsTest.java
@@ -16,6 +16,17 @@
 
 package com.android.settings.applications;
 
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
 import android.app.Activity;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
@@ -35,7 +46,6 @@
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.testutils.shadow.SettingsShadowResources;
 import com.android.settings.testutils.shadow.SettingsShadowResources.SettingsShadowTheme;
-import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
 import com.android.settings.testutils.shadow.ShadowEventLogWriter;
 import com.android.settings.widget.LoadingViewController;
 import com.android.settingslib.applications.ApplicationsState;
@@ -53,17 +63,6 @@
 
 import java.util.ArrayList;
 
-import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
 /**
  * Tests for {@link ManageApplications}.
  */
@@ -74,7 +73,6 @@
         shadows = {
                 SettingsShadowResources.class,
                 SettingsShadowTheme.class,
-                ShadowDynamicIndexableContentMonitor.class,
                 ShadowEventLogWriter.class
         })
 public class ManageApplicationsTest {
diff --git a/tests/robotests/src/com/android/settings/bluetooth/AlwaysDiscoverableTest.java b/tests/robotests/src/com/android/settings/bluetooth/AlwaysDiscoverableTest.java
new file mode 100644
index 0000000..fd46b4b
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/bluetooth/AlwaysDiscoverableTest.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settings.bluetooth;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.bluetooth.BluetoothAdapter;
+import android.content.Context;
+import android.content.Intent;
+
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class AlwaysDiscoverableTest {
+    @Mock
+    private LocalBluetoothAdapter mLocalAdapter;
+
+    @Mock
+    private Context mContext;
+
+    private AlwaysDiscoverable mAlwaysDiscoverable;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mAlwaysDiscoverable = new AlwaysDiscoverable(mContext, mLocalAdapter);
+    }
+
+    @Test
+    public void isStartedWithoutStart() {
+        assertThat(mAlwaysDiscoverable.mStarted).isFalse();
+    }
+
+    @Test
+    public void isStartedWithStart() {
+        mAlwaysDiscoverable.start();
+        assertThat(mAlwaysDiscoverable.mStarted).isTrue();
+    }
+
+    @Test
+    public void isStartedWithStartStop() {
+        mAlwaysDiscoverable.start();
+        mAlwaysDiscoverable.stop();
+        assertThat(mAlwaysDiscoverable.mStarted).isFalse();
+    }
+
+    @Test
+    public void stopWithoutStart() {
+        mAlwaysDiscoverable.stop();
+        // expect no crash
+        verify(mLocalAdapter, never()).setScanMode(anyInt());
+    }
+
+    @Test
+    public void startSetsModeAndRegistersReceiver() {
+        when(mLocalAdapter.getScanMode()).thenReturn(BluetoothAdapter.SCAN_MODE_NONE);
+        mAlwaysDiscoverable.start();
+        verify(mLocalAdapter).setScanMode(eq(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE));
+        verify(mContext).registerReceiver(eq(mAlwaysDiscoverable), any());
+    }
+
+    @Test
+    public void stopUnregistersReceiver() {
+        mAlwaysDiscoverable.start();
+        mAlwaysDiscoverable.stop();
+        verify(mContext).unregisterReceiver(mAlwaysDiscoverable);
+    }
+
+    @Test
+    public void resetsToDiscoverableModeWhenScanModeChanges() {
+        mAlwaysDiscoverable.start();
+        verify(mLocalAdapter, times(1)).setScanMode(
+                BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
+
+        sendScanModeChangedIntent(BluetoothAdapter.SCAN_MODE_CONNECTABLE,
+                BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
+
+        verify(mLocalAdapter, times(2)).setScanMode(
+                BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
+    }
+
+    private void sendScanModeChangedIntent(int newMode, int previousMode) {
+        when(mLocalAdapter.getScanMode()).thenReturn(newMode);
+        Intent intent = new Intent(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
+        intent.putExtra(BluetoothAdapter.EXTRA_SCAN_MODE, newMode);
+        intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_SCAN_MODE, previousMode);
+        mAlwaysDiscoverable.onReceive(mContext, intent);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingDetailTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingDetailTest.java
index c4772e5..d1d4935 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingDetailTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingDetailTest.java
@@ -85,6 +85,7 @@
         mFragment.mLocalAdapter = mLocalAdapter;
         mFragment.mLocalManager = mLocalManager;
         mFragment.mDeviceListGroup = mPreferenceGroup;
+        mFragment.mAlwaysDiscoverable = new AlwaysDiscoverable(mContext, mLocalAdapter);
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingDialogTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingDialogTest.java
index 7a6ae79..fba11de 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingDialogTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingDialogTest.java
@@ -28,6 +28,7 @@
 import static org.mockito.Mockito.when;
 
 import android.app.AlertDialog;
+import android.app.Dialog;
 import android.content.Context;
 import android.text.SpannableStringBuilder;
 import android.text.TextUtils;
@@ -47,6 +48,7 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowAlertDialog;
 import org.robolectric.shadows.ShadowApplication;
 import org.robolectric.util.FragmentTestUtil;
 
@@ -412,6 +414,39 @@
         verify(dialogActivity, times(1)).dismiss();
     }
 
+    @Test
+    public void rotateDialog_nullPinText_okButtonEnabled() {
+        userEntryDialogExistingTextTest(null);
+    }
+
+    @Test
+    public void rotateDialog_emptyPinText_okButtonEnabled() {
+        userEntryDialogExistingTextTest("");
+    }
+
+    @Test
+    public void rotateDialog_nonEmptyPinText_okButtonEnabled() {
+        userEntryDialogExistingTextTest("test");
+    }
+
+    // Runs a test simulating the user entry dialog type in a situation like device rotation, where
+    // the dialog fragment gets created and we already have some existing text entered into the
+    // pin field.
+    private void userEntryDialogExistingTextTest(CharSequence existingText) {
+        when(controller.getDialogType()).thenReturn(BluetoothPairingController.USER_ENTRY_DIALOG);
+        when(controller.getDeviceVariantMessageHintId())
+                .thenReturn(BluetoothPairingController.INVALID_DIALOG_TYPE);
+        when(controller.getDeviceVariantMessageId())
+                .thenReturn(BluetoothPairingController.INVALID_DIALOG_TYPE);
+
+        BluetoothPairingDialogFragment fragment = spy(new BluetoothPairingDialogFragment());
+        when(fragment.getPairingViewText()).thenReturn(existingText);
+        setupFragment(fragment);
+        AlertDialog dialog = ShadowAlertDialog.getLatestAlertDialog();
+        boolean expected = !TextUtils.isEmpty(existingText);
+        assertThat(dialog.getButton(Dialog.BUTTON_POSITIVE).isEnabled()).isEqualTo(expected);
+    }
+
     private void setupFragment(BluetoothPairingDialogFragment frag) {
         assertThat(frag.isPairingControllerSet()).isFalse();
         frag.setPairingController(controller);
diff --git a/tests/robotests/src/com/android/settings/core/instrumentation/SharedPreferenceLoggerTest.java b/tests/robotests/src/com/android/settings/core/instrumentation/SharedPreferenceLoggerTest.java
index ec644a6..bb41cf0 100644
--- a/tests/robotests/src/com/android/settings/core/instrumentation/SharedPreferenceLoggerTest.java
+++ b/tests/robotests/src/com/android/settings/core/instrumentation/SharedPreferenceLoggerTest.java
@@ -39,7 +39,7 @@
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent
         .FIELD_SETTINGS_PREFERENCE_CHANGE_FLOAT_VALUE;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent
-        .FIELD_SETTINGS_PREFERENCE_CHANGE_LONG_VALUE;
+        .FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent
         .FIELD_SETTINGS_PREFERENCE_CHANGE_NAME;
 import static org.mockito.Matchers.any;
@@ -88,7 +88,7 @@
 
         verify(mMetricsFeature, times(6)).action(any(Context.class), anyInt(),
                 argThat(mNamePairMatcher),
-                argThat(pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_LONG_VALUE, Long.class)));
+                argThat(pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE, Integer.class)));
     }
 
     @Test
@@ -103,10 +103,10 @@
 
         verify(mMetricsFeature).action(any(Context.class), anyInt(),
                 argThat(mNamePairMatcher),
-                argThat(pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_LONG_VALUE, true)));
+                argThat(pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE, true)));
         verify(mMetricsFeature, times(3)).action(any(Context.class), anyInt(),
                 argThat(mNamePairMatcher),
-                argThat(pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_LONG_VALUE, false)));
+                argThat(pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE, false)));
     }
 
     @Test
@@ -120,7 +120,33 @@
 
         verify(mMetricsFeature, times(4)).action(any(Context.class), anyInt(),
                 argThat(mNamePairMatcher),
-                argThat(pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_LONG_VALUE, Long.class)));
+                argThat(pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE, Integer.class)));
+    }
+
+    @Test
+    public void putLong_biggerThanIntMax_shouldLogIntMax() {
+        final SharedPreferences.Editor editor = mSharedPrefLogger.edit();
+        final long veryBigNumber = 500L + Integer.MAX_VALUE;
+        editor.putLong(TEST_KEY, 1);
+        editor.putLong(TEST_KEY, veryBigNumber);
+
+        verify(mMetricsFeature).action(any(Context.class), anyInt(),
+                argThat(mNamePairMatcher),
+                argThat(pairMatches(
+                        FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE, Integer.MAX_VALUE)));
+    }
+
+    @Test
+    public void putLong_smallerThanIntMin_shouldLogIntMin() {
+        final SharedPreferences.Editor editor = mSharedPrefLogger.edit();
+        final long veryNegativeNumber = -500L + Integer.MIN_VALUE;
+        editor.putLong(TEST_KEY, 1);
+        editor.putLong(TEST_KEY, veryNegativeNumber);
+
+        verify(mMetricsFeature).action(any(Context.class), anyInt(),
+                argThat(mNamePairMatcher),
+                argThat(pairMatches(
+                        FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE, Integer.MIN_VALUE)));
     }
 
     @Test
@@ -152,7 +178,13 @@
 
     private ArgumentMatcher<Pair<Integer, Object>> pairMatches(int tag, boolean bool) {
         return pair -> pair.first == tag
-                && Platform.isInstanceOfType(pair.second, Long.class)
-                && pair.second.equals((bool ? 1L : 0L));
+                && Platform.isInstanceOfType(pair.second, Integer.class)
+                && pair.second.equals((bool ? 1 : 0));
+    }
+
+    private ArgumentMatcher<Pair<Integer, Object>> pairMatches(int tag, int val) {
+        return pair -> pair.first == tag
+                && Platform.isInstanceOfType(pair.second, Integer.class)
+                && pair.second.equals(val);
     }
 }
diff --git a/tests/robotests/src/com/android/settings/dashboard/DashboardAdapterTest.java b/tests/robotests/src/com/android/settings/dashboard/DashboardAdapterTest.java
index 8a8a13d..6b56c29 100644
--- a/tests/robotests/src/com/android/settings/dashboard/DashboardAdapterTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/DashboardAdapterTest.java
@@ -15,6 +15,19 @@
  */
 package com.android.settings.dashboard;
 
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -38,7 +51,6 @@
 import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.testutils.shadow.SettingsShadowResources;
-import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
 import com.android.settingslib.drawer.DashboardCategory;
 import com.android.settingslib.drawer.Tile;
 
@@ -56,26 +68,12 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH,
         sdk = TestConfig.SDK_VERSION,
         shadows = {
                 SettingsShadowResources.class,
                 SettingsShadowResources.SettingsShadowTheme.class,
-                ShadowDynamicIndexableContentMonitor.class
         })
 public class DashboardAdapterTest {
 
diff --git a/tests/robotests/src/com/android/settings/fingerprint/FingerprintEnrollFindSensorTest.java b/tests/robotests/src/com/android/settings/fingerprint/FingerprintEnrollFindSensorTest.java
index 344914a..ad52bf6 100644
--- a/tests/robotests/src/com/android/settings/fingerprint/FingerprintEnrollFindSensorTest.java
+++ b/tests/robotests/src/com/android/settings/fingerprint/FingerprintEnrollFindSensorTest.java
@@ -36,7 +36,6 @@
 import com.android.settings.password.IFingerprintManager;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.testutils.shadow.SettingsShadowResources;
-import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
 import com.android.settings.testutils.shadow.ShadowEventLogWriter;
 import com.android.settings.testutils.shadow.ShadowUtils;
 
@@ -61,7 +60,6 @@
         shadows = {
                 SettingsShadowResources.class,
                 SettingsShadowResources.SettingsShadowTheme.class,
-                ShadowDynamicIndexableContentMonitor.class,
                 ShadowEventLogWriter.class,
                 ShadowUtils.class
         })
diff --git a/tests/robotests/src/com/android/settings/fingerprint/SetupFingerprintEnrollFindSensorTest.java b/tests/robotests/src/com/android/settings/fingerprint/SetupFingerprintEnrollFindSensorTest.java
index f1b7ee0..ce31328 100644
--- a/tests/robotests/src/com/android/settings/fingerprint/SetupFingerprintEnrollFindSensorTest.java
+++ b/tests/robotests/src/com/android/settings/fingerprint/SetupFingerprintEnrollFindSensorTest.java
@@ -30,7 +30,6 @@
 import com.android.settings.password.IFingerprintManager;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.testutils.shadow.SettingsShadowResources;
-import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
 import com.android.settings.testutils.shadow.ShadowEventLogWriter;
 import com.android.settings.testutils.shadow.ShadowUtils;
 
@@ -53,7 +52,6 @@
         shadows = {
                 SettingsShadowResources.class,
                 SettingsShadowResources.SettingsShadowTheme.class,
-                ShadowDynamicIndexableContentMonitor.class,
                 ShadowEventLogWriter.class,
                 ShadowUtils.class
         })
@@ -97,7 +95,7 @@
         AlertDialog alertDialog = ShadowAlertDialog.getLatestAlertDialog();
         assertNotNull(alertDialog);
         ShadowAlertDialog shadowAlertDialog = Shadows.shadowOf(alertDialog);
-        int titleRes = R.string.fingerprint_enroll_skip_after_adding_lock_title;
+        int titleRes = R.string.setup_fingerprint_enroll_skip_title;
         assertEquals(application.getString(titleRes), shadowAlertDialog.getTitle());
     }
 
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceControllerTest.java
index 013d379..e434bb3 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceControllerTest.java
@@ -17,6 +17,15 @@
 
 package com.android.settings.fuelgauge;
 
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
 import android.app.Activity;
 import android.content.Context;
 import android.content.Intent;
@@ -27,11 +36,10 @@
 import android.widget.TextView;
 
 import com.android.settings.R;
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
 import com.android.settings.applications.LayoutPreference;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.testutils.shadow.SettingsShadowResources;
-import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
 import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
 import com.android.settings.widget.EntityHeaderController;
 import com.android.settingslib.core.lifecycle.Lifecycle;
@@ -45,23 +53,12 @@
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.nullable;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH,
         sdk = TestConfig.SDK_VERSION,
         shadows = {
                 SettingsShadowResources.class,
                 SettingsShadowResources.SettingsShadowTheme.class,
-                ShadowDynamicIndexableContentMonitor.class,
                 ShadowEntityHeaderController.class
         })
 public class BatteryHeaderPreferenceControllerTest {
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryMeterViewTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryMeterViewTest.java
index e3a94d2..3a1fad0 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryMeterViewTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryMeterViewTest.java
@@ -16,15 +16,17 @@
 package com.android.settings.fuelgauge;
 
 import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
 
 import android.content.Context;
 import android.graphics.ColorFilter;
 
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.testutils.shadow.SettingsShadowResources;
 import com.android.settings.testutils.shadow.SettingsShadowResources.SettingsShadowTheme;
-import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -34,10 +36,6 @@
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-
 @RunWith(SettingsRobolectricTestRunner.class)
 // TODO: Consider making the shadow class set global using a robolectric.properties file.
 @Config(manifest = TestConfig.MANIFEST_PATH,
@@ -45,7 +43,6 @@
         shadows = {
                 SettingsShadowResources.class,
                 SettingsShadowTheme.class,
-                ShadowDynamicIndexableContentMonitor.class
         })
 public class BatteryMeterViewTest {
     private static final int BATTERY_LEVEL = 100;
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
index 83e630d..48a48b1 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
@@ -18,9 +18,7 @@
 import static com.android.settings.fuelgauge.PowerUsageSummary.MENU_ADDITIONAL_BATTERY_INFO;
 import static com.android.settings.fuelgauge.PowerUsageSummary.MENU_HIGH_POWER_APPS;
 import static com.android.settings.fuelgauge.PowerUsageSummary.MENU_TOGGLE_APPS;
-
 import static com.google.common.truth.Truth.assertThat;
-
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.anyLong;
@@ -34,8 +32,6 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import java.util.List;
-
 import android.app.LoaderManager;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -68,7 +64,6 @@
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.testutils.XmlTestUtils;
 import com.android.settings.testutils.shadow.SettingsShadowResources;
-import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
 import com.android.settingslib.core.AbstractPreferenceController;
 
 import org.junit.Before;
@@ -95,7 +90,6 @@
         shadows = {
                 SettingsShadowResources.class,
                 SettingsShadowResources.SettingsShadowTheme.class,
-                ShadowDynamicIndexableContentMonitor.class
         })
 public class PowerUsageSummaryTest {
     private static final String[] PACKAGE_NAMES = {"com.app1", "com.app2"};
diff --git a/tests/robotests/src/com/android/settings/gestures/AssistGesturePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/AssistGestureSettingsPreferenceControllerTest.java
similarity index 70%
rename from tests/robotests/src/com/android/settings/gestures/AssistGesturePreferenceControllerTest.java
rename to tests/robotests/src/com/android/settings/gestures/AssistGestureSettingsPreferenceControllerTest.java
index b2d3596..6767346 100644
--- a/tests/robotests/src/com/android/settings/gestures/AssistGesturePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/AssistGestureSettingsPreferenceControllerTest.java
@@ -16,9 +16,6 @@
 
 package com.android.settings.gestures;
 
-import static android.provider.Settings.Secure.ASSIST_GESTURE_ENABLED;
-
-import static android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE;
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.Mockito.when;
@@ -26,17 +23,16 @@
 import android.content.ContentResolver;
 import android.content.Context;
 import android.provider.Settings;
-
 import android.provider.Settings.Secure;
+
 import com.android.settings.TestConfig;
-import com.android.settings.display.AutoBrightnessPreferenceController;
 import com.android.settings.search.InlinePayload;
 import com.android.settings.search.InlineSwitchPayload;
 import com.android.settings.search.ResultPayload;
 import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
-
 import com.android.settings.testutils.shadow.ShadowSecureSettings;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -45,16 +41,15 @@
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowApplication;
 
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
-public class AssistGesturePreferenceControllerTest {
+public class AssistGestureSettingsPreferenceControllerTest {
 
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private Context mContext;
     private FakeFeatureFactory mFactory;
-    private AssistGesturePreferenceController mController;
+    private AssistGestureSettingsPreferenceController mController;
 
     private static final String KEY_ASSIST = "gesture_assist";
 
@@ -63,7 +58,8 @@
         MockitoAnnotations.initMocks(this);
         FakeFeatureFactory.setupForTest(mContext);
         mFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
-        mController = new AssistGesturePreferenceController(mContext, null, KEY_ASSIST, false);
+        mController = new AssistGestureSettingsPreferenceController(mContext, null, KEY_ASSIST,
+                false);
     }
 
     @Test
@@ -80,31 +76,11 @@
     }
 
     @Test
-    public void testSwitchEnabled_configIsSet_shouldReturnTrue() {
-        // Set the setting to be enabled.
-        final Context context = ShadowApplication.getInstance().getApplicationContext();
-        Settings.System.putInt(context.getContentResolver(), ASSIST_GESTURE_ENABLED, 1);
-        mController = new AssistGesturePreferenceController(context, null, KEY_ASSIST, false);
-
-        assertThat(mController.isSwitchPrefEnabled()).isTrue();
-    }
-
-    @Test
-    public void testSwitchEnabled_configIsNotSet_shouldReturnFalse() {
-        // Set the setting to be disabled.
-        final Context context = ShadowApplication.getInstance().getApplicationContext();
-        Settings.System.putInt(context.getContentResolver(), ASSIST_GESTURE_ENABLED, 0);
-        mController = new AssistGesturePreferenceController(context, null, KEY_ASSIST, false);
-
-        assertThat(mController.isSwitchPrefEnabled()).isFalse();
-    }
-
-    @Test
     public void testPreferenceController_ProperResultPayloadType() {
         final Context context = RuntimeEnvironment.application;
-        AssistGesturePreferenceController controller =
-                new AssistGesturePreferenceController(context, null /* lifecycle */, KEY_ASSIST,
-                        false /* assistOnly */);
+        AssistGestureSettingsPreferenceController controller =
+                new AssistGestureSettingsPreferenceController(context, null /* lifecycle */,
+                        KEY_ASSIST, false /* assistOnly */);
         ResultPayload payload = controller.getResultPayload();
         assertThat(payload).isInstanceOf(InlineSwitchPayload.class);
     }
diff --git a/tests/robotests/src/com/android/settings/gestures/AssistGestureSettingsTest.java b/tests/robotests/src/com/android/settings/gestures/AssistGestureSettingsTest.java
index cfd3f52..1f5c9be 100644
--- a/tests/robotests/src/com/android/settings/gestures/AssistGestureSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/AssistGestureSettingsTest.java
@@ -62,13 +62,6 @@
     }
 
     @Test
-    public void testGetPreferenceControllers_shouldAllBeCreated() {
-        final List<AbstractPreferenceController> controllers =
-                mSettings.getPreferenceControllers(mContext);
-        assertThat(controllers.isEmpty()).isFalse();
-    }
-
-    @Test
     public void testSearchIndexProvider_shouldIndexResource() {
         final List<SearchIndexableResource> indexRes =
                 AssistGestureSettings.SEARCH_INDEX_DATA_PROVIDER.getXmlResourcesToIndex(
diff --git a/tests/robotests/src/com/android/settings/gestures/SwipeToNotificationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/SwipeToNotificationPreferenceControllerTest.java
index 3b92ed1..d4fc014 100644
--- a/tests/robotests/src/com/android/settings/gestures/SwipeToNotificationPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/SwipeToNotificationPreferenceControllerTest.java
@@ -129,46 +129,6 @@
         assertThat(mController.isSwitchPrefEnabled()).isFalse();
     }
 
-    @Test
-    public void testPreferenceController_ProperResultPayloadType() {
-        when(mContext.getResources().
-                getBoolean(com.android.internal.R.bool.config_supportSystemNavigationKeys))
-                .thenReturn(true);
-
-        SwipeToNotificationPreferenceController controller =
-                new SwipeToNotificationPreferenceController(mContext, null /* lifecycle */,
-                        SYSTEM_NAVIGATION_KEYS_ENABLED);
-        ResultPayload payload = controller.getResultPayload();
-        assertThat(payload).isInstanceOf(InlineSwitchPayload.class);
-    }
-
-    @Test
-    @Config(shadows = ShadowSecureSettings.class)
-    public void testSetValue_updatesCorrectly() {
-        int newValue = 1;
-        ContentResolver resolver = mContext.getContentResolver();
-        Settings.Secure.putInt(resolver, Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 0);
-
-        ((InlinePayload) mController.getResultPayload()).setValue(mContext, newValue);
-        int updatedValue = Settings.Secure.getInt(resolver,
-                Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, -1);
-
-        assertThat(updatedValue).isEqualTo(newValue);
-    }
-
-    @Test
-    @Config(shadows = ShadowSecureSettings.class)
-    public void testGetValue_correctValueReturned() {
-        int currentValue = 1;
-        ContentResolver resolver = mContext.getContentResolver();
-        Settings.Secure.putInt(resolver,
-                Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, currentValue);
-
-        int newValue = ((InlinePayload) mController.getResultPayload()).getValue(mContext);
-
-        assertThat(newValue).isEqualTo(currentValue);
-    }
-
     private void stubFingerprintSupported(boolean enabled) {
         when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT))
                 .thenReturn(enabled);
diff --git a/tests/robotests/src/com/android/settings/network/MobileNetworkPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/MobileNetworkPreferenceControllerTest.java
index e115dad..66e357b 100644
--- a/tests/robotests/src/com/android/settings/network/MobileNetworkPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/MobileNetworkPreferenceControllerTest.java
@@ -26,6 +26,7 @@
 
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
+import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsWrapper;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
 import org.junit.Before;
@@ -87,6 +88,7 @@
     }
 
     @Test
+    @Config(shadows = ShadowRestrictedLockUtilsWrapper.class)
     public void wifiOnly_prefIsNotAvailable() {
         when(mUserManager.isAdminUser()).thenReturn(true);
         when(mUserManager.hasUserRestriction(anyString(), any(UserHandle.class)))
diff --git a/tests/robotests/src/com/android/settings/notification/VolumeSeekBarPreferenceTest.java b/tests/robotests/src/com/android/settings/notification/VolumeSeekBarPreferenceTest.java
new file mode 100644
index 0000000..b091cd3
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/VolumeSeekBarPreferenceTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2017 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.notification;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doCallRealMethod;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.media.AudioManager;
+
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class VolumeSeekBarPreferenceTest {
+
+    @Mock
+    private AudioManager mAudioManager;
+    @Mock
+    private VolumeSeekBarPreference mPreference;
+    @Mock
+    private Context mContext;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        when(mContext.getSystemService(Context.AUDIO_SERVICE)).thenReturn(mAudioManager);
+        mPreference.mAudioManager = mAudioManager;
+    }
+
+    @Test
+    public void setStream_shouldSetMaxAndProgress() {
+        final int stream = 5;
+        final int max = 17;
+        final int progress = 4;
+        when(mAudioManager.getStreamMaxVolume(stream)).thenReturn(max);
+        when(mAudioManager.getStreamVolume(stream)).thenReturn(progress);
+        doCallRealMethod().when(mPreference).setStream(anyInt());
+
+        mPreference.setStream(stream);
+
+        verify(mPreference).setMax(max);
+        verify(mPreference).setProgress(progress);
+    }
+
+}
diff --git a/tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java b/tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java
index 5fa731e..b8f0679 100644
--- a/tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java
+++ b/tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java
@@ -31,7 +31,6 @@
 import com.android.settings.password.ChooseLockPassword.IntentBuilder;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.testutils.shadow.SettingsShadowResources;
-import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
 import com.android.settings.testutils.shadow.ShadowEventLogWriter;
 import com.android.settings.testutils.shadow.ShadowUtils;
 import com.android.setupwizardlib.GlifLayout;
@@ -52,7 +51,6 @@
         shadows = {
                 SettingsShadowResources.class,
                 SettingsShadowResources.SettingsShadowTheme.class,
-                ShadowDynamicIndexableContentMonitor.class,
                 ShadowEventLogWriter.class,
                 ShadowUtils.class
         })
diff --git a/tests/robotests/src/com/android/settings/password/ChooseLockPatternTest.java b/tests/robotests/src/com/android/settings/password/ChooseLockPatternTest.java
index b238049..c74448b 100644
--- a/tests/robotests/src/com/android/settings/password/ChooseLockPatternTest.java
+++ b/tests/robotests/src/com/android/settings/password/ChooseLockPatternTest.java
@@ -29,7 +29,6 @@
 import com.android.settings.password.ChooseLockPattern.IntentBuilder;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.testutils.shadow.SettingsShadowResources;
-import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
 import com.android.settings.testutils.shadow.ShadowEventLogWriter;
 import com.android.settings.testutils.shadow.ShadowUtils;
 import com.android.setupwizardlib.GlifLayout;
@@ -48,7 +47,6 @@
         shadows = {
                 SettingsShadowResources.class,
                 SettingsShadowResources.SettingsShadowTheme.class,
-                ShadowDynamicIndexableContentMonitor.class,
                 ShadowEventLogWriter.class,
                 ShadowUtils.class
         })
diff --git a/tests/robotests/src/com/android/settings/password/SetupChooseLockPasswordTest.java b/tests/robotests/src/com/android/settings/password/SetupChooseLockPasswordTest.java
index 39a0fb6..1195a2c 100644
--- a/tests/robotests/src/com/android/settings/password/SetupChooseLockPasswordTest.java
+++ b/tests/robotests/src/com/android/settings/password/SetupChooseLockPasswordTest.java
@@ -34,7 +34,6 @@
 import com.android.settings.password.SetupChooseLockPassword.SetupChooseLockPasswordFragment;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.testutils.shadow.SettingsShadowResources;
-import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
 import com.android.settings.testutils.shadow.ShadowEventLogWriter;
 import com.android.settings.testutils.shadow.ShadowUtils;
 
@@ -62,7 +61,6 @@
         shadows = {
                 SettingsShadowResources.class,
                 SettingsShadowResources.SettingsShadowTheme.class,
-                ShadowDynamicIndexableContentMonitor.class,
                 ShadowEventLogWriter.class,
                 ShadowUtils.class
         })
diff --git a/tests/robotests/src/com/android/settings/password/SetupSkipDialogTest.java b/tests/robotests/src/com/android/settings/password/SetupSkipDialogTest.java
index 639349d..0e6f28a 100644
--- a/tests/robotests/src/com/android/settings/password/SetupSkipDialogTest.java
+++ b/tests/robotests/src/com/android/settings/password/SetupSkipDialogTest.java
@@ -27,7 +27,6 @@
 import com.android.settings.TestConfig;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.testutils.shadow.SettingsShadowResources;
-import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
 import com.android.settings.testutils.shadow.ShadowEventLogWriter;
 import com.android.settings.testutils.shadow.ShadowUtils;
 
@@ -40,13 +39,11 @@
 import org.robolectric.shadows.ShadowAlertDialog;
 
 @RunWith(SettingsRobolectricTestRunner.class)
-@Config(
-        manifest = TestConfig.MANIFEST_PATH,
+@Config(manifest = TestConfig.MANIFEST_PATH,
         sdk = TestConfig.SDK_VERSION,
         shadows = {
                 SettingsShadowResources.class,
                 SettingsShadowResources.SettingsShadowTheme.class,
-                ShadowDynamicIndexableContentMonitor.class,
                 ShadowEventLogWriter.class,
                 ShadowUtils.class
         })
diff --git a/tests/robotests/src/com/android/settings/search/DynamicIndexableContentMonitorTest.java b/tests/robotests/src/com/android/settings/search/DynamicIndexableContentMonitorTest.java
deleted file mode 100644
index 26c89d5..0000000
--- a/tests/robotests/src/com/android/settings/search/DynamicIndexableContentMonitorTest.java
+++ /dev/null
@@ -1,563 +0,0 @@
-/*
- * 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.search;
-
-import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.only;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-import android.accessibilityservice.AccessibilityServiceInfo;
-import android.app.Activity;
-import android.app.Application;
-import android.app.LoaderManager;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.Loader;
-import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.pm.ServiceInfo;
-import android.database.ContentObserver;
-import android.hardware.input.InputManager;
-import android.net.Uri;
-import android.os.Bundle;
-import android.print.PrintManager;
-import android.print.PrintServicesLoader;
-import android.printservice.PrintServiceInfo;
-import android.provider.Settings;
-import android.provider.UserDictionary;
-import android.view.inputmethod.InputMethodInfo;
-
-import com.android.internal.content.PackageMonitor;
-import com.android.settings.TestConfig;
-import com.android.settings.inputmethod.AvailableVirtualKeyboardFragment;
-import com.android.settings.inputmethod.PhysicalKeyboardFragment;
-import com.android.settings.inputmethod.VirtualKeyboardFragment;
-import com.android.settings.language.LanguageAndInputSettings;
-import com.android.settings.print.PrintSettingsFragment;
-import com.android.settings.testutils.DatabaseTestUtils;
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
-import com.android.settings.testutils.shadow.ShadowActivityWithLoadManager;
-import com.android.settings.testutils.shadow.ShadowContextImplWithRegisterReceiver;
-import com.android.settings.testutils.shadow.ShadowInputManager;
-import com.android.settings.testutils.shadow.ShadowInputMethodManagerWithMethodList;
-import com.android.settings.testutils.shadow.ShadowPackageMonitor;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.Robolectric;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-import org.robolectric.internal.ShadowExtractor;
-import org.robolectric.res.builder.RobolectricPackageManager;
-import org.robolectric.shadows.ShadowAccessibilityManager;
-import org.robolectric.shadows.ShadowApplication;
-import org.robolectric.shadows.ShadowContentResolver;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
-@RunWith(SettingsRobolectricTestRunner.class)
-@Config(
-        manifest = TestConfig.MANIFEST_PATH,
-        sdk = TestConfig.SDK_VERSION,
-        shadows = {
-                ShadowActivityWithLoadManager.class,
-                ShadowContextImplWithRegisterReceiver.class,
-                ShadowInputManager.class,
-                ShadowInputMethodManagerWithMethodList.class,
-                ShadowPackageMonitor.class,
-        }
-)
-public class DynamicIndexableContentMonitorTest {
-
-    private static final int LOADER_ID = 1234;
-    private static final String A11Y_PACKAGE_1 = "a11y-1";
-    private static final String A11Y_PACKAGE_2 = "a11y-2";
-    private static final String IME_PACKAGE_1 = "ime-1";
-    private static final String IME_PACKAGE_2 = "ime-2";
-
-    @Mock
-    private LoaderManager mLoaderManager;
-    @Mock
-    private DatabaseIndexingManager mIndexManager;
-
-    private Activity mActivity;
-    private InputManager mInputManager;
-
-    private ShadowContextImplWithRegisterReceiver mShadowContextImpl;
-    private ShadowActivityWithLoadManager mShadowActivity;
-    private ShadowAccessibilityManager mShadowAccessibilityManager;
-    private ShadowInputMethodManagerWithMethodList mShadowInputMethodManager;
-    private RobolectricPackageManager mRobolectricPackageManager;
-
-    private final DynamicIndexableContentMonitor mMonitor = new DynamicIndexableContentMonitor();
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mActivity = Robolectric.buildActivity(Activity.class).get();
-        mInputManager = InputManager.getInstance();
-
-        // Robolectric shadows.
-        mShadowContextImpl = (ShadowContextImplWithRegisterReceiver) ShadowExtractor.extract(
-                ((Application) ShadowApplication.getInstance().getApplicationContext())
-                .getBaseContext());
-        mShadowActivity = (ShadowActivityWithLoadManager) ShadowExtractor.extract(mActivity);
-        mShadowAccessibilityManager = (ShadowAccessibilityManager) ShadowExtractor.extract(
-                mActivity.getSystemService(Context.ACCESSIBILITY_SERVICE));
-        mShadowInputMethodManager = (ShadowInputMethodManagerWithMethodList) ShadowExtractor
-                .extract(mActivity.getSystemService(Context.INPUT_METHOD_SERVICE));
-        mRobolectricPackageManager = RuntimeEnvironment.getRobolectricPackageManager();
-
-        // Setup shadows.
-        mShadowContextImpl.setSystemService(Context.PRINT_SERVICE, mock(PrintManager.class));
-        mShadowContextImpl.setSystemService(Context.INPUT_SERVICE, mInputManager);
-        mShadowActivity.setLoaderManager(mLoaderManager);
-        mShadowAccessibilityManager.setInstalledAccessibilityServiceList(Collections.emptyList());
-        mShadowInputMethodManager.setInputMethodList(Collections.emptyList());
-        mRobolectricPackageManager.setSystemFeature(PackageManager.FEATURE_PRINTING, true);
-        mRobolectricPackageManager.setSystemFeature(PackageManager.FEATURE_INPUT_METHODS, true);
-    }
-
-    @After
-    public void shutDown() {
-        mMonitor.unregister(mActivity, LOADER_ID);
-        // BroadcastReceiver must be unregistered.
-        assertThat(extractPackageMonitor()).isNull();
-
-        DynamicIndexableContentMonitor.resetForTesting();
-        mRobolectricPackageManager.reset();
-
-        DatabaseTestUtils.clearDb(mActivity);
-    }
-
-    @Test
-    public void testLockedUser() {
-        mMonitor.register(mActivity, LOADER_ID, mIndexManager, false /* isUserUnlocked */);
-
-        // No loader procedure happens.
-        verify(mLoaderManager, never()).initLoader(
-                anyInt(), any(Bundle.class), any(LoaderManager.LoaderCallbacks.class));
-        // No indexing happens.
-        verify(mIndexManager, never()).updateFromClassNameResource(
-                anyString(), anyBoolean());
-
-        mMonitor.unregister(mActivity, LOADER_ID);
-
-        // No destroy loader should happen.
-        verify(mLoaderManager, never()).destroyLoader(anyInt());
-    }
-
-    @Test
-    public void testWithNoPrintingFeature() {
-        mRobolectricPackageManager.setSystemFeature(PackageManager.FEATURE_PRINTING, false);
-
-        mMonitor.register(mActivity, LOADER_ID, mIndexManager, true /* isUserUnlocked */);
-
-        // No loader procedure happens.
-        verify(mLoaderManager, never()).initLoader(
-                anyInt(), any(Bundle.class), any(LoaderManager.LoaderCallbacks.class));
-        verifyNoIndexing(PrintSettingsFragment.class);
-
-        mMonitor.unregister(mActivity, LOADER_ID);
-
-        // No destroy loader should happen.
-        verify(mLoaderManager, never()).destroyLoader(anyInt());
-        // BroadcastReceiver must be unregistered.
-        assertThat(extractPackageMonitor()).isNull();
-
-        // To suppress spurious test fail in {@link #shutDown()}.
-        mMonitor.register(mActivity, LOADER_ID, mIndexManager, true /* isUserUnlocked */);
-    }
-
-    @Test
-    public void testPrinterServiceIndex() {
-        mMonitor.register(mActivity, LOADER_ID, mIndexManager, true /* isUserUnlocked */);
-
-        // Loader procedure happens.
-        verify(mLoaderManager, only()).initLoader(LOADER_ID, null, mMonitor);
-
-        // Loading print services happens.
-        final Loader<List<PrintServiceInfo>> loader =
-                mMonitor.onCreateLoader(LOADER_ID, null /* args */);
-        assertThat(loader).isInstanceOf(PrintServicesLoader.class);
-        verifyNoIndexing(PrintSettingsFragment.class);
-
-        mMonitor.onLoadFinished(loader, Collections.emptyList());
-
-        verifyIncrementalIndexing(PrintSettingsFragment.class);
-    }
-
-    @Test
-    public void testInputDevicesMonitor() {
-        mMonitor.register(mActivity, LOADER_ID, mIndexManager, true /* isUserUnlocked */);
-
-        // Rebuild indexing should happen.
-        verifyIncrementalIndexing(PhysicalKeyboardFragment.class);
-        // Input monitor should be registered to InputManager.
-        final InputManager.InputDeviceListener listener = extactInputDeviceListener();
-        assertThat(listener).isNotNull();
-
-        /*
-         * Nothing happens on successive register calls.
-         */
-        mMonitor.unregister(mActivity, LOADER_ID);
-        reset(mIndexManager);
-
-        mMonitor.register(mActivity, LOADER_ID, mIndexManager, true /* isUserUnlocked */);
-
-        verifyNoIndexing(PhysicalKeyboardFragment.class);
-        assertThat(extactInputDeviceListener()).isEqualTo(listener);
-
-        /*
-         * A device is added.
-         */
-        reset(mIndexManager);
-
-        listener.onInputDeviceAdded(1 /* deviceId */);
-
-        verifyIncrementalIndexing(PhysicalKeyboardFragment.class);
-
-        /*
-         * A device is removed.
-         */
-        reset(mIndexManager);
-
-        listener.onInputDeviceRemoved(2 /* deviceId */);
-
-        verifyIncrementalIndexing(PhysicalKeyboardFragment.class);
-
-        /*
-         * A device is changed.
-         */
-        reset(mIndexManager);
-
-        listener.onInputDeviceChanged(3 /* deviceId */);
-
-        verifyIncrementalIndexing(PhysicalKeyboardFragment.class);
-    }
-
-    @Test
-    public void testInputMethodServicesMonitor() throws Exception {
-        mMonitor.register(mActivity, LOADER_ID, mIndexManager, true /* isUserUnlocked */);
-
-        verifyIncrementalIndexing(VirtualKeyboardFragment.class);
-        verifyIncrementalIndexing(AvailableVirtualKeyboardFragment.class);
-
-        final Uri enabledInputMethodsContentUri = Settings.Secure.getUriFor(
-                Settings.Secure.ENABLED_INPUT_METHODS);
-        // Content observer should be registered.
-        final ContentObserver observer = extractContentObserver(enabledInputMethodsContentUri);
-        assertThat(observer).isNotNull();
-
-        /*
-         * When an input method service package is installed, incremental indexing happen.
-         */
-        reset(mIndexManager);
-
-        installInputMethodService(IME_PACKAGE_1);
-
-        verifyIncrementalIndexing(VirtualKeyboardFragment.class);
-        verifyIncrementalIndexing(AvailableVirtualKeyboardFragment.class);
-
-        /*
-         * When another input method service package is installed, incremental indexing happens.
-         */
-        reset(mIndexManager);
-
-        installInputMethodService(IME_PACKAGE_2);
-
-        verifyIncrementalIndexing(VirtualKeyboardFragment.class);
-        verifyIncrementalIndexing(AvailableVirtualKeyboardFragment.class);
-
-        /*
-         * When an input method service is disabled, rebuild indexing happens.
-         */
-        reset(mIndexManager);
-
-        disableInstalledPackage(IME_PACKAGE_1);
-
-        verifyIncrementalIndexing(VirtualKeyboardFragment.class);
-        verifyIncrementalIndexing(AvailableVirtualKeyboardFragment.class);
-
-        /*
-         * When an input method service is enabled, incremental indexing happens.
-         */
-        reset(mIndexManager);
-
-        enableInstalledPackage(IME_PACKAGE_1);
-
-        verifyIncrementalIndexing(VirtualKeyboardFragment.class);
-        verifyIncrementalIndexing(AvailableVirtualKeyboardFragment.class);
-
-        /*
-         * When an input method service package is uninstalled, rebuild indexing happens.
-         */
-        reset(mIndexManager);
-
-        uninstallInputMethodService(IME_PACKAGE_1);
-
-        verifyIncrementalIndexing(VirtualKeyboardFragment.class);
-        verifyIncrementalIndexing(AvailableVirtualKeyboardFragment.class);
-
-        /*
-         * When an accessibility service package is installed, nothing happens.
-         */
-        reset(mIndexManager);
-
-        installAccessibilityService(A11Y_PACKAGE_1);
-
-        verifyNoIndexing(VirtualKeyboardFragment.class);
-        verifyNoIndexing(AvailableVirtualKeyboardFragment.class);
-
-        /*
-         * When enabled IMEs list is changed, rebuild indexing happens.
-         */
-        reset(mIndexManager);
-
-        observer.onChange(false /* selfChange */, enabledInputMethodsContentUri);
-
-        verifyIncrementalIndexing(VirtualKeyboardFragment.class);
-        verifyIncrementalIndexing(AvailableVirtualKeyboardFragment.class);
-    }
-
-    @Test
-    public void testUserDictionaryChangeMonitor() throws Exception {
-        mMonitor.register(mActivity, LOADER_ID, mIndexManager, true /* isUserUnlocked */);
-
-        // Content observer should be registered.
-        final ContentObserver observer = extractContentObserver(UserDictionary.Words.CONTENT_URI);
-        assertThat(observer).isNotNull();
-
-        verifyIncrementalIndexing(LanguageAndInputSettings.class);
-
-        /*
-         * When user dictionary content is changed, rebuild indexing happens.
-         */
-        reset(mIndexManager);
-
-        observer.onChange(false /* selfChange */, UserDictionary.Words.CONTENT_URI);
-
-        verifyIncrementalIndexing(LanguageAndInputSettings.class);
-    }
-
-    /*
-     * Verification helpers.
-     */
-
-    private void verifyNoIndexing(Class<?> indexingClass) {
-        verify(mIndexManager, never()).updateFromClassNameResource(eq(indexingClass.getName()),
-                anyBoolean());
-    }
-
-    private void verifyIncrementalIndexing(Class<?> indexingClass) {
-        verify(mIndexManager, times(1)).updateFromClassNameResource(indexingClass.getName(),
-                true /* includeInSearchResults */);
-        verify(mIndexManager, never()).updateFromClassNameResource(indexingClass.getName(),
-                false /* includeInSearchResults */);
-    }
-
-    /*
-     * Testing helper methods.
-     */
-
-    private InputManager.InputDeviceListener extactInputDeviceListener() {
-        List<InputManager.InputDeviceListener> listeners = ((ShadowInputManager) ShadowExtractor
-                .extract(mInputManager))
-                .getRegisteredInputDeviceListeners();
-        InputManager.InputDeviceListener inputDeviceListener = null;
-        for (InputManager.InputDeviceListener listener : listeners) {
-            if (isUnderTest(listener)) {
-                if (inputDeviceListener != null) {
-                    assertThat(listener).isEqualTo(inputDeviceListener);
-                } else {
-                    inputDeviceListener = listener;
-                }
-            }
-        }
-        return inputDeviceListener;
-    }
-
-    private PackageMonitor extractPackageMonitor() {
-        List<ShadowApplication.Wrapper> receivers = ShadowApplication.getInstance()
-                .getRegisteredReceivers();
-        PackageMonitor packageMonitor = null;
-        for (ShadowApplication.Wrapper wrapper : receivers) {
-            BroadcastReceiver receiver = wrapper.getBroadcastReceiver();
-            if (isUnderTest(receiver) && receiver instanceof PackageMonitor) {
-                if (packageMonitor != null) {
-                    assertThat(receiver).isEqualTo(packageMonitor);
-                } else {
-                    packageMonitor = (PackageMonitor) receiver;
-                }
-            }
-        }
-        return packageMonitor;
-    }
-
-    private ContentObserver extractContentObserver(Uri uri) {
-        ShadowContentResolver contentResolver = (ShadowContentResolver) ShadowExtractor
-                .extract(mActivity.getContentResolver());
-        Collection<ContentObserver> observers = contentResolver.getContentObservers(uri);
-        ContentObserver contentObserver = null;
-        for (ContentObserver observer : observers) {
-            if (isUnderTest(observer)) {
-                if (contentObserver != null) {
-                    assertThat(observer).isEqualTo(contentObserver);
-                } else {
-                    contentObserver = observer;
-                }
-            }
-        }
-        return contentObserver;
-    }
-
-    private void enableInstalledPackage(String packageName) {
-        ((PackageManager) mRobolectricPackageManager).setApplicationEnabledSetting(
-                packageName, PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, 0 /* flags */);
-        extractPackageMonitor().onPackageModified(packageName);
-        Robolectric.flushBackgroundThreadScheduler();
-    }
-
-    private void disableInstalledPackage(String packageName) {
-        ((PackageManager) mRobolectricPackageManager).setApplicationEnabledSetting(
-                packageName, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 0 /* flags */);
-        extractPackageMonitor().onPackageModified(packageName);
-        Robolectric.flushBackgroundThreadScheduler();
-    }
-
-    private void installAccessibilityService(String packageName) throws Exception {
-        final AccessibilityServiceInfo serviceToAdd = buildAccessibilityServiceInfo(packageName);
-
-        final List<AccessibilityServiceInfo> services = new ArrayList<>();
-        services.addAll(mShadowAccessibilityManager.getInstalledAccessibilityServiceList());
-        services.add(serviceToAdd);
-        mShadowAccessibilityManager.setInstalledAccessibilityServiceList(services);
-
-        final Intent intent = DynamicIndexableContentMonitor
-                .getAccessibilityServiceIntent(packageName);
-        mRobolectricPackageManager.addResolveInfoForIntent(intent, serviceToAdd.getResolveInfo());
-        mRobolectricPackageManager.addPackage(packageName);
-
-        extractPackageMonitor()
-                .onPackageAppeared(packageName, PackageMonitor.PACKAGE_PERMANENT_CHANGE);
-        Robolectric.flushBackgroundThreadScheduler();
-    }
-
-    private void uninstallAccessibilityService(String packageName) throws Exception {
-        final AccessibilityServiceInfo serviceToRemove = buildAccessibilityServiceInfo(packageName);
-
-        final List<AccessibilityServiceInfo> services = new ArrayList<>();
-        services.addAll(mShadowAccessibilityManager.getInstalledAccessibilityServiceList());
-        services.remove(serviceToRemove);
-        mShadowAccessibilityManager.setInstalledAccessibilityServiceList(services);
-
-        final Intent intent = DynamicIndexableContentMonitor
-                .getAccessibilityServiceIntent(packageName);
-        mRobolectricPackageManager.removeResolveInfosForIntent(intent, packageName);
-        mRobolectricPackageManager.removePackage(packageName);
-
-        extractPackageMonitor()
-                .onPackageDisappeared(packageName, PackageMonitor.PACKAGE_PERMANENT_CHANGE);
-        Robolectric.flushBackgroundThreadScheduler();
-    }
-
-    private void installInputMethodService(String packageName) throws Exception {
-        final ResolveInfo resolveInfoToAdd = buildResolveInfo(packageName, "imeService");
-        final InputMethodInfo serviceToAdd = buildInputMethodInfo(resolveInfoToAdd);
-
-        final List<InputMethodInfo> services = new ArrayList<>();
-        services.addAll(mShadowInputMethodManager.getInputMethodList());
-        services.add(serviceToAdd);
-        mShadowInputMethodManager.setInputMethodList(services);
-
-        final Intent intent = DynamicIndexableContentMonitor.getIMEServiceIntent(packageName);
-        mRobolectricPackageManager.addResolveInfoForIntent(intent, resolveInfoToAdd);
-        mRobolectricPackageManager.addPackage(packageName);
-
-        extractPackageMonitor()
-                .onPackageAppeared(packageName, PackageMonitor.PACKAGE_PERMANENT_CHANGE);
-        Robolectric.flushBackgroundThreadScheduler();
-    }
-
-    private void uninstallInputMethodService(String packageName) throws Exception {
-        final ResolveInfo resolveInfoToRemove = buildResolveInfo(packageName, "imeService");
-        final InputMethodInfo serviceToRemove = buildInputMethodInfo(resolveInfoToRemove);
-
-        final List<InputMethodInfo> services = new ArrayList<>();
-        services.addAll(mShadowInputMethodManager.getInputMethodList());
-        services.remove(serviceToRemove);
-        mShadowInputMethodManager.setInputMethodList(services);
-
-        final Intent intent = DynamicIndexableContentMonitor.getIMEServiceIntent(packageName);
-        mRobolectricPackageManager.removeResolveInfosForIntent(intent, packageName);
-        mRobolectricPackageManager.removePackage(packageName);
-
-        extractPackageMonitor()
-                .onPackageDisappeared(packageName, PackageMonitor.PACKAGE_PERMANENT_CHANGE);
-        Robolectric.flushBackgroundThreadScheduler();
-    }
-
-    private AccessibilityServiceInfo buildAccessibilityServiceInfo(String packageName)
-            throws IOException, XmlPullParserException {
-        return new AccessibilityServiceInfo(
-                buildResolveInfo(packageName, "A11yService"), mActivity);
-    }
-
-    private static InputMethodInfo buildInputMethodInfo(ResolveInfo resolveInfo) {
-        return new InputMethodInfo(resolveInfo, false /* isAuxIme */, "SettingsActivity",
-                null /* subtypes */,  0 /* defaultResId */, false /* forceDefault */);
-    }
-
-    private static ResolveInfo buildResolveInfo(String packageName, String className) {
-        final ResolveInfo resolveInfo = new ResolveInfo();
-        resolveInfo.serviceInfo = new ServiceInfo();
-        resolveInfo.serviceInfo.packageName = packageName;
-        resolveInfo.serviceInfo.name = className;
-        // To workaround that RobolectricPackageManager.removeResolveInfosForIntent() only works
-        // for activity/broadcast resolver.
-        resolveInfo.activityInfo = new ActivityInfo();
-        resolveInfo.activityInfo.packageName = packageName;
-        resolveInfo.activityInfo.name = className;
-
-        return resolveInfo;
-    }
-
-    private static boolean isUnderTest(Object object) {
-        return object.getClass().getName().startsWith(
-                DynamicIndexableContentMonitor.class.getName());
-    }
-}
diff --git a/tests/robotests/src/com/android/settings/search/InputDeviceResultLoaderTest.java b/tests/robotests/src/com/android/settings/search/InputDeviceResultLoaderTest.java
new file mode 100644
index 0000000..a955af1
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/search/InputDeviceResultLoaderTest.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2017 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.search;
+
+import static android.content.Context.INPUT_METHOD_SERVICE;
+import static com.android.settings.search.InputDeviceResultLoader.PHYSICAL_KEYBOARD_FRAGMENT;
+import static com.android.settings.search.InputDeviceResultLoader.VIRTUAL_KEYBOARD_FRAGMENT;
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.ServiceInfo;
+import android.hardware.input.InputManager;
+import android.view.InputDevice;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodManager;
+
+import com.android.settings.R;
+import com.android.settings.TestConfig;
+import com.android.settings.dashboard.SiteMapManager;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.ShadowInputDevice;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH,
+        sdk = TestConfig.SDK_VERSION,
+        shadows = {
+                ShadowInputDevice.class
+        })
+public class InputDeviceResultLoaderTest {
+
+    private static final String QUERY = "test_query";
+    private static final List<String> PHYSICAL_KEYBOARD_BREADCRUMB;
+    private static final List<String> VIRTUAL_KEYBOARD_BREADCRUMB;
+
+    static {
+        PHYSICAL_KEYBOARD_BREADCRUMB = new ArrayList<>();
+        VIRTUAL_KEYBOARD_BREADCRUMB = new ArrayList<>();
+        PHYSICAL_KEYBOARD_BREADCRUMB.add("Settings");
+        PHYSICAL_KEYBOARD_BREADCRUMB.add("physical keyboard");
+        VIRTUAL_KEYBOARD_BREADCRUMB.add("Settings");
+        VIRTUAL_KEYBOARD_BREADCRUMB.add("virtual keyboard");
+    }
+
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private Context mContext;
+    @Mock
+    private SiteMapManager mSiteMapManager;
+    @Mock
+    private InputManager mInputManager;
+    @Mock
+    private InputMethodManager mImm;
+    @Mock
+    private PackageManager mPackageManager;
+
+    private InputDeviceResultLoader mLoader;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        when(mContext.getApplicationContext()).thenReturn(mContext);
+        when(mContext.getSystemService(Context.INPUT_SERVICE))
+                .thenReturn(mInputManager);
+        when(mContext.getSystemService(INPUT_METHOD_SERVICE))
+                .thenReturn(mImm);
+        when(mContext.getPackageManager())
+                .thenReturn(mPackageManager);
+        when(mContext.getString(anyInt()))
+                .thenAnswer(invocation -> RuntimeEnvironment.application.getString(
+                        (Integer) invocation.getArguments()[0]));
+        mLoader = new InputDeviceResultLoader(mContext, QUERY, mSiteMapManager);
+    }
+
+    @After
+    public void tearDown() {
+        ShadowInputDevice.reset();
+    }
+
+    @Test
+    public void query_noKeyboard_shouldNotReturnAnything() {
+        assertThat(mLoader.loadInBackground()).isEmpty();
+    }
+
+    @Test
+    public void query_hasPhysicalKeyboard_match() {
+        addPhysicalKeyboard(QUERY);
+        when(mSiteMapManager.buildBreadCrumb(mContext, PHYSICAL_KEYBOARD_FRAGMENT,
+                RuntimeEnvironment.application.getString(R.string.physical_keyboard_title)))
+                .thenReturn(PHYSICAL_KEYBOARD_BREADCRUMB);
+
+        final List<SearchResult> results = new ArrayList<>(mLoader.loadInBackground());
+
+        assertThat(results).hasSize(1);
+        assertThat(results.get(0).title).isEqualTo(QUERY);
+        assertThat(results.get(0).breadcrumbs)
+                .containsExactlyElementsIn(PHYSICAL_KEYBOARD_BREADCRUMB);
+    }
+
+    @Test
+    public void query_hasVirtualKeyboard_match() {
+        addVirtualKeyboard(QUERY);
+        when(mSiteMapManager.buildBreadCrumb(mContext, VIRTUAL_KEYBOARD_FRAGMENT,
+                RuntimeEnvironment.application.getString(R.string.add_virtual_keyboard)))
+                .thenReturn(VIRTUAL_KEYBOARD_BREADCRUMB);
+
+        final List<SearchResult> results = new ArrayList<>(mLoader.loadInBackground());
+        assertThat(results).hasSize(1);
+        assertThat(results.get(0).title).isEqualTo(QUERY);
+        assertThat(results.get(0).breadcrumbs)
+                .containsExactlyElementsIn(VIRTUAL_KEYBOARD_BREADCRUMB);
+    }
+
+    @Test
+    public void query_hasPhysicalVirtualKeyboard_doNotMatch() {
+        addPhysicalKeyboard("abc");
+        addVirtualKeyboard("def");
+
+        assertThat(mLoader.loadInBackground()).isEmpty();
+        verifyZeroInteractions(mSiteMapManager);
+    }
+
+    private void addPhysicalKeyboard(String name) {
+        final InputDevice device = mock(InputDevice.class);
+        when(device.isVirtual()).thenReturn(false);
+        when(device.isFullKeyboard()).thenReturn(true);
+        when(device.getName()).thenReturn(name);
+        ShadowInputDevice.sDeviceIds = new int[]{0};
+        ShadowInputDevice.addDevice(0, device);
+    }
+
+    private void addVirtualKeyboard(String name) {
+        final List<InputMethodInfo> imis = new ArrayList<>();
+        final InputMethodInfo info = mock(InputMethodInfo.class);
+        imis.add(info);
+        when(info.getServiceInfo()).thenReturn(new ServiceInfo());
+        when(info.loadLabel(mPackageManager)).thenReturn(name);
+        info.getServiceInfo().packageName = "pkg";
+        info.getServiceInfo().name = "class";
+        when(mImm.getInputMethodList()).thenReturn(imis);
+    }
+
+}
diff --git a/tests/robotests/src/com/android/settings/search/MockAccessiblityLoader.java b/tests/robotests/src/com/android/settings/search/MockAccessibilityLoader.java
similarity index 88%
rename from tests/robotests/src/com/android/settings/search/MockAccessiblityLoader.java
rename to tests/robotests/src/com/android/settings/search/MockAccessibilityLoader.java
index aa9b778..0a06a35 100644
--- a/tests/robotests/src/com/android/settings/search/MockAccessiblityLoader.java
+++ b/tests/robotests/src/com/android/settings/search/MockAccessibilityLoader.java
@@ -21,9 +21,9 @@
 import java.util.HashSet;
 import java.util.Set;
 
-public class MockAccessiblityLoader extends AccessibilityServiceResultLoader {
+public class MockAccessibilityLoader extends AccessibilityServiceResultLoader {
 
-    public MockAccessiblityLoader(Context context) {
+    public MockAccessibilityLoader(Context context) {
         super(context, "test_query", null);
     }
 
diff --git a/tests/robotests/src/com/android/settings/search/MockAccessiblityLoader.java b/tests/robotests/src/com/android/settings/search/MockInputDeviceResultLoader.java
similarity index 88%
copy from tests/robotests/src/com/android/settings/search/MockAccessiblityLoader.java
copy to tests/robotests/src/com/android/settings/search/MockInputDeviceResultLoader.java
index aa9b778..2c16b14 100644
--- a/tests/robotests/src/com/android/settings/search/MockAccessiblityLoader.java
+++ b/tests/robotests/src/com/android/settings/search/MockInputDeviceResultLoader.java
@@ -21,9 +21,8 @@
 import java.util.HashSet;
 import java.util.Set;
 
-public class MockAccessiblityLoader extends AccessibilityServiceResultLoader {
-
-    public MockAccessiblityLoader(Context context) {
+public class MockInputDeviceResultLoader extends InputDeviceResultLoader {
+    public MockInputDeviceResultLoader(Context context) {
         super(context, "test_query", null);
     }
 
diff --git a/tests/robotests/src/com/android/settings/search/SearchFragmentTest.java b/tests/robotests/src/com/android/settings/search/SearchFragmentTest.java
index 6588805..71c31aa 100644
--- a/tests/robotests/src/com/android/settings/search/SearchFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/search/SearchFragmentTest.java
@@ -17,6 +17,20 @@
 
 package com.android.settings.search;
 
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
 import android.app.LoaderManager;
 import android.content.Context;
 import android.content.Intent;
@@ -28,10 +42,10 @@
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.R;
 import com.android.settings.SettingsActivity;
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
 import com.android.settings.testutils.DatabaseTestUtils;
 import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.testutils.shadow.SettingsShadowResources;
 
 import org.junit.After;
@@ -52,20 +66,6 @@
 
 import java.util.Set;
 
-import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.nullable;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.argThat;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH,
         sdk = TestConfig.SDK_VERSION,
@@ -83,6 +83,8 @@
     private InstalledAppResultLoader mInstalledAppResultLoader;
     @Mock
     private AccessibilityServiceResultLoader mAccessibilityServiceResultLoader;
+    @Mock
+    private InputDeviceResultLoader mInputDeviceResultLoader;
 
     @Mock
     private SavedQueryLoader mSavedQueryLoader;
@@ -118,6 +120,9 @@
         when(mFeatureFactory.searchFeatureProvider
                 .getAccessibilityServiceResultLoader(any(Context.class), anyString()))
                 .thenReturn(mAccessibilityServiceResultLoader);
+        when(mFeatureFactory.searchFeatureProvider
+                .getInputDeviceResultLoader(any(Context.class), anyString()))
+                .thenReturn(mInputDeviceResultLoader);
         when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
                 .thenReturn(mSavedQueryLoader);
 
@@ -178,6 +183,9 @@
         when(mFeatureFactory.searchFeatureProvider
                 .getAccessibilityServiceResultLoader(any(Context.class), anyString()))
                 .thenReturn(mAccessibilityServiceResultLoader);
+        when(mFeatureFactory.searchFeatureProvider
+                .getInputDeviceResultLoader(any(Context.class), anyString()))
+                .thenReturn(mInputDeviceResultLoader);
         when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
                 .thenReturn(mSavedQueryLoader);
 
@@ -236,6 +244,9 @@
         when(mFeatureFactory.searchFeatureProvider
                 .getAccessibilityServiceResultLoader(any(Context.class), anyString()))
                 .thenReturn(mAccessibilityServiceResultLoader);
+        when(mFeatureFactory.searchFeatureProvider
+                .getInputDeviceResultLoader(any(Context.class), anyString()))
+                .thenReturn(mInputDeviceResultLoader);
         when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
                 .thenReturn(mSavedQueryLoader);
         ActivityController<SearchActivity> activityController =
@@ -270,6 +281,9 @@
         when(mFeatureFactory.searchFeatureProvider
                 .getAccessibilityServiceResultLoader(any(Context.class), anyString()))
                 .thenReturn(mAccessibilityServiceResultLoader);
+        when(mFeatureFactory.searchFeatureProvider
+                .getInputDeviceResultLoader(any(Context.class), anyString()))
+                .thenReturn(mInputDeviceResultLoader);
         when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
                 .thenReturn(mSavedQueryLoader);
 
@@ -349,7 +363,10 @@
                 .thenReturn(new MockAppLoader(RuntimeEnvironment.application));
         when(mFeatureFactory.searchFeatureProvider
                 .getAccessibilityServiceResultLoader(any(Context.class), anyString()))
-                .thenReturn(new MockAccessiblityLoader(RuntimeEnvironment.application));
+                .thenReturn(new MockAccessibilityLoader(RuntimeEnvironment.application));
+        when(mFeatureFactory.searchFeatureProvider
+                .getInputDeviceResultLoader(any(Context.class), anyString()))
+                .thenReturn(new MockInputDeviceResultLoader(RuntimeEnvironment.application));
         when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
                 .thenReturn(mSavedQueryLoader);
         ActivityController<SearchActivity> activityController =
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDynamicIndexableContentMonitor.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDynamicIndexableContentMonitor.java
deleted file mode 100644
index de5d243..0000000
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDynamicIndexableContentMonitor.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.android.settings.testutils.shadow;
-
-import android.app.Activity;
-import android.os.UserManager;
-import com.android.settings.search.DynamicIndexableContentMonitor;
-import org.robolectric.annotation.Implementation;
-import org.robolectric.annotation.Implements;
-import org.robolectric.annotation.RealObject;
-
-/**
- * A shadow class of {@link DynamicIndexableContentMonitor}. The real implementation of
- * {@link DynamicIndexableContentMonitor#register} calls {@link UserManager#isUserUnlocked()}, which
- * Robolectric has not yet been updated to support, so throws a NoSuchMethodError exception.
- */
-// TODO: Delete this once Robolectric is updated to the latest SDK.
-@Implements(DynamicIndexableContentMonitor.class)
-public class ShadowDynamicIndexableContentMonitor {
-
-    @Implementation
-    public void register(Activity activity, int loaderId) {
-    }
-}
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowMobileNetworkPreferenceController.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowMobileNetworkPreferenceController.java
new file mode 100644
index 0000000..8d76063
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowMobileNetworkPreferenceController.java
@@ -0,0 +1,28 @@
+package com.android.settings.testutils.shadow;
+
+import android.content.Context;
+import com.android.settings.network.MobileNetworkPreferenceController;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+@Implements(MobileNetworkPreferenceController.class)
+public class ShadowMobileNetworkPreferenceController {
+    private static boolean mIsRestricted = false;
+
+    public void __constructor__(Context context) {
+    }
+
+    @Implementation
+    public boolean isAvailable() {
+        return mIsRestricted ? false : true;
+    }
+
+    @Implementation
+    public boolean isUserRestricted() {
+        return mIsRestricted;
+    }
+
+    public static void setRestricted(boolean restricted) {
+        mIsRestricted = restricted;
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowRestrictedLockUtilsWrapper.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowRestrictedLockUtilsWrapper.java
new file mode 100644
index 0000000..0e0adce
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowRestrictedLockUtilsWrapper.java
@@ -0,0 +1,25 @@
+package com.android.settings.testutils.shadow;
+
+import android.content.Context;
+import com.android.settings.network.RestrictedLockUtilsWrapper;
+import org.robolectric.annotation.Implements;
+
+/**
+ * Shadow for the wrapper around RestrictedLockUtils. Should be removed/updated once robolectric is
+ * updated to allow usage of new UserManager API's. see
+ * {@link com.android.settingslib.RestrictedLockUtils} and
+ * {@link com.android.settings.network.RestrictedLockUtilsWrapper}
+ */
+@Implements(RestrictedLockUtilsWrapper.class)
+public class ShadowRestrictedLockUtilsWrapper {
+
+    private boolean isRestricted;
+
+    public boolean hasBaseUserRestriction(Context context, String userRestriction, int userId) {
+        return isRestricted;
+    }
+
+    public void setRestricted(boolean restricted) {
+        isRestricted = restricted;
+    }
+}