Merge "Changes to installed app details screen for instant apps"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 81b2524..10c0bc2 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -727,6 +727,14 @@
                 <category android:name="android.intent.category.DEFAULT" />
                 <category android:name="com.android.settings.SHORTCUT" />
             </intent-filter>
+            <intent-filter android:priority="1">
+                <action android:name="android.settings.ZEN_MODE_AUTOMATION_SETTINGS" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+            <intent-filter android:priority="1">
+                <action android:name="android.settings.ACTION_CONDITION_PROVIDER_SETTINGS" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
             <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
                 android:value="com.android.settings.notification.ZenModeSettings" />
             <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
@@ -759,25 +767,6 @@
                 android:value="true" />
         </activity>
 
-        <activity android:name="Settings$ZenModeAutomationSettingsActivity"
-                android:label="@string/zen_mode_automation_settings_title"
-                android:icon="@drawable/ic_settings_notifications"
-                android:exported="true"
-                android:taskAffinity="">
-            <intent-filter android:priority="1">
-                <action android:name="android.settings.ZEN_MODE_AUTOMATION_SETTINGS" />
-                <category android:name="android.intent.category.DEFAULT" />
-            </intent-filter>
-            <intent-filter android:priority="1">
-                <action android:name="android.settings.ACTION_CONDITION_PROVIDER_SETTINGS" />
-                <category android:name="android.intent.category.DEFAULT" />
-            </intent-filter>
-            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
-                android:value="com.android.settings.notification.ZenModeAutomationSettings" />
-            <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
-                android:value="true" />
-        </activity>
-
         <activity android:name="Settings$ZenModeAutomationSuggestionActivity"
                 android:label="@string/zen_mode_automation_settings_title"
                 android:icon="@drawable/ic_settings_notifications"
diff --git a/res/layout-land/fingerprint_enroll_enrolling.xml b/res/layout-land/fingerprint_enroll_enrolling.xml
index 5c4e99b..b321519 100644
--- a/res/layout-land/fingerprint_enroll_enrolling.xml
+++ b/res/layout-land/fingerprint_enroll_enrolling.xml
@@ -66,14 +66,14 @@
                 android:layout_height="wrap_content">
 
                 <TextView
-                    style="@style/TextAppearance.FingerprintMessage"
+                    style="@style/SuwDescription.Glif"
                     android:id="@+id/start_message"
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
                     android:text="@string/security_settings_fingerprint_enroll_start_message"/>
 
                 <TextView
-                    style="@style/TextAppearance.FingerprintMessage"
+                    style="@style/SuwDescription.Glif"
                     android:id="@+id/repeat_message"
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
diff --git a/res/layout-land/fingerprint_enroll_find_sensor.xml b/res/layout-land/fingerprint_enroll_find_sensor.xml
index 3dadece..a43534f 100644
--- a/res/layout-land/fingerprint_enroll_find_sensor.xml
+++ b/res/layout-land/fingerprint_enroll_find_sensor.xml
@@ -65,7 +65,7 @@
                     android:layout_marginEnd="0dp" />
 
                 <TextView
-                    style="@style/TextAppearance.FingerprintMessage"
+                    style="@style/SuwDescription.Glif"
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
                     android:text="@string/security_settings_fingerprint_enroll_find_sensor_message"/>
diff --git a/res/layout-land/fingerprint_enroll_finish.xml b/res/layout-land/fingerprint_enroll_finish.xml
index 5fc0d73..ca1a2d2 100644
--- a/res/layout-land/fingerprint_enroll_finish.xml
+++ b/res/layout-land/fingerprint_enroll_finish.xml
@@ -42,14 +42,14 @@
 
             <TextView
                 android:id="@+id/message"
-                style="@style/TextAppearance.FingerprintMessage"
+                style="@style/SuwDescription.Glif"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:text="@string/security_settings_fingerprint_enroll_finish_message"/>
 
             <TextView
                 android:id="@+id/message_secondary"
-                style="@style/TextAppearance.FingerprintMessage"
+                style="@style/SuwDescription.Glif"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:layout_marginTop="@dimen/suw_description_glif_margin_top"
diff --git a/res/layout/choose_lock_generic_fingerprint_header.xml b/res/layout/choose_lock_generic_fingerprint_header.xml
index 6a107bf..a92b68f 100644
--- a/res/layout/choose_lock_generic_fingerprint_header.xml
+++ b/res/layout/choose_lock_generic_fingerprint_header.xml
@@ -18,9 +18,9 @@
     android:id="@+id/fingerprint_header_description"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:gravity="center_vertical"
-    android:minHeight="56dp"
     android:paddingStart="?android:attr/listPreferredItemPaddingStart"
     android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+    android:paddingTop="@dimen/suw_description_glif_margin_top"
+    android:paddingBottom="@dimen/suw_description_glif_margin_bottom_lists"
     android:text="@string/lock_settings_picker_fingerprint_message"
-    style="@style/FingerprintHeaderStyle" />
+    style="@style/SuwDescription.Glif" />
diff --git a/res/layout/fingerprint_enroll_enrolling_base.xml b/res/layout/fingerprint_enroll_enrolling_base.xml
index bd1e2c2..7f8eb1b 100644
--- a/res/layout/fingerprint_enroll_enrolling_base.xml
+++ b/res/layout/fingerprint_enroll_enrolling_base.xml
@@ -38,14 +38,14 @@
             android:layout_marginTop="@dimen/suw_description_glif_margin_top">
 
             <TextView
-                style="@style/TextAppearance.FingerprintMessage"
+                style="@style/SuwDescription.Glif"
                 android:id="@+id/start_message"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:text="@string/security_settings_fingerprint_enroll_start_message"/>
 
             <TextView
-                style="@style/TextAppearance.FingerprintMessage"
+                style="@style/SuwDescription.Glif"
                 android:id="@+id/repeat_message"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
diff --git a/res/layout/fingerprint_enroll_find_sensor_base.xml b/res/layout/fingerprint_enroll_find_sensor_base.xml
index d38818b..60c8bc7 100644
--- a/res/layout/fingerprint_enroll_find_sensor_base.xml
+++ b/res/layout/fingerprint_enroll_find_sensor_base.xml
@@ -44,7 +44,7 @@
             android:clipChildren="false">
 
             <TextView
-                style="@style/TextAppearance.FingerprintMessage"
+                style="@style/SuwDescription.Glif"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:layout_marginTop="@dimen/suw_description_glif_margin_top"
diff --git a/res/layout/fingerprint_enroll_finish_base.xml b/res/layout/fingerprint_enroll_finish_base.xml
index 99c96ad..db099c3 100644
--- a/res/layout/fingerprint_enroll_finish_base.xml
+++ b/res/layout/fingerprint_enroll_finish_base.xml
@@ -32,7 +32,7 @@
 
         <TextView
             android:id="@+id/message"
-            style="@style/TextAppearance.FingerprintMessage"
+            style="@style/SuwDescription.Glif"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_marginTop="@dimen/suw_description_glif_margin_top"
@@ -40,7 +40,7 @@
 
         <TextView
             android:id="@+id/message_secondary"
-            style="@style/TextAppearance.FingerprintMessage"
+            style="@style/SuwDescription.Glif"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_marginTop="@dimen/suw_description_glif_margin_top"
diff --git a/res/layout/setup_choose_lock_generic_fingerprint_header.xml b/res/layout/setup_choose_lock_generic_fingerprint_header.xml
index b19bec1..4c696f3 100644
--- a/res/layout/setup_choose_lock_generic_fingerprint_header.xml
+++ b/res/layout/setup_choose_lock_generic_fingerprint_header.xml
@@ -16,14 +16,11 @@
 -->
 
 <TextView xmlns:android="http://schemas.android.com/apk/res/android"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:gravity="center_vertical"
-        android:minHeight="56dp"
-        android:paddingBottom="@dimen/suw_description_glif_margin_bottom_lists"
-        android:paddingStart="?android:attr/listPreferredItemPaddingStart"
-        android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
-        android:paddingTop="@dimen/suw_description_glif_margin_top"
-        android:text="@string/setup_lock_settings_picker_fingerprint_message"
-        android:lineSpacingExtra="@dimen/suw_description_line_spacing_extra"
-        android:textAppearance="?android:attr/textAppearanceListItem" />
+    style="@style/SuwDescription.Glif"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+    android:paddingTop="@dimen/suw_description_glif_margin_top"
+    android:paddingBottom="@dimen/suw_description_glif_margin_bottom_lists"
+    android:text="@string/setup_lock_settings_picker_fingerprint_message" />
diff --git a/res/layout/setup_choose_lock_generic_header.xml b/res/layout/setup_choose_lock_generic_header.xml
index 9a3547d..8875e1f 100644
--- a/res/layout/setup_choose_lock_generic_header.xml
+++ b/res/layout/setup_choose_lock_generic_header.xml
@@ -16,14 +16,11 @@
 -->
 
 <TextView xmlns:android="http://schemas.android.com/apk/res/android"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:gravity="center_vertical"
-        android:minHeight="56dp"
-        android:paddingBottom="@dimen/suw_description_glif_margin_bottom_lists"
-        android:paddingStart="?android:attr/listPreferredItemPaddingStart"
-        android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
-        android:paddingTop="@dimen/suw_description_glif_margin_top"
-        android:text="@string/setup_lock_settings_picker_message"
-        android:lineSpacingExtra="@dimen/suw_description_line_spacing_extra"
-        android:textAppearance="?android:attr/textAppearanceListItem" />
+    style="@style/SuwDescription.Glif"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+    android:paddingTop="@dimen/suw_description_glif_margin_top"
+    android:paddingBottom="@dimen/suw_description_glif_margin_bottom_lists"
+    android:text="@string/setup_lock_settings_picker_message" />
diff --git a/res/values/strings.xml b/res/values/strings.xml
index a194442..c5a233b 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1612,8 +1612,6 @@
     <string name="wifi_starting">Turning Wi\u2011Fi on\u2026</string>
     <!-- Summary text when turning Wi-Fi or bluetooth off -->
     <string name="wifi_stopping">Turning off Wi\u2011Fi\u2026</string>
-    <!-- Title of Button to show all Wi-Fi networks in the picker. [CHAR LIMIT=30] -->
-    <string name="wifi_see_all_networks_button_title">See all networks</string>
     <!-- Summary text when Wi-Fi or bluetooth has error -->
     <string name="wifi_error">Error</string>
     <!-- Summary text when wifi SoftAP started failed due to no legal usable channel allowed in this region by regulatory -->
@@ -2249,11 +2247,44 @@
     <string name="auto_brightness_title">Adaptive brightness</string>
     <!-- Sound & display settings screen, setting option summary to enable adaptive brightness [CHAR LIMIT=100] -->
     <string name="auto_brightness_summary">Optimize brightness level for available light</string>
+    <!-- Sound & display settings screen, setting option summary when adaptive brightness is off [CHAR LIMIT=100] -->
+    <string name="auto_brightness_summary_off">Off</string>
+    <!-- Sound & display settings screen, setting option summary when preferred adaptive brightness is very low [CHAR LIMIT=100] -->
+    <string name="auto_brightness_summary_very_low">Preferred brightness is very low</string>
+    <!-- Sound & display settings screen, setting option summary when preferred adaptive brightness is low [CHAR LIMIT=100] -->
+    <string name="auto_brightness_summary_low">Preferred brightness is low</string>
+    <!-- Sound & display settings screen, setting option summary when preferred adaptive brightness is the default [CHAR LIMIT=100] -->
+    <string name="auto_brightness_summary_default">Preferred brightness is default</string>
+    <!-- Sound & display settings screen, setting option summary when preferred adaptive brightness is high [CHAR LIMIT=100] -->
+    <string name="auto_brightness_summary_high">Preferred brightness is high</string>
+    <!-- Sound & display settings screen, setting option summary when preferred adaptive brightness is very high [CHAR LIMIT=100] -->
+    <string name="auto_brightness_summary_very_high">Preferred brightness is very high</string>
+    <!-- Adaptive brightness settings screen, setting option to disable adaptive brightness [CHAR LIMIT=100] -->
+    <string name="auto_brightness_off_title">Off</string>
+    <!-- Adaptive brightness settings screen, setting option to enable adaptive brightness when user prefers very low brightness [CHAR LIMIT=100] -->
+    <string name="auto_brightness_very_low_title">Very low</string>
+    <!-- Adaptive brightness settings screen, setting option to enable adaptive brightness when user prefers low brightness [CHAR LIMIT=100] -->
+    <string name="auto_brightness_low_title">Low</string>
+    <!-- Adaptive brightness settings screen, setting option to enable adaptive brightness when user prefers default brightness [CHAR LIMIT=100] -->
+    <string name="auto_brightness_default_title">Default</string>
+    <!-- Adaptive brightness settings screen, setting option to enable adaptive brightness when user prefers high brightness [CHAR LIMIT=100] -->
+    <string name="auto_brightness_high_title">High</string>
+    <!-- Adaptive brightness settings screen, setting option to enable adaptive brightness when user prefers very high brightness [CHAR LIMIT=100] -->
+    <string name="auto_brightness_very_high_title">Very high</string>
+    <!-- Adaptive brightness settings screen, subtitle [CHAR LIMIT=100] -->
+    <string name="auto_brightness_subtitle">Your preferred brightness level</string>
+    <!-- Adaptive brightness settings screen, setting option summary to disable adaptive brightness [CHAR LIMIT=100] -->
+    <string name="auto_brightness_off_summary">Don\'t adjust for available light</string>
+    <!-- Adaptive brightness settings screen, setting option summary to enable adaptive brightness when user prefers very high brightness.
+         Meant to make it clear that preferring very high brightness uses more battery. [CHAR LIMIT=100] -->
+    <string name="auto_brightness_very_high_summary">Increased battery usage</string>
+    <!-- Adaptive brightness settings screen, disclaimer that explains in more detail about how adaptive brightness works [CHAR LIMIT=100] -->
+    <string name="auto_brightness_disclaimer">Optimize brightness level for available light. When this feature is on, you can still adjust brightness temporarily.</string>
 
-    <!-- Night display screen, setting option name to enable night display (renamed "Night Light" with title caps). [CHAR LIMIT=30] -->
-    <string name="night_display_title">Night Light</string>
-    <!-- Night display screen, description of night display feature (renamed "Night Light" with title caps). [CHAR LIMIT=NONE] -->
-    <string name="night_display_text">Night Light tints your screen amber. This makes it easier to look at your screen or read in dim light, and may help you fall asleep more easily.</string>
+    <!-- Night display screen, setting option name to enable night display. [CHAR LIMIT=30] -->
+    <string name="night_display_title">Night display</string>
+    <!-- Night display screen, description of night display feature. [CHAR LIMIT=NONE] -->
+    <string name="night_display_text">Night display tints your screen amber. This makes it easier to look at your screen or read in dim light, and may help you fall asleep more easily.</string>
     <!-- Night display screen, category title for settings to schedule when night display activates automatically. [CHAR LIMIT=30] -->
     <string name="night_display_category_schedule">Schedule</string>
     <!-- Night display screen, category title for settings to manually activate night display. [CHAR LIMIT=30] -->
@@ -2310,19 +2341,21 @@
     <!-- Display settings screen, trigger for screen saver options -->
     <string name="screensaver_settings_title">Screen saver</string>
     <!-- Display settings screen, summary fragment for screen saver options, activated when docked or asleep and charging -->
-    <string name="screensaver_settings_summary_either_long">When docked or asleep and charging</string>
+    <string name="screensaver_settings_summary_either_long">While charging or docked</string>
     <!-- Dream settings screen, dialog option, activated when docked or asleep and charging -->
     <string name="screensaver_settings_summary_either_short">Either</string>
     <!-- Display settings screen, summary fragment for screen saver options, activated when asleep and charging -->
     <string name="screensaver_settings_summary_sleep">While charging</string>
     <!-- Display settings screen, summary fragment for screen saver options, activated when docked  -->
     <string name="screensaver_settings_summary_dock">While docked</string>
+    <!-- Display settings screen, summary fragment for screen saver options, activated never  -->
+    <string name="screensaver_settings_summary_never">Never</string>
     <!-- Display settings screen, summary for screen saver options, screen saver is turned off -->
     <string name="screensaver_settings_summary_off">Off</string>
     <!-- Dream settings screen, caption for when dreams are disabled -->
     <string name="screensaver_settings_disabled_prompt">To control what happens when the phone is docked and/or sleeping, turn screen saver on.</string>
     <!-- Dream settings screen, action label, when to dream -->
-    <string name="screensaver_settings_when_to_dream">When to start screen saver</string>
+    <string name="screensaver_settings_when_to_dream">When to start</string>
     <!-- Dream settings screen, button label to start dreaming -->
     <string name="screensaver_settings_dream_start">Start now</string>
     <!-- Dream settings screen, button label for settings for a specific screensaver -->
@@ -2936,6 +2969,10 @@
     <!-- APNs screen toast message to inform reset default APN settings is completed -->
     <string name="restore_default_apn_completed">Reset default APN settings completed.</string>
 
+
+    <!-- Title for a screen containing all device reset options [CHAR LIMIT=50] -->
+    <string name="reset_dashboard_title">Reset</string>
+
     <!-- Reset Network -->
     <!-- SD card & phone storage settings screen, setting option name under Backup & Restore heading -->
     <string name="reset_network_title">Network settings reset</string>
@@ -2957,6 +2994,12 @@
     <!-- Master Clear -->
     <!-- SD card & phone storage settings screen, setting option name under Internal phone storage heading -->
     <string name="master_clear_title">Factory data reset</string>
+    <!-- Summary text for factory data reset describing what will be reset [CHAR_LIMIT=NONE]-->
+    <plurals name="master_clear_with_account_summary">
+        <item quantity="one">1 account will be reset</item>
+        <item quantity="other"><xliff:g id="account_count">%1$d</xliff:g> accounts will be reset</item>
+    </plurals>
+    <string name="master_clear_summary">Internal storage &amp; all data will be reset</string>
     <!-- SD card & phone storage settings screen, message on screen after user selects Factory data reset [CHAR LIMIT=NONE] -->
     <string name="master_clear_desc" product="tablet">"This will erase all data from your tablet\u2019s <b>internal storage</b>, including:\n\n<li>Your Google account</li>\n<li>System and app data and settings</li>\n<li>Downloaded apps</li>"</string>
     <!-- SD card & phone storage settings screen, message on screen after user selects Factory data reset [CHAR LIMIT=NONE] -->
@@ -3462,11 +3505,11 @@
     <!-- Manage applications, individual application info screen,label under Storage heading.  The total storage space taken up by this app. -->
     <string name="total_size_label">Total</string>
     <!-- Manage applications, individual application info screen, label under Storage heading. The amount of space taken up by the application itself (for example, the java compield files and things like that) -->
-    <string name="application_size_label">App</string>
+    <string name="application_size_label">App size</string>
     <!--  Manage applications, individual application info screen, label under Storage heading.  The amount of space taken up by the app's code on USB storage [CHARSIZE=40] -->
     <string name="external_code_size_label">USB storage app</string>
     <!-- Manage applications, individual application info screen, label under Storage heading.  The amount of sapce taken up by the app's data (for example, downloaded emails or something like that) -->
-    <string name="data_size_label">Data</string>
+    <string name="data_size_label">User data</string>
     <!--  Manage applications, individual application info screen, label under Storage heading.  The amount of space taken up by the app's data on USB storage [CHARSIZE=40] -->
     <string name="external_data_size_label" product="nosdcard">USB storage data</string>
     <!--  Manage applications, individual application info screen, label under Storage heading.  The amount of space taken up by the app's data on the SD card [CHARSIZE=40] -->
@@ -3859,7 +3902,7 @@
     <!-- Title for the 'keyboard and input methods' preference category. [CHAR LIMIT=45] -->
     <string name="keyboard_and_input_methods_category">Keyboard &amp; inputs</string>
     <!-- Title for the 'virtual keyboard' preference sub-screen. [CHAR LIMIT=35] -->
-    <string name="virtual_keyboard_category">Virtual keyboards</string>
+    <string name="virtual_keyboard_category">Virtual keyboard</string>
     <!-- Title for the 'available virtual keyboard' preference sub-screen. [CHAR LIMIT=35] -->
     <string name="available_virtual_keyboard_category">Available virtual keyboard</string>
     <!-- Title for the button to trigger the 'Manage keyboards' preference sub-screen, where the user can turn on/off installed virtual keyboards.[CHAR LIMIT=35] -->
@@ -4083,6 +4126,8 @@
     <string name="accessibility_screen_magnification_gestures_title">Magnify with triple-tap</string>
     <!-- Title for the accessibility preference screen to enable navigation bar screen magnification. [CHAR LIMIT=35] -->
     <string name="accessibility_screen_magnification_navbar_title">Magnify with button</string>
+    <!-- Summary for the accessibility magnification setting indicating both "Magnify with button" and "Magnify with triple-tap" are enabled [CHAR LIMIT=50] -->
+    <string name="accessibility_screen_magnification_state_navbar_gesture">Magnify with button &amp; triple-tap</string>
     <!-- Summary for the accessibility preference to enable screen magnification. [CHAR LIMIT=25] -->
     <string name="accessibility_preference_magnification_summary">Zoom in on screen</string>
     <!-- Short summary for Magnification gesture. Tells the user that this feature allows the user to magnify the screen by tapping 3 times. Appears in accessibility portion of setup wizard -->
@@ -4090,13 +4135,19 @@
     <!-- Short summary for nav bar Magnification. Tells the user that this feature allows the user to magnify the screen using a button in the nav bar -->
     <string name="accessibility_screen_magnification_navbar_short_summary">Tap a button to zoom</string>
     <!-- Summary for the accessibility preference screen to enable screen magnification gestures. [CHAR LIMIT=none] -->
-    <string name="accessibility_screen_magnification_summary"><b>To zoom</b>, quickly tap the screen 3 times with one finger.\n<ul><li>Drag 2 or more fingers to scroll</li>\n<li>Pinch 2 or more fingers together or apart to adjust zoom</li></ul>\n\n<b>To zoom temporarily</b>, quickly tap the screen 3 times and hold down your finger on the third tap.\n<ul><li>Drag your finger to move around the screen</li>\n<li>Lift your finger to zoom out</li></ul>\n\nYou can\'t zoom in on the keyboard and navigation bar.</string>
+    <string name="accessibility_screen_magnification_summary"><b>To zoom</b>, quickly tap the screen 3 times.\n<ul><li>Drag 2 or more fingers to scroll</li>\n<li>Pinch 2 or more fingers to adjust zoom</li></ul>\n\n<b>To zoom temporarily</b>, quickly tap the screen 3 times and hold down your finger on the third tap.\n<ul><li>Drag to move around the screen</li>\n<li>Lift finger to zoom out</li></ul>\n\nYou can\'t zoom in on the keyboard and navigation bar.</string>
     <!-- Summary for the accessibility preference screen to enable screen magnification via the nav bar. [CHAR LIMIT=none] -->
     <string name="accessibility_screen_magnification_navbar_summary">When magnification is turned on, use the Accessibility button at the bottom of the screen to quickly magnify.\n\n<b>To zoom</b>, tap the Accessibility button, then tap anywhere on the screen.\n<ul><li>Drag 2 or more fingers to scroll</li>\n<li>Pinch 2 or more fingers to adjust zoom</li></ul>\n\n<b>To zoom temporarily</b>, tap the Accessibility button, then touch &amp; hold anywhere on the screen.\n<ul><li>Drag to move around the screen</li>\n<li>Lift finger to zoom out</li></ul>\n\nYou can’t zoom in on the keyboard or navigation bar.</string>
     <!-- Summary text appearing on the accessibility preference screen to enable screen magnification from the nav bar when the feature is enabled, but the accessibility button is not configured correctly for the feature to be used [CHAR LIMIT=none] -->
     <string name="accessibility_screen_magnification_navbar_configuration_warning">The Accessibility button is set to <xliff:g id="service" example="Select to Speak">%1$s</xliff:g>. To use magnification, touch &amp; hold the Accessibility button, then select magnification.</string>
-    <!-- Title for the preference to enable the global geture that turns on accessibility. [CHAR LIMIT=35] -->
+    <!-- Title for the preference to configure the accessibility shortcut. [CHAR LIMIT=35] -->
     <string name="accessibility_global_gesture_preference_title">Accessibility shortcut</string>
+    <!-- Title for the preference to choose the service that is turned on and off by the accessibility shortcut. [CHAR LIMIT=35] -->
+    <string name="accessibility_shortcut_service_title">Shortcut service</string>
+    <!-- Title for the switch preference that controls whether or not the accessibility shortcut works on the lock screen. [CHAR LIMIT=35] -->
+    <string name="accessibility_shortcut_service_on_lock_screen_title">Allow from lock screen</string>
+    <!-- Description of accessibility shortcut. [CHAR LIMIT=NONE] -->
+    <string name="accessibility_shortcut_description">When the shortcut is on, you can press both volume buttons for 3 seconds to start an accessibility feature.</string>
     <!-- Title for the accessibility preference to high contrast text. [CHAR LIMIT=35] -->
     <string name="accessibility_toggle_high_text_contrast_preference_title">High contrast text</string>
     <!-- Title for the accessibility preference to auto update screen magnification. [CHAR LIMIT=35] -->
@@ -4124,6 +4175,13 @@
     <!-- Title for accessibility preference for configuring amount of time that has to pass after pointer stops moving before click action can be performed (if automatic click after pointer stops moving feature is enabled). [CHAR LIMIT=NONE] -->
     <string name="accessibility_autoclick_delay_preference_title">Delay before click</string>
 
+    <!-- Summary text for accessibility service preferences, or preferences including a short description (eg. "ON / High accuracy mode"). -->
+    <string name="accessibility_summary_default_combination"><xliff:g id="state" example="ON">%1$s</xliff:g> / <xliff:g id="description" example="High accuracy mode">%2$s</xliff:g></string>
+    <!-- Preference's state when enabled. Note: UPPERCASE -->
+    <string name="accessibility_summary_state_enabled">ON</string>
+    <!-- Preference's state when disabled. Note: UPPERCASE -->
+    <string name="accessibility_summary_state_disabled">OFF</string>
+
     <!-- Title for the preference to show a tile for a particular feature in the Quick Settings pane. [CHAR LIMIT=NONE] -->
     <string name="enable_quick_setting">Show in Quick Settings</string>
     <!-- Title for the preference to configure the type of color space correction to apply. [CHAR LIMIT=NONE] -->
@@ -4280,6 +4338,9 @@
     <!-- Title for the prompt shown as a placeholder if no accessibility services are installed. [CHAR LIMIT=50] -->
     <string name="accessibility_no_services_installed">No services installed</string>
 
+    <!-- Title for the acccessibility shortcut's summary if no service is selected for use with the shortcut. [CHAR LIMIT=50] -->
+    <string name="accessibility_no_service_selected">No service selected</string>
+
     <!-- Default description for an accessibility service if the latter doesn't provide one. [CHAR LIMIT=NONE] -->
     <string name="accessibility_service_default_description">No description provided.</string>
 
@@ -4393,18 +4454,26 @@
     <string name="background_activity_title">Background activity</string>
     <!-- Summary for the background activity [CHAR_LIMIT=120] -->
     <string name="background_activity_summary">Allow the app to run in the background</string>
+    <!-- Summary for the background activity when it is on [CHAR_LIMIT=120] -->
+    <string name="background_activity_summary_on">App can run in the background when not in use</string>
+    <!-- Summary for the background activity when it is off [CHAR_LIMIT=120] -->
+    <string name="background_activity_summary_off">App\'s background activity is limited when not in use</string>
+    <!-- Summary for the background activity when it is disabled [CHAR_LIMIT=120] -->
+    <string name="background_activity_summary_disabled">App not allowed to run in background</string>
 
     <!-- Title for the screen usage in power use UI [CHAR_LIMIT=40] -->
-    <string name="device_screen_usage">Screen usage</string>
+    <string name="device_screen_usage">Screen usage since full charge</string>
     <!-- Title for the screen consumption in power use UI(i.e. Screen consumption: 30% of battery usage) [CHAR_LIMIT=40] -->
     <string name="device_screen_consumption">Screen consumption</string>
     <!-- Title for the cellular network in power use UI(i.e. Mobile network scanning: 30% of battery usage) [CHAR_LIMIT=40] -->
     <string name="device_cellular_network">Mobile network scanning</string>
 
     <!-- Label for list of apps using battery in power use UI [CHAR_LIMIT=60] -->
-    <string name="power_usage_list_summary">App usage since last full charge</string>
+    <string name="power_usage_list_summary">App usage since full charge</string>
+    <!-- Description for the screen usage item [CHAR_LIMIT=120] -->
+    <string name="screen_usage_summary">Amount of time screen has been on since full charge</string>
     <!-- Label for list of different types using battery in power use UI [CHAR_LIMIT=60] -->
-    <string name="device_usage_list_summary">Device usage since last full charge</string>
+    <string name="device_usage_list_summary">Device usage since full charge</string>
     <!-- Battery usage since unplugged -->
     <string name="battery_since_unplugged">Battery use since unplugged</string>
     <!-- Battery usage since user reset the stats -->
@@ -4444,7 +4513,7 @@
     <string name="history_details_title">History details</string>
 
     <!-- Activity title for battery usage details for an app. or power consumer -->
-    <string name="details_title">Use details</string>
+    <string name="battery_details_title">Battery usage</string>
     <!-- Subtitle for application/subsystem details -->
     <string name="details_subtitle">Use details</string>
     <!-- Subtitle for possible options -->
@@ -4601,19 +4670,37 @@
 
     <!-- Description for battery usage time for an app, i.e. Used for 30min. [CHAR LIMIT=60] -->
     <string name="battery_used_for">Used for %1$s</string>
+    <!-- Description for battery usage info for an app, i.e. 60% used by facebook. [CHAR LIMIT=60] -->
+    <string name="battery_used_by"><xliff:g id="percent">%1$s</xliff:g> used by <xliff:g id="app">%2$s</xliff:g></string>
     <!-- Description for percentage of battery usage for an app, i.e. Screen: 30% of overall battery. [CHAR LIMIT=60] -->
-    <string name="battery_overall_usage">%1$s of overall battery</string>
+    <string name="battery_overall_usage"><xliff:g id="percent">%1$s</xliff:g> of overall battery</string>
     <!-- Description for battery usage detail information since last full charge. [CHAR LIMIT=120] -->
-    <string name="battery_detail_since_full_charge">Usage breakdown since last full charge</string>
+    <string name="battery_detail_since_full_charge">Breakdown since last full charge</string>
+    <!-- Title for usage time since last full charge. [CHAR LIMIT=60] -->
+    <string name="battery_last_full_charge">Last full charge</string>
+    <!-- Description for text in battery footer. [CHAR LIMIT=120] -->
+    <string name="battery_footer_summary">Remaining battery time is approximate and can change based on usage</string>
+    <!-- Title for battery usage detail in foreground. [CHAR LIMIT=80] -->
+    <string name="battery_detail_foreground">While using app</string>
+    <!-- Title for battery usage detail in background. [CHAR LIMIT=80] -->
+    <string name="battery_detail_background">While in background</string>
+    <!-- Title for battery usage amount by this app. [CHAR LIMIT=80] -->
+    <string name="battery_detail_power_usage">Battery usage</string>
+    <!-- Description for battery usage amount, i.e. 16% of overall app usage(340 mAh). [CHAR LIMIT=120] -->
+    <string name="battery_detail_power_percentage"><xliff:g id="percent">%1$s</xliff:g> of total app usage (<xliff:g id="power">%2$d</xliff:g>mAh)</string>
+    <!-- Title for the battery usage group, which means all the battery data are calculated 'since full charge' [CHAR LIMIT=40] -->
+    <string name ="battery_detail_info_title">Since full charge</string>
+    <!-- Title for the battery management group [CHAR LIMIT=40] -->
+    <string name ="battery_detail_manage_title">Manage battery usage</string>
 
     <!-- Description for battery time left, i.e. 50min Estimated time left. [CHAR LIMIT=80]-->
     <string name="estimated_time_left">Estimated time left</string>
 
-    <!-- Description for charging time left, i.e. 50min Time to full charge. [CHAR LIMIT=80]-->
-    <string name="estimated_charging_time_left">Time to full charge</string>
+    <!-- Description for charging time left, i.e. 50min until fully charged [CHAR LIMIT=80]-->
+    <string name="estimated_charging_time_left">Until fully charged</string>
 
     <!-- Description for estimated time. [CHAR LIMIT=80]-->
-    <string name="estimated_time_description">Estimation may change based on usage</string>
+    <string name="estimated_time_description">Estimate may change based on usage</string>
 
     <!-- Menu label for viewing battery usage since unplugged -->
     <string name="menu_stats_unplugged"><xliff:g id="unplugged">%1$s</xliff:g> since unplugged</string>
@@ -5486,16 +5573,26 @@
     <string name="vpn_no_ca_cert">(don\u2019t verify server)</string>
     <!-- Option to use the server certificate received from the VPN server. [CHAR LIMIT=40] -->
     <string name="vpn_no_server_cert">(received from server)</string>
-    <!-- Reason for Always-on VPN checkbox being disabled: the selected VPN type doesn't support always-on. [CHAR LIMIT=120] -->
-    <string name="vpn_always_on_invalid_reason_type">The selected VPN type can\u2019t be always on</string>
-    <!-- Reason for Always-on VPN checkbox being disabled: the server address is invalid. [CHAR LIMIT=120] -->
-    <string name="vpn_always_on_invalid_reason_server">Always-on VPN only supports numeric server addresses</string>
-    <!-- Reason for Always-on VPN checkbox being disabled: no DNS is found. [CHAR LIMIT=120] -->
-    <string name="vpn_always_on_invalid_reason_no_dns">A DNS server must be specified for always-on VPN</string>
-    <!-- Reason for Always-on VPN checkbox being disabled: DNS server addresses are invalid. [CHAR LIMIT=120] -->
-    <string name="vpn_always_on_invalid_reason_dns">DNS server addresses must be numeric for always-on VPN</string>
-    <!-- Reason for Always-on VPN checkbox being disabled: generic reason. [CHAR LIMIT=120] -->
-    <string name="vpn_always_on_invalid_reason_other">The information entered doesn\u2019t support always-on VPN</string>
+    <!-- Error message displayed below the always-on VPN checkbox when the checkbox is disabled:
+        the selected VPN type doesn't support always-on. [CHAR LIMIT=120] -->
+    <string name="vpn_always_on_invalid_reason_type">This VPN type can\'t stay connected at all
+        times</string>
+    <!-- Error message displayed below the always-on VPN checkbox when the checkbox is disabled:
+        the server address is not in numeric form (e.g. 8.8.8.8). [CHAR LIMIT=120] -->
+    <string name="vpn_always_on_invalid_reason_server">Always-on VPN only supports numeric server
+        addresses</string>
+    <!-- Error message displayed below the always-on VPN checkbox when the checkbox is disabled:
+        no DNS is found. [CHAR LIMIT=120] -->
+    <string name="vpn_always_on_invalid_reason_no_dns">A DNS server must be specified for always-on
+        VPN</string>
+    <!-- Error message displayed below the always-on VPN checkbox when the checkbox is disabled:
+        DNS server addresses are not in numeric form (e.g. 8.8.8.8). [CHAR LIMIT=120] -->
+    <string name="vpn_always_on_invalid_reason_dns">DNS server addresses must be numeric for
+        always-on VPN</string>
+    <!-- Error message displayed below the always-on VPN checkbox when the checkbox is disabled:
+        generic error. [CHAR LIMIT=120] -->
+    <string name="vpn_always_on_invalid_reason_other">The information entered doesn\'t support
+        always-on VPN</string>
 
     <!-- Button label to cancel changing a VPN profile. [CHAR LIMIT=40] -->
     <string name="vpn_cancel">Cancel</string>
@@ -5551,20 +5648,16 @@
     <string name="vpn_menu_lockdown">Always-on VPN</string>
     <!-- Placeholder when VPN settings is open but no VPNs have been created. [CHAR LIMIT=100] -->
     <string name="vpn_no_vpns_added">No VPNs added</string>
-    <!-- Preference summary for active always-on vpn [CHAR LIMIT=40] -->
-    <string name="vpn_always_on_active">Always-on active</string>
-    <!-- Preference summary for inactive always-on vpn [CHAR LIMIT=40] -->
-    <string name="vpn_always_on_inactive">Always-on inactive</string>
-    <!-- Preference summary for app not supporting always-on vpn [CHAR LIMIT=NONE] -->
-    <string name="vpn_not_supported_by_this_app">Not supported by this app</string>
-    <!-- Preference title for forcing all network connections to go through VPN. -->
-    <string name="vpn_require_connection">Only allow connections through VPN</string>
-    <!-- Dialog message title to confirm forcing all network connections to go through VPN. [CHAR LIMIT=40] -->
+    <!-- Preference summary for always-on VPN checkbox. [CHAR LIMIT=40] -->
+    <string name="vpn_always_on_summary">Stay connected to VPN at all times</string>
+    <!-- Preference summary for app not supporting always-on VPN [CHAR LIMIT=40] -->
+    <string name="vpn_always_on_summary_not_supported">Not supported by this app</string>
+    <!-- Preference title for the toggle that controls whether to force all network connections to
+        go through VPN. [CHAR LIMIT=40] -->
+    <string name="vpn_require_connection">Block connections without VPN</string>
+    <!-- Dialog message title to confirm forcing all network connections to go through VPN.
+        [CHAR LIMIT=40] -->
     <string name="vpn_require_connection_title">Require VPN connection?</string>
-    <!-- Preference summary when the preference to force all network connections to go through a VPN is enabled, blocking all other network traffic. In this case apps must use the VPN for all connections. -->
-    <string name="vpn_lockdown_active">Lockdown active</string>
-    <!-- Preference summary when the preference to force all network connections to go through a VPN is disabled. In this case use of the VPN is optional for apps. -->
-    <string name="vpn_lockdown_inactive">Lockdown inactive</string>
 
     <!-- Summary describing the always-on VPN feature. [CHAR LIMIT=NONE] -->
     <string name="vpn_lockdown_summary">Select a VPN profile to always remain connected to. Network traffic will only be allowed when connected to this VPN.</string>
@@ -6320,19 +6413,19 @@
     </plurals>
 
     <!-- Sound: Title for the Do not Disturb option and associated settings page. [CHAR LIMIT=50]-->
-    <string name="zen_mode_settings_title">Do Not Disturb</string>
+    <string name="zen_mode_settings_title">Do Not Disturb preferences</string>
 
     <!-- Do not disturb: Title for the Priority interruptions option and associated settings page. [CHAR LIMIT=30] -->
     <string name="zen_mode_priority_settings_title">Priority only allows</string>
 
-    <!--  Do not disturb: Title for the zen mode automation option and associated settings page. [CHAR LIMIT=30] -->
+    <!--  Do not disturb: Title for the zen mode automation listing. [CHAR LIMIT=30] -->
     <string name="zen_mode_automation_settings_title">Automatic rules</string>
 
     <!--  Do not disturb: Title for the zen mode automation option Suggestion. [CHAR LIMIT=30] -->
-    <string name="zen_mode_automation_suggestion_title">Set Do Not Disturb schedule</string>
+    <string name="zen_mode_automation_suggestion_title">Set Do Not Disturb rules</string>
 
     <!--  Do not disturb: Summary for the zen mode automation option Suggestion. [CHAR LIMIT=30] -->
-    <string name="zen_mode_automation_suggestion_summary">Silence your device at certain times</string>
+    <string name="zen_mode_automation_suggestion_summary">Limit sounds &amp; vibrations at certain times</string>
 
     <!--  Do not disturb: Zen mode option: Important interruptions [CHAR LIMIT=60] -->
     <string name="zen_mode_option_important_interruptions">Priority only</string>
@@ -7647,7 +7740,10 @@
     <string name="apps_summary_example">24 apps installed</string>
 
     <!-- Summary of storage usage [CHAR LIMIT=NONE] -->
-    <string name="storage_summary">Internal storage: <xliff:g id="percentage" example="54%">%1$s</xliff:g> used - <xliff:g id="free_space" example="32GB">%2$s</xliff:g> free</string>
+    <string name="storage_summary"><xliff:g id="percentage" example="54%">%1$s</xliff:g> used - <xliff:g id="free_space" example="32GB">%2$s</xliff:g> free</string>
+
+    <!-- Summary of storage usage when there is SD card [CHAR LIMIT=NONE] -->
+    <string name="storage_summary_with_sdcard">Internal storage: <xliff:g id="percentage" example="54%">%1$s</xliff:g> used - <xliff:g id="free_space" example="32GB">%2$s</xliff:g> free</string>
 
     <!-- Summary of display with screen sleep timeout [CHAR LIMIT=NONE] -->
     <string name="display_summary">Sleep after <xliff:g id="timeout_description" example="10 minutes">%1$s</xliff:g> of inactivity</string>
@@ -7761,10 +7857,16 @@
     <!-- Summary of condition that work mode is off [CHAR LIMIT=NONE] -->
     <string name="condition_work_summary">Apps, background sync, and other features related to your work profile are turned off.</string>
 
-    <!-- Title of condition that night display is on (renamed "Night Light" with title caps) [CHAR LIMIT=30] -->
-    <string name="condition_night_display_title">Night Light is on</string>
+    <!--  Night display: Title for the night display option Suggestion. [CHAR LIMIT=NONE] -->
+    <string name="night_display_suggestion_title">Set night display schedule</string>
 
-    <!-- Summary of condition that night display is on (renamed "Night Light" with title caps) [CHAR LIMIT=NONE] -->
+    <!--  Night display: Summary for the night display option Suggestion. [CHAR LIMIT=30] -->
+    <string name="night_display_suggestion_summary">Tint screen amber to help you fall asleep</string>
+
+    <!-- Title of condition that night display is on [CHAR LIMIT=30] -->
+    <string name="condition_night_display_title">Night display is on</string>
+
+    <!-- Summary of condition that night display is on [CHAR LIMIT=NONE] -->
     <string name="condition_night_display_summary">Screen is tinted amber. This may help you fall asleep.</string>
 
     <!-- Title for the suggestions section on the dashboard [CHAR LIMIT=30] -->
@@ -8537,4 +8639,10 @@
     <!-- Warning for when the automatic storage manager is turned off. [CHAR LIMIT=NONE] -->
     <string name="automatic_storage_manager_deactivation_warning">Turn off the storage manager?</string>
 
+    <!-- Preference label for the Movies & TV apps section [CHAR LIMIT=50] -->
+    <string name="storage_movies_tv">Movie &amp; TV apps</string>
+
+    <!-- Title for the installed app info storage page. The total storage space taken up by this app. [CHAR LIMIT=40]-->
+    <string name="app_info_storage_title">Space used</string>
+
 </resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 0cb2249..e9d25ff 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -319,22 +319,6 @@
         <item name="android:textSize">14sp</item>
     </style>
 
-    <style name="TextAppearance.FingerprintMessage"
-        parent="android:TextAppearance.Material.Subhead">
-        <item name="android:lineSpacingExtra">@dimen/suw_description_line_spacing_extra</item>
-    </style>
-
-    <style name="Button.FingerprintButton"
-        parent="android:Widget.Material.Button.Borderless">
-        <item name="android:lineSpacingExtra">@dimen/suw_description_line_spacing_extra</item>
-        <item name="android:textColor">?android:attr/colorAccent</item>
-    </style>
-
-    <style name="TextAppearance.FingerprintLink"
-           parent="TextAppearance.FingerprintMessage">
-        <item name="android:textColor">?android:attr/colorAccent</item>
-    </style>
-
     <style name="TextAppearance.FingerprintErrorText"
         parent="android:TextAppearance.Material.Body1">
         <item name="android:textColor">?android:attr/colorError</item>
diff --git a/res/xml/accessibility_settings.xml b/res/xml/accessibility_settings.xml
index 065ead1..48e11af 100644
--- a/res/xml/accessibility_settings.xml
+++ b/res/xml/accessibility_settings.xml
@@ -18,8 +18,9 @@
         android:title="@string/accessibility_settings"
         android:persistent="true">
 
-    <ListPreference
+    <Preference
             android:key="accessibility_shortcut_preference"
+            android:fragment="com.android.settings.accessibility.AccessibilityShortcutPreferenceFragment"
             android:title="@string/accessibility_global_gesture_preference_title"/>
 
     <PreferenceCategory
diff --git a/res/xml/accessibility_shortcut_settings.xml b/res/xml/accessibility_shortcut_settings.xml
new file mode 100644
index 0000000..1245050
--- /dev/null
+++ b/res/xml/accessibility_shortcut_settings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+                  android:title="@string/accessibility_global_gesture_preference_title" >
+
+    <Preference
+            android:key="accessibility_shortcut_service"
+            android:title="@string/accessibility_shortcut_service_title"
+            android:fragment="com.android.settings.accessibility.ShortcutServicePickerFragment"/>
+
+    <SwitchPreference
+            android:key="accessibility_shortcut_on_lock_screen"
+            android:title="@string/accessibility_shortcut_service_on_lock_screen_title"/>
+</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/display_settings.xml b/res/xml/display_settings.xml
index c5e5e93..71825b1 100644
--- a/res/xml/display_settings.xml
+++ b/res/xml/display_settings.xml
@@ -24,7 +24,7 @@
         android:key="brightness"
         android:title="@string/brightness"
         settings:keywords="@string/keywords_display_brightness_level">
-        <intent android:action="android.intent.action.SHOW_BRIGHTNESS_DIALOG" />
+        <intent android:action="com.android.intent.action.SHOW_BRIGHTNESS_DIALOG" />
     </Preference>
 
     <com.android.settingslib.RestrictedPreference
diff --git a/res/xml/language_and_input.xml b/res/xml/language_and_input.xml
index 79f441f..17bd576 100644
--- a/res/xml/language_and_input.xml
+++ b/res/xml/language_and_input.xml
@@ -28,10 +28,13 @@
     <PreferenceCategory
         android:title="@string/keyboard_and_input_methods_category">
         <Preference
+            android:key="virtual_keyboard_pref"
             android:title="@string/virtual_keyboard_category"
             android:fragment="com.android.settings.inputmethod.VirtualKeyboardFragment"/>
         <Preference
+            android:key="physical_keyboard_pref"
             android:title="@string/physical_keyboard_title"
+            android:summary="@string/summary_placeholder"
             android:fragment="com.android.settings.inputmethod.PhysicalKeyboardFragment"/>
     </PreferenceCategory>
 
diff --git a/res/xml/power_usage_detail_ia.xml b/res/xml/power_usage_detail_ia.xml
new file mode 100644
index 0000000..cfaa712
--- /dev/null
+++ b/res/xml/power_usage_detail_ia.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2017 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <com.android.settings.applications.LayoutPreference
+        android:key="header_view"
+        android:layout="@layout/app_details"
+        android:selectable="false"
+        android:order="-10000"/>
+
+    <com.android.settings.applications.LayoutPreference
+        android:key="action_buttons"
+        android:layout="@layout/app_action_buttons"
+        android:selectable="false"
+        android:order="-9999"/>
+
+    <PreferenceCategory
+        android:title="@string/battery_detail_info_title">
+
+        <Preference
+            android:key="app_usage_foreground"
+            android:title="@string/battery_detail_foreground"/>
+
+        <Preference
+            android:key="app_usage_background"
+            android:title="@string/battery_detail_background"/>
+
+        <Preference
+            android:key="app_power_usage"
+            android:title="@string/battery_detail_power_usage"/>
+
+    </PreferenceCategory>
+
+    <PreferenceCategory
+        android:title="@string/battery_detail_manage_title">
+
+        <SwitchPreference
+            android:key="background_activity"
+            android:title="@string/background_activity_title"
+            android:selectable="true"/>
+
+        <Preference
+            android:key="battery_optimization"
+            android:title="@string/battery_detail_background"
+            android:summary="@string/high_power_off"
+            android:selectable="true"/>
+
+    </PreferenceCategory>
+
+</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/reset_dashboard_fragment.xml b/res/xml/reset_dashboard_fragment.xml
new file mode 100644
index 0000000..02328af
--- /dev/null
+++ b/res/xml/reset_dashboard_fragment.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2017 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<PreferenceScreen
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
+    android:title="@string/reset_dashboard_title">
+
+    <!-- Network reset -->
+    <Preference
+        android:key="network_reset_pref"
+        android:title="@string/reset_network_title"
+        android:fragment="com.android.settings.ResetNetwork" />
+
+    <!-- Reset app preferences -->
+    <Preference
+        android:key="reset_app_prefs"
+        android:title="@string/reset_app_preferences" />
+
+    <!-- Factory reset -->
+    <com.android.settingslib.RestrictedPreference
+        android:key="factory_reset"
+        android:title="@string/master_clear_title"
+        android:summary="@string/master_clear_summary"
+        settings:keywords="@string/keywords_factory_data_reset"
+        settings:userRestriction="no_factory_reset"
+        settings:useAdminDisabledSummary="true"
+        android:fragment="com.android.settings.MasterClear" />
+</PreferenceScreen>
diff --git a/res/xml/sound_settings.xml b/res/xml/sound_settings.xml
index 0aaaff1..d288a9d 100644
--- a/res/xml/sound_settings.xml
+++ b/res/xml/sound_settings.xml
@@ -56,38 +56,34 @@
                 android:title="@string/zen_mode_settings_title"
                 settings:useAdminDisabledSummary="true"
                 settings:keywords="@string/keywords_sounds_and_notifications_interruptions"
-                android:fragment="com.android.settings.notification.ZenModeSettings" />
+                android:fragment="com.android.settings.notification.ZenModeSettings"
+                settings:allowDividerAbove="true" />
 
-        <PreferenceCategory
-          android:key="ringtones_preferecence_category"
-          android:title="@string/ringtones_category_preference_title" >
+        <!-- Phone ringtone -->
+        <com.android.settings.DefaultRingtonePreference
+            android:key="ringtone"
+            android:title="@string/ringtone_title"
+            android:dialogTitle="@string/ringtone_title"
+            android:summary="@string/summary_placeholder"
+            android:ringtoneType="ringtone"
+            settings:allowDividerAbove="true" />
 
-                <!-- Phone ringtone -->
-                <com.android.settings.DefaultRingtonePreference
-                    android:key="ringtone"
-                    android:title="@string/ringtone_title"
-                    android:dialogTitle="@string/ringtone_title"
-                    android:summary="@string/summary_placeholder"
-                    android:ringtoneType="ringtone" />
+        <!-- Default notification ringtone -->
+        <com.android.settings.DefaultRingtonePreference
+            android:key="notification_ringtone"
+            android:title="@string/notification_ringtone_title"
+            android:dialogTitle="@string/notification_ringtone_title"
+            android:summary="@string/summary_placeholder"
+            android:ringtoneType="notification" />
 
-                <!-- Default notification ringtone -->
-                <com.android.settings.DefaultRingtonePreference
-                    android:key="notification_ringtone"
-                    android:title="@string/notification_ringtone_title"
-                    android:dialogTitle="@string/notification_ringtone_title"
-                    android:summary="@string/summary_placeholder"
-                    android:ringtoneType="notification" />
-
-                <!-- Default alarm ringtone -->
-                <com.android.settings.DefaultRingtonePreference
-                    android:key="alarm_ringtone"
-                    android:title="@string/alarm_ringtone_title"
-                    android:dialogTitle="@string/alarm_ringtone_title"
-                    android:summary="@string/summary_placeholder"
-                    android:persistent="false"
-                    android:ringtoneType="alarm" />
-
-        </PreferenceCategory>
+        <!-- Default alarm ringtone -->
+        <com.android.settings.DefaultRingtonePreference
+            android:key="alarm_ringtone"
+            android:title="@string/alarm_ringtone_title"
+            android:dialogTitle="@string/alarm_ringtone_title"
+            android:summary="@string/summary_placeholder"
+            android:persistent="false"
+            android:ringtoneType="alarm" />
 
         <!-- Other sounds -->
         <PreferenceCategory
@@ -144,7 +140,8 @@
         <com.android.settingslib.RestrictedPreference
           android:key="cell_broadcast_settings"
           android:title="@string/cell_broadcast_settings"
-          settings:useAdminDisabledSummary="true">
+          settings:useAdminDisabledSummary="true"
+          settings:allowDividerAbove="true" >
                 <intent
                   android:action="android.intent.action.MAIN"
                   android:targetPackage="com.android.cellbroadcastreceiver"
diff --git a/res/xml/storage_profile_fragment.xml b/res/xml/storage_profile_fragment.xml
index c675744..98cb1dc 100644
--- a/res/xml/storage_profile_fragment.xml
+++ b/res/xml/storage_profile_fragment.xml
@@ -20,22 +20,27 @@
     android:title="@string/storage_settings">
     <com.android.settings.deviceinfo.StorageItemPreference
         android:key="pref_photos_videos"
-        android:title="@string/storage_photos_videos">
-    </com.android.settings.deviceinfo.StorageItemPreference>
+        android:title="@string/storage_photos_videos"
+        android:icon="@drawable/ic_photo_library_vd_theme_24"
+        android:order="2" />
     <com.android.settings.deviceinfo.StorageItemPreference
         android:key="pref_music_audio"
-        android:title="@string/storage_music_audio">
-    </com.android.settings.deviceinfo.StorageItemPreference>
+        android:title="@string/storage_music_audio"
+        android:icon="@drawable/ic_music_note_vd_theme_24"
+        android:order="3" />
     <com.android.settings.deviceinfo.StorageItemPreference
         android:key="pref_games"
-        android:title="@string/storage_games">
-    </com.android.settings.deviceinfo.StorageItemPreference>
+        android:title="@string/storage_games"
+        android:icon="@drawable/ic_videogame_vd_theme_24"
+        android:order="4" />
     <com.android.settings.deviceinfo.StorageItemPreference
         android:key="pref_other_apps"
-        android:title="@string/storage_other_apps">
-    </com.android.settings.deviceinfo.StorageItemPreference>
+        android:title="@string/storage_other_apps"
+        android:icon="@drawable/ic_apps_vd_theme_24"
+        android:order="5" />
     <com.android.settings.deviceinfo.StorageItemPreference
         android:key="pref_files"
-        android:title="@string/storage_files">
-    </com.android.settings.deviceinfo.StorageItemPreference>
+        android:title="@string/storage_files"
+        android:icon="@drawable/ic_folder_vd_theme_24"
+        android:order="6" />
 </PreferenceScreen>
diff --git a/res/xml/system_dashboard_fragment.xml b/res/xml/system_dashboard_fragment.xml
index b03fab6..1186e78 100644
--- a/res/xml/system_dashboard_fragment.xml
+++ b/res/xml/system_dashboard_fragment.xml
@@ -16,7 +16,6 @@
 
 <PreferenceScreen
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
     android:title="@string/header_category_system">
 
     <!-- System updates -->
@@ -26,7 +25,7 @@
         android:summary="@string/summary_placeholder"
         android:icon="@drawable/ic_system_update"
         android:order="-30">
-        <intent android:action="android.settings.SYSTEM_UPDATE_SETTINGS"/>
+        <intent android:action="android.settings.SYSTEM_UPDATE_SETTINGS" />
     </Preference>
 
     <Preference
@@ -35,17 +34,14 @@
         android:order="-31">
         <intent android:action="android.intent.action.MAIN"
                 android:targetPackage="@string/additional_system_update"
-                android:targetClass="@string/additional_system_update_menu"/>
+                android:targetClass="@string/additional_system_update_menu" />
     </Preference>
 
-    <!-- Factory reset -->
-    <com.android.settingslib.RestrictedPreference
-        android:key="factory_reset"
-        android:title="@string/master_clear_title"
+    <Preference
+        android:key="reset_dashboard"
+        android:title="@string/reset_dashboard_title"
         android:icon="@drawable/ic_restore"
         android:order="-20"
-        settings:keywords="@string/keywords_factory_data_reset"
-        settings:userRestriction="no_factory_reset"
-        settings:useAdminDisabledSummary="true"
-        android:fragment="com.android.settings.MasterClear" />
+        android:fragment="com.android.settings.system.ResetDashboardFragment" />
+
 </PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/vpn_app_management.xml b/res/xml/vpn_app_management.xml
index 1b6f37b..c044a58 100644
--- a/res/xml/vpn_app_management.xml
+++ b/res/xml/vpn_app_management.xml
@@ -27,8 +27,7 @@
                 android:key="always_on_vpn"
                 android:title="@string/vpn_menu_lockdown"
                 android:defaultValue="false"
-                android:summaryOn="@string/vpn_always_on_active"
-                android:summaryOff="@string/vpn_always_on_inactive"
+                android:summary="@string/vpn_always_on_summary"
                 settings:userRestriction="no_config_vpn"
                 settings:useAdditionalSummary="true"
                 settings:restrictedSwitchSummary="@string/disabled_by_admin_summary_text" />
@@ -37,8 +36,6 @@
                 android:key="lockdown_vpn"
                 android:title="@string/vpn_require_connection"
                 android:defaultValue="false"
-                android:summaryOn="@string/vpn_lockdown_active"
-                android:summaryOff="@string/vpn_lockdown_inactive"
                 android:dependency="always_on_vpn"
                 settings:userRestriction="no_config_vpn"
                 settings:useAdditionalSummary="true"
diff --git a/res/xml/zen_mode_automation_settings.xml b/res/xml/zen_mode_automation_settings.xml
deleted file mode 100644
index 7cfffd4..0000000
--- a/res/xml/zen_mode_automation_settings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
-    android:key="zen_mode_settings"
-    android:title="@string/zen_mode_automation_settings_title" >
-
-    <!-- Rules added at runtime -->
-</PreferenceScreen>
diff --git a/res/xml/zen_mode_settings.xml b/res/xml/zen_mode_settings.xml
index b22ad6a..5fc72aa 100644
--- a/res/xml/zen_mode_settings.xml
+++ b/res/xml/zen_mode_settings.xml
@@ -25,15 +25,14 @@
             android:title="@string/zen_mode_priority_settings_title"
             android:fragment="com.android.settings.notification.ZenModePrioritySettings" />
 
-    <!-- Automated rules -->
-    <Preference
-            android:key="automation_settings"
-            android:title="@string/zen_mode_automation_settings_title"
-            android:fragment="com.android.settings.notification.ZenModeAutomationSettings" />
-
     <!-- Visual interruptions -->
     <Preference
             android:key="visual_interruptions_settings"
             android:title="@string/zen_mode_visual_interruptions_settings_title"
             android:fragment="com.android.settings.notification.ZenModeVisualInterruptionSettings" />
+
+    <!-- Automatic rules -->
+    <PreferenceCategory
+        android:key="automatic_rules"
+        android:title="@string/zen_mode_automation_settings_title" />
 </PreferenceScreen>
diff --git a/src/com/android/settings/TetherSettings.java b/src/com/android/settings/TetherSettings.java
index 61cad39..5d797a7 100644
--- a/src/com/android/settings/TetherSettings.java
+++ b/src/com/android/settings/TetherSettings.java
@@ -142,7 +142,7 @@
         setIfOnlyAvailableForAdmins(true);
         if (isUiRestricted()) {
             mUnavailable = true;
-            setPreferenceScreen(new PreferenceScreen(getPrefContext(), null));
+            getPreferenceScreen().removeAll();
             return;
         }
 
diff --git a/src/com/android/settings/UserCredentialsSettings.java b/src/com/android/settings/UserCredentialsSettings.java
index ea9eee9..6cf1ae0 100644
--- a/src/com/android/settings/UserCredentialsSettings.java
+++ b/src/com/android/settings/UserCredentialsSettings.java
@@ -37,20 +37,18 @@
 import android.security.KeyChain;
 import android.security.KeyChain.KeyChainConnection;
 import android.security.KeyStore;
+import android.support.v7.widget.RecyclerView;
 import android.util.Log;
 import android.util.SparseArray;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-import android.widget.AdapterView;
-import android.widget.AdapterView.OnItemClickListener;
-import android.widget.ArrayAdapter;
-import android.widget.ListView;
 import android.widget.TextView;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+import com.android.settings.SettingsPreferenceFragment;
 import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
 
@@ -63,11 +61,10 @@
 import static android.view.View.GONE;
 import static android.view.View.VISIBLE;
 
-public class UserCredentialsSettings extends OptionsMenuFragment implements OnItemClickListener {
+public class UserCredentialsSettings extends SettingsPreferenceFragment
+        implements View.OnClickListener {
     private static final String TAG = "UserCredentialsSettings";
 
-    private ListView mListView;
-
     @Override
     public int getMetricsCategory() {
         return MetricsEvent.USER_CREDENTIALS;
@@ -80,27 +77,18 @@
     }
 
     @Override
-    public View onCreateView(
-            LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
-        final View rootView = inflater.inflate(R.layout.user_credentials, parent, false);
-
-        // Set up an OnItemClickListener for the credential list.
-        mListView = (ListView) rootView.findViewById(R.id.credential_list);
-        mListView.setOnItemClickListener(this);
-
-        return rootView;
-    }
-
-    @Override
-    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
-        final Credential item = (Credential) parent.getItemAtPosition(position);
-        CredentialDialogFragment.show(this, item);
+    public void onClick(final View view) {
+        final Credential item = (Credential) view.getTag();
+        if (item != null) {
+            CredentialDialogFragment.show(this, item);
+        }
     }
 
     protected void announceRemoval(String alias) {
-        if (isAdded()) {
-            mListView.announceForAccessibility(getString(R.string.user_credential_removed, alias));
+        if (!isAdded()) {
+            return;
         }
+        getListView().announceForAccessibility(getString(R.string.user_credential_removed, alias));
     }
 
     protected void refreshItems() {
@@ -288,25 +276,60 @@
 
         @Override
         protected void onPostExecute(List<Credential> credentials) {
-            final Credential[] credentialArray = credentials.toArray(new Credential[0]);
-            mListView.setAdapter(new CredentialAdapter(getContext(), credentialArray));
+            if (!isAdded()) {
+                return;
+            }
+
+            if (credentials == null || credentials.size() == 0) {
+                // Create a "no credentials installed" message for the empty case.
+                TextView emptyTextView = (TextView) getActivity().findViewById(android.R.id.empty);
+                emptyTextView.setText(R.string.user_credential_none_installed);
+                setEmptyView(emptyTextView);
+            } else {
+                setEmptyView(null);
+            }
+
+            getListView().setAdapter(
+                    new CredentialAdapter(credentials, UserCredentialsSettings.this));
         }
     }
 
     /**
      * Helper class to display {@link Credential}s in a list.
      */
-    private static class CredentialAdapter extends ArrayAdapter<Credential> {
+    private static class CredentialAdapter extends RecyclerView.Adapter<ViewHolder> {
         private static final int LAYOUT_RESOURCE = R.layout.user_credential_preference;
 
-        public CredentialAdapter(Context context, final Credential[] objects) {
-            super(context, LAYOUT_RESOURCE, objects);
+        private final List<Credential> mItems;
+        private final View.OnClickListener mListener;
+
+        public CredentialAdapter(List<Credential> items, @Nullable View.OnClickListener listener) {
+            mItems = items;
+            mListener = listener;
         }
 
         @Override
-        public View getView(int position, @Nullable View view, ViewGroup parent) {
-            return getCredentialView(getItem(position), LAYOUT_RESOURCE, view, parent,
-                    /* expanded */ false);
+        public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+            final LayoutInflater inflater = LayoutInflater.from(parent.getContext());
+            return new ViewHolder(inflater.inflate(LAYOUT_RESOURCE, parent, false));
+        }
+
+        @Override
+        public void onBindViewHolder(ViewHolder h, int position) {
+            getCredentialView(mItems.get(position), LAYOUT_RESOURCE, h.itemView, null, false);
+            h.itemView.setTag(mItems.get(position));
+            h.itemView.setOnClickListener(mListener);
+        }
+
+        @Override
+        public int getItemCount() {
+            return mItems.size();
+        }
+    }
+
+    private static class ViewHolder extends RecyclerView.ViewHolder {
+        public ViewHolder(View item) {
+            super(item);
         }
     }
 
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index 909ddfe..4c8fb2d 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -74,6 +74,7 @@
 import android.provider.ContactsContract.RawContacts;
 import android.provider.Settings;
 import android.service.persistentdata.PersistentDataBlockManager;
+import android.support.annotation.StringRes;
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.PreferenceGroup;
 import android.support.v7.preference.PreferenceManager;
@@ -1241,6 +1242,17 @@
         return isVolumeValid(volume) ? volume : null;
     }
 
+    /**
+     * Return the resource id to represent the install status for an app
+     */
+    @StringRes
+    public static int getInstallationStatus(ApplicationInfo info) {
+        if ((info.flags & ApplicationInfo.FLAG_INSTALLED) == 0) {
+            return R.string.not_installed;
+        }
+        return info.enabled ? R.string.installed : R.string.disabled;
+    }
+
     private static boolean isVolumeValid(VolumeInfo volume) {
         return (volume != null) && (volume.getType() == VolumeInfo.TYPE_PRIVATE)
                 && volume.isMountedReadable();
diff --git a/src/com/android/settings/accessibility/AccessibilityServiceWarning.java b/src/com/android/settings/accessibility/AccessibilityServiceWarning.java
index 3a84d74..71cafba 100644
--- a/src/com/android/settings/accessibility/AccessibilityServiceWarning.java
+++ b/src/com/android/settings/accessibility/AccessibilityServiceWarning.java
@@ -78,9 +78,16 @@
         return StorageManager.isNonDefaultBlockEncrypted();
     }
 
-    private static View createEnableDialogContentView(Activity parentActivity,
+    /**
+     * Get a content View for a dialog to confirm that they want to enable a service.
+     *
+     * @param context A valid context
+     * @param info The info about a service
+     * @return A content view suitable for viewing
+     */
+    private static View createEnableDialogContentView(Context context,
             AccessibilityServiceInfo info) {
-        LayoutInflater inflater = (LayoutInflater) parentActivity.getSystemService(
+        LayoutInflater inflater = (LayoutInflater) context.getSystemService(
                 Context.LAYOUT_INFLATER_SERVICE);
 
         View content = inflater.inflate(R.layout.enable_accessibility_service_dialog_content,
@@ -89,8 +96,8 @@
         TextView encryptionWarningView = (TextView) content.findViewById(
                 R.id.encryption_warning);
         if (isFullDiskEncrypted()) {
-            String text = parentActivity.getString(R.string.enable_service_encryption_warning,
-                    info.getResolveInfo().loadLabel(parentActivity.getPackageManager()));
+            String text = context.getString(R.string.enable_service_encryption_warning,
+                    info.getResolveInfo().loadLabel(context.getPackageManager()));
             encryptionWarningView.setText(text);
             encryptionWarningView.setVisibility(View.VISIBLE);
         } else {
@@ -99,8 +106,8 @@
 
         TextView capabilitiesHeaderView = (TextView) content.findViewById(
                 R.id.capabilities_header);
-        capabilitiesHeaderView.setText(parentActivity.getString(R.string.capabilities_list_title,
-                info.getResolveInfo().loadLabel(parentActivity.getPackageManager())));
+        capabilitiesHeaderView.setText(context.getString(R.string.capabilities_list_title,
+                info.getResolveInfo().loadLabel(context.getPackageManager())));
 
         LinearLayout capabilitiesView = (LinearLayout) content.findViewById(R.id.capabilities);
 
@@ -110,21 +117,21 @@
 
         ImageView imageView = (ImageView) capabilityView.findViewById(
                 com.android.internal.R.id.perm_icon);
-        imageView.setImageDrawable(parentActivity.getDrawable(
+        imageView.setImageDrawable(context.getDrawable(
                 com.android.internal.R.drawable.ic_text_dot));
 
         TextView labelView = (TextView) capabilityView.findViewById(
                 com.android.internal.R.id.permission_group);
-        labelView.setText(parentActivity.getString(
+        labelView.setText(context.getString(
                 R.string.capability_title_receiveAccessibilityEvents));
 
         TextView descriptionView = (TextView) capabilityView.findViewById(
                 com.android.internal.R.id.permission_list);
         descriptionView.setText(
-                parentActivity.getString(R.string.capability_desc_receiveAccessibilityEvents));
+                context.getString(R.string.capability_desc_receiveAccessibilityEvents));
 
         List<AccessibilityServiceInfo.CapabilityInfo> capabilities =
-                info.getCapabilityInfos(parentActivity);
+                info.getCapabilityInfos(context);
 
         capabilitiesView.addView(capabilityView);
 
@@ -138,16 +145,16 @@
 
             imageView = (ImageView) capabilityView.findViewById(
                     com.android.internal.R.id.perm_icon);
-            imageView.setImageDrawable(parentActivity.getDrawable(
+            imageView.setImageDrawable(context.getDrawable(
                     com.android.internal.R.drawable.ic_text_dot));
 
             labelView = (TextView) capabilityView.findViewById(
                     com.android.internal.R.id.permission_group);
-            labelView.setText(parentActivity.getString(capability.titleResId));
+            labelView.setText(context.getString(capability.titleResId));
 
             descriptionView = (TextView) capabilityView.findViewById(
                     com.android.internal.R.id.permission_list);
-            descriptionView.setText(parentActivity.getString(capability.descResId));
+            descriptionView.setText(context.getString(capability.descResId));
 
             capabilitiesView.addView(capabilityView);
         }
diff --git a/src/com/android/settings/accessibility/AccessibilitySettings.java b/src/com/android/settings/accessibility/AccessibilitySettings.java
index 9b2c853..760755c 100644
--- a/src/com/android/settings/accessibility/AccessibilitySettings.java
+++ b/src/com/android/settings/accessibility/AccessibilitySettings.java
@@ -17,11 +17,9 @@
 package com.android.settings.accessibility;
 
 import android.accessibilityservice.AccessibilityServiceInfo;
-import android.app.Dialog;
 import android.app.admin.DevicePolicyManager;
 import android.content.ComponentName;
 import android.content.Context;
-import android.content.DialogInterface;
 import android.content.pm.PackageManager;
 import android.content.pm.ServiceInfo;
 import android.content.res.Resources;
@@ -105,7 +103,7 @@
     private static final String CAPTIONING_PREFERENCE_SCREEN =
             "captioning_preference_screen";
     private static final String DISPLAY_MAGNIFICATION_PREFERENCE_SCREEN =
-            "screen_magnification_preference_screen";
+            "magnification_preference_screen";
     private static final String FONT_SIZE_PREFERENCE_SCREEN =
             "font_size_preference_screen";
     private static final String AUTOCLICK_PREFERENCE_SCREEN =
@@ -130,9 +128,6 @@
     // presentation.
     private static final long DELAY_UPDATE_SERVICES_MILLIS = 1000;
 
-    // ID for dialog that confirms shortcut capabilities
-    private static final int DIALOG_ID_ADD_SHORTCUT_WARNING = 1;
-
     private final Map<String, String> mLongPressTimeoutValueToTitleMap = new HashMap<>();
 
     private final Handler mHandler = new Handler();
@@ -205,7 +200,7 @@
     private Preference mDisplayMagnificationPreferenceScreen;
     private Preference mFontSizePreferenceScreen;
     private Preference mAutoclickPreferenceScreen;
-    private ListPreference mAccessibilityShortcutPreference;
+    private Preference mAccessibilityShortcutPreferenceScreen;
     private Preference mDisplayDaltonizerPreferenceScreen;
     private SwitchPreference mToggleInversionPreference;
 
@@ -264,9 +259,6 @@
         } else if (mToggleInversionPreference == preference) {
             handleToggleInversionPreferenceChange((Boolean) newValue);
             return true;
-        } else if (mAccessibilityShortcutPreference == preference) {
-            handleAccessibilityShortcutPreferenceChange((String) newValue);
-            return true;
         }
         return false;
     }
@@ -283,58 +275,6 @@
                 Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, (checked ? 1 : 0));
     }
 
-    private void handleAccessibilityShortcutPreferenceChange(String serviceComponentName) {
-        // When assigning a service to the shortcut the user must explicitly agree to the same
-        // capabilities that are present if the service were being enabled.
-        // No need if clearing the setting or the service is already enabled.
-        if (TextUtils.isEmpty(serviceComponentName)
-                || AccessibilityUtils.getEnabledServicesFromSettings(getActivity())
-                        .contains(ComponentName.unflattenFromString(serviceComponentName))) {
-            Settings.Secure.putString(getContentResolver(),
-                    Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, serviceComponentName);
-            updateAccessibilityShortcut();
-            return;
-        }
-        if (!serviceComponentName.equals(mAccessibilityShortcutPreference.getValue())) {
-            showDialog(DIALOG_ID_ADD_SHORTCUT_WARNING);
-        }
-    }
-
-    @Override
-    public Dialog onCreateDialog(int dialogId) {
-        switch (dialogId) {
-            case DIALOG_ID_ADD_SHORTCUT_WARNING: {
-                DialogInterface.OnClickListener listener =
-                        (DialogInterface dialogInterface, int buttonId) -> {
-                            if (buttonId == DialogInterface.BUTTON_POSITIVE) {
-                                Settings.Secure.putString(getContentResolver(),
-                                        Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE,
-                                        mAccessibilityShortcutPreference.getValue());
-                            }
-                            updateAccessibilityShortcut();
-                        };
-                AccessibilityServiceInfo info = AccessibilityManager.getInstance(getActivity())
-                        .getInstalledServiceInfoWithComponentName(
-                                ComponentName.unflattenFromString(
-                                        mAccessibilityShortcutPreference.getValue()));
-                if (info == null) {
-                    return null;
-                }
-                return AccessibilityServiceWarning
-                        .createCapabilitiesDialog(getActivity(), info, listener);
-            }
-            default: {
-                throw new IllegalArgumentException();
-            }
-        }
-    }
-
-    @Override
-    public int getDialogMetricsCategory(int dialogId) {
-        // The only dialog is the one that confirms the properties for the accessibility shortcut
-        return MetricsEvent.ACCESSIBILITY_TOGGLE_GLOBAL_GESTURE;
-    }
-
     @Override
     public boolean onPreferenceTreeClick(Preference preference) {
         if (mToggleHighTextContrastPreference == preference) {
@@ -458,9 +398,7 @@
         mDisplayDaltonizerPreferenceScreen = findPreference(DISPLAY_DALTONIZER_PREFERENCE_SCREEN);
 
         // Accessibility shortcut
-        mAccessibilityShortcutPreference =
-                (ListPreference) findPreference(ACCESSIBILITY_SHORTCUT_PREFERENCE);
-        mAccessibilityShortcutPreference.setOnPreferenceChangeListener(this);
+        mAccessibilityShortcutPreferenceScreen = findPreference(ACCESSIBILITY_SHORTCUT_PREFERENCE);
     }
 
     private void updateAllPreferences() {
@@ -532,12 +470,15 @@
             preference.setIcon(icon);
             final boolean serviceEnabled = accessibilityEnabled
                     && enabledServices.contains(componentName);
-            String serviceState = serviceEnabled ?
-                    getString(R.string.accessibility_feature_state_on) :
-                    getString(R.string.accessibility_feature_state_off);
-            String serviceSummary = info.loadSummary(getPackageManager());
-            serviceSummary = (TextUtils.isEmpty(serviceSummary)) ? serviceState :
-                    serviceSummary;
+            final String serviceState = serviceEnabled ?
+                    getString(R.string.accessibility_summary_state_enabled) :
+                    getString(R.string.accessibility_summary_state_disabled);
+            final String serviceSummary = info.loadSummary(getPackageManager());
+            final String stateSummaryCombo = getString(
+                    R.string.accessibility_summary_default_combination,
+                    serviceState, serviceSummary);
+            preference.setSummary((TextUtils.isEmpty(serviceSummary)) ? serviceState
+                    : stateSummaryCombo);
 
             // Disable all accessibility services that are not permitted.
             boolean serviceAllowed =
@@ -554,7 +495,6 @@
                 preference.setEnabled(true);
             }
 
-            preference.setSummary(serviceSummary);
             preference.setFragment(ToggleAccessibilityServicePreferenceFragment.class.getName());
             preference.setPersistent(true);
 
@@ -647,11 +587,32 @@
         updateFeatureSummary(Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED,
                 mDisplayDaltonizerPreferenceScreen);
 
+        updateMagnificationSummary(mDisplayMagnificationPreferenceScreen);
+
         updateFontSizeSummary(mFontSizePreferenceScreen);
 
         updateAutoclickSummary(mAutoclickPreferenceScreen);
 
-        updateAccessibilityShortcut();
+        updateAccessibilityShortcut(mAccessibilityShortcutPreferenceScreen);
+    }
+
+    private void updateMagnificationSummary(Preference pref) {
+        final boolean tripleTapEnabled = Settings.Secure.getInt(getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, 0) == 1;
+        final boolean buttonEnabled = Settings.Secure.getInt(getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED, 0) == 1;
+
+        int summaryResId = 0;
+        if (!tripleTapEnabled && !buttonEnabled) {
+            summaryResId = R.string.accessibility_feature_state_off;
+        } else if (!tripleTapEnabled && buttonEnabled) {
+            summaryResId = R.string.accessibility_screen_magnification_navbar_title;
+        } else if (tripleTapEnabled && !buttonEnabled) {
+            summaryResId = R.string.accessibility_screen_magnification_gestures_title;
+        } else {
+            summaryResId = R.string.accessibility_screen_magnification_state_navbar_gesture;
+        }
+        pref.setSummary(summaryResId);
     }
 
     private void updateFeatureSummary(String prefKey, Preference pref) {
@@ -700,35 +661,21 @@
         mToggleMasterMonoPreference.setChecked(masterMono);
     }
 
-    private void updateAccessibilityShortcut() {
-        String currentShortcutNameString =
-                AccessibilityUtils.getShortcutTargetServiceComponentNameString(getActivity(),
-                        UserHandle.myUserId());
-        final PackageManager pm = getPackageManager();
-        final AccessibilityManager accessibilityManager = getActivity()
-                .getSystemService(AccessibilityManager.class);
-        final List<AccessibilityServiceInfo> installedServices =
-                accessibilityManager.getInstalledAccessibilityServiceList();
-        final int numInstalledServices = installedServices.size();
-
-        CharSequence[] entries = new CharSequence[numInstalledServices + 1];
-        CharSequence[] entryValues = new CharSequence[numInstalledServices + 1];
-        int currentSettingIndex = numInstalledServices;
-        for (int i = 0; i < numInstalledServices; i++) {
-            AccessibilityServiceInfo installedService = installedServices.get(i);
-            entries[i] = installedService.getResolveInfo().loadLabel(pm);
-            entryValues[i] = installedService.getComponentName().flattenToShortString();
-            if (installedService.getId().equals(currentShortcutNameString)) {
-                currentSettingIndex = i;
-            }
+    private void updateAccessibilityShortcut(Preference preference) {
+        if (AccessibilityManager.getInstance(getActivity())
+                .getInstalledAccessibilityServiceList().isEmpty()) {
+            mAccessibilityShortcutPreferenceScreen
+                    .setSummary(getString(R.string.accessibility_no_services_installed));
+            mAccessibilityShortcutPreferenceScreen.setEnabled(false);
+        } else {
+            mAccessibilityShortcutPreferenceScreen.setEnabled(true);
+            boolean shortcutEnabled =
+                    AccessibilityUtils.isShortcutEnabled(getContext(), UserHandle.myUserId());
+            CharSequence summary = shortcutEnabled
+                    ? AccessibilityShortcutPreferenceFragment.getServiceName(getContext())
+                    : getString(R.string.accessibility_feature_state_off);
+            mAccessibilityShortcutPreferenceScreen.setSummary(summary);
         }
-        entries[numInstalledServices] =
-                getString(com.android.internal.R.string.disable_accessibility_shortcut);
-        entryValues[numInstalledServices] = "";
-        mAccessibilityShortcutPreference.setEntryValues(entryValues);
-        mAccessibilityShortcutPreference.setEntries(entries);
-        mAccessibilityShortcutPreference.setSummary(entries[currentSettingIndex]);
-        mAccessibilityShortcutPreference.setValueIndex(currentSettingIndex);
     }
 
     public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
diff --git a/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java b/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java
new file mode 100644
index 0000000..6ed06da
--- /dev/null
+++ b/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settings.accessibility;
+
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.support.v14.preference.SwitchPreference;
+import android.support.v7.preference.Preference;
+import android.text.TextUtils;
+import android.view.accessibility.AccessibilityManager;
+import android.widget.Switch;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settings.R;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.search.Indexable;
+import com.android.settingslib.accessibility.AccessibilityUtils;
+
+/**
+ * Settings page for accessibility shortcut
+ */
+public class AccessibilityShortcutPreferenceFragment extends ToggleFeaturePreferenceFragment
+        implements Indexable {
+
+    public static final String SHORTCUT_SERVICE_KEY = "accessibility_shortcut_service";
+    public static final String ON_LOCK_SCREEN_KEY = "accessibility_shortcut_on_lock_screen";
+    // ID for dialog that confirms shortcut capabilities
+    private static final int DIALOG_ID_ADD_SHORTCUT_WARNING = 1;
+
+    private Preference mServicePreference;
+    private SwitchPreference mOnLockScreenSwitchPreference;
+    private String mSelectedServiceComponentNameString;
+
+    @Override
+    public int getMetricsCategory() {
+        return MetricsEvent.ACCESSIBILITY_TOGGLE_GLOBAL_GESTURE;
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        addPreferencesFromResource(R.xml.accessibility_shortcut_settings);
+        mServicePreference = findPreference(SHORTCUT_SERVICE_KEY);
+        mOnLockScreenSwitchPreference = (SwitchPreference) findPreference(ON_LOCK_SCREEN_KEY);
+        mOnLockScreenSwitchPreference.setOnPreferenceChangeListener((Preference p, Object o) -> {
+            Settings.Secure.putInt(getContentResolver(),
+                    Settings.Secure.ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN,
+                    ((Boolean) o) ? 1 : 0);
+            return true;
+        });
+        mFooterPreferenceMixin.createFooterPreference()
+                .setTitle(R.string.accessibility_shortcut_description);
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        updatePreferences();
+    }
+
+    @Override
+    protected void onInstallSwitchBarToggleSwitch() {
+        super.onInstallSwitchBarToggleSwitch();
+        mSwitchBar.addOnSwitchChangeListener((Switch switchView, boolean enabled) -> {
+            onPreferenceToggled(Settings.Secure.ACCESSIBILITY_SHORTCUT_ENABLED, enabled);
+        });
+    }
+
+    @Override
+    protected void onPreferenceToggled(String preferenceKey, boolean enabled) {
+        Settings.Secure.putInt(getContentResolver(), preferenceKey, enabled ? 1 : 0);
+    }
+
+    private void updatePreferences() {
+        ContentResolver cr = getContentResolver();
+        boolean isEnabled = Settings.Secure
+                .getInt(cr, Settings.Secure.ACCESSIBILITY_SHORTCUT_ENABLED, 1) == 1;
+        mToggleSwitch.setChecked(isEnabled);
+        CharSequence serviceName = getServiceName(getContext());
+        mServicePreference.setSummary(serviceName);
+        mOnLockScreenSwitchPreference.setChecked(Settings.Secure.getInt(
+                cr, Settings.Secure.ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN, 1) == 1);
+        if (TextUtils.equals(serviceName, getString(R.string.accessibility_no_service_selected))) {
+            // If there's no service configured, enabling the shortcut will have no effect
+            // It should already be disabled, but force the switch to off just in case
+            mToggleSwitch.setChecked(false);
+            mToggleSwitch.setEnabled(false);
+            mSwitchBar.setEnabled(false);
+        } else {
+            mToggleSwitch.setEnabled(true);
+            mSwitchBar.setEnabled(true);
+        }
+    }
+
+    /**
+     * Get the user-visible name of the service currently selected for the shortcut.
+     *
+     * @param context The current context
+     * @return The name of the service or a string saying that none is selected.
+     */
+    public static CharSequence getServiceName(Context context) {
+        ComponentName shortcutServiceName = ComponentName.unflattenFromString(
+                AccessibilityUtils.getShortcutTargetServiceComponentNameString(
+                        context, UserHandle.myUserId()));
+        AccessibilityServiceInfo shortcutServiceInfo = AccessibilityManager.getInstance(context)
+                .getInstalledServiceInfoWithComponentName(shortcutServiceName);
+        if (shortcutServiceInfo != null) {
+            return shortcutServiceInfo.getResolveInfo().loadLabel(context.getPackageManager());
+        }
+        return context.getString(R.string.accessibility_no_service_selected);
+    }
+
+    public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+            new BaseSearchIndexProvider() {
+                // This fragment is for details of the shortcut. Only the shortcut itself needs
+                // to be indexed.
+                protected boolean isPageSearchEnabled(Context context) {
+                    return false;
+                }
+            };
+}
diff --git a/src/com/android/settings/accessibility/MagnificationPreferenceFragment.java b/src/com/android/settings/accessibility/MagnificationPreferenceFragment.java
index 4a55ea9..22706d7 100644
--- a/src/com/android/settings/accessibility/MagnificationPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/MagnificationPreferenceFragment.java
@@ -16,13 +16,16 @@
 
 package com.android.settings.accessibility;
 
-import android.content.ContentResolver;
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.content.ComponentName;
 import android.content.Context;
 import android.os.Bundle;
 import android.provider.SearchIndexableResource;
 import android.provider.Settings;
 import android.support.v7.preference.Preference;
+import android.text.TextUtils;
 import android.view.View;
+import android.view.accessibility.AccessibilityManager;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settings.R;
@@ -42,6 +45,10 @@
     private static final String MAGNIFICATION_NAVBAR_PREFERENCE_SCREEN_KEY =
             "screen_magnification_navbar_preference_screen";
 
+    // Pseudo ComponentName used to represent navbar magnification in Settings.Secure.
+    private static final String MAGNIFICATION_COMPONENT_ID =
+            "com.android.server.accessibility.MagnificationController";
+
     private Preference mMagnificationGesturesPreference;
     private Preference mMagnificationNavbarPreference;
 
@@ -147,17 +154,38 @@
         extras.putBoolean(AccessibilitySettings.EXTRA_LAUNCHED_FROM_SUW, mLaunchedFromSuw);
     }
 
-    static int getConfigurationWarningStringResourceForSecureSettingsKey(String key,
-            ContentResolver resolver) {
-        if (Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED.equals(key)) {
-            if (Settings.Secure.getInt(resolver,
-                    Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED, 0) == 1) {
-                // TODO(b/34720082): Only report a config warning when nav-bar is not mapped to mag
-                return R.string.accessibility_screen_magnification_navbar_configuration_warning;
+    static CharSequence getConfigurationWarningStringForSecureSettingsKey(String key,
+            Context context) {
+        if (!Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED.equals(key)) {
+            return null;
+        }
+        if (Settings.Secure.getInt(context.getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED, 0) == 0) {
+            return null;
+        }
+        final AccessibilityManager am = (AccessibilityManager) context.getSystemService(
+                Context.ACCESSIBILITY_SERVICE);
+        final String assignedId = Settings.Secure.getString(context.getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT);
+        if (!TextUtils.isEmpty(assignedId) && !MAGNIFICATION_COMPONENT_ID.equals(assignedId)) {
+            final ComponentName assignedComponentName = ComponentName.unflattenFromString(
+                    assignedId);
+            final List<AccessibilityServiceInfo> activeServices =
+                    am.getEnabledAccessibilityServiceList(
+                            AccessibilityServiceInfo.FEEDBACK_ALL_MASK);
+            final int serviceCount = activeServices.size();
+            for (int i = 0; i < serviceCount; i++) {
+                final AccessibilityServiceInfo info = activeServices.get(i);
+                if (info.getComponentName().equals(assignedComponentName)) {
+                    final CharSequence assignedServiceName = info.getResolveInfo().loadLabel(
+                            context.getPackageManager());
+                    return context.getString(
+                            R.string.accessibility_screen_magnification_navbar_configuration_warning,
+                            assignedServiceName);
+                }
             }
         }
-
-        return -1;
+        return null;
     }
 
     public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
diff --git a/src/com/android/settings/accessibility/ShortcutServicePickerFragment.java b/src/com/android/settings/accessibility/ShortcutServicePickerFragment.java
new file mode 100644
index 0000000..8b6d52a
--- /dev/null
+++ b/src/com/android/settings/accessibility/ShortcutServicePickerFragment.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settings.accessibility;
+
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.app.Fragment;
+import android.content.ComponentName;
+import android.content.DialogInterface;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageParser;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.support.v7.preference.Preference;
+import android.text.TextUtils;
+import android.view.accessibility.AccessibilityManager;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settings.DialogCreatable;
+import com.android.settings.applications.defaultapps.DefaultAppInfo;
+import com.android.settings.applications.defaultapps.DefaultAppPickerFragment;
+import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+import com.android.settings.widget.RadioButtonPreference;
+import com.android.settingslib.accessibility.AccessibilityUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Fragment for picking accessibility shortcut service
+ */
+public class ShortcutServicePickerFragment extends DefaultAppPickerFragment {
+
+    @Override
+    public int getMetricsCategory() {
+        return MetricsEvent.ACCESSIBILITY_TOGGLE_GLOBAL_GESTURE;
+    }
+
+    @Override
+    protected List<? extends DefaultAppInfo> getCandidates() {
+        final AccessibilityManager accessibilityManager = getContext()
+                .getSystemService(AccessibilityManager.class);
+        final List<AccessibilityServiceInfo> installedServices =
+                accessibilityManager.getInstalledAccessibilityServiceList();
+        final int numInstalledServices = installedServices.size();
+
+        List<DefaultAppInfo> candidates = new ArrayList<>(numInstalledServices);
+        for (int i = 0; i < numInstalledServices; i++) {
+            AccessibilityServiceInfo installedServiceInfo = installedServices.get(i);
+            candidates.add(new DefaultAppInfo(mPm,
+                    UserHandle.myUserId(),
+                    installedServiceInfo.getComponentName(),
+                    installedServiceInfo.loadSummary(mPm.getPackageManager()),
+                    true /* enabled */));
+        }
+
+        return candidates;
+    }
+
+    @Override
+    protected String getDefaultKey() {
+        String shortcutServiceString = AccessibilityUtils
+                .getShortcutTargetServiceComponentNameString(getContext(), UserHandle.myUserId());
+        if (shortcutServiceString != null) {
+            ComponentName shortcutName = ComponentName.unflattenFromString(shortcutServiceString);
+            if (shortcutName != null) {
+                return shortcutName.flattenToString();
+            }
+        }
+        return null;
+    }
+
+    @Override
+    protected boolean setDefaultKey(String key) {
+        Settings.Secure.putString(getContext().getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, key);
+        return true;
+    }
+
+    @Override
+    public void onRadioButtonClicked(RadioButtonPreference selected) {
+        final String selectedKey = selected.getKey();
+
+        final Activity activity = getActivity();
+        if (TextUtils.isEmpty(selectedKey)) {
+            super.onRadioButtonClicked(selected);
+        } else if (activity != null) {
+            final DialogFragment fragment = ConfirmationDialogFragment.newInstance(
+                    this, selectedKey);
+            fragment.show(activity.getFragmentManager(), ConfirmationDialogFragment.TAG);
+        }
+    }
+
+    private void onServiceConfirmed(String serviceKey) {
+        onRadioButtonConfirmed(serviceKey);
+    }
+
+    public static class ConfirmationDialogFragment extends InstrumentedDialogFragment
+            implements DialogInterface.OnClickListener {
+        private static final String EXTRA_KEY = "extra_key";
+        private static final String TAG = "ConfirmationDialogFragment";
+
+        public static ConfirmationDialogFragment newInstance(ShortcutServicePickerFragment parent,
+                String key) {
+            final ConfirmationDialogFragment fragment = new ConfirmationDialogFragment();
+            final Bundle argument = new Bundle();
+            argument.putString(EXTRA_KEY, key);
+            fragment.setArguments(argument);
+            fragment.setTargetFragment(parent, 0);
+            return fragment;
+        }
+
+        @Override
+        public int getMetricsCategory() {
+            return MetricsEvent.ACCESSIBILITY_TOGGLE_GLOBAL_GESTURE;
+        }
+
+        @Override
+        public Dialog onCreateDialog(Bundle savedInstanceState) {
+            final Bundle bundle = getArguments();
+            final String key = bundle.getString(EXTRA_KEY);
+            final ComponentName serviceComponentName = ComponentName.unflattenFromString(key);
+            final AccessibilityManager accessibilityManager = getActivity()
+                    .getSystemService(AccessibilityManager.class);
+            AccessibilityServiceInfo info = accessibilityManager
+                    .getInstalledServiceInfoWithComponentName(serviceComponentName);
+            return AccessibilityServiceWarning.createCapabilitiesDialog(getActivity(), info, this);
+        }
+
+        @Override
+        public void onClick(DialogInterface dialog, int which) {
+            final Fragment fragment = getTargetFragment();
+            if (fragment instanceof DefaultAppPickerFragment) {
+                final Bundle bundle = getArguments();
+                ((ShortcutServicePickerFragment) fragment).onServiceConfirmed(
+                        bundle.getString(EXTRA_KEY));
+            }
+        }
+    }
+}
diff --git a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java
index 19cde08..c6dc7a7 100644
--- a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java
@@ -214,14 +214,13 @@
     }
 
     private void updateConfigurationWarningIfNeeded() {
-        final int warningRes =
-                MagnificationPreferenceFragment
-                        .getConfigurationWarningStringResourceForSecureSettingsKey(
-                        mPreferenceKey, getContentResolver());
-        if (warningRes != -1) {
-            mConfigWarningPreference.setSummary(warningRes);
+        final CharSequence warningMessage =
+                MagnificationPreferenceFragment.getConfigurationWarningStringForSecureSettingsKey(
+                        mPreferenceKey, getPrefContext());
+        if (warningMessage != null) {
+            mConfigWarningPreference.setSummary(warningMessage);
         }
-        mConfigWarningPreference.setVisible(warningRes != -1);
+        mConfigWarningPreference.setVisible(warningMessage != null);
     }
 
     private static int getScreenWidth(Context context) {
diff --git a/src/com/android/settings/applications/InstalledAppDetails.java b/src/com/android/settings/applications/InstalledAppDetails.java
index 2ab007e..828eca6 100755
--- a/src/com/android/settings/applications/InstalledAppDetails.java
+++ b/src/com/android/settings/applications/InstalledAppDetails.java
@@ -551,7 +551,7 @@
             .newAppHeaderController(this, appSnippet)
             .setLabel(mAppEntry)
             .setIcon(mAppEntry)
-            .setSummary(getString(getInstallationStatus(mAppEntry.info)))
+            .setSummary(getString(Utils.getInstallationStatus(mAppEntry.info)))
             .setIsInstantApp(AppUtils.isInstant(mPackageInfo.applicationInfo))
             .done(false /* rebindActions */);
         mVersionPreference.setSummary(getString(R.string.version_text, pkgInfo.versionName));
@@ -581,14 +581,6 @@
         return showIt;
     }
 
-    @VisibleForTesting
-    int getInstallationStatus(ApplicationInfo info) {
-        if ((info.flags & ApplicationInfo.FLAG_INSTALLED) == 0) {
-            return R.string.not_installed;
-        }
-        return info.enabled ? R.string.installed : R.string.disabled;
-    }
-
     private boolean signaturesMatch(String pkg1, String pkg2) {
         if (pkg1 != null && pkg2 != null) {
             try {
diff --git a/src/com/android/settings/applications/ResetAppPrefPreferenceController.java b/src/com/android/settings/applications/ResetAppPrefPreferenceController.java
new file mode 100644
index 0000000..41352bb
--- /dev/null
+++ b/src/com/android/settings/applications/ResetAppPrefPreferenceController.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.applications;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.support.v7.preference.Preference;
+import android.text.TextUtils;
+
+import com.android.settings.core.PreferenceController;
+import com.android.settings.core.lifecycle.Lifecycle;
+import com.android.settings.core.lifecycle.LifecycleObserver;
+import com.android.settings.core.lifecycle.events.OnCreate;
+import com.android.settings.core.lifecycle.events.OnSaveInstanceState;
+
+public class ResetAppPrefPreferenceController extends PreferenceController
+        implements LifecycleObserver, OnCreate, OnSaveInstanceState {
+
+    private ResetAppsHelper mResetAppsHelper;
+
+    public ResetAppPrefPreferenceController(Context context, Lifecycle lifecycle) {
+        super(context);
+        mResetAppsHelper = new ResetAppsHelper(context);
+        if (lifecycle != null) {
+            lifecycle.addObserver(this);
+        }
+    }
+
+    @Override
+    public boolean handlePreferenceTreeClick(Preference preference) {
+        if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
+            return false;
+        }
+        mResetAppsHelper.buildResetDialog();
+        return true;
+    }
+
+    @Override
+    public boolean isAvailable() {
+        return true;
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return "reset_app_prefs";
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        mResetAppsHelper.onRestoreInstanceState(savedInstanceState);
+    }
+
+    @Override
+    public void onSaveInstanceState(Bundle outState) {
+        mResetAppsHelper.onSaveInstanceState(outState);
+    }
+}
diff --git a/src/com/android/settings/applications/ResetAppsHelper.java b/src/com/android/settings/applications/ResetAppsHelper.java
index ddcb244..93d384d 100644
--- a/src/com/android/settings/applications/ResetAppsHelper.java
+++ b/src/com/android/settings/applications/ResetAppsHelper.java
@@ -15,6 +15,9 @@
  */
 package com.android.settings.applications;
 
+import static android.net.NetworkPolicyManager.POLICY_NONE;
+import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
+
 import android.app.ActivityManager;
 import android.app.AlertDialog;
 import android.app.AppOpsManager;
@@ -36,9 +39,6 @@
 
 import java.util.List;
 
-import static android.net.NetworkPolicyManager.POLICY_NONE;
-import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
-
 public class ResetAppsHelper implements DialogInterface.OnClickListener,
         DialogInterface.OnDismissListener {
 
diff --git a/src/com/android/settings/applications/defaultapps/DefaultAppInfo.java b/src/com/android/settings/applications/defaultapps/DefaultAppInfo.java
index e99b106..b40943f 100644
--- a/src/com/android/settings/applications/defaultapps/DefaultAppInfo.java
+++ b/src/com/android/settings/applications/defaultapps/DefaultAppInfo.java
@@ -20,6 +20,7 @@
 import android.content.ComponentName;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.ComponentInfo;
 import android.content.pm.PackageItemInfo;
 import android.content.pm.PackageManager;
 import android.graphics.drawable.Drawable;
@@ -76,16 +77,15 @@
     public CharSequence loadLabel() {
         if (componentName != null) {
             try {
-                final ActivityInfo actInfo = AppGlobals.getPackageManager().getActivityInfo(
-                        componentName, 0, userId);
-                if (actInfo != null) {
-                    return actInfo.loadLabel(mPm.getPackageManager());
+                final ComponentInfo componentInfo = getComponentInfo();
+                if (componentInfo != null) {
+                    return componentInfo.loadLabel(mPm.getPackageManager());
                 } else {
                     final ApplicationInfo appInfo = mPm.getApplicationInfoAsUser(
                             componentName.getPackageName(), 0, userId);
                     return appInfo.loadLabel(mPm.getPackageManager());
                 }
-            } catch (RemoteException | PackageManager.NameNotFoundException e) {
+            } catch (PackageManager.NameNotFoundException e) {
                 return null;
             }
         } else if (packageItemInfo != null) {
@@ -100,16 +100,15 @@
     public Drawable loadIcon() {
         if (componentName != null) {
             try {
-                final ActivityInfo actInfo = AppGlobals.getPackageManager().getActivityInfo(
-                        componentName, 0, userId);
-                if (actInfo != null) {
-                    return actInfo.loadIcon(mPm.getPackageManager());
+                final ComponentInfo componentInfo = getComponentInfo();
+                if (componentInfo != null) {
+                    return componentInfo.loadIcon(mPm.getPackageManager());
                 } else {
                     final ApplicationInfo appInfo = mPm.getApplicationInfoAsUser(
                             componentName.getPackageName(), 0, userId);
                     return appInfo.loadIcon(mPm.getPackageManager());
                 }
-            } catch (RemoteException | PackageManager.NameNotFoundException e) {
+            } catch (PackageManager.NameNotFoundException e) {
                 return null;
             }
         }
@@ -130,4 +129,18 @@
             return null;
         }
     }
+
+    private ComponentInfo getComponentInfo() {
+        try {
+            ComponentInfo componentInfo = AppGlobals.getPackageManager().getActivityInfo(
+                    componentName, 0, userId);
+            if (componentInfo == null) {
+                componentInfo = AppGlobals.getPackageManager().getServiceInfo(
+                        componentName, 0, userId);
+            }
+            return componentInfo;
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
 }
diff --git a/src/com/android/settings/applications/defaultapps/DefaultAppPickerFragment.java b/src/com/android/settings/applications/defaultapps/DefaultAppPickerFragment.java
index d08ac99..98557ee 100644
--- a/src/com/android/settings/applications/defaultapps/DefaultAppPickerFragment.java
+++ b/src/com/android/settings/applications/defaultapps/DefaultAppPickerFragment.java
@@ -61,7 +61,6 @@
         }
     }
 
-
     @Override
     public void bindPreferenceExtra(RadioButtonPreference pref,
             String key, CandidateInfo info, String defaultKey, String systemDefaultKey) {
diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java
index 59cedf8..d1bb9d6 100644
--- a/src/com/android/settings/core/gateway/SettingsGateway.java
+++ b/src/com/android/settings/core/gateway/SettingsGateway.java
@@ -103,7 +103,6 @@
 import com.android.settings.notification.NotificationStation;
 import com.android.settings.notification.SoundSettings;
 import com.android.settings.notification.ZenAccessSettings;
-import com.android.settings.notification.ZenModeAutomationSettings;
 import com.android.settings.notification.ZenModeEventRuleSettings;
 import com.android.settings.notification.ZenModePrioritySettings;
 import com.android.settings.notification.ZenModeScheduleRuleSettings;
@@ -113,6 +112,7 @@
 import com.android.settings.print.PrintSettingsFragment;
 import com.android.settings.security.LockscreenDashboardFragment;
 import com.android.settings.sim.SimSettings;
+import com.android.settings.system.ResetDashboardFragment;
 import com.android.settings.system.SystemDashboardFragment;
 import com.android.settings.tts.TextToSpeechSettings;
 import com.android.settings.users.UserSettings;
@@ -206,7 +206,6 @@
             ApnEditor.class.getName(),
             WifiCallingSettings.class.getName(),
             ZenModePrioritySettings.class.getName(),
-            ZenModeAutomationSettings.class.getName(),
             ZenModeScheduleRuleSettings.class.getName(),
             ZenModeEventRuleSettings.class.getName(),
             ZenModeVisualInterruptionSettings.class.getName(),
@@ -231,6 +230,7 @@
             WifiAPITest.class.getName(),
             WifiInfo.class.getName(),
             MasterClear.class.getName(),
+            ResetDashboardFragment.class.getName(),
             NightDisplaySettings.class.getName(),
             ManageDomainUrls.class.getName(),
             AutomaticStorageManagerSettings.class.getName(),
diff --git a/src/com/android/settings/deviceinfo/StorageProfileFragment.java b/src/com/android/settings/deviceinfo/StorageProfileFragment.java
index 1a24962..c5d1045 100644
--- a/src/com/android/settings/deviceinfo/StorageProfileFragment.java
+++ b/src/com/android/settings/deviceinfo/StorageProfileFragment.java
@@ -73,8 +73,7 @@
 
         mPreferenceController.setVolume(mVolume);
         mUserId = args.getInt(USER_ID_EXTRA, UserHandle.myUserId());
-        // TODO(b/36224168): Use the user id to appropriately badge the preferences.
-        mPreferenceController.setUserId(mUserId);
+        mPreferenceController.setUserId(UserHandle.of(mUserId));
     }
 
     @Override
diff --git a/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java b/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
index e22aa24..5b27592 100644
--- a/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
@@ -20,6 +20,9 @@
 import android.content.ActivityNotFoundException;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.os.storage.VolumeInfo;
@@ -165,8 +168,35 @@
     /**
      * Sets the user id for which this preference controller is handling.
      */
-    public void setUserId(int userId) {
-        mUserId = userId;
+    public void setUserId(UserHandle userHandle) {
+        mUserId = userHandle.getIdentifier();
+
+        PackageManager pm = mContext.getPackageManager();
+        badgePreference(pm, userHandle, mPhotoPreference);
+        badgePreference(pm, userHandle, mAudioPreference);
+        badgePreference(pm, userHandle, mGamePreference);
+        badgePreference(pm, userHandle, mAppPreference);
+        badgePreference(pm, userHandle, mSystemPreference);
+        badgePreference(pm, userHandle, mFilePreference);
+    }
+
+    private void badgePreference(PackageManager pm, UserHandle userHandle, Preference preference) {
+        if (preference != null) {
+            Drawable currentIcon = preference.getIcon();
+            // Sigh... Applying the badge to the icon clobbers the tint on the base drawable.
+            // For some reason, re-applying it here means the tint remains.
+            currentIcon = applyTint(mContext, currentIcon);
+            preference.setIcon(pm.getUserBadgedIcon(currentIcon, userHandle));
+        }
+    }
+
+    private static Drawable applyTint(Context context, Drawable icon) {
+        TypedArray array =
+                context.obtainStyledAttributes(new int[]{android.R.attr.colorControlNormal});
+        icon = icon.mutate();
+        icon.setTint(array.getColor(0, 0));
+        array.recycle();
+        return icon;
     }
 
     @Override
diff --git a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
new file mode 100644
index 0000000..73cb5b5
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.fuelgauge;
+
+import android.content.Context;
+import android.os.BatteryStats;
+import android.os.Bundle;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.support.annotation.VisibleForTesting;
+import android.support.v14.preference.PreferenceFragment;
+import android.support.v7.preference.Preference;
+import android.view.View;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.os.BatterySipper;
+import com.android.internal.os.BatteryStatsHelper;
+import com.android.internal.util.ArrayUtils;
+import com.android.settings.R;
+import com.android.settings.SettingsActivity;
+import com.android.settings.Utils;
+import com.android.settings.applications.AppHeaderController;
+import com.android.settings.applications.LayoutPreference;
+import com.android.settings.core.PreferenceController;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settingslib.applications.ApplicationsState;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Power usage detail fragment for each app, this fragment contains
+ *
+ * 1. Detail battery usage information for app(i.e. usage time, usage amount)
+ * 2. Battery related controls for app(i.e uninstall, force stop)
+ *
+ * This fragment will replace {@link PowerUsageDetail}
+ */
+public class AdvancedPowerUsageDetail extends PowerUsageBase {
+
+    public static final String TAG = "AdvancedPowerUsageDetail";
+    public static final String EXTRA_UID = "extra_uid";
+    public static final String EXTRA_PACKAGE_NAME = "extra_package_name";
+    public static final String EXTRA_FOREGROUND_TIME = "extra_foreground_time";
+    public static final String EXTRA_BACKGROUND_TIME = "extra_background_time";
+    public static final String EXTRA_LABEL = "extra_label";
+    public static final String EXTRA_ICON_ID = "extra_icon_id";
+    public static final String EXTRA_POWER_USAGE_PERCENT = "extra_power_usage_percent";
+    public static final String EXTRA_POWER_USAGE_AMOUNT = "extra_power_usage_amount";
+
+    private static final String KEY_PREF_FOREGROUND = "app_usage_foreground";
+    private static final String KEY_PREF_BACKGROUND = "app_usage_background";
+    private static final String KEY_PREF_POWER_USAGE = "app_power_usage";
+    private static final String KEY_PREF_HEADER = "header_view";
+
+    @VisibleForTesting
+    LayoutPreference mHeaderPreference;
+    @VisibleForTesting
+    ApplicationsState mState;
+    @VisibleForTesting
+    ApplicationsState.AppEntry mAppEntry;
+
+    private Preference mForegroundPreference;
+    private Preference mBackgroundPreference;
+    private Preference mPowerUsagePreference;
+
+    public static void startBatteryDetailPage(SettingsActivity caller, PreferenceFragment fragment,
+            BatteryStatsHelper helper, int which, BatteryEntry entry, String usagePercent) {
+        // Initialize mStats if necessary.
+        helper.getStats();
+
+        final Bundle args = new Bundle();
+        final BatterySipper sipper = entry.sipper;
+        final BatteryStats.Uid uid = sipper.uidObj;
+
+        final long backgroundTimeMs = BatteryUtils.getProcessTimeMs(
+                BatteryUtils.StatusType.BACKGROUND, uid, which);
+        final long foregroundTimeMs = BatteryUtils.getProcessTimeMs(
+                BatteryUtils.StatusType.FOREGROUND, uid, which);
+
+        if (ArrayUtils.isEmpty(sipper.mPackages)) {
+            // populate data for system app
+            args.putString(EXTRA_LABEL, entry.getLabel());
+            args.putInt(EXTRA_ICON_ID, entry.iconId);
+            args.putString(EXTRA_PACKAGE_NAME, null);
+        } else {
+            // populate data for normal app
+            args.putString(EXTRA_PACKAGE_NAME, sipper.mPackages[0]);
+        }
+
+        args.putInt(EXTRA_UID, sipper.getUid());
+        args.putLong(EXTRA_BACKGROUND_TIME, backgroundTimeMs);
+        args.putLong(EXTRA_FOREGROUND_TIME, foregroundTimeMs);
+        args.putString(EXTRA_POWER_USAGE_PERCENT, usagePercent);
+        args.putInt(EXTRA_POWER_USAGE_AMOUNT, (int) sipper.totalPowerMah);
+
+        caller.startPreferencePanelAsUser(fragment, AdvancedPowerUsageDetail.class.getName(), args,
+                R.string.battery_details_title, null, new UserHandle(UserHandle.myUserId()));
+    }
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        mForegroundPreference = findPreference(KEY_PREF_FOREGROUND);
+        mBackgroundPreference = findPreference(KEY_PREF_BACKGROUND);
+        mPowerUsagePreference = findPreference(KEY_PREF_POWER_USAGE);
+        mHeaderPreference = (LayoutPreference) findPreference(KEY_PREF_HEADER);
+        mState = ApplicationsState.getInstance(getActivity().getApplication());
+
+        final String packageName = getArguments().getString(EXTRA_PACKAGE_NAME);
+        if (packageName != null) {
+            mAppEntry = mState.getEntry(packageName, UserHandle.myUserId());
+        }
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+
+        initHeader();
+
+        final Bundle bundle = getArguments();
+        final Context context = getContext();
+
+        final long foregroundTimeMs = bundle.getLong(EXTRA_FOREGROUND_TIME);
+        final long backgroundTimeMs = bundle.getLong(EXTRA_BACKGROUND_TIME);
+        final String usagePercent = bundle.getString(EXTRA_POWER_USAGE_PERCENT);
+        final int powerMah = bundle.getInt(EXTRA_POWER_USAGE_AMOUNT);
+        mForegroundPreference.setSummary(Utils.formatElapsedTime(context, foregroundTimeMs, false));
+        mBackgroundPreference.setSummary(Utils.formatElapsedTime(context, backgroundTimeMs, false));
+        mPowerUsagePreference.setSummary(
+                getString(R.string.battery_detail_power_percentage, usagePercent, powerMah));
+    }
+
+    @VisibleForTesting
+    void initHeader() {
+        final View appSnippet = mHeaderPreference.findViewById(R.id.app_snippet);
+        final Context context = getContext();
+        final Bundle bundle = getArguments();
+        AppHeaderController controller = FeatureFactory.getFactory(context)
+                .getApplicationFeatureProvider(context)
+                .newAppHeaderController(this, appSnippet)
+                .setButtonActions(AppHeaderController.ActionType.ACTION_NONE,
+                        AppHeaderController.ActionType.ACTION_NONE);
+
+        if (mAppEntry == null) {
+            controller.setLabel(bundle.getString(EXTRA_LABEL));
+            controller.setIcon(getContext().getDrawable(bundle.getInt(EXTRA_ICON_ID)));
+        } else {
+            mState.ensureIcon(mAppEntry);
+            controller.setLabel(mAppEntry);
+            controller.setIcon(mAppEntry);
+            controller.setSummary(getString(Utils.getInstallationStatus(mAppEntry.info)));
+        }
+
+        controller.done(true /* rebindActions */);
+    }
+
+    @Override
+    public int getMetricsCategory() {
+        return MetricsEvent.FUELGAUGE_POWER_USAGE_DETAIL;
+    }
+
+    @Override
+    protected String getLogTag() {
+        return TAG;
+    }
+
+    @Override
+    protected int getPreferenceScreenResId() {
+        return R.xml.power_usage_detail_ia;
+    }
+
+    @Override
+    protected List<PreferenceController> getPreferenceControllers(Context context) {
+        final List<PreferenceController> controllers = new ArrayList<>();
+        final Bundle bundle = getArguments();
+        final int uid = bundle.getInt(EXTRA_UID, 0);
+        final String packageName = bundle.getString(EXTRA_PACKAGE_NAME);
+
+        controllers.add(new BackgroundActivityPreferenceController(context, uid));
+        controllers.add(new BatteryOptimizationPreferenceController(
+                (SettingsActivity) getActivity(), this));
+        controllers.add(
+                new AppButtonsPreferenceController(getActivity(), getLifecycle(), packageName));
+
+        return controllers;
+    }
+}
diff --git a/src/com/android/settings/fuelgauge/AppButtonsPreferenceController.java b/src/com/android/settings/fuelgauge/AppButtonsPreferenceController.java
new file mode 100644
index 0000000..b02c8c5
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/AppButtonsPreferenceController.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.fuelgauge;
+
+import android.app.Activity;
+import android.os.UserHandle;
+import android.support.v7.preference.PreferenceScreen;
+import android.view.View;
+import android.widget.Button;
+
+import com.android.settings.R;
+import com.android.settings.applications.LayoutPreference;
+import com.android.settings.core.PreferenceController;
+import com.android.settings.core.lifecycle.Lifecycle;
+import com.android.settings.core.lifecycle.LifecycleObserver;
+import com.android.settings.core.lifecycle.events.OnResume;
+import com.android.settingslib.applications.ApplicationsState;
+
+/**
+ * Controller to control the uninstall button and forcestop button
+ */
+//TODO(b/35810915): refine the button logic and make InstalledAppDetails use this controller
+//TODO(b/35810915): add test for this file
+public class AppButtonsPreferenceController extends PreferenceController implements
+        LifecycleObserver, OnResume {
+    private static final String KEY_ACTION_BUTTONS = "action_buttons";
+
+    private ApplicationsState.AppEntry mAppEntry;
+    private LayoutPreference mButtonsPref;
+    private Button mForceStopButton;
+    private Button mUninstallButton;
+
+    public AppButtonsPreferenceController(Activity activity, Lifecycle lifecycle,
+            String packageName) {
+        super(activity);
+
+        lifecycle.addObserver(this);
+        ApplicationsState state = ApplicationsState.getInstance(activity.getApplication());
+
+        if (packageName != null) {
+            mAppEntry = state.getEntry(packageName, UserHandle.myUserId());
+        }
+    }
+
+    @Override
+    public boolean isAvailable() {
+        return mAppEntry != null;
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        if (isAvailable()) {
+            mButtonsPref = (LayoutPreference) screen.findPreference(KEY_ACTION_BUTTONS);
+
+            mUninstallButton = (Button) mButtonsPref.findViewById(R.id.left_button);
+            mUninstallButton.setText(R.string.uninstall_text);
+
+            mForceStopButton = (Button) mButtonsPref.findViewById(R.id.right_button);
+            mForceStopButton.setText(R.string.force_stop);
+        }
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return KEY_ACTION_BUTTONS;
+    }
+
+    @Override
+    public void onResume() {
+        //TODO(b/35810915): check and update the status of buttons
+    }
+}
diff --git a/src/com/android/settings/fuelgauge/BackgroundActivityPreferenceController.java b/src/com/android/settings/fuelgauge/BackgroundActivityPreferenceController.java
index 0f08398..c249676 100644
--- a/src/com/android/settings/fuelgauge/BackgroundActivityPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/BackgroundActivityPreferenceController.java
@@ -23,6 +23,8 @@
 import android.support.v14.preference.SwitchPreference;
 import android.support.v7.preference.Preference;
 import android.util.Log;
+
+import com.android.settings.R;
 import com.android.settings.core.PreferenceController;
 
 /**
@@ -56,8 +58,12 @@
 
         if (mode == AppOpsManager.MODE_ERRORED) {
             preference.setEnabled(false);
+            preference.setSummary(R.string.background_activity_summary_disabled);
         } else {
-            ((SwitchPreference) preference).setChecked(mode != AppOpsManager.MODE_IGNORED);
+            final boolean checked = mode != AppOpsManager.MODE_IGNORED;
+            ((SwitchPreference) preference).setChecked(checked);
+            preference.setSummary(checked ? R.string.background_activity_summary_on
+                    : R.string.background_activity_summary_off);
         }
     }
 
diff --git a/src/com/android/settings/fuelgauge/BatteryOptimizationPreferenceController.java b/src/com/android/settings/fuelgauge/BatteryOptimizationPreferenceController.java
new file mode 100644
index 0000000..946a9b8
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/BatteryOptimizationPreferenceController.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.settings.fuelgauge;
+
+import android.app.Fragment;
+import android.content.Context;
+import android.os.Bundle;
+import android.support.v7.preference.Preference;
+import android.text.TextUtils;
+
+import com.android.settings.R;
+import com.android.settings.Settings;
+import com.android.settings.SettingsActivity;
+import com.android.settings.applications.ManageApplications;
+import com.android.settings.core.PreferenceController;
+
+/**
+ * Controller that jumps to high power optimization fragment
+ */
+public class BatteryOptimizationPreferenceController extends PreferenceController {
+
+    private static final String KEY_BACKGROUND_ACTIVITY = "battery_optimization";
+
+    private Fragment mFragment;
+    private SettingsActivity mSettingsActivity;
+
+    public BatteryOptimizationPreferenceController(SettingsActivity settingsActivity,
+            Fragment fragment) {
+        super(settingsActivity);
+        mFragment = fragment;
+        mSettingsActivity = settingsActivity;
+    }
+
+    @Override
+    public boolean isAvailable() {
+        return true;
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return KEY_BACKGROUND_ACTIVITY;
+    }
+
+    @Override
+    public boolean handlePreferenceTreeClick(Preference preference) {
+        if (!KEY_BACKGROUND_ACTIVITY.equals(preference.getKey())) {
+            return false;
+        }
+
+        Bundle args = new Bundle(1);
+        args.putString(ManageApplications.EXTRA_CLASSNAME,
+                Settings.HighPowerApplicationsActivity.class.getName());
+        mSettingsActivity.startPreferencePanel(mFragment, ManageApplications.class.getName(), args,
+                R.string.high_power_apps, null, null, 0);
+        return true;
+    }
+}
diff --git a/src/com/android/settings/fuelgauge/BatteryUtils.java b/src/com/android/settings/fuelgauge/BatteryUtils.java
new file mode 100644
index 0000000..85bc0fd
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/BatteryUtils.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settings.fuelgauge;
+
+import android.annotation.IntDef;
+import android.os.BatteryStats;
+import android.os.SystemClock;
+import android.support.annotation.Nullable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Utils for battery operation
+ */
+public class BatteryUtils {
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({StatusType.FOREGROUND,
+            StatusType.BACKGROUND,
+            StatusType.ALL
+    })
+    public @interface StatusType {
+        int FOREGROUND = 0;
+        int BACKGROUND = 1;
+        int ALL = 2;
+    }
+
+    public static long getProcessTimeMs(@StatusType int type, @Nullable BatteryStats.Uid uid,
+            int which) {
+        if (uid == null) {
+            return 0;
+        }
+
+        switch (type) {
+            case StatusType.FOREGROUND:
+                return getProcessForegroundTimeMs(uid, which);
+            case StatusType.BACKGROUND:
+                return getProcessBackgroundTimeMs(uid, which);
+            case StatusType.ALL:
+                return getProcessForegroundTimeMs(uid, which)
+                        + getProcessBackgroundTimeMs(uid, which);
+        }
+        return 0;
+    }
+
+    private static long getProcessBackgroundTimeMs(BatteryStats.Uid uid, int which) {
+        final long rawRealTimeUs = convertMsToUs(SystemClock.elapsedRealtime());
+        final long timeUs = uid.getProcessStateTime(
+                BatteryStats.Uid.PROCESS_STATE_BACKGROUND, rawRealTimeUs, which);
+        return  convertUsToMs(timeUs);
+    }
+
+    private static long getProcessForegroundTimeMs(BatteryStats.Uid uid, int which) {
+        final long rawRealTimeUs = convertMsToUs(SystemClock.elapsedRealtime());
+        final int foregroundTypes[] = {BatteryStats.Uid.PROCESS_STATE_TOP,
+                BatteryStats.Uid.PROCESS_STATE_FOREGROUND_SERVICE,
+                BatteryStats.Uid.PROCESS_STATE_TOP_SLEEPING,
+                BatteryStats.Uid.PROCESS_STATE_FOREGROUND};
+        long timeUs = 0;
+        for (int type : foregroundTypes) {
+            timeUs += uid.getProcessStateTime(type, rawRealTimeUs, which);
+        }
+
+        return convertUsToMs(timeUs);
+    }
+
+    private static long convertUsToMs(long timeUs) {
+        return timeUs / 1000;
+    }
+
+    private static long convertMsToUs(long timeMs) {
+        return timeMs * 1000;
+    }
+
+}
+
diff --git a/src/com/android/settings/fuelgauge/FakeUid.java b/src/com/android/settings/fuelgauge/FakeUid.java
index 4faa832..770c567 100644
--- a/src/com/android/settings/fuelgauge/FakeUid.java
+++ b/src/com/android/settings/fuelgauge/FakeUid.java
@@ -142,6 +142,21 @@
     }
 
     @Override
+    public int getWifiScanBackgroundCount(int which)  {
+        return 0;
+    }
+
+    @Override
+    public long getWifiScanActualTime(long elapsedRealtimeUs)  {
+        return 0;
+    }
+
+    @Override
+    public long getWifiScanBackgroundTime(long elapsedRealtimeUs)  {
+        return 0;
+    }
+
+    @Override
     public long getWifiBatchedScanTime(int csphBin, long elapsedRealtimeUs, int which) {
         return 0;
     }
@@ -276,6 +291,11 @@
     }
 
     @Override
+    public Timer getBluetoothScanBackgroundTimer() {
+        return null;
+    }
+
+    @Override
     public long getWifiRadioApWakeupCount(int which) {
         return 0;
     }
diff --git a/src/com/android/settings/fuelgauge/PowerGaugePreference.java b/src/com/android/settings/fuelgauge/PowerGaugePreference.java
index fe7ef6e..d4f2dd2 100644
--- a/src/com/android/settings/fuelgauge/PowerGaugePreference.java
+++ b/src/com/android/settings/fuelgauge/PowerGaugePreference.java
@@ -63,6 +63,10 @@
         notifyChanged();
     }
 
+    public String getPercent() {
+        return mProgress.toString();
+    }
+
     BatteryEntry getInfo() {
         return mInfo;
     }
diff --git a/src/com/android/settings/fuelgauge/PowerUsageDetail.java b/src/com/android/settings/fuelgauge/PowerUsageDetail.java
index 956b279..f0d0a10 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageDetail.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageDetail.java
@@ -69,6 +69,7 @@
 import java.util.ArrayList;
 import java.util.List;
 
+// TODO(b/35810915): Delete this page once ag/1971493 is done.
 public class PowerUsageDetail extends PowerUsageBase implements Button.OnClickListener {
 
     // Note: Must match the sequence of the DrainType
diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
index 1ffc594..b0e8fb0 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
@@ -165,8 +165,8 @@
         }
         PowerGaugePreference pgp = (PowerGaugePreference) preference;
         BatteryEntry entry = pgp.getInfo();
-        PowerUsageDetail.startBatteryDetailPage((SettingsActivity) getActivity(), this,
-                mStatsHelper, mStatsType, entry, true, true);
+        AdvancedPowerUsageDetail.startBatteryDetailPage((SettingsActivity) getActivity(),
+                this, mStatsHelper, mStatsType, entry, pgp.getPercent());
         return super.onPreferenceTreeClick(preference);
     }
 
diff --git a/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java b/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java
index ad6e041..42eff15 100644
--- a/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java
+++ b/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java
@@ -136,7 +136,7 @@
         unregisterShowVirtualKeyboardSettingsObserver();
     }
 
-    public void onLoadFinishedInternal(
+    private void onLoadFinishedInternal(
             final int loaderId, @NonNull final List<Keyboards> keyboardsList) {
         if (!mLoaderIDs.remove(loaderId)) {
             // Already destroyed loader.  Ignore.
@@ -198,8 +198,8 @@
     }
 
     @NonNull
-    private static ArrayList<HardKeyboardDeviceInfo> getHardKeyboards() {
-        final ArrayList<HardKeyboardDeviceInfo> keyboards = new ArrayList<>();
+    public static List<HardKeyboardDeviceInfo> getHardKeyboards() {
+        final List<HardKeyboardDeviceInfo> keyboards = new ArrayList<>();
         final int[] devicesIds = InputDevice.getDeviceIds();
         for (int deviceId : devicesIds) {
             final InputDevice device = InputDevice.getDevice(deviceId);
@@ -211,7 +211,7 @@
     }
 
     private void updateHardKeyboards() {
-        final ArrayList<HardKeyboardDeviceInfo> newHardKeyboards = getHardKeyboards();
+        final List<HardKeyboardDeviceInfo> newHardKeyboards = getHardKeyboards();
         if (!Objects.equals(newHardKeyboards, mLastHardKeyboards)) {
             clearLoader();
             mLastHardKeyboards.clear();
diff --git a/src/com/android/settings/inputmethod/PhysicalKeyboardPreferenceController.java b/src/com/android/settings/inputmethod/PhysicalKeyboardPreferenceController.java
new file mode 100644
index 0000000..aa9f5ad
--- /dev/null
+++ b/src/com/android/settings/inputmethod/PhysicalKeyboardPreferenceController.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.inputmethod;
+
+import android.content.Context;
+import android.hardware.input.InputManager;
+import android.support.v7.preference.Preference;
+
+import com.android.settings.R;
+import com.android.settings.core.PreferenceController;
+import com.android.settings.core.lifecycle.Lifecycle;
+import com.android.settings.core.lifecycle.LifecycleObserver;
+import com.android.settings.core.lifecycle.events.OnPause;
+import com.android.settings.core.lifecycle.events.OnResume;
+import com.android.settings.inputmethod.PhysicalKeyboardFragment.HardKeyboardDeviceInfo;
+
+import java.util.List;
+
+public class PhysicalKeyboardPreferenceController extends PreferenceController implements
+        LifecycleObserver, OnResume, OnPause, InputManager.InputDeviceListener {
+
+    private final InputManager mIm;
+
+    private Preference mPreference;
+
+    public PhysicalKeyboardPreferenceController(Context context, Lifecycle lifecycle) {
+        super(context);
+        mIm = (InputManager) context.getSystemService(Context.INPUT_SERVICE);
+
+        if (lifecycle != null) {
+            lifecycle.addObserver(this);
+        }
+    }
+
+    @Override
+    public boolean isAvailable() {
+        return true;
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        mPreference = preference;
+        updateSummary();
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return "physical_keyboard_pref";
+    }
+
+    @Override
+    public void onPause() {
+        mIm.registerInputDeviceListener(this, null);
+    }
+
+    @Override
+    public void onResume() {
+        mIm.unregisterInputDeviceListener(this);
+    }
+
+    @Override
+    public void onInputDeviceAdded(int deviceId) {
+        updateSummary();
+    }
+
+    @Override
+    public void onInputDeviceRemoved(int deviceId) {
+        updateSummary();
+    }
+
+    @Override
+    public void onInputDeviceChanged(int deviceId) {
+        updateSummary();
+    }
+
+    private void updateSummary() {
+        if (mPreference == null) {
+            return;
+        }
+        final List<HardKeyboardDeviceInfo> keyboards =
+                PhysicalKeyboardFragment.getHardKeyboards();
+        if (keyboards.isEmpty()) {
+            mPreference.setSummary(R.string.disconnected);
+            return;
+        }
+        String summary = null;
+        for (HardKeyboardDeviceInfo info : keyboards) {
+            if (summary == null) {
+                summary = info.mDeviceName;
+            } else {
+                summary = mContext.getString(R.string.join_many_items_middle, summary,
+                        info.mDeviceName);
+            }
+        }
+        mPreference.setSummary(summary);
+    }
+}
diff --git a/src/com/android/settings/inputmethod/VirtualKeyboardPreferenceController.java b/src/com/android/settings/inputmethod/VirtualKeyboardPreferenceController.java
new file mode 100644
index 0000000..b7bf3dc
--- /dev/null
+++ b/src/com/android/settings/inputmethod/VirtualKeyboardPreferenceController.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.inputmethod;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.support.v7.preference.Preference;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodManager;
+
+import com.android.settings.R;
+import com.android.settings.core.PreferenceController;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class VirtualKeyboardPreferenceController extends PreferenceController {
+
+    private final InputMethodManager mImm;
+    private final DevicePolicyManager mDpm;
+    private final PackageManager mPm;
+
+    public VirtualKeyboardPreferenceController(Context context) {
+        super(context);
+        mPm = mContext.getPackageManager();
+        mDpm = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
+        mImm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
+    }
+
+    @Override
+    public boolean isAvailable() {
+        return true;
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return "virtual_keyboard_pref";
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        final List<InputMethodInfo> imis = mImm.getEnabledInputMethodList();
+        if (imis == null) {
+            preference.setSummary(R.string.summary_empty);
+            return;
+        }
+
+        final List<String> permittedList = mDpm.getPermittedInputMethodsForCurrentUser();
+        final List<String> labels = new ArrayList<>();
+
+        for (InputMethodInfo imi : imis) {
+            final boolean isAllowedByOrganization = permittedList == null
+                    || permittedList.contains(imi.getPackageName());
+            if (!isAllowedByOrganization) {
+                continue;
+            }
+            labels.add(imi.loadLabel(mPm).toString());
+        }
+        if (labels.isEmpty()) {
+            preference.setSummary(R.string.summary_empty);
+            return;
+        }
+
+        String summary = null;
+        for (String label : labels) {
+            if (summary == null) {
+                summary = label;
+            } else {
+                summary = mContext.getString(R.string.join_many_items_middle, summary, label);
+            }
+        }
+        preference.setSummary(summary);
+    }
+}
diff --git a/src/com/android/settings/language/LanguageAndInputSettings.java b/src/com/android/settings/language/LanguageAndInputSettings.java
index 5a2c0c7..86ce118 100644
--- a/src/com/android/settings/language/LanguageAndInputSettings.java
+++ b/src/com/android/settings/language/LanguageAndInputSettings.java
@@ -43,7 +43,9 @@
 import com.android.settings.gestures.PickupGesturePreferenceController;
 import com.android.settings.gestures.SwipeToNotificationPreferenceController;
 import com.android.settings.inputmethod.GameControllerPreferenceController;
+import com.android.settings.inputmethod.PhysicalKeyboardPreferenceController;
 import com.android.settings.inputmethod.SpellCheckerPreferenceController;
+import com.android.settings.inputmethod.VirtualKeyboardPreferenceController;
 import com.android.settings.search.BaseSearchIndexProvider;
 
 import java.util.ArrayList;
@@ -87,9 +89,11 @@
         controllers.add(new UserDictionaryPreferenceController(context));
         controllers.add(new TtsPreferenceController(context, new TtsEngines(context)));
         // Input
+        controllers.add(new VirtualKeyboardPreferenceController(context));
+        controllers.add(new PhysicalKeyboardPreferenceController(context, lifecycle));
         final GameControllerPreferenceController gameControllerPreferenceController
                 = new GameControllerPreferenceController(context);
-        getLifecycle().addObserver(gameControllerPreferenceController);
+        lifecycle.addObserver(gameControllerPreferenceController);
 
         if (mAmbientDisplayConfig == null) {
             mAmbientDisplayConfig = new AmbientDisplayConfiguration(context);
diff --git a/src/com/android/settings/network/NetworkResetActionMenuController.java b/src/com/android/settings/network/NetworkResetActionMenuController.java
index d5065d1..028ac7b 100644
--- a/src/com/android/settings/network/NetworkResetActionMenuController.java
+++ b/src/com/android/settings/network/NetworkResetActionMenuController.java
@@ -55,7 +55,12 @@
 
     @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
     boolean isAvailable() {
-        return !RestrictedLockUtils.hasBaseUserRestriction(mContext,
+        return isAvailable(mContext);
+    }
+
+    static boolean isAvailable(Context context) {
+        return !RestrictedLockUtils.hasBaseUserRestriction(context,
                 UserManager.DISALLOW_NETWORK_RESET, UserHandle.myUserId());
     }
+
 }
diff --git a/src/com/android/settings/network/NetworkResetPreferenceController.java b/src/com/android/settings/network/NetworkResetPreferenceController.java
new file mode 100644
index 0000000..04573c9
--- /dev/null
+++ b/src/com/android/settings/network/NetworkResetPreferenceController.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network;
+
+import android.content.Context;
+
+import com.android.settings.core.PreferenceController;
+
+public class NetworkResetPreferenceController extends PreferenceController {
+
+    public NetworkResetPreferenceController(Context context) {
+        super(context);
+    }
+
+    @Override
+    public boolean isAvailable() {
+        return NetworkResetActionMenuController.isAvailable(mContext);
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return "network_reset_pref";
+    }
+}
diff --git a/src/com/android/settings/notification/VibrateOnTouchPreferenceController.java b/src/com/android/settings/notification/VibrateOnTouchPreferenceController.java
index 8fd938e..544c372 100644
--- a/src/com/android/settings/notification/VibrateOnTouchPreferenceController.java
+++ b/src/com/android/settings/notification/VibrateOnTouchPreferenceController.java
@@ -32,7 +32,7 @@
             Lifecycle lifecycle) {
         super(context, parent, lifecycle);
         mPreference = new SettingPref(
-            TYPE_SYSTEM, KEY_VIBRATE_ON_TOUCH, System.HAPTIC_FEEDBACK_ENABLED, DEFAULT_ON) {
+            TYPE_SYSTEM, KEY_VIBRATE_ON_TOUCH, System.HAPTIC_FEEDBACK_ENABLED, 0) {
             @Override
             public boolean isApplicable(Context context) {
                 return hasHaptic(context);
diff --git a/src/com/android/settings/notification/ZenModeAutomationSettings.java b/src/com/android/settings/notification/ZenModeAutomationSettings.java
deleted file mode 100644
index 495e499..0000000
--- a/src/com/android/settings/notification/ZenModeAutomationSettings.java
+++ /dev/null
@@ -1,362 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.notification;
-
-import android.app.AlertDialog;
-import android.app.AutomaticZenRule;
-import android.app.NotificationManager;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ServiceInfo;
-import android.content.res.Resources;
-import android.graphics.drawable.Drawable;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.provider.Settings;
-import android.service.notification.ConditionProviderService;
-import android.service.notification.ZenModeConfig;
-import android.support.v7.preference.Preference;
-import android.support.v7.preference.Preference.OnPreferenceClickListener;
-import android.support.v7.preference.PreferenceScreen;
-import android.support.v7.preference.PreferenceViewHolder;
-import android.view.View;
-
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.settings.R;
-import com.android.settings.utils.ManagedServiceSettings.Config;
-import com.android.settings.utils.ZenServiceListing;
-
-import java.lang.ref.WeakReference;
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.Map;
-
-public class ZenModeAutomationSettings extends ZenModeSettingsBase {
-
-    static final Config CONFIG = getConditionProviderConfig();
-
-    private PackageManager mPm;
-    private ZenServiceListing mServiceListing;
-
-    @Override
-    public void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
-        addPreferencesFromResource(R.xml.zen_mode_automation_settings);
-        mPm = mContext.getPackageManager();
-        mServiceListing = new ZenServiceListing(mContext, CONFIG);
-        mServiceListing.reloadApprovedServices();
-    }
-
-    @Override
-    public void onDestroy() {
-        super.onDestroy();
-    }
-
-    @Override
-    protected void onZenModeChanged() {
-        // don't care
-    }
-
-    @Override
-    protected void onZenModeConfigChanged() {
-        updateControls();
-    }
-
-    @Override
-    public void onResume() {
-        super.onResume();
-        if (isUiRestricted()) {
-            return;
-        }
-        updateControls();
-    }
-
-    private void showAddRuleDialog() {
-        new ZenRuleSelectionDialog(mContext, mServiceListing) {
-            @Override
-            public void onSystemRuleSelected(ZenRuleInfo ri) {
-                showNameRuleDialog(ri);
-            }
-
-            @Override
-            public void onExternalRuleSelected(ZenRuleInfo ri) {
-                Intent intent = new Intent().setComponent(ri.configurationActivity);
-                startActivity(intent);
-            }
-        }.show();
-    }
-
-    private void showNameRuleDialog(final ZenRuleInfo ri) {
-        new ZenRuleNameDialog(mContext, null) {
-            @Override
-            public void onOk(String ruleName) {
-                mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_ZEN_ADD_RULE_OK);
-                AutomaticZenRule rule = new AutomaticZenRule(ruleName, ri.serviceComponent,
-                        ri.defaultConditionId, NotificationManager.INTERRUPTION_FILTER_PRIORITY,
-                        true);
-                String savedRuleId = addZenRule(rule);
-                if (savedRuleId != null) {
-                    startActivity(getRuleIntent(ri.settingsAction, null, savedRuleId));
-                }
-            }
-        }.show();
-    }
-
-    private void showDeleteRuleDialog(final String ruleId, final CharSequence ruleName) {
-        new AlertDialog.Builder(mContext)
-                .setMessage(getString(R.string.zen_mode_delete_rule_confirmation, ruleName))
-                .setNegativeButton(R.string.cancel, null)
-                .setPositiveButton(R.string.zen_mode_delete_rule_button,
-                        new DialogInterface.OnClickListener() {
-                    @Override
-                    public void onClick(DialogInterface dialog, int which) {
-                        mMetricsFeatureProvider.action(mContext,
-                                MetricsEvent.ACTION_ZEN_DELETE_RULE_OK);
-                        removeZenRule(ruleId);
-                    }
-                })
-                .show();
-    }
-
-    private Intent getRuleIntent(String settingsAction, ComponentName configurationActivity,
-            String ruleId) {
-        Intent intent = new Intent()
-                .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
-                .putExtra(ConditionProviderService.EXTRA_RULE_ID, ruleId);
-        if (configurationActivity != null) {
-            intent.setComponent(configurationActivity);
-        } else {
-            intent.setAction(settingsAction);
-        }
-        return intent;
-    }
-
-    private Map.Entry<String,AutomaticZenRule>[] sortedRules() {
-        final Map.Entry<String,AutomaticZenRule>[] rt =
-                mRules.toArray(new Map.Entry[mRules.size()]);
-        Arrays.sort(rt, RULE_COMPARATOR);
-        return rt;
-    }
-
-    private void updateControls() {
-        final PreferenceScreen root = getPreferenceScreen();
-        root.removeAll();
-        final Map.Entry<String,AutomaticZenRule>[] sortedRules = sortedRules();
-        for (Map.Entry<String,AutomaticZenRule> sortedRule : sortedRules) {
-            ZenRulePreference pref = new ZenRulePreference(getPrefContext(), sortedRule);
-            if (pref.appExists) {
-                root.addPreference(pref);
-            }
-        }
-        final Preference p = new Preference(getPrefContext());
-        p.setIcon(R.drawable.ic_add);
-        p.setTitle(R.string.zen_mode_add_rule);
-        p.setPersistent(false);
-        p.setOnPreferenceClickListener(new OnPreferenceClickListener() {
-            @Override
-            public boolean onPreferenceClick(Preference preference) {
-                mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_ZEN_ADD_RULE);
-                showAddRuleDialog();
-                return true;
-            }
-        });
-        root.addPreference(p);
-    }
-
-    @Override
-    public int getMetricsCategory() {
-        return MetricsEvent.NOTIFICATION_ZEN_MODE_AUTOMATION;
-    }
-
-    private String computeRuleSummary(AutomaticZenRule rule, boolean isSystemRule,
-            CharSequence providerLabel) {
-        final String mode = computeZenModeCaption(getResources(), rule.getInterruptionFilter());
-        final String ruleState = (rule == null || !rule.isEnabled())
-                ? getString(R.string.switch_off_text)
-                : getString(R.string.zen_mode_rule_summary_enabled_combination, mode);
-
-        return isSystemRule ? ruleState
-                : getString(R.string.zen_mode_rule_summary_provider_combination,
-                        providerLabel, ruleState);
-    }
-
-    private static Config getConditionProviderConfig() {
-        final Config c = new Config();
-        c.tag = TAG;
-        c.setting = Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES;
-        c.secondarySetting = Settings.Secure.ENABLED_NOTIFICATION_LISTENERS;
-        c.intentAction = ConditionProviderService.SERVICE_INTERFACE;
-        c.permission = android.Manifest.permission.BIND_CONDITION_PROVIDER_SERVICE;
-        c.noun = "condition provider";
-        return c;
-    }
-
-    private static String computeZenModeCaption(Resources res, int zenMode) {
-        switch (zenMode) {
-            case NotificationManager.INTERRUPTION_FILTER_ALARMS:
-                return res.getString(R.string.zen_mode_option_alarms);
-            case NotificationManager.INTERRUPTION_FILTER_PRIORITY:
-                return res.getString(R.string.zen_mode_option_important_interruptions);
-            case NotificationManager.INTERRUPTION_FILTER_NONE:
-                return res.getString(R.string.zen_mode_option_no_interruptions);
-            default:
-                return null;
-        }
-    }
-
-    public static ZenRuleInfo getRuleInfo(PackageManager pm, ServiceInfo si) {
-        if (si == null || si.metaData == null) return null;
-        final String ruleType = si.metaData.getString(ConditionProviderService.META_DATA_RULE_TYPE);
-        final ComponentName configurationActivity = getSettingsActivity(si);
-        if (ruleType != null && !ruleType.trim().isEmpty() && configurationActivity != null) {
-            final ZenRuleInfo ri = new ZenRuleInfo();
-            ri.serviceComponent = new ComponentName(si.packageName, si.name);
-            ri.settingsAction = Settings.ACTION_ZEN_MODE_EXTERNAL_RULE_SETTINGS;
-            ri.title = ruleType;
-            ri.packageName = si.packageName;
-            ri.configurationActivity = getSettingsActivity(si);
-            ri.packageLabel = si.applicationInfo.loadLabel(pm);
-            ri.ruleInstanceLimit =
-                    si.metaData.getInt(ConditionProviderService.META_DATA_RULE_INSTANCE_LIMIT, -1);
-            return ri;
-        }
-        return null;
-    }
-
-    private static ComponentName getSettingsActivity(ServiceInfo si) {
-        if (si == null || si.metaData == null) return null;
-        final String configurationActivity =
-                si.metaData.getString(ConditionProviderService.META_DATA_CONFIGURATION_ACTIVITY);
-        if (configurationActivity != null) {
-            return ComponentName.unflattenFromString(configurationActivity);
-        }
-        return null;
-    }
-
-    private static final Comparator<Map.Entry<String,AutomaticZenRule>> RULE_COMPARATOR =
-            new Comparator<Map.Entry<String,AutomaticZenRule>>() {
-        @Override
-        public int compare(Map.Entry<String,AutomaticZenRule> lhs,
-                Map.Entry<String,AutomaticZenRule> rhs) {
-            int byDate = Long.compare(lhs.getValue().getCreationTime(),
-                    rhs.getValue().getCreationTime());
-            if (byDate != 0) {
-                return byDate;
-            } else {
-                return key(lhs.getValue()).compareTo(key(rhs.getValue()));
-            }
-        }
-
-        private String key(AutomaticZenRule rule) {
-            final int type = ZenModeConfig.isValidScheduleConditionId(rule.getConditionId()) ? 1
-                    : ZenModeConfig.isValidEventConditionId(rule.getConditionId()) ? 2
-                    : 3;
-            return type + rule.getName().toString();
-        }
-    };
-
-    private class ZenRulePreference extends Preference {
-        final CharSequence mName;
-        final String mId;
-        final boolean appExists;
-
-        public ZenRulePreference(Context context,
-                final Map.Entry<String, AutomaticZenRule> ruleEntry) {
-            super(context);
-
-            final AutomaticZenRule rule = ruleEntry.getValue();
-            mName = rule.getName();
-            mId = ruleEntry.getKey();
-
-            final boolean isSchedule = ZenModeConfig.isValidScheduleConditionId(
-                    rule.getConditionId());
-            final boolean isEvent = ZenModeConfig.isValidEventConditionId(rule.getConditionId());
-            final boolean isSystemRule = isSchedule || isEvent;
-
-            try {
-                ApplicationInfo info = mPm.getApplicationInfo(rule.getOwner().getPackageName(), 0);
-                LoadIconTask task = new LoadIconTask(this);
-                task.execute(info);
-                setSummary(computeRuleSummary(rule, isSystemRule, info.loadLabel(mPm)));
-            } catch (PackageManager.NameNotFoundException e) {
-                setIcon(R.drawable.ic_label);
-                appExists = false;
-                return;
-            }
-
-            appExists = true;
-            setTitle(rule.getName());
-            setPersistent(false);
-
-            final String action = isSchedule ? ZenModeScheduleRuleSettings.ACTION
-                    : isEvent ? ZenModeEventRuleSettings.ACTION : "";
-            ServiceInfo si = mServiceListing.findService(rule.getOwner());
-            ComponentName settingsActivity = getSettingsActivity(si);
-            setIntent(getRuleIntent(action, settingsActivity, mId));
-            setSelectable(settingsActivity != null || isSystemRule);
-
-            setWidgetLayoutResource(R.layout.zen_rule_widget);
-        }
-
-        @Override
-        public void onBindViewHolder(PreferenceViewHolder view) {
-            super.onBindViewHolder(view);
-
-            View v = view.findViewById(R.id.delete_zen_rule);
-            if (v != null) {
-                v.setOnClickListener(mDeleteListener);
-            }
-            view.setDividerAllowedAbove(true);
-            view.setDividerAllowedBelow(true);
-        }
-
-        private final View.OnClickListener mDeleteListener = new View.OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                showDeleteRuleDialog(mId, mName);
-            }
-        };
-    }
-
-    private class LoadIconTask extends AsyncTask<ApplicationInfo, Void, Drawable> {
-        private final WeakReference<Preference> prefReference;
-
-        public LoadIconTask(Preference pref) {
-            prefReference = new WeakReference<>(pref);
-        }
-
-        @Override
-        protected Drawable doInBackground(ApplicationInfo... params) {
-            return params[0].loadIcon(mPm);
-        }
-
-        @Override
-        protected void onPostExecute(Drawable icon) {
-            if (icon != null) {
-                final Preference pref = prefReference.get();
-                if (pref != null) {
-                    pref.setIcon(icon);
-                }
-            }
-        }
-    }
-
-}
diff --git a/src/com/android/settings/notification/ZenModePreferenceController.java b/src/com/android/settings/notification/ZenModePreferenceController.java
index 1427d5a..e11b422 100644
--- a/src/com/android/settings/notification/ZenModePreferenceController.java
+++ b/src/com/android/settings/notification/ZenModePreferenceController.java
@@ -16,22 +16,18 @@
 
 package com.android.settings.notification;
 
-import android.app.NotificationManager;
 import android.content.Context;
 import android.support.v7.preference.Preference;
-import com.android.settings.R;
 
 public class ZenModePreferenceController extends AdjustVolumeRestrictedPreferenceController {
 
     private static final String KEY_ZEN_MODE = "zen_mode";
-    private String mSummaryPrefix;
 
     private ZenModeSettings.SummaryBuilder mSummaryBuilder;
 
     public ZenModePreferenceController(Context context) {
         super(context);
         mSummaryBuilder = new ZenModeSettings.SummaryBuilder(context);
-        mSummaryPrefix = context.getString(R.string.zen_mode_priority_settings_title) + " ";
     }
 
     @Override
@@ -48,8 +44,7 @@
     public void updateState(Preference preference) {
         super.updateState(preference);
         if (preference.isEnabled()) {
-            preference.setSummary(mSummaryPrefix + mSummaryBuilder.getPrioritySettingSummary(
-                NotificationManager.from(mContext).getNotificationPolicy()));
+            preference.setSummary(mSummaryBuilder.getAutomaticRulesSummary());
         }
     }
 }
diff --git a/src/com/android/settings/notification/ZenModeSettings.java b/src/com/android/settings/notification/ZenModeSettings.java
index 6266af9..bbcaa9c 100644
--- a/src/com/android/settings/notification/ZenModeSettings.java
+++ b/src/com/android/settings/notification/ZenModeSettings.java
@@ -16,25 +16,56 @@
 
 package com.android.settings.notification;
 
+import android.app.AlertDialog;
+import android.app.AutomaticZenRule;
 import android.app.NotificationManager;
 import android.app.NotificationManager.Policy;
+import android.content.ComponentName;
 import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ServiceInfo;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.os.AsyncTask;
 import android.os.Bundle;
+import android.provider.Settings;
+import android.service.notification.ConditionProviderService;
+import android.service.notification.ZenModeConfig;
+import com.android.settings.utils.ManagedServiceSettings;
+import com.android.settings.utils.ZenServiceListing;
 import android.support.annotation.VisibleForTesting;
 import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceCategory;
 import android.support.v7.preference.PreferenceScreen;
+import android.support.v7.preference.PreferenceViewHolder;
+import android.view.View;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settings.R;
 
+import java.lang.ref.WeakReference;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Map;
+import java.util.Map.Entry;
+
 public class ZenModeSettings extends ZenModeSettingsBase {
     private static final String KEY_PRIORITY_SETTINGS = "priority_settings";
     private static final String KEY_VISUAL_SETTINGS = "visual_interruptions_settings";
+    private static final String KEY_AUTOMATIC_RULES = "automatic_rules";
 
+    static final ManagedServiceSettings.Config CONFIG = getConditionProviderConfig();
+
+    private PreferenceCategory mAutomaticRules;
     private Preference mPrioritySettings;
     private Preference mVisualSettings;
     private Policy mPolicy;
     private SummaryBuilder mSummaryBuilder;
+    private PackageManager mPm;
+    private ZenServiceListing mServiceListing;
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
@@ -43,10 +74,14 @@
         addPreferencesFromResource(R.xml.zen_mode_settings);
         final PreferenceScreen root = getPreferenceScreen();
 
+        mAutomaticRules = (PreferenceCategory) root.findPreference(KEY_AUTOMATIC_RULES);
         mPrioritySettings = root.findPreference(KEY_PRIORITY_SETTINGS);
         mVisualSettings = root.findPreference(KEY_VISUAL_SETTINGS);
         mPolicy = NotificationManager.from(mContext).getNotificationPolicy();
         mSummaryBuilder = new SummaryBuilder(getContext());
+        mPm = mContext.getPackageManager();
+        mServiceListing = new ZenServiceListing(mContext, CONFIG);
+        mServiceListing.reloadApprovedServices();
     }
 
     @Override
@@ -55,6 +90,7 @@
         if (isUiRestricted()) {
             return;
         }
+        updateControls();
     }
 
     @Override
@@ -76,6 +112,7 @@
     private void updateControls() {
         updatePrioritySettingsSummary();
         updateVisualSettingsSummary();
+        updateAutomaticRules();
     }
 
     private void updatePrioritySettingsSummary() {
@@ -86,11 +123,251 @@
         mVisualSettings.setSummary(mSummaryBuilder.getVisualSettingSummary(mPolicy));
     }
 
+    private void updateAutomaticRules() {
+        mAutomaticRules.removeAll();
+        final Map.Entry<String,AutomaticZenRule>[] sortedRules = sortedRules();
+        for (Map.Entry<String,AutomaticZenRule> sortedRule : sortedRules) {
+            ZenRulePreference pref = new ZenRulePreference(getPrefContext(), sortedRule);
+            if (pref.appExists) {
+                mAutomaticRules.addPreference(pref);
+            }
+        }
+        final Preference p = new Preference(getPrefContext());
+        p.setIcon(R.drawable.ic_add);
+        p.setTitle(R.string.zen_mode_add_rule);
+        p.setPersistent(false);
+        p.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
+            @Override
+            public boolean onPreferenceClick(Preference preference) {
+                mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_ZEN_ADD_RULE);
+                showAddRuleDialog();
+                return true;
+            }
+        });
+        mAutomaticRules.addPreference(p);
+    }
+
+    private void showAddRuleDialog() {
+        new ZenRuleSelectionDialog(mContext, mServiceListing) {
+            @Override
+            public void onSystemRuleSelected(ZenRuleInfo ri) {
+                showNameRuleDialog(ri);
+            }
+
+            @Override
+            public void onExternalRuleSelected(ZenRuleInfo ri) {
+                Intent intent = new Intent().setComponent(ri.configurationActivity);
+                startActivity(intent);
+            }
+        }.show();
+    }
+
+    private String computeRuleSummary(AutomaticZenRule rule, boolean isSystemRule,
+            CharSequence providerLabel) {
+        final String mode = computeZenModeCaption(getResources(), rule.getInterruptionFilter());
+        final String ruleState = (rule == null || !rule.isEnabled())
+                ? getString(R.string.switch_off_text)
+                : getString(R.string.zen_mode_rule_summary_enabled_combination, mode);
+
+        return isSystemRule ? ruleState
+                : getString(R.string.zen_mode_rule_summary_provider_combination,
+                        providerLabel, ruleState);
+    }
+
+    private static ManagedServiceSettings.Config getConditionProviderConfig() {
+        final ManagedServiceSettings.Config c = new ManagedServiceSettings.Config();
+        c.tag = TAG;
+        c.setting = Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES;
+        c.secondarySetting = Settings.Secure.ENABLED_NOTIFICATION_LISTENERS;
+        c.intentAction = ConditionProviderService.SERVICE_INTERFACE;
+        c.permission = android.Manifest.permission.BIND_CONDITION_PROVIDER_SERVICE;
+        c.noun = "condition provider";
+        return c;
+    }
+
+    private static String computeZenModeCaption(Resources res, int zenMode) {
+        switch (zenMode) {
+            case NotificationManager.INTERRUPTION_FILTER_ALARMS:
+                return res.getString(R.string.zen_mode_option_alarms);
+            case NotificationManager.INTERRUPTION_FILTER_PRIORITY:
+                return res.getString(R.string.zen_mode_option_important_interruptions);
+            case NotificationManager.INTERRUPTION_FILTER_NONE:
+                return res.getString(R.string.zen_mode_option_no_interruptions);
+            default:
+                return null;
+        }
+    }
+
+    public static ZenRuleInfo getRuleInfo(PackageManager pm, ServiceInfo si) {
+        if (si == null || si.metaData == null) return null;
+        final String ruleType = si.metaData.getString(ConditionProviderService.META_DATA_RULE_TYPE);
+        final ComponentName configurationActivity = getSettingsActivity(si);
+        if (ruleType != null && !ruleType.trim().isEmpty() && configurationActivity != null) {
+            final ZenRuleInfo ri = new ZenRuleInfo();
+            ri.serviceComponent = new ComponentName(si.packageName, si.name);
+            ri.settingsAction = Settings.ACTION_ZEN_MODE_EXTERNAL_RULE_SETTINGS;
+            ri.title = ruleType;
+            ri.packageName = si.packageName;
+            ri.configurationActivity = getSettingsActivity(si);
+            ri.packageLabel = si.applicationInfo.loadLabel(pm);
+            ri.ruleInstanceLimit =
+                    si.metaData.getInt(ConditionProviderService.META_DATA_RULE_INSTANCE_LIMIT, -1);
+            return ri;
+        }
+        return null;
+    }
+
+    private static ComponentName getSettingsActivity(ServiceInfo si) {
+        if (si == null || si.metaData == null) return null;
+        final String configurationActivity =
+                si.metaData.getString(ConditionProviderService.META_DATA_CONFIGURATION_ACTIVITY);
+        if (configurationActivity != null) {
+            return ComponentName.unflattenFromString(configurationActivity);
+        }
+        return null;
+    }
+
+    private void showNameRuleDialog(final ZenRuleInfo ri) {
+        new ZenRuleNameDialog(mContext, null) {
+            @Override
+            public void onOk(String ruleName) {
+                mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_ZEN_ADD_RULE_OK);
+                AutomaticZenRule rule = new AutomaticZenRule(ruleName, ri.serviceComponent,
+                        ri.defaultConditionId, NotificationManager.INTERRUPTION_FILTER_PRIORITY,
+                        true);
+                String savedRuleId = addZenRule(rule);
+                if (savedRuleId != null) {
+                    startActivity(getRuleIntent(ri.settingsAction, null, savedRuleId));
+                }
+            }
+        }.show();
+    }
+
+    private void showDeleteRuleDialog(final String ruleId, final CharSequence ruleName) {
+        new AlertDialog.Builder(mContext)
+                .setMessage(getString(R.string.zen_mode_delete_rule_confirmation, ruleName))
+                .setNegativeButton(R.string.cancel, null)
+                .setPositiveButton(R.string.zen_mode_delete_rule_button,
+                        new DialogInterface.OnClickListener() {
+                            @Override
+                            public void onClick(DialogInterface dialog, int which) {
+                                mMetricsFeatureProvider.action(mContext,
+                                        MetricsEvent.ACTION_ZEN_DELETE_RULE_OK);
+                                removeZenRule(ruleId);
+                            }
+                        })
+                .show();
+    }
+
+    private Intent getRuleIntent(String settingsAction, ComponentName configurationActivity,
+            String ruleId) {
+        Intent intent = new Intent()
+                .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
+                .putExtra(ConditionProviderService.EXTRA_RULE_ID, ruleId);
+        if (configurationActivity != null) {
+            intent.setComponent(configurationActivity);
+        } else {
+            intent.setAction(settingsAction);
+        }
+        return intent;
+    }
+
+    private Map.Entry<String,AutomaticZenRule>[] sortedRules() {
+        final Map.Entry<String,AutomaticZenRule>[] rt =
+                mRules.toArray(new Map.Entry[mRules.size()]);
+        Arrays.sort(rt, RULE_COMPARATOR);
+        return rt;
+    }
+
     @Override
     protected int getHelpResource() {
         return R.string.help_uri_interruptions;
     }
 
+    private class ZenRulePreference extends Preference {
+        final CharSequence mName;
+        final String mId;
+        final boolean appExists;
+
+        public ZenRulePreference(Context context,
+                final Map.Entry<String, AutomaticZenRule> ruleEntry) {
+            super(context);
+
+            final AutomaticZenRule rule = ruleEntry.getValue();
+            mName = rule.getName();
+            mId = ruleEntry.getKey();
+
+            final boolean isSchedule = ZenModeConfig.isValidScheduleConditionId(
+                    rule.getConditionId());
+            final boolean isEvent = ZenModeConfig.isValidEventConditionId(rule.getConditionId());
+            final boolean isSystemRule = isSchedule || isEvent;
+
+            try {
+                ApplicationInfo info = mPm.getApplicationInfo(rule.getOwner().getPackageName(), 0);
+                LoadIconTask task = new LoadIconTask(this);
+                task.execute(info);
+                setSummary(computeRuleSummary(rule, isSystemRule, info.loadLabel(mPm)));
+            } catch (PackageManager.NameNotFoundException e) {
+                setIcon(R.drawable.ic_label);
+                appExists = false;
+                return;
+            }
+
+            appExists = true;
+            setTitle(rule.getName());
+            setPersistent(false);
+
+            final String action = isSchedule ? ZenModeScheduleRuleSettings.ACTION
+                    : isEvent ? ZenModeEventRuleSettings.ACTION : "";
+            ServiceInfo si = mServiceListing.findService(rule.getOwner());
+            ComponentName settingsActivity = getSettingsActivity(si);
+            setIntent(getRuleIntent(action, settingsActivity, mId));
+            setSelectable(settingsActivity != null || isSystemRule);
+
+            setWidgetLayoutResource(R.layout.zen_rule_widget);
+        }
+
+        @Override
+        public void onBindViewHolder(PreferenceViewHolder view) {
+            super.onBindViewHolder(view);
+
+            View v = view.findViewById(R.id.delete_zen_rule);
+            if (v != null) {
+                v.setOnClickListener(mDeleteListener);
+            }
+        }
+
+        private final View.OnClickListener mDeleteListener = new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                showDeleteRuleDialog(mId, mName);
+            }
+        };
+    }
+
+    private class LoadIconTask extends AsyncTask<ApplicationInfo, Void, Drawable> {
+        private final WeakReference<Preference> prefReference;
+
+        public LoadIconTask(Preference pref) {
+            prefReference = new WeakReference<>(pref);
+        }
+
+        @Override
+        protected Drawable doInBackground(ApplicationInfo... params) {
+            return params[0].loadIcon(mPm);
+        }
+
+        @Override
+        protected void onPostExecute(Drawable icon) {
+            if (icon != null) {
+                final Preference pref = prefReference.get();
+                if (pref != null) {
+                    pref.setIcon(icon);
+                }
+            }
+        }
+    }
+
     public static class SummaryBuilder {
 
         private Context mContext;
@@ -137,6 +414,29 @@
             return s;
         }
 
+        String getAutomaticRulesSummary() {
+            final int count = getEnabledAutomaticRulesCount();
+            return count == 0 ? mContext.getString(R.string.zen_mode_settings_summary_off)
+                : mContext.getResources().getQuantityString(
+                    R.plurals.zen_mode_settings_summary_on, count, count);
+        }
+
+        @VisibleForTesting
+        int getEnabledAutomaticRulesCount() {
+            int count = 0;
+            final Map<String, AutomaticZenRule> ruleMap =
+                NotificationManager.from(mContext).getAutomaticZenRules();
+            if (ruleMap != null) {
+                for (Entry<String, AutomaticZenRule> ruleEntry : ruleMap.entrySet()) {
+                    final AutomaticZenRule rule = ruleEntry.getValue();
+                    if (rule != null && rule.isEnabled()) {
+                        count++;
+                    }
+                }
+            }
+            return count;
+        }
+
         @VisibleForTesting
         String append(String s, boolean condition, int resId) {
             if (condition) {
@@ -153,6 +453,29 @@
         private boolean isEffectSuppressed(Policy policy, int effect) {
             return (policy.suppressedVisualEffects & effect) != 0;
         }
-
     }
+
+    private static final Comparator<Map.Entry<String,AutomaticZenRule>> RULE_COMPARATOR =
+            new Comparator<Map.Entry<String,AutomaticZenRule>>() {
+                @Override
+                public int compare(Map.Entry<String,AutomaticZenRule> lhs,
+                        Map.Entry<String,AutomaticZenRule> rhs) {
+                    int byDate = Long.compare(lhs.getValue().getCreationTime(),
+                            rhs.getValue().getCreationTime());
+                    if (byDate != 0) {
+                        return byDate;
+                    } else {
+                        return key(lhs.getValue()).compareTo(key(rhs.getValue()));
+                    }
+                }
+
+                private String key(AutomaticZenRule rule) {
+                    final int type = ZenModeConfig.isValidScheduleConditionId(rule.getConditionId())
+                            ? 1
+                            : ZenModeConfig.isValidEventConditionId(rule.getConditionId())
+                                    ? 2
+                                    : 3;
+                    return type + rule.getName().toString();
+                }
+            };
 }
diff --git a/src/com/android/settings/notification/ZenRuleSelectionDialog.java b/src/com/android/settings/notification/ZenRuleSelectionDialog.java
index 9de9a60..4fa632a 100644
--- a/src/com/android/settings/notification/ZenRuleSelectionDialog.java
+++ b/src/com/android/settings/notification/ZenRuleSelectionDialog.java
@@ -169,7 +169,7 @@
             if (DEBUG) Log.d(TAG, "Services reloaded: count=" + services.size());
             Set<ZenRuleInfo> externalRuleTypes = new TreeSet<>(RULE_TYPE_COMPARATOR);
             for (ServiceInfo serviceInfo : services) {
-                final ZenRuleInfo ri = ZenModeAutomationSettings.getRuleInfo(mPm, serviceInfo);
+                final ZenRuleInfo ri = ZenModeSettings.getRuleInfo(mPm, serviceInfo);
                 if (ri != null && ri.configurationActivity != null
                         && mNm.isNotificationPolicyAccessGrantedForPackage(ri.packageName)
                         && (ri.ruleInstanceLimit <= 0 || ri.ruleInstanceLimit
diff --git a/src/com/android/settings/search/SearchIndexableResources.java b/src/com/android/settings/search/SearchIndexableResources.java
index 8b19834..f8cedc1 100644
--- a/src/com/android/settings/search/SearchIndexableResources.java
+++ b/src/com/android/settings/search/SearchIndexableResources.java
@@ -30,6 +30,7 @@
 import com.android.settings.ScreenPinningSettings;
 import com.android.settings.SecuritySettings;
 import com.android.settings.accessibility.AccessibilitySettings;
+import com.android.settings.accessibility.AccessibilityShortcutPreferenceFragment;
 import com.android.settings.accessibility.MagnificationPreferenceFragment;
 import com.android.settings.accounts.UserAndAccountDashboardFragment;
 import com.android.settings.applications.AdvancedAppSettings;
@@ -73,6 +74,7 @@
 import com.android.settings.print.PrintSettingsFragment;
 import com.android.settings.security.LockscreenDashboardFragment;
 import com.android.settings.sim.SimSettings;
+import com.android.settings.system.ResetDashboardFragment;
 import com.android.settings.system.SystemDashboardFragment;
 import com.android.settings.tts.TtsEnginePreferenceFragment;
 import com.android.settings.users.UserSettings;
@@ -165,6 +167,7 @@
                 R.xml.zen_mode_visual_interruptions_settings,
                 R.drawable.ic_settings_notifications);
         addIndex(SystemDashboardFragment.class, NO_DATA_RES_ID, R.drawable.ic_settings_about);
+        addIndex(ResetDashboardFragment.class, NO_DATA_RES_ID, R.drawable.ic_restore);
         addIndex(StorageDashboardFragment.class, NO_DATA_RES_ID, R.drawable.ic_settings_storage);
         addIndex(ConnectedDeviceDashboardFragment.class, NO_DATA_RES_ID,
                 R.drawable.ic_devices_other);
@@ -176,6 +179,8 @@
             R.drawable.ic_settings_security);
         addIndex(MagnificationPreferenceFragment.class, NO_DATA_RES_ID,
                 R.drawable.ic_settings_accessibility);
+        addIndex(AccessibilityShortcutPreferenceFragment.class, NO_DATA_RES_ID,
+                R.drawable.ic_settings_accessibility);
     }
 
     private SearchIndexableResources() {
diff --git a/src/com/android/settings/system/FactoryResetPreferenceController.java b/src/com/android/settings/system/FactoryResetPreferenceController.java
index 95a9e54..38afd16 100644
--- a/src/com/android/settings/system/FactoryResetPreferenceController.java
+++ b/src/com/android/settings/system/FactoryResetPreferenceController.java
@@ -15,22 +15,30 @@
  */
 package com.android.settings.system;
 
+import android.accounts.Account;
+import android.accounts.AccountManager;
 import android.content.Context;
-
+import android.content.pm.UserInfo;
+import android.os.UserHandle;
 import android.os.UserManager;
+import android.support.v7.preference.Preference;
 
 import com.android.settings.R;
 import com.android.settings.core.PreferenceController;
 
+import java.util.List;
+
 public class FactoryResetPreferenceController extends PreferenceController {
-    /** Key of the "Factory reset" preference in {@link R.xml.system_dashboard_fragment}.*/
+    /** Key of the "Factory reset" preference in {@link R.xml.reset_dashboard_fragment}. */
     private static final String KEY_FACTORY_RESET = "factory_reset";
 
     private final UserManager mUm;
+    private final AccountManager mAm;
 
-    public FactoryResetPreferenceController(Context context, UserManager um) {
+    public FactoryResetPreferenceController(Context context) {
         super(context);
-        mUm = um;
+        mUm = (UserManager) context.getSystemService(Context.USER_SERVICE);
+        mAm = (AccountManager) context.getSystemService(Context.ACCOUNT_SERVICE);
     }
 
     /** Hide "Factory reset" settings for secondary users. */
@@ -43,4 +51,22 @@
     public String getPreferenceKey() {
         return KEY_FACTORY_RESET;
     }
+
+    @Override
+    public void updateState(Preference preference) {
+        final List<UserInfo> profiles = mUm.getProfiles(UserHandle.myUserId());
+        int accountsCount = 0;
+        for (UserInfo userInfo : profiles) {
+            final int profileId = userInfo.id;
+            Account[] accounts = mAm.getAccountsAsUser(profileId);
+            accountsCount += accounts.length;
+        }
+        if (accountsCount == 0) {
+            preference.setSummary(R.string.master_clear_summary);
+        } else {
+            preference.setSummary(mContext.getResources().getQuantityString(
+                    R.plurals.master_clear_with_account_summary,
+                    accountsCount, accountsCount));
+        }
+    }
 }
diff --git a/src/com/android/settings/system/ResetDashboardFragment.java b/src/com/android/settings/system/ResetDashboardFragment.java
new file mode 100644
index 0000000..d4685bc
--- /dev/null
+++ b/src/com/android/settings/system/ResetDashboardFragment.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.system;
+
+import android.content.Context;
+import android.provider.SearchIndexableResource;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.R;
+import com.android.settings.applications.ResetAppPrefPreferenceController;
+import com.android.settings.core.PreferenceController;
+import com.android.settings.core.lifecycle.Lifecycle;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.network.NetworkResetPreferenceController;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.search.Indexable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ResetDashboardFragment extends DashboardFragment {
+
+    private static final String TAG = "ResetDashboardFragment";
+
+    @Override
+    public int getMetricsCategory() {
+        return MetricsProto.MetricsEvent.RESET_DASHBOARD;
+    }
+
+    @Override
+    protected String getLogTag() {
+        return TAG;
+    }
+
+    @Override
+    protected int getPreferenceScreenResId() {
+        return R.xml.reset_dashboard_fragment;
+    }
+
+    @Override
+    protected List<PreferenceController> getPreferenceControllers(Context context) {
+        return buildPreferenceControllers(context, getLifecycle());
+    }
+
+    private static List<PreferenceController> buildPreferenceControllers(Context context,
+            Lifecycle lifecycle) {
+        final List<PreferenceController> controllers = new ArrayList<>();
+        controllers.add(new NetworkResetPreferenceController(context));
+        controllers.add(new FactoryResetPreferenceController(context));
+        controllers.add(new ResetAppPrefPreferenceController(context, lifecycle));
+        return controllers;
+    }
+
+    public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+            new BaseSearchIndexProvider() {
+                @Override
+                public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
+                        boolean enabled) {
+                    final ArrayList<SearchIndexableResource> result = new ArrayList<>();
+
+                    final SearchIndexableResource sir = new SearchIndexableResource(context);
+                    sir.xmlResId = R.xml.reset_dashboard_fragment;
+                    result.add(sir);
+                    return result;
+                }
+
+                @Override
+                public List<PreferenceController> getPreferenceControllers(Context context) {
+                    return buildPreferenceControllers(context, null /* lifecycle */);
+                }
+            };
+}
diff --git a/src/com/android/settings/system/SystemDashboardFragment.java b/src/com/android/settings/system/SystemDashboardFragment.java
index d4c63c2..76ac4a6 100644
--- a/src/com/android/settings/system/SystemDashboardFragment.java
+++ b/src/com/android/settings/system/SystemDashboardFragment.java
@@ -60,7 +60,6 @@
         final List<PreferenceController> controllers = new ArrayList<>();
         controllers.add(new SystemUpdatePreferenceController(context, UserManager.get(context)));
         controllers.add(new AdditionalSystemUpdatePreferenceController(context));
-        controllers.add(new FactoryResetPreferenceController(context, UserManager.get(context)));
         return controllers;
     }
 
diff --git a/src/com/android/settings/vpn2/AppManagementFragment.java b/src/com/android/settings/vpn2/AppManagementFragment.java
index 9ef087b..7559512 100644
--- a/src/com/android/settings/vpn2/AppManagementFragment.java
+++ b/src/com/android/settings/vpn2/AppManagementFragment.java
@@ -259,13 +259,13 @@
 
             if (isAlwaysOnSupportedByApp(mPackageInfo.applicationInfo)) {
                 // setSummary doesn't override the admin message when user restriction is applied
-                mPreferenceAlwaysOn.setSummary(null);
+                mPreferenceAlwaysOn.setSummary(R.string.vpn_always_on_summary);
                 // setEnabled is not required here, as checkRestrictionAndSetDisabled
                 // should have refreshed the enable state.
             } else {
                 mPreferenceAlwaysOn.setEnabled(false);
                 mPreferenceLockdown.setEnabled(false);
-                mPreferenceAlwaysOn.setSummary(R.string.vpn_not_supported_by_this_app);
+                mPreferenceAlwaysOn.setSummary(R.string.vpn_always_on_summary_not_supported);
             }
         }
     }
diff --git a/src/com/android/settings/vpn2/VpnSettings.java b/src/com/android/settings/vpn2/VpnSettings.java
index ead2143..d40441f 100644
--- a/src/com/android/settings/vpn2/VpnSettings.java
+++ b/src/com/android/settings/vpn2/VpnSettings.java
@@ -18,6 +18,7 @@
 
 import android.annotation.UiThread;
 import android.annotation.WorkerThread;
+import android.app.Activity;
 import android.app.AppOpsManager;
 import android.content.Context;
 import android.content.Intent;
@@ -215,9 +216,16 @@
 
     @Override @WorkerThread
     public boolean handleMessage(Message message) {
+        //Return if activity has been recycled
+        final Activity activity = getActivity();
+        if (activity == null) {
+            return true;
+        }
+        final Context context = activity.getApplicationContext();
+
         // Run heavy RPCs before switching to UI thread
         final List<VpnProfile> vpnProfiles = loadVpnProfiles(mKeyStore);
-        final List<AppVpnInfo> vpnApps = getVpnApps(getActivity(), /* includeProfiles */ true);
+        final List<AppVpnInfo> vpnApps = getVpnApps(context, /* includeProfiles */ true);
 
         final Map<String, LegacyVpnInfo> connectedLegacyVpns = getConnectedLegacyVpns();
         final Set<AppVpnInfo> connectedAppVpns = getConnectedAppVpns();
@@ -226,7 +234,7 @@
         final String lockdownVpnKey = VpnUtils.getLockdownVpn();
 
         // Refresh list of VPNs
-        getActivity().runOnUiThread(new UpdatePreferences(this)
+        activity.runOnUiThread(new UpdatePreferences(this)
                 .legacyVpns(vpnProfiles, connectedLegacyVpns, lockdownVpnKey)
                 .appVpns(vpnApps, connectedAppVpns, alwaysOnAppVpnInfos));
 
diff --git a/src/com/android/settings/wifi/WifiManagerWrapper.java b/src/com/android/settings/wifi/WifiManagerWrapper.java
new file mode 100644
index 0000000..69b5ee9
--- /dev/null
+++ b/src/com/android/settings/wifi/WifiManagerWrapper.java
@@ -0,0 +1,23 @@
+package com.android.settings.wifi;
+
+import android.net.wifi.WifiManager;
+
+/**
+ * Wrapper around {@link WifiManager} to facilitate unit testing.
+ *
+ * TODO: delete this class once robolectric supports Android O
+ */
+public class WifiManagerWrapper {
+    private final WifiManager mWifiManager;
+
+    public WifiManagerWrapper(WifiManager wifiManager) {
+        mWifiManager = wifiManager;
+    }
+
+    /**
+     * {@link WifiManager#getCurrentNetworkWpsNfcConfigurationToken}
+     */
+    public String getCurrentNetworkWpsNfcConfigurationToken() {
+        return mWifiManager.getCurrentNetworkWpsNfcConfigurationToken();
+    }
+}
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index ab1e04e..e9204f9 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -139,10 +139,6 @@
     // should Next button only be enabled when we have a connection?
     private boolean mEnableNextOnConnection;
 
-    // should see all networks instead of collapsing networks and showing mSeeAllNetworksPreference.
-    private boolean mSeeAllNetworks;
-    private static final int NETWORKS_TO_INITIALLY_SHOW = 5;
-
     // Save the dialog details
     private int mDialogMode;
     private AccessPoint mDlgAccessPoint;
@@ -160,7 +156,6 @@
     private PreferenceCategory mAccessPointsPreferenceCategory;
     private PreferenceCategory mAdditionalSettingsPreferenceCategory;
     private Preference mAddPreference;
-    private Preference mSeeAllNetworksPreference;
     private Preference mConfigureWifiSettingsPreference;
     private Preference mSavedNetworksPreference;
     private LinkablePreference mStatusMessagePreference;
@@ -210,10 +205,6 @@
         mAddPreference = new Preference(prefContext);
         mAddPreference.setIcon(R.drawable.ic_menu_add_inset);
         mAddPreference.setTitle(R.string.wifi_add_network);
-        mSeeAllNetworksPreference = new Preference(prefContext);
-        mSeeAllNetworksPreference.setIcon(R.drawable.ic_arrow_down_24dp);
-        mSeeAllNetworksPreference.setTitle(R.string.wifi_see_all_networks_button_title);
-        mSeeAllNetworks = false;
         mStatusMessagePreference = new LinkablePreference(prefContext);
 
         mUserBadgeCache = new AccessPointPreference.UserBadgeCache(getPackageManager());
@@ -335,6 +326,8 @@
 
         // On/off switch is hidden for Setup Wizard (returns null)
         mWifiEnabler = createWifiEnabler();
+
+        mWifiTracker.startTracking();
     }
 
     /**
@@ -354,7 +347,6 @@
             mWifiEnabler.resume(activity);
         }
 
-        mWifiTracker.startTracking();
         activity.invalidateOptionsMenu();
     }
 
@@ -364,7 +356,11 @@
         if (mWifiEnabler != null) {
             mWifiEnabler.pause();
         }
+    }
 
+    @Override
+    public void onStop() {
+        super.onStop();
         mWifiTracker.stopTracking();
     }
 
@@ -520,9 +516,6 @@
             }
         } else if (preference == mAddPreference) {
             onAddNetworkPressed();
-        } else if (preference == mSeeAllNetworksPreference) {
-            mSeeAllNetworks = true;
-            onAccessPointsChanged();
         } else {
             return super.onPreferenceTreeClick(preference);
         }
@@ -577,12 +570,12 @@
             case WRITE_NFC_DIALOG_ID:
                 if (mSelectedAccessPoint != null) {
                     mWifiToNfcDialog = new WriteWifiConfigToNfcDialog(
-                            getActivity(), mSelectedAccessPoint.getConfig().networkId,
+                            getActivity(),
                             mSelectedAccessPoint.getSecurity(),
-                            mWifiManager);
+                            new WifiManagerWrapper(mWifiManager));
                 } else if (mWifiNfcDialogSavedState != null) {
-                    mWifiToNfcDialog = new WriteWifiConfigToNfcDialog(
-                            getActivity(), mWifiNfcDialogSavedState, mWifiManager);
+                    mWifiToNfcDialog = new WriteWifiConfigToNfcDialog(getActivity(),
+                            mWifiNfcDialogSavedState, new WifiManagerWrapper(mWifiManager));
                 }
 
                 return mWifiToNfcDialog;
@@ -666,12 +659,8 @@
 
         int index =
                 configureConnectedAccessPointPreferenceCategory(accessPoints) ? 1 : 0;
-        boolean fewerNetworksThanLimit =
-                accessPoints.size() <= index + NETWORKS_TO_INITIALLY_SHOW;
-        int numAccessPointsToShow = mSeeAllNetworks || fewerNetworksThanLimit
-                ? accessPoints.size() : index + NETWORKS_TO_INITIALLY_SHOW;
-
-        for (; index < numAccessPointsToShow; index++) {
+        int numAccessPoints = accessPoints.size();
+        for (; index < numAccessPoints; index++) {
             AccessPoint accessPoint = accessPoints.get(index);
             // Ignore access points that are out of range.
             if (accessPoint.isReachable()) {
@@ -702,15 +691,8 @@
             }
         }
         removeCachedPrefs(mAccessPointsPreferenceCategory);
-        if (mSeeAllNetworks || fewerNetworksThanLimit) {
-            mAccessPointsPreferenceCategory.removePreference(mSeeAllNetworksPreference);
-            mAddPreference.setOrder(index);
-            mAccessPointsPreferenceCategory.addPreference(mAddPreference);
-        } else {
-            mAccessPointsPreferenceCategory.removePreference(mAddPreference);
-            mSeeAllNetworksPreference.setOrder(index);
-            mAccessPointsPreferenceCategory.addPreference(mSeeAllNetworksPreference);
-        }
+        mAddPreference.setOrder(index);
+        mAccessPointsPreferenceCategory.addPreference(mAddPreference);
         setConfigureWifiSettingsVisibility();
 
         if (!hasAvailableAccessPoints) {
@@ -810,8 +792,17 @@
             return;
         }
         mAdditionalSettingsPreferenceCategory.addPreference(mConfigureWifiSettingsPreference);
-        if (mWifiTracker.doSavedNetworksExist()) {
+        boolean wifiWakeupEnabled = Settings.Global.getInt(
+                getContentResolver(), Settings.Global.WIFI_WAKEUP_ENABLED, 0) == 1;
+        mConfigureWifiSettingsPreference.setSummary(getString(wifiWakeupEnabled
+                ? R.string.wifi_configure_settings_preference_summary_wakeup_on
+                : R.string.wifi_configure_settings_preference_summary_wakeup_off));
+        int numSavedNetworks = mWifiTracker.getNumSavedNetworks();
+        if (numSavedNetworks > 0) {
             mAdditionalSettingsPreferenceCategory.addPreference(mSavedNetworksPreference);
+            mSavedNetworksPreference.setSummary(
+                    getResources().getQuantityString(R.plurals.wifi_saved_access_points_summary,
+                            numSavedNetworks, numSavedNetworks));
         } else {
             mAdditionalSettingsPreferenceCategory.removePreference(mSavedNetworksPreference);
         }
diff --git a/src/com/android/settings/wifi/WriteWifiConfigToNfcDialog.java b/src/com/android/settings/wifi/WriteWifiConfigToNfcDialog.java
index 0d3f3b6..6fca8f2 100644
--- a/src/com/android/settings/wifi/WriteWifiConfigToNfcDialog.java
+++ b/src/com/android/settings/wifi/WriteWifiConfigToNfcDialog.java
@@ -56,7 +56,6 @@
     private static final String PASSWORD_FORMAT = "102700%s%s";
     private static final int HEX_RADIX = 16;
     private static final char[] hexArray = "0123456789ABCDEF".toCharArray();
-    private static final String NETWORK_ID = "network_id";
     private static final String SECURITY = "security";
 
     private final PowerManager.WakeLock mWakeLock;
@@ -69,33 +68,29 @@
     private TextView mLabelView;
     private CheckBox mPasswordCheckBox;
     private ProgressBar mProgressBar;
-    private WifiManager mWifiManager;
+    private WifiManagerWrapper mWifiManager;
     private String mWpsNfcConfigurationToken;
     private Context mContext;
-    private int mNetworkId;
     private int mSecurity;
 
-    WriteWifiConfigToNfcDialog(Context context, int networkId, int security,
-            WifiManager wifiManager) {
+    WriteWifiConfigToNfcDialog(Context context, int security, WifiManagerWrapper wifiManager) {
         super(context);
 
         mContext = context;
         mWakeLock = ((PowerManager) context.getSystemService(Context.POWER_SERVICE))
                 .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WriteWifiConfigToNfcDialog:wakeLock");
         mOnTextChangedHandler = new Handler();
-        mNetworkId = networkId;
         mSecurity = security;
         mWifiManager = wifiManager;
     }
 
-    WriteWifiConfigToNfcDialog(Context context, Bundle savedState, WifiManager wifiManager) {
+    WriteWifiConfigToNfcDialog(Context context, Bundle savedState, WifiManagerWrapper wifiManager) {
         super(context);
 
         mContext = context;
         mWakeLock = ((PowerManager) context.getSystemService(Context.POWER_SERVICE))
                 .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WriteWifiConfigToNfcDialog:wakeLock");
         mOnTextChangedHandler = new Handler();
-        mNetworkId = savedState.getInt(NETWORK_ID);
         mSecurity = savedState.getInt(SECURITY);
         mWifiManager = wifiManager;
     }
@@ -114,12 +109,12 @@
                 mContext.getResources().getString(com.android.internal.R.string.cancel),
                 (OnClickListener) null);
 
-        mPasswordView = (TextView) mView.findViewById(R.id.password);
-        mLabelView = (TextView) mView.findViewById(R.id.password_label);
+        mPasswordView = mView.findViewById(R.id.password);
+        mLabelView = mView.findViewById(R.id.password_label);
         mPasswordView.addTextChangedListener(this);
-        mPasswordCheckBox = (CheckBox) mView.findViewById(R.id.show_password);
+        mPasswordCheckBox = mView.findViewById(R.id.show_password);
         mPasswordCheckBox.setOnCheckedChangeListener(this);
-        mProgressBar = (ProgressBar) mView.findViewById(R.id.progress_bar);
+        mProgressBar = mView.findViewById(R.id.progress_bar);
 
         super.onCreate(savedInstanceState);
 
@@ -135,8 +130,7 @@
         mWakeLock.acquire();
 
         String password = mPasswordView.getText().toString();
-        String wpsNfcConfigurationToken
-                = mWifiManager.getWpsNfcConfigurationToken(mNetworkId);
+        String wpsNfcConfigurationToken = mWifiManager.getCurrentNetworkWpsNfcConfigurationToken();
         String passwordHex = byteArrayToHexString(password.getBytes());
 
         String passwordLength = password.length() >= HEX_RADIX
@@ -180,7 +174,6 @@
     }
 
     public void saveState(Bundle state) {
-        state.putInt(NETWORK_ID, mNetworkId);
         state.putInt(SECURITY, mSecurity);
     }
 
diff --git a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
index 1ed25f2..d0e21e926 100644
--- a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
+++ b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
@@ -149,7 +149,6 @@
     @Override
     public void onResume() {
         mWifiInfo = mWifiManager.getConnectionInfo();
-        mWifiConfig = mWifiManager.getWifiApConfiguration();
 
         refreshFromWifiInfo();
         setIpText();
@@ -257,4 +256,17 @@
         }
         mDnsPref.setDetailText(builder.toString());
     }
+
+    /**
+     * Forgets the wifi network associated with this preference.
+     */
+    public void forgetNetwork() {
+        if (mWifiConfig.ephemeral) {
+            mWifiManager.disableEphemeralNetwork(mWifiConfig.SSID);
+        } else if (mWifiConfig.isPasspoint()) {
+            mWifiManager.removePasspointConfiguration(mWifiConfig.FQDN);
+        } else {
+            mWifiManager.forget(mWifiConfig.networkId, null /* action listener */);
+        }
+    }
 }
diff --git a/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java b/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
index 0073202..ade9d6a 100644
--- a/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
+++ b/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
@@ -19,6 +19,7 @@
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
 import android.os.Bundle;
+import android.view.View;
 import android.widget.Button;
 
 import com.android.internal.logging.nano.MetricsProto;
@@ -69,17 +70,9 @@
     }
 
     private void forgetNetwork() {
-        WifiInfo info = mWifiDetailPreferenceController.getWifiInfo();
         mMetricsFeatureProvider.action(getActivity(), MetricsProto.MetricsEvent.ACTION_WIFI_FORGET);
-        if (!info.isEphemeral()) {
-                // Network is active but has no network ID - must be ephemeral.
-                mWifiManager.disableEphemeralNetwork(
-                        AccessPoint.convertToQuotedString(info.getSSID()));
-        } else if (mAccessPoint.getConfig().isPasspoint()) {
-            mWifiManager.removePasspointConfiguration(mAccessPoint.getConfig().FQDN);
-        } else {
-            mWifiManager.forget(info.getNetworkId(), null /* action listener */);
-        }
+        mWifiDetailPreferenceController.forgetNetwork();
+        mForgetButton.setEnabled(false);
     }
 
     @Override
diff --git a/tests/app/src/com/android/settings/notification/ZenModeSettingsIntegrationTest.java b/tests/app/src/com/android/settings/notification/ZenModeSettingsIntegrationTest.java
new file mode 100644
index 0000000..e7e5e19
--- /dev/null
+++ b/tests/app/src/com/android/settings/notification/ZenModeSettingsIntegrationTest.java
@@ -0,0 +1,53 @@
+package com.android.settings.notification;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.action.ViewActions.click;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
+
+import android.content.Context;
+import android.content.Intent;
+import android.provider.Settings;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.LargeTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.test.uiautomator.UiDevice;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class ZenModeSettingsIntegrationTest {
+    private static final String WM_DISMISS_KEYGUARD_COMMAND = "wm dismiss-keyguard";
+
+    private Context mContext;
+    private UiDevice mUiDevice;
+
+    @Before
+    public void setUp() throws Exception {
+        mContext = InstrumentationRegistry.getTargetContext();
+        mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+        mUiDevice.wakeUp();
+        mUiDevice.executeShellCommand(WM_DISMISS_KEYGUARD_COMMAND);
+    }
+
+    @Test
+    public void testAutomaticRulesAppear() {
+        launchZenSettings();
+        onView(withText("Automatic rules")).check(matches(isDisplayed()));
+        onView(withText("Weekend")).check(matches(isDisplayed()));
+        onView(withText("Add more")).check(matches(isDisplayed())).perform(click());
+        onView(withText("Choose rule type")).check(matches(isDisplayed()));
+    }
+
+    private void launchZenSettings() {
+        Intent settingsIntent = new Intent(Settings.ACTION_ZEN_MODE_SETTINGS)
+                .setPackage(mContext.getPackageName())
+                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        mContext.startActivity(settingsIntent);
+    }
+}
diff --git a/tests/robotests/assets/grandfather_not_implementing_index_provider b/tests/robotests/assets/grandfather_not_implementing_index_provider
index 778440d..240b8eb 100644
--- a/tests/robotests/assets/grandfather_not_implementing_index_provider
+++ b/tests/robotests/assets/grandfather_not_implementing_index_provider
@@ -4,5 +4,6 @@
 com.android.settings.inputmethod.InputAndGestureSettings
 com.android.settings.accounts.AccountDetailDashboardFragment
 com.android.settings.fuelgauge.PowerUsageDetail
+com.android.settings.fuelgauge.AdvancedPowerUsageDetail
 com.android.settings.deviceinfo.StorageProfileFragment
 com.android.settings.wifi.details.WifiNetworkDetailsFragment
diff --git a/tests/robotests/src/android/net/NetworkScorerAppData.java b/tests/robotests/src/android/net/NetworkScorerAppData.java
index 1eaa8a7..f7da4d1 100644
--- a/tests/robotests/src/android/net/NetworkScorerAppData.java
+++ b/tests/robotests/src/android/net/NetworkScorerAppData.java
@@ -23,13 +23,20 @@
      * wifi networks automatically" feature.
      */
     private final ComponentName mEnableUseOpenWifiActivity;
+    /**
+     * The {@link android.app.NotificationChannel} ID used by {@link #mRecommendationService} to
+     * post open network notifications.
+     */
+    private final String mNetworkAvailableNotificationChannelId;
 
     public NetworkScorerAppData(int packageUid, ComponentName recommendationServiceComp,
-            String recommendationServiceLabel, ComponentName enableUseOpenWifiActivity) {
+            String recommendationServiceLabel, ComponentName enableUseOpenWifiActivity,
+            String networkAvailableNotificationChannelId) {
         this.packageUid = packageUid;
         this.mRecommendationService = recommendationServiceComp;
         this.mRecommendationServiceLabel = recommendationServiceLabel;
         this.mEnableUseOpenWifiActivity = enableUseOpenWifiActivity;
+        this.mNetworkAvailableNotificationChannelId = networkAvailableNotificationChannelId;
     }
 
     protected NetworkScorerAppData(Parcel in) {
@@ -37,6 +44,7 @@
         mRecommendationService = ComponentName.readFromParcel(in);
         mRecommendationServiceLabel = in.readString();
         mEnableUseOpenWifiActivity = ComponentName.readFromParcel(in);
+        mNetworkAvailableNotificationChannelId = in.readString();
     }
 
     @Override
@@ -45,6 +53,7 @@
         ComponentName.writeToParcel(mRecommendationService, dest);
         dest.writeString(mRecommendationServiceLabel);
         ComponentName.writeToParcel(mEnableUseOpenWifiActivity, dest);
+        dest.writeString(mNetworkAvailableNotificationChannelId);
     }
 
     @Override
@@ -83,6 +92,11 @@
         return mRecommendationServiceLabel;
     }
 
+    @Nullable
+    public String getNetworkAvailableNotificationChannelId() {
+        return mNetworkAvailableNotificationChannelId;
+    }
+
     @Override
     public String toString() {
         return "NetworkScorerAppData{" +
@@ -90,6 +104,8 @@
                 ", mRecommendationService=" + mRecommendationService +
                 ", mRecommendationServiceLabel=" + mRecommendationServiceLabel +
                 ", mEnableUseOpenWifiActivity=" + mEnableUseOpenWifiActivity +
+                ", mNetworkAvailableNotificationChannelId=" +
+                mNetworkAvailableNotificationChannelId +
                 '}';
     }
 
@@ -101,12 +117,14 @@
         return packageUid == that.packageUid &&
                 Objects.equals(mRecommendationService, that.mRecommendationService) &&
                 Objects.equals(mRecommendationServiceLabel, that.mRecommendationServiceLabel) &&
-                Objects.equals(mEnableUseOpenWifiActivity, that.mEnableUseOpenWifiActivity);
+                Objects.equals(mEnableUseOpenWifiActivity, that.mEnableUseOpenWifiActivity) &&
+                Objects.equals(mNetworkAvailableNotificationChannelId,
+                        that.mNetworkAvailableNotificationChannelId);
     }
 
     @Override
     public int hashCode() {
         return Objects.hash(packageUid, mRecommendationService, mRecommendationServiceLabel,
-                mEnableUseOpenWifiActivity);
+                mEnableUseOpenWifiActivity, mNetworkAvailableNotificationChannelId);
     }
 }
diff --git a/tests/robotests/src/com/android/settings/UtilsTest.java b/tests/robotests/src/com/android/settings/UtilsTest.java
index 324e751..8b7605c 100644
--- a/tests/robotests/src/com/android/settings/UtilsTest.java
+++ b/tests/robotests/src/com/android/settings/UtilsTest.java
@@ -9,6 +9,7 @@
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
+import android.content.pm.ApplicationInfo;
 import android.net.ConnectivityManager;
 import android.net.LinkAddress;
 import android.net.LinkProperties;
@@ -116,4 +117,28 @@
 
         Utils.maybeInitializeVolume(storageManager, new Bundle());
     }
+
+    @Test
+    public void getInstallationStatus_notInstalled_shouldReturnUninstalled() {
+        assertThat(Utils.getInstallationStatus(new ApplicationInfo()))
+                .isEqualTo(R.string.not_installed);
+    }
+
+    @Test
+    public void getInstallationStatus_enabled_shouldReturnInstalled() {
+        final ApplicationInfo info = new ApplicationInfo();
+        info.flags = ApplicationInfo.FLAG_INSTALLED;
+        info.enabled = true;
+
+        assertThat(Utils.getInstallationStatus(info)).isEqualTo(R.string.installed);
+    }
+
+    @Test
+    public void getInstallationStatus_disabled_shouldReturnDisabled() {
+        final ApplicationInfo info = new ApplicationInfo();
+        info.flags = ApplicationInfo.FLAG_INSTALLED;
+        info.enabled = false;
+
+        assertThat(Utils.getInstallationStatus(info)).isEqualTo(R.string.disabled);
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/accessibility/ShortcutServicePickerFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/ShortcutServicePickerFragmentTest.java
new file mode 100644
index 0000000..9161f06
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/accessibility/ShortcutServicePickerFragmentTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.accessibility;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.UserManager;
+
+import android.test.mock.MockContentResolver;
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import com.android.settings.applications.PackageManagerWrapper;
+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.RuntimeEnvironment;
+import org.robolectric.Shadows;
+import org.robolectric.annotation.Config;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class ShortcutServicePickerFragmentTest {
+
+    private static final String TEST_SERVICE_KEY_1 = "abc/123";
+    private static final String TEST_SERVICE_KEY_2 = "abcd/1234";
+
+    private static final String SUMMARY_1 = "summary1";
+    private static final String SUMMARY_2 = "summary2";
+
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private Activity mActivity;
+    @Mock
+    private UserManager mUserManager;
+    @Mock
+    private PackageManagerWrapper mPackageManager;
+
+    private ShortcutServicePickerFragment mFragment;
+    private MockContentResolver mContentResolver;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        FakeFeatureFactory.setupForTest(mActivity);
+        when(mActivity.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
+
+        mFragment = spy(new ShortcutServicePickerFragment());
+        mFragment.onAttach((Context) mActivity);
+
+        doReturn(RuntimeEnvironment.application).when(mFragment).getContext();
+    }
+
+    @Test
+    public void setAndGetDefaultAppKey_shouldUpdateDefaultAppKey() {
+        assertThat(mFragment.setDefaultKey(TEST_SERVICE_KEY_1)).isTrue();
+        assertThat(mFragment.getDefaultKey()).isEqualTo(TEST_SERVICE_KEY_1);
+    }
+}
+
diff --git a/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java b/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java
index b457422..209cdeb 100644
--- a/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java
+++ b/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java
@@ -85,31 +85,6 @@
     }
 
     @Test
-    public void getInstallationStatus_notInstalled_shouldReturnUninstalled() {
-
-        assertThat(mAppDetail.getInstallationStatus(new ApplicationInfo()))
-                .isEqualTo(R.string.not_installed);
-    }
-
-    @Test
-    public void getInstallationStatus_enabled_shouldReturnInstalled() {
-        final ApplicationInfo info = new ApplicationInfo();
-        info.flags = ApplicationInfo.FLAG_INSTALLED;
-        info.enabled = true;
-
-        assertThat(mAppDetail.getInstallationStatus(info)).isEqualTo(R.string.installed);
-    }
-
-    @Test
-    public void getInstallationStatus_disabled_shouldReturnDisabled() {
-        final ApplicationInfo info = new ApplicationInfo();
-        info.flags = ApplicationInfo.FLAG_INSTALLED;
-        info.enabled = false;
-
-        assertThat(mAppDetail.getInstallationStatus(info)).isEqualTo(R.string.disabled);
-    }
-
-    @Test
     public void shouldShowUninstallForAll_installForOneOtherUserOnly_shouldReturnTrue() {
         when(mDevicePolicyManager.packageHasActiveAdmins(anyString())).thenReturn(false);
         when(mUserManager.getUsers().size()).thenReturn(2);
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java
index 18b0c82..7d1f79b 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java
@@ -31,6 +31,7 @@
 import android.app.Fragment;
 import android.content.Context;
 import android.content.Intent;
+import android.graphics.drawable.Drawable;
 import android.os.UserHandle;
 import android.os.storage.VolumeInfo;
 import android.support.v7.preference.PreferenceScreen;
@@ -243,4 +244,43 @@
         assertThat(system.getSummary().toString()).isEqualTo("16.00KB");
         assertThat(files.getSummary().toString()).isEqualTo("5.00KB");
     }
+
+    @Test
+    public void settingUserIdAppliesNewIcons() {
+        StorageItemPreference audio = spy(new StorageItemPreference(mContext));
+        audio.setIcon(R.drawable.ic_photo_library_vd_theme_24);
+        StorageItemPreference image = spy(new StorageItemPreference(mContext));
+        image.setIcon(R.drawable.ic_photo_library_vd_theme_24);
+        StorageItemPreference games = spy(new StorageItemPreference(mContext));
+        games.setIcon(R.drawable.ic_photo_library_vd_theme_24);
+        StorageItemPreference apps = spy(new StorageItemPreference(mContext));
+        apps.setIcon(R.drawable.ic_photo_library_vd_theme_24);
+        StorageItemPreference system = spy(new StorageItemPreference(mContext));
+        system.setIcon(R.drawable.ic_photo_library_vd_theme_24);
+        StorageItemPreference files = spy(new StorageItemPreference(mContext));
+        files.setIcon(R.drawable.ic_photo_library_vd_theme_24);
+        PreferenceScreen screen = mock(PreferenceScreen.class);
+        when(screen.findPreference(
+                eq(StorageItemPreferenceController.AUDIO_KEY))).thenReturn(audio);
+        when(screen.findPreference(
+                eq(StorageItemPreferenceController.PHOTO_KEY))).thenReturn(image);
+        when(screen.findPreference(
+                eq(StorageItemPreferenceController.GAME_KEY))).thenReturn(games);
+        when(screen.findPreference(
+                eq(StorageItemPreferenceController.OTHER_APPS_KEY))).thenReturn(apps);
+        when(screen.findPreference(
+                eq(StorageItemPreferenceController.SYSTEM_KEY))).thenReturn(system);
+        when(screen.findPreference(
+                eq(StorageItemPreferenceController.FILES_KEY))).thenReturn(files);
+        mController.displayPreference(screen);
+
+        mController.setUserId(new UserHandle(10));
+
+        verify(audio, times(2)).setIcon(any(Drawable.class));
+        verify(image, times(2)).setIcon(any(Drawable.class));
+        verify(games, times(2)).setIcon(any(Drawable.class));
+        verify(apps, times(2)).setIcon(any(Drawable.class));
+        verify(system, times(2)).setIcon(any(Drawable.class));
+        verify(files, times(2)).setIcon(any(Drawable.class));
+    }
 }
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
new file mode 100644
index 0000000..8b5ce19
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.fuelgauge;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.Fragment;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.graphics.drawable.Drawable;
+import android.os.BatteryStats;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.view.View;
+
+import com.android.internal.os.BatterySipper;
+import com.android.internal.os.BatteryStatsHelper;
+import com.android.settings.SettingsActivity;
+import com.android.settings.TestConfig;
+import com.android.settings.applications.AppHeaderController;
+import com.android.settings.applications.LayoutPreference;
+import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settingslib.applications.ApplicationsState;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
+
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class AdvancedPowerUsageDetailTest {
+    private static final String APP_LABEL = "app label";
+    private static final String SUMMARY = "summary";
+    private static final String[] PACKAGE_NAME = {"com.android.app"};
+    private static final String USAGE_PERCENT = "16";
+    private static final int ICON_ID = 123;
+    private static final int UID = 1;
+    private static final long BACKGROUND_TIME_US = 100 * 1000;
+    private static final long FOREGROUND_TIME_US = 200 * 1000;
+    private static final long BACKGROUND_TIME_MS = 100;
+    private static final long FOREGROUND_TIME_MS = 200;
+
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private Context mContext;
+    @Mock
+    private AppHeaderController mAppHeaderController;
+    @Mock
+    private LayoutPreference mHeaderPreference;
+    @Mock
+    private ApplicationsState mState;
+    @Mock
+    private ApplicationsState.AppEntry mAppEntry;
+    @Mock
+    private Drawable mIconDrawable;
+    @Mock
+    private Bundle mBundle;
+    @Mock
+    private BatteryEntry mBatteryEntry;
+    @Mock
+    private BatterySipper mBatterySipper;
+    @Mock
+    private BatteryStatsHelper mBatteryStatsHelper;
+    @Mock
+    private BatteryStats.Uid mUid;
+    private Bundle mTestBundle;
+    private AdvancedPowerUsageDetail mFragment;
+    private FakeFeatureFactory mFeatureFactory;
+    private SettingsActivity mTestActivity;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        FakeFeatureFactory.setupForTest(mContext);
+        mFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
+
+        mFragment = spy(new AdvancedPowerUsageDetail());
+        doReturn(mContext).when(mFragment).getContext();
+        doReturn(SUMMARY).when(mFragment).getString(anyInt());
+        doReturn(APP_LABEL).when(mBundle).getString(anyString());
+        doReturn(mBundle).when(mFragment).getArguments();
+
+        doReturn(mAppHeaderController).when(mFeatureFactory.applicationFeatureProvider)
+                .newAppHeaderController(any(Fragment.class), any(View.class));
+        doReturn(mAppHeaderController).when(mAppHeaderController).setButtonActions(anyInt(),
+                anyInt());
+        doReturn(mAppHeaderController).when(mAppHeaderController).setIcon(any(Drawable.class));
+        doReturn(mAppHeaderController).when(mAppHeaderController).setIcon(any(
+                ApplicationsState.AppEntry.class));
+        doReturn(mAppHeaderController).when(mAppHeaderController).setLabel(anyString());
+        doReturn(mAppHeaderController).when(mAppHeaderController).setLabel(any(
+                ApplicationsState.AppEntry.class));
+        doReturn(mAppHeaderController).when(mAppHeaderController).setSummary(anyString());
+
+
+        doReturn(UID).when(mBatterySipper).getUid();
+        doReturn(APP_LABEL).when(mBatteryEntry).getLabel();
+        doReturn(BACKGROUND_TIME_US).when(mUid).getProcessStateTime(
+                eq(BatteryStats.Uid.PROCESS_STATE_BACKGROUND), anyLong(), anyInt());
+        doReturn(FOREGROUND_TIME_US).when(mUid).getProcessStateTime(
+                eq(BatteryStats.Uid.PROCESS_STATE_FOREGROUND), anyLong(), anyInt());
+        ReflectionHelpers.setField(mBatteryEntry, "sipper", mBatterySipper);
+        mBatteryEntry.iconId = ICON_ID;
+        mBatterySipper.uidObj = mUid;
+
+        mFragment.mHeaderPreference = mHeaderPreference;
+        mFragment.mState = mState;
+        mAppEntry.info = mock(ApplicationInfo.class);
+
+        mTestActivity = spy(new SettingsActivity());
+
+        final ArgumentCaptor<Bundle> captor = ArgumentCaptor.forClass(Bundle.class);
+
+        Answer<Void> callable = new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Exception {
+                mBundle = captor.getValue();
+                return null;
+            }
+        };
+        doAnswer(callable).when(mTestActivity).startPreferencePanelAsUser(any(), anyString(),
+                captor.capture(), anyInt(), any(), any());
+    }
+
+    @Test
+    public void testInitHeader_NoAppEntry_BuildByBundle() {
+        mFragment.mAppEntry = null;
+        mFragment.initHeader();
+
+        verify(mAppHeaderController).setIcon(any(Drawable.class));
+        verify(mAppHeaderController).setLabel(APP_LABEL);
+    }
+
+    @Test
+    public void testInitHeader_HasAppEntry_BuildByAppEntry() {
+        mFragment.mAppEntry = mAppEntry;
+        mFragment.initHeader();
+
+        verify(mAppHeaderController).setIcon(mAppEntry);
+        verify(mAppHeaderController).setLabel(mAppEntry);
+    }
+
+    @Test
+    public void testStartBatteryDetailPage_hasBasicData() {
+        AdvancedPowerUsageDetail.startBatteryDetailPage(mTestActivity, null, mBatteryStatsHelper, 0,
+                mBatteryEntry, USAGE_PERCENT);
+
+        assertThat(mBundle.getInt(AdvancedPowerUsageDetail.EXTRA_UID)).isEqualTo(UID);
+        assertThat(mBundle.getLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME)).isEqualTo(
+                BACKGROUND_TIME_MS);
+        assertThat(mBundle.getLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME)).isEqualTo(
+                FOREGROUND_TIME_MS);
+        assertThat(mBundle.getString(AdvancedPowerUsageDetail.EXTRA_POWER_USAGE_PERCENT)).isEqualTo(
+                USAGE_PERCENT);
+    }
+
+    @Test
+    public void testStartBatteryDetailPage_NormalApp() {
+        mBatterySipper.mPackages = PACKAGE_NAME;
+        AdvancedPowerUsageDetail.startBatteryDetailPage(mTestActivity, null, mBatteryStatsHelper, 0,
+                mBatteryEntry, USAGE_PERCENT);
+
+        assertThat(mBundle.getString(AdvancedPowerUsageDetail.EXTRA_PACKAGE_NAME)).isEqualTo(
+                PACKAGE_NAME[0]);
+    }
+
+    @Test
+    public void testStartBatteryDetailPage_SystemApp() {
+        mBatterySipper.mPackages = null;
+        AdvancedPowerUsageDetail.startBatteryDetailPage(mTestActivity, null, mBatteryStatsHelper, 0,
+                mBatteryEntry, USAGE_PERCENT);
+
+        assertThat(mBundle.getString(AdvancedPowerUsageDetail.EXTRA_LABEL)).isEqualTo(APP_LABEL);
+        assertThat(mBundle.getInt(AdvancedPowerUsageDetail.EXTRA_ICON_ID)).isEqualTo(ICON_ID);
+        assertThat(mBundle.getString(AdvancedPowerUsageDetail.EXTRA_PACKAGE_NAME)).isEqualTo(null);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryOptimizationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryOptimizationPreferenceControllerTest.java
new file mode 100644
index 0000000..2c5296a
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryOptimizationPreferenceControllerTest.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.fuelgauge;
+
+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.Matchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import android.support.v7.preference.Preference;
+
+import com.android.settings.SettingsActivity;
+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.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class BatteryOptimizationPreferenceControllerTest {
+    private static final String KEY_OPTIMIZATION = "battery_optimization";
+    private static final String KEY_OTHER = "other";
+    @Mock
+    private SettingsActivity mSettingsActivity;
+    @Mock
+    private Fragment mFragment;
+    @Mock
+    private Preference mPreference;
+
+    private BatteryOptimizationPreferenceController mController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mController = new BatteryOptimizationPreferenceController(mSettingsActivity, mFragment);
+    }
+
+    @Test
+    public void testHandlePreferenceTreeClick_OptimizationPreference_HandleClick() {
+        when(mPreference.getKey()).thenReturn(KEY_OPTIMIZATION);
+
+        final boolean handled = mController.handlePreferenceTreeClick(mPreference);
+
+        assertThat(handled).isTrue();
+        verify(mSettingsActivity).startPreferencePanel(any(Fragment.class),
+                anyString(), any(Bundle.class), anyInt(), any(CharSequence.class),
+                any(Fragment.class), anyInt());
+    }
+
+    @Test
+    public void testHandlePreferenceTreeClick_OtherPreference_NotHandleClick() {
+        when(mPreference.getKey()).thenReturn(KEY_OTHER);
+
+        final boolean handled = mController.handlePreferenceTreeClick(mPreference);
+
+        assertThat(handled).isFalse();
+        verify(mSettingsActivity, never()).startPreferencePanel(any(Fragment.class),
+                anyString(), any(Bundle.class), anyInt(), any(CharSequence.class),
+                any(Fragment.class), anyInt());
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java
new file mode 100644
index 0000000..672cc90
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settings.fuelgauge;
+
+import android.os.BatteryStats;
+
+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 android.os.BatteryStats.Uid.PROCESS_STATE_BACKGROUND;
+import static android.os.BatteryStats.Uid.PROCESS_STATE_FOREGROUND;
+import static android.os.BatteryStats.Uid.PROCESS_STATE_FOREGROUND_SERVICE;
+import static android.os.BatteryStats.Uid.PROCESS_STATE_TOP;
+import static android.os.BatteryStats.Uid.PROCESS_STATE_TOP_SLEEPING;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Matchers.eq;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class BatteryUtilsTest {
+    // unit that used to converted ms to us
+    private static final long UNIT = 1000;
+    private static final long TIME_STATE_TOP = 1500 * UNIT;
+    private static final long TIME_STATE_FOREGROUND_SERVICE = 2000 * UNIT;
+    private static final long TIME_STATE_TOP_SLEEPING = 2500 * UNIT;
+    private static final long TIME_STATE_FOREGROUND = 3000 * UNIT;
+    private static final long TIME_STATE_BACKGROUND = 6000 * UNIT;
+
+    private static final long TIME_EXPECTED_FOREGROUND = 9000;
+    private static final long TIME_EXPECTED_BACKGROUND = 6000;
+    private static final long TIME_EXPECTED_ALL = 15000;
+
+    @Mock
+    BatteryStats.Uid mUid;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        doReturn(TIME_STATE_TOP).when(mUid).getProcessStateTime(eq(PROCESS_STATE_TOP), anyLong(),
+                anyInt());
+        doReturn(TIME_STATE_FOREGROUND_SERVICE).when(mUid).getProcessStateTime(
+                eq(PROCESS_STATE_FOREGROUND_SERVICE), anyLong(), anyInt());
+        doReturn(TIME_STATE_TOP_SLEEPING).when(mUid).getProcessStateTime(
+                eq(PROCESS_STATE_TOP_SLEEPING), anyLong(), anyInt());
+        doReturn(TIME_STATE_FOREGROUND).when(mUid).getProcessStateTime(eq(PROCESS_STATE_FOREGROUND),
+                anyLong(), anyInt());
+        doReturn(TIME_STATE_BACKGROUND).when(mUid).getProcessStateTime(eq(PROCESS_STATE_BACKGROUND),
+                anyLong(), anyInt());
+    }
+
+    @Test
+    public void testGetProcessTimeMs_typeForeground_timeCorrect() {
+        final long time = BatteryUtils.getProcessTimeMs(BatteryUtils.StatusType.FOREGROUND, mUid,
+                BatteryStats.STATS_SINCE_CHARGED);
+
+        assertThat(time).isEqualTo(TIME_EXPECTED_FOREGROUND);
+    }
+
+    @Test
+    public void testGetProcessTimeMs_typeBackground_timeCorrect() {
+        final long time = BatteryUtils.getProcessTimeMs(BatteryUtils.StatusType.BACKGROUND, mUid,
+                BatteryStats.STATS_SINCE_CHARGED);
+
+        assertThat(time).isEqualTo(TIME_EXPECTED_BACKGROUND);
+    }
+
+    @Test
+    public void testGetProcessTimeMs_typeAll_timeCorrect() {
+        final long time = BatteryUtils.getProcessTimeMs(BatteryUtils.StatusType.ALL, mUid,
+                BatteryStats.STATS_SINCE_CHARGED);
+
+        assertThat(time).isEqualTo(TIME_EXPECTED_ALL);
+    }
+
+    @Test
+    public void testGetProcessTimeMs_uidNull_returnZero() {
+        final long time = BatteryUtils.getProcessTimeMs(BatteryUtils.StatusType.ALL, null,
+                BatteryStats.STATS_SINCE_CHARGED);
+
+        assertThat(time).isEqualTo(0);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/inputmethod/PhysicalKeyboardPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/inputmethod/PhysicalKeyboardPreferenceControllerTest.java
new file mode 100644
index 0000000..5fa2c0d
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/inputmethod/PhysicalKeyboardPreferenceControllerTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.inputmethod;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.hardware.input.InputManager;
+import android.support.v7.preference.Preference;
+import android.view.InputDevice;
+
+import com.android.settings.R;
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.shadow.ShadowInputDevice;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class PhysicalKeyboardPreferenceControllerTest {
+
+    @Mock
+    private Context mContext;
+    @Mock
+    private InputManager mIm;
+    @Mock
+    private Preference mPreference;
+
+    private PhysicalKeyboardPreferenceController mController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        when(mContext.getSystemService(Context.INPUT_SERVICE)).thenReturn(mIm);
+        mController = new PhysicalKeyboardPreferenceController(mContext, null /* lifecycle */);
+    }
+
+    @After
+    public void tearDown() {
+        ShadowInputDevice.reset();
+    }
+
+    @Test
+    public void shouldAlwaysBeAvailable() {
+        assertThat(mController.isAvailable()).isTrue();
+    }
+
+    @Test
+    @Config(shadows = {
+            ShadowInputDevice.class,
+    })
+    public void updateState_noKeyboard_setDisconnectedSummary() {
+        ShadowInputDevice.sDeviceIds = new int[]{};
+        mController.updateState(mPreference);
+
+        verify(mPreference).setSummary(R.string.disconnected);
+    }
+
+    @Test
+    @Config(shadows = ShadowInputDevice.class)
+    public void updateState_hasKeyboard_setSummaryToKeyboardName() {
+        final InputDevice device = mock(InputDevice.class);
+        when(device.isVirtual()).thenReturn(false);
+        when(device.isFullKeyboard()).thenReturn(true);
+        when(device.getName()).thenReturn("test_keyboard");
+        ShadowInputDevice.sDeviceIds = new int[]{0};
+        ShadowInputDevice.addDevice(0, device);
+
+        mController.updateState(mPreference);
+
+        verify(mPreference).setSummary(device.getName());
+    }
+
+}
diff --git a/tests/robotests/src/com/android/settings/inputmethod/VirtualKeyboardPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/inputmethod/VirtualKeyboardPreferenceControllerTest.java
new file mode 100644
index 0000000..3256950
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/inputmethod/VirtualKeyboardPreferenceControllerTest.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.inputmethod;
+
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.support.v7.preference.Preference;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodManager;
+
+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.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class VirtualKeyboardPreferenceControllerTest {
+
+    @Mock
+    private Context mContext;
+    @Mock
+    private InputMethodManager mImm;
+    @Mock
+    private DevicePolicyManager mDpm;
+    @Mock
+    private PackageManager mPm;
+    @Mock
+    private Preference mPreference;
+
+    private VirtualKeyboardPreferenceController mController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        when(mContext.getSystemService(Context.DEVICE_POLICY_SERVICE)).thenReturn(mDpm);
+        when(mContext.getSystemService(Context.INPUT_METHOD_SERVICE)).thenReturn(mImm);
+        when(mContext.getPackageManager()).thenReturn(mPm);
+        mController = new VirtualKeyboardPreferenceController(mContext);
+    }
+
+    @Test
+    public void shouldAlwaysBeAvailable() {
+        assertThat(mController.isAvailable()).isTrue();
+    }
+
+    @Test
+    public void updateState_noEnabledIMEs_setEmptySummary() {
+        mController.updateState(mPreference);
+
+        verify(mPreference).setSummary(R.string.summary_empty);
+    }
+
+    @Test
+    public void updateState_singleIme_setImeLabelToSummary() {
+        when(mDpm.getPermittedInputMethodsForCurrentUser()).thenReturn(null);
+        final ComponentName componentName = new ComponentName("pkg", "cls");
+        final List<InputMethodInfo> imis = new ArrayList<>();
+        imis.add(mock(InputMethodInfo.class));
+        when(imis.get(0).getPackageName()).thenReturn(componentName.getPackageName());
+        when(mImm.getEnabledInputMethodList()).thenReturn(imis);
+        when(imis.get(0).loadLabel(mPm)).thenReturn("label");
+
+        mController.updateState(mPreference);
+
+        verify(mPreference).setSummary("label");
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/language/LanguageAndInputSettingsTest.java b/tests/robotests/src/com/android/settings/language/LanguageAndInputSettingsTest.java
index 026264e..643e305 100644
--- a/tests/robotests/src/com/android/settings/language/LanguageAndInputSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/language/LanguageAndInputSettingsTest.java
@@ -16,7 +16,15 @@
 
 package com.android.settings.language;
 
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
 import android.app.Activity;
+import android.app.admin.DevicePolicyManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.PackageManager;
@@ -48,13 +56,6 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.mock;
-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 LanguageAndInputSettingsTest {
@@ -64,6 +65,12 @@
     @Mock
     private PackageManager mPackageManager;
     @Mock
+    private InputManager mIm;
+    @Mock
+    private InputMethodManager mImm;
+    @Mock
+    private DevicePolicyManager mDpm;
+    @Mock
     private InputMethodManager mInputMethodManager;
     private TestFragment mFragment;
 
@@ -72,8 +79,11 @@
         MockitoAnnotations.initMocks(this);
         when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mock(UserManager.class));
         when(mContext.getSystemService(Context.INPUT_SERVICE)).thenReturn(mock(InputManager.class));
+        when(mContext.getSystemService(Context.INPUT_SERVICE)).thenReturn(mIm);
         when(mContext.getSystemService(Context.TEXT_SERVICES_MANAGER_SERVICE))
                 .thenReturn(mock(TextServicesManager.class));
+        when(mContext.getSystemService(Context.DEVICE_POLICY_SERVICE)).thenReturn(mDpm);
+        when(mContext.getSystemService(Context.INPUT_METHOD_SERVICE)).thenReturn(mImm);
         mFragment = new TestFragment(mContext);
     }
 
@@ -96,6 +106,7 @@
     }
 
     @Test
+
     public void testGetPreferenceControllers_shouldAllBeCreated() {
         final List<PreferenceController> controllers = mFragment.getPreferenceControllers(mContext);
 
diff --git a/tests/robotests/src/com/android/settings/network/NetworkResetActionMenuControllerTest.java b/tests/robotests/src/com/android/settings/network/NetworkResetActionMenuControllerTest.java
index ba332b7..7cd76d3 100644
--- a/tests/robotests/src/com/android/settings/network/NetworkResetActionMenuControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/NetworkResetActionMenuControllerTest.java
@@ -17,6 +17,14 @@
 package com.android.settings.network;
 
 
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
 import android.content.Context;
 import android.view.Menu;
 import android.view.MenuItem;
@@ -32,14 +40,6 @@
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Mockito.doReturn;
-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 NetworkResetActionMenuControllerTest {
diff --git a/tests/robotests/src/com/android/settings/network/NetworkScorerPickerPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/NetworkScorerPickerPreferenceControllerTest.java
index 6bf47ac..1e468a3 100644
--- a/tests/robotests/src/com/android/settings/network/NetworkScorerPickerPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/NetworkScorerPickerPreferenceControllerTest.java
@@ -68,7 +68,8 @@
         Settings.System.putInt(mContext.getContentResolver(), NETWORK_RECOMMENDATIONS_ENABLED, 1);
         ComponentName scorer = new ComponentName(TEST_SCORER_PACKAGE, TEST_SCORER_CLASS);
         NetworkScorerAppData scorerAppData = new NetworkScorerAppData(
-                0, scorer, TEST_SCORER_LABEL, null /* enableUseOpenWifiActivity */);
+                0, scorer, TEST_SCORER_LABEL, null /* enableUseOpenWifiActivity */,
+                null /* networkAvailableNotificationChannelId */);
         when(mNetworkScorer.getActiveScorer()).thenReturn(scorerAppData);
         Preference preference = mock(Preference.class);
 
diff --git a/tests/robotests/src/com/android/settings/network/NetworkScorerPickerTest.java b/tests/robotests/src/com/android/settings/network/NetworkScorerPickerTest.java
index fef6f85..bb8635f 100644
--- a/tests/robotests/src/com/android/settings/network/NetworkScorerPickerTest.java
+++ b/tests/robotests/src/com/android/settings/network/NetworkScorerPickerTest.java
@@ -118,7 +118,8 @@
     public void testUpdateCandidates_validScorer() {
         ComponentName scorer = new ComponentName(TEST_SCORER_PACKAGE_1, TEST_SCORER_CLASS_1);
         NetworkScorerAppData scorerAppData = new NetworkScorerAppData(
-                0, scorer, TEST_SCORER_LABEL_1, null /* enableUseOpenWifiActivity */);
+                0, scorer, TEST_SCORER_LABEL_1, null /* enableUseOpenWifiActivity */,
+                null /* networkAvailableNotificationChannelId */);
         when(mNetworkScoreManager.getAllValidScorers()).thenReturn(
                 Lists.newArrayList(scorerAppData));
         when(mNetworkScoreManager.getActiveScorerPackage()).thenReturn(TEST_SCORER_PACKAGE_1);
diff --git a/tests/robotests/src/com/android/settings/notification/ZenModePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenModePreferenceControllerTest.java
index a31fb5e..685390e 100644
--- a/tests/robotests/src/com/android/settings/notification/ZenModePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/ZenModePreferenceControllerTest.java
@@ -21,6 +21,7 @@
 import android.content.Context;
 import android.support.v7.preference.Preference;
 
+import com.android.settings.R;
 import com.android.settings.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
 
@@ -30,11 +31,14 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowApplication;
 import org.robolectric.util.ReflectionHelpers;
 
 import static com.google.common.truth.Truth.assertThat;
 import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -43,23 +47,27 @@
 public class ZenModePreferenceControllerTest {
 
     @Mock
-    private Context mContext;
-    @Mock
     private Preference mPreference;
     @Mock
     private NotificationManager mNotificationManager;
     @Mock
     private Policy mPolicy;
 
+    private Context mContext;
     private ZenModePreferenceController mController;
+    private ZenModeSettings.SummaryBuilder mSummaryBuilder;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
+        ShadowApplication shadowApplication = ShadowApplication.getInstance();
+        shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
+        mContext = shadowApplication.getApplicationContext();
         mController = new ZenModePreferenceController(mContext);
-        when(mContext.getSystemService(Context.NOTIFICATION_SERVICE))
-            .thenReturn(mNotificationManager);
         when(mNotificationManager.getNotificationPolicy()).thenReturn(mPolicy);
+        mSummaryBuilder = spy(new ZenModeSettings.SummaryBuilder(mContext));
+        ReflectionHelpers.setField(mController, "mSummaryBuilder", mSummaryBuilder);
+        doReturn(0).when(mSummaryBuilder).getEnabledAutomaticRulesCount();
     }
 
     @Test
@@ -72,8 +80,12 @@
         when(mPreference.isEnabled()).thenReturn(true);
 
         mController.updateState(mPreference);
+        verify(mPreference).setSummary(mContext.getString(R.string.zen_mode_settings_summary_off));
 
-        verify(mPreference).setSummary(anyString());
+        doReturn(1).when(mSummaryBuilder).getEnabledAutomaticRulesCount();
+        mController.updateState(mPreference);
+        verify(mPreference).setSummary(mContext.getResources().getQuantityString(
+            R.plurals.zen_mode_settings_summary_on, 1, 1));
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/system/FactoryResetPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/system/FactoryResetPreferenceControllerTest.java
index f41870e..1d15b42 100644
--- a/tests/robotests/src/com/android/settings/system/FactoryResetPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/system/FactoryResetPreferenceControllerTest.java
@@ -16,11 +16,10 @@
 package com.android.settings.system;
 
 import static com.google.common.truth.Truth.assertThat;
-
 import static org.mockito.Answers.RETURNS_DEEP_STUBS;
-
 import static org.mockito.Mockito.when;
 
+import android.accounts.AccountManager;
 import android.content.Context;
 import android.os.UserManager;
 
@@ -45,13 +44,17 @@
     private Context mContext;
     @Mock
     private UserManager mUserManager;
+    @Mock
+    private AccountManager mAccountManager;
 
     private FactoryResetPreferenceController mController;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mController = new FactoryResetPreferenceController(mContext, mUserManager);
+        when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
+        when(mContext.getSystemService(Context.ACCOUNT_SERVICE)).thenReturn(mAccountManager);
+        mController = new FactoryResetPreferenceController(mContext);
     }
 
     @Test
@@ -68,7 +71,8 @@
         assertThat(mController.isAvailable()).isFalse();
     }
 
-    @Test public void getPreferenceKey() {
+    @Test
+    public void getPreferenceKey() {
         assertThat(mController.getPreferenceKey()).isEqualTo(FACTORY_RESET_KEY);
     }
 }
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowInputDevice.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowInputDevice.java
new file mode 100644
index 0000000..ecb1b71
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowInputDevice.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.testutils.shadow;
+
+import android.view.InputDevice;
+
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+import org.robolectric.annotation.Resetter;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Implements(InputDevice.class)
+public class ShadowInputDevice extends org.robolectric.shadows.ShadowInputDevice {
+
+    public static int[] sDeviceIds;
+
+    private static Map<Integer, InputDevice> sDeviceMap = new HashMap<>();
+
+    @Implementation
+    public static int[] getDeviceIds() {
+        return sDeviceIds;
+    }
+
+    @Implementation
+    public static InputDevice getDevice(int id) {
+        return sDeviceMap.get(id);
+    }
+
+    public static void addDevice(int id, InputDevice device) {
+        sDeviceMap.put(id, device);
+    }
+
+    @Resetter
+    public static void reset() {
+        sDeviceIds = null;
+        sDeviceMap.clear();
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/wifi/UseOpenWifiPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/UseOpenWifiPreferenceControllerTest.java
index aa89464..5b55006 100644
--- a/tests/robotests/src/com/android/settings/wifi/UseOpenWifiPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/UseOpenWifiPreferenceControllerTest.java
@@ -56,9 +56,9 @@
 public class UseOpenWifiPreferenceControllerTest {
     private static ComponentName ENABLE_ACTIVITY_COMPONENT = new ComponentName("package", "activityClass");
     private static NetworkScorerAppData APP_DATA =
-            new NetworkScorerAppData(0, null, null, ENABLE_ACTIVITY_COMPONENT);
+            new NetworkScorerAppData(0, null, null, ENABLE_ACTIVITY_COMPONENT, null);
     private static NetworkScorerAppData APP_DATA_NO_ACTIVITY =
-            new NetworkScorerAppData(0, null, null, null);
+            new NetworkScorerAppData(0, null, null, null, null);
 
     @Mock private Lifecycle mLifecycle;
     @Mock private Fragment mFragment;
diff --git a/tests/robotests/src/com/android/settings/wifi/WriteWifiConfigToNfcDialogTest.java b/tests/robotests/src/com/android/settings/wifi/WriteWifiConfigToNfcDialogTest.java
index 6e45cde..000f2fa 100644
--- a/tests/robotests/src/com/android/settings/wifi/WriteWifiConfigToNfcDialogTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/WriteWifiConfigToNfcDialogTest.java
@@ -46,10 +46,8 @@
         shadows = ShadowNfcAdapter.class
 )
 public class WriteWifiConfigToNfcDialogTest {
-    private static final int NETWORK_ID = 17;
-
     @Mock Activity mActivity;
-    @Mock WifiManager mWifiManager;
+    @Mock WifiManagerWrapper mWifiManager;
 
     private WriteWifiConfigToNfcDialog mWriteWifiConfigToNfcDialog;
 
@@ -61,7 +59,7 @@
                 .thenReturn(ReflectionHelpers.newInstance(InputMethodManager.class));
 
         mWriteWifiConfigToNfcDialog = new WriteWifiConfigToNfcDialog(RuntimeEnvironment.application,
-                NETWORK_ID, 0 /* security */, mWifiManager);
+                0 /* security */, mWifiManager);
         mWriteWifiConfigToNfcDialog.setOwnerActivity(mActivity);
         mWriteWifiConfigToNfcDialog.onCreate(null /* savedInstanceState */);
     }
@@ -73,7 +71,7 @@
 
     @Test
     public void testOnClick_nfcConfigurationTokenDoesNotContainPasswordHex() {
-        when(mWifiManager.getWpsNfcConfigurationToken(NETWORK_ID)).thenReturn("blah");
+        when(mWifiManager.getCurrentNetworkWpsNfcConfigurationToken()).thenReturn("blah");
 
         mWriteWifiConfigToNfcDialog.onClick(null);
 
@@ -82,7 +80,7 @@
 
     @Test
     public void testOnClick_nfcConfigurationTokenIsNull() {
-        when(mWifiManager.getWpsNfcConfigurationToken(NETWORK_ID)).thenReturn(null);
+        when(mWifiManager.getCurrentNetworkWpsNfcConfigurationToken()).thenReturn(null);
 
         mWriteWifiConfigToNfcDialog.onClick(null);
 
@@ -92,7 +90,7 @@
     @Test
     public void testOnClick_nfcConfigurationTokenContainsPasswordHex() {
         // This is the corresponding passwordHex for an empty string password.
-        when(mWifiManager.getWpsNfcConfigurationToken(NETWORK_ID)).thenReturn("10270000");
+        when(mWifiManager.getCurrentNetworkWpsNfcConfigurationToken()).thenReturn("10270000");
 
         mWriteWifiConfigToNfcDialog.onClick(null);
 
diff --git a/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
index a7e12b3..88a63b3 100644
--- a/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
@@ -84,8 +84,6 @@
         MockitoAnnotations.initMocks(this);
 
         mLifecycle = new Lifecycle();
-        mController = new WifiDetailPreferenceController(
-                mockAccessPoint, mContext, mLifecycle, mockWifiManager);
 
         when(mockAccessPoint.getConfig()).thenReturn(mockWifiConfig);
         when(mockAccessPoint.getLevel()).thenReturn(LEVEL);
@@ -93,11 +91,13 @@
         when(mockAccessPoint.getRssi()).thenReturn(RSSI);
         when(mockAccessPoint.getSecurityString(false)).thenReturn(SECURITY);
 
+        mController = new WifiDetailPreferenceController(
+                mockAccessPoint, mContext, mLifecycle, mockWifiManager);
+
         setupMockedPreferenceScreen();
 
-        when (mockWifiInfo.getRssi()).thenReturn(RSSI);
+        when(mockWifiInfo.getRssi()).thenReturn(RSSI);
         when(mockWifiManager.getConnectionInfo()).thenReturn(mockWifiInfo);
-        when(mockWifiManager.getWifiApConfiguration()).thenReturn(mockWifiConfig);
     }
 
     private void setupMockedPreferenceScreen() {
@@ -139,7 +139,6 @@
         mController.onResume();
 
         verify(mockWifiManager).getConnectionInfo();
-        verify(mockWifiManager).getWifiApConfiguration();
     }
 
     @Test
@@ -178,4 +177,29 @@
 
         verify(mockSignalStrengthPref).setDetailText(expectedStrength);
     }
+
+    @Test
+    public void forgetNetwork_ephemeral() {
+        WifiConfiguration wifiConfiguration = new WifiConfiguration();
+        wifiConfiguration.SSID = "ssid";
+        // WifiConfiguration#isEphemeral will not be visible in robolectric until O is supported
+        wifiConfiguration.ephemeral = true;
+        when(mockAccessPoint.getConfig()).thenReturn(wifiConfiguration);
+
+        mController = new WifiDetailPreferenceController(
+                mockAccessPoint, mContext, mLifecycle, mockWifiManager);
+
+        mController.forgetNetwork();
+
+        verify(mockWifiManager).disableEphemeralNetwork(wifiConfiguration.SSID);
+    }
+
+    @Test
+    public void forgetNetwork_saved() {
+        mockWifiConfig.networkId = 5;
+
+        mController.forgetNetwork();
+
+        verify(mockWifiManager).forget(mockWifiConfig.networkId, null);
+    }
 }