Merge "Fix account picker crash when there is no account before."
diff --git a/res/drawable/ic_settings_24dp.xml b/res/drawable/ic_settings_24dp.xml
index 545bc2d..da34345 100644
--- a/res/drawable/ic_settings_24dp.xml
+++ b/res/drawable/ic_settings_24dp.xml
@@ -18,7 +18,8 @@
         android:width="24dp"
         android:height="24dp"
         android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
+        android:viewportHeight="24.0"
+        android:tint="?android:attr/colorControlNormal">
     <path
         android:pathData="M19.4,13.0c0.0,-0.3 0.1,-0.6 0.1,-1.0s0.0,-0.7 -0.1,-1.0l2.1,-1.7c0.2,-0.2 0.2,-0.4 0.1,-0.6l-2.0,-3.5C19.5,5.1 19.3,5.0 19.0,5.1l-2.5,1.0c-0.5,-0.4 -1.1,-0.7 -1.7,-1.0l-0.4,-2.6C14.5,2.2 14.2,2.0 14.0,2.0l-4.0,0.0C9.8,2.0 9.5,2.2 9.5,2.4L9.1,5.1C8.5,5.3 8.0,5.7 7.4,6.1L5.0,5.1C4.7,5.0 4.5,5.1 4.3,5.3l-2.0,3.5C2.2,8.9 2.3,9.2 2.5,9.4L4.6,11.0c0.0,0.3 -0.1,0.6 -0.1,1.0s0.0,0.7 0.1,1.0l-2.1,1.7c-0.2,0.2 -0.2,0.4 -0.1,0.6l2.0,3.5C4.5,18.9 4.7,19.0 5.0,18.9l2.5,-1.0c0.5,0.4 1.1,0.7 1.7,1.0l0.4,2.6c0.0,0.2 0.2,0.4 0.5,0.4l4.0,0.0c0.2,0.0 0.5,-0.2 0.5,-0.4l0.4,-2.6c0.6,-0.3 1.2,-0.6 1.7,-1.0l2.5,1.0c0.2,0.1 0.5,0.0 0.6,-0.2l2.0,-3.5c0.1,-0.2 0.1,-0.5 -0.1,-0.6L19.4,13.0zM12.0,15.5c-1.9,0.0 -3.5,-1.6 -3.5,-3.5s1.6,-3.5 3.5,-3.5s3.5,1.6 3.5,3.5S13.9,15.5 12.0,15.5z"
         android:fillColor="#ffffffff" />
diff --git a/res/layout/activity_list.xml b/res/layout/activity_list.xml
new file mode 100644
index 0000000..ca9e12b
--- /dev/null
+++ b/res/layout/activity_list.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2016 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+             android:layout_width="match_parent"
+             android:layout_height="match_parent">
+
+    <ListView
+        android:id="@android:id/list"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"/>
+
+    <TextView
+        android:id="@android:id/empty"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:gravity="center"
+        android:text="@string/activity_list_empty"
+        android:visibility="gone"
+        android:textAppearance="?android:attr/textAppearanceMedium"/>
+
+</FrameLayout>
diff --git a/res/layout/switch_bar.xml b/res/layout/switch_bar.xml
index 8b69a1d..11d7306 100644
--- a/res/layout/switch_bar.xml
+++ b/res/layout/switch_bar.xml
@@ -43,7 +43,6 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_gravity="center_vertical"
-            android:background="@null"
             android:theme="@style/ThemeOverlay.SwitchBar.Settings" />
 
 </merge>
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index ea17d0e..5e908df 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Instellings"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Instellings"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Instellingskortpad"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Vliegtuigmodus"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Nog"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Draadloos en netwerke"</string>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index 6aa737b..645093e 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"ቅንብሮች"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"ቅንብሮች"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"የቅንብሮች አቋራጭ"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"የአውሮፕላን ሁነታ"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"ተጨማሪ"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"ገመድ አልባ&amp; አውታረ መረቦች"</string>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index e4c5ddf..b2d2c45 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -278,6 +278,8 @@
     <string name="settings_label" msgid="1626402585530130914">"الإعدادات"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"الإعدادات"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"اختصار الإعدادات"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"وضع الطائرة"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"المزيد"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"اللاسلكي والشبكات"</string>
@@ -3311,7 +3313,7 @@
     <string name="notification_log_details_ranking_null" msgid="244660392058720919">"ترتيب العناصر مفقود."</string>
     <string name="notification_log_details_ranking_none" msgid="599607025882587844">"لا يحتوي ترتيب العناصر على هذا المفتاح."</string>
     <string name="special_access" msgid="8275242424094109976">"الوصول الخاص"</string>
-    <string name="confirm_convert_to_fbe_warning" msgid="1487005506049137659">"هل تريد بالتأكيد مسح بيانات المستخدم والتحويل إلى تشفير الملفات؟"</string>
+    <string name="confirm_convert_to_fbe_warning" msgid="1487005506049137659">"هل تريد فعلًا مسح بيانات المستخدم والتحويل إلى تشفير الملفات؟"</string>
     <string name="button_confirm_convert_fbe" msgid="7101855374850373091">"مسح وتحويل"</string>
     <string name="reset_shortcut_manager_throttling" msgid="6495066467198668994">"‏هل تريد إعادة تعيين تقييد المعدل في ShortcutManager؟"</string>
     <string name="reset_shortcut_manager_throttling_complete" msgid="1826770872063707900">"‏تمت إعادة تعيين تقييد المعدل في ShortcutManager."</string>
diff --git a/res/values-az-rAZ/strings.xml b/res/values-az-rAZ/strings.xml
index 81774c5..ed6e36a 100644
--- a/res/values-az-rAZ/strings.xml
+++ b/res/values-az-rAZ/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Ayarlar"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Ayarlar"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Ayarlar qısayolunu seçin"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Uçuş rejimi"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Digər"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Simsiz &amp; şəbəkələr"</string>
diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml
index ddef56a..4d1688c 100644
--- a/res/values-b+sr+Latn/strings.xml
+++ b/res/values-b+sr+Latn/strings.xml
@@ -272,6 +272,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Podešavanja"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Podešavanja"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Prečica podešavanja"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Režim rada u avionu"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Još"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Bežična veza i mreže"</string>
diff --git a/res/values-be-rBY/strings.xml b/res/values-be-rBY/strings.xml
index 5d1e37f..b66744e 100644
--- a/res/values-be-rBY/strings.xml
+++ b/res/values-be-rBY/strings.xml
@@ -274,6 +274,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Налады"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Налады"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Ярлык налад"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Рэжым самалёту"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Яшчэ"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Бесправадныя і правадныя сеткі"</string>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index 4948c6e..17566c6 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Настройки"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Настройки"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Пряк път за настройките"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Самолетен режим"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Още"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Кабелни и безжични мрежи"</string>
diff --git a/res/values-bn-rBD/strings.xml b/res/values-bn-rBD/strings.xml
index d7ca576..e4a1695 100644
--- a/res/values-bn-rBD/strings.xml
+++ b/res/values-bn-rBD/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"সেটিংস"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"সেটিংস"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"সেটিংস শর্টকাট"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"বিমান মোড"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"আরো"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"ওয়্যারলেস ও নেটওয়ার্ক"</string>
@@ -2683,11 +2685,11 @@
     <string name="notification_listener_disable_warning_summary" msgid="6738915379642948000">"যদি আপনি <xliff:g id="NOTIFICATION_LISTENER_NAME">%1$s</xliff:g> এর জন্য বিজ্ঞপ্তির অ্যাক্সেস বন্ধ করেন, তাহলে \'বিরক্ত করবেন না\' এর অ্যাক্সেসও বন্ধ হয়ে যেতে পারে৷"</string>
     <string name="notification_listener_disable_warning_confirm" msgid="8333442186428083057">"বন্ধ করুন"</string>
     <string name="notification_listener_disable_warning_cancel" msgid="8586417377104211584">"বাতিল করুন"</string>
-    <string name="vr_listeners_title" msgid="1318901577754715777">"VR সহায়তাকারী পরিষেবাগুলি"</string>
+    <string name="vr_listeners_title" msgid="1318901577754715777">"(ভিআর)VR সহায়তাকারী পরিষেবাগুলি"</string>
     <string name="no_vr_listeners" msgid="2689382881717507390">"vr সহায়তাকারী পরিষেবা হিসাবে চলার জন্য কোনো অ্যাপ্লিকেশান ইনস্টল করা নেই৷"</string>
-    <string name="vr_listener_security_warning_title" msgid="8309673749124927122">"<xliff:g id="SERVICE">%1$s</xliff:g> এর জন্য VR পরিষেবার অ্যাক্সেসের অনুমতি দেবেন?"</string>
+    <string name="vr_listener_security_warning_title" msgid="8309673749124927122">"<xliff:g id="SERVICE">%1$s</xliff:g> এর জন্য (ভিআর)VR পরিষেবার অ্যাক্সেসের অনুমতি দেবেন?"</string>
     <string name="vr_listener_security_warning_summary" msgid="6931541068825094653">"ভার্চুয়াল রিয়েলিটি মোডে আপনি যখন অ্যাপ্লিকেশানগুলি ব্যবহার করবেন তখন <xliff:g id="VR_LISTENER_NAME">%1$s</xliff:g> চালাতে পারবেন৷"</string>
-    <string name="display_vr_pref_title" msgid="8104485269504335481">"যখন ডিভাইসটি VR মোডে থাকে"</string>
+    <string name="display_vr_pref_title" msgid="8104485269504335481">"যখন ডিভাইসটি (ভিআর)VR মোডে থাকে"</string>
     <string name="display_vr_pref_low_persistence" msgid="5707494209944718537">"অস্পষ্ট কমান (প্রস্তাবিত)"</string>
     <string name="display_vr_pref_off" msgid="2190091757123260989">"ফ্লিকার কমান"</string>
     <string name="manage_zen_access_title" msgid="2611116122628520522">"বিরক্ত করবেন না অ্যাক্সেস করুন"</string>
diff --git a/res/values-bs-rBA/strings.xml b/res/values-bs-rBA/strings.xml
index d45767d..530ce8d 100644
--- a/res/values-bs-rBA/strings.xml
+++ b/res/values-bs-rBA/strings.xml
@@ -272,6 +272,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Postavke"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Postavke"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Prečica za postavke"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Način rada u avionu"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Više"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Bežična veza i mreže"</string>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index c5f56ba..51a4c68 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Configuració"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Configuració"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Drecera de configuració"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Mode d\'avió"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Més"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Connexions sense fil i xarxes"</string>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index 066852a..9dc8292 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -274,6 +274,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Nastavení"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Nastavení"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Zástupce nastavení"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Režim Letadlo"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Další"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Bezdrátová připojení a sítě"</string>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index 13e9356..fa51fdb 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Indstillinger"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Indstillinger"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Genvej til Indstillinger"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Flytilstand"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Mere"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Trådløs og netværk"</string>
@@ -2416,7 +2418,7 @@
     <string name="user_enable_calling_confirm_message" msgid="8061594235219352787">"Opkaldshistorikken deles med denne bruger."</string>
     <string name="user_enable_calling_and_sms_confirm_title" msgid="7243308401401932681">"Vil du aktivere telefonopkald og sms?"</string>
     <string name="user_enable_calling_and_sms_confirm_message" msgid="4025082715546544967">"Opkalds- og sms-historikken deles med denne bruger."</string>
-    <string name="emergency_info_title" msgid="208607506217060337">"Oplysninger om nødopkald"</string>
+    <string name="emergency_info_title" msgid="208607506217060337">"Oplysninger i nødsituationer"</string>
     <string name="application_restrictions" msgid="8207332020898004394">"Tillad apps og indhold"</string>
     <string name="apps_with_restrictions_header" msgid="3660449891478534440">"Applikationer med begrænsninger"</string>
     <string name="apps_with_restrictions_settings_button" msgid="3841347287916635821">"Udvid indstillingerne for applikationen"</string>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index 68c8bc5..d14ebf7 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -269,6 +269,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Einstellungen"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Einstellungen"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Einstellungsverknüpfung"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Flugmodus"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Mehr"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Drahtlos &amp; Netzwerke"</string>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index aae8d6b..7b3a118 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Ρυθμίσεις"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Ρυθμίσεις"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Συντόμευση ρυθμίσεων"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Λειτουργία πτήσης"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Περισσότερα"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Ασύρματο και δίκτυα"</string>
diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml
index 61e5454..5188e6b 100644
--- a/res/values-en-rAU/strings.xml
+++ b/res/values-en-rAU/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Settings"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Settings"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Settings shortcut"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Aeroplane mode"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"More"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Wireless &amp; networks"</string>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index 0749663..c3dad02 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Settings"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Settings"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Settings shortcut"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Aeroplane mode"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"More"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Wireless &amp; networks"</string>
diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml
index 0749663..c3dad02 100644
--- a/res/values-en-rIN/strings.xml
+++ b/res/values-en-rIN/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Settings"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Settings"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Settings shortcut"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Aeroplane mode"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"More"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Wireless &amp; networks"</string>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index c1e9112..5804ec9 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Configuración"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Configuración"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Configuración"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Modo avión"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Más"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Conexiones inalámbricas y redes"</string>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index 6bb1039..0d65ca9 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Ajustes"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Ajustes"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Acceso a Ajustes"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Modo avión"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Más"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Conexiones inalámbricas y redes"</string>
@@ -554,7 +556,7 @@
     <string name="lockpattern_tutorial_cancel_label" msgid="6431583477570493261">"Cancelar"</string>
     <string name="lockpattern_tutorial_continue_label" msgid="3559793618653400434">"Siguiente"</string>
     <string name="lock_setup" msgid="3355847066343753943">"Se ha completado la configuración."</string>
-    <string name="device_admin_title" msgid="3562216873644263804">"Administración de dispositivos"</string>
+    <string name="device_admin_title" msgid="3562216873644263804">"Administración del dispositivo"</string>
     <string name="manage_device_admin" msgid="5059296715271077278">"Administradores de dispositivos"</string>
     <string name="manage_device_admin_summary" msgid="7672709110988761075">"Ver o desactivar administradores de dispositivos"</string>
     <string name="manage_trust_agents" msgid="4629279457536987768">"Agentes de confianza"</string>
diff --git a/res/values-et-rEE/strings.xml b/res/values-et-rEE/strings.xml
index aad5f57..8effb9e 100644
--- a/res/values-et-rEE/strings.xml
+++ b/res/values-et-rEE/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Seaded"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Seaded"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Seadete otsetee"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Lennurežiim"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Rohkem"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Traadita ühendus ja võrgud"</string>
diff --git a/res/values-eu-rES/strings.xml b/res/values-eu-rES/strings.xml
index 4d16e4d..2287d8f 100644
--- a/res/values-eu-rES/strings.xml
+++ b/res/values-eu-rES/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Ezarpenak"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Ezarpenak"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Ezarpenen lasterbidea"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Hegaldi modua"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Gehiago"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Hari gabeko konexioak eta sareak"</string>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index a3fe937..66c0a26 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"تنظیمات"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"تنظیمات"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"میان‌بر تنظیمات"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"حالت هواپیما"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"بیشتر"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"بی‌سیم و شبکه‌ها"</string>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index e9aa48c..8ad02b6 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Asetukset"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Asetukset"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Asetukset-pikakuvake"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Lentokonetila"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Lisää"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Langaton verkko ja verkot"</string>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index 29f6f8b..b6e5915 100644
--- a/res/values-fr-rCA/strings.xml
+++ b/res/values-fr-rCA/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Paramètres"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Paramètres"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Raccourci vers les paramètres"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Mode avion"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Plus"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Sans fil et réseaux"</string>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index 5ce666b..a1562a3 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Paramètres"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Paramètres"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Raccourci vers les paramètres"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Mode Avion"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Plus"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Sans fil et réseaux"</string>
diff --git a/res/values-gl-rES/strings.xml b/res/values-gl-rES/strings.xml
index 88532a3..086d187 100644
--- a/res/values-gl-rES/strings.xml
+++ b/res/values-gl-rES/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Configuración"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Configuración"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Atallo de configuración"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Modo avión"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Máis"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Sen fíos e redes"</string>
diff --git a/res/values-gu-rIN/strings.xml b/res/values-gu-rIN/strings.xml
index 17b9700..6bec17f 100644
--- a/res/values-gu-rIN/strings.xml
+++ b/res/values-gu-rIN/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"સેટિંગ્સ"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"સેટિંગ્સ"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"સેટિંગ્સ શૉર્ટકટ"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"એરપ્લેન મોડ"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"વધુ"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"વાયરલેસ અને નેટવર્ક્સ"</string>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index 1a7dbc4..747e00a 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"सेटिंग"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"सेटिंग"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"सेटिंग शॉर्टकट"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"हवाई जहाज मोड"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"अधिक"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"वायरलेस और नेटवर्क"</string>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index 7dd3198..018db7a 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -272,6 +272,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Postavke"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Postavke"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Prečac postavki"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Način rada u zrakoplovu"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Više"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Bežično povezivanje i mreže"</string>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index e474ab3..c4aa8c1 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Beállítások"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Beállítások"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Beállítások parancsikon"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Repülési üzemmód"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Továbbiak"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Vezeték nélküli és egyéb hálózatok"</string>
diff --git a/res/values-hy-rAM/strings.xml b/res/values-hy-rAM/strings.xml
index 541bcb4..a573849 100644
--- a/res/values-hy-rAM/strings.xml
+++ b/res/values-hy-rAM/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Կարգավորումներ"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Կարգավորումներ"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Կարգավորումների դյուրանցում"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Ինքնաթիռի ռեժիմ"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Ավելին"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Անլար կապ և ցանցեր"</string>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index 38ba841..ea4f508 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Setelan"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Setelan"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Pintasan setelan"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Mode pesawat"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Lainnya"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Jaringan &amp; nirkabel"</string>
diff --git a/res/values-is-rIS/strings.xml b/res/values-is-rIS/strings.xml
index 66f10fb..e1763dd 100644
--- a/res/values-is-rIS/strings.xml
+++ b/res/values-is-rIS/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Stillingar"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Stillingar"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Flýtileið stillinga"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Flugstilling"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Meira"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Þráðlaus net og símkerfi"</string>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index a6cd39c..78dbed0 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Impostazioni"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Impostazioni"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Scorciatoia Impostazioni"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Modalità aereo"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Altro"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Wireless e reti"</string>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index 3daa918..85671ee 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -274,6 +274,8 @@
     <string name="settings_label" msgid="1626402585530130914">"הגדרות"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"הגדרות"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"קיצור דרך של הגדרות"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"מצב טיסה"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"עוד"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"אלחוטי ורשתות"</string>
@@ -1965,8 +1967,7 @@
     <string name="battery_saver" msgid="1426682272004907982">"חיסכון בסוללה"</string>
     <string name="battery_saver_turn_on_automatically_title" msgid="9023847300114669426">"הפעל אוטומטית"</string>
     <string name="battery_saver_turn_on_automatically_never" msgid="6610846456314373">"אף פעם"</string>
-    <!-- no translation found for battery_saver_turn_on_automatically_pct (8665950426992057191) -->
-    <skip />
+    <string name="battery_saver_turn_on_automatically_pct" msgid="8665950426992057191">"סוללה ברמת טעינה של <xliff:g id="PERCENT">%1$s</xliff:g>"</string>
     <string name="process_stats_summary_title" msgid="1144688045609771677">"סטטיסטיקה של תהליך"</string>
     <string name="process_stats_summary" msgid="109387941605607762">"סטטיסטיקה של מומחי מחשבים על התהליכים הפועלים"</string>
     <string name="app_memory_use" msgid="7849258480392171939">"זיכרון בשימוש"</string>
@@ -3287,10 +3288,8 @@
     <string name="support_sign_in_required_help" msgid="5200654782405538114">"לא מצליח להיכנס?"</string>
     <string name="support_disclaimer_title" msgid="4825302018208770031">"שליחת פרטי מערכת"</string>
     <string name="support_disclaimer_do_not_show" msgid="3378367075323727539">"אל תציג שוב"</string>
-    <!-- no translation found for support_account_request_prefix (6387847874661861650) -->
-    <skip />
-    <!-- no translation found for support_account_picker_add_account (5076277544846506214) -->
-    <skip />
+    <string name="support_account_request_prefix" msgid="6387847874661861650">"מבקש בשם"</string>
+    <string name="support_account_picker_add_account" msgid="5076277544846506214">"הוסף חשבון"</string>
     <string name="managed_profile_settings_title" msgid="2729481936758125054">"הגדרות של פרופיל עבודה"</string>
     <string name="managed_profile_contact_search_title" msgid="6034734926815544221">"חיפוש אנשי קשר"</string>
     <string name="managed_profile_contact_search_summary" msgid="5431253552272970512">"אפשר לחיפושי אנשי קשר שמבצע הארגון לזהות מתקשרים ואנשי קשר"</string>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index d4aeaf7..b69ff62 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"設定"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"設定"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"設定のショートカット"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"機内モード"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"もっと見る"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"無線とネットワーク"</string>
diff --git a/res/values-ka-rGE/strings.xml b/res/values-ka-rGE/strings.xml
index 4e59991..e25d2a2 100644
--- a/res/values-ka-rGE/strings.xml
+++ b/res/values-ka-rGE/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"პარამეტრები"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"პარამეტრები"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"პარამეტრების მალსახმობი"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"თვითმფრინავის რეჟიმი"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"დამატებით"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"უსადენო კავშირი და ქსელები"</string>
diff --git a/res/values-kk-rKZ/strings.xml b/res/values-kk-rKZ/strings.xml
index 3c69f6e..1a04cb0 100644
--- a/res/values-kk-rKZ/strings.xml
+++ b/res/values-kk-rKZ/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Параметрлер"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Параметрлер"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Параметрлердің төте пернелері"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Ұшақ режимі"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Басқалары"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Сымсыз желілер"</string>
diff --git a/res/values-km-rKH/strings.xml b/res/values-km-rKH/strings.xml
index 77947dc..b94b363 100644
--- a/res/values-km-rKH/strings.xml
+++ b/res/values-km-rKH/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"ការ​កំណត់"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"ការ​កំណត់"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"កំណត់​ផ្លូវកាត់"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"ពេលជិះយន្តហោះ"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"ច្រើន​ទៀត"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"ឥត​ខ្សែ &amp; បណ្ដាញ"</string>
diff --git a/res/values-kn-rIN/strings.xml b/res/values-kn-rIN/strings.xml
index 5743752..0cc56fb 100644
--- a/res/values-kn-rIN/strings.xml
+++ b/res/values-kn-rIN/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"ಸೆಟ್ಟಿಂಗ್‌ಗಳ ಶಾರ್ಟ್‌ಕಟ್‌"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"ಏರ್‌ಪ್ಲೇನ್ ಮೋಡ್"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"ಇನ್ನಷ್ಟು"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"ವಯರ್‌ಲೆಸ್ &amp; ನೆಟ್‌ವರ್ಕ್‌ಗಳು"</string>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index 7db0b40..7171d98 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"설정"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"설정"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"설정 바로가기"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"비행기 모드"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"더보기"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"무선 및 네트워크 설정"</string>
@@ -1931,8 +1933,7 @@
     <string name="battery_saver" msgid="1426682272004907982">"배터리 세이버"</string>
     <string name="battery_saver_turn_on_automatically_title" msgid="9023847300114669426">"자동으로 사용 설정"</string>
     <string name="battery_saver_turn_on_automatically_never" msgid="6610846456314373">"사용 안함"</string>
-    <!-- no translation found for battery_saver_turn_on_automatically_pct (8665950426992057191) -->
-    <skip />
+    <string name="battery_saver_turn_on_automatically_pct" msgid="8665950426992057191">"배터리 잔량 <xliff:g id="PERCENT">%1$s</xliff:g>"</string>
     <string name="process_stats_summary_title" msgid="1144688045609771677">"프로세스 통계"</string>
     <string name="process_stats_summary" msgid="109387941605607762">"프로세스 실행에 관한 통계"</string>
     <string name="app_memory_use" msgid="7849258480392171939">"메모리 사용량"</string>
@@ -3221,10 +3222,8 @@
     <string name="support_sign_in_required_help" msgid="5200654782405538114">"로그인할 수 없나요?"</string>
     <string name="support_disclaimer_title" msgid="4825302018208770031">"시스템 정보 보내기"</string>
     <string name="support_disclaimer_do_not_show" msgid="3378367075323727539">"다시 표시 안 함"</string>
-    <!-- no translation found for support_account_request_prefix (6387847874661861650) -->
-    <skip />
-    <!-- no translation found for support_account_picker_add_account (5076277544846506214) -->
-    <skip />
+    <string name="support_account_request_prefix" msgid="6387847874661861650">"요청 계정:"</string>
+    <string name="support_account_picker_add_account" msgid="5076277544846506214">"계정 추가"</string>
     <string name="managed_profile_settings_title" msgid="2729481936758125054">"직장 프로필 설정"</string>
     <string name="managed_profile_contact_search_title" msgid="6034734926815544221">"연락처 검색"</string>
     <string name="managed_profile_contact_search_summary" msgid="5431253552272970512">"조직에서 연락처를 검색하여 발신자 및 연락처를 확인할 수 있도록 허용합니다."</string>
diff --git a/res/values-ky-rKG/strings.xml b/res/values-ky-rKG/strings.xml
index 6464e40..dbf39b6 100644
--- a/res/values-ky-rKG/strings.xml
+++ b/res/values-ky-rKG/strings.xml
@@ -269,6 +269,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Жөндөөлөр"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Жөндөөлөр"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Жөндөөлөр"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Учак режими"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Дагы"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Зымсыз тармактар"</string>
diff --git a/res/values-lo-rLA/strings.xml b/res/values-lo-rLA/strings.xml
index 7cb5bd5..369b1b6 100644
--- a/res/values-lo-rLA/strings.xml
+++ b/res/values-lo-rLA/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"ການຕັ້ງຄ່າ"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"ການຕັ້ງຄ່າ"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"ທາງລັດການຕັ້ງຄ່າ"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"ໂໝດຢູ່ໃນຍົນ"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"ເພີ່ມເຕີມ"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"ລະບົບໄຮ້ສາຍ &amp; ເຄືອຂ່າຍ"</string>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index ba30424..bf00362 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -274,6 +274,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Nustatymai"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Nustatymai"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Spartusis nustatymų klavišas"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Lėktuvo režimas"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Daugiau"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Belaidis ryšys ir tinklai"</string>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index a5fc98d..8489d15 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -272,6 +272,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Iestatījumi"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Iestatījumi"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Saīsne Iestatījumi"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Lidojuma režīms"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Vairāk"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Bezvadu sakari un tīkli"</string>
diff --git a/res/values-mk-rMK/strings.xml b/res/values-mk-rMK/strings.xml
index c42202c..33c0864 100644
--- a/res/values-mk-rMK/strings.xml
+++ b/res/values-mk-rMK/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Поставки"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Поставки"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Кратенка за подесувања"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Режим на работа во авион"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Повеќе"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Безжичен и мрежи"</string>
diff --git a/res/values-ml-rIN/strings.xml b/res/values-ml-rIN/strings.xml
index caec2a1..e95e606 100644
--- a/res/values-ml-rIN/strings.xml
+++ b/res/values-ml-rIN/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"ക്രമീകരണം"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"ക്രമീകരണം"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"ക്രമീകരണങ്ങളിലേയ്ക്ക്"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"ഫ്ലൈറ്റ് മോഡ്"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"കൂടുതൽ"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"വയർലസ്സും നെറ്റ്‌വർക്കും"</string>
@@ -1931,8 +1933,7 @@
     <string name="battery_saver" msgid="1426682272004907982">"ബാറ്ററി സേവർ"</string>
     <string name="battery_saver_turn_on_automatically_title" msgid="9023847300114669426">"ഓട്ടോമാറ്റിക്കായി ഓണാക്കുക"</string>
     <string name="battery_saver_turn_on_automatically_never" msgid="6610846456314373">"ഒരിക്കലും"</string>
-    <!-- no translation found for battery_saver_turn_on_automatically_pct (8665950426992057191) -->
-    <skip />
+    <string name="battery_saver_turn_on_automatically_pct" msgid="8665950426992057191">"<xliff:g id="PERCENT">%1$s</xliff:g> ബാറ്ററിയിൽ"</string>
     <string name="process_stats_summary_title" msgid="1144688045609771677">"പ്രോസസ്സ് സ്ഥിതിവിവരക്കണക്കുകൾ"</string>
     <string name="process_stats_summary" msgid="109387941605607762">"പ്രവർത്തന പ്രോസസ്സുകളെക്കുറിച്ചുള്ള Geeky സ്ഥിതിവിവരക്കണക്കുകൾ"</string>
     <string name="app_memory_use" msgid="7849258480392171939">"മെമ്മറി ഉപയോഗം"</string>
@@ -3221,10 +3222,8 @@
     <string name="support_sign_in_required_help" msgid="5200654782405538114">"സൈൻ ഇൻ ചെയ്യാൻ കഴിയുന്നില്ലേ?"</string>
     <string name="support_disclaimer_title" msgid="4825302018208770031">"സിസ്റ്റം വിവരങ്ങൾ അയയ്ക്കുക"</string>
     <string name="support_disclaimer_do_not_show" msgid="3378367075323727539">"വീണ്ടും കാണിക്കരുത്"</string>
-    <!-- no translation found for support_account_request_prefix (6387847874661861650) -->
-    <skip />
-    <!-- no translation found for support_account_picker_add_account (5076277544846506214) -->
-    <skip />
+    <string name="support_account_request_prefix" msgid="6387847874661861650">"ഇനിപ്പറയുന്നതായി അഭ്യർത്ഥിക്കുന്നു"</string>
+    <string name="support_account_picker_add_account" msgid="5076277544846506214">"അക്കൗണ്ട് ചേർക്കുക"</string>
     <string name="managed_profile_settings_title" msgid="2729481936758125054">"ഔദ്യോഗിക പ്രൊഫൈൽ ക്രമീകരണം"</string>
     <string name="managed_profile_contact_search_title" msgid="6034734926815544221">"കോൺടാക്റ്റ് തിരയൽ"</string>
     <string name="managed_profile_contact_search_summary" msgid="5431253552272970512">"വിളിക്കുന്നവരെയും കോൺടാക്റ്റുകളെയും തിരിച്ചറിയുന്നതിന് കോൺടാക്റ്റുകൾ തിരയാൻ നിങ്ങളുടെ സ്ഥാപനത്തെ അനുവദിക്കുക"</string>
diff --git a/res/values-mn-rMN/strings.xml b/res/values-mn-rMN/strings.xml
index d2b492d..dc3823f 100644
--- a/res/values-mn-rMN/strings.xml
+++ b/res/values-mn-rMN/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Тохиргоо"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Тохиргоо"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Тохиргооны товчилбор"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Нислэгийн горим"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Цааш"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Утасгүй &amp; сүлжээ"</string>
diff --git a/res/values-mr-rIN/strings.xml b/res/values-mr-rIN/strings.xml
index 651c50f..992259e 100644
--- a/res/values-mr-rIN/strings.xml
+++ b/res/values-mr-rIN/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"सेटिंग्ज"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"सेटिंग्ज"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"सेटिंग्ज शॉर्टकट"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"विमान मोड"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"अधिक"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"वायरलेस आणि नेटवर्क"</string>
diff --git a/res/values-ms-rMY/strings.xml b/res/values-ms-rMY/strings.xml
index 9baf311..4c1152a 100644
--- a/res/values-ms-rMY/strings.xml
+++ b/res/values-ms-rMY/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Tetapan"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Tetapan"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Pintasan tetapan"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Mod pesawat"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Lagi"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Wayarles &amp; rangkaian"</string>
diff --git a/res/values-my-rMM/strings.xml b/res/values-my-rMM/strings.xml
index 3fd39e3..7f8c287 100644
--- a/res/values-my-rMM/strings.xml
+++ b/res/values-my-rMM/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"ဆက်တင်များ"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"ဆက်တင်များ"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"ဆက်တင်အတိုကောက်"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"လေယာဉ်ပေါ်သုံးစနစ်"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"နောက်ထပ်"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"ကြိုးမဲ့နှင့် ကွန်ယက်များ"</string>
@@ -3220,7 +3222,7 @@
     <string name="support_sign_in_required_help" msgid="5200654782405538114">"လက်မှတ်ထိုးဝင်၍ မရဘူးလား။"</string>
     <string name="support_disclaimer_title" msgid="4825302018208770031">"စနစ်အချက်အလက်များကို ပို့ပါ"</string>
     <string name="support_disclaimer_do_not_show" msgid="3378367075323727539">"နောက်တစ်ခါ မပြပါနှင့်"</string>
-    <string name="support_account_request_prefix" msgid="6387847874661861650">"ဤအကောင့်အဖြစ် တောင်းဆိုနေသည်"</string>
+    <string name="support_account_request_prefix" msgid="6387847874661861650">"အဖြစ် တောင်းဆိုနေသည်"</string>
     <string name="support_account_picker_add_account" msgid="5076277544846506214">"အကောင့်ထည့်ရန်"</string>
     <string name="managed_profile_settings_title" msgid="2729481936758125054">"အလုပ်ပရိုဖိုင်ဆက်တင်များ"</string>
     <string name="managed_profile_contact_search_title" msgid="6034734926815544221">"အဆက်အသွယ်ကို ရှာဖွေပါ"</string>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index 2cd9d69..6c73b49 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Innstillinger"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Innstillinger"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Snarvei for Innstillinger"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Flymodus"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Mer"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Trådløst og nettverk"</string>
diff --git a/res/values-ne-rNP/strings.xml b/res/values-ne-rNP/strings.xml
index 53533f7..872246d 100644
--- a/res/values-ne-rNP/strings.xml
+++ b/res/values-ne-rNP/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"सेटिङहरू"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"सेटिङहरू"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"सेटिङ सर्टकट"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"हवाइजहाज मोड"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"थप"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"ताररहित सञ्जाल"</string>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index 662d649..7d075ed 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Instellingen"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Instellingen"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Snelle link voor instellingen"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Vliegtuigmodus"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Meer"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Draadloos en netwerken"</string>
diff --git a/res/values-pa-rIN/strings.xml b/res/values-pa-rIN/strings.xml
index dd87890..c8e74e8 100644
--- a/res/values-pa-rIN/strings.xml
+++ b/res/values-pa-rIN/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"ਸੈਟਿੰਗਾਂ"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"ਸੈਟਿੰਗਾਂ"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"ਸੈਟਿੰਗਾਂ ਸ਼ਾਰਟਕੱਟ"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"ਹਵਾਈ ਜਹਾਜ਼ ਮੋਡ"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"ਹੋਰ"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"ਵਾਇਰਲੈੱਸ ਅਤੇ ਨੈੱਟਵਰਕ"</string>
@@ -3220,7 +3222,7 @@
     <string name="support_sign_in_required_help" msgid="5200654782405538114">"ਕੀ ਸਾਈਨ ਇਨ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ?"</string>
     <string name="support_disclaimer_title" msgid="4825302018208770031">"ਸਿਸਟਮ ਜਾਣਕਾਰੀ ਭੇਜੋ"</string>
     <string name="support_disclaimer_do_not_show" msgid="3378367075323727539">"ਦੁਬਾਰਾ ਨਾ ਵਿਖਾਓ"</string>
-    <string name="support_account_request_prefix" msgid="6387847874661861650">"ਦੇ ਤੌਰ \'ਤੇ ਬੇਨਤੀ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ"</string>
+    <string name="support_account_request_prefix" msgid="6387847874661861650">"ਇਸ ਵਜੋਂ ਬੇਨਤੀ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ"</string>
     <string name="support_account_picker_add_account" msgid="5076277544846506214">"ਖਾਤਾ ਸ਼ਾਮਲ ਕਰੋ"</string>
     <string name="managed_profile_settings_title" msgid="2729481936758125054">"ਕੰਮ ਪ੍ਰੋਫਾਈਲ ਸੈਟਿੰਗਾਂ"</string>
     <string name="managed_profile_contact_search_title" msgid="6034734926815544221">"ਸੰਪਰਕ ਖੋਜ"</string>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index 8e7cc25..ae2f48c 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -274,6 +274,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Ustawienia"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Ustawienia"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Skrót do ustawień"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Tryb samolotowy"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Więcej"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Sieci zwykłe i bezprzewodowe"</string>
diff --git a/res/values-pt-rBR/strings.xml b/res/values-pt-rBR/strings.xml
index 2fd9cd0..609e9a1 100644
--- a/res/values-pt-rBR/strings.xml
+++ b/res/values-pt-rBR/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Configurações"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Configurar"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Atalho para as configurações"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Modo avião"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Mais"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Redes sem fio e outras"</string>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index 194b70c..90c6b45 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Definições"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Definições"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Atalho das definições"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Modo de voo"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Mais"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Redes sem fios e outras"</string>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index 2fd9cd0..609e9a1 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Configurações"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Configurar"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Atalho para as configurações"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Modo avião"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Mais"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Redes sem fio e outras"</string>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index 2241f43..2625c33 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -272,6 +272,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Setări"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Setări"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Comandă rapidă pentru setări"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Mod Avion"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Mai multe"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Wireless și rețele"</string>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 17cd6c5..bee2f9f 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -274,6 +274,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Настройки"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Настройки"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Ярлык настроек"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Режим полета"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Ещё"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Беспроводные сети"</string>
@@ -1965,8 +1967,7 @@
     <string name="battery_saver" msgid="1426682272004907982">"Режим энергосбережения"</string>
     <string name="battery_saver_turn_on_automatically_title" msgid="9023847300114669426">"Включать автоматически"</string>
     <string name="battery_saver_turn_on_automatically_never" msgid="6610846456314373">"Никогда"</string>
-    <!-- no translation found for battery_saver_turn_on_automatically_pct (8665950426992057191) -->
-    <skip />
+    <string name="battery_saver_turn_on_automatically_pct" msgid="8665950426992057191">"при <xliff:g id="PERCENT">%1$s</xliff:g> заряда"</string>
     <string name="process_stats_summary_title" msgid="1144688045609771677">"Статистика процессов"</string>
     <string name="process_stats_summary" msgid="109387941605607762">"Статистика запущенных процессов"</string>
     <string name="app_memory_use" msgid="7849258480392171939">"Использование памяти"</string>
@@ -3285,10 +3286,8 @@
     <string name="support_sign_in_required_help" msgid="5200654782405538114">"Не удается войти"</string>
     <string name="support_disclaimer_title" msgid="4825302018208770031">"Отправьте информацию о системе"</string>
     <string name="support_disclaimer_do_not_show" msgid="3378367075323727539">"Больше не показывать"</string>
-    <!-- no translation found for support_account_request_prefix (6387847874661861650) -->
-    <skip />
-    <!-- no translation found for support_account_picker_add_account (5076277544846506214) -->
-    <skip />
+    <string name="support_account_request_prefix" msgid="6387847874661861650">"Запрос от:"</string>
+    <string name="support_account_picker_add_account" msgid="5076277544846506214">"Добавить аккаунт"</string>
     <string name="managed_profile_settings_title" msgid="2729481936758125054">"Настройки рабочего профиля"</string>
     <string name="managed_profile_contact_search_title" msgid="6034734926815544221">"Поиск контактов"</string>
     <string name="managed_profile_contact_search_summary" msgid="5431253552272970512">"Разрешить поиск контактов в организации для определения вызывающих абонентов"</string>
diff --git a/res/values-si-rLK/strings.xml b/res/values-si-rLK/strings.xml
index d0b939c..aec5022 100644
--- a/res/values-si-rLK/strings.xml
+++ b/res/values-si-rLK/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"සැකසීම්"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"සැකසීම්"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"සැකසීම කෙටිමඟ"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"අහස්යානා ආකාරය"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"තවත්"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"නොරැහැන් සහ ජාල"</string>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index 21a41df..4304d85 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -274,6 +274,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Nastavenia"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Nastavenia"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Odkaz na nastavenia"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Režim v lietadle"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Ďalšie"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Bezdrôtové pripojenia a siete"</string>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index ec6de51..f7607e3 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -274,6 +274,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Nastavitve"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Nastavitve"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Bližnjica do nastavitev"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Način za letalo"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Več"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Brezžično in omrežja"</string>
diff --git a/res/values-sq-rAL/strings.xml b/res/values-sq-rAL/strings.xml
index 49371b9..8cded4f 100644
--- a/res/values-sq-rAL/strings.xml
+++ b/res/values-sq-rAL/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Cilësimet"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Cilësimet"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Shkurtorja e cilësimeve"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Modaliteti i aeroplanit"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Më shumë"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Wi-Fi dhe rrjetet"</string>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index 3edc018..420a5c0 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -272,6 +272,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Подешавања"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Подешавања"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Пречица подешавања"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Режим рада у авиону"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Још"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Бежична веза и мреже"</string>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index 1eca079..87a9935 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Inställningar"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Inställningar"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Genväg för inställningar"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Flygplansläge"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Mer"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Trådlöst och nätverk"</string>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index 32d0d62..6bec2cb 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Mipangilio"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Mipangilio"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Mipangilio ya njia ya mkato"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Hali ya ndege"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Mengineyo"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Mitandao isiyotumia waya"</string>
diff --git a/res/values-ta-rIN/strings.xml b/res/values-ta-rIN/strings.xml
index c6d27dd..50f84f2 100644
--- a/res/values-ta-rIN/strings.xml
+++ b/res/values-ta-rIN/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"அமைப்பு"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"அமைப்பு"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"அமைப்பு"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"விமானப் பயன்முறை"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"மேலும்"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"வயர்லெஸ் &amp; நெட்வொர்க்குகள்"</string>
diff --git a/res/values-te-rIN/strings.xml b/res/values-te-rIN/strings.xml
index de758ae..e3b13b5 100644
--- a/res/values-te-rIN/strings.xml
+++ b/res/values-te-rIN/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"సెట్టింగ్‌లు"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"సెట్టింగ్‌లు"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"సెట్టింగ్‌ల సత్వరమార్గం"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"ఎయిర్‌ప్లైన్ మోడ్"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"మరిన్ని"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"వైర్‌లెస్ &amp; నెట్‌వర్క్‌లు"</string>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index a203684..4a29e11 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"การตั้งค่า"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"การตั้งค่า"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"ทางลัดการตั้งค่า"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"โหมดใช้งานบนเครื่องบิน"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"เพิ่มเติม"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"ระบบไร้สายและเครือข่าย"</string>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index c96bcb1..72a916c 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Mga Setting"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Mga Setting"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Shortcut ng Mga Setting"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Airplane mode"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Higit pa"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Wireless at mga network"</string>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index a940e01..f45d2d3 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Ayarlar"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Ayarlar"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Ayarlar kısayolu"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Uçak modu"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Diğer"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Kablosuz özelliği ve ağlar"</string>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index 0ca3ac7..9657602 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -274,6 +274,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Налаштування"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Налаштування"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Ярлик налаштувань"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Режим польоту"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Більше"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Бездротовий зв\'язок і мережі"</string>
diff --git a/res/values-ur-rPK/strings.xml b/res/values-ur-rPK/strings.xml
index 0388739..7b3213e 100644
--- a/res/values-ur-rPK/strings.xml
+++ b/res/values-ur-rPK/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"ترتیبات"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"ترتیبات"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"ترتیبات کا شارٹ کٹ"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"ہوائی جہاز وضع"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"مزید"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"وائرلیس اور نیٹ ورکس"</string>
diff --git a/res/values-uz-rUZ/strings.xml b/res/values-uz-rUZ/strings.xml
index 4b6f213..3d361c9 100644
--- a/res/values-uz-rUZ/strings.xml
+++ b/res/values-uz-rUZ/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Sozlamalar"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Sozlamalar"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Sozlamalar yorlig‘i"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Parvoz rejimi"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Yana"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Simsiz tarmoqlar"</string>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index 45014f8..89c2c74 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Cài đặt"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Cài đặt"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Lối tắt cài đặt"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Chế độ trên máy bay"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Thêm"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Không dây &amp; mạng"</string>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index 60c17b0..81bd327 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"设置"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"设置"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"设置快捷方式"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"飞行模式"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"更多"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"无线和网络"</string>
@@ -711,7 +713,7 @@
     <string name="wifi_more" msgid="3195296805089107950">"更多"</string>
     <string name="wifi_setup_wps" msgid="8128702488486283957">"自动设置 (WPS)"</string>
     <string name="wifi_show_advanced" msgid="3409422789616520979">"高级选项"</string>
-    <string name="wifi_advanced_toggle_description_expanded" msgid="2380600578544493084">"高级选项下拉列表。点按两次即可折叠。"</string>
+    <string name="wifi_advanced_toggle_description_expanded" msgid="2380600578544493084">"高级选项下拉列表。点按两次即可收起。"</string>
     <string name="wifi_advanced_toggle_description_collapsed" msgid="1463812308429197263">"高级选项下拉列表。点按两次即可展开。"</string>
     <string name="wifi_wps_setup_title" msgid="8207552222481570175">"WLAN保护设置"</string>
     <string name="wifi_wps_setup_msg" msgid="315174329121275092">"正在启动 WPS..."</string>
diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml
index c75de70..20d4ca8 100644
--- a/res/values-zh-rHK/strings.xml
+++ b/res/values-zh-rHK/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"設定"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"設定"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"設定捷徑"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"飛行模式"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"更多"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"無線與網絡"</string>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index a911e31..c29edf0 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"設定"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"設定"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"設定捷徑"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"飛航模式"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"更多"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"無線與網路"</string>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index 3b38019..b3ba0c5 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -270,6 +270,8 @@
     <string name="settings_label" msgid="1626402585530130914">"Izilungiselelo"</string>
     <string name="settings_label_launcher" msgid="8344735489639482340">"Izilungiselelo"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Isinqamuleli sezilungiselelo"</string>
+    <!-- no translation found for activity_list_empty (6428823323471264836) -->
+    <skip />
     <string name="airplane_mode" msgid="8837269988154128601">"Imodi yendiza"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"Okuningi"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Amanethiwekhi; nokungenantambo"</string>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 75449b2..4d872b1 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -612,6 +612,8 @@
     <string name="settings_label_launcher">Settings</string>
     <!-- Label for option to select a settings panel as a shortcut -->
     <string name="settings_shortcut">Settings shortcut</string>
+    <!-- Shown in create shortcut activity when there is no shortcut that can be created. [CHAR_LIMIT=None] -->
+    <string name="activity_list_empty">No matching activities found.</string>
     <!-- Wireless controls settings screen, setting check box label -->
     <string name="airplane_mode">Airplane mode</string>
     <!-- Main Settings screen settings title for things like airplane mode, tethering, NFC, VPN.  This will take you to another screen with those settings.  [CHAR LIMIT=30] -->
diff --git a/src/com/android/settings/ApnEditor.java b/src/com/android/settings/ApnEditor.java
index 061c18a..f97811c 100644
--- a/src/com/android/settings/ApnEditor.java
+++ b/src/com/android/settings/ApnEditor.java
@@ -759,6 +759,8 @@
     public void onViewCreated(View view, Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
         view.setOnKeyListener(this);
+        view.setFocusableInTouchMode(true);
+        view.requestFocus();
     }
 
     public boolean onKey(View v, int keyCode, KeyEvent event) {
diff --git a/src/com/android/settings/CreateShortcut.java b/src/com/android/settings/CreateShortcut.java
index 7317738..7cd6748 100644
--- a/src/com/android/settings/CreateShortcut.java
+++ b/src/com/android/settings/CreateShortcut.java
@@ -85,6 +85,11 @@
         return false;
     }
 
+    @Override
+    protected void onSetContentView() {
+        setContentView(R.layout.activity_list);
+    }
+
     /**
      * Perform query on package manager for list items.  The default
      * implementation queries for activities.
diff --git a/src/com/android/settings/DevelopmentSettings.java b/src/com/android/settings/DevelopmentSettings.java
index 867fbfd..41d96d6 100644
--- a/src/com/android/settings/DevelopmentSettings.java
+++ b/src/com/android/settings/DevelopmentSettings.java
@@ -83,6 +83,8 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settings.applications.BackgroundCheckSummary;
 import com.android.settings.dashboard.DashboardFeatureProvider;
+import com.android.settings.development.BugReportPreferenceController;
+import com.android.settings.development.BugReportInPowerPreferenceController;
 import com.android.settings.fuelgauge.InactiveApps;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.search.BaseSearchIndexProvider;
@@ -129,8 +131,6 @@
     private static final String LOCAL_BACKUP_PASSWORD = "local_backup_password";
     private static final String HARDWARE_UI_PROPERTY = "persist.sys.ui.hw";
     private static final String MSAA_PROPERTY = "debug.egl.force_msaa";
-    private static final String BUGREPORT = "bugreport";
-    private static final String BUGREPORT_IN_POWER_KEY = "bugreport_in_power";
     private static final String OPENGL_TRACES_PROPERTY = "debug.egl.trace";
     private static final String TUNER_UI_KEY = "tuner_ui";
     private static final String COLOR_TEMPERATURE_PROPERTY = "persist.sys.debug.color_temp";
@@ -248,8 +248,6 @@
     private SwitchPreference mEnableAdb;
     private Preference mClearAdbKeys;
     private SwitchPreference mEnableTerminal;
-    private Preference mBugreport;
-    private SwitchPreference mBugreportInPower;
     private RestrictedSwitchPreference mKeepScreenOn;
     private SwitchPreference mBtHciSnoopLog;
     private RestrictedSwitchPreference mEnableOemUnlock;
@@ -330,6 +328,8 @@
     private boolean mLogpersistCleared;
     private Dialog mLogpersistClearDialog;
     private DashboardFeatureProvider mDashboardFeatureProvider;
+    private BugReportPreferenceController mBugReportController;
+    private BugReportInPowerPreferenceController mBugReportInPowerController;
 
     public DevelopmentSettings() {
         super(UserManager.DISALLOW_DEBUGGING_FEATURES);
@@ -365,6 +365,9 @@
 
         mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
 
+        mBugReportController = new BugReportPreferenceController(getActivity());
+        mBugReportInPowerController = new BugReportInPowerPreferenceController(getActivity());
+
         setIfOnlyAvailableForAdmins(true);
         if (isUiRestricted() || !Utils.isDeviceProvisioned(getActivity())) {
             // Block access to developer options if the user is not the owner, if user policy
@@ -392,8 +395,9 @@
             mEnableTerminal = null;
         }
 
-        mBugreport = findPreference(BUGREPORT);
-        mBugreportInPower = findAndInitSwitchPref(BUGREPORT_IN_POWER_KEY);
+        mBugReportController.displayPreference(getPreferenceScreen());
+        mBugReportInPowerController.displayPreference(getPreferenceScreen());
+
         mKeepScreenOn = (RestrictedSwitchPreference) findAndInitSwitchPref(KEEP_SCREEN_ON);
         mBtHciSnoopLog = findAndInitSwitchPref(BT_HCI_SNOOP_LOG);
         mEnableOemUnlock = (RestrictedSwitchPreference) findAndInitSwitchPref(ENABLE_OEM_UNLOCK);
@@ -601,6 +605,7 @@
             Preference pref = mAllPrefs.get(i);
             pref.setEnabled(enabled && !mDisabledPrefs.contains(pref));
         }
+        mBugReportInPowerController.enablePreference(enabled);
         updateAllOptions();
     }
 
@@ -702,8 +707,7 @@
                     context.getPackageManager().getApplicationEnabledSetting(TERMINAL_APP_PACKAGE)
                             == PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
         }
-        updateSwitchPreference(mBugreportInPower, Settings.Secure.getInt(cr,
-                Settings.Global.BUGREPORT_IN_POWER_MENU, 0) != 0);
+        mHaveDebugSettings |= mBugReportInPowerController.updatePreference();
         updateSwitchPreference(mKeepScreenOn, Settings.Global.getInt(cr,
                 Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0) != 0);
         updateSwitchPreference(mBtHciSnoopLog, Settings.Secure.getInt(cr,
@@ -765,6 +769,7 @@
                 onPreferenceTreeClick(cb);
             }
         }
+        mBugReportInPowerController.resetPreference();
         resetDebuggerOptions();
         writeLogpersistOption(null, true);
         writeLogdSizeOption(null);
@@ -1076,19 +1081,8 @@
     }
 
     private void updateBugreportOptions() {
-        mBugreport.setEnabled(true);
-        mBugreportInPower.setEnabled(true);
-        setBugreportStorageProviderStatus();
-    }
-
-    private void setBugreportStorageProviderStatus() {
-        final ComponentName componentName = new ComponentName("com.android.shell",
-                "com.android.shell.BugreportStorageProvider");
-        final boolean enabled = mBugreportInPower.isChecked();
-        getPackageManager().setComponentEnabledSetting(componentName,
-                enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
-                        : PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
-                0);
+        mBugReportController.enablePreference(true);
+        mBugReportInPowerController.updateBugreportOptions();
     }
 
     // Returns the current state of the system property that controls
@@ -1951,6 +1945,10 @@
             return false;
         }
 
+        if (mBugReportInPowerController.handlePreferenceTreeClick(preference)) {
+            return true;
+        }
+
         if (preference == mEnableAdb) {
             if (mEnableAdb.isChecked()) {
                 mDialogClicked = false;
@@ -1981,11 +1979,6 @@
             pm.setApplicationEnabledSetting(TERMINAL_APP_PACKAGE,
                     mEnableTerminal.isChecked() ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
                             : PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, 0);
-        } else if (preference == mBugreportInPower) {
-            Settings.Secure.putInt(getActivity().getContentResolver(),
-                    Settings.Global.BUGREPORT_IN_POWER_MENU,
-                    mBugreportInPower.isChecked() ? 1 : 0);
-            setBugreportStorageProviderStatus();
         } else if (preference == mKeepScreenOn) {
             Settings.Global.putInt(getActivity().getContentResolver(),
                     Settings.Global.STAY_ON_WHILE_PLUGGED_IN,
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index fe25a8f..aa76517 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -253,7 +253,7 @@
             String action = intent.getAction();
             if (action.equals(Intent.ACTION_USER_ADDED)
                     || action.equals(Intent.ACTION_USER_REMOVED)) {
-                Index.getInstance(getApplicationContext()).update();
+                mSearchFeatureProvider.updateIndex(getApplicationContext());
             }
         }
     };
@@ -310,7 +310,7 @@
     @Override
     public void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
-        Index.getInstance(this).update();
+        mSearchFeatureProvider.updateIndex(getApplicationContext());
     }
 
     @Override
diff --git a/src/com/android/settings/AccountPreference.java b/src/com/android/settings/accounts/AccountPreference.java
similarity index 94%
rename from src/com/android/settings/AccountPreference.java
rename to src/com/android/settings/accounts/AccountPreference.java
index fe39244..7d613b0 100644
--- a/src/com/android/settings/AccountPreference.java
+++ b/src/com/android/settings/accounts/AccountPreference.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.settings;
+package com.android.settings.accounts;
 
 import android.accounts.Account;
 import android.content.Context;
@@ -24,6 +24,8 @@
 import android.util.Log;
 import android.widget.ImageView;
 
+import com.android.settings.R;
+
 import java.util.ArrayList;
 
 /**
@@ -78,6 +80,10 @@
     }
 
     public void setSyncStatus(int status, boolean updateSummary) {
+        if (mStatus == status) {
+            Log.d(TAG, "Status is the same, not changing anything");
+            return;
+        }
         mStatus = status;
         if (!mShowTypeIcon && mSyncStatusIcon != null) {
             mSyncStatusIcon.setImageResource(getSyncStatusIcon(status));
diff --git a/src/com/android/settings/accounts/AccountPreferenceBase.java b/src/com/android/settings/accounts/AccountPreferenceBase.java
index c6581ac..aa5c518 100644
--- a/src/com/android/settings/accounts/AccountPreferenceBase.java
+++ b/src/com/android/settings/accounts/AccountPreferenceBase.java
@@ -32,6 +32,7 @@
 import android.os.UserManager;
 import android.support.v7.preference.PreferenceScreen;
 import android.text.format.DateFormat;
+import android.text.format.DateUtils;
 import android.util.Log;
 
 import com.android.settings.SettingsPreferenceFragment;
@@ -46,6 +47,7 @@
         implements AuthenticatorHelper.OnAccountsUpdateListener {
 
     protected static final String TAG = "AccountSettings";
+    protected static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
 
     public static final String AUTHORITIES_FILTER_KEY = "authorities";
     public static final String ACCOUNT_TYPES_FILTER_KEY = "account_types";
diff --git a/src/com/android/settings/accounts/AccountPreferenceController.java b/src/com/android/settings/accounts/AccountPreferenceController.java
index 2a8eaf6..06d8c2d 100644
--- a/src/com/android/settings/accounts/AccountPreferenceController.java
+++ b/src/com/android/settings/accounts/AccountPreferenceController.java
@@ -147,11 +147,6 @@
     }
 
     @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        return false;
-    }
-
-    @Override
     public String getPreferenceKey() {
         return null;
     }
diff --git a/src/com/android/settings/accounts/AddUserWhenLockedPreferenceController.java b/src/com/android/settings/accounts/AddUserWhenLockedPreferenceController.java
index 898d4a2..10e3610 100644
--- a/src/com/android/settings/accounts/AddUserWhenLockedPreferenceController.java
+++ b/src/com/android/settings/accounts/AddUserWhenLockedPreferenceController.java
@@ -71,11 +71,6 @@
     }
 
     @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        return false;
-    }
-
-    @Override
     public boolean isAvailable() {
         return mUserCaps.isAdmin() &&
                 (!mUserCaps.disallowAddUser() || mUserCaps.disallowAddUserSetByAdmin());
diff --git a/src/com/android/settings/accounts/ManageAccountsSettings.java b/src/com/android/settings/accounts/ManageAccountsSettings.java
index abfa6a1..ce717e2 100644
--- a/src/com/android/settings/accounts/ManageAccountsSettings.java
+++ b/src/com/android/settings/accounts/ManageAccountsSettings.java
@@ -34,9 +34,11 @@
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.os.UserHandle;
+import android.support.annotation.VisibleForTesting;
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.Preference.OnPreferenceClickListener;
 import android.support.v7.preference.PreferenceScreen;
+import android.util.ArraySet;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.Menu;
@@ -47,7 +49,6 @@
 import android.widget.TextView;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.settings.AccountPreference;
 import com.android.settings.R;
 import com.android.settings.SettingsActivity;
 import com.android.settings.Utils;
@@ -56,8 +57,8 @@
 
 import java.util.ArrayList;
 import java.util.Date;
-import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 import static android.content.Intent.EXTRA_USER;
 
@@ -74,7 +75,7 @@
             "com.android.settings.accounts.LAUNCHING_LOCATION_SETTINGS";
 
     private static final int MENU_SYNC_NOW_ID = Menu.FIRST;
-    private static final int MENU_SYNC_CANCEL_ID    = Menu.FIRST + 1;
+    private static final int MENU_SYNC_CANCEL_ID = Menu.FIRST + 1;
 
     private static final int REQUEST_SHOW_SYNC_SETTINGS = 1;
 
@@ -87,6 +88,8 @@
     // mFirstAccount is used for the injected preferences
     private Account mFirstAccount;
 
+    protected Set<String> mUserFacingSyncAuthorities;
+
     @Override
     public int getMetricsCategory() {
         return MetricsEvent.ACCOUNTS_MANAGE_ACCOUNTS;
@@ -131,7 +134,7 @@
         final Activity activity = getActivity();
         final View view = getView();
 
-        mErrorInfoView = (TextView)view.findViewById(R.id.sync_settings_error_info);
+        mErrorInfoView = (TextView) view.findViewById(R.id.sync_settings_error_info);
         mErrorInfoView.setVisibility(View.GONE);
 
         mAuthorities = activity.getIntent().getStringArrayExtra(AUTHORITIES_FILTER_KEY);
@@ -188,8 +191,7 @@
     @Override
     public void onPrepareOptionsMenu(Menu menu) {
         super.onPrepareOptionsMenu(menu);
-        boolean syncActive = !ContentResolver.getCurrentSyncsAsUser(
-                mUserHandle.getIdentifier()).isEmpty();
+        boolean syncActive = !getCurrentSyncs(mUserHandle.getIdentifier()).isEmpty();
         menu.findItem(MENU_SYNC_NOW_ID).setVisible(!syncActive);
         menu.findItem(MENU_SYNC_CANCEL_ID).setVisible(syncActive);
     }
@@ -197,12 +199,12 @@
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
         switch (item.getItemId()) {
-        case MENU_SYNC_NOW_ID:
-            requestOrCancelSyncForAccounts(true);
-            return true;
-        case MENU_SYNC_CANCEL_ID:
-            requestOrCancelSyncForAccounts(false);
-            return true;
+            case MENU_SYNC_NOW_ID:
+                requestOrCancelSyncForAccounts(true);
+                return true;
+            case MENU_SYNC_CANCEL_ID:
+                requestOrCancelSyncForAccounts(false);
+                return true;
         }
         return super.onOptionsItemSelected(item);
     }
@@ -223,7 +225,7 @@
                     SyncAdapterType sa = syncAdapters[j];
                     if (syncAdapters[j].accountType.equals(mAccountType)
                             && ContentResolver.getSyncAutomaticallyAsUser(account, sa.authority,
-                                    userId)) {
+                            userId)) {
                         if (sync) {
                             ContentResolver.requestSyncAsUser(account, sa.authority, userId,
                                     extras);
@@ -238,47 +240,58 @@
 
     @Override
     protected void onSyncStateUpdated() {
-        showSyncState();
-        // Catch any delayed delivery of update messages
         final Activity activity = getActivity();
-        if (activity != null) {
-            activity.invalidateOptionsMenu();
+        // Catch any delayed delivery of update messages
+        if (activity == null || activity.isFinishing()) {
+            return;
+        }
+        showSyncState();
+        activity.invalidateOptionsMenu();
+    }
+
+    private void tryInitUserFacingSyncAuthorities(int userId) {
+        if (mUserFacingSyncAuthorities != null) {
+            return;
+        }
+        mUserFacingSyncAuthorities = new ArraySet<>();
+
+        // only track userfacing sync adapters when deciding if account is synced or not
+        final SyncAdapterType[] syncAdapters = ContentResolver.getSyncAdapterTypesAsUser(userId);
+        for (int k = 0, n = syncAdapters.length; k < n; k++) {
+            final SyncAdapterType sa = syncAdapters[k];
+            if (sa.isUserVisible()) {
+                mUserFacingSyncAuthorities.add(sa.authority);
+            }
         }
     }
 
     /**
      * Shows the sync state of the accounts. Note: it must be called after the accounts have been
-     * loaded, @see #showAccountsIfNeeded().
+     * loaded.
+     *
+     * @see {@link #showAccountsIfNeeded()}.
      */
-    private void showSyncState() {
-        // Catch any delayed delivery of update messages
-        if (getActivity() == null || getActivity().isFinishing()) return;
-
+    @VisibleForTesting
+    void showSyncState() {
         final int userId = mUserHandle.getIdentifier();
+        tryInitUserFacingSyncAuthorities(userId);
 
         // iterate over all the preferences, setting the state properly for each
-        List<SyncInfo> currentSyncs = ContentResolver.getCurrentSyncsAsUser(userId);
+        final List<SyncInfo> currentSyncs = getCurrentSyncs(userId);
 
         boolean anySyncFailed = false; // true if sync on any account failed
         Date date = new Date();
 
-        // only track userfacing sync adapters when deciding if account is synced or not
-        final SyncAdapterType[] syncAdapters = ContentResolver.getSyncAdapterTypesAsUser(userId);
-        HashSet<String> userFacing = new HashSet<String>();
-        for (int k = 0, n = syncAdapters.length; k < n; k++) {
-            final SyncAdapterType sa = syncAdapters[k];
-            if (sa.isUserVisible()) {
-                userFacing.add(sa.authority);
-            }
-        }
-        for (int i = 0, count = getPreferenceScreen().getPreferenceCount(); i < count; i++) {
-            Preference pref = getPreferenceScreen().getPreference(i);
-            if (! (pref instanceof AccountPreference)) {
+        final PreferenceScreen screen = getPreferenceScreen();
+        final int prefCount = screen.getPreferenceCount();
+        for (int i = 0; i < prefCount; i++) {
+            Preference pref = screen.getPreference(i);
+            if (!(pref instanceof AccountPreference)) {
                 continue;
             }
 
-            AccountPreference accountPref = (AccountPreference) pref;
-            Account account = accountPref.getAccount();
+            final AccountPreference accountPref = (AccountPreference) pref;
+            final Account account = accountPref.getAccount();
             int syncCount = 0;
             long lastSuccessTime = 0;
             boolean syncIsFailing = false;
@@ -286,28 +299,33 @@
             boolean syncingNow = false;
             if (authorities != null) {
                 for (String authority : authorities) {
-                    SyncStatusInfo status = ContentResolver.getSyncStatusAsUser(account, authority,
-                            userId);
+                    SyncStatusInfo status = getSyncStatusInfo(account, authority, userId);
                     boolean syncEnabled = isSyncEnabled(userId, account, authority);
-                    boolean authorityIsPending = ContentResolver.isSyncPending(account, authority);
                     boolean activelySyncing = isSyncing(currentSyncs, account, authority);
                     boolean lastSyncFailed = status != null
                             && syncEnabled
                             && status.lastFailureTime != 0
                             && status.getLastFailureMesgAsInt(0)
-                               != ContentResolver.SYNC_ERROR_SYNC_ALREADY_IN_PROGRESS;
-                    if (lastSyncFailed && !activelySyncing && !authorityIsPending) {
+                            != ContentResolver.SYNC_ERROR_SYNC_ALREADY_IN_PROGRESS;
+                    if (lastSyncFailed && !activelySyncing
+                            && !ContentResolver.isSyncPending(account, authority)) {
                         syncIsFailing = true;
                         anySyncFailed = true;
+                        break;
                     }
-                    syncingNow |= activelySyncing;
+
                     if (status != null && lastSuccessTime < status.lastSuccessTime) {
                         lastSuccessTime = status.lastSuccessTime;
                     }
-                    syncCount += syncEnabled && userFacing.contains(authority) ? 1 : 0;
+                    syncCount += syncEnabled && mUserFacingSyncAuthorities.contains(authority)
+                            ? 1 : 0;
+                    syncingNow |= activelySyncing;
+                    if (syncingNow) {
+                        break;
+                    }
                 }
             } else {
-                if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                if (VERBOSE) {
                     Log.v(TAG, "no syncadapters found for " + account);
                 }
             }
@@ -332,14 +350,14 @@
                 accountPref.setSyncStatus(AccountPreference.SYNC_DISABLED, true);
             }
         }
-
-        mErrorInfoView.setVisibility(anySyncFailed ? View.VISIBLE : View.GONE);
+        if (mErrorInfoView != null) {
+            mErrorInfoView.setVisibility(anySyncFailed ? View.VISIBLE : View.GONE);
+        }
     }
 
-
     private boolean isSyncing(List<SyncInfo> currentSyncs, Account account, String authority) {
         final int count = currentSyncs.size();
-        for (int i = 0; i < count;  i++) {
+        for (int i = 0; i < count; i++) {
             SyncInfo syncInfo = currentSyncs.get(i);
             if (syncInfo.account.equals(account) && syncInfo.authority.equals(authority)) {
                 return true;
@@ -348,7 +366,8 @@
         return false;
     }
 
-    private boolean isSyncEnabled(int userId, Account account, String authority) {
+    @VisibleForTesting
+    protected boolean isSyncEnabled(int userId, Account account, String authority) {
         return ContentResolver.getSyncAutomaticallyAsUser(account, authority, userId)
                 && ContentResolver.getMasterSyncAutomaticallyAsUser(userId)
                 && (ContentResolver.getIsSyncableAsUser(account, authority, userId) > 0);
@@ -436,7 +455,7 @@
      */
     private void updatePreferenceIntents(PreferenceScreen prefs) {
         final PackageManager pm = getActivity().getPackageManager();
-        for (int i = 0; i < prefs.getPreferenceCount();) {
+        for (int i = 0; i < prefs.getPreferenceCount(); ) {
             Preference pref = prefs.getPreference(i);
             Intent intent = pref.getIntent();
             if (intent != null) {
@@ -486,8 +505,8 @@
                                 } else {
                                     Log.e(TAG,
                                             "Refusing to launch authenticator intent because"
-                                            + "it exploits Settings permissions: "
-                                            + prefIntent);
+                                                    + "it exploits Settings permissions: "
+                                                    + prefIntent);
                                 }
                                 return true;
                             }
@@ -536,4 +555,14 @@
             }
         }
     }
+
+    @VisibleForTesting
+    protected List<SyncInfo> getCurrentSyncs(int userId) {
+        return ContentResolver.getCurrentSyncsAsUser(userId);
+    }
+
+    @VisibleForTesting
+    protected SyncStatusInfo getSyncStatusInfo(Account account, String authority, int userId) {
+        return ContentResolver.getSyncStatusAsUser(account, authority, userId);
+    }
 }
diff --git a/src/com/android/settings/applications/ManageApplications.java b/src/com/android/settings/applications/ManageApplications.java
index 37b4b96..099d30e 100644
--- a/src/com/android/settings/applications/ManageApplications.java
+++ b/src/com/android/settings/applications/ManageApplications.java
@@ -767,6 +767,12 @@
         private boolean mHasReceivedLoadEntries;
         private boolean mHasReceivedBridgeCallback;
 
+        // These two variables are used to remember and restore the last scroll position when this
+        // fragment is paused. We need this special handling because app entries are added gradually
+        // when we rebuild the list after the user made some changes, like uninstalling an app.
+        private int mLastIndex = -1;
+        private int mLastTop;
+
         private AlphabeticIndex.ImmutableIndex<Locale> mIndex;
         private SectionInfo[] mSections = EMPTY_SECTIONS;
         private int[] mPositionToSectionIndex;
@@ -851,6 +857,10 @@
                     mExtraInfoBridge.pause();
                 }
             }
+            // Record the current scroll position before pausing.
+            mLastIndex = mManageApplications.mListView.getFirstVisiblePosition();
+            View v = mManageApplications.mListView.getChildAt(0);
+            mLastTop = (v == null) ? 0 : (v.getTop() - mManageApplications.mListView.getPaddingTop());
         }
 
         public void release() {
@@ -971,6 +981,12 @@
             }
 
             notifyDataSetChanged();
+            // Restore the last scroll position if the number of entries added so far is bigger than
+            // it.
+            if (mLastIndex != -1 && getCount() > mLastIndex) {
+                mManageApplications.mListView.setSelectionFromTop(mLastIndex, mLastTop);
+                mLastIndex = -1;
+            }
 
             if (mSession.getAllApps().size() != 0
                     && mManageApplications.mListContainer.getVisibility() != View.VISIBLE) {
diff --git a/src/com/android/settings/applications/PackageManagerWrapper.java b/src/com/android/settings/applications/PackageManagerWrapper.java
index d399115..6c783d8 100644
--- a/src/com/android/settings/applications/PackageManagerWrapper.java
+++ b/src/com/android/settings/applications/PackageManagerWrapper.java
@@ -18,6 +18,7 @@
 
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 
 import java.util.List;
@@ -29,24 +30,30 @@
  * the API version supported by Robolectric.
  */
 public interface PackageManagerWrapper {
+
+    /**
+     * Returns the real {@code PackageManager} object.
+     */
+    PackageManager getPackageManager();
+
     /**
      * Calls {@code PackageManager.getInstalledApplicationsAsUser()}.
      *
-     * @see android.content.pm.PackageManager.PackageManager#getInstalledApplicationsAsUser
+     * @see android.content.pm.PackageManager#getInstalledApplicationsAsUser
      */
     List<ApplicationInfo> getInstalledApplicationsAsUser(int flags, int userId);
 
     /**
      * Calls {@code PackageManager.hasSystemFeature()}.
      *
-     * @see android.content.pm.PackageManager.PackageManager#hasSystemFeature
+     * @see android.content.pm.PackageManager#hasSystemFeature
      */
     boolean hasSystemFeature(String name);
 
     /**
      * Calls {@code PackageManager.queryIntentActivitiesAsUser()}.
      *
-     * @see android.content.pm.PackageManager.PackageManager#queryIntentActivitiesAsUser
+     * @see android.content.pm.PackageManager#queryIntentActivitiesAsUser
      */
     List<ResolveInfo> queryIntentActivitiesAsUser(Intent intent, int flags, int userId);
 }
diff --git a/src/com/android/settings/applications/PackageManagerWrapperImpl.java b/src/com/android/settings/applications/PackageManagerWrapperImpl.java
index 8966869..db1d30a 100644
--- a/src/com/android/settings/applications/PackageManagerWrapperImpl.java
+++ b/src/com/android/settings/applications/PackageManagerWrapperImpl.java
@@ -24,6 +24,7 @@
 import java.util.List;
 
 public class PackageManagerWrapperImpl implements PackageManagerWrapper {
+
     private final PackageManager mPm;
 
     public PackageManagerWrapperImpl(PackageManager pm) {
@@ -31,6 +32,11 @@
     }
 
     @Override
+    public PackageManager getPackageManager() {
+        return mPm;
+    }
+
+    @Override
     public List<ApplicationInfo> getInstalledApplicationsAsUser(int flags, int userId) {
         return mPm.getInstalledApplicationsAsUser(flags, userId);
     }
diff --git a/src/com/android/settings/connecteddevice/UsbModePreferenceController.java b/src/com/android/settings/connecteddevice/UsbModePreferenceController.java
index f782e9e..5f700bd 100644
--- a/src/com/android/settings/connecteddevice/UsbModePreferenceController.java
+++ b/src/com/android/settings/connecteddevice/UsbModePreferenceController.java
@@ -58,11 +58,6 @@
     }
 
     @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        return false;
-    }
-
-    @Override
     public boolean isAvailable() {
         return true;
     }
diff --git a/src/com/android/settings/core/PreferenceController.java b/src/com/android/settings/core/PreferenceController.java
index 93ffe36..8f551de 100644
--- a/src/com/android/settings/core/PreferenceController.java
+++ b/src/com/android/settings/core/PreferenceController.java
@@ -18,6 +18,7 @@
 import android.content.Context;
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.PreferenceScreen;
+
 import com.android.settings.search.SearchIndexableRaw;
 
 import java.util.List;
@@ -27,7 +28,7 @@
  */
 public abstract class PreferenceController {
 
-    protected Context mContext;
+    protected final Context mContext;
 
     public PreferenceController(Context context) {
         mContext = context;
@@ -85,7 +86,9 @@
      * @param preference the preference being clicked
      * @return true if click is handled
      */
-    public abstract boolean handlePreferenceTreeClick(Preference preference);
+    public boolean handlePreferenceTreeClick(Preference preference) {
+        return false;
+    }
 
     /**
      * Returns the key for this preference.
diff --git a/src/com/android/settings/dashboard/DashboardDividerDecoration.java b/src/com/android/settings/dashboard/DashboardDividerDecoration.java
deleted file mode 100644
index ed8a077..0000000
--- a/src/com/android/settings/dashboard/DashboardDividerDecoration.java
+++ /dev/null
@@ -1,92 +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.dashboard;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.drawable.Drawable;
-import android.support.v4.view.ViewCompat;
-import android.support.v7.preference.Preference;
-import android.support.v7.preference.PreferenceGroupAdapter;
-import android.support.v7.widget.RecyclerView;
-import android.view.View;
-
-import com.android.settings.overlay.FeatureFactory;
-
-public class DashboardDividerDecoration extends RecyclerView.ItemDecoration {
-
-    private final DashboardFeatureProvider mDashboardFeatureProvider;
-
-    private Drawable mDivider;
-    private int mDividerHeight;
-
-    public DashboardDividerDecoration(Context context) {
-        mDashboardFeatureProvider = FeatureFactory.getFactory(context)
-                .getDashboardFeatureProvider(context);
-    }
-
-    public void setDivider(Drawable divider) {
-        if (divider != null) {
-            mDividerHeight = divider.getIntrinsicHeight();
-        } else {
-            mDividerHeight = 0;
-        }
-        mDivider = divider;
-    }
-
-    public void setDividerHeight(int dividerHeight) {
-        mDividerHeight = dividerHeight;
-    }
-
-    @Override
-    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
-        if (mDivider == null) {
-            return;
-        }
-        final int childCount = parent.getChildCount();
-        final int width = parent.getWidth();
-        for (int childViewIndex = 0; childViewIndex < childCount - 1; childViewIndex++) {
-            final View view = parent.getChildAt(childViewIndex);
-            if (shouldDrawDividerBelow(view, parent)) {
-                int top = (int) ViewCompat.getY(view) + view.getHeight();
-                mDivider.setBounds(0, top, width, top + mDividerHeight);
-                mDivider.draw(c);
-            }
-        }
-    }
-
-    private boolean shouldDrawDividerBelow(View view, RecyclerView parent) {
-        final RecyclerView.Adapter adapter = parent.getAdapter();
-        if (adapter == null || !(adapter instanceof PreferenceGroupAdapter)) {
-            return false;
-        }
-        final PreferenceGroupAdapter prefAdapter = (PreferenceGroupAdapter) adapter;
-        final int adapterPosition = parent.getChildAdapterPosition(view);
-        if (adapterPosition == RecyclerView.NO_POSITION) {
-            return false;
-        }
-        final Preference pref = prefAdapter.getItem(adapterPosition);
-        final Preference nextPref = prefAdapter.getItem(adapterPosition + 1);
-        if (nextPref == null) {
-            return false;
-        }
-
-        return mDashboardFeatureProvider.getPriorityGroup(pref)
-                != mDashboardFeatureProvider.getPriorityGroup(nextPref);
-    }
-
-}
diff --git a/src/com/android/settings/dashboard/DashboardFragment.java b/src/com/android/settings/dashboard/DashboardFragment.java
index 7dd8346..e59b7ba 100644
--- a/src/com/android/settings/dashboard/DashboardFragment.java
+++ b/src/com/android/settings/dashboard/DashboardFragment.java
@@ -58,7 +58,6 @@
     private final Map<Class, PreferenceController> mPreferenceControllers =
             new ArrayMap<>();
     private final Set<String> mDashboardTilePrefKeys = new ArraySet<>();
-    private DashboardDividerDecoration mDividerDecoration;
 
     protected ProgressiveDisclosureMixin mProgressiveDisclosureMixin;
     protected DashboardFeatureProvider mDashboardFeatureProvider;
@@ -99,9 +98,6 @@
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
             Bundle savedInstanceState) {
         final View view = super.onCreateView(inflater, container, savedInstanceState);
-        if (mDashboardFeatureProvider.isEnabled()) {
-            getListView().addItemDecoration(mDividerDecoration);
-        }
         return view;
     }
 
@@ -118,7 +114,6 @@
     @Override
     public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
         super.onCreatePreferences(savedInstanceState, rootKey);
-        mDividerDecoration = new DashboardDividerDecoration(getContext());
         refreshAllPreferences(getLogTag());
     }
 
@@ -126,8 +121,6 @@
     public void setDivider(Drawable divider) {
         if (mDashboardFeatureProvider.isEnabled()) {
             // Intercept divider and set it transparent so system divider decoration is disabled.
-            // We will use our decoration to draw divider more intelligently.
-            mDividerDecoration.setDivider(divider);
             super.setDivider(new ColorDrawable(Color.TRANSPARENT));
         } else {
             super.setDivider(divider);
diff --git a/src/com/android/settings/dashboard/DashboardTilePlaceholderPreferenceController.java b/src/com/android/settings/dashboard/DashboardTilePlaceholderPreferenceController.java
index 6b0018c..eb99fb3 100644
--- a/src/com/android/settings/dashboard/DashboardTilePlaceholderPreferenceController.java
+++ b/src/com/android/settings/dashboard/DashboardTilePlaceholderPreferenceController.java
@@ -53,11 +53,6 @@
     }
 
     @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        return false;
-    }
-
-    @Override
     public String getPreferenceKey() {
         return KEY_PLACEHOLDER;
     }
diff --git a/src/com/android/settings/datetime/AutoTimePreferenceController.java b/src/com/android/settings/datetime/AutoTimePreferenceController.java
index a372a49..fdeef29 100644
--- a/src/com/android/settings/datetime/AutoTimePreferenceController.java
+++ b/src/com/android/settings/datetime/AutoTimePreferenceController.java
@@ -41,11 +41,6 @@
     }
 
     @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        return false;
-    }
-
-    @Override
     public void updateState(Preference preference) {
         if (!(preference instanceof RestrictedSwitchPreference)) {
             return;
diff --git a/src/com/android/settings/datetime/AutoTimeZonePreferenceController.java b/src/com/android/settings/datetime/AutoTimeZonePreferenceController.java
index 760b2a0..c70289b 100644
--- a/src/com/android/settings/datetime/AutoTimeZonePreferenceController.java
+++ b/src/com/android/settings/datetime/AutoTimeZonePreferenceController.java
@@ -45,11 +45,6 @@
     }
 
     @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        return false;
-    }
-
-    @Override
     public String getPreferenceKey() {
         return KEY_AUTO_TIME_ZONE;
     }
diff --git a/src/com/android/settings/datetime/TimeZonePreferenceController.java b/src/com/android/settings/datetime/TimeZonePreferenceController.java
index 57c1bc7..f0b604e 100644
--- a/src/com/android/settings/datetime/TimeZonePreferenceController.java
+++ b/src/com/android/settings/datetime/TimeZonePreferenceController.java
@@ -49,11 +49,6 @@
     }
 
     @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        return false;
-    }
-
-    @Override
     public String getPreferenceKey() {
         return KEY_TIMEZONE;
     }
diff --git a/src/com/android/settings/development/BugReportInPowerPreferenceController.java b/src/com/android/settings/development/BugReportInPowerPreferenceController.java
new file mode 100644
index 0000000..47b2d0d
--- /dev/null
+++ b/src/com/android/settings/development/BugReportInPowerPreferenceController.java
@@ -0,0 +1,119 @@
+/*
+ * 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.development;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.UserManager;
+import android.provider.Settings;
+import android.support.v14.preference.SwitchPreference;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.core.PreferenceController;
+
+public class BugReportInPowerPreferenceController extends PreferenceController {
+
+    private static final String KEY_BUGREPORT_IN_POWER = "bugreport_in_power";
+
+    private UserManager mUserManager;
+    private SwitchPreference mPreference;
+
+    public BugReportInPowerPreferenceController(Context context) {
+        super(context);
+        mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+    }
+
+    @Override
+    public boolean handlePreferenceTreeClick(Preference preference) {
+        if (KEY_BUGREPORT_IN_POWER.equals(preference.getKey())) {
+            final SwitchPreference switchPreference = (SwitchPreference) preference;
+            Settings.Secure.putInt(mContext.getContentResolver(),
+                Settings.Global.BUGREPORT_IN_POWER_MENU,
+                switchPreference.isChecked() ? 1 : 0);
+            setBugreportStorageProviderStatus();
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        if (isAvailable()) {
+            mPreference = (SwitchPreference) screen.findPreference(KEY_BUGREPORT_IN_POWER);
+        }
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return KEY_BUGREPORT_IN_POWER;
+    }
+
+    @Override
+    public boolean isAvailable() {
+        return !mUserManager.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES);
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        updatePreference();
+    }
+
+    public void enablePreference(boolean enabled) {
+        if (isAvailable()) {
+            mPreference.setEnabled(enabled);
+        }
+    }
+
+    public void resetPreference() {
+        if (mPreference.isChecked()) {
+            mPreference.setChecked(false);
+            handlePreferenceTreeClick(mPreference);
+        }
+    }
+
+    public boolean updatePreference() {
+        if (!isAvailable()) {
+            return false;
+        }
+        final boolean enabled = Settings.Secure.getInt(
+            mContext.getContentResolver(), Settings.Global.BUGREPORT_IN_POWER_MENU, 0) != 0;
+        mPreference.setChecked(enabled);
+        return enabled;
+    }
+
+    public void updateBugreportOptions() {
+        if (!isAvailable()) {
+            return;
+        }
+        mPreference.setEnabled(true);
+        setBugreportStorageProviderStatus();
+    }
+
+    private void setBugreportStorageProviderStatus() {
+        final ComponentName componentName = new ComponentName("com.android.shell",
+            "com.android.shell.BugreportStorageProvider");
+        final boolean enabled = mPreference.isChecked();
+        mContext.getPackageManager().setComponentEnabledSetting(componentName,
+            enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
+                : PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
+            0);
+    }
+
+}
diff --git a/src/com/android/settings/development/BugReportPreferenceController.java b/src/com/android/settings/development/BugReportPreferenceController.java
new file mode 100644
index 0000000..371fb73
--- /dev/null
+++ b/src/com/android/settings/development/BugReportPreferenceController.java
@@ -0,0 +1,62 @@
+/*
+ * 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.development;
+
+import android.content.Context;
+import android.os.UserManager;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.core.PreferenceController;
+
+public class BugReportPreferenceController extends PreferenceController {
+
+    private static final String KEY_BUGREPORT = "bugreport";
+
+    private UserManager mUserManager;
+    private Preference mPreference;
+
+    public BugReportPreferenceController(Context context) {
+        super(context);
+        mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        if (isAvailable()) {
+            mPreference = screen.findPreference(KEY_BUGREPORT);
+        }
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return KEY_BUGREPORT;
+    }
+
+    @Override
+    public boolean isAvailable() {
+        return !mUserManager.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES);
+    }
+
+    public void enablePreference(boolean enabled) {
+        if (isAvailable()) {
+            mPreference.setEnabled(enabled);
+        }
+    }
+
+}
diff --git a/src/com/android/settings/deviceinfo/AdditionalSystemUpdatePreferenceController.java b/src/com/android/settings/deviceinfo/AdditionalSystemUpdatePreferenceController.java
index 3435b53..8d35eca 100644
--- a/src/com/android/settings/deviceinfo/AdditionalSystemUpdatePreferenceController.java
+++ b/src/com/android/settings/deviceinfo/AdditionalSystemUpdatePreferenceController.java
@@ -29,11 +29,6 @@
     }
 
     @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        return false;
-    }
-
-    @Override
     public boolean isAvailable() {
         return mContext.getResources().getBoolean(
                 com.android.settings.R.bool.config_additional_system_update_setting_enable);
diff --git a/src/com/android/settings/deviceinfo/ManageStoragePreferenceController.java b/src/com/android/settings/deviceinfo/ManageStoragePreferenceController.java
index e64525b..f4dd14e 100644
--- a/src/com/android/settings/deviceinfo/ManageStoragePreferenceController.java
+++ b/src/com/android/settings/deviceinfo/ManageStoragePreferenceController.java
@@ -35,11 +35,6 @@
     }
 
     @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        return false;
-    }
-
-    @Override
     public boolean isAvailable() {
         return mContext.getResources().getBoolean(R.bool.config_storage_manager_settings_enabled);
     }
diff --git a/src/com/android/settings/deviceinfo/SerialNumberPreferenceController.java b/src/com/android/settings/deviceinfo/SerialNumberPreferenceController.java
index 1029e20..0362bbc 100644
--- a/src/com/android/settings/deviceinfo/SerialNumberPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/SerialNumberPreferenceController.java
@@ -56,11 +56,6 @@
     }
 
     @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        return false;
-    }
-
-    @Override
     public String getPreferenceKey() {
         return KEY_SERIAL_NUMBER;
     }
diff --git a/src/com/android/settings/display/AutoBrightnessPreferenceController.java b/src/com/android/settings/display/AutoBrightnessPreferenceController.java
index df2000e..1d644a4 100644
--- a/src/com/android/settings/display/AutoBrightnessPreferenceController.java
+++ b/src/com/android/settings/display/AutoBrightnessPreferenceController.java
@@ -46,11 +46,6 @@
     }
 
     @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        return false;
-    }
-
-    @Override
     public void updateState(Preference preference) {
         int brightnessMode = Settings.System.getInt(mContext.getContentResolver(),
                 SCREEN_BRIGHTNESS_MODE, SCREEN_BRIGHTNESS_MODE_MANUAL);
diff --git a/src/com/android/settings/display/AutoRotatePreferenceController.java b/src/com/android/settings/display/AutoRotatePreferenceController.java
index ee940a3..11c9333 100644
--- a/src/com/android/settings/display/AutoRotatePreferenceController.java
+++ b/src/com/android/settings/display/AutoRotatePreferenceController.java
@@ -68,11 +68,6 @@
     }
 
     @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        return false;
-    }
-
-    @Override
     public boolean isAvailable() {
         return RotationPolicy.isRotationLockToggleVisible(mContext);
     }
diff --git a/src/com/android/settings/display/CameraGesturePreferenceController.java b/src/com/android/settings/display/CameraGesturePreferenceController.java
index a3dc6cf..1b60721 100644
--- a/src/com/android/settings/display/CameraGesturePreferenceController.java
+++ b/src/com/android/settings/display/CameraGesturePreferenceController.java
@@ -38,11 +38,6 @@
     }
 
     @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        return false;
-    }
-
-    @Override
     public void updateState(Preference preference) {
         int value = Settings.Secure.getInt(mContext.getContentResolver(),
                 CAMERA_GESTURE_DISABLED, 0);
diff --git a/src/com/android/settings/display/FontSizePreferenceController.java b/src/com/android/settings/display/FontSizePreferenceController.java
index 5014bda..7528f18 100644
--- a/src/com/android/settings/display/FontSizePreferenceController.java
+++ b/src/com/android/settings/display/FontSizePreferenceController.java
@@ -51,9 +51,4 @@
                 strEntryValues);
         preference.setSummary(entries[index]);
     }
-
-    @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        return false;
-    }
 }
diff --git a/src/com/android/settings/display/LiftToWakePreferenceController.java b/src/com/android/settings/display/LiftToWakePreferenceController.java
index 81ba5f5..e8be936 100644
--- a/src/com/android/settings/display/LiftToWakePreferenceController.java
+++ b/src/com/android/settings/display/LiftToWakePreferenceController.java
@@ -45,11 +45,6 @@
     }
 
     @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        return false;
-    }
-
-    @Override
     public boolean onPreferenceChange(Preference preference, Object newValue) {
         boolean value = (Boolean) newValue;
         Settings.Secure.putInt(mContext.getContentResolver(), WAKE_GESTURE_ENABLED, value ? 1 : 0);
diff --git a/src/com/android/settings/display/NightDisplayPreferenceController.java b/src/com/android/settings/display/NightDisplayPreferenceController.java
index 9cf2409..4b18778 100644
--- a/src/com/android/settings/display/NightDisplayPreferenceController.java
+++ b/src/com/android/settings/display/NightDisplayPreferenceController.java
@@ -28,11 +28,6 @@
     }
 
     @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        return false;
-    }
-
-    @Override
     public boolean isAvailable() {
         return NightDisplayController.isAvailable(mContext);
     }
diff --git a/src/com/android/settings/display/NightModePreferenceController.java b/src/com/android/settings/display/NightModePreferenceController.java
index 874d84f..2eb64c0 100644
--- a/src/com/android/settings/display/NightModePreferenceController.java
+++ b/src/com/android/settings/display/NightModePreferenceController.java
@@ -62,11 +62,6 @@
     }
 
     @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        return false;
-    }
-
-    @Override
     public boolean onPreferenceChange(Preference preference, Object newValue) {
         try {
             final int value = Integer.parseInt((String) newValue);
diff --git a/src/com/android/settings/display/ScreenSaverPreferenceController.java b/src/com/android/settings/display/ScreenSaverPreferenceController.java
index 7335b1f..fab9062 100644
--- a/src/com/android/settings/display/ScreenSaverPreferenceController.java
+++ b/src/com/android/settings/display/ScreenSaverPreferenceController.java
@@ -39,11 +39,6 @@
     }
 
     @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        return false;
-    }
-
-    @Override
     public void updateState(Preference preference) {
         preference.setSummary(DreamSettings.getSummaryTextWithDreamName(mContext));
     }
diff --git a/src/com/android/settings/display/TapToWakePreferenceController.java b/src/com/android/settings/display/TapToWakePreferenceController.java
index 18c877a..1f24d74 100644
--- a/src/com/android/settings/display/TapToWakePreferenceController.java
+++ b/src/com/android/settings/display/TapToWakePreferenceController.java
@@ -41,11 +41,6 @@
     }
 
     @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        return false;
-    }
-
-    @Override
     public void updateState(Preference preference) {
         int value = Settings.Secure.getInt(
                 mContext.getContentResolver(), Settings.Secure.DOUBLE_TAP_TO_WAKE, 0);
diff --git a/src/com/android/settings/display/TimeoutPreferenceController.java b/src/com/android/settings/display/TimeoutPreferenceController.java
index d33f813..d409656 100644
--- a/src/com/android/settings/display/TimeoutPreferenceController.java
+++ b/src/com/android/settings/display/TimeoutPreferenceController.java
@@ -52,11 +52,6 @@
     }
 
     @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        return false;
-    }
-
-    @Override
     public void updateState(Preference preference) {
         final TimeoutListPreference timeoutListPreference = (TimeoutListPreference) preference;
         final long currentTimeout = Settings.System.getLong(mContext.getContentResolver(),
diff --git a/src/com/android/settings/display/VrDisplayPreferenceController.java b/src/com/android/settings/display/VrDisplayPreferenceController.java
index 61c3ed2..0eb1c88 100644
--- a/src/com/android/settings/display/VrDisplayPreferenceController.java
+++ b/src/com/android/settings/display/VrDisplayPreferenceController.java
@@ -74,9 +74,4 @@
         }
         return true;
     }
-
-    @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        return false;
-    }
 }
diff --git a/src/com/android/settings/display/WallpaperPreferenceController.java b/src/com/android/settings/display/WallpaperPreferenceController.java
index 8352377..aa29afc 100644
--- a/src/com/android/settings/display/WallpaperPreferenceController.java
+++ b/src/com/android/settings/display/WallpaperPreferenceController.java
@@ -46,11 +46,6 @@
         disablePreferenceIfManaged((RestrictedPreference) preference);
     }
 
-    @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        return false;
-    }
-
     private void disablePreferenceIfManaged(RestrictedPreference pref) {
         final String restriction = DISALLOW_SET_WALLPAPER;
         if (pref != null) {
diff --git a/src/com/android/settings/enterprise/AdminActionPreferenceControllerBase.java b/src/com/android/settings/enterprise/AdminActionPreferenceControllerBase.java
index 67b1d13..99ff62e 100644
--- a/src/com/android/settings/enterprise/AdminActionPreferenceControllerBase.java
+++ b/src/com/android/settings/enterprise/AdminActionPreferenceControllerBase.java
@@ -50,9 +50,4 @@
     public boolean isAvailable() {
         return true;
     }
-
-    @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        return false;
-    }
 }
diff --git a/src/com/android/settings/enterprise/InstalledPackagesPreferenceController.java b/src/com/android/settings/enterprise/InstalledPackagesPreferenceController.java
index df1c6c4..a7afac0 100644
--- a/src/com/android/settings/enterprise/InstalledPackagesPreferenceController.java
+++ b/src/com/android/settings/enterprise/InstalledPackagesPreferenceController.java
@@ -51,11 +51,6 @@
     }
 
     @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        return false;
-    }
-
-    @Override
     public String getPreferenceKey() {
         return KEY_NUMBER_INSTALLED_PACKAGES;
     }
diff --git a/src/com/android/settings/gestures/GesturePreferenceController.java b/src/com/android/settings/gestures/GesturePreferenceController.java
index 345f7b7..ebfccb5 100644
--- a/src/com/android/settings/gestures/GesturePreferenceController.java
+++ b/src/com/android/settings/gestures/GesturePreferenceController.java
@@ -65,11 +65,6 @@
     }
 
     @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        return false;
-    }
-
-    @Override
     public void onStop() {
         if (mVideoPreference != null) {
             mVideoPreference.onViewInvisible();
diff --git a/src/com/android/settings/gestures/SwipeToNotificationPreferenceController.java b/src/com/android/settings/gestures/SwipeToNotificationPreferenceController.java
index 01af974..08dc614 100644
--- a/src/com/android/settings/gestures/SwipeToNotificationPreferenceController.java
+++ b/src/com/android/settings/gestures/SwipeToNotificationPreferenceController.java
@@ -32,11 +32,6 @@
     }
 
     @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        return false;
-    }
-
-    @Override
     public String getPreferenceKey() {
         return PREF_KEY_SWIPE_DOWN_FINGERPRINT;
     }
diff --git a/src/com/android/settings/inputmethod/SpellCheckerPreferenceController.java b/src/com/android/settings/inputmethod/SpellCheckerPreferenceController.java
index 17d3fdc..8fcaa74 100644
--- a/src/com/android/settings/inputmethod/SpellCheckerPreferenceController.java
+++ b/src/com/android/settings/inputmethod/SpellCheckerPreferenceController.java
@@ -52,11 +52,6 @@
     }
 
     @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        return false;
-    }
-
-    @Override
     public String getPreferenceKey() {
         return KEY_SPELL_CHECKERS;
     }
diff --git a/src/com/android/settings/language/PhoneLanguagePreferenceController.java b/src/com/android/settings/language/PhoneLanguagePreferenceController.java
index 2b87fd9..cd2f539 100644
--- a/src/com/android/settings/language/PhoneLanguagePreferenceController.java
+++ b/src/com/android/settings/language/PhoneLanguagePreferenceController.java
@@ -36,11 +36,6 @@
     }
 
     @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        return false;
-    }
-
-    @Override
     public void updateState(Preference preference) {
         if (preference == null) {
             return;
diff --git a/src/com/android/settings/language/TtsPreferenceController.java b/src/com/android/settings/language/TtsPreferenceController.java
index ffc1eb1..9b40b6d 100644
--- a/src/com/android/settings/language/TtsPreferenceController.java
+++ b/src/com/android/settings/language/TtsPreferenceController.java
@@ -49,11 +49,6 @@
     }
 
     @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        return false;
-    }
-
-    @Override
     public String getPreferenceKey() {
         return KEY_TTS_SETTINGS;
     }
diff --git a/src/com/android/settings/language/UserDictionaryPreferenceController.java b/src/com/android/settings/language/UserDictionaryPreferenceController.java
index d26761b..01ce3aa 100644
--- a/src/com/android/settings/language/UserDictionaryPreferenceController.java
+++ b/src/com/android/settings/language/UserDictionaryPreferenceController.java
@@ -44,11 +44,6 @@
     }
 
     @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        return false;
-    }
-
-    @Override
     public String getPreferenceKey() {
         return KEY_USER_DICTIONARY_SETTINGS;
     }
diff --git a/src/com/android/settings/network/MobileNetworkPreferenceController.java b/src/com/android/settings/network/MobileNetworkPreferenceController.java
index 588d80c..7c8cd40 100644
--- a/src/com/android/settings/network/MobileNetworkPreferenceController.java
+++ b/src/com/android/settings/network/MobileNetworkPreferenceController.java
@@ -40,11 +40,6 @@
     }
 
     @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        return false;
-    }
-
-    @Override
     public boolean isAvailable() {
         return !mIsSecondaryUser
                 && !Utils.isWifiOnly(mContext)
diff --git a/src/com/android/settings/network/NetworkResetPreferenceController.java b/src/com/android/settings/network/NetworkResetPreferenceController.java
index 2842139..e357fbe 100644
--- a/src/com/android/settings/network/NetworkResetPreferenceController.java
+++ b/src/com/android/settings/network/NetworkResetPreferenceController.java
@@ -32,11 +32,6 @@
     }
 
     @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        return false;
-    }
-
-    @Override
     public boolean isAvailable() {
         return !RestrictedLockUtils.hasBaseUserRestriction(mContext,
                 UserManager.DISALLOW_NETWORK_RESET, UserHandle.myUserId());
diff --git a/src/com/android/settings/network/ProxyPreferenceController.java b/src/com/android/settings/network/ProxyPreferenceController.java
index 54b8ca9..edec247 100644
--- a/src/com/android/settings/network/ProxyPreferenceController.java
+++ b/src/com/android/settings/network/ProxyPreferenceController.java
@@ -31,11 +31,6 @@
     }
 
     @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        return false;
-    }
-
-    @Override
     public boolean isAvailable() {
         // proxy UI disabled until we have better app support
         return false;
diff --git a/src/com/android/settings/network/TetherPreferenceController.java b/src/com/android/settings/network/TetherPreferenceController.java
index f6ef678..e24c873 100644
--- a/src/com/android/settings/network/TetherPreferenceController.java
+++ b/src/com/android/settings/network/TetherPreferenceController.java
@@ -49,11 +49,6 @@
     }
 
     @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        return false;
-    }
-
-    @Override
     public void displayPreference(PreferenceScreen screen) {
         super.displayPreference(screen);
         final Preference preference = screen.findPreference(KEY_TETHER_SETTINGS);
diff --git a/src/com/android/settings/network/VpnPreferenceController.java b/src/com/android/settings/network/VpnPreferenceController.java
index 146b400..f7e230f 100644
--- a/src/com/android/settings/network/VpnPreferenceController.java
+++ b/src/com/android/settings/network/VpnPreferenceController.java
@@ -41,11 +41,6 @@
     }
 
     @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        return false;
-    }
-
-    @Override
     public void displayPreference(PreferenceScreen screen) {
         super.displayPreference(screen);
         // Manually set dependencies for Wifi when not toggleable.
diff --git a/src/com/android/settings/network/WifiCallingPreferenceController.java b/src/com/android/settings/network/WifiCallingPreferenceController.java
index 5036c46..b35d476 100644
--- a/src/com/android/settings/network/WifiCallingPreferenceController.java
+++ b/src/com/android/settings/network/WifiCallingPreferenceController.java
@@ -35,11 +35,6 @@
     }
 
     @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        return false;
-    }
-
-    @Override
     public void displayPreference(PreferenceScreen screen) {
         super.displayPreference(screen);
         final Preference pref = screen.findPreference(KEY_WFC_SETTINGS);
diff --git a/src/com/android/settings/nfc/NfcPreferenceController.java b/src/com/android/settings/nfc/NfcPreferenceController.java
index 6303d5b..65c2d4c 100644
--- a/src/com/android/settings/nfc/NfcPreferenceController.java
+++ b/src/com/android/settings/nfc/NfcPreferenceController.java
@@ -96,11 +96,6 @@
     }
 
     @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        return false;
-    }
-
-    @Override
     public boolean isAvailable() {
         return mNfcAdapter != null;
     }
diff --git a/src/com/android/settings/notification/AlarmRingtonePreferenceController.java b/src/com/android/settings/notification/AlarmRingtonePreferenceController.java
new file mode 100644
index 0000000..2e7aab0
--- /dev/null
+++ b/src/com/android/settings/notification/AlarmRingtonePreferenceController.java
@@ -0,0 +1,39 @@
+/*
+ * 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.notification;
+
+import android.content.Context;
+import android.media.RingtoneManager;
+
+public class AlarmRingtonePreferenceController extends RingtonePreferenceControllerBase {
+
+    private static final String KEY_ALARM_RINGTONE = "alarm_ringtone";
+
+    public AlarmRingtonePreferenceController(Context context) {
+        super(context);
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return KEY_ALARM_RINGTONE;
+    }
+
+    @Override
+    public int getRingtoneType() {
+        return RingtoneManager.TYPE_ALARM;
+    }
+}
diff --git a/src/com/android/settings/notification/CastPreferenceController.java b/src/com/android/settings/notification/CastPreferenceController.java
index 2ec7821..7de5c48 100644
--- a/src/com/android/settings/notification/CastPreferenceController.java
+++ b/src/com/android/settings/notification/CastPreferenceController.java
@@ -32,11 +32,6 @@
     }
 
     @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        return false;
-    }
-
-    @Override
     public String getPreferenceKey() {
         return KEY_WIFI_DISPLAY;
     }
diff --git a/src/com/android/settings/notification/EmergencyBroadcastPreferenceController.java b/src/com/android/settings/notification/EmergencyBroadcastPreferenceController.java
new file mode 100644
index 0000000..1154493
--- /dev/null
+++ b/src/com/android/settings/notification/EmergencyBroadcastPreferenceController.java
@@ -0,0 +1,99 @@
+/*
+ * 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.notification;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.support.v7.preference.Preference;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.settings.accounts.AccountRestrictionHelper;
+import com.android.settings.core.PreferenceController;
+import com.android.settingslib.RestrictedPreference;
+
+/**
+ * Base class for preference controller that handles preference that enforce adjust volume
+ * restriction
+ */
+public class EmergencyBroadcastPreferenceController extends PreferenceController {
+
+    private static final String KEY_CELL_BROADCAST_SETTINGS = "cell_broadcast_settings";
+
+    private AccountRestrictionHelper mHelper;
+    private UserManager mUserManager;
+    private PackageManager mPm;
+    private boolean mCellBroadcastAppLinkEnabled;
+
+    public EmergencyBroadcastPreferenceController(Context context) {
+        this(context, new AccountRestrictionHelper(context));
+    }
+
+    @VisibleForTesting
+    EmergencyBroadcastPreferenceController(Context context, AccountRestrictionHelper helper) {
+        super(context);
+        mHelper = helper;
+        mUserManager = UserManager.get(context);
+        mPm = mContext.getPackageManager();
+        // Enable link to CMAS app settings depending on the value in config.xml.
+        mCellBroadcastAppLinkEnabled = isCellBroadcastAppLinkEnabled();
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        if (!(preference instanceof RestrictedPreference)) {
+            return;
+        }
+        ((RestrictedPreference) preference).checkRestrictionAndSetDisabled(
+            UserManager.DISALLOW_CONFIG_CELL_BROADCASTS);
+    }
+
+    @Override
+    public boolean handlePreferenceTreeClick(Preference preference) {
+        return false;
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return KEY_CELL_BROADCAST_SETTINGS;
+    }
+
+    @Override
+    public boolean isAvailable() {
+        return mUserManager.isAdminUser() && mCellBroadcastAppLinkEnabled
+            && !mHelper.hasBaseUserRestriction(
+                UserManager.DISALLOW_CONFIG_CELL_BROADCASTS, UserHandle.myUserId());
+    }
+
+    private boolean isCellBroadcastAppLinkEnabled() {
+        boolean enabled = mContext.getResources().getBoolean(
+            com.android.internal.R.bool.config_cellBroadcastAppLinks);
+        if (enabled) {
+            try {
+                if (mPm.getApplicationEnabledSetting("com.android.cellbroadcastreceiver")
+                    == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) {
+                    enabled = false;  // CMAS app disabled
+                }
+            } catch (IllegalArgumentException ignored) {
+                enabled = false;  // CMAS app not installed
+            }
+        }
+        return enabled;
+    }
+
+}
\ No newline at end of file
diff --git a/src/com/android/settings/notification/LockScreenNotificationPreferenceController.java b/src/com/android/settings/notification/LockScreenNotificationPreferenceController.java
index 15f8c9f..a7ebbe1 100644
--- a/src/com/android/settings/notification/LockScreenNotificationPreferenceController.java
+++ b/src/com/android/settings/notification/LockScreenNotificationPreferenceController.java
@@ -76,11 +76,6 @@
     }
 
     @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        return false;
-    }
-
-    @Override
     public void displayPreference(PreferenceScreen screen) {
         super.displayPreference(screen);
         mLockscreen =
diff --git a/src/com/android/settings/notification/NotificationRingtonePreferenceController.java b/src/com/android/settings/notification/NotificationRingtonePreferenceController.java
new file mode 100644
index 0000000..72e8d8f
--- /dev/null
+++ b/src/com/android/settings/notification/NotificationRingtonePreferenceController.java
@@ -0,0 +1,39 @@
+/*
+ * 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.notification;
+
+import android.content.Context;
+import android.media.RingtoneManager;
+
+public class NotificationRingtonePreferenceController extends RingtonePreferenceControllerBase {
+
+    private static final String KEY_NOTIFICATION_RINGTONE = "notification_ringtone";
+
+    public NotificationRingtonePreferenceController(Context context) {
+        super(context);
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return KEY_NOTIFICATION_RINGTONE;
+    }
+
+    @Override
+    public int getRingtoneType() {
+        return RingtoneManager.TYPE_NOTIFICATION;
+    }
+}
diff --git a/src/com/android/settings/notification/PhoneRingtonePreferenceController.java b/src/com/android/settings/notification/PhoneRingtonePreferenceController.java
new file mode 100644
index 0000000..cb11151
--- /dev/null
+++ b/src/com/android/settings/notification/PhoneRingtonePreferenceController.java
@@ -0,0 +1,45 @@
+/*
+ * 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.notification;
+
+import android.content.Context;
+import android.media.RingtoneManager;
+import com.android.settings.Utils;
+
+public class PhoneRingtonePreferenceController extends RingtonePreferenceControllerBase {
+
+    private static final String KEY_PHONE_RINGTONE = "ringtone";
+
+    public PhoneRingtonePreferenceController(Context context) {
+        super(context);
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return KEY_PHONE_RINGTONE;
+    }
+
+    @Override
+    public boolean isAvailable() {
+        return Utils.isVoiceCapable(mContext);
+    }
+
+    @Override
+    public int getRingtoneType() {
+        return RingtoneManager.TYPE_RINGTONE;
+    }
+}
diff --git a/src/com/android/settings/notification/PulseNotificationPreferenceController.java b/src/com/android/settings/notification/PulseNotificationPreferenceController.java
index de365f1..3e37ab0 100644
--- a/src/com/android/settings/notification/PulseNotificationPreferenceController.java
+++ b/src/com/android/settings/notification/PulseNotificationPreferenceController.java
@@ -69,11 +69,6 @@
     }
 
     @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        return false;
-    }
-
-    @Override
     public String getPreferenceKey() {
         return KEY_NOTIFICATION_PULSE;
     }
diff --git a/src/com/android/settings/notification/RingtonePreferenceControllerBase.java b/src/com/android/settings/notification/RingtonePreferenceControllerBase.java
new file mode 100644
index 0000000..333f08a
--- /dev/null
+++ b/src/com/android/settings/notification/RingtonePreferenceControllerBase.java
@@ -0,0 +1,55 @@
+/*
+ * 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.notification;
+
+import android.content.Context;
+import android.media.Ringtone;
+import android.media.RingtoneManager;
+import android.net.Uri;
+import android.support.v7.preference.Preference;
+
+import com.android.settings.core.PreferenceController;
+
+public abstract class RingtonePreferenceControllerBase extends PreferenceController {
+
+    public RingtonePreferenceControllerBase(Context context) {
+        super(context);
+    }
+
+    @Override
+    public boolean handlePreferenceTreeClick(Preference preference) {
+        return false;
+    }
+
+    @Override
+    public boolean isAvailable() {
+        return true;
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        Uri ringtoneUri = RingtoneManager.getActualDefaultRingtoneUri(mContext, getRingtoneType());
+        final CharSequence summary = Ringtone.getTitle(
+            mContext, ringtoneUri, false /* followSettingsUri */, true /* allowRemote */);
+        if (summary != null) {
+            preference.setSummary(summary);
+        }
+    }
+
+    public abstract int getRingtoneType();
+
+}
diff --git a/src/com/android/settings/notification/SoundSettings.java b/src/com/android/settings/notification/SoundSettings.java
index 1adfdd8..9166377 100644
--- a/src/com/android/settings/notification/SoundSettings.java
+++ b/src/com/android/settings/notification/SoundSettings.java
@@ -23,19 +23,15 @@
 import android.app.FragmentManager;
 import android.app.NotificationManager;
 import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.pm.PackageManager;
-import android.database.ContentObserver;
 import android.media.AudioManager;
 import android.media.AudioSystem;
 import android.media.Ringtone;
 import android.media.RingtoneManager;
 import android.net.Uri;
-import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
@@ -63,8 +59,6 @@
 import com.android.settings.dashboard.DashboardFragment;
 import com.android.settings.dashboard.SummaryLoader;
 import com.android.settings.search.BaseSearchIndexProvider;
-import com.android.settingslib.RestrictedLockUtils;
-import com.android.settingslib.RestrictedPreference;
 
 import com.android.settingslib.drawer.CategoryKey;
 import java.text.NumberFormat;
@@ -76,12 +70,6 @@
         implements OnPreferenceChangeListener {
     private static final String TAG = "SoundSettings";
 
-    private static final String KEY_PHONE_RINGTONE = "ringtone";
-    private static final String KEY_NOTIFICATION_RINGTONE = "notification_ringtone";
-    private static final String KEY_ALARM_RINGTONE = "alarm_ringtone";
-    private static final String KEY_VIBRATE_WHEN_RINGING = "vibrate_when_ringing";
-    private static final String KEY_CELL_BROADCAST_SETTINGS = "cell_broadcast_settings";
-
     private static final String KEY_WORK_CATEGORY = "sound_work_settings_section";
     private static final String KEY_WORK_USE_PERSONAL_SOUNDS = "work_use_personal_sounds";
     private static final String KEY_WORK_PHONE_RINGTONE = "work_ringtone";
@@ -95,23 +83,16 @@
 
     private final VolumePreferenceCallback mVolumeCallback = new VolumePreferenceCallback();
     private final H mHandler = new H();
-    private final SettingsObserver mSettingsObserver = new SettingsObserver();
 
     private Context mContext;
     private boolean mVoiceCapable;
 
-    private Preference mPhoneRingtonePreference;
-    private Preference mNotificationRingtonePreference;
-    private Preference mAlarmRingtonePreference;
-    private TwoStatePreference mVibrateWhenRinging;
-
     private PreferenceGroup mWorkPreferenceCategory;
     private TwoStatePreference mWorkUsePersonalSounds;
     private Preference mWorkPhoneRingtonePreference;
     private Preference mWorkNotificationRingtonePreference;
     private Preference mWorkAlarmRingtonePreference;
 
-    private PackageManager mPm;
     private UserManager mUserManager;
     private RingtonePreference mRequestPreference;
 
@@ -126,31 +107,9 @@
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         mContext = getActivity();
-        mPm = getPackageManager();
         mUserManager = UserManager.get(getContext());
         mVoiceCapable = Utils.isVoiceCapable(mContext);
 
-        // Enable link to CMAS app settings depending on the value in config.xml.
-        boolean isCellBroadcastAppLinkEnabled = this.getResources().getBoolean(
-                com.android.internal.R.bool.config_cellBroadcastAppLinks);
-        try {
-            if (isCellBroadcastAppLinkEnabled) {
-                if (mPm.getApplicationEnabledSetting("com.android.cellbroadcastreceiver")
-                        == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) {
-                    isCellBroadcastAppLinkEnabled = false;  // CMAS app disabled
-                }
-            }
-        } catch (IllegalArgumentException ignored) {
-            isCellBroadcastAppLinkEnabled = false;  // CMAS app not installed
-        }
-        if (!mUserManager.isAdminUser() || !isCellBroadcastAppLinkEnabled ||
-                RestrictedLockUtils.hasBaseUserRestriction(mContext,
-                        UserManager.DISALLOW_CONFIG_CELL_BROADCASTS, UserHandle.myUserId())) {
-            removePreference(KEY_CELL_BROADCAST_SETTINGS);
-        }
-        initRingtones();
-        initVibrateWhenRinging();
-
         if (savedInstanceState != null) {
             String selectedPreference = savedInstanceState.getString(SELECTED_PREFERENCE_KEY, null);
             if (!TextUtils.isEmpty(selectedPreference)) {
@@ -162,15 +121,6 @@
     @Override
     public void onResume() {
         super.onResume();
-        lookupRingtoneNames();
-        mSettingsObserver.register(true);
-
-        RestrictedPreference broadcastSettingsPref = (RestrictedPreference) findPreference(
-                KEY_CELL_BROADCAST_SETTINGS);
-        if (broadcastSettingsPref != null) {
-            broadcastSettingsPref.checkRestrictionAndSetDisabled(
-                    UserManager.DISALLOW_CONFIG_CELL_BROADCASTS);
-        }
 
         mManagedProfileId = Utils.getManagedProfileId(mUserManager, UserHandle.myUserId());
         if (mManagedProfileId != UserHandle.USER_NULL && shouldShowRingtoneSettings()) {
@@ -191,7 +141,6 @@
     public void onPause() {
         super.onPause();
         mVolumeCallback.stopSample();
-        mSettingsObserver.register(false);
     }
 
     @Override
@@ -226,12 +175,21 @@
         Lifecycle lifecycle = getLifecycle();
         controllers.add(new CastPreferenceController(context));
         controllers.add(new ZenModePreferenceController(context));
+        controllers.add(new EmergencyBroadcastPreferenceController(context));
+        controllers.add(new VibrateWhenRingPreferenceController(context));
+
         // === Volumes ===
         controllers.add(new AlarmVolumePreferenceController(context, mVolumeCallback, lifecycle));
         controllers.add(new MediaVolumePreferenceController(context, mVolumeCallback, lifecycle));
         controllers.add(
             new NotificationVolumePreferenceController(context, mVolumeCallback, lifecycle));
         controllers.add(new RingVolumePreferenceController(context, mVolumeCallback, lifecycle));
+
+        // === Phone & notification ringtone ===
+        controllers.add(new PhoneRingtonePreferenceController(context));
+        controllers.add(new AlarmRingtonePreferenceController(context));
+        controllers.add(new NotificationRingtonePreferenceController(context));
+
         return controllers;
     }
 
@@ -314,48 +272,6 @@
         return !AudioSystem.isSingleVolume(mContext);
     }
 
-    private void initRingtones() {
-        mPhoneRingtonePreference = getPreferenceScreen().findPreference(KEY_PHONE_RINGTONE);
-        if (mPhoneRingtonePreference != null && !mVoiceCapable) {
-            getPreferenceScreen().removePreference(mPhoneRingtonePreference);
-            mPhoneRingtonePreference = null;
-        }
-        mNotificationRingtonePreference =
-                getPreferenceScreen().findPreference(KEY_NOTIFICATION_RINGTONE);
-        mAlarmRingtonePreference = getPreferenceScreen().findPreference(KEY_ALARM_RINGTONE);
-    }
-
-    private void lookupRingtoneNames() {
-        AsyncTask.execute(mLookupRingtoneNames);
-    }
-
-    private final Runnable mLookupRingtoneNames = new Runnable() {
-        @Override
-        public void run() {
-            if (mPhoneRingtonePreference != null) {
-                final CharSequence summary = updateRingtoneName(
-                        mContext, RingtoneManager.TYPE_RINGTONE);
-                if (summary != null) {
-                    mHandler.obtainMessage(H.UPDATE_PHONE_RINGTONE, summary).sendToTarget();
-                }
-            }
-            if (mNotificationRingtonePreference != null) {
-                final CharSequence summary = updateRingtoneName(
-                        mContext, RingtoneManager.TYPE_NOTIFICATION);
-                if (summary != null) {
-                    mHandler.obtainMessage(H.UPDATE_NOTIFICATION_RINGTONE, summary).sendToTarget();
-                }
-            }
-            if (mAlarmRingtonePreference != null) {
-                final CharSequence summary =
-                        updateRingtoneName(mContext, RingtoneManager.TYPE_ALARM);
-                if (summary != null) {
-                    mHandler.obtainMessage(H.UPDATE_ALARM_RINGTONE, summary).sendToTarget();
-                }
-            }
-        }
-    };
-
     private static CharSequence updateRingtoneName(Context context, int type) {
         if (context == null) {
             Log.e(TAG, "Unable to update ringtone name, no context provided");
@@ -366,74 +282,11 @@
                 true /* allowRemote */);
     }
 
-    // === Vibrate when ringing ===
-
-    private void initVibrateWhenRinging() {
-        mVibrateWhenRinging =
-                (TwoStatePreference) getPreferenceScreen().findPreference(KEY_VIBRATE_WHEN_RINGING);
-        if (mVibrateWhenRinging == null) {
-            Log.i(TAG, "Preference not found: " + KEY_VIBRATE_WHEN_RINGING);
-            return;
-        }
-        if (!mVoiceCapable) {
-            getPreferenceScreen().removePreference(mVibrateWhenRinging);
-            mVibrateWhenRinging = null;
-            return;
-        }
-        mVibrateWhenRinging.setPersistent(false);
-        updateVibrateWhenRinging();
-        mVibrateWhenRinging.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
-            @Override
-            public boolean onPreferenceChange(Preference preference, Object newValue) {
-                final boolean val = (Boolean) newValue;
-                return Settings.System.putInt(getContentResolver(),
-                        Settings.System.VIBRATE_WHEN_RINGING,
-                        val ? 1 : 0);
-            }
-        });
-    }
-
-    private void updateVibrateWhenRinging() {
-        if (mVibrateWhenRinging == null) return;
-        mVibrateWhenRinging.setChecked(Settings.System.getInt(getContentResolver(),
-                Settings.System.VIBRATE_WHEN_RINGING, 0) != 0);
-    }
-
     // === Callbacks ===
 
-    private final class SettingsObserver extends ContentObserver {
-        private final Uri VIBRATE_WHEN_RINGING_URI =
-                Settings.System.getUriFor(Settings.System.VIBRATE_WHEN_RINGING);
-
-        public SettingsObserver() {
-            super(mHandler);
-        }
-
-        public void register(boolean register) {
-            final ContentResolver cr = getContentResolver();
-            if (register) {
-                cr.registerContentObserver(VIBRATE_WHEN_RINGING_URI, false, this);
-            } else {
-                cr.unregisterContentObserver(this);
-            }
-        }
-
-        @Override
-        public void onChange(boolean selfChange, Uri uri) {
-            super.onChange(selfChange, uri);
-            if (VIBRATE_WHEN_RINGING_URI.equals(uri)) {
-                updateVibrateWhenRinging();
-            }
-        }
-    }
 
     private final class H extends Handler {
-        private static final int UPDATE_PHONE_RINGTONE = 1;
-        private static final int UPDATE_NOTIFICATION_RINGTONE = 2;
-        private static final int STOP_SAMPLE = 3;
-        private static final int UPDATE_EFFECTS_SUPPRESSOR = 4;
-        private static final int UPDATE_RINGER_MODE = 5;
-        private static final int UPDATE_ALARM_RINGTONE = 6;
+        private static final int STOP_SAMPLE = 1;
 
         private H() {
             super(Looper.getMainLooper());
@@ -442,18 +295,9 @@
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
-                case UPDATE_PHONE_RINGTONE:
-                    mPhoneRingtonePreference.setSummary((CharSequence) msg.obj);
-                    break;
-                case UPDATE_NOTIFICATION_RINGTONE:
-                    mNotificationRingtonePreference.setSummary((CharSequence) msg.obj);
-                    break;
                 case STOP_SAMPLE:
                     mVolumeCallback.stopSample();
                     break;
-                case UPDATE_ALARM_RINGTONE:
-                    mAlarmRingtonePreference.setSummary((CharSequence) msg.obj);
-                    break;
             }
         }
     }
@@ -539,30 +383,9 @@
             new RingVolumePreferenceController(
                 context, null /* Callback */, null /* Lifecycle */).updateNonIndexableKeys(rt);
             new CastPreferenceController(context).updateNonIndexableKeys(rt);
-            if (!Utils.isVoiceCapable(context)) {
-                rt.add(KEY_PHONE_RINGTONE);
-                rt.add(KEY_VIBRATE_WHEN_RINGING);
-            }
-
-            final PackageManager pm = context.getPackageManager();
-            final UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
-
-            // Enable link to CMAS app settings depending on the value in config.xml.
-            boolean isCellBroadcastAppLinkEnabled = context.getResources().getBoolean(
-                    com.android.internal.R.bool.config_cellBroadcastAppLinks);
-            try {
-                if (isCellBroadcastAppLinkEnabled) {
-                    if (pm.getApplicationEnabledSetting("com.android.cellbroadcastreceiver")
-                            == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) {
-                        isCellBroadcastAppLinkEnabled = false;  // CMAS app disabled
-                    }
-                }
-            } catch (IllegalArgumentException ignored) {
-                isCellBroadcastAppLinkEnabled = false;  // CMAS app not installed
-            }
-            if (!um.isAdminUser() || !isCellBroadcastAppLinkEnabled) {
-                rt.add(KEY_CELL_BROADCAST_SETTINGS);
-            }
+            new PhoneRingtonePreferenceController(context).updateNonIndexableKeys(rt);
+            new VibrateWhenRingPreferenceController(context).updateNonIndexableKeys(rt);
+            new EmergencyBroadcastPreferenceController(context).updateNonIndexableKeys(rt);
 
             return rt;
         }
diff --git a/src/com/android/settings/notification/VibrateWhenRingPreferenceController.java b/src/com/android/settings/notification/VibrateWhenRingPreferenceController.java
new file mode 100644
index 0000000..2160f3d
--- /dev/null
+++ b/src/com/android/settings/notification/VibrateWhenRingPreferenceController.java
@@ -0,0 +1,129 @@
+/*
+ * 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.notification;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.provider.Settings;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+import android.support.v7.preference.TwoStatePreference;
+
+import com.android.settings.Utils;
+import com.android.settings.core.PreferenceController;
+import com.android.settings.core.lifecycle.LifecycleObserver;
+import com.android.settings.core.lifecycle.events.OnPause;
+import com.android.settings.core.lifecycle.events.OnResume;
+
+import static android.provider.Settings.System.VIBRATE_WHEN_RINGING;
+
+public class VibrateWhenRingPreferenceController extends PreferenceController implements
+        Preference.OnPreferenceChangeListener, LifecycleObserver, OnResume, OnPause {
+
+    private static final String KEY_VIBRATE_WHEN_RINGING = "vibrate_when_ringing";
+    private SettingObserver mSettingObserver;
+
+    public VibrateWhenRingPreferenceController(Context context) {
+        super(context);
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        Preference preference = screen.findPreference(KEY_VIBRATE_WHEN_RINGING);
+        if (preference != null) {
+            mSettingObserver = new SettingObserver(preference);
+            preference.setPersistent(false);
+        }
+    }
+
+    @Override
+    public void onResume() {
+        if (mSettingObserver != null) {
+            mSettingObserver.register(true /* register */);
+        }
+    }
+
+    @Override
+    public void onPause() {
+        if (mSettingObserver != null) {
+            mSettingObserver.register(false /* register */);
+        }
+    }
+
+    @Override
+    public boolean handlePreferenceTreeClick(Preference preference) {
+        return false;
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return KEY_VIBRATE_WHEN_RINGING;
+    }
+
+    @Override
+    public boolean isAvailable() {
+        return Utils.isVoiceCapable(mContext);
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        ((TwoStatePreference) preference).setChecked(
+            Settings.System.getInt(mContext.getContentResolver(), VIBRATE_WHEN_RINGING, 0) != 0);
+    }
+
+    @Override
+    public boolean onPreferenceChange(Preference preference, Object newValue) {
+        final boolean val = (Boolean) newValue;
+        return Settings.System.putInt(mContext.getContentResolver(),
+            VIBRATE_WHEN_RINGING, val ? 1 : 0);
+    }
+
+    private final class SettingObserver extends ContentObserver {
+
+        private final Uri VIBRATE_WHEN_RINGING_URI =
+            Settings.System.getUriFor(VIBRATE_WHEN_RINGING);
+
+        private final Preference mPreference;
+
+        public SettingObserver(Preference preference) {
+            super(new Handler());
+            mPreference = preference;
+        }
+
+        public void register(boolean register) {
+            final ContentResolver cr = mContext.getContentResolver();
+            if (register) {
+                cr.registerContentObserver(VIBRATE_WHEN_RINGING_URI, false, this);
+            } else {
+                cr.unregisterContentObserver(this);
+            }
+        }
+
+        @Override
+        public void onChange(boolean selfChange, Uri uri) {
+            super.onChange(selfChange, uri);
+            if (VIBRATE_WHEN_RINGING_URI.equals(uri)) {
+                updateState(mPreference);
+            }
+        }
+    }
+
+}
diff --git a/src/com/android/settings/notification/VolumeSeekBarPreferenceController.java b/src/com/android/settings/notification/VolumeSeekBarPreferenceController.java
index adc86b8..eeb9c28 100644
--- a/src/com/android/settings/notification/VolumeSeekBarPreferenceController.java
+++ b/src/com/android/settings/notification/VolumeSeekBarPreferenceController.java
@@ -17,8 +17,6 @@
 package com.android.settings.notification;
 
 import android.content.Context;
-
-import android.support.v7.preference.Preference;
 import android.support.v7.preference.PreferenceScreen;
 
 import com.android.settings.core.lifecycle.Lifecycle;
@@ -31,13 +29,13 @@
  * Base class for preference controller that handles VolumeSeekBarPreference
  */
 public abstract class VolumeSeekBarPreferenceController extends
-    AdjustVolumeRestrictedPreferenceController implements LifecycleObserver, OnResume, OnPause {
+        AdjustVolumeRestrictedPreferenceController implements LifecycleObserver, OnResume, OnPause {
 
     protected VolumeSeekBarPreference mPreference;
     protected VolumeSeekBarPreference.Callback mVolumePreferenceCallback;
 
     public VolumeSeekBarPreferenceController(Context context, Callback callback,
-        Lifecycle lifecycle) {
+            Lifecycle lifecycle) {
         super(context);
         mVolumePreferenceCallback = callback;
         if (lifecycle != null) {
@@ -70,11 +68,6 @@
         }
     }
 
-    @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        return false;
-    }
-
     protected abstract int getAudioStream();
 
     protected abstract int getMuteIcon();
diff --git a/src/com/android/settings/notification/ZenModePreferenceController.java b/src/com/android/settings/notification/ZenModePreferenceController.java
index e554732..61bbe9a 100644
--- a/src/com/android/settings/notification/ZenModePreferenceController.java
+++ b/src/com/android/settings/notification/ZenModePreferenceController.java
@@ -17,7 +17,6 @@
 package com.android.settings.notification;
 
 import android.content.Context;
-import android.support.v7.preference.Preference;
 
 public class ZenModePreferenceController extends AdjustVolumeRestrictedPreferenceController {
 
@@ -28,11 +27,6 @@
     }
 
     @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        return false;
-    }
-
-    @Override
     public String getPreferenceKey() {
         return KEY_ZEN_MODE;
     }
diff --git a/src/com/android/settings/search2/DatabaseIndexingManager.java b/src/com/android/settings/search2/DatabaseIndexingManager.java
new file mode 100644
index 0000000..9bb4538
--- /dev/null
+++ b/src/com/android/settings/search2/DatabaseIndexingManager.java
@@ -0,0 +1,963 @@
+/*
+ * 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.search2;
+
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.res.XmlResourceParser;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteException;
+import android.database.sqlite.SQLiteFullException;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.provider.SearchIndexableData;
+import android.provider.SearchIndexableResource;
+import android.provider.SearchIndexablesContract;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.Xml;
+
+import com.android.settings.search.IndexDatabaseHelper;
+import com.android.settings.search.Indexable;
+import com.android.settings.search.Ranking;
+import com.android.settings.search.SearchIndexableRaw;
+import com.android.settings.search.SearchIndexableResources;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import static android.provider.SearchIndexablesContract.COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE;
+import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_CLASS_NAME;
+import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_ENTRIES;
+import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_ICON_RESID;
+import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_INTENT_ACTION;
+import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_INTENT_TARGET_CLASS;
+import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_INTENT_TARGET_PACKAGE;
+import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_KEY;
+import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_KEYWORDS;
+import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_RANK;
+import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_SCREEN_TITLE;
+import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_SUMMARY_OFF;
+import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_SUMMARY_ON;
+import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_TITLE;
+import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_USER_ID;
+import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_CLASS_NAME;
+import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_ICON_RESID;
+import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_INTENT_ACTION;
+import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_INTENT_TARGET_CLASS;
+import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_INTENT_TARGET_PACKAGE;
+import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_RANK;
+import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_RESID;
+
+/**
+ * Consumes the SearchIndexableProvider content providers.
+ * Updates the Resource, Raw Data and non-indexable data for Search.
+ */
+public class DatabaseIndexingManager {
+    private static final String LOG_TAG = "DatabaseIndexingManager";
+
+    // Those indices should match the indices of SELECT_COLUMNS !
+    public static final int COLUMN_INDEX_RANK = 0;
+    public static final int COLUMN_INDEX_TITLE = 1;
+    public static final int COLUMN_INDEX_SUMMARY_ON = 2;
+    public static final int COLUMN_INDEX_SUMMARY_OFF = 3;
+    public static final int COLUMN_INDEX_ENTRIES = 4;
+    public static final int COLUMN_INDEX_KEYWORDS = 5;
+    public static final int COLUMN_INDEX_CLASS_NAME = 6;
+    public static final int COLUMN_INDEX_SCREEN_TITLE = 7;
+    public static final int COLUMN_INDEX_ICON = 8;
+    public static final int COLUMN_INDEX_INTENT_ACTION = 9;
+    public static final int COLUMN_INDEX_INTENT_ACTION_TARGET_PACKAGE = 10;
+    public static final int COLUMN_INDEX_INTENT_ACTION_TARGET_CLASS = 11;
+    public static final int COLUMN_INDEX_ENABLED = 12;
+    public static final int COLUMN_INDEX_KEY = 13;
+    public static final int COLUMN_INDEX_USER_ID = 14;
+
+    // If you change the order of columns here, you SHOULD change the COLUMN_INDEX_XXX values
+    private static final String[] SELECT_COLUMNS = new String[] {
+            IndexDatabaseHelper.IndexColumns.DATA_RANK,               // 0
+            IndexDatabaseHelper.IndexColumns.DATA_TITLE,              // 1
+            IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_ON,         // 2
+            IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_OFF,        // 3
+            IndexDatabaseHelper.IndexColumns.DATA_ENTRIES,            // 4
+            IndexDatabaseHelper.IndexColumns.DATA_KEYWORDS,           // 5
+            IndexDatabaseHelper.IndexColumns.CLASS_NAME,              // 6
+            IndexDatabaseHelper.IndexColumns.SCREEN_TITLE,            // 7
+            IndexDatabaseHelper.IndexColumns.ICON,                    // 8
+            IndexDatabaseHelper.IndexColumns.INTENT_ACTION,           // 9
+            IndexDatabaseHelper.IndexColumns.INTENT_TARGET_PACKAGE,   // 10
+            IndexDatabaseHelper.IndexColumns.INTENT_TARGET_CLASS,     // 11
+            IndexDatabaseHelper.IndexColumns.ENABLED,                 // 12
+            IndexDatabaseHelper.IndexColumns.DATA_KEY_REF             // 13
+    };
+
+    private static final String[] MATCH_COLUMNS_PRIMARY = {
+            IndexDatabaseHelper.IndexColumns.DATA_TITLE,
+            IndexDatabaseHelper.IndexColumns.DATA_TITLE_NORMALIZED,
+            IndexDatabaseHelper.IndexColumns.DATA_KEYWORDS
+    };
+
+    private static final String[] MATCH_COLUMNS_SECONDARY = {
+            IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_ON,
+            IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_ON_NORMALIZED,
+            IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_OFF,
+            IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_OFF_NORMALIZED,
+            IndexDatabaseHelper.IndexColumns.DATA_ENTRIES
+    };
+
+
+    private static final String NODE_NAME_PREFERENCE_SCREEN = "PreferenceScreen";
+    private static final String NODE_NAME_CHECK_BOX_PREFERENCE = "CheckBoxPreference";
+    private static final String NODE_NAME_LIST_PREFERENCE = "ListPreference";
+
+    private static final List<String> EMPTY_LIST = Collections.<String>emptyList();
+
+    private final String mBaseAuthority;
+
+    /**
+     * A private class to describe the update data for the Index database
+     */
+    private static class UpdateData {
+        public List<SearchIndexableData> dataToUpdate;
+        public List<SearchIndexableData> dataToDelete;
+        public Map<String, List<String>> nonIndexableKeys;
+
+        public boolean forceUpdate;
+        public boolean fullIndex;
+
+        public UpdateData() {
+            dataToUpdate = new ArrayList<SearchIndexableData>();
+            dataToDelete = new ArrayList<SearchIndexableData>();
+            nonIndexableKeys = new HashMap<String, List<String>>();
+        }
+
+        public UpdateData(DatabaseIndexingManager.UpdateData other) {
+            dataToUpdate = new ArrayList<SearchIndexableData>(other.dataToUpdate);
+            dataToDelete = new ArrayList<SearchIndexableData>(other.dataToDelete);
+            nonIndexableKeys = new HashMap<String, List<String>>(other.nonIndexableKeys);
+            forceUpdate = other.forceUpdate;
+            fullIndex = other.fullIndex;
+        }
+
+        public DatabaseIndexingManager.UpdateData copy() {
+            return new DatabaseIndexingManager.UpdateData(this);
+        }
+
+        public void clear() {
+            dataToUpdate.clear();
+            dataToDelete.clear();
+            nonIndexableKeys.clear();
+            forceUpdate = false;
+            fullIndex = false;
+        }
+    }
+
+    private final AtomicBoolean mIsAvailable = new AtomicBoolean(false);
+    private final DatabaseIndexingManager.UpdateData mDataToProcess =
+            new DatabaseIndexingManager.UpdateData();
+    private Context mContext;
+
+    public DatabaseIndexingManager(Context context, String baseAuthority) {
+        mContext = context;
+        mBaseAuthority = baseAuthority;
+    }
+
+    public void setContext(Context context) {
+        mContext = context;
+    }
+
+    public boolean isAvailable() {
+        return mIsAvailable.get();
+    }
+
+    public void update() {
+        AsyncTask.execute(new Runnable() {
+            @Override
+            public void run() {
+                final Intent intent = new Intent(SearchIndexablesContract.PROVIDER_INTERFACE);
+                List<ResolveInfo> list =
+                        mContext.getPackageManager().queryIntentContentProviders(intent, 0);
+
+                final int size = list.size();
+                for (int n = 0; n < size; n++) {
+                    final ResolveInfo info = list.get(n);
+                    if (!DatabaseIndexingUtils.isWellKnownProvider(info, mContext)) {
+                        continue;
+                    }
+                    final String authority = info.providerInfo.authority;
+                    final String packageName = info.providerInfo.packageName;
+
+                    addIndexablesFromRemoteProvider(packageName, authority);
+                    addNonIndexablesKeysFromRemoteProvider(packageName, authority);
+                }
+
+                mDataToProcess.fullIndex = true;
+                updateInternal();
+            }
+        });
+    }
+
+    private boolean addIndexablesFromRemoteProvider(String packageName, String authority) {
+        try {
+            final int baseRank = Ranking.getBaseRankForAuthority(authority);
+
+            final Context context = mBaseAuthority.equals(authority) ?
+                    mContext : mContext.createPackageContext(packageName, 0);
+
+            final Uri uriForResources = buildUriForXmlResources(authority);
+            addIndexablesForXmlResourceUri(context, packageName, uriForResources,
+                    SearchIndexablesContract.INDEXABLES_XML_RES_COLUMNS, baseRank);
+
+            final Uri uriForRawData = buildUriForRawData(authority);
+            addIndexablesForRawDataUri(context, packageName, uriForRawData,
+                    SearchIndexablesContract.INDEXABLES_RAW_COLUMNS, baseRank);
+            return true;
+        } catch (PackageManager.NameNotFoundException e) {
+            Log.w(LOG_TAG, "Could not create context for " + packageName + ": "
+                    + Log.getStackTraceString(e));
+            return false;
+        }
+    }
+
+    private void addNonIndexablesKeysFromRemoteProvider(String packageName,
+            String authority) {
+        final List<String> keys =
+                getNonIndexablesKeysFromRemoteProvider(packageName, authority);
+        addNonIndexableKeys(packageName, keys);
+    }
+
+    private List<String> getNonIndexablesKeysFromRemoteProvider(String packageName,
+            String authority) {
+        try {
+            final Context packageContext = mContext.createPackageContext(packageName, 0);
+
+            final Uri uriForNonIndexableKeys = buildUriForNonIndexableKeys(authority);
+            return getNonIndexablesKeys(packageContext, uriForNonIndexableKeys,
+                    SearchIndexablesContract.NON_INDEXABLES_KEYS_COLUMNS);
+        } catch (PackageManager.NameNotFoundException e) {
+            Log.w(LOG_TAG, "Could not create context for " + packageName + ": "
+                    + Log.getStackTraceString(e));
+            return EMPTY_LIST;
+        }
+    }
+
+    private List<String> getNonIndexablesKeys(Context packageContext, Uri uri,
+            String[] projection) {
+
+        final ContentResolver resolver = packageContext.getContentResolver();
+        final Cursor cursor = resolver.query(uri, projection, null, null, null);
+
+        if (cursor == null) {
+            Log.w(LOG_TAG, "Cannot add index data for Uri: " + uri.toString());
+            return EMPTY_LIST;
+        }
+
+        List<String> result = new ArrayList<String>();
+        try {
+            final int count = cursor.getCount();
+            if (count > 0) {
+                while (cursor.moveToNext()) {
+                    final String key = cursor.getString(COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE);
+                    result.add(key);
+                }
+            }
+            return result;
+        } finally {
+            cursor.close();
+        }
+    }
+
+    public void addIndexableData(SearchIndexableData data) {
+        synchronized (mDataToProcess) {
+            mDataToProcess.dataToUpdate.add(data);
+        }
+    }
+
+    public void deleteIndexableData(SearchIndexableData data) {
+        synchronized (mDataToProcess) {
+            mDataToProcess.dataToDelete.add(data);
+        }
+    }
+
+    public void addNonIndexableKeys(String authority, List<String> keys) {
+        synchronized (mDataToProcess) {
+            mDataToProcess.nonIndexableKeys.put(authority, keys);
+        }
+    }
+
+    private void updateFromRemoteProvider(String packageName, String authority) {
+        if (addIndexablesFromRemoteProvider(packageName, authority)) {
+            updateInternal();
+        }
+    }
+
+    /**
+     * Update the Index for a specific class name resources
+     *
+     * @param className the class name (typically a fragment name).
+     * @param rebuild true means that you want to delete the data from the Index first.
+     * @param includeInSearchResults true means that you want the bit "enabled" set so that the
+     *                               data will be seen included into the search results
+     */
+    public void updateFromClassNameResource(String className, final boolean rebuild,
+            boolean includeInSearchResults) {
+        if (className == null) {
+            throw new IllegalArgumentException("class name cannot be null!");
+        }
+        final SearchIndexableResource res = SearchIndexableResources.getResourceByName(className);
+        if (res == null ) {
+            Log.e(LOG_TAG, "Cannot find SearchIndexableResources for class name: " + className);
+            return;
+        }
+        res.context = mContext;
+        res.enabled = includeInSearchResults;
+        AsyncTask.execute(new Runnable() {
+            @Override
+            public void run() {
+                if (rebuild) {
+                    deleteIndexableData(res);
+                }
+                addIndexableData(res);
+                mDataToProcess.forceUpdate = true;
+                updateInternal();
+                res.enabled = false;
+            }
+        });
+    }
+
+    public void updateFromSearchIndexableData(final SearchIndexableData data) {
+        AsyncTask.execute(new Runnable() {
+            @Override
+            public void run() {
+                addIndexableData(data);
+                mDataToProcess.forceUpdate = true;
+                updateInternal();
+            }
+        });
+    }
+
+    private SQLiteDatabase getReadableDatabase() {
+        return IndexDatabaseHelper.getInstance(mContext).getReadableDatabase();
+    }
+
+    private SQLiteDatabase getWritableDatabase() {
+        try {
+            return IndexDatabaseHelper.getInstance(mContext).getWritableDatabase();
+        } catch (SQLiteException e) {
+            Log.e(LOG_TAG, "Cannot open writable database", e);
+            return null;
+        }
+    }
+
+    private static Uri buildUriForXmlResources(String authority) {
+        return Uri.parse("content://" + authority + "/" +
+                SearchIndexablesContract.INDEXABLES_XML_RES_PATH);
+    }
+
+    private static Uri buildUriForRawData(String authority) {
+        return Uri.parse("content://" + authority + "/" +
+                SearchIndexablesContract.INDEXABLES_RAW_PATH);
+    }
+
+    private static Uri buildUriForNonIndexableKeys(String authority) {
+        return Uri.parse("content://" + authority + "/" +
+                SearchIndexablesContract.NON_INDEXABLES_KEYS_PATH);
+    }
+
+    private void updateInternal() {
+        synchronized (mDataToProcess) {
+            final DatabaseIndexingManager.UpdateIndexTask task =
+                    new DatabaseIndexingManager.UpdateIndexTask();
+            DatabaseIndexingManager.UpdateData copy = mDataToProcess.copy();
+            task.execute(copy);
+            mDataToProcess.clear();
+        }
+    }
+
+    private void addIndexablesForXmlResourceUri(Context packageContext, String packageName,
+            Uri uri, String[] projection, int baseRank) {
+
+        final ContentResolver resolver = packageContext.getContentResolver();
+        final Cursor cursor = resolver.query(uri, projection, null, null, null);
+
+        if (cursor == null) {
+            Log.w(LOG_TAG, "Cannot add index data for Uri: " + uri.toString());
+            return;
+        }
+
+        try {
+            final int count = cursor.getCount();
+            if (count > 0) {
+                while (cursor.moveToNext()) {
+                    final int providerRank = cursor.getInt(COLUMN_INDEX_XML_RES_RANK);
+                    final int rank = (providerRank > 0) ? baseRank + providerRank : baseRank;
+
+                    final int xmlResId = cursor.getInt(COLUMN_INDEX_XML_RES_RESID);
+
+                    final String className = cursor.getString(COLUMN_INDEX_XML_RES_CLASS_NAME);
+                    final int iconResId = cursor.getInt(COLUMN_INDEX_XML_RES_ICON_RESID);
+
+                    final String action = cursor.getString(COLUMN_INDEX_XML_RES_INTENT_ACTION);
+                    final String targetPackage = cursor.getString(
+                            COLUMN_INDEX_XML_RES_INTENT_TARGET_PACKAGE);
+                    final String targetClass = cursor.getString(
+                            COLUMN_INDEX_XML_RES_INTENT_TARGET_CLASS);
+
+                    SearchIndexableResource sir = new SearchIndexableResource(packageContext);
+                    sir.rank = rank;
+                    sir.xmlResId = xmlResId;
+                    sir.className = className;
+                    sir.packageName = packageName;
+                    sir.iconResId = iconResId;
+                    sir.intentAction = action;
+                    sir.intentTargetPackage = targetPackage;
+                    sir.intentTargetClass = targetClass;
+
+                    addIndexableData(sir);
+                }
+            }
+        } finally {
+            cursor.close();
+        }
+    }
+
+    private void addIndexablesForRawDataUri(Context packageContext, String packageName,
+            Uri uri, String[] projection, int baseRank) {
+
+        final ContentResolver resolver = packageContext.getContentResolver();
+        final Cursor cursor = resolver.query(uri, projection, null, null, null);
+
+        if (cursor == null) {
+            Log.w(LOG_TAG, "Cannot add index data for Uri: " + uri.toString());
+            return;
+        }
+
+        try {
+            final int count = cursor.getCount();
+            if (count > 0) {
+                while (cursor.moveToNext()) {
+                    final int providerRank = cursor.getInt(COLUMN_INDEX_RAW_RANK);
+                    final int rank = (providerRank > 0) ? baseRank + providerRank : baseRank;
+
+                    final String title = cursor.getString(COLUMN_INDEX_RAW_TITLE);
+                    final String summaryOn = cursor.getString(COLUMN_INDEX_RAW_SUMMARY_ON);
+                    final String summaryOff = cursor.getString(COLUMN_INDEX_RAW_SUMMARY_OFF);
+                    final String entries = cursor.getString(COLUMN_INDEX_RAW_ENTRIES);
+                    final String keywords = cursor.getString(COLUMN_INDEX_RAW_KEYWORDS);
+
+                    final String screenTitle = cursor.getString(COLUMN_INDEX_RAW_SCREEN_TITLE);
+
+                    final String className = cursor.getString(COLUMN_INDEX_RAW_CLASS_NAME);
+                    final int iconResId = cursor.getInt(COLUMN_INDEX_RAW_ICON_RESID);
+
+                    final String action = cursor.getString(COLUMN_INDEX_RAW_INTENT_ACTION);
+                    final String targetPackage = cursor.getString(
+                            COLUMN_INDEX_RAW_INTENT_TARGET_PACKAGE);
+                    final String targetClass = cursor.getString(
+                            COLUMN_INDEX_RAW_INTENT_TARGET_CLASS);
+
+                    final String key = cursor.getString(COLUMN_INDEX_RAW_KEY);
+                    final int userId = cursor.getInt(COLUMN_INDEX_RAW_USER_ID);
+
+                    SearchIndexableRaw data = new SearchIndexableRaw(packageContext);
+                    data.rank = rank;
+                    data.title = title;
+                    data.summaryOn = summaryOn;
+                    data.summaryOff = summaryOff;
+                    data.entries = entries;
+                    data.keywords = keywords;
+                    data.screenTitle = screenTitle;
+                    data.className = className;
+                    data.packageName = packageName;
+                    data.iconResId = iconResId;
+                    data.intentAction = action;
+                    data.intentTargetPackage = targetPackage;
+                    data.intentTargetClass = targetClass;
+                    data.key = key;
+                    data.userId = userId;
+
+                    addIndexableData(data);
+                }
+            }
+        } finally {
+            cursor.close();
+        }
+    }
+
+    private void indexOneSearchIndexableData(SQLiteDatabase database, String localeStr,
+            SearchIndexableData data, Map<String, List<String>> nonIndexableKeys) {
+        if (data instanceof SearchIndexableResource) {
+            indexOneResource(database, localeStr, (SearchIndexableResource) data, nonIndexableKeys);
+        } else if (data instanceof SearchIndexableRaw) {
+            indexOneRaw(database, localeStr, (SearchIndexableRaw) data);
+        }
+    }
+
+    private void indexOneRaw(SQLiteDatabase database, String localeStr,
+            SearchIndexableRaw raw) {
+        // Should be the same locale as the one we are processing
+        if (!raw.locale.toString().equalsIgnoreCase(localeStr)) {
+            return;
+        }
+
+        updateOneRowWithFilteredData(database, localeStr,
+                raw.title,
+                raw.summaryOn,
+                raw.summaryOff,
+                raw.entries,
+                raw.className,
+                raw.screenTitle,
+                raw.iconResId,
+                raw.rank,
+                raw.keywords,
+                raw.intentAction,
+                raw.intentTargetPackage,
+                raw.intentTargetClass,
+                raw.enabled,
+                raw.key,
+                raw.userId);
+    }
+
+    private void indexOneResource(SQLiteDatabase database, String localeStr,
+            SearchIndexableResource sir, Map<String, List<String>> nonIndexableKeysFromResource) {
+
+        if (sir == null) {
+            Log.e(LOG_TAG, "Cannot index a null resource!");
+            return;
+        }
+
+        final List<String> nonIndexableKeys = new ArrayList<String>();
+
+        if (sir.xmlResId > SearchIndexableResources.NO_DATA_RES_ID) {
+            List<String> resNonIndxableKeys = nonIndexableKeysFromResource.get(sir.packageName);
+            if (resNonIndxableKeys != null && resNonIndxableKeys.size() > 0) {
+                nonIndexableKeys.addAll(resNonIndxableKeys);
+            }
+
+            indexFromResource(sir.context, database, localeStr,
+                    sir.xmlResId, sir.className, sir.iconResId, sir.rank,
+                    sir.intentAction, sir.intentTargetPackage, sir.intentTargetClass,
+                    nonIndexableKeys);
+        } else {
+            if (TextUtils.isEmpty(sir.className)) {
+                Log.w(LOG_TAG, "Cannot index an empty Search Provider name!");
+                return;
+            }
+
+            final Class<?> clazz = DatabaseIndexingUtils.getIndexableClass(sir.className);
+            if (clazz == null) {
+                Log.d(LOG_TAG, "SearchIndexableResource '" + sir.className +
+                        "' should implement the " + Indexable.class.getName() + " interface!");
+                return;
+            }
+
+            // Will be non null only for a Local provider implementing a
+            // SEARCH_INDEX_DATA_PROVIDER field
+            final Indexable.SearchIndexProvider provider =
+                    DatabaseIndexingUtils.getSearchIndexProvider(clazz);
+            if (provider != null) {
+                List<String> providerNonIndexableKeys = provider.getNonIndexableKeys(sir.context);
+                if (providerNonIndexableKeys != null && providerNonIndexableKeys.size() > 0) {
+                    nonIndexableKeys.addAll(providerNonIndexableKeys);
+                }
+
+                indexFromProvider(mContext, database, localeStr, provider, sir.className,
+                        sir.iconResId, sir.rank, sir.enabled, nonIndexableKeys);
+            }
+        }
+    }
+
+    private void indexFromResource(Context context, SQLiteDatabase database, String localeStr,
+            int xmlResId, String fragmentName, int iconResId, int rank,
+            String intentAction, String intentTargetPackage, String intentTargetClass,
+            List<String> nonIndexableKeys) {
+
+        XmlResourceParser parser = null;
+        try {
+            parser = context.getResources().getXml(xmlResId);
+
+            int type;
+            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                    && type != XmlPullParser.START_TAG) {
+                // Parse next until start tag is found
+            }
+
+            String nodeName = parser.getName();
+            if (!NODE_NAME_PREFERENCE_SCREEN.equals(nodeName)) {
+                throw new RuntimeException(
+                        "XML document must start with <PreferenceScreen> tag; found"
+                                + nodeName + " at " + parser.getPositionDescription());
+            }
+
+            final int outerDepth = parser.getDepth();
+            final AttributeSet attrs = Xml.asAttributeSet(parser);
+
+            final String screenTitle = XMLParserUtil.getDataTitle(context, attrs);
+
+            String key = XMLParserUtil.getDataKey(context, attrs);
+
+            String title;
+            String summary;
+            String keywords;
+
+            // Insert rows for the main PreferenceScreen node. Rewrite the data for removing
+            // hyphens.
+            if (!nonIndexableKeys.contains(key)) {
+                title = XMLParserUtil.getDataTitle(context, attrs);
+                summary = XMLParserUtil.getDataSummary(context, attrs);
+                keywords = XMLParserUtil.getDataKeywords(context, attrs);
+
+                updateOneRowWithFilteredData(database, localeStr, title, summary, null, null,
+                        fragmentName, screenTitle, iconResId, rank,
+                        keywords, intentAction, intentTargetPackage, intentTargetClass, true,
+                        key, -1 /* default user id */);
+            }
+
+            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+                if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                    continue;
+                }
+
+                nodeName = parser.getName();
+
+                key = XMLParserUtil.getDataKey(context, attrs);
+                if (nonIndexableKeys.contains(key)) {
+                    continue;
+                }
+
+                title = XMLParserUtil.getDataTitle(context, attrs);
+                keywords = XMLParserUtil.getDataKeywords(context, attrs);
+
+                if (!nodeName.equals(NODE_NAME_CHECK_BOX_PREFERENCE)) {
+                    summary = XMLParserUtil.getDataSummary(context, attrs);
+
+                    String entries = null;
+
+                    if (nodeName.endsWith(NODE_NAME_LIST_PREFERENCE)) {
+                        entries = XMLParserUtil.getDataEntries(context, attrs);
+                    }
+
+                    // Insert rows for the child nodes of PreferenceScreen
+                    updateOneRowWithFilteredData(database, localeStr, title, summary, null, entries,
+                            fragmentName, screenTitle, iconResId, rank,
+                            keywords, intentAction, intentTargetPackage, intentTargetClass,
+                            true, key, -1 /* default user id */);
+                } else {
+                    String summaryOn = XMLParserUtil.getDataSummaryOn(context, attrs);
+                    String summaryOff = XMLParserUtil.getDataSummaryOff(context, attrs);
+
+                    if (TextUtils.isEmpty(summaryOn) && TextUtils.isEmpty(summaryOff)) {
+                        summaryOn = XMLParserUtil.getDataSummary(context, attrs);
+                    }
+
+                    updateOneRowWithFilteredData(database, localeStr, title, summaryOn, summaryOff,
+                            null, fragmentName, screenTitle, iconResId, rank,
+                            keywords, intentAction, intentTargetPackage, intentTargetClass,
+                            true, key, -1 /* default user id */);
+                }
+            }
+
+        } catch (XmlPullParserException e) {
+            throw new RuntimeException("Error parsing PreferenceScreen", e);
+        } catch (IOException e) {
+            throw new RuntimeException("Error parsing PreferenceScreen", e);
+        } finally {
+            if (parser != null) parser.close();
+        }
+    }
+
+    private void indexFromProvider(Context context, SQLiteDatabase database, String localeStr,
+            Indexable.SearchIndexProvider provider, String className, int iconResId, int rank,
+            boolean enabled, List<String> nonIndexableKeys) {
+
+        if (provider == null) {
+            Log.w(LOG_TAG, "Cannot find provider: " + className);
+            return;
+        }
+
+        final List<SearchIndexableRaw> rawList = provider.getRawDataToIndex(context, enabled);
+
+        if (rawList != null) {
+            final int rawSize = rawList.size();
+            for (int i = 0; i < rawSize; i++) {
+                SearchIndexableRaw raw = rawList.get(i);
+
+                // Should be the same locale as the one we are processing
+                if (!raw.locale.toString().equalsIgnoreCase(localeStr)) {
+                    continue;
+                }
+
+                if (nonIndexableKeys.contains(raw.key)) {
+                    continue;
+                }
+
+                updateOneRowWithFilteredData(database, localeStr,
+                        raw.title,
+                        raw.summaryOn,
+                        raw.summaryOff,
+                        raw.entries,
+                        className,
+                        raw.screenTitle,
+                        iconResId,
+                        rank,
+                        raw.keywords,
+                        raw.intentAction,
+                        raw.intentTargetPackage,
+                        raw.intentTargetClass,
+                        raw.enabled,
+                        raw.key,
+                        raw.userId);
+            }
+        }
+
+        final List<SearchIndexableResource> resList =
+                provider.getXmlResourcesToIndex(context, enabled);
+        if (resList != null) {
+            final int resSize = resList.size();
+            for (int i = 0; i < resSize; i++) {
+                SearchIndexableResource item = resList.get(i);
+
+                // Should be the same locale as the one we are processing
+                if (!item.locale.toString().equalsIgnoreCase(localeStr)) {
+                    continue;
+                }
+
+                final int itemIconResId = (item.iconResId == 0) ? iconResId : item.iconResId;
+                final int itemRank = (item.rank == 0) ? rank : item.rank;
+                String itemClassName = (TextUtils.isEmpty(item.className))
+                        ? className : item.className;
+
+                indexFromResource(context, database, localeStr,
+                        item.xmlResId, itemClassName, itemIconResId, itemRank,
+                        item.intentAction, item.intentTargetPackage,
+                        item.intentTargetClass, nonIndexableKeys);
+            }
+        }
+    }
+
+    private void updateOneRowWithFilteredData(SQLiteDatabase database, String locale,
+            String title, String summaryOn, String summaryOff, String entries,
+            String className,
+            String screenTitle, int iconResId, int rank, String keywords,
+            String intentAction, String intentTargetPackage, String intentTargetClass,
+            boolean enabled, String key, int userId) {
+
+        final String updatedTitle = XMLParserUtil.normalizeHyphen(title);
+        final String updatedSummaryOn = XMLParserUtil.normalizeHyphen(summaryOn);
+        final String updatedSummaryOff = XMLParserUtil.normalizeHyphen(summaryOff);
+
+        final String normalizedTitle = XMLParserUtil.normalizeString(updatedTitle);
+        final String normalizedSummaryOn = XMLParserUtil.normalizeString(updatedSummaryOn);
+        final String normalizedSummaryOff = XMLParserUtil.normalizeString(updatedSummaryOff);
+
+        final String spaceDelimitedKeywords = XMLParserUtil.normalizeKeywords(keywords);
+
+        updateOneRow(database, locale,
+                updatedTitle, normalizedTitle, updatedSummaryOn, normalizedSummaryOn,
+                updatedSummaryOff, normalizedSummaryOff, entries, className, screenTitle, iconResId,
+                rank, spaceDelimitedKeywords, intentAction, intentTargetPackage, intentTargetClass,
+                enabled, key, userId);
+    }
+
+    private void updateOneRow(SQLiteDatabase database, String locale, String updatedTitle,
+            String normalizedTitle, String updatedSummaryOn, String normalizedSummaryOn,
+            String updatedSummaryOff, String normalizedSummaryOff, String entries, String className,
+            String screenTitle, int iconResId, int rank, String spaceDelimitedKeywords,
+            String intentAction, String intentTargetPackage, String intentTargetClass,
+            boolean enabled, String key, int userId) {
+
+        if (TextUtils.isEmpty(updatedTitle)) {
+            return;
+        }
+
+        // The DocID should contains more than the title string itself (you may have two settings
+        // with the same title). So we need to use a combination of the title and the screenTitle.
+        StringBuilder sb = new StringBuilder(updatedTitle);
+        sb.append(screenTitle);
+        int docId = sb.toString().hashCode();
+
+        ContentValues values = new ContentValues();
+        values.put(IndexDatabaseHelper.IndexColumns.DOCID, docId);
+        values.put(IndexDatabaseHelper.IndexColumns.LOCALE, locale);
+        values.put(IndexDatabaseHelper.IndexColumns.DATA_RANK, rank);
+        values.put(IndexDatabaseHelper.IndexColumns.DATA_TITLE, updatedTitle);
+        values.put(IndexDatabaseHelper.IndexColumns.DATA_TITLE_NORMALIZED, normalizedTitle);
+        values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_ON, updatedSummaryOn);
+        values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_ON_NORMALIZED,
+                normalizedSummaryOn);
+        values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_OFF, updatedSummaryOff);
+        values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_OFF_NORMALIZED,
+                normalizedSummaryOff);
+        values.put(IndexDatabaseHelper.IndexColumns.DATA_ENTRIES, entries);
+        values.put(IndexDatabaseHelper.IndexColumns.DATA_KEYWORDS, spaceDelimitedKeywords);
+        values.put(IndexDatabaseHelper.IndexColumns.CLASS_NAME, className);
+        values.put(IndexDatabaseHelper.IndexColumns.SCREEN_TITLE, screenTitle);
+        values.put(IndexDatabaseHelper.IndexColumns.INTENT_ACTION, intentAction);
+        values.put(IndexDatabaseHelper.IndexColumns.INTENT_TARGET_PACKAGE, intentTargetPackage);
+        values.put(IndexDatabaseHelper.IndexColumns.INTENT_TARGET_CLASS, intentTargetClass);
+        values.put(IndexDatabaseHelper.IndexColumns.ICON, iconResId);
+        values.put(IndexDatabaseHelper.IndexColumns.ENABLED, enabled);
+        values.put(IndexDatabaseHelper.IndexColumns.DATA_KEY_REF, key);
+        values.put(IndexDatabaseHelper.IndexColumns.USER_ID, userId);
+
+        database.replaceOrThrow(IndexDatabaseHelper.Tables.TABLE_PREFS_INDEX, null, values);
+    }
+
+    /**
+     * A private class for updating the Index database
+     */
+    private class UpdateIndexTask extends AsyncTask<DatabaseIndexingManager.UpdateData, Integer,
+            Void> {
+
+        @Override
+        protected void onPreExecute() {
+            super.onPreExecute();
+            mIsAvailable.set(false);
+        }
+
+        @Override
+        protected void onPostExecute(Void aVoid) {
+            super.onPostExecute(aVoid);
+            mIsAvailable.set(true);
+        }
+
+        @Override
+        protected Void doInBackground(DatabaseIndexingManager.UpdateData... params) {
+            try {
+                final List<SearchIndexableData> dataToUpdate = params[0].dataToUpdate;
+                final List<SearchIndexableData> dataToDelete = params[0].dataToDelete;
+                final Map<String, List<String>> nonIndexableKeys = params[0].nonIndexableKeys;
+
+                final boolean forceUpdate = params[0].forceUpdate;
+                final boolean fullIndex = params[0].fullIndex;
+
+                final SQLiteDatabase database = getWritableDatabase();
+                if (database == null) {
+                    Log.e(LOG_TAG, "Cannot update Index as I cannot get a writable database");
+                    return null;
+                }
+                final String localeStr = Locale.getDefault().toString();
+
+                try {
+                    database.beginTransaction();
+                    if (dataToDelete.size() > 0) {
+                        processDataToDelete(database, localeStr, dataToDelete);
+                    }
+                    if (dataToUpdate.size() > 0) {
+                        processDataToUpdate(database, localeStr, dataToUpdate, nonIndexableKeys,
+                                forceUpdate);
+                    }
+                    database.setTransactionSuccessful();
+                } finally {
+                    database.endTransaction();
+                }
+                if (fullIndex) {
+                    IndexDatabaseHelper.setLocaleIndexed(mContext, localeStr);
+                }
+            } catch (SQLiteFullException e) {
+                Log.e(LOG_TAG, "Unable to index search, out of space", e);
+            }
+
+            return null;
+        }
+
+        private boolean processDataToUpdate(SQLiteDatabase database, String localeStr,
+                List<SearchIndexableData> dataToUpdate, Map<String, List<String>> nonIndexableKeys,
+                boolean forceUpdate) {
+
+            if (!forceUpdate && IndexDatabaseHelper.isLocaleAlreadyIndexed(mContext, localeStr)) {
+                Log.d(LOG_TAG, "Locale '" + localeStr + "' is already indexed");
+                return true;
+            }
+
+            boolean result = false;
+            final long current = System.currentTimeMillis();
+
+            final int count = dataToUpdate.size();
+            for (int n = 0; n < count; n++) {
+                final SearchIndexableData data = dataToUpdate.get(n);
+                try {
+                    indexOneSearchIndexableData(database, localeStr, data, nonIndexableKeys);
+                } catch (Exception e) {
+                    Log.e(LOG_TAG, "Cannot index: " + (data != null ? data.className : data)
+                            + " for locale: " + localeStr, e);
+                }
+            }
+
+            final long now = System.currentTimeMillis();
+            Log.d(LOG_TAG, "Indexing locale '" + localeStr + "' took " +
+                    (now - current) + " millis");
+            return result;
+        }
+
+        private boolean processDataToDelete(SQLiteDatabase database, String localeStr,
+                List<SearchIndexableData> dataToDelete) {
+
+            boolean result = false;
+            final long current = System.currentTimeMillis();
+
+            final int count = dataToDelete.size();
+            for (int n = 0; n < count; n++) {
+                final SearchIndexableData data = dataToDelete.get(n);
+                if (data == null) {
+                    continue;
+                }
+                if (!TextUtils.isEmpty(data.className)) {
+                    delete(database, IndexDatabaseHelper.IndexColumns.CLASS_NAME, data.className);
+                } else  {
+                    if (data instanceof SearchIndexableRaw) {
+                        final SearchIndexableRaw raw = (SearchIndexableRaw) data;
+                        if (!TextUtils.isEmpty(raw.title)) {
+                            delete(database, IndexDatabaseHelper.IndexColumns.DATA_TITLE,
+                                    raw.title);
+                        }
+                    }
+                }
+            }
+
+            final long now = System.currentTimeMillis();
+            Log.d(LOG_TAG, "Deleting data for locale '" + localeStr + "' took " +
+                    (now - current) + " millis");
+            return result;
+        }
+
+        private int delete(SQLiteDatabase database, String columName, String value) {
+            final String whereClause = columName + "=?";
+            final String[] whereArgs = new String[] { value };
+
+            return database.delete(IndexDatabaseHelper.Tables.TABLE_PREFS_INDEX, whereClause,
+                    whereArgs);
+        }
+    }
+}
diff --git a/src/com/android/settings/search2/DatabaseIndexingUtils.java b/src/com/android/settings/search2/DatabaseIndexingUtils.java
new file mode 100644
index 0000000..a8f64df
--- /dev/null
+++ b/src/com/android/settings/search2/DatabaseIndexingUtils.java
@@ -0,0 +1,118 @@
+/*
+ * 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.search2;
+
+import android.Manifest;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.settings.search.Indexable;
+
+import java.lang.reflect.Field;
+
+/**
+ * Utility class for {@like DatabaseIndexingManager} to handle the mapping between Payloads
+ * and Preference controllers, and managing indexable classes.
+ */
+public class DatabaseIndexingUtils {
+
+    private static final String LOG_TAG = "IndexingUtil";
+
+    private static final String FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER =
+            "SEARCH_INDEX_DATA_PROVIDER";
+
+    public static Class<?> getIndexableClass(String className) {
+        final Class<?> clazz;
+        try {
+            clazz = Class.forName(className);
+        } catch (ClassNotFoundException e) {
+            Log.d(LOG_TAG, "Cannot find class: " + className);
+            return null;
+        }
+        return isIndexableClass(clazz) ? clazz : null;
+    }
+
+    public static boolean isIndexableClass(final Class<?> clazz) {
+        return (clazz != null) && Indexable.class.isAssignableFrom(clazz);
+    }
+
+    public static Indexable.SearchIndexProvider getSearchIndexProvider(final Class<?> clazz) {
+        try {
+            final Field f = clazz.getField(FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER);
+            return (Indexable.SearchIndexProvider) f.get(null);
+        } catch (NoSuchFieldException e) {
+            Log.d(LOG_TAG, "Cannot find field '" + FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER + "'");
+        } catch (SecurityException se) {
+            Log.d(LOG_TAG,
+                    "Security exception for field '" + FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER + "'");
+        } catch (IllegalAccessException e) {
+            Log.d(LOG_TAG,
+                    "Illegal access to field '" + FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER + "'");
+        } catch (IllegalArgumentException e) {
+            Log.d(LOG_TAG,
+                    "Illegal argument when accessing field '" +
+                            FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER + "'");
+        }
+        return null;
+    }
+
+    /**
+     * Only allow a "well known" SearchIndexablesProvider. The provider should:
+     *
+     * - have read/write {@link Manifest.permission#READ_SEARCH_INDEXABLES}
+     * - be from a privileged package
+     */
+    public static boolean isWellKnownProvider(ResolveInfo info, Context context) {
+        final String authority = info.providerInfo.authority;
+        final String packageName = info.providerInfo.applicationInfo.packageName;
+
+        if (TextUtils.isEmpty(authority) || TextUtils.isEmpty(packageName)) {
+            return false;
+        }
+
+        final String readPermission = info.providerInfo.readPermission;
+        final String writePermission = info.providerInfo.writePermission;
+
+        if (TextUtils.isEmpty(readPermission) || TextUtils.isEmpty(writePermission)) {
+            return false;
+        }
+
+        if (!android.Manifest.permission.READ_SEARCH_INDEXABLES.equals(readPermission) ||
+                !android.Manifest.permission.READ_SEARCH_INDEXABLES.equals(writePermission)) {
+            return false;
+        }
+
+        return isPrivilegedPackage(packageName, context);
+    }
+
+    public static boolean isPrivilegedPackage(String packageName, Context context) {
+        final PackageManager pm = context.getPackageManager();
+        try {
+            PackageInfo packInfo = pm.getPackageInfo(packageName, 0);
+            return ((packInfo.applicationInfo.privateFlags
+                    & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0);
+        } catch (PackageManager.NameNotFoundException e) {
+            return false;
+        }
+    }
+}
diff --git a/src/com/android/settings/search2/DatabaseResultLoader.java b/src/com/android/settings/search2/DatabaseResultLoader.java
index aca94b1..b268f6a 100644
--- a/src/com/android/settings/search2/DatabaseResultLoader.java
+++ b/src/com/android/settings/search2/DatabaseResultLoader.java
@@ -16,31 +16,37 @@
 
 package com.android.settings.search2;
 
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteDatabase;
 import android.graphics.drawable.Drawable;
+import android.os.Bundle;
 import android.support.annotation.VisibleForTesting;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.settings.SettingsActivity;
+import com.android.settings.Utils;
 import com.android.settings.search.Index;
 import com.android.settings.search.IndexDatabaseHelper;
 import com.android.settings.utils.AsyncLoader;
-import com.android.settings.R;
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
-
-import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_ICON_RESID;
-import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_SUMMARY_ON;
-import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_RANK;
+import java.util.Map;
 
 
 /**
  * AsyncTask to retrieve Settings, First party app and any intent based results.
  */
 public class DatabaseResultLoader extends AsyncLoader<List<SearchResult>> {
+    private static final String LOG = "DatabaseResultLoader";
     private final String mQueryText;
     private final Context mContext;
     protected final SQLiteDatabase mDatabase;
@@ -64,7 +70,7 @@
         }
 
         String query = getSQLQuery();
-        Cursor result  = mDatabase.rawQuery(query, null);
+        Cursor result = mDatabase.rawQuery(query, null);
 
         return parseCursorForSearch(result);
     }
@@ -77,10 +83,12 @@
 
     protected String getSQLQuery() {
         return String.format("SELECT data_rank, data_title, data_summary_on, " +
-                "data_summary_off, data_entries, data_keywords, class_name, screen_title, icon, " +
-                "intent_action, intent_target_package, intent_target_class, enabled, " +
-                "data_key_reference FROM prefs_index WHERE prefs_index MATCH 'data_title:%s* " +
-                "OR data_title_normalized:%s* OR data_keywords:%s*' AND locale = 'en_US'",
+                        "data_summary_off, data_entries, data_keywords, class_name, screen_title,"
+                        + " icon, " +
+                        "intent_action, intent_target_package, intent_target_class, enabled, " +
+                        "data_key_reference FROM prefs_index WHERE prefs_index MATCH "
+                        + "'data_title:%s* " +
+                        "OR data_title_normalized:%s* OR data_keywords:%s*' AND locale = 'en_US'",
                 mQueryText, mQueryText, mQueryText);
     }
 
@@ -89,36 +97,89 @@
         if (cursorResults == null) {
             return null;
         }
+        final Map<String, Context> contextMap = new HashMap<>();
         final ArrayList<SearchResult> results = new ArrayList<>();
 
         while (cursorResults.moveToNext()) {
-            final String title = cursorResults.getString(Index.COLUMN_INDEX_TITLE);
-            final String summaryOn = cursorResults.getString(COLUMN_INDEX_RAW_SUMMARY_ON);
-            final ArrayList<String> breadcrumbs = new ArrayList<>();
-            final int rank = cursorResults.getInt(COLUMN_INDEX_XML_RES_RANK);
-
-            final String intentString = cursorResults.getString(Index.COLUMN_INDEX_INTENT_ACTION);
-            final IntentPayload intentPayload = new IntentPayload(new Intent(intentString));
-            final int iconID = cursorResults.getInt(COLUMN_INDEX_RAW_ICON_RESID);
-            Drawable icon;
-            try {
-                icon = mContext.getDrawable(iconID);
-            } catch (Resources.NotFoundException nfe) {
-                icon = mContext.getDrawable(R.drawable.ic_search_history);
+            SearchResult result = buildSingleSearchResultFromCursor(contextMap, cursorResults);
+            if (result != null) {
+                results.add(result);
             }
-
-
-            SearchResult.Builder builder = new SearchResult.Builder();
-            builder.addTitle(title)
-                    .addSummary(summaryOn)
-                    .addBreadcrumbs(breadcrumbs)
-                    .addRank(rank)
-                    .addIcon(icon)
-                    .addPayload(intentPayload);
-            results.add(builder.build());
         }
         Collections.sort(results);
         return results;
     }
 
+    private SearchResult buildSingleSearchResultFromCursor(Map<String, Context> contextMap,
+            Cursor cursor) {
+        final String pkgName = cursor.getString(Index.COLUMN_INDEX_INTENT_ACTION_TARGET_PACKAGE);
+        final String action = cursor.getString(Index.COLUMN_INDEX_INTENT_ACTION);
+        final String title = cursor.getString(Index.COLUMN_INDEX_TITLE);
+        final String summaryOn = cursor.getString(Index.COLUMN_INDEX_SUMMARY_ON);
+        final String className = cursor.getString(Index.COLUMN_INDEX_CLASS_NAME);
+        final int rank = cursor.getInt(Index.COLUMN_INDEX_RANK);
+        final String key = cursor.getString(Index.COLUMN_INDEX_KEY);
+        final String iconResStr = cursor.getString(Index.COLUMN_INDEX_ICON);
+
+        final ResultPayload payload;
+        if (TextUtils.isEmpty(action)) {
+            final String screenTitle = cursor.getString(Index.COLUMN_INDEX_SCREEN_TITLE);
+            // Action is null, we will launch it as a sub-setting
+            final Bundle args = new Bundle();
+            args.putString(SettingsActivity.EXTRA_FRAGMENT_ARG_KEY, key);
+            final Intent intent = Utils.onBuildStartFragmentIntent(mContext,
+                    className, args, null, 0, screenTitle, false);
+            payload = new IntentPayload(intent);
+        } else {
+            final Intent intent = new Intent(action);
+            final String targetClass = cursor.getString(
+                    Index.COLUMN_INDEX_INTENT_ACTION_TARGET_CLASS);
+            if (!TextUtils.isEmpty(pkgName) && !TextUtils.isEmpty(targetClass)) {
+                final ComponentName component = new ComponentName(pkgName, targetClass);
+                intent.setComponent(component);
+            }
+            intent.putExtra(SettingsActivity.EXTRA_FRAGMENT_ARG_KEY, key);
+            payload = new IntentPayload(intent);
+        }
+        SearchResult.Builder builder = new SearchResult.Builder();
+        builder.addTitle(title)
+                .addSummary(summaryOn)
+                .addRank(rank)
+                .addIcon(getIconForPackage(contextMap, pkgName, className, iconResStr))
+                .addPayload(payload);
+        return builder.build();
+    }
+
+    private Drawable getIconForPackage(Map<String, Context> contextMap, String pkgName,
+            String className, String iconResStr) {
+        final int iconId = TextUtils.isEmpty(iconResStr)
+                ? 0 : Integer.parseInt(iconResStr);
+        Drawable icon;
+        Context packageContext;
+        if (iconId == 0) {
+            icon = null;
+        } else {
+            if (TextUtils.isEmpty(className) && !TextUtils.isEmpty(pkgName)) {
+                packageContext = contextMap.get(pkgName);
+                if (packageContext == null) {
+                    try {
+                        packageContext = mContext.createPackageContext(pkgName, 0);
+                    } catch (PackageManager.NameNotFoundException e) {
+                        Log.e(LOG, "Cannot create Context for package: " + pkgName);
+                        return null;
+                    }
+                    contextMap.put(pkgName, packageContext);
+                }
+            } else {
+                packageContext = mContext;
+            }
+            try {
+                icon = packageContext.getDrawable(iconId);
+            } catch (Resources.NotFoundException nfe) {
+                icon = null;
+            }
+        }
+        return icon;
+    }
+
 }
diff --git a/src/com/android/settings/search2/InstalledAppResultLoader.java b/src/com/android/settings/search2/InstalledAppResultLoader.java
new file mode 100644
index 0000000..449e52c
--- /dev/null
+++ b/src/com/android/settings/search2/InstalledAppResultLoader.java
@@ -0,0 +1,139 @@
+/*
+ * 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.search2;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.UserInfo;
+import android.net.Uri;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.Settings;
+import android.text.TextUtils;
+
+import com.android.settings.applications.PackageManagerWrapper;
+import com.android.settings.utils.AsyncLoader;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Search loader for installed apps.
+ */
+public class InstalledAppResultLoader extends AsyncLoader<List<SearchResult>> {
+
+    private static final int NAME_NO_MATCH = -1;
+    private static final int NAME_EXACT_MATCH = 0;
+
+    private final String mQuery;
+    private final UserManager mUserManager;
+    private final PackageManagerWrapper mPackageManager;
+
+    public InstalledAppResultLoader(Context context, PackageManagerWrapper pmWrapper,
+            String query) {
+        super(context);
+        mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+        mPackageManager = pmWrapper;
+        mQuery = query;
+    }
+
+    @Override
+    public List<SearchResult> loadInBackground() {
+        final List<SearchResult> results = new ArrayList<>();
+        final PackageManager pm = mPackageManager.getPackageManager();
+
+        for (UserInfo user : getUsersToCount()) {
+            final List<ApplicationInfo> apps =
+                    mPackageManager.getInstalledApplicationsAsUser(
+                            PackageManager.MATCH_DISABLED_COMPONENTS
+                                    | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
+                                    | (user.isAdmin() ? PackageManager.MATCH_ANY_USER : 0),
+                            user.id);
+            for (ApplicationInfo info : apps) {
+                if (info.isSystemApp()) {
+                    continue;
+                }
+                final CharSequence label = info.loadLabel(pm);
+                final int wordDiff = getWordDifference(label.toString(), mQuery);
+                if (wordDiff == NAME_NO_MATCH) {
+                    continue;
+                }
+                final Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
+                        .setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
+                        .setData(Uri.fromParts("package", info.packageName, null));
+
+                final SearchResult.Builder builder = new SearchResult.Builder();
+                builder.addIcon(info.loadIcon(pm))
+                        .addTitle(info.loadLabel(pm))
+                        .addRank(wordDiff)
+                        .addPayload(new IntentPayload(intent));
+                results.add(builder.build());
+            }
+        }
+        Collections.sort(results);
+        return results;
+    }
+
+    @Override
+    protected void onDiscardResult(List<SearchResult> result) {
+
+    }
+
+    private List<UserInfo> getUsersToCount() {
+        return mUserManager.getProfiles(UserHandle.myUserId());
+    }
+
+    /**
+     * Returns "difference" between appName and query string. appName must contain all
+     * characters from query, in the same order. If not, returns NAME_NO_MATCH. If they do match,
+     * returns an int value representing how different they are, NAME_EXACT_MATCH means they match
+     * perfectly, and larger values means they are less similar.
+     * <p/>
+     * Example:
+     * appName: Abcde, query: Abcde, Returns NAME_EXACT_MATCH
+     * appName: Abcde, query: ade, Returns 2
+     * appName: Abcde, query: ae, Returns 3
+     * appName: Abcde, query: ea, Returns NAME_NO_MATCH
+     * appName: Abcde, query: xyz, Returns NAME_NO_MATCH
+     */
+    private int getWordDifference(String appName, String query) {
+        if (TextUtils.isEmpty(appName) || TextUtils.isEmpty(query)) {
+            return NAME_NO_MATCH;
+        }
+        final char[] queryTokens = query.toString().toLowerCase().toCharArray();
+        final char[] valueText = appName.toLowerCase().toCharArray();
+        if (queryTokens.length > valueText.length) {
+            return NAME_NO_MATCH;
+        }
+        int i = 0;
+        int j = 0;
+        while (i < valueText.length && j < queryTokens.length) {
+            if (valueText[i++] == queryTokens[j]) {
+                j++;
+            }
+        }
+        if (j != queryTokens.length) {
+            return NAME_NO_MATCH;
+        }
+        // Use the diff in length as a proxy of how close the 2 words match. Value range from 0
+        // to infinity.
+        return valueText.length - queryTokens.length;
+    }
+}
diff --git a/src/com/android/settings/search2/IntentSearchViewHolder.java b/src/com/android/settings/search2/IntentSearchViewHolder.java
index 0b99d6e..0ef27d0 100644
--- a/src/com/android/settings/search2/IntentSearchViewHolder.java
+++ b/src/com/android/settings/search2/IntentSearchViewHolder.java
@@ -15,9 +15,11 @@
  */
 package com.android.settings.search2;
 
+import android.app.Fragment;
 import android.view.View;
 import android.widget.ImageView;
 import android.widget.TextView;
+
 import com.android.settings.R;
 
 /**
@@ -25,6 +27,7 @@
  * The DatabaseResultLoader is the primary use case for this ViewHolder.
  */
 public class IntentSearchViewHolder extends SearchViewHolder {
+
     public final TextView titleView;
     public final TextView summaryView;
     public final ImageView iconView;
@@ -33,12 +36,22 @@
         super(view);
         titleView = (TextView) view.findViewById(R.id.title);
         summaryView = (TextView) view.findViewById(R.id.summary);
-        iconView= (ImageView) view.findViewById(R.id.icon);
+        iconView = (ImageView) view.findViewById(R.id.icon);
     }
 
-    public void onBind(SearchResult result) {
+    @Override
+    public void onBind(Fragment fragment, SearchResult result) {
         titleView.setText(result.title);
         summaryView.setText(result.summary);
         iconView.setImageDrawable(result.icon);
+        if (result.icon == null) {
+            iconView.setBackgroundResource(R.drawable.empty_icon);
+        }
+        itemView.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                fragment.startActivity(((IntentPayload) result.payload).intent);
+            }
+        });
     }
 }
diff --git a/src/com/android/settings/search2/ResultPayload.java b/src/com/android/settings/search2/ResultPayload.java
index 3a4e477..84df7b6 100644
--- a/src/com/android/settings/search2/ResultPayload.java
+++ b/src/com/android/settings/search2/ResultPayload.java
@@ -31,8 +31,19 @@
     @IntDef({PayloadType.INLINE_SLIDER, PayloadType.INLINE_SWITCH, PayloadType.INTENT})
     @Retention(RetentionPolicy.SOURCE)
     public @interface PayloadType {
+        /**
+         * Resulting page will be started using an intent
+         */
         int INTENT = 0;
+
+        /**
+         * Result is a inline widget, using a slider widget as UI.
+         */
         int INLINE_SLIDER = 1;
+
+        /**
+         * Result is a inline widget, using a toggle widget as UI.
+         */
         int INLINE_SWITCH = 2;
     }
 
diff --git a/src/com/android/settings/search2/SearchFeatureProvider.java b/src/com/android/settings/search2/SearchFeatureProvider.java
index 569a627..ad26eae 100644
--- a/src/com/android/settings/search2/SearchFeatureProvider.java
+++ b/src/com/android/settings/search2/SearchFeatureProvider.java
@@ -41,4 +41,19 @@
      * Returns a new loader to search in index database.
      */
     DatabaseResultLoader getDatabaseSearchLoader(Context context, String query);
+
+    /**
+     * Returns a new loader to search installed apps.
+     */
+    InstalledAppResultLoader getInstalledAppSearchLoader(Context context, String query);
+
+    /**
+     * Returns the manager for indexing Settings data.
+     */
+    DatabaseIndexingManager getIndexingManager(Context context);
+
+    /**
+     * Updates the Settings indexes
+     */
+    void updateIndex(Context context);
 }
diff --git a/src/com/android/settings/search2/SearchFeatureProviderImpl.java b/src/com/android/settings/search2/SearchFeatureProviderImpl.java
index 81a41dc..e2d25ad 100644
--- a/src/com/android/settings/search2/SearchFeatureProviderImpl.java
+++ b/src/com/android/settings/search2/SearchFeatureProviderImpl.java
@@ -19,14 +19,13 @@
 import android.app.Activity;
 import android.content.Context;
 import android.content.Intent;
-import android.widget.SearchView;
 import android.view.Menu;
-
 import android.view.MenuItem;
-import com.android.settings.R;
-import com.android.settings.utils.AsyncLoader;
 
-import java.util.List;
+import com.android.settings.R;
+import com.android.settings.search.Index;
+
+import com.android.settings.applications.PackageManagerWrapperImpl;
 
 /**
  * FeatureProvider for the refactored search code.
@@ -34,6 +33,7 @@
 public class SearchFeatureProviderImpl implements SearchFeatureProvider {
     protected Context mContext;
 
+    private DatabaseIndexingManager mDatabaseIndexingManager;
 
     public SearchFeatureProviderImpl(Context context) {
         mContext = context;
@@ -51,15 +51,15 @@
         }
         String menuTitle = mContext.getString(R.string.search_menu);
         MenuItem menuItem = menu.add(Menu.NONE, Menu.NONE, Menu.NONE, menuTitle)
-            .setIcon(R.drawable.abc_ic_search_api_material)
-            .setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
-                @Override
-                public boolean onMenuItemClick(MenuItem item) {
-                    Intent intent = new Intent(activity, SearchActivity.class);
-                    activity.startActivity(intent);
-                    return true;
-                }
-            });
+                .setIcon(R.drawable.abc_ic_search_api_material)
+                .setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+                    @Override
+                    public boolean onMenuItemClick(MenuItem item) {
+                        Intent intent = new Intent(activity, SearchActivity.class);
+                        activity.startActivity(intent);
+                        return true;
+                    }
+                });
 
         menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
     }
@@ -68,4 +68,28 @@
     public DatabaseResultLoader getDatabaseSearchLoader(Context context, String query) {
         return new DatabaseResultLoader(context, query);
     }
+
+    @Override
+    public InstalledAppResultLoader getInstalledAppSearchLoader(Context context, String query) {
+        return new InstalledAppResultLoader(
+                context, new PackageManagerWrapperImpl(context.getPackageManager()), query);
+    }
+
+    @Override
+    public DatabaseIndexingManager getIndexingManager(Context context) {
+        if (mDatabaseIndexingManager == null) {
+            mDatabaseIndexingManager = new DatabaseIndexingManager(context.getApplicationContext(),
+                    context.getPackageName());
+        }
+        return mDatabaseIndexingManager;
+    }
+
+    @Override
+    public void updateIndex(Context context) {
+        if (isEnabled()) {
+            getIndexingManager(context).update();
+        } else {
+            Index.getInstance(context).update();
+        }
+    }
 }
diff --git a/src/com/android/settings/search2/SearchFragment.java b/src/com/android/settings/search2/SearchFragment.java
index 1fb123c..fca52e9 100644
--- a/src/com/android/settings/search2/SearchFragment.java
+++ b/src/com/android/settings/search2/SearchFragment.java
@@ -46,13 +46,13 @@
     static final String STATE_QUERY = "query";
 
     // Loader IDs
-    private static final int DATABASE_LOADER_ID = 0;
+    private static final int LOADER_ID_DATABASE = 0;
+    private static final int LOADER_ID_INSTALLED_APPS = 1;
 
     @VisibleForTesting
     String mQuery;
 
     private SearchFeatureProvider mSearchFeatureProvider;
-    private DatabaseResultLoader mSearchLoader;
 
     private SearchResultsAdapter mSearchAdapter;
     private RecyclerView mResultsRecyclerView;
@@ -73,10 +73,12 @@
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setHasOptionsMenu(true);
-        mSearchAdapter = new SearchResultsAdapter();
+        mSearchAdapter = new SearchResultsAdapter(this);
         if (savedInstanceState != null) {
             mQuery = savedInstanceState.getString(STATE_QUERY);
-            getLoaderManager().initLoader(DATABASE_LOADER_ID, null, this);
+            final LoaderManager loaderManager = getLoaderManager();
+            loaderManager.initLoader(LOADER_ID_DATABASE, null, this);
+            loaderManager.initLoader(LOADER_ID_INSTALLED_APPS, null, this);
         }
         final ActionBar actionBar = getActivity().getActionBar();
         actionBar.setCustomView(makeSearchView(actionBar, mQuery));
@@ -109,7 +111,7 @@
         mSearchAdapter.clearResults();
 
         if (TextUtils.isEmpty(mQuery)) {
-            getLoaderManager().destroyLoader(DATABASE_LOADER_ID);
+            getLoaderManager().destroyLoader(LOADER_ID_DATABASE);
         } else {
             restartLoaders();
         }
@@ -127,9 +129,10 @@
         final Activity activity = getActivity();
 
         switch (id) {
-            case DATABASE_LOADER_ID:
-                mSearchLoader = mSearchFeatureProvider.getDatabaseSearchLoader(activity, mQuery);
-                return mSearchLoader;
+            case LOADER_ID_DATABASE:
+                return mSearchFeatureProvider.getDatabaseSearchLoader(activity, mQuery);
+            case LOADER_ID_INSTALLED_APPS:
+                return mSearchFeatureProvider.getInstalledAppSearchLoader(activity, mQuery);
             default:
                 return null;
         }
@@ -137,10 +140,6 @@
 
     @Override
     public void onLoadFinished(Loader<List<SearchResult>> loader, List<SearchResult> data) {
-        if (data == null) {
-            return;
-        }
-
         mSearchAdapter.mergeResults(data, loader.getClass().getName());
     }
 
@@ -150,7 +149,8 @@
 
     private void restartLoaders() {
         final LoaderManager loaderManager = getLoaderManager();
-        loaderManager.restartLoader(DATABASE_LOADER_ID, null /* args */, this /* callback */);
+        loaderManager.restartLoader(LOADER_ID_DATABASE, null /* args */, this /* callback */);
+        loaderManager.restartLoader(LOADER_ID_INSTALLED_APPS, null /* args */, this /* callback */);
     }
 
     private SearchView makeSearchView(ActionBar actionBar, String query) {
diff --git a/src/com/android/settings/search2/SearchResult.java b/src/com/android/settings/search2/SearchResult.java
index e483df3..5bf757f 100644
--- a/src/com/android/settings/search2/SearchResult.java
+++ b/src/com/android/settings/search2/SearchResult.java
@@ -19,90 +19,24 @@
 import android.graphics.drawable.Drawable;
 
 import java.util.ArrayList;
+import java.util.Objects;
 
 /**
- * Dataclass as an interface for all Search Results.
+ * Data class as an interface for all Search Results.
  */
 public class SearchResult implements Comparable<SearchResult> {
-    @Override
-    public int compareTo(SearchResult searchResult) {
-        if (searchResult == null) {
-            return -1;
-        }
-        return this.rank - searchResult.rank;
-    }
-
-    public static class Builder {
-        protected String mTitle;
-        protected String mSummary;
-        protected ArrayList<String> mBreadcrumbs;
-        protected int mRank = -1;
-        protected ResultPayload mResultPayload;
-        protected Drawable mIcon;
-
-        public Builder addTitle(String title) {
-            mTitle = title;
-            return this;
-        }
-
-        public Builder addSummary(String summary) {
-            mSummary = summary;
-            return this;
-        }
-
-        public Builder addBreadcrumbs(ArrayList<String> breadcrumbs) {
-            mBreadcrumbs = breadcrumbs;
-            return this;
-        }
-
-        public Builder addRank(int rank) {
-            if (rank < 0 || rank > 9) {
-                rank = 42;
-            }
-            mRank = rank;
-            return this;
-        }
-
-        public Builder addIcon(Drawable icon) {
-            mIcon = icon;
-            return this;
-        }
-
-        public Builder addPayload(ResultPayload payload) {
-            mResultPayload = payload;
-            return this;
-        }
-
-        public SearchResult build() {
-            // Check that all of the mandatory fields are set.
-            if (mTitle == null) {
-                throw new IllegalArgumentException("SearchResult missing title argument");
-            } else if (mSummary == null ) {
-                throw new IllegalArgumentException("SearchResult missing summary argument");
-            } else if (mBreadcrumbs == null){
-                throw new IllegalArgumentException("SearchResult missing breadcrumbs argument");
-            } else if (mRank == -1) {
-                throw new IllegalArgumentException("SearchResult missing rank argument");
-            } else if (mIcon == null) {
-                throw new IllegalArgumentException("SearchResult missing icon argument");
-            } else if (mResultPayload == null) {
-                throw new IllegalArgumentException("SearchResult missing Payload argument");
-            }
-            return new SearchResult(this);
-        }
-    }
 
     /**
      * The title of the result and main text displayed.
      * Intent Results: Displays as the primary
      */
-    public final String title;
+    public final CharSequence title;
 
     /**
      * Summary / subtitle text
      * Intent Results: Displays the text underneath the title
      */
-    final public String summary;
+    final public CharSequence summary;
 
     /**
      * An ordered list of the information hierarchy.
@@ -122,7 +56,8 @@
     /**
      * Identifier for the recycler view adapter.
      */
-    @ResultPayload.PayloadType public final int viewType;
+    @ResultPayload.PayloadType
+    public final int viewType;
 
     /**
      * Metadata for the specific result types.
@@ -134,6 +69,11 @@
      */
     public final Drawable icon;
 
+    /**
+     * Stable id for this object.
+     */
+    public final long stableId;
+
     private SearchResult(Builder builder) {
         title = builder.mTitle;
         summary = builder.mSummary;
@@ -142,5 +82,65 @@
         icon = builder.mIcon;
         payload = builder.mResultPayload;
         viewType = payload.getType();
+        stableId = Objects.hash(title, summary, breadcrumbs, rank, icon, payload, viewType);
+    }
+
+    @Override
+    public int compareTo(SearchResult searchResult) {
+        if (searchResult == null) {
+            return -1;
+        }
+        return this.rank - searchResult.rank;
+    }
+
+    public static class Builder {
+        protected CharSequence mTitle;
+        protected CharSequence mSummary;
+        protected ArrayList<String> mBreadcrumbs;
+        protected int mRank = 42;
+        protected ResultPayload mResultPayload;
+        protected Drawable mIcon;
+
+        public Builder addTitle(CharSequence title) {
+            mTitle = title;
+            return this;
+        }
+
+        public Builder addSummary(CharSequence summary) {
+            mSummary = summary;
+            return this;
+        }
+
+        public Builder addBreadcrumbs(ArrayList<String> breadcrumbs) {
+            mBreadcrumbs = breadcrumbs;
+            return this;
+        }
+
+        public Builder addRank(int rank) {
+            if (rank >= 0 && rank <= 9) {
+                mRank = rank;
+            }
+            return this;
+        }
+
+        public Builder addIcon(Drawable icon) {
+            mIcon = icon;
+            return this;
+        }
+
+        public Builder addPayload(ResultPayload payload) {
+            mResultPayload = payload;
+            return this;
+        }
+
+        public SearchResult build() {
+            // Check that all of the mandatory fields are set.
+            if (mTitle == null) {
+                throw new IllegalArgumentException("SearchResult missing title argument");
+            } else if (mResultPayload == null) {
+                throw new IllegalArgumentException("SearchResult missing Payload argument");
+            }
+            return new SearchResult(this);
+        }
     }
 }
diff --git a/src/com/android/settings/search2/SearchResultsAdapter.java b/src/com/android/settings/search2/SearchResultsAdapter.java
index 62b79b3..b588496 100644
--- a/src/com/android/settings/search2/SearchResultsAdapter.java
+++ b/src/com/android/settings/search2/SearchResultsAdapter.java
@@ -33,40 +33,19 @@
 public class SearchResultsAdapter extends Adapter<SearchViewHolder> {
     private final List<SearchResult> mSearchResults;
     private final Map<String, List<SearchResult>> mResultsMap;
+    private final SearchFragment mFragment;
 
-    public SearchResultsAdapter() {
+    public SearchResultsAdapter(SearchFragment fragment) {
+        mFragment = fragment;
         mSearchResults = new ArrayList<>();
         mResultsMap = new HashMap<>();
 
         setHasStableIds(true);
     }
 
-    public void mergeResults(List<SearchResult> freshResults, String loaderClassName) {
-        if (freshResults == null) {
-            return;
-        }
-        mResultsMap.put(loaderClassName, freshResults);
-        mSearchResults.addAll(mergeMappedResults());
-        notifyDataSetChanged();
-    }
-
-    public void clearResults() {
-        mSearchResults.clear();
-        mResultsMap.clear();
-        notifyDataSetChanged();
-    }
-
-    private ArrayList<SearchResult> mergeMappedResults() {
-        ArrayList<SearchResult> mergedResults = new ArrayList<>();
-        for (String key : mResultsMap.keySet()) {
-            mergedResults.addAll(mResultsMap.get(key));
-        }
-        return mergedResults;
-    }
-
     @Override
     public SearchViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
-        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
+        final LayoutInflater inflater = LayoutInflater.from(parent.getContext());
         switch (viewType) {
             case PayloadType.INTENT:
                 View view = inflater.inflate(R.layout.search_intent_item, parent, false);
@@ -82,13 +61,12 @@
 
     @Override
     public void onBindViewHolder(SearchViewHolder holder, int position) {
-        SearchResult result = mSearchResults.get(position);
-        holder.onBind(result);
+        holder.onBind(mFragment, mSearchResults.get(position));
     }
 
     @Override
     public long getItemId(int position) {
-        return super.getItemId(position);
+        return mSearchResults.get(position).stableId;
     }
 
     @Override
@@ -101,6 +79,23 @@
         return mSearchResults.size();
     }
 
+    public void mergeResults(List<SearchResult> freshResults, String loaderClassName) {
+        if (freshResults == null) {
+            return;
+        }
+        mResultsMap.put(loaderClassName, freshResults);
+        final int oldSize = mSearchResults.size();
+        mSearchResults.addAll(freshResults);
+        final int newSize = mSearchResults.size();
+        notifyItemRangeInserted(oldSize, newSize - oldSize);
+    }
+
+    public void clearResults() {
+        mSearchResults.clear();
+        mResultsMap.clear();
+        notifyDataSetChanged();
+    }
+
     @VisibleForTesting
     public List<SearchResult> getSearchResults() {
         return mSearchResults;
diff --git a/src/com/android/settings/search2/SearchViewHolder.java b/src/com/android/settings/search2/SearchViewHolder.java
index 2f500fb..45ceb38 100644
--- a/src/com/android/settings/search2/SearchViewHolder.java
+++ b/src/com/android/settings/search2/SearchViewHolder.java
@@ -15,6 +15,7 @@
  */
 package com.android.settings.search2;
 
+import android.app.Fragment;
 import android.support.v7.widget.RecyclerView;
 import android.view.View;
 
@@ -29,5 +30,5 @@
         super(view);
     }
 
-    public abstract void onBind(SearchResult result);
+    public abstract void onBind(Fragment fragment, SearchResult result);
 }
\ No newline at end of file
diff --git a/src/com/android/settings/search2/XMLParserUtil.java b/src/com/android/settings/search2/XMLParserUtil.java
new file mode 100644
index 0000000..dcb3cbb
--- /dev/null
+++ b/src/com/android/settings/search2/XMLParserUtil.java
@@ -0,0 +1,137 @@
+/*
+ * 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.search2;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.util.TypedValue;
+
+import com.android.settings.R;
+
+import java.text.Normalizer;
+import java.util.regex.Pattern;
+
+/**
+ * Utility class to parse elements of XML preferences
+ */
+public class XMLParserUtil {
+
+    private static final String NON_BREAKING_HYPHEN = "\u2011";
+    private static final String EMPTY = "";
+    private static final String LIST_DELIMITERS = "[,]\\s*";
+    private static final String HYPHEN = "-";
+    private static final String SPACE = " ";
+
+    private static final String ENTRIES_SEPARATOR = "|";
+
+    private static final Pattern REMOVE_DIACRITICALS_PATTERN
+            = Pattern.compile("\\p{InCombiningDiacriticalMarks}+");
+
+    public static String getDataKey(Context context, AttributeSet attrs) {
+        return getData(context, attrs,
+                com.android.internal.R.styleable.Preference,
+                com.android.internal.R.styleable.Preference_key);
+    }
+
+    public static String getDataTitle(Context context, AttributeSet attrs) {
+        return getData(context, attrs,
+                com.android.internal.R.styleable.Preference,
+                com.android.internal.R.styleable.Preference_title);
+    }
+
+    public static String getDataSummary(Context context, AttributeSet attrs) {
+        return getData(context, attrs,
+                com.android.internal.R.styleable.Preference,
+                com.android.internal.R.styleable.Preference_summary);
+    }
+
+    public static String getDataSummaryOn(Context context, AttributeSet attrs) {
+        return getData(context, attrs,
+                com.android.internal.R.styleable.CheckBoxPreference,
+                com.android.internal.R.styleable.CheckBoxPreference_summaryOn);
+    }
+
+    public static String getDataSummaryOff(Context context, AttributeSet attrs) {
+        return getData(context, attrs,
+                com.android.internal.R.styleable.CheckBoxPreference,
+                com.android.internal.R.styleable.CheckBoxPreference_summaryOff);
+    }
+
+    public static String getDataEntries(Context context, AttributeSet attrs) {
+        return getDataEntries(context, attrs,
+                com.android.internal.R.styleable.ListPreference,
+                com.android.internal.R.styleable.ListPreference_entries);
+    }
+
+    public static String getDataKeywords(Context context, AttributeSet attrs) {
+        return getData(context, attrs, R.styleable.Preference, R.styleable.Preference_keywords);
+    }
+
+    public static String getData(Context context, AttributeSet set, int[] attrs, int resId) {
+        final TypedArray sa = context.obtainStyledAttributes(set, attrs);
+        final TypedValue tv = sa.peekValue(resId);
+
+        CharSequence data = null;
+        if (tv != null && tv.type == TypedValue.TYPE_STRING) {
+            if (tv.resourceId != 0) {
+                data = context.getText(tv.resourceId);
+            } else {
+                data = tv.string;
+            }
+        }
+        return (data != null) ? data.toString() : null;
+    }
+
+    public static String getDataEntries(Context context, AttributeSet set, int[] attrs, int resId) {
+        final TypedArray sa = context.obtainStyledAttributes(set, attrs);
+        final TypedValue tv = sa.peekValue(resId);
+
+        String[] data = null;
+        if (tv != null && tv.type == TypedValue.TYPE_REFERENCE) {
+            if (tv.resourceId != 0) {
+                data = context.getResources().getStringArray(tv.resourceId);
+            }
+        }
+        final int count = (data == null ) ? 0 : data.length;
+        if (count == 0) {
+            return null;
+        }
+        final StringBuilder result = new StringBuilder();
+        for (int n = 0; n < count; n++) {
+            result.append(data[n]);
+            result.append(ENTRIES_SEPARATOR);
+        }
+        return result.toString();
+    }
+
+    public static String normalizeHyphen(String input) {
+        return (input != null) ? input.replaceAll(NON_BREAKING_HYPHEN, HYPHEN) : EMPTY;
+    }
+
+    public static String normalizeString(String input) {
+        final String nohyphen = (input != null) ? input.replaceAll(HYPHEN, EMPTY) : EMPTY;
+        final String normalized = Normalizer.normalize(nohyphen, Normalizer.Form.NFD);
+
+        return REMOVE_DIACRITICALS_PATTERN.matcher(normalized).replaceAll("").toLowerCase();
+    }
+
+    public static String normalizeKeywords(String input) {
+        return (input != null) ? input.replaceAll(LIST_DELIMITERS, SPACE) : EMPTY;
+    }
+}
diff --git a/src/com/android/settings/widget/SwitchBar.java b/src/com/android/settings/widget/SwitchBar.java
index e998e79..7bf6a83 100644
--- a/src/com/android/settings/widget/SwitchBar.java
+++ b/src/com/android/settings/widget/SwitchBar.java
@@ -117,7 +117,6 @@
         lp = (MarginLayoutParams) mSwitch.getLayoutParams();
         lp.setMarginEnd(switchBarMarginEnd);
         setBackgroundColor(switchBarBackgroundColor);
-        mSwitch.setBackgroundColor(switchBarBackgroundColor);
 
         addOnSwitchChangeListener(new OnSwitchChangeListener() {
             @Override
diff --git a/tests/app/src/com/android/settings/CreateShortcutTest.java b/tests/app/src/com/android/settings/CreateShortcutTest.java
new file mode 100644
index 0000000..9481a64
--- /dev/null
+++ b/tests/app/src/com/android/settings/CreateShortcutTest.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings;
+
+import android.app.Instrumentation;
+import android.content.Intent;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class CreateShortcutTest {
+
+    @Test
+    public void test_layoutDoesNotHaveCancelButton() {
+        Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+        instrumentation.startActivitySync(new Intent(Intent.ACTION_CREATE_SHORTCUT)
+                .setClassName(instrumentation.getTargetContext(),
+                        CreateShortcut.class.getName()));
+        onView(withText(R.string.cancel)).check(doesNotExist());
+    }
+}
diff --git a/tests/robotests/assets/grandfather_not_implementing_indexable b/tests/robotests/assets/grandfather_not_implementing_indexable
index c1b8cf5..0c539d8 100644
--- a/tests/robotests/assets/grandfather_not_implementing_indexable
+++ b/tests/robotests/assets/grandfather_not_implementing_indexable
@@ -87,4 +87,5 @@
 com.android.settings.notification.NotificationAccessSettings
 com.android.settings.notification.ZenModeSettings
 com.android.settings.accessibility.ToggleDaltonizerPreferenceFragment
-com.android.settings.applications.ConvertToFbe
\ No newline at end of file
+com.android.settings.applications.ConvertToFbe
+com.android.settings.localepicker.LocaleListEditor
\ No newline at end of file
diff --git a/tests/robotests/src/android/print/PrintServicesLoader.java b/tests/robotests/src/android/print/PrintServicesLoader.java
new file mode 100644
index 0000000..e4975ed
--- /dev/null
+++ b/tests/robotests/src/android/print/PrintServicesLoader.java
@@ -0,0 +1,19 @@
+package android.print;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.content.Loader;
+import android.printservice.PrintServiceInfo;
+import com.android.internal.util.Preconditions;
+
+import java.util.List;
+
+/**
+ * A placeholder class to prevent ClassNotFound exceptions caused by lack of visibility.
+ */
+public class PrintServicesLoader extends Loader<List<PrintServiceInfo>> {
+    public PrintServicesLoader(@NonNull PrintManager printManager, @NonNull Context context,
+            int selectionFlags) {
+        super(Preconditions.checkNotNull(context));
+    }
+}
diff --git a/tests/robotests/src/com/android/internal/app/LocalePickerWithRegion.java b/tests/robotests/src/com/android/internal/app/LocalePickerWithRegion.java
new file mode 100644
index 0000000..9edda45
--- /dev/null
+++ b/tests/robotests/src/com/android/internal/app/LocalePickerWithRegion.java
@@ -0,0 +1,11 @@
+package com.android.internal.app;
+
+/**
+ * A placeholder class to prevent ClassNotFound exceptions caused by lack of visibility.
+ */
+public class LocalePickerWithRegion {
+
+    public interface LocaleSelectedListener {
+        void onLocaleSelected(LocaleStore.LocaleInfo locale);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/SettingsRobolectricTestRunner.java b/tests/robotests/src/com/android/settings/SettingsRobolectricTestRunner.java
index 9127d5f..4472025 100644
--- a/tests/robotests/src/com/android/settings/SettingsRobolectricTestRunner.java
+++ b/tests/robotests/src/com/android/settings/SettingsRobolectricTestRunner.java
@@ -15,15 +15,23 @@
  */
 package com.android.settings;
 
+import android.app.Activity;
+import android.app.Fragment;
+import android.content.Intent;
 import org.junit.runners.model.InitializationError;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.annotation.Config;
 import org.robolectric.manifest.AndroidManifest;
 import org.robolectric.res.Fs;
 import org.robolectric.res.ResourcePath;
+import org.robolectric.util.ActivityController;
+import org.robolectric.util.ReflectionHelpers;
 
 import java.util.List;
 
+import static com.android.settings.SettingsActivity.EXTRA_SHOW_FRAGMENT;
+import static org.robolectric.Robolectric.getShadowsAdapter;
+
 /**
  * Custom test runner for the testing of BluetoothPairingDialogs. This is needed because the
  * default behavior for robolectric is just to grab the resource directory in the target package.
@@ -77,4 +85,15 @@
         manifest.setPackageName("com.android.settings");
         return manifest;
     }
-}
\ No newline at end of file
+
+    // A simple utility class to start a Settings fragment with an intent. The code here is almost
+    // the same as FragmentTestUtil.startFragment except that it starts an activity with an intent.
+    public static void startSettingsFragment(
+            Fragment fragment, Class<? extends SettingsActivity> activityClass) {
+        Intent intent = new Intent().putExtra(EXTRA_SHOW_FRAGMENT, fragment.getClass().getName());
+        SettingsActivity activity = ActivityController.of(
+                getShadowsAdapter(), ReflectionHelpers.callConstructor(activityClass), intent)
+                .setup().get();
+        activity.getFragmentManager().beginTransaction().add(fragment, null).commit();
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/accounts/AccountPreferenceTest.java b/tests/robotests/src/com/android/settings/accounts/AccountPreferenceTest.java
new file mode 100644
index 0000000..eeca90b
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/accounts/AccountPreferenceTest.java
@@ -0,0 +1,73 @@
+/*
+ * 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.accounts;
+
+import android.accounts.Account;
+import android.content.Context;
+
+import com.android.settings.R;
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowApplication;
+
+import java.util.ArrayList;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class AccountPreferenceTest {
+
+    private Context mContext;
+    private Account mAccount;
+    private ArrayList<String> mAuthorities;
+    private AccountPreference mPreference;
+
+    @Before
+    public void setUp() {
+        mContext = ShadowApplication.getInstance().getApplicationContext();
+        mAccount = new Account("name", "type");
+        mAuthorities = new ArrayList<>();
+        mAuthorities.add("authority");
+
+        mPreference = spy(new AccountPreference(
+                mContext, mAccount, null /* icon */, mAuthorities, false /* showTypeIcon */));
+    }
+
+    @Test
+    public void setSyncStatus_differentStatus_shouldUpdate() {
+        mPreference.setSyncStatus(AccountPreference.SYNC_ERROR, true);
+        verify(mPreference).setSummary(R.string.sync_error);
+    }
+
+    @Test
+    public void setSyncStatus_sameStatus_shouldNotUpdate() {
+        // Set it once, should update summary
+        mPreference.setSyncStatus(AccountPreference.SYNC_ERROR, true);
+        verify(mPreference).setSummary(R.string.sync_error);
+
+        // Set it again, should not update summary
+        mPreference.setSyncStatus(AccountPreference.SYNC_ERROR, true);
+        verify(mPreference).setSummary(R.string.sync_error);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/accounts/ManageAccountsSettingsTest.java b/tests/robotests/src/com/android/settings/accounts/ManageAccountsSettingsTest.java
new file mode 100644
index 0000000..916e395
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/accounts/ManageAccountsSettingsTest.java
@@ -0,0 +1,135 @@
+/*
+ * 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.accounts;
+
+import android.accounts.Account;
+import android.content.SyncInfo;
+import android.content.SyncStatusInfo;
+import android.os.UserHandle;
+import android.support.v7.preference.PreferenceScreen;
+import android.util.ArraySet;
+
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+
+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.annotation.Config;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class ManageAccountsSettingsTest {
+
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private AccountPreference mAccountPref;
+    private Account mAccount;
+    private ArrayList<String> mAuthorities;
+    private TestFragment mSettings;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mAuthorities = new ArrayList<>();
+        mAuthorities.add("authority");
+        mAccount = new Account("name", "type");
+        when(mAccountPref.getAccount()).thenReturn(mAccount);
+        when(mAccountPref.getAuthorities()).thenReturn(mAuthorities);
+        mSettings = new TestFragment();
+    }
+
+    @Test
+    public void showSyncState_noAccountPrefs_shouldUpdateNothing() {
+        when(mAccountPref.getAuthorities()).thenReturn(null);
+        mSettings.showSyncState();
+        verify(mSettings.getPreferenceScreen(), never()).getPreference(anyInt());
+    }
+
+    @Test
+    public void showSyncState_syncInProgress_shouldUpdateInProgress() {
+        mSettings.mUserFacingSyncAuthorities.add(mAuthorities.get(0));
+        mSettings.mSyncInfos.add(new SyncInfo(0, mAccount, mAuthorities.get(0), 0));
+        mSettings.mSyncStatusInfo = new SyncStatusInfo(0);
+        when(mSettings.getPreferenceScreen().getPreferenceCount()).thenReturn(1);
+        when(mSettings.getPreferenceScreen().getPreference(0)).thenReturn(mAccountPref);
+
+        mSettings.showSyncState();
+
+        verify(mSettings.getPreferenceScreen()).getPreference(anyInt());
+        verify(mAccountPref).setSyncStatus(AccountPreference.SYNC_IN_PROGRESS, true);
+    }
+
+    @Test
+    public void showSyncState_noUserFacingSynclets_shouldUpdateToDisabled() {
+        mSettings.mSyncInfos.add(new SyncInfo(0, mAccount, mAuthorities.get(0), 0));
+        mSettings.mSyncStatusInfo = new SyncStatusInfo(0);
+        when(mSettings.getPreferenceScreen().getPreferenceCount()).thenReturn(1);
+        when(mSettings.getPreferenceScreen().getPreference(0)).thenReturn(mAccountPref);
+
+        mSettings.showSyncState();
+
+        verify(mSettings.getPreferenceScreen()).getPreference(anyInt());
+        verify(mAccountPref).setSyncStatus(AccountPreference.SYNC_DISABLED, true);
+    }
+
+    public static class TestFragment extends ManageAccountsSettings {
+
+        private PreferenceScreen mScreen;
+        private List<SyncInfo> mSyncInfos;
+        private SyncStatusInfo mSyncStatusInfo;
+
+        public TestFragment() {
+            mUserHandle = mock(UserHandle.class);
+            mScreen = mock(PreferenceScreen.class);
+            mUserFacingSyncAuthorities = new ArraySet<>();
+            mSyncInfos = new ArrayList<>();
+        }
+
+        @Override
+        public PreferenceScreen getPreferenceScreen() {
+            return mScreen;
+        }
+
+        @Override
+        protected boolean isSyncEnabled(int userId, Account account, String authority) {
+            return true;
+        }
+
+        @Override
+        protected List<SyncInfo> getCurrentSyncs(int userId) {
+            return mSyncInfos;
+        }
+
+        @Override
+        protected SyncStatusInfo getSyncStatusInfo(Account account, String authority, int userId) {
+            return mSyncStatusInfo;
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/applications/ManageApplicationsTest.java b/tests/robotests/src/com/android/settings/applications/ManageApplicationsTest.java
new file mode 100644
index 0000000..e49b8b8
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/applications/ManageApplicationsTest.java
@@ -0,0 +1,61 @@
+package com.android.settings.applications;
+
+import android.os.Looper;
+import android.os.UserManager;
+import com.android.settings.Settings;
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
+import com.android.settings.testutils.shadow.SettingsShadowResources;
+import com.android.settings.testutils.shadow.SettingsShadowResources.SettingsShadowTheme;
+import com.android.settingslib.applications.ApplicationsState;
+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;
+import org.robolectric.util.ReflectionHelpers;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.when;
+
+/**
+ * Tests for {@link ManageApplications}.
+ */
+@RunWith(SettingsRobolectricTestRunner.class)
+// TODO: Consider making the shadow class set global using a robolectric.properties file.
+@Config(manifest = TestConfig.MANIFEST_PATH,
+        sdk = TestConfig.SDK_VERSION,
+        shadows = {
+                SettingsShadowResources.class,
+                SettingsShadowTheme.class,
+                ShadowDynamicIndexableContentMonitor.class
+        })
+public class ManageApplicationsTest {
+
+    @Mock private ApplicationsState mState;
+    @Mock private ApplicationsState.Session mSession;
+    @Mock private UserManager mUserManager;
+
+    private Looper mBgLooper;
+
+    private ManageApplications mFragment;
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        ReflectionHelpers.setStaticField(ApplicationsState.class, "sInstance", mState);
+        when(mState.newSession(any())).thenReturn(mSession);
+        mBgLooper = Looper.myLooper();
+        when(mState.getBackgroundLooper()).thenReturn(mBgLooper);
+
+        mFragment = new ManageApplications();
+    }
+
+    @Test
+    public void launchFragment() {
+        SettingsRobolectricTestRunner.startSettingsFragment(
+                mFragment, Settings.ManageApplicationsActivity.class);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/dashboard/DashboardDividerDecorationTest.java b/tests/robotests/src/com/android/settings/dashboard/DashboardDividerDecorationTest.java
deleted file mode 100644
index e829eb2..0000000
--- a/tests/robotests/src/com/android/settings/dashboard/DashboardDividerDecorationTest.java
+++ /dev/null
@@ -1,107 +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.dashboard;
-
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.drawable.Drawable;
-import android.support.v7.preference.Preference;
-import android.support.v7.preference.PreferenceGroupAdapter;
-import android.support.v7.widget.RecyclerView;
-import android.view.View;
-import com.android.settings.SettingsRobolectricTestRunner;
-import com.android.settings.TestConfig;
-import com.android.settings.overlay.FeatureFactory;
-import com.android.settings.testutils.FakeFeatureFactory;
-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.annotation.Config;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-@RunWith(SettingsRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
-public class DashboardDividerDecorationTest {
-
-    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
-    private Context mContext;
-    @Mock
-    private Drawable mDrawable;
-    @Mock
-    private Canvas mCanvas;
-    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
-    private RecyclerView mRecyclerView;
-    @Mock
-    private PreferenceGroupAdapter mAdapter;
-    @Mock
-    private Preference pref1;
-    @Mock
-    private Preference pref2;
-    private DashboardDividerDecoration mDecoration;
-    private FakeFeatureFactory mFactory;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        FakeFeatureFactory.setupForTest(mContext);
-        mFactory = (FakeFeatureFactory) FeatureFactory.getFactory(mContext);
-        mDecoration = new DashboardDividerDecoration(mContext);
-        mDecoration.setDivider(mDrawable);
-        mDecoration.setDividerHeight(3);
-    }
-
-    @Test
-    public void drawOver_differentPriorityGroup_shouldDrawDivider() {
-        when(mRecyclerView.getAdapter()).thenReturn(mAdapter);
-        when(mRecyclerView.getChildCount()).thenReturn(2);
-        when(mRecyclerView.getChildAdapterPosition(any(View.class)))
-                .thenReturn(0)
-                .thenReturn(1);
-        when(mAdapter.getItem(0)).thenReturn(pref1);
-        when(mAdapter.getItem(1)).thenReturn(pref2);
-        when(mFactory.dashboardFeatureProvider.getPriorityGroup(pref1)).thenReturn(1);
-        when(mFactory.dashboardFeatureProvider.getPriorityGroup(pref2)).thenReturn(2);
-
-        mDecoration.onDrawOver(mCanvas, mRecyclerView, null /* state */);
-
-        verify(mDrawable).draw(mCanvas);
-    }
-
-
-    @Test
-    public void drawOver_samePriorityGroup_doNotDrawDivider() {
-        when(mRecyclerView.getAdapter()).thenReturn(mAdapter);
-        when(mRecyclerView.getChildCount()).thenReturn(2);
-        when(mRecyclerView.getChildAdapterPosition(any(View.class)))
-                .thenReturn(0)
-                .thenReturn(1);
-        when(mAdapter.getItem(0)).thenReturn(pref1);
-        when(mAdapter.getItem(1)).thenReturn(pref2);
-
-        mDecoration.onDrawOver(mCanvas, mRecyclerView, null /* state */);
-
-        verify(mDrawable, never()).draw(mCanvas);
-    }
-}
diff --git a/tests/robotests/src/com/android/settings/development/BugReportInPowerPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/BugReportInPowerPreferenceControllerTest.java
new file mode 100644
index 0000000..4ca6609
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/BugReportInPowerPreferenceControllerTest.java
@@ -0,0 +1,193 @@
+/*
+ * 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.development;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.provider.Settings;
+import android.os.UserManager;
+import android.support.v14.preference.SwitchPreference;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+
+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;
+import org.robolectric.shadows.ShadowApplication;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Answers.RETURNS_DEEP_STUBS;
+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.doCallRealMethod;
+import static org.mockito.Mockito.never;
+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)
+public class BugReportInPowerPreferenceControllerTest {
+
+    @Mock(answer = RETURNS_DEEP_STUBS)
+    private PreferenceScreen mScreen;
+    @Mock
+    private UserManager mUserManager;
+    @Mock
+    private PackageManager mPackageManager;
+
+    private Context mContext;
+    private SwitchPreference mPreference;
+    private BugReportInPowerPreferenceController mController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        ShadowApplication shadowContext = ShadowApplication.getInstance();
+        shadowContext.setSystemService(Context.USER_SERVICE, mUserManager);
+        mContext = spy(shadowContext.getApplicationContext());
+        when(mContext.getPackageManager()).thenReturn(mPackageManager);
+        mPreference = new SwitchPreference(mContext);
+        when(mScreen.findPreference(anyString())).thenReturn(mPreference);
+        mController = new BugReportInPowerPreferenceController(mContext);
+        mPreference.setKey(mController.getPreferenceKey());
+    }
+
+    @Test
+    public void displayPreference_hasDebugRestriction_shouldRemovePreference() {
+        when(mUserManager.hasUserRestriction(anyString())).thenReturn(true);
+
+        mController.displayPreference(mScreen);
+
+        verify(mScreen).removePreference(any(Preference.class));
+    }
+
+    @Test
+    public void displayPreference_noDebugRestriction_shouldNotRemovePreference() {
+        when(mUserManager.hasUserRestriction(anyString())).thenReturn(false);
+
+        mController.displayPreference(mScreen);
+
+        verify(mScreen, never()).removePreference(any(Preference.class));
+    }
+
+    @Test
+    public void enablePreference_hasDebugRestriction_shouldNotEnable() {
+        when(mUserManager.hasUserRestriction(anyString())).thenReturn(true);
+        mController.displayPreference(mScreen);
+        mPreference.setEnabled(false);
+
+        mController.enablePreference(true);
+
+        assertThat(mPreference.isEnabled()).isFalse();
+    }
+
+    @Test
+    public void enablePreference_noDebugRestriction_shouldEnable() {
+        when(mUserManager.hasUserRestriction(anyString())).thenReturn(false);
+        mController.displayPreference(mScreen);
+        mPreference.setEnabled(false);
+
+        mController.enablePreference(true);
+
+        assertThat(mPreference.isEnabled()).isTrue();
+    }
+
+    @Test
+    public void resetPreference_shouldUncheck() {
+        when(mUserManager.hasUserRestriction(anyString())).thenReturn(false);
+        mController.displayPreference(mScreen);
+        mPreference.setChecked(true);
+
+        mController.resetPreference();
+
+        assertThat(mPreference.isChecked()).isFalse();
+    }
+
+    @Test
+    public void handlePreferenceTreeClick_shouldUpdateSettings() {
+        when(mUserManager.hasUserRestriction(anyString())).thenReturn(false);
+        Settings.Secure.putInt(mContext.getContentResolver(),
+            Settings.Global.BUGREPORT_IN_POWER_MENU, 0);
+        mPreference.setChecked(true);
+        mController.displayPreference(mScreen);
+
+        mController.handlePreferenceTreeClick(mPreference);
+
+        assertThat(Settings.Secure.getInt(mContext.getContentResolver(),
+            Settings.Global.BUGREPORT_IN_POWER_MENU, 0)).isEqualTo(1);
+    }
+
+    @Test
+    public void updateState_settingsOn_shouldCheck() {
+        when(mUserManager.hasUserRestriction(anyString())).thenReturn(false);
+        Settings.Secure.putInt(mContext.getContentResolver(),
+            Settings.Global.BUGREPORT_IN_POWER_MENU, 1);
+        mPreference.setChecked(false);
+        mController.displayPreference(mScreen);
+
+        mController.updateState(mPreference);
+
+        assertThat(mPreference.isChecked()).isTrue();
+    }
+
+    @Test
+    public void updateState_settingsOff_shouldUncheck() {
+        when(mUserManager.hasUserRestriction(anyString())).thenReturn(false);
+        Settings.Secure.putInt(mContext.getContentResolver(),
+            Settings.Global.BUGREPORT_IN_POWER_MENU, 0);
+        mPreference.setChecked(true);
+        mController.displayPreference(mScreen);
+
+        mController.updateState(mPreference);
+
+        assertThat(mPreference.isChecked()).isFalse();
+    }
+
+    @Test
+    public void updateBugreportOptions_shouldEnable() {
+        when(mUserManager.hasUserRestriction(anyString())).thenReturn(false);
+        mPreference.setEnabled(false);
+        mController.displayPreference(mScreen);
+
+        mController.updateBugreportOptions();
+
+        assertThat(mPreference.isEnabled()).isTrue();
+    }
+
+    @Test
+    public void updateBugreportOptions_shouldEnableBugReportStorage() {
+        final ComponentName componentName = new ComponentName("com.android.shell",
+            "com.android.shell.BugreportStorageProvider");
+        when(mUserManager.hasUserRestriction(anyString())).thenReturn(false);
+        mController.displayPreference(mScreen);
+
+        mController.updateBugreportOptions();
+
+        verify(mPackageManager).setComponentEnabledSetting(eq(componentName), anyInt(), anyInt());
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/development/BugReportPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/BugReportPreferenceControllerTest.java
new file mode 100644
index 0000000..377b467
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/BugReportPreferenceControllerTest.java
@@ -0,0 +1,106 @@
+/*
+ * 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.development;
+
+import android.content.Context;
+import android.os.UserManager;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import com.android.settingslib.drawer.CategoryKey;
+
+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.annotation.Config;
+
+import static org.mockito.Answers.RETURNS_DEEP_STUBS;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.never;
+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)
+public class BugReportPreferenceControllerTest {
+
+    @Mock
+    private Context mContext;
+    @Mock
+    private Preference mPreference;
+    @Mock(answer = RETURNS_DEEP_STUBS)
+    private PreferenceScreen mScreen;
+    @Mock
+    private UserManager mUserManager;
+
+    private BugReportPreferenceController mController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
+        when(mScreen.findPreference(anyString())).thenReturn(mPreference);
+        mController = new BugReportPreferenceController(mContext);
+    }
+
+    @Test
+    public void displayPreference_hasDebugRestriction_shouldRemovePreference() {
+        when(mUserManager.hasUserRestriction(anyString())).thenReturn(true);
+
+        mController.displayPreference(mScreen);
+
+        verify(mScreen).removePreference(any(Preference.class));
+    }
+
+    @Test
+    public void displayPreference_noDebugRestriction_shouldNotRemovePreference() {
+        when(mUserManager.hasUserRestriction(anyString())).thenReturn(false);
+
+        mController.displayPreference(mScreen);
+
+        verify(mScreen, never()).removePreference(any(Preference.class));
+    }
+
+    @Test
+    public void enablePreference_hasDebugRestriction_shouldNotEnable() {
+        when(mUserManager.hasUserRestriction(anyString())).thenReturn(true);
+        mController.displayPreference(mScreen);
+
+        mController.enablePreference(true);
+
+        verify(mPreference, never()).setEnabled(anyBoolean());
+    }
+
+    @Test
+    public void enablePreference_noDebugRestriction_shouldEnable() {
+        when(mUserManager.hasUserRestriction(anyString())).thenReturn(false);
+        mController.displayPreference(mScreen);
+
+        mController.enablePreference(true);
+
+        verify(mPreference).setEnabled(anyBoolean());
+    }
+
+}
diff --git a/tests/robotests/src/com/android/settings/notification/AdjustVolumeRestrictedPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/AdjustVolumeRestrictedPreferenceControllerTest.java
index 76e5a22..994582c 100644
--- a/tests/robotests/src/com/android/settings/notification/AdjustVolumeRestrictedPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/AdjustVolumeRestrictedPreferenceControllerTest.java
@@ -28,7 +28,6 @@
 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.annotation.Config;
diff --git a/tests/robotests/src/com/android/settings/notification/AlarmRingtonePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/AlarmRingtonePreferenceControllerTest.java
new file mode 100644
index 0000000..4ac9179
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/AlarmRingtonePreferenceControllerTest.java
@@ -0,0 +1,53 @@
+/*
+ * 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.notification;
+
+import android.content.Context;
+import android.media.RingtoneManager;
+
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+
+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;
+
+import static com.google.common.truth.Truth.assertThat;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class AlarmRingtonePreferenceControllerTest {
+
+    @Mock
+    private Context mContext;
+    private AlarmRingtonePreferenceController mController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mController = new AlarmRingtonePreferenceController(mContext);
+    }
+
+    @Test
+    public void getRingtoneType_shouldReturnAlarm() {
+        assertThat(mController.getRingtoneType()).isEqualTo(RingtoneManager.TYPE_ALARM);
+    }
+
+}
diff --git a/tests/robotests/src/com/android/settings/notification/AlarmVolumePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/AlarmVolumePreferenceControllerTest.java
index 11370e3..a08ec17 100644
--- a/tests/robotests/src/com/android/settings/notification/AlarmVolumePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/AlarmVolumePreferenceControllerTest.java
@@ -25,7 +25,6 @@
 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.annotation.Config;
diff --git a/tests/robotests/src/com/android/settings/notification/CastPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/CastPreferenceControllerTest.java
index 7f1888a..5fe4c42 100644
--- a/tests/robotests/src/com/android/settings/notification/CastPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/CastPreferenceControllerTest.java
@@ -28,7 +28,6 @@
 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.annotation.Config;
diff --git a/tests/robotests/src/com/android/settings/notification/EmergencyBroadcastPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/EmergencyBroadcastPreferenceControllerTest.java
new file mode 100644
index 0000000..98951d1
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/EmergencyBroadcastPreferenceControllerTest.java
@@ -0,0 +1,124 @@
+/*
+ * 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.notification;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.UserManager;
+
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import com.android.settings.accounts.AccountRestrictionHelper;
+import com.android.settingslib.RestrictedPreference;
+
+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.annotation.Config;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class EmergencyBroadcastPreferenceControllerTest {
+
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private Context mContext;
+    @Mock
+    private AccountRestrictionHelper mAccountHelper;
+    @Mock
+    private PackageManager mPackageManager;
+    @Mock
+    private UserManager mUserManager;
+    @Mock
+    private RestrictedPreference mPreference;
+
+    private EmergencyBroadcastPreferenceController mController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
+        when(mContext.getPackageManager()).thenReturn(mPackageManager);
+        mController = new EmergencyBroadcastPreferenceController(mContext, mAccountHelper);
+    }
+
+    @Test
+    public void updateState_shouldCheckRestriction() {
+        mController.updateState(mPreference);
+
+        verify(mPreference).checkRestrictionAndSetDisabled(anyString());
+    }
+
+    @Test
+    public void isAvailable_notAdminUser_shouldReturnFalse() {
+        when(mUserManager.isAdminUser()).thenReturn(false);
+        when(mContext.getResources().getBoolean(
+            com.android.internal.R.bool.config_cellBroadcastAppLinks)).thenReturn(true);
+        when(mPackageManager.getApplicationEnabledSetting(anyString()))
+            .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
+        when(mAccountHelper.hasBaseUserRestriction(anyString(), anyInt())).thenReturn(false);
+
+        assertThat(mController.isAvailable()).isFalse();
+    }
+
+    @Test
+    public void isAvailable_hasConfigCellBroadcastRestriction_shouldReturnFalse() {
+        when(mUserManager.isAdminUser()).thenReturn(true);
+        when(mContext.getResources().getBoolean(
+            com.android.internal.R.bool.config_cellBroadcastAppLinks)).thenReturn(true);
+        when(mPackageManager.getApplicationEnabledSetting(anyString()))
+            .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
+        when(mAccountHelper.hasBaseUserRestriction(
+            eq(UserManager.DISALLOW_CONFIG_CELL_BROADCASTS), anyInt())).thenReturn(true);
+
+        assertThat(mController.isAvailable()).isFalse();
+    }
+
+    @Test
+    public void isAvailable_cellBroadcastAppLinkDisabled_shouldReturnFalse() {
+        when(mUserManager.isAdminUser()).thenReturn(true);
+        when(mContext.getResources().getBoolean(
+            com.android.internal.R.bool.config_cellBroadcastAppLinks)).thenReturn(false);
+        when(mPackageManager.getApplicationEnabledSetting(anyString()))
+            .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
+        when(mAccountHelper.hasBaseUserRestriction(anyString(), anyInt())).thenReturn(false);
+
+        assertThat(mController.isAvailable()).isFalse();
+    }
+
+    @Test
+    public void isAvailable_cellBroadcastReceiverDisabled_shouldReturnFalse() {
+        when(mUserManager.isAdminUser()).thenReturn(true);
+        when(mContext.getResources().getBoolean(
+            com.android.internal.R.bool.config_cellBroadcastAppLinks)).thenReturn(true);
+        when(mPackageManager.getApplicationEnabledSetting(anyString()))
+            .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
+        when(mAccountHelper.hasBaseUserRestriction(anyString(), anyInt())).thenReturn(false);
+
+        assertThat(mController.isAvailable()).isFalse();
+    }
+
+}
diff --git a/tests/robotests/src/com/android/settings/notification/MediaVolumePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/MediaVolumePreferenceControllerTest.java
index 9c16937..9944379 100644
--- a/tests/robotests/src/com/android/settings/notification/MediaVolumePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/MediaVolumePreferenceControllerTest.java
@@ -25,7 +25,6 @@
 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.annotation.Config;
diff --git a/tests/robotests/src/com/android/settings/notification/NotificationRingtonePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/NotificationRingtonePreferenceControllerTest.java
new file mode 100644
index 0000000..841367f
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/NotificationRingtonePreferenceControllerTest.java
@@ -0,0 +1,53 @@
+/*
+ * 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.notification;
+
+import android.content.Context;
+import android.media.RingtoneManager;
+
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+
+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;
+
+import static com.google.common.truth.Truth.assertThat;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class NotificationRingtonePreferenceControllerTest {
+
+    @Mock
+    private Context mContext;
+    private NotificationRingtonePreferenceController mController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mController = new NotificationRingtonePreferenceController(mContext);
+    }
+
+    @Test
+    public void getRingtoneType_shouldReturnNotification() {
+        assertThat(mController.getRingtoneType()).isEqualTo(RingtoneManager.TYPE_NOTIFICATION);
+    }
+
+}
diff --git a/tests/robotests/src/com/android/settings/notification/NotificationVolumePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/NotificationVolumePreferenceControllerTest.java
index e0aa88e..e6d8a41 100644
--- a/tests/robotests/src/com/android/settings/notification/NotificationVolumePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/NotificationVolumePreferenceControllerTest.java
@@ -27,7 +27,6 @@
 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.annotation.Config;
diff --git a/tests/robotests/src/com/android/settings/notification/PhoneRingtonePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/PhoneRingtonePreferenceControllerTest.java
new file mode 100644
index 0000000..85e74b0
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/PhoneRingtonePreferenceControllerTest.java
@@ -0,0 +1,75 @@
+/*
+ * 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.notification;
+
+import android.content.Context;
+import android.media.RingtoneManager;
+import android.telephony.TelephonyManager;
+
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+
+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;
+import org.robolectric.shadows.ShadowApplication;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.when;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class PhoneRingtonePreferenceControllerTest {
+
+    @Mock
+    private TelephonyManager mTelephonyManager;
+
+    private Context mContext;
+    private PhoneRingtonePreferenceController mController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        ShadowApplication shadowContext = ShadowApplication.getInstance();
+        shadowContext.setSystemService(Context.TELEPHONY_SERVICE, mTelephonyManager);
+        mContext = shadowContext.getApplicationContext();
+        mController = new PhoneRingtonePreferenceController(mContext);
+    }
+
+    @Test
+    public void isAvailable_notVoiceCapable_shouldReturnFalse() {
+        when(mTelephonyManager.isVoiceCapable()).thenReturn(false);
+
+        assertThat(mController.isAvailable()).isFalse();
+    }
+
+    @Test
+    public void isAvailable_VoiceCapable_shouldReturnTrue() {
+        when(mTelephonyManager.isVoiceCapable()).thenReturn(true);
+
+        assertThat(mController.isAvailable()).isTrue();
+    }
+
+    @Test
+    public void getRingtoneType_shouldReturnRingtone() {
+        assertThat(mController.getRingtoneType()).isEqualTo(RingtoneManager.TYPE_RINGTONE);
+    }
+
+}
diff --git a/tests/robotests/src/com/android/settings/notification/RingVolumePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/RingVolumePreferenceControllerTest.java
index 2d54cef..4780e5c 100644
--- a/tests/robotests/src/com/android/settings/notification/RingVolumePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/RingVolumePreferenceControllerTest.java
@@ -30,7 +30,6 @@
 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.annotation.Config;
diff --git a/tests/robotests/src/com/android/settings/notification/RingtonePreferenceControllerBaseTest.java b/tests/robotests/src/com/android/settings/notification/RingtonePreferenceControllerBaseTest.java
new file mode 100644
index 0000000..d680c38
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/RingtonePreferenceControllerBaseTest.java
@@ -0,0 +1,85 @@
+/*
+ * 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.notification;
+
+import android.content.Context;
+import android.support.v7.preference.Preference;
+import android.media.RingtoneManager;
+
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+
+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;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class RingtonePreferenceControllerBaseTest {
+
+    @Mock
+    private Context mContext;
+
+    private RingtonePreferenceControllerBase mController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mController = new RingtonePreferenceControllerBaseTestable(mContext);
+    }
+
+    @Test
+    public void isAlwaysAvailable() {
+        assertThat(mController.isAvailable()).isTrue();
+    }
+
+
+    @Test
+    public void updateState_shouldSetSummary() {
+        Preference preference = mock(Preference.class);
+
+        mController.updateState(preference);
+
+        verify(preference).setSummary(anyString());
+    }
+
+    private class RingtonePreferenceControllerBaseTestable extends
+        RingtonePreferenceControllerBase {
+        RingtonePreferenceControllerBaseTestable(Context context) {
+            super(context);
+        }
+
+        @Override
+        public String getPreferenceKey() {
+            return null;
+        }
+
+        @Override
+        public int getRingtoneType() {
+            return RingtoneManager.TYPE_RINGTONE;
+        }
+    }
+
+}
diff --git a/tests/robotests/src/com/android/settings/notification/VibrateWhenRingPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/VibrateWhenRingPreferenceControllerTest.java
new file mode 100644
index 0000000..3c3f212
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/VibrateWhenRingPreferenceControllerTest.java
@@ -0,0 +1,109 @@
+/*
+ * 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.notification;
+
+import android.content.Context;
+import android.provider.Settings;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+import android.support.v7.preference.TwoStatePreference;
+import android.telephony.TelephonyManager;
+
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+
+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;
+import org.robolectric.shadows.ShadowApplication;
+
+import static android.provider.Settings.System.VIBRATE_WHEN_RINGING;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class VibrateWhenRingPreferenceControllerTest {
+
+    @Mock
+    private Context mContext;
+    @Mock
+    private PreferenceScreen mScreen;
+    @Mock
+    private TelephonyManager mTelephonyManager;
+
+    private VibrateWhenRingPreferenceController mController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager);
+        mController = new VibrateWhenRingPreferenceController(mContext);
+    }
+
+    @Test
+    public void display_voiceCapable_shouldDisplay() {
+        when(mTelephonyManager.isVoiceCapable()).thenReturn(true);
+        when(mScreen.findPreference(mController.getPreferenceKey()))
+            .thenReturn(mock(Preference.class));
+
+        mController.displayPreference(mScreen);
+
+        verify(mScreen, never()).removePreference(any(Preference.class));
+    }
+
+    @Test
+    public void display_notVoiceCapable_shouldNotDisplay() {
+        when(mTelephonyManager.isVoiceCapable()).thenReturn(false);
+        when(mScreen.findPreference(mController.getPreferenceKey()))
+                .thenReturn(mock(Preference.class));
+
+        mController.displayPreference(mScreen);
+
+        verify(mScreen).removePreference(any(Preference.class));
+    }
+
+    @Test
+    public void updateState_settingIsOn_preferenceShouldBeChecked() {
+        final TwoStatePreference preference = mock(TwoStatePreference.class);
+        final Context context = ShadowApplication.getInstance().getApplicationContext();
+        Settings.System.putInt(context.getContentResolver(), VIBRATE_WHEN_RINGING, 1);
+
+        mController = new VibrateWhenRingPreferenceController(context);
+        mController.updateState(preference);
+
+        verify(preference).setChecked(true);
+    }
+
+    @Test
+    public void updateState_settingIsOff_preferenceShouldNotBeChecked() {
+        final TwoStatePreference preference = mock(TwoStatePreference.class);
+        final Context context = ShadowApplication.getInstance().getApplicationContext();
+        Settings.System.putInt(context.getContentResolver(), VIBRATE_WHEN_RINGING, 0);
+
+        mController = new VibrateWhenRingPreferenceController(context);
+        mController.updateState(preference);
+
+        verify(preference).setChecked(false);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/VolumeSeekBarPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/VolumeSeekBarPreferenceControllerTest.java
index 2d0aaeb..581ed47 100644
--- a/tests/robotests/src/com/android/settings/notification/VolumeSeekBarPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/VolumeSeekBarPreferenceControllerTest.java
@@ -27,7 +27,6 @@
 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.annotation.Config;
diff --git a/tests/robotests/src/com/android/settings/notification/ZenModePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenModePreferenceControllerTest.java
index 7b53a86..155e6ea 100644
--- a/tests/robotests/src/com/android/settings/notification/ZenModePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/ZenModePreferenceControllerTest.java
@@ -24,7 +24,6 @@
 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.annotation.Config;
diff --git a/tests/robotests/src/com/android/settings/search/DatabaseResultLoaderTest.java b/tests/robotests/src/com/android/settings/search/DatabaseResultLoaderTest.java
index a744bb7..1df7b1f 100644
--- a/tests/robotests/src/com/android/settings/search/DatabaseResultLoaderTest.java
+++ b/tests/robotests/src/com/android/settings/search/DatabaseResultLoaderTest.java
@@ -22,20 +22,23 @@
 import android.content.Intent;
 import android.database.MatrixCursor;
 import android.graphics.drawable.Drawable;
+
+import com.android.settings.R;
 import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.SubSettings;
 import com.android.settings.TestConfig;
+import com.android.settings.gestures.GestureSettings;
 import com.android.settings.search2.DatabaseResultLoader;
 import com.android.settings.search2.IntentPayload;
 import com.android.settings.search2.ResultPayload;
 import com.android.settings.search2.ResultPayload.PayloadType;
 import com.android.settings.search2.SearchResult;
-import com.android.settings.R;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-
-import org.robolectric.annotation.Config;
 import org.robolectric.Robolectric;
+import org.robolectric.annotation.Config;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -47,7 +50,11 @@
 public class DatabaseResultLoaderTest {
     private DatabaseResultLoader mLoader;
 
-    private static final String[] TITLES = new String[] {"title1", "title2", "title3"};
+    private static final String[] COLUMNS = new String[]{"rank", "title", "summary_on",
+            "summary off", "entries", "keywords", "class name", "screen title", "icon",
+            "intent action", "target package", "target class", "enabled", "key", "user id"};
+
+    private static final String[] TITLES = new String[]{"title1", "title2", "title3"};
     private static final String SUMMARY = "SUMMARY";
     private static final int EXAMPLES = 3;
     private static final Intent mIntent = new Intent("com.android.settings");
@@ -108,6 +115,16 @@
     }
 
     @Test
+    public void testParseCursor_NoIcon() {
+        List<SearchResult> results = mLoader.parseCursorForSearch(
+                getDummyCursor(false /* hasIcon */));
+        for (int i = 0; i < EXAMPLES; i++) {
+            Drawable resultDrawable = results.get(i).icon;
+            assertThat(resultDrawable).isNull();
+        }
+    }
+
+    @Test
     public void testParseCursor_MatchesPayloadType() {
         List<SearchResult> results = mLoader.parseCursorForSearch(getDummyCursor());
         ResultPayload payload;
@@ -118,6 +135,33 @@
     }
 
     @Test
+    public void testParseCursor_MatchesIntentForSubSettings() {
+        MatrixCursor cursor = new MatrixCursor(COLUMNS);
+        final String BLANK = "";
+        cursor.addRow(new Object[]{
+                0,       // rank
+                TITLES[0],
+                SUMMARY,
+                SUMMARY, // summary off
+                BLANK,   // entries
+                BLANK,   // Keywords
+                GestureSettings.class.getName(),
+                BLANK,   // screen title
+                null,    // icon
+                BLANK,   // action
+                null,    // target package
+                BLANK,   // target class
+                BLANK,   // enabled
+                BLANK,   // key
+                BLANK    // user id
+        });
+        List<SearchResult> results = mLoader.parseCursorForSearch(cursor);
+        IntentPayload payload = (IntentPayload) results.get(0).payload;
+        Intent intent = payload.intent;
+        assertThat(intent.getComponent().getClassName()).isEqualTo(SubSettings.class.getName());
+    }
+
+    @Test
     public void testParseCursor_MatchesIntentPayload() {
         List<SearchResult> results = mLoader.parseCursorForSearch(getDummyCursor());
         IntentPayload payload;
@@ -129,14 +173,15 @@
     }
 
     private MatrixCursor getDummyCursor() {
-        String[] columns = new String[] {"rank", "title",  "summary_on", "summary off", "entries",
-                "keywords", "class name", "screen title", "icon", "intent action",
-                "target package", "target class", "enabled", "key", "user id"};
-        MatrixCursor cursor = new MatrixCursor(columns);
+        return getDummyCursor(true /* hasIcon */);
+    }
+
+    private MatrixCursor getDummyCursor(boolean hasIcon) {
+        MatrixCursor cursor = new MatrixCursor(COLUMNS);
         final String BLANK = "";
 
         for (int i = 0; i < EXAMPLES; i++) {
-            ArrayList<String> item = new ArrayList<>(columns.length);
+            ArrayList<String> item = new ArrayList<>(COLUMNS.length);
             item.add(Integer.toString(i));
             item.add(TITLES[i]);
             item.add(SUMMARY);
@@ -145,7 +190,7 @@
             item.add(BLANK); // keywords
             item.add(BLANK); // classname
             item.add(BLANK); // screen title
-            item.add(Integer.toString(mIcon));
+            item.add(hasIcon ? Integer.toString(mIcon) : null);
             item.add(mIntent.getAction());
             item.add(BLANK); // target package
             item.add(BLANK); // target class
diff --git a/tests/robotests/src/com/android/settings/search/IntentSearchViewHolderTest.java b/tests/robotests/src/com/android/settings/search/IntentSearchViewHolderTest.java
index 2534c0b..805c7cb 100644
--- a/tests/robotests/src/com/android/settings/search/IntentSearchViewHolderTest.java
+++ b/tests/robotests/src/com/android/settings/search/IntentSearchViewHolderTest.java
@@ -17,40 +17,50 @@
 
 package com.android.settings.search;
 
+import android.app.Fragment;
 import android.content.Context;
+import android.content.Intent;
 import android.graphics.drawable.Drawable;
 import android.view.LayoutInflater;
 import android.view.View;
+
 import com.android.settings.R;
 import com.android.settings.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
 import com.android.settings.search2.IntentPayload;
 import com.android.settings.search2.IntentSearchViewHolder;
-import com.android.settings.search2.SearchResult.Builder;
 import com.android.settings.search2.SearchResult;
+import com.android.settings.search2.SearchResult.Builder;
+
 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;
 import org.robolectric.shadows.ShadowApplication;
 
 import java.util.ArrayList;
 
 import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.verify;
 
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class IntentSearchViewHolderTest {
-    private IntentSearchViewHolder mHolder;
-    private static Drawable mIcon;
 
     private static final String TITLE = "title";
     private static final String SUMMARY = "summary";
 
+    @Mock
+    private Fragment mFragment;
+    private IntentSearchViewHolder mHolder;
+    private Drawable mIcon;
 
     @Before
     public void setUp() {
+        MockitoAnnotations.initMocks(this);
         final Context context = ShadowApplication.getInstance().getApplicationContext();
         View view = LayoutInflater.from(context).inflate(R.layout.search_intent_item, null);
         mHolder = new IntentSearchViewHolder(view);
@@ -68,11 +78,13 @@
     @Test
     public void testBindViewElements_AllUpdated() {
         SearchResult result = getSearchResult();
-        mHolder.onBind(result);
+        mHolder.onBind(mFragment, result);
+        mHolder.itemView.performClick();
 
         assertThat(mHolder.titleView.getText()).isEqualTo(TITLE);
         assertThat(mHolder.summaryView.getText()).isEqualTo(SUMMARY);
         assertThat(mHolder.iconView.getDrawable()).isEqualTo(mIcon);
+        verify(mFragment).startActivity(any(Intent.class));
     }
 
     private SearchResult getSearchResult() {
@@ -81,7 +93,7 @@
                 .addSummary(SUMMARY)
                 .addRank(1)
                 .addPayload(new IntentPayload(null))
-                .addBreadcrumbs(new ArrayList<String>())
+                .addBreadcrumbs(new ArrayList<>())
                 .addIcon(mIcon);
 
         return builder.build();
diff --git a/tests/robotests/src/com/android/settings/search/SearchAdapterTest.java b/tests/robotests/src/com/android/settings/search/SearchAdapterTest.java
index 81e9180..0756d3f 100644
--- a/tests/robotests/src/com/android/settings/search/SearchAdapterTest.java
+++ b/tests/robotests/src/com/android/settings/search/SearchAdapterTest.java
@@ -27,6 +27,7 @@
 import com.android.settings.search2.DatabaseResultLoader;
 import com.android.settings.search2.IntentPayload;
 import com.android.settings.search2.ResultPayload;
+import com.android.settings.search2.SearchFragment;
 import com.android.settings.search2.SearchResult;
 import com.android.settings.search2.SearchResult.Builder;
 import com.android.settings.search2.SearchResultsAdapter;
@@ -34,6 +35,8 @@
 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.annotation.Config;
 
@@ -46,14 +49,17 @@
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class SearchAdapterTest {
 
+    @Mock
+    private SearchFragment mFragment;
     private SearchResultsAdapter mAdapter;
     private Context mContext;
     private String mLoaderClassName;
 
     @Before
     public void setUp() {
+        MockitoAnnotations.initMocks(this);
         mContext = Robolectric.buildActivity(Activity.class).get();
-        mAdapter = new SearchResultsAdapter();
+        mAdapter = new SearchResultsAdapter(mFragment);
         mLoaderClassName = DatabaseResultLoader.class.getName();
     }
 
@@ -62,8 +68,7 @@
         ArrayList<String> breadcrumbs = new ArrayList<>();
         final Drawable icon = mContext.getDrawable(R.drawable.ic_search_history);
         final ResultPayload payload = new IntentPayload(null);
-
-        SearchResult.Builder builder = new Builder();
+        final SearchResult.Builder builder = new Builder();
         builder.addTitle("title")
                 .addSummary("summary")
                 .addRank(1)
diff --git a/tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java
index 67189d0..d9e2dd6 100644
--- a/tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java
@@ -18,12 +18,18 @@
 package com.android.settings.search;
 
 import android.app.Activity;
+import android.content.Context;
+import android.content.res.Configuration;
 import android.view.Menu;
 
 import com.android.settings.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.search2.DatabaseIndexingManager;
 import com.android.settings.search2.SearchFeatureProviderImpl;
 
+import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settingslib.drawer.DashboardCategory;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -33,9 +39,14 @@
 import org.robolectric.Robolectric;
 import org.robolectric.annotation.Config;
 
+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.anyString;
+import static org.mockito.Mockito.never;
+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)
@@ -64,4 +75,22 @@
 
         verify(menu).add(anyInt(), anyInt(), anyInt(), anyString());
     }
+
+    @Test
+    public void testUpdateIndexNewSearch_UsesDatabaseIndexingManager() {
+        mProvider = spy(new SearchFeatureProviderImpl(mActivity));
+        when(mProvider.isEnabled()).thenReturn(true);
+
+        mProvider.updateIndex(mActivity);
+        verify(mProvider).getIndexingManager(any(Context.class));
+    }
+
+    @Test
+    public void testUpdateIndexNewSearch_UsesIndex() {
+        mProvider = spy(new SearchFeatureProviderImpl(mActivity));
+        when(mProvider.isEnabled()).thenReturn(false);
+
+        mProvider.updateIndex(mActivity);
+        verify(mProvider, never()).getIndexingManager(any(Context.class));
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/search/SearchResultBuilderTest.java b/tests/robotests/src/com/android/settings/search/SearchResultBuilderTest.java
index c2ec49c..5649a95 100644
--- a/tests/robotests/src/com/android/settings/search/SearchResultBuilderTest.java
+++ b/tests/robotests/src/com/android/settings/search/SearchResultBuilderTest.java
@@ -19,23 +19,23 @@
 
 import android.content.Context;
 import android.graphics.drawable.Drawable;
+
+import com.android.settings.R;
 import com.android.settings.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
 import com.android.settings.search2.IntentPayload;
 import com.android.settings.search2.ResultPayload;
 import com.android.settings.search2.SearchResult;
 import com.android.settings.search2.SearchResult.Builder;
-import com.android.settings.R;
-
-import java.util.ArrayList;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-
 import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowApplication;
 
+import java.util.ArrayList;
+
 import static com.google.common.truth.Truth.assertThat;
 
 @RunWith(SettingsRobolectricTestRunner.class)
@@ -100,23 +100,6 @@
     }
 
     @Test
-    public void testNoSummary_BuildSearchResultException() {
-        mBuilder.addTitle(mTitle)
-                .addRank(mRank)
-                .addBreadcrumbs(mBreadcrumbs)
-                .addIcon(mIcon)
-                .addPayload(mResultPayload);
-
-        SearchResult result = null;
-        try {
-            result = mBuilder.build();
-        } catch (IllegalArgumentException e) {
-            // passes.
-        }
-        assertThat(result).isNull();
-    }
-
-    @Test
     public void testNoRank_BuildSearchResultException() {
         mBuilder.addTitle(mTitle)
                 .addSummary(mSummary)
@@ -134,23 +117,6 @@
     }
 
     @Test
-    public void testNoBreadcrumbs_BuildSearchResultException() {
-        mBuilder.addTitle(mTitle)
-                .addSummary(mSummary)
-                .addRank(mRank)
-                .addIcon(mIcon)
-                .addPayload(mResultPayload);
-
-        SearchResult result = null;
-        try {
-            result = mBuilder.build();
-        } catch (IllegalArgumentException e) {
-            // passes.
-        }
-        assertThat(result).isNull();
-    }
-
-    @Test
     public void testNoIcon_BuildSearchResultException() {
         mBuilder.addTitle(mTitle)
                 .addSummary(mSummary)
@@ -158,13 +124,7 @@
                 .addBreadcrumbs(mBreadcrumbs)
                 .addPayload(mResultPayload);
 
-        SearchResult result = null;
-        try {
-            result = mBuilder.build();
-        } catch (IllegalArgumentException e) {
-            // passes.
-        }
-        assertThat(result).isNull();
+        assertThat(mBuilder.build()).isNotNull();
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/search2/InstalledAppResultLoaderTest.java b/tests/robotests/src/com/android/settings/search2/InstalledAppResultLoaderTest.java
new file mode 100644
index 0000000..e3c2180
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/search2/InstalledAppResultLoaderTest.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.search2;
+
+import android.content.Context;
+import android.content.pm.UserInfo;
+import android.os.UserManager;
+
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import com.android.settings.applications.PackageManagerWrapper;
+import com.android.settings.testutils.ApplicationTestUtils;
+
+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.annotation.Config;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static android.content.pm.ApplicationInfo.FLAG_SYSTEM;
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.when;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class InstalledAppResultLoaderTest {
+
+
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private Context mContext;
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private PackageManagerWrapper mPackageManagerWrapper;
+    @Mock
+    private UserManager mUserManager;
+
+    private InstalledAppResultLoader mLoader;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        final List<UserInfo> infos = new ArrayList<>();
+        infos.add(new UserInfo(1, "user 1", 0));
+        when(mUserManager.getProfiles(anyInt())).thenReturn(infos);
+        when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
+        when(mPackageManagerWrapper.getInstalledApplicationsAsUser(anyInt(), anyInt()))
+                .thenReturn(Arrays.asList(
+                        ApplicationTestUtils.buildInfo(0 /* uid */, "app1", FLAG_SYSTEM),
+                        ApplicationTestUtils.buildInfo(0 /* uid */, "app2", FLAG_SYSTEM),
+                        ApplicationTestUtils.buildInfo(0 /* uid */, "app3", FLAG_SYSTEM),
+                        ApplicationTestUtils.buildInfo(0 /* uid */, "app4", 0 /* flags */),
+                        ApplicationTestUtils.buildInfo(0 /* uid */, "app", 0 /* flags */)));
+    }
+
+    @Test
+    public void query_noMatchingQuery_shouldReturnEmptyResult() {
+        final String query = "abc";
+
+        mLoader = new InstalledAppResultLoader(mContext, mPackageManagerWrapper, query);
+
+        assertThat(mLoader.loadInBackground()).isEmpty();
+    }
+
+    @Test
+    public void query_matchingQuery_shouldReturnNonSystemApps() {
+        final String query = "app";
+
+        mLoader = new InstalledAppResultLoader(mContext, mPackageManagerWrapper, query);
+
+        assertThat(mLoader.loadInBackground().size()).isEqualTo(2);
+    }
+
+    @Test
+    public void query_matchingQuery_shouldRankBasedOnSimilarity() {
+        final String query = "app";
+
+        mLoader = new InstalledAppResultLoader(mContext, mPackageManagerWrapper, query);
+        final List<SearchResult> results = mLoader.loadInBackground();
+
+        // List is sorted by rank
+        assertThat(results.get(0).rank).isLessThan(results.get(1).rank);
+        // perfect match first
+        assertThat(results.get(0).title).isEqualTo(query);
+        // Then partial match
+        assertThat(results.get(1).title).isNotEqualTo(query);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/search2/SearchFragmentTest.java b/tests/robotests/src/com/android/settings/search2/SearchFragmentTest.java
index 979b7e5..40d1ae5 100644
--- a/tests/robotests/src/com/android/settings/search2/SearchFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/search2/SearchFragmentTest.java
@@ -47,6 +47,8 @@
     private Context mContext;
     @Mock
     private DatabaseResultLoader mDatabaseResultLoader;
+    @Mock
+    private InstalledAppResultLoader mInstalledAppResultLoader;
     private FakeFeatureFactory mFeatureFactory;
 
     @Before
@@ -54,14 +56,16 @@
         MockitoAnnotations.initMocks(this);
         FakeFeatureFactory.setupForTest(mContext);
         mFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
+        when(mFeatureFactory.searchFeatureProvider
+                .getDatabaseSearchLoader(any(Context.class), anyString()))
+                .thenReturn(mDatabaseResultLoader);
+        when(mFeatureFactory.searchFeatureProvider
+                .getInstalledAppSearchLoader(any(Context.class), anyString()))
+                .thenReturn(mInstalledAppResultLoader);
     }
 
     @Test
     public void screenRotate_shouldPersistQuery() {
-        when(mFeatureFactory.searchFeatureProvider
-                .getDatabaseSearchLoader(any(Context.class), anyString()))
-                .thenReturn(mDatabaseResultLoader);
-
         final Bundle bundle = new Bundle();
         final String testQuery = "test";
         ActivityController<SearchActivity> activityController =
@@ -79,14 +83,12 @@
 
         verify(mFeatureFactory.searchFeatureProvider)
                 .getDatabaseSearchLoader(any(Context.class), anyString());
+        verify(mFeatureFactory.searchFeatureProvider)
+                .getInstalledAppSearchLoader(any(Context.class), anyString());
     }
 
     @Test
     public void queryTextChange_shouldTriggerLoader() {
-        when(mFeatureFactory.searchFeatureProvider
-                .getDatabaseSearchLoader(any(Context.class), anyString()))
-                .thenReturn(mDatabaseResultLoader);
-
         final String testQuery = "test";
         ActivityController<SearchActivity> activityController =
                 Robolectric.buildActivity(SearchActivity.class);
@@ -98,5 +100,7 @@
 
         verify(mFeatureFactory.searchFeatureProvider)
                 .getDatabaseSearchLoader(any(Context.class), anyString());
+        verify(mFeatureFactory.searchFeatureProvider)
+                .getInstalledAppSearchLoader(any(Context.class), anyString());
     }
 }
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/SettingsShadowResources.java b/tests/robotests/src/com/android/settings/testutils/shadow/SettingsShadowResources.java
new file mode 100644
index 0000000..51a187b
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/SettingsShadowResources.java
@@ -0,0 +1,126 @@
+package com.android.settings.testutils.shadow;
+
+import android.annotation.DimenRes;
+import android.content.res.Resources;
+import android.content.res.Resources.NotFoundException;
+import android.content.res.Resources.Theme;
+import android.content.res.TypedArray;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.util.TypedValue;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+import org.robolectric.annotation.RealObject;
+import org.robolectric.res.StyleData;
+import org.robolectric.res.StyleResolver;
+import org.robolectric.res.builder.XmlResourceParserImpl;
+import org.robolectric.shadows.ShadowAssetManager;
+import org.robolectric.shadows.ShadowResources;
+import org.robolectric.util.ReflectionHelpers;
+import org.w3c.dom.Node;
+
+import java.util.List;
+import java.util.Map;
+
+import static android.util.TypedValue.TYPE_REFERENCE;
+import static org.robolectric.Shadows.shadowOf;
+import static org.robolectric.internal.Shadow.directlyOn;
+
+/**
+ * Shadow Resources and Theme classes to handle resource references that Robolectric shadows cannot
+ * handle because they are too new or private.
+ */
+@Implements(Resources.class)
+public class SettingsShadowResources extends ShadowResources {
+
+    @RealObject Resources realResources;
+
+    @Implementation
+    public int getDimensionPixelSize(@DimenRes int id) throws NotFoundException {
+        // Handle requests for private dimension resources,
+        // TODO: Consider making a set of private dimension resource ids if this happens repeatedly.
+        if (id == com.android.internal.R.dimen.preference_fragment_padding_bottom) {
+            return 0;
+        }
+        return directlyOn(realResources, Resources.class).getDimensionPixelSize(id);
+    }
+
+    @Implementation
+    public Drawable loadDrawable(TypedValue value, int id, Theme theme)
+            throws NotFoundException {
+        // The drawable item in switchbar_background.xml refers to a very recent color attribute
+        // that Robolectric isn't yet aware of.
+        // TODO: Remove this once Robolectric is updated.
+        if (id == com.android.settings.R.drawable.switchbar_background) {
+            return new ColorDrawable();
+        }
+        return super.loadDrawable(value, id, theme);
+    }
+
+    @Implements(Theme.class)
+    public static class SettingsShadowTheme extends ShadowTheme {
+
+        @RealObject
+        Theme realTheme;
+
+        @Implementation
+        public TypedArray obtainStyledAttributes(
+                AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes) {
+            // Replace all private string references with a placeholder.
+            if (set != null) {
+                for (int i = 0; i < set.getAttributeCount(); ++i) {
+                    if (set.getAttributeValue(i).startsWith("@*android:string")) {
+                        Node node = ReflectionHelpers.callInstanceMethod(
+                                XmlResourceParserImpl.class, set, "getAttributeAt",
+                                ReflectionHelpers.ClassParameter.from(int.class, i));
+                        node.setNodeValue("PLACEHOLDER");
+                    }
+                }
+            }
+
+            // Track down all styles and remove all inheritance from private styles.
+            ShadowAssetManager assetManager = shadowOf(RuntimeEnvironment.application.getAssets());
+            // The Object's below are actually ShadowAssetManager.OverlayedStyle. We can't use it
+            // here because it's package private.
+            Map<Long, List<Object>> appliedStylesList =
+                    ReflectionHelpers.getField(assetManager, "appliedStyles");
+            for (Long idx : appliedStylesList.keySet()) {
+                List<Object> appliedStyles = appliedStylesList.get(idx);
+                int i = 1;
+                for (Object appliedStyle : appliedStyles) {
+                    StyleResolver styleResolver = ReflectionHelpers.getField(appliedStyle, "style");
+                    List<StyleData> styleDatas =
+                            ReflectionHelpers.getField(styleResolver, "styles");
+                    for (StyleData styleData : styleDatas) {
+                        if (styleData.getParent() != null &&
+                                styleData.getParent().startsWith("@*android:style")) {
+                            ReflectionHelpers.setField(StyleData.class, styleData, "parent", null);
+                        }
+                    }
+                }
+
+            }
+            return super.obtainStyledAttributes(set, attrs, defStyleAttr, defStyleRes);
+        }
+
+        @Implementation
+        public boolean resolveAttribute(int resid, TypedValue outValue, boolean resolveRefs) {
+            // The real Resources instance in Robolectric tests somehow fails to find the
+            // preferenceTheme attribute in the layout. Let's do it ourselves.
+            if (getResources().getResourceName(resid)
+                    .equals("com.android.settings:attr/preferenceTheme")) {
+                int preferenceThemeResId =
+                        getResources().getIdentifier(
+                                "PreferenceTheme", "style", "com.android.settings");
+                outValue.type = TYPE_REFERENCE;
+                outValue.data = preferenceThemeResId;
+                outValue.resourceId = preferenceThemeResId;
+                return true;
+            }
+            return directlyOn(realTheme, Theme.class)
+                    .resolveAttribute(resid, outValue, resolveRefs);
+        }
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDynamicIndexableContentMonitor.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDynamicIndexableContentMonitor.java
new file mode 100644
index 0000000..de5d243
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDynamicIndexableContentMonitor.java
@@ -0,0 +1,22 @@
+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/unit/Android.mk b/tests/unit/Android.mk
index ae1cc72..d852ac5 100644
--- a/tests/unit/Android.mk
+++ b/tests/unit/Android.mk
@@ -10,7 +10,8 @@
 LOCAL_STATIC_JAVA_LIBRARIES := \
     android-support-test \
     mockito-target-minus-junit4 \
-    espresso-core
+    espresso-core \
+    truth-prebuilt
 
 # Include all test java files.
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/unit/src/com/android/settings/search/SearchIndexablesContractTest.java b/tests/unit/src/com/android/settings/search/SearchIndexablesContractTest.java
new file mode 100644
index 0000000..4de5fb7
--- /dev/null
+++ b/tests/unit/src/com/android/settings/search/SearchIndexablesContractTest.java
@@ -0,0 +1,121 @@
+/*
+ * 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 android.provider.SearchIndexablesContract;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+
+public class SearchIndexablesContractTest extends AndroidTestCase {
+        @SmallTest
+        public void testRawColumns_IncludesRank() {
+            assertEquals(SearchIndexablesContract.RawData.COLUMN_RANK,
+                    SearchIndexablesContract.INDEXABLES_RAW_COLUMNS[0]);
+        }
+
+        @SmallTest
+        public void testRawColumns_IncludesTitle() {
+            assertEquals(SearchIndexablesContract.RawData.COLUMN_TITLE,
+                    SearchIndexablesContract.INDEXABLES_RAW_COLUMNS[1]);
+        }
+
+        @SmallTest
+        public void testRawColumns_IncludesSummaryOn() {
+            assertEquals(SearchIndexablesContract.RawData.COLUMN_SUMMARY_ON,
+                    SearchIndexablesContract.INDEXABLES_RAW_COLUMNS[2]);
+        }
+
+        @SmallTest
+        public void testRawColumns_IncludesSummaryOff() {
+            assertEquals(SearchIndexablesContract.RawData.COLUMN_SUMMARY_OFF,
+                    SearchIndexablesContract.INDEXABLES_RAW_COLUMNS[3]);
+        }
+
+        @SmallTest
+        public void testRawColumns_IncludesEntries() {
+            assertEquals(SearchIndexablesContract.RawData.COLUMN_ENTRIES,
+                    SearchIndexablesContract.INDEXABLES_RAW_COLUMNS[4]);
+        }
+
+        @SmallTest
+        public void testRawColumns_IncludesKeywords() {
+            assertEquals(SearchIndexablesContract.RawData.COLUMN_KEYWORDS,
+                    SearchIndexablesContract.INDEXABLES_RAW_COLUMNS[5]);
+        }
+
+        @SmallTest
+        public void testRawColumns_IncludesScreenTitle() {
+            assertEquals(SearchIndexablesContract.RawData.COLUMN_SCREEN_TITLE,
+                    SearchIndexablesContract.INDEXABLES_RAW_COLUMNS[6]);
+        }
+
+        @SmallTest
+        public void testRawColumns_IncludesClassName() {
+            assertEquals(SearchIndexablesContract.RawData.COLUMN_CLASS_NAME,
+                    SearchIndexablesContract.INDEXABLES_RAW_COLUMNS[7]);
+        }
+
+        @SmallTest
+        public void testRawColumns_IncludesIcon() {
+            assertEquals(SearchIndexablesContract.RawData.COLUMN_ICON_RESID,
+                    SearchIndexablesContract.INDEXABLES_RAW_COLUMNS[8]);
+        }
+
+        @SmallTest
+        public void testRawColumns_IncludesIntentAction() {
+            assertEquals(SearchIndexablesContract.RawData.COLUMN_INTENT_ACTION,
+                    SearchIndexablesContract.INDEXABLES_RAW_COLUMNS[9]);
+        }
+
+        @SmallTest
+        public void testRawColumns_IncludesIntentTargetPackage() {
+            assertEquals(SearchIndexablesContract.RawData.COLUMN_INTENT_TARGET_PACKAGE,
+                    SearchIndexablesContract.INDEXABLES_RAW_COLUMNS[10]);
+        }
+
+        @SmallTest
+        public void testRawColumns_IncludesTargetClass() {
+            assertEquals(SearchIndexablesContract.RawData.COLUMN_INTENT_TARGET_CLASS,
+                    SearchIndexablesContract.INDEXABLES_RAW_COLUMNS[11]);
+        }
+
+        @SmallTest
+        public void testRawColumns_IncludesKey() {
+            assertEquals(SearchIndexablesContract.RawData.COLUMN_KEY,
+                    SearchIndexablesContract.INDEXABLES_RAW_COLUMNS[12]);
+        }
+
+        @SmallTest
+        public void testRawColumns_IncludesUserId() {
+            assertEquals(SearchIndexablesContract.RawData.COLUMN_USER_ID,
+                    SearchIndexablesContract.INDEXABLES_RAW_COLUMNS[13]);
+        }
+
+        @SmallTest
+        public void testRawColumns_IncludesPayloadType() {
+            assertEquals(SearchIndexablesContract.RawData.PAYLOAD_TYPE,
+                    SearchIndexablesContract.INDEXABLES_RAW_COLUMNS[14]);
+        }
+
+        @SmallTest
+        public void testRawColumns_IncludesPayload() {
+            assertEquals(SearchIndexablesContract.RawData.PAYLOAD,
+                    SearchIndexablesContract.INDEXABLES_RAW_COLUMNS[15]);
+        }
+}