Merge "Re-order the display settings items." into oc-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index ed00054..da88f76 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -902,13 +902,23 @@
                 android:icon="@drawable/ic_settings_night_display"
                 android:taskAffinity="">
             <intent-filter android:priority="1">
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="com.android.settings.suggested.category.SETTINGS_ONLY" />
+            </intent-filter>
+            <intent-filter android:priority="1">
                 <action android:name="android.settings.NIGHT_DISPLAY_SETTINGS" />
                 <category android:name="android.intent.category.DEFAULT" />
             </intent-filter>
-            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
-                android:value="com.android.settings.display.NightDisplaySettings" />
             <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
                 android:value="true" />
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                android:value="com.android.settings.display.NightDisplaySettings" />
+            <meta-data android:name="com.android.settings.dismiss"
+                android:value="30" />
+            <meta-data android:name="com.android.settings.title"
+                android:resource="@string/night_display_suggestion_title" />
+            <meta-data android:name="com.android.settings.summary"
+                android:resource="@string/night_display_suggestion_summary" />
         </activity>
 
         <activity android:name="Settings$DeviceInfoSettingsActivity"
@@ -2548,6 +2558,7 @@
             <intent-filter android:priority="1">
                 <action android:name="com.android.settings.SOUND_SETTINGS" />
                 <action android:name="android.settings.SOUND_SETTINGS" />
+                <action android:name="android.settings.ACTION_OTHER_SOUND_SETTINGS" />
                 <category android:name="android.intent.category.DEFAULT" />
             </intent-filter>
             <intent-filter>
@@ -2556,10 +2567,6 @@
                 <category android:name="android.intent.category.VOICE_LAUNCH" />
                 <category android:name="com.android.settings.SHORTCUT" />
             </intent-filter>
-            <intent-filter android:priority="1">
-                <action android:name="android.settings.ACTION_OTHER_SOUND_SETTINGS" />
-                <category android:name="android.intent.category.DEFAULT" />
-            </intent-filter>
             <intent-filter android:priority="6">
                 <action android:name="com.android.settings.action.SETTINGS" />
             </intent-filter>
diff --git a/res/drawable/ic_friction_lock_closed.xml b/res/drawable/ic_friction_lock_closed.xml
index 7a05ac6..194c9af 100644
--- a/res/drawable/ic_friction_lock_closed.xml
+++ b/res/drawable/ic_friction_lock_closed.xml
@@ -21,6 +21,6 @@
         android:height="18dp">
     <path
         android:pathData="M36 16l-2 0 0 -4C34 6.48 29.52 2 24 2 18.48 2 14 6.48 14 12l0 4 -2 0c-2.21 0 -4 1.79 -4 4l0 20c0 2.21 1.79 4 4 4l24 0c2.21 0 4 -1.79 4 -4l0 -20c0 -2.21 -1.79 -4 -4 -4zM24 34c-2.21 0 -4 -1.79 -4 -4 0 -2.21 1.79 -4 4 -4 2.21 0 4 1.79 4 4 0 2.21 -1.79 4 -4 4zm6.2 -18l-12.4 0 0 -4c0 -3.42 2.78 -6.2 6.2 -6.2 3.42 0 6.2 2.78 6.2 6.2l0 4z"
-        android:fillColor="#000000"
+        android:fillColor="?android:attr/colorForeground"
         android:fillAlpha="0.54" />
 </vector>
diff --git a/res/drawable/ic_friction_lock_open.xml b/res/drawable/ic_friction_lock_open.xml
deleted file mode 100644
index 957e537..0000000
--- a/res/drawable/ic_friction_lock_open.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:viewportWidth="48"
-        android:viewportHeight="48"
-        android:width="18dp"
-        android:height="18dp">
-    <path
-        android:pathData="M24 34c2.21 0 4 -1.79 4 -4 0 -2.21 -1.79 -4 -4 -4 -2.21 0 -4 1.79 -4 4 0 2.21 1.79 4 4 4zm12 -18l-2 0 0 -4C34 6.48 29.52 2 24 2 18.48 2 14 6.48 14 12l3.8 0c0 -3.42 2.78 -6.2 6.2 -6.2 3.42 0 6.2 2.78 6.2 6.2l0 4 -18.2 0c-2.21 0 -4 1.79 -4 4l0 20c0 2.21 1.79 4 4 4l24 0c2.21 0 4 -1.79 4 -4l0 -20c0 -2.21 -1.79 -4 -4 -4zm0 24l-24 0 0 -20 24 0 0 20z"
-        android:fillColor="#000000"
-        android:fillAlpha="0.54" />
-</vector>
diff --git a/res/drawable/ic_friction_money.xml b/res/drawable/ic_friction_money.xml
new file mode 100644
index 0000000..1018533
--- /dev/null
+++ b/res/drawable/ic_friction_money.xml
@@ -0,0 +1,31 @@
+<?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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:viewportWidth="18"
+        android:viewportHeight="18"
+        android:width="18dp"
+        android:height="18dp">
+
+    <path android:fillColor="?android:attr/colorForeground"
+          android:fillAlpha="0.54"
+          android:pathData="M9.56 8.1c-1.6-.51-2.66-.71-2.66-1.88 0-.83 .72 -1.62 2.1-1.62 1.59 0 2.1 .88
+          2.1 1.94H13c0-1.79-1.17-3.09-3-3.44V1H8v2.11c-1.58 .32 -3 1.37-3 3.12 0 2.25
+          1.78 2.8 4 3.52 1.88 .61 2.25 1.04 2.25 2.09 0 .9-.67 1.56-2.25 1.56-1.2
+          0-2.25-.84-2.25-2.06h-2c0 1.88 1.38 3.2 3.25 3.56V17h2v-2.07c2.04-.29 3.2-1.49
+          3.2-3.1 0-1.87-.94-2.87-3.64-3.73z" />
+    <path android:pathData="M0 0h18v18H0z" />
+</vector>
diff --git a/res/drawable/ic_instant_apps_badge.xml b/res/drawable/ic_instant_apps_badge.xml
new file mode 100644
index 0000000..115aa83
--- /dev/null
+++ b/res/drawable/ic_instant_apps_badge.xml
@@ -0,0 +1,33 @@
+<?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
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="48dp"
+        android:height="48dp"
+        android:viewportWidth="48"
+        android:viewportHeight="48">
+    <path
+        android:fillColor="#FFFFFF"
+        android:fillType="evenOdd"
+        android:pathData="M 24.5 2.7 C 35.5456949966 2.7 44.5 11.6543050034 44.5 22.7 C 44.5 33.7456949966 35.5456949966 42.7 24.5 42.7 C 13.4543050034 42.7 4.5 33.7456949966 4.5 22.7 C 4.5 11.6543050034 13.4543050034 2.7 24.5 2.7 Z" />
+    <path
+        android:fillColor="#757575"
+        android:fillType="evenOdd"
+        android:pathData="M 33.3 19.1 L 26.4 19.1 L 26.4 5.8 L 16.6 26.4 L 23.5 26.3 L 23.5 39.6 Z" />
+    <path
+        android:fillType="evenOdd"
+        android:pathData="M 0.5 0 H 48.5 V 48 H 0.5 V 0 Z" />
+</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_instant_apps_badge_bg.xml b/res/drawable/ic_instant_apps_badge_bg.xml
new file mode 100644
index 0000000..bf8d3ea
--- /dev/null
+++ b/res/drawable/ic_instant_apps_badge_bg.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2017 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="oval">
+    <gradient android:type="radial"
+        android:startColor="#4d000000"
+        android:endColor="#00000000"
+        android:gradientRadius="12dp"/>
+</shape>
\ No newline at end of file
diff --git a/res/drawable/wifi_friction.xml b/res/drawable/wifi_friction.xml
index 98993c5..fa8268d 100644
--- a/res/drawable/wifi_friction.xml
+++ b/res/drawable/wifi_friction.xml
@@ -19,4 +19,7 @@
     <item
         settings:state_encrypted="true"
         android:drawable="@drawable/ic_friction_lock_closed"/>
+    <item
+        settings:state_metered="true"
+        android:drawable="@drawable/ic_friction_money"/>
 </selector>
diff --git a/res/layout/app_details.xml b/res/layout/app_details.xml
index 00d4cca..4aa1496 100644
--- a/res/layout/app_details.xml
+++ b/res/layout/app_details.xml
@@ -34,13 +34,26 @@
         android:layout_height="wrap_content"
         android:paddingStart="8dp">
 
-        <ImageView
-            android:id="@+id/app_detail_icon"
-            android:layout_width="80dp"
-            android:layout_height="80dp"
-            android:scaleType="fitXY"
-            android:layout_gravity="center_horizontal"
-            android:antialias="true"/>
+        <FrameLayout android:id="@+id/app_icon_frame"
+                     android:layout_width="80dp"
+                     android:layout_height="80dp">
+            <ImageView
+                android:id="@+id/app_detail_icon"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:scaleType="fitXY"
+                android:layout_gravity="center_horizontal"
+                android:antialias="true"/>
+            <ImageView android:id="@+id/app_icon_instant_apps_badge"
+                android:layout_width="22dp"
+                android:layout_height="22dp"
+                android:layout_gravity="end|bottom"
+                android:layout_margin="8dp"
+                android:visibility="gone"
+                android:elevation="20dp"
+                android:background="@drawable/ic_instant_apps_badge_bg"
+                android:src="@drawable/ic_instant_apps_badge" />
+        </FrameLayout>
 
         <LinearLayout
             android:id="@+id/app_detail_links"
@@ -71,7 +84,7 @@
         <LinearLayout
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_toEndOf="@id/app_detail_icon"
+            android:layout_toEndOf="@id/app_icon_frame"
             android:layout_toStartOf="@id/app_detail_links"
             android:paddingStart="24dp"
             android:paddingEnd="24dp"
diff --git a/res/layout/battery_header.xml b/res/layout/battery_header.xml
index ef39d8b..04ef74d 100644
--- a/res/layout/battery_header.xml
+++ b/res/layout/battery_header.xml
@@ -27,44 +27,35 @@
     android:background="@drawable/selectable_card_grey"
     style="@style/EntityHeader">
 
-    <com.android.settings.fuelgauge.BatteryMeterView
-        android:id="@+id/battery_header_icon"
-        android:layout_width="@dimen/battery_meter_width"
-        android:layout_height="@dimen/battery_meter_height"/>
-
     <LinearLayout
-        android:layout_width="wrap_content"
+        android:layout_width="216dp"
         android:layout_height="wrap_content"
-        android:layout_marginStart="12dp"
+        android:layout_marginStart="48dp"
         android:layout_marginEnd="12dp"
         android:orientation="vertical">
 
         <TextView
-            android:id="@+id/time"
+            android:id="@+id/battery_percent"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_marginTop="12dp"
-            android:gravity="center"
-            android:textAppearance="@android:style/TextAppearance.Material.Medium"/>
+            android:textAppearance="@android:style/TextAppearance.Material.Display1"/>
 
         <TextView
             android:id="@+id/summary1"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_marginTop="12dp"
-            android:gravity="center"
             android:textAppearance="@android:style/TextAppearance.Material.Small"
             android:text="@string/estimated_time_left"/>
 
-        <TextView
-            android:id="@+id/summary2"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="12dp"
-            android:gravity="center"
-            android:textAppearance="@android:style/TextAppearance.Material.Small"
-            android:text="@string/estimated_time_description"/>
-
     </LinearLayout>
 
+    <com.android.settings.fuelgauge.BatteryMeterView
+        android:id="@+id/battery_header_icon"
+        android:layout_width="@dimen/battery_meter_width"
+        android:layout_height="@dimen/battery_meter_height"
+        android:layout_gravity="end"
+        android:layout_marginEnd="24dp"/>
+
 </LinearLayout>
\ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 6578374..2dbd222 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -765,6 +765,8 @@
     <string name="security_status_title">Security status</string>
     <!-- Summary for Security settings, explaining a few important settings under it [CHAR LIMIT=NONE]-->
     <string name="security_dashboard_summary">Location, fingerprint</string>
+    <!-- Summary for Security settings when fingerprint is not supported [CHAR LIMIT=NONE]-->
+    <string name="security_dashboard_summary_no_fingerprint">Location</string>
     <!-- Fingerprint enrollment and settings --><skip />
     <!-- Title shown for menu item that launches fingerprint settings or enrollment [CHAR LIMIT=22] -->
     <string name="security_settings_fingerprint_preference_title">Fingerprint</string>
@@ -1640,13 +1642,20 @@
     <string name="use_open_wifi_automatically_summary">Automatically connect to high\u2011quality public networks</string>
     <!-- Preference title for option to install certificates -->
     <string name="wifi_install_credentials">Install certificates</string>
-    <!-- Message to describe "Wi-Fi scan always available feature" when Wi-Fi is off. The
-      place-holders "LINK_BEGIN" and "LINK_END" must NOT be translated. They mark a link to bring
-      the user to "scanning settings" screen. -->
+    <!-- Message to describe "Wi-Fi scan always available feature" when Wi-Fi is off and Wi-Fi
+      scanning is on. The place-holders "LINK_BEGIN" and "LINK_END" must NOT be translated. They
+      mark a link to bring the user to "scanning settings" screen. -->
     <string name="wifi_scan_notify_text">To improve location accuracy, system apps and services can
         still scan for Wi\u2011Fi networks. You can change this in
         <xliff:g id="link_begin">LINK_BEGIN</xliff:g>scanning
         settings<xliff:g id="link_end">LINK_END</xliff:g>.</string>
+    <!-- Message to describe "Wi-Fi scan always available feature" when Wi-Fi is off and Wi-Fi
+      scanning is also off. The place-holders "LINK_BEGIN" and "LINK_END" must NOT be translated.
+      They mark a link to bring the user to "scanning settings" screen. -->
+    <string name="wifi_scan_notify_text_scanning_off">To improve location accuracy,
+        turn on Wi-Fi scanning in
+        <xliff:g id="link_begin">LINK_BEGIN</xliff:g>scanning
+        settings<xliff:g id="link_end">LINK_END</xliff:g>.</string>
     <!-- Wifi scan always mode checkbox text -->
     <string name="wifi_scan_notify_remember_choice">Don\u2019t show again</string>
     <!-- Setting title for setting the wifi sleep policy. Do we keep Wi-Fi active when the screen turns off? -->
@@ -3880,13 +3889,6 @@
     <string name="show_password">Show passwords</string>
     <!-- On Security & location settings screen. This is a short summary text describing what "Show passwords" setting does -->
     <string name="show_password_summary">Display characters briefly as you type</string>
-    <!-- Warning message about security implications of enabling an input method, displayed as a dialog
-         message when the user selects to enable an IME. -->
-    <string name="ime_security_warning">This input method may be able to collect
-    all the text you type, including personal data like passwords and credit
-    card numbers.  It comes from the app
-    <xliff:g id="ime_application_name">%1$s</xliff:g>.
-    Use this input method?</string>
     <!-- Warning message about security implications of enabling a spell checker, displayed as a dialog
          message when the user selects to enable a spell checker. -->
     <string name="spellchecker_security_warning">This spell checker may be able to collect
@@ -3898,9 +3900,6 @@
     <string name="spellchecker_quick_settings">Settings</string>
     <!-- Image button description for spell checker language. -->
     <string name="spellchecker_language">Language</string>
-    <!-- Toast that settings for an application is failed to open. -->
-    <string name="failed_to_open_app_settings_toast">Failed to open settings for <xliff:g id="spell_application_name">%1$s</xliff:g></string>
-
     <!-- Title for the 'keyboard and input methods' preference category. [CHAR LIMIT=45] -->
     <string name="keyboard_and_input_methods_category">Keyboard &amp; inputs</string>
     <!-- Title for the 'virtual keyboard' preference sub-screen. [CHAR LIMIT=35] -->
@@ -5656,6 +5655,8 @@
     <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 summary for a VPN app that is set to be always-on. [CHAR LIMIT=40]  -->
+    <string name="vpn_always_on_summary_active">Always-on active</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>
@@ -7398,7 +7399,7 @@
         Allowing <xliff:g id="app_name" example="Settings">%1$s</xliff:g> to always run in the background may reduce battery life.
         \n\nYou can change this later from Settings > Apps &amp; notifications.</string>
     <!-- Summary of power usage for an app [CHAR LIMIT=NONE] -->
-    <string name="battery_summary"><xliff:g id="percentage" example="2">%1$d</xliff:g>%% use since last full charge</string>
+    <string name="battery_summary"><xliff:g id="percentage" example="2">%1$s</xliff:g> use since last full charge</string>
 
     <!-- Title of a group of settings that let you manage settings that affect battery life [CHAR LIMIT=60] -->
     <string name="battery_power_management">Power management</string>
@@ -7434,7 +7435,7 @@
     <!-- Title of one of the choices in a dialog (with title defined in usb_use) that lets the user
          select what the USB connection for this device should be used for. This choice
          is for charging only. -->
-    <string name="usb_use_charging_only">Charging this device</string>
+    <string name="usb_use_charging_only">Charge this device</string>
     <!-- Decription of one of the choices in a dialog (with title defined in usb_use) that lets the
          user select what the USB connection for this device should be used for. This choice
          is for charging only. -->
@@ -7442,15 +7443,15 @@
     <!-- Title of one of the choices in a dialog (with title defined in usb_use) that lets the user
          select what the USB connection for this device should be used for. This choice
          is for powering the other device only. -->
-    <string name="usb_use_power_only">Supplying power</string>
+    <string name="usb_use_power_only">Supply power</string>
     <!-- Decription of one of the choices in a dialog (with title defined in usb_use) that lets the
          user select what the USB connection for this device should be used for. This choice
          is for powering the other device. -->
-    <string name="usb_use_power_only_desc">Supply power to the other connected device</string>
+    <string name="usb_use_power_only_desc">Charge the connected device. Works only with devices that support USB charging.</string>
     <!-- Title of one of the choices in a dialog (with title defined in usb_use) that lets the user
          select what the USB connection for this device should be used for. This choice
          is for transferring files via MTP. -->
-    <string name="usb_use_file_transfers">Transferring files</string>
+    <string name="usb_use_file_transfers">Transfer files</string>
     <!-- Description of one of the choices in a dialog (with title defined in usb_use) that lets the user
          select what the USB connection for this device should be used for. This choice
          is for transferring files via MTP. -->
@@ -7458,7 +7459,7 @@
     <!-- Title of one of the choices in a dialog (with title defined in usb_use) that lets the user
          select what the USB connection for this device should be used for. This choice
          is for transferring photos via PTP. -->
-    <string name="usb_use_photo_transfers">Transferring photos (PTP)</string>
+    <string name="usb_use_photo_transfers">Transfer photos (PTP)</string>
     <!-- Description of one of the choices in a dialog (with title defined in usb_use) that lets the user
          select what the USB connection for this device should be used for. This choice
          is for transferring photos via PTP. -->
@@ -7466,7 +7467,7 @@
     <!-- Title of one of the choices in a dialog (with title defined in usb_use) that lets the user
          select what the USB connection for this device should be used for. This choice
          is for entering MIDI mode. -->
-    <string name="usb_use_MIDI">Using device as MIDI</string>
+    <string name="usb_use_MIDI">Use device as MIDI</string>
     <!-- Description of one of the choices in a dialog (with title defined in usb_use) that lets the user
          select what the USB connection for this device should be used for. This choice
          is for entering MIDI mode. -->
@@ -7479,6 +7480,17 @@
     <!-- Settings item title for USB preference [CHAR LIMIT=35] -->
     <string name="usb_pref">USB</string>
 
+    <!-- Settings item summary for USB preference when set to charging only [CHAR LIMIT=NONE] -->
+    <string name="usb_summary_charging_only">Charging this device</string>
+    <!-- Settings item summary for USB preference when set to powering the other device only [CHAR LIMIT=NONE] -->
+    <string name="usb_summary_power_only">Supplying power</string>
+    <!-- Settings item summary for USB preference when set to transferring files via MTP [CHAR LIMIT=NONE] -->
+    <string name="usb_summary_file_transfers">Transferring files</string>
+    <!-- Settings item summary for USB preference when set to transferring photos via PTP [CHAR LIMIT=NONE] -->
+    <string name="usb_summary_photo_transfers">Transferring photos (PTP)</string>
+    <!-- Settings item summary for USB preference when set to entering MIDI mode [CHAR LIMIT=NONE] -->
+    <string name="usb_summary_MIDI">Using device as MIDI</string>
+
     <!-- Settings item title for background check prefs [CHAR LIMIT=35] -->
     <string name="background_check_pref">Background check</string>
 
@@ -7618,7 +7630,7 @@
     <!-- Link to the apps page for SYSTEM_ALERT_WINDOW settings [CHAR LIMIT=45] -->
     <string name="app_overlay_permission_preference">App display on top permission</string>
     <!-- Description of allowing overlay setting [CHAR LIMIT=NONE] -->
-    <string name="allow_overlay_description">This feature allows an app to display on top of other apps you\u2019re using. It may interfere with your use of those apps or change the way they seem to appear or behave.</string>
+    <string name="allow_overlay_description">Allow this app to display on top of other apps you\u2019re using. It may interfere with your use of those apps or change the way they seem to appear or behave.</string>
 
     <!-- Keyword for VR setting -->
     <string name="keywords_vr_listener">vr virtual reality listener stereo helper service</string>
@@ -8594,8 +8606,11 @@
     <string name="storage_percent_full">full</string>
 
 
-    <!-- Label for button allow user to clear the data for an instant app -->
+    <!-- Label for button allow user to remove the instant app from the device. -->
     <string name="clear_instant_app_data">Clear app</string>
+    <!-- Confirmation message displayed when the user taps Clear app, to ensure they want to remove
+         the instant app from the device. -->
+    <string name="clear_instant_app_confirmation">Do you want to remove this instant app?</string>
 
     <!-- Title of games app storage screen [CHAR LIMIT=30] -->
     <string name="game_storage_settings">Games</string>
diff --git a/res/xml/enterprise_privacy_settings.xml b/res/xml/enterprise_privacy_settings.xml
index 15e4e22..3ea0860 100644
--- a/res/xml/enterprise_privacy_settings.xml
+++ b/res/xml/enterprise_privacy_settings.xml
@@ -100,7 +100,7 @@
                 android:title="@string/enterprise_privacy_wipe_device"
                 settings:multiLine="true"/>
         <com.android.settings.DividerPreference
-                android:key="failed_password_wipe_primary_user"
+                android:key="failed_password_wipe_current_user"
                 android:title="@string/enterprise_privacy_failed_password_wipe_device"
                 settings:multiLine="true"/>
         <com.android.settings.DividerPreference
diff --git a/res/xml/external_sources_details.xml b/res/xml/external_sources_details.xml
index fb443f4..6bc7390 100644
--- a/res/xml/external_sources_details.xml
+++ b/res/xml/external_sources_details.xml
@@ -14,13 +14,17 @@
      limitations under the License.
 -->
 
-<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+        xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
+        android:title="@string/install_other_apps">
 
-    <SwitchPreference
-        android:key="external_sources_settings_switch" />
+    <com.android.settingslib.RestrictedSwitchPreference
+        android:key="external_sources_settings_switch"
+        android:title="@string/external_source_switch_title" />
 
     <Preference
         android:key="external_sources_settings_description"
+        android:summary="@string/install_all_warning"
         android:selectable="false" />
 
 </PreferenceScreen>
diff --git a/res/xml/power_usage_summary.xml b/res/xml/power_usage_summary.xml
index a387813..b486776 100644
--- a/res/xml/power_usage_summary.xml
+++ b/res/xml/power_usage_summary.xml
@@ -26,6 +26,19 @@
         android:layout="@layout/battery_header"/>
 
     <PreferenceCategory
+        android:key="device_usage_list">
+
+        <com.android.settings.fuelgauge.PowerGaugePreference
+            android:key="last_full_charge"
+            android:title="@string/battery_last_full_charge"/>
+
+        <com.android.settings.fuelgauge.PowerGaugePreference
+            android:key="screen_usage"
+            android:title="@string/device_screen_usage"/>
+
+    </PreferenceCategory>
+
+    <PreferenceCategory
         android:key="power_management"
         android:title="@string/battery_power_management">
 
@@ -60,22 +73,4 @@
         android:key="app_list"
         android:title="@string/power_usage_list_summary"/>
 
-    <PreferenceCategory
-        android:key="device_usage_list"
-        android:title="@string/device_usage_list_summary">
-
-        <Preference
-            android:key="screen_usage"
-            android:title="@string/device_screen_usage"/>
-
-        <Preference
-            android:key="screen_consumption"
-            android:title="@string/device_screen_consumption"/>
-
-        <Preference
-            android:key="cellular_network"
-            android:title="@string/device_cellular_network"/>
-
-    </PreferenceCategory>
-
 </PreferenceScreen>
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index 8f645f8..589421f 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -16,7 +16,10 @@
 
 package com.android.settings;
 
+import android.os.Bundle;
+
 import com.android.settings.applications.AppOpsSummary;
+import com.android.settings.enterprise.EnterprisePrivacySettings;
 import com.android.settings.fingerprint.FingerprintEnrollIntroduction;
 import com.android.settings.fingerprint.FingerprintSettings;
 
@@ -154,7 +157,15 @@
     public static class TestingSettingsActivity extends SettingsActivity { /* empty */ }
     public static class WifiAPITestActivity extends SettingsActivity { /* empty */ }
     public static class WifiInfoActivity extends SettingsActivity { /* empty */ }
-    public static class EnterprisePrivacySettingsActivity extends SettingsActivity { /* empty */ }
+    public static class EnterprisePrivacySettingsActivity extends SettingsActivity {
+        @Override
+        public void onCreate(Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+            if (!EnterprisePrivacySettings.isPageEnabled(this)) {
+                finish();
+            }
+        }
+    }
     public static class WebViewAppPickerActivity extends SettingsActivity { /* empty */ }
 
     // Top level categories for new IA
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index 09380e5..015af17 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -60,7 +60,6 @@
 import com.android.settings.dashboard.DashboardFeatureProvider;
 import com.android.settings.dashboard.DashboardSummary;
 import com.android.settings.development.DevelopmentSettings;
-import com.android.settings.enterprise.EnterprisePrivacySettings;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.search.DynamicIndexableContentMonitor;
 import com.android.settings.search2.SearchFeatureProvider;
@@ -827,10 +826,6 @@
                 isAdmin || Utils.isCarrierDemoUser(this));
 
         setTileEnabled(new ComponentName(packageName,
-                        Settings.EnterprisePrivacySettingsActivity.class.getName()),
-                EnterprisePrivacySettings.isPageEnabled(this), isAdmin);
-
-        setTileEnabled(new ComponentName(packageName,
                         Settings.WifiDisplaySettingsActivity.class.getName()),
                 WifiDisplaySettings.isAvailable(this), isAdmin);
 
diff --git a/src/com/android/settings/applications/AppCounter.java b/src/com/android/settings/applications/AppCounter.java
index 09a10e2..8758b14 100644
--- a/src/com/android/settings/applications/AppCounter.java
+++ b/src/com/android/settings/applications/AppCounter.java
@@ -20,6 +20,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
 import android.os.AsyncTask;
+import android.os.UserHandle;
 import android.os.UserManager;
 
 import java.util.List;
@@ -37,7 +38,7 @@
     @Override
     protected Integer doInBackground(Void... params) {
         int count = 0;
-        for (UserInfo user : getUsersToCount()) {
+        for (UserInfo user : mUm.getProfiles(UserHandle.myUserId())) {
             final List<ApplicationInfo> list =
                     mPm.getInstalledApplicationsAsUser(PackageManager.GET_DISABLED_COMPONENTS
                             | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS
@@ -62,6 +63,5 @@
     }
 
     protected abstract void onCountComplete(int num);
-    protected abstract List<UserInfo> getUsersToCount();
     protected abstract boolean includeInCount(ApplicationInfo info);
 }
diff --git a/src/com/android/settings/applications/AppHeaderController.java b/src/com/android/settings/applications/AppHeaderController.java
index 0bc9f8f..b138ede 100644
--- a/src/com/android/settings/applications/AppHeaderController.java
+++ b/src/com/android/settings/applications/AppHeaderController.java
@@ -212,18 +212,22 @@
         ImageView iconView = (ImageView) mAppHeader.findViewById(R.id.app_detail_icon);
         if (iconView != null) {
             iconView.setImageDrawable(mIcon);
+            ImageView badgeView = mAppHeader.findViewById(R.id.app_icon_instant_apps_badge);
+            if (badgeView != null) {
+                badgeView.setVisibility(mIsInstantApp ? View.VISIBLE : View.GONE);
+            }
         }
         setText(R.id.app_detail_title, mLabel);
         setText(R.id.app_detail_summary, mSummary);
-        if (rebindActions) {
-            bindAppHeaderButtons();
-        }
-
         if (mIsInstantApp) {
             setText(R.id.install_type,
                     mAppHeader.getResources().getString(R.string.install_type_instant));
         }
 
+        if (rebindActions) {
+            bindAppHeaderButtons();
+        }
+
         return mAppHeader;
     }
 
diff --git a/src/com/android/settings/applications/ApplicationFeatureProvider.java b/src/com/android/settings/applications/ApplicationFeatureProvider.java
index 1816793..5e986db 100644
--- a/src/com/android/settings/applications/ApplicationFeatureProvider.java
+++ b/src/com/android/settings/applications/ApplicationFeatureProvider.java
@@ -37,11 +37,11 @@
      *  only relevant to instant apps.
      */
     InstantAppButtonsController newInstantAppButtonsController(Fragment fragment,
-            View view);
+            View view, InstantAppButtonsController.ShowDialogDelegate showDialogDelegate);
 
     /**
-     * Calculates the total number of apps installed on the device via policy across all users
-     * and managed profiles.
+     * Calculates the total number of apps installed on the device via policy in the current user
+     * and all its managed profiles.
      *
      * @param async Whether to count asynchronously in a background thread
      * @param callback The callback to invoke with the result
@@ -49,9 +49,8 @@
     void calculateNumberOfPolicyInstalledApps(boolean async, NumberOfAppsCallback callback);
 
     /**
-     * Asynchronously calculates the total number of apps installed on the device, across all users
-     * and managed profiles, that have been granted one or more of the given permissions by the
-     * admin.
+     * Asynchronously calculates the total number of apps installed in the current user and all its
+     * managed profiles that have been granted one or more of the given permissions by the admin.
      *
      * @param permissions Only consider apps that have been granted one or more of these permissions
      *        by the admin, either at run-time or install-time
diff --git a/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java b/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java
index 7cc899b..4171857 100644
--- a/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java
+++ b/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java
@@ -22,7 +22,6 @@
 import android.content.pm.ComponentInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
-import android.content.pm.UserInfo;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -59,14 +58,14 @@
 
     @Override
     public InstantAppButtonsController newInstantAppButtonsController(Fragment fragment,
-            View view) {
-        return new InstantAppButtonsController(mContext, fragment, view);
+            View view, InstantAppButtonsController.ShowDialogDelegate showDialogDelegate) {
+        return new InstantAppButtonsController(mContext, fragment, view, showDialogDelegate);
     }
 
     @Override
     public void calculateNumberOfPolicyInstalledApps(boolean async, NumberOfAppsCallback callback) {
-        final AllUserPolicyInstalledAppCounter counter =
-                new AllUserPolicyInstalledAppCounter(mContext, mPm, callback);
+        final CurrentUserAndManagedProfilePolicyInstalledAppCounter counter =
+                new CurrentUserAndManagedProfilePolicyInstalledAppCounter(mContext, mPm, callback);
         if (async) {
             counter.execute();
         } else {
@@ -77,9 +76,9 @@
     @Override
     public void calculateNumberOfAppsWithAdminGrantedPermissions(String[] permissions,
             boolean async, NumberOfAppsCallback callback) {
-        final AllUserAppWithAdminGrantedPermissionsCounter counter =
-                new AllUserAppWithAdminGrantedPermissionsCounter(mContext, permissions, mPm, mPms,
-                        mDpm, callback);
+        final CurrentUserAndManagedProfileAppWithAdminGrantedPermissionsCounter counter =
+                new CurrentUserAndManagedProfileAppWithAdminGrantedPermissionsCounter(mContext,
+                        permissions, mPm, mPms, mDpm, callback);
         if (async) {
             counter.execute();
         } else {
@@ -120,11 +119,12 @@
         return activities;
     }
 
-    private static class AllUserPolicyInstalledAppCounter extends InstalledAppCounter {
+    private static class CurrentUserAndManagedProfilePolicyInstalledAppCounter
+            extends InstalledAppCounter {
         private NumberOfAppsCallback mCallback;
 
-        AllUserPolicyInstalledAppCounter(Context context, PackageManagerWrapper packageManager,
-                                         NumberOfAppsCallback callback) {
+        CurrentUserAndManagedProfilePolicyInstalledAppCounter(Context context,
+                PackageManagerWrapper packageManager, NumberOfAppsCallback callback) {
             super(context, PackageManager.INSTALL_REASON_POLICY, packageManager);
             mCallback = callback;
         }
@@ -133,19 +133,15 @@
         protected void onCountComplete(int num) {
             mCallback.onNumberOfAppsResult(num);
         }
-
-        @Override
-        protected List<UserInfo> getUsersToCount() {
-            return mUm.getUsers(true /* excludeDying */);
-        }
     }
 
-    private static class AllUserAppWithAdminGrantedPermissionsCounter extends
-            AppWithAdminGrantedPermissionsCounter {
+    private static class CurrentUserAndManagedProfileAppWithAdminGrantedPermissionsCounter
+            extends AppWithAdminGrantedPermissionsCounter {
         private NumberOfAppsCallback mCallback;
 
-        AllUserAppWithAdminGrantedPermissionsCounter(Context context, String[] permissions,
-                PackageManagerWrapper packageManager, IPackageManagerWrapper packageManagerService,
+        CurrentUserAndManagedProfileAppWithAdminGrantedPermissionsCounter(Context context,
+                String[] permissions, PackageManagerWrapper packageManager,
+                IPackageManagerWrapper packageManagerService,
                 DevicePolicyManagerWrapper devicePolicyManager, NumberOfAppsCallback callback) {
             super(context, permissions, packageManager, packageManagerService, devicePolicyManager);
             mCallback = callback;
@@ -155,10 +151,5 @@
         protected void onCountComplete(int num) {
             mCallback.onNumberOfAppsResult(num);
         }
-
-        @Override
-        protected List<UserInfo> getUsersToCount() {
-            return mUm.getUsers(true /* excludeDying */);
-        }
     }
 }
diff --git a/src/com/android/settings/applications/DrawOverlayDetails.java b/src/com/android/settings/applications/DrawOverlayDetails.java
index 39b8919..72564bc 100644
--- a/src/com/android/settings/applications/DrawOverlayDetails.java
+++ b/src/com/android/settings/applications/DrawOverlayDetails.java
@@ -36,6 +36,7 @@
 import com.android.settings.R;
 import com.android.settings.applications.AppStateAppOpsBridge.PermissionState;
 import com.android.settings.applications.AppStateOverlayBridge.OverlayState;
+import com.android.settings.core.TouchOverlayManager;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settingslib.applications.ApplicationsState.AppEntry;
 
@@ -61,6 +62,8 @@
     private Intent mSettingsIntent;
     private OverlayState mOverlayState;
 
+    private TouchOverlayManager mTouchOverlayManager;
+
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -68,6 +71,7 @@
         Context context = getActivity();
         mOverlayBridge = new AppStateOverlayBridge(context, mState, null);
         mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
+        mTouchOverlayManager = new TouchOverlayManager(context);
 
         // find preferences
         addPreferencesFromResource(R.xml.app_ops_permissions_details);
@@ -90,6 +94,20 @@
     }
 
     @Override
+    public void onStart() {
+        super.onStart();
+
+        mTouchOverlayManager.setOverlayAllowed(false);
+    }
+
+    @Override
+    public void onStop() {
+        super.onStop();
+
+        mTouchOverlayManager.setOverlayAllowed(true);
+    }
+
+    @Override
     public void onDestroy() {
         super.onDestroy();
         mOverlayBridge.release();
diff --git a/src/com/android/settings/applications/ExternalSourcesDetails.java b/src/com/android/settings/applications/ExternalSourcesDetails.java
index 6441437..fe51a87 100644
--- a/src/com/android/settings/applications/ExternalSourcesDetails.java
+++ b/src/com/android/settings/applications/ExternalSourcesDetails.java
@@ -24,27 +24,26 @@
 import android.app.AppOpsManager;
 import android.content.Context;
 import android.os.Bundle;
-import android.support.v14.preference.SwitchPreference;
+import android.os.UserHandle;
+import android.os.UserManager;
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.Preference.OnPreferenceChangeListener;
 
 import com.android.settings.R;
 import com.android.settings.Settings;
 import com.android.settings.applications.AppStateInstallAppsBridge.InstallAppsState;
+import com.android.settingslib.RestrictedSwitchPreference;
 import com.android.settingslib.applications.ApplicationsState.AppEntry;
 
 public class ExternalSourcesDetails extends AppInfoWithHeader
         implements OnPreferenceChangeListener {
 
-    private static final String KEY_EXTERNAL_SOURCES_SETTINGS_SWITCH =
-            "external_sources_settings_switch";
-    private static final String KEY_EXTERNAL_SOURCES_SETTINGS_DESC =
-            "external_sources_settings_description";
+    private static final String KEY_EXTERNAL_SOURCE_SWITCH = "external_sources_settings_switch";
 
     private AppStateInstallAppsBridge mAppBridge;
     private AppOpsManager mAppOpsManager;
-    private SwitchPreference mSwitchPref;
-    private Preference mExternalSourcesSettingsDesc;
+    private UserManager mUserManager;
+    private RestrictedSwitchPreference mSwitchPref;
     private InstallAppsState mInstallAppsState;
 
     @Override
@@ -54,15 +53,10 @@
         final Context context = getActivity();
         mAppBridge = new AppStateInstallAppsBridge(context, mState, null);
         mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
+        mUserManager = UserManager.get(context);
 
         addPreferencesFromResource(R.xml.external_sources_details);
-        mSwitchPref = (SwitchPreference) findPreference(KEY_EXTERNAL_SOURCES_SETTINGS_SWITCH);
-        mExternalSourcesSettingsDesc = findPreference(KEY_EXTERNAL_SOURCES_SETTINGS_DESC);
-
-        getPreferenceScreen().setTitle(R.string.install_other_apps);
-        mSwitchPref.setTitle(R.string.external_source_switch_title);
-        mExternalSourcesSettingsDesc.setSummary(R.string.install_all_warning);
-
+        mSwitchPref = (RestrictedSwitchPreference) findPreference(KEY_EXTERNAL_SOURCE_SWITCH);
         mSwitchPref.setOnPreferenceChangeListener(this);
     }
 
@@ -84,6 +78,18 @@
     }
 
     static CharSequence getPreferenceSummary(Context context, AppEntry entry) {
+        final UserManager um = UserManager.get(context);
+        final int userRestrictionSource = um.getUserRestrictionSource(
+                UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES,
+                UserHandle.getUserHandleForUid(entry.info.uid));
+        switch (userRestrictionSource) {
+            case UserManager.RESTRICTION_SOURCE_DEVICE_OWNER:
+            case UserManager.RESTRICTION_SOURCE_PROFILE_OWNER:
+                return context.getString(R.string.disabled_by_admin);
+            case UserManager.RESTRICTION_SOURCE_SYSTEM:
+                return context.getString(R.string.disabled);
+        }
+
         final InstallAppsState appsState;
         if (entry.extraInfo instanceof InstallAppsState) {
             appsState = (InstallAppsState) entry.extraInfo;
@@ -103,6 +109,17 @@
 
     @Override
     protected boolean refreshUi() {
+        if (mUserManager.hasBaseUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES,
+                UserHandle.of(UserHandle.myUserId()))) {
+            mSwitchPref.setChecked(false);
+            mSwitchPref.setSummary(R.string.disabled);
+            mSwitchPref.setEnabled(false);
+            return true;
+        }
+        mSwitchPref.checkRestrictionAndSetDisabled(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES);
+        if (mSwitchPref.isDisabledByAdmin()) {
+            return true;
+        }
         mInstallAppsState = mAppBridge.createInstallAppsStateFor(mPackageName,
                 mPackageInfo.applicationInfo.uid);
         if (!mInstallAppsState.isPotentialAppSource()) {
@@ -110,8 +127,7 @@
             mSwitchPref.setEnabled(false);
             return true;
         }
-        final boolean canInstallApps = mInstallAppsState.canInstallApps();
-        mSwitchPref.setChecked(canInstallApps);
+        mSwitchPref.setChecked(mInstallAppsState.canInstallApps());
         return true;
     }
 
diff --git a/src/com/android/settings/applications/InstalledAppDetails.java b/src/com/android/settings/applications/InstalledAppDetails.java
index 828eca6..9967918 100755
--- a/src/com/android/settings/applications/InstalledAppDetails.java
+++ b/src/com/android/settings/applications/InstalledAppDetails.java
@@ -85,9 +85,11 @@
 import com.android.settings.applications.defaultapps.DefaultHomePreferenceController;
 import com.android.settings.applications.defaultapps.DefaultPhonePreferenceController;
 import com.android.settings.applications.defaultapps.DefaultSmsPreferenceController;
+import com.android.settings.applications.instantapps.InstantAppButtonsController;
 import com.android.settings.datausage.AppDataUsage;
 import com.android.settings.datausage.DataUsageList;
 import com.android.settings.datausage.DataUsageSummary;
+import com.android.settings.fuelgauge.AdvancedPowerUsageDetail;
 import com.android.settings.fuelgauge.BatteryEntry;
 import com.android.settings.fuelgauge.PowerUsageDetail;
 import com.android.settings.notification.AppNotificationSettings;
@@ -182,15 +184,20 @@
     private ChartData mChartData;
     private INetworkStatsSession mStatsSession;
 
-    private Preference mBatteryPreference;
-
-    private BatteryStatsHelper mBatteryHelper;
-    private BatterySipper mSipper;
+    @VisibleForTesting
+    Preference mBatteryPreference;
+    @VisibleForTesting
+    BatterySipper mSipper;
+    @VisibleForTesting
+    BatteryStatsHelper mBatteryHelper;
 
     protected ProcStatsData mStatsManager;
     protected ProcStatsPackageEntry mStats;
 
+    private InstantAppButtonsController mInstantAppButtonsController;
+
     private AppStorageStats mLastResult;
+    private String mBatteryPercent;
 
     private boolean handleDisableable(Button button) {
         boolean disableable = false;
@@ -546,13 +553,16 @@
         final View appSnippet = mHeader.findViewById(R.id.app_snippet);
         mState.ensureIcon(mAppEntry);
         final Activity activity = getActivity();
+        final boolean isInstantApp = AppUtils.isInstant(mPackageInfo.applicationInfo);
+        final CharSequence summary =
+                isInstantApp ? null : getString(Utils.getInstallationStatus(mAppEntry.info));
         FeatureFactory.getFactory(activity)
             .getApplicationFeatureProvider(activity)
             .newAppHeaderController(this, appSnippet)
             .setLabel(mAppEntry)
             .setIcon(mAppEntry)
-            .setSummary(getString(Utils.getInstallationStatus(mAppEntry.info)))
-            .setIsInstantApp(AppUtils.isInstant(mPackageInfo.applicationInfo))
+            .setSummary(summary)
+            .setIsInstantApp(isInstantApp)
             .done(false /* rebindActions */);
         mVersionPreference.setSummary(getString(R.string.version_text, pkgInfo.versionName));
     }
@@ -680,7 +690,8 @@
                     BatteryStats.STATS_SINCE_CHARGED);
             final int percentOfMax = (int) ((mSipper.totalPowerMah)
                     / mBatteryHelper.getTotalPower() * dischargeAmount + .5f);
-            mBatteryPreference.setSummary(getString(R.string.battery_summary, percentOfMax));
+            mBatteryPercent = Utils.formatPercentage(percentOfMax);
+            mBatteryPreference.setSummary(getString(R.string.battery_summary, mBatteryPercent));
         } else {
             mBatteryPreference.setEnabled(false);
             mBatteryPreference.setSummary(getString(R.string.no_battery_summary));
@@ -712,7 +723,7 @@
                     ? R.string.storage_type_external
                     : R.string.storage_type_internal);
             return context.getString(R.string.storage_summary_format,
-                    getSize(context, stats), storageType);
+                    getSize(context, stats), storageType.toString().toLowerCase());
         }
     }
 
@@ -768,6 +779,9 @@
                         .setNegativeButton(R.string.dlg_cancel, null)
                         .create();
         }
+        if (mInstantAppButtonsController != null) {
+            return mInstantAppButtonsController.createDialog(id);
+        }
         return null;
     }
 
@@ -951,9 +965,9 @@
         } else if (preference == mDataPreference) {
             startAppInfoFragment(AppDataUsage.class, getString(R.string.app_data_usage));
         } else if (preference == mBatteryPreference) {
-            BatteryEntry entry = new BatteryEntry(getActivity(), null, mUserManager, mSipper);
-            PowerUsageDetail.startBatteryDetailPage((SettingsActivity) getActivity(), this,
-                    mBatteryHelper, BatteryStats.STATS_SINCE_CHARGED, entry, true, false);
+            BatteryEntry entry = new BatteryEntry(getContext(), null, mUserManager, mSipper);
+            AdvancedPowerUsageDetail.startBatteryDetailPage((SettingsActivity) getActivity(), this,
+                    mBatteryHelper, BatteryStats.STATS_SINCE_CHARGED, entry, mBatteryPercent);
         } else {
             return false;
         }
@@ -1117,10 +1131,11 @@
         if (AppUtils.isInstant(mPackageInfo.applicationInfo)) {
             LayoutPreference buttons = (LayoutPreference) findPreference(KEY_INSTANT_APP_BUTTONS);
             final Activity activity = getActivity();
-            FeatureFactory.getFactory(activity)
+            mInstantAppButtonsController = FeatureFactory.getFactory(activity)
                     .getApplicationFeatureProvider(activity)
                     .newInstantAppButtonsController(this,
-                            buttons.findViewById(R.id.instant_app_button_container))
+                            buttons.findViewById(R.id.instant_app_button_container),
+                            id -> showDialogInner(id, 0))
                     .setPackageName(mPackageName)
                     .show();
         }
diff --git a/src/com/android/settings/applications/ManageApplications.java b/src/com/android/settings/applications/ManageApplications.java
index f83dfeb..229e294 100644
--- a/src/com/android/settings/applications/ManageApplications.java
+++ b/src/com/android/settings/applications/ManageApplications.java
@@ -23,7 +23,6 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageItemInfo;
 import android.content.pm.PackageManager;
-import android.content.pm.UserInfo;
 import android.icu.text.AlphabeticIndex;
 import android.os.Bundle;
 import android.os.Environment;
@@ -34,6 +33,7 @@
 import android.preference.PreferenceFrameLayout;
 import android.support.annotation.VisibleForTesting;
 import android.text.TextUtils;
+import android.util.ArraySet;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.Menu;
@@ -87,10 +87,12 @@
 import com.android.settingslib.applications.StorageStatsSource;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
 import java.util.Locale;
+import java.util.Set;
 
 /**
  * Activity to pick an application that will be used to display installation information and
@@ -254,6 +256,12 @@
     public static final int LIST_TYPE_MANAGE_SOURCES = 8;
     public static final int LIST_TYPE_GAMES = 9;
 
+
+    // List types that should show instant apps.
+    public static final Set<Integer> LIST_TYPES_WITH_INSTANT = new ArraySet<>(Arrays.asList(
+                    LIST_TYPE_MAIN,
+                    LIST_TYPE_STORAGE));
+
     private View mRootView;
 
     private View mSpinnerHeader;
@@ -702,7 +710,9 @@
     }
 
     public void setHasInstant(boolean haveInstantApps) {
-        mFilterAdapter.setFilterEnabled(FILTER_APPS_INSTANT, haveInstantApps);
+        if (LIST_TYPES_WITH_INSTANT.contains(mListType)) {
+            mFilterAdapter.setFilterEnabled(FILTER_APPS_INSTANT, haveInstantApps);
+        }
     }
 
     static class FilterSpinnerAdapter extends ArrayAdapter<CharSequence> {
@@ -957,8 +967,13 @@
                 filterObj = mOverrideFilter;
             }
             if (!mManageApplications.mShowSystem) {
-                filterObj = new CompoundFilter(filterObj,
-                        ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER);
+                if (LIST_TYPES_WITH_INSTANT.contains(mManageApplications.mListType)) {
+                    filterObj = new CompoundFilter(filterObj,
+                            ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER_AND_INSTANT);
+                } else {
+                    filterObj = new CompoundFilter(filterObj,
+                            ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER);
+                }
             }
             switch (mLastSortMode) {
                 case R.id.sort_order_size:
@@ -1404,11 +1419,6 @@
                         mLoader.setSummary(SummaryProvider.this,
                                 mContext.getString(R.string.apps_summary, num));
                     }
-
-                    @Override
-                    protected List<UserInfo> getUsersToCount() {
-                         return mUm.getProfiles(UserHandle.myUserId());
-                    }
                 }.execute();
             }
         }
diff --git a/src/com/android/settings/applications/NotificationApps.java b/src/com/android/settings/applications/NotificationApps.java
index 7aaa36e..c54363a 100644
--- a/src/com/android/settings/applications/NotificationApps.java
+++ b/src/com/android/settings/applications/NotificationApps.java
@@ -18,16 +18,11 @@
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
-import android.content.pm.UserInfo;
-import android.os.UserHandle;
-import android.os.UserManager;
 
 import com.android.settings.R;
 import com.android.settings.dashboard.SummaryLoader;
 import com.android.settings.notification.NotificationBackend;
 
-import java.util.List;
-
 /**
  * Extension of ManageApplications with no changes other than having its own
  * SummaryProvider.
@@ -57,11 +52,6 @@
                     }
 
                     @Override
-                    protected List<UserInfo> getUsersToCount() {
-                         return mUm.getProfiles(UserHandle.myUserId());
-                    }
-
-                    @Override
                     protected boolean includeInCount(ApplicationInfo info) {
                         return mNotificationBackend.getNotificationsBanned(info.packageName,
                                 info.uid);
diff --git a/src/com/android/settings/applications/PackageManagerWrapper.java b/src/com/android/settings/applications/PackageManagerWrapper.java
index 2be92ed..8dae417 100644
--- a/src/com/android/settings/applications/PackageManagerWrapper.java
+++ b/src/com/android/settings/applications/PackageManagerWrapper.java
@@ -20,6 +20,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageDeleteObserver;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.os.UserHandle;
@@ -98,4 +99,10 @@
      */
     void replacePreferredActivity(IntentFilter homeFilter, int matchCategoryEmpty,
             ComponentName[] componentNames, ComponentName component);
+
+    /**
+     * Calls {@code PackageManager.deletePackageAsUser}
+     */
+    void deletePackageAsUser(String packageName, IPackageDeleteObserver observer, int flags,
+            int userId);
 }
diff --git a/src/com/android/settings/applications/PackageManagerWrapperImpl.java b/src/com/android/settings/applications/PackageManagerWrapperImpl.java
index 698c14c..a0d824f 100644
--- a/src/com/android/settings/applications/PackageManagerWrapperImpl.java
+++ b/src/com/android/settings/applications/PackageManagerWrapperImpl.java
@@ -20,6 +20,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageDeleteObserver;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.os.UserHandle;
@@ -90,4 +91,10 @@
             ComponentName[] componentNames, ComponentName component) {
         mPm.replacePreferredActivity(homeFilter, matchCategoryEmpty, componentNames, component);
     }
+
+    @Override
+    public void deletePackageAsUser(String packageName, IPackageDeleteObserver observer, int flags,
+            int userId) {
+        mPm.deletePackageAsUser(packageName, observer, flags, userId);
+    }
 }
diff --git a/src/com/android/settings/applications/defaultapps/DefaultAutofillPicker.java b/src/com/android/settings/applications/defaultapps/DefaultAutofillPicker.java
index ce9344f..d943de7 100644
--- a/src/com/android/settings/applications/defaultapps/DefaultAutofillPicker.java
+++ b/src/com/android/settings/applications/defaultapps/DefaultAutofillPicker.java
@@ -22,7 +22,6 @@
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.provider.Settings;
-import android.service.autofill.AutoFillService;
 import android.service.autofill.AutofillService;
 import android.service.autofill.AutofillServiceInfo;
 import android.text.TextUtils;
@@ -36,8 +35,6 @@
 public class DefaultAutofillPicker extends DefaultAppPickerFragment {
 
     static final String SETTING = Settings.Secure.AUTOFILL_SERVICE;
-    // TODO(b/35956626): remove once clients migrated
-    static final Intent OLD_AUTO_FILL_PROBE = new Intent(AutoFillService.OLD_SERVICE_INTERFACE);
     static final Intent AUTOFILL_PROBE = new Intent(AutofillService.SERVICE_INTERFACE);
 
     @Override
@@ -59,12 +56,6 @@
             candidates.add(new DefaultAppInfo(mPm, mUserId, new ComponentName(
                     info.serviceInfo.packageName, info.serviceInfo.name)));
         }
-        final List<ResolveInfo> oldResolveInfos = mPm.getPackageManager()
-                .queryIntentServices(OLD_AUTO_FILL_PROBE, PackageManager.GET_META_DATA);
-        for (ResolveInfo info : oldResolveInfos) {
-            candidates.add(new DefaultAppInfo(mPm, mUserId, new ComponentName(
-                    info.serviceInfo.packageName, info.serviceInfo.name)));
-        }
         return candidates;
     }
 
@@ -122,24 +113,6 @@
                 }
             }
 
-            final List<ResolveInfo> oldResolveInfos = mPackageManager.queryIntentServices(
-                    OLD_AUTO_FILL_PROBE, PackageManager.GET_META_DATA);
-
-            for (ResolveInfo resolveInfo : oldResolveInfos) {
-                final ServiceInfo serviceInfo = resolveInfo.serviceInfo;
-                final String flattenKey = new ComponentName(
-                        serviceInfo.packageName, serviceInfo.name).flattenToString();
-                if (TextUtils.equals(mSelectedKey, flattenKey)) {
-                    final String settingsActivity = new AutofillServiceInfo(
-                            mPackageManager, serviceInfo)
-                            .getSettingsActivity();
-                    if (TextUtils.isEmpty(settingsActivity)) {
-                        return null;
-                    }
-                    return new Intent(Intent.ACTION_MAIN).setComponent(
-                            new ComponentName(serviceInfo.packageName, settingsActivity));
-                }
-            }
             return null;
         }
     }
diff --git a/src/com/android/settings/applications/instantapps/InstantAppButtonsController.java b/src/com/android/settings/applications/instantapps/InstantAppButtonsController.java
index aa7c418..16956df 100644
--- a/src/com/android/settings/applications/instantapps/InstantAppButtonsController.java
+++ b/src/com/android/settings/applications/instantapps/InstantAppButtonsController.java
@@ -16,31 +16,53 @@
 
 package com.android.settings.applications.instantapps;
 
+import android.app.AlertDialog;
+import android.app.Fragment;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.UserHandle;
+import android.view.View;
+import android.widget.Button;
+
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settings.R;
 import com.android.settings.applications.AppStoreUtil;
+import com.android.settings.applications.PackageManagerWrapper;
+import com.android.settings.applications.PackageManagerWrapperImpl;
 import com.android.settings.overlay.FeatureFactory;
 
-import android.app.Fragment;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.Button;
-
 /** Encapsulates a container for buttons relevant to instant apps */
-public class InstantAppButtonsController {
+public class InstantAppButtonsController implements DialogInterface.OnClickListener {
+
+    public interface ShowDialogDelegate {
+        /**
+         * Delegate that should be called when this controller wants to show a dialog.
+         */
+        void showDialog(int id);
+    }
 
     private final Context mContext;
     private final Fragment mFragment;
     private final View mView;
+    private final PackageManagerWrapper mPackageManagerWrapper;
+    private final ShowDialogDelegate mShowDialogDelegate;
     private String mPackageName;
 
-    public InstantAppButtonsController(Context context, Fragment fragment, View view) {
+    public static final int DLG_BASE = 0x5032;
+    public static final int DLG_CLEAR_APP = DLG_BASE + 1;
+
+    public InstantAppButtonsController(
+            Context context,
+            Fragment fragment,
+            View view,
+            ShowDialogDelegate showDialogDelegate) {
       mContext = context;
       mFragment = fragment;
       mView = view;
+      mShowDialogDelegate = showDialogDelegate;
+      mPackageManagerWrapper = new PackageManagerWrapperImpl(context.getPackageManager());
     }
 
     public InstantAppButtonsController setPackageName(String packageName) {
@@ -51,17 +73,38 @@
     public void bindButtons() {
         Button installButton = (Button)mView.findViewById(R.id.install);
         Button clearDataButton = (Button)mView.findViewById(R.id.clear_data);
-        Intent installIntent = AppStoreUtil.getAppStoreLink(mContext, mPackageName);
-        if (installIntent != null) {
+        Intent appStoreIntent = AppStoreUtil.getAppStoreLink(mContext, mPackageName);
+        if (appStoreIntent != null) {
             installButton.setEnabled(true);
-            installButton.setOnClickListener(v -> mFragment.startActivity(installIntent));
+            installButton.setOnClickListener(v -> mFragment.startActivity(appStoreIntent));
         }
-        clearDataButton.setOnClickListener(v -> {
-            FeatureFactory.getFactory(mContext).getMetricsFeatureProvider().action(mContext,
-                    MetricsEvent.ACTION_SETTINGS_CLEAR_INSTANT_APP, mPackageName);
-            PackageManager pm = mContext.getPackageManager();
-            pm.clearApplicationUserData(mPackageName, null);
-        });
+
+        clearDataButton.setOnClickListener(v -> mShowDialogDelegate.showDialog(DLG_CLEAR_APP));
+    }
+
+    public AlertDialog createDialog(int id) {
+        if (id == DLG_CLEAR_APP) {
+            AlertDialog dialog = new AlertDialog.Builder(mFragment.getActivity())
+                    .setPositiveButton(R.string.clear_instant_app_data, this)
+                    .setNegativeButton(R.string.cancel, null)
+                    .setTitle(R.string.clear_instant_app_data)
+                    .setMessage(mContext.getString(R.string.clear_instant_app_confirmation))
+                    .create();
+            return dialog;
+        }
+        return null;
+    }
+
+    public void onClick(DialogInterface dialog, int which) {
+        if (which == DialogInterface.BUTTON_POSITIVE) {
+            FeatureFactory.getFactory(mContext)
+                    .getMetricsFeatureProvider()
+                    .action(mContext,
+                            MetricsEvent.ACTION_SETTINGS_CLEAR_INSTANT_APP,
+                            mPackageName);
+            mPackageManagerWrapper.deletePackageAsUser(
+                    mPackageName, null, 0, UserHandle.myUserId());
+        }
     }
 
     public InstantAppButtonsController show() {
diff --git a/src/com/android/settings/bluetooth/RequestPermissionActivity.java b/src/com/android/settings/bluetooth/RequestPermissionActivity.java
index 20788c9..d2e2060 100644
--- a/src/com/android/settings/bluetooth/RequestPermissionActivity.java
+++ b/src/com/android/settings/bluetooth/RequestPermissionActivity.java
@@ -180,8 +180,8 @@
                 builder.setMessage(message);
             } else {
                 CharSequence message = mAppLabel != null
-                        ? getString(R.string.bluetooth_ask_discovery, mAppLabel)
-                        : getString(R.string.bluetooth_ask_discovery_no_name);
+                        ? getString(R.string.bluetooth_ask_discovery, mAppLabel, mTimeout)
+                        : getString(R.string.bluetooth_ask_discovery_no_name, mTimeout);
                 builder.setMessage(message);
             }
             builder.setPositiveButton(getString(R.string.allow), this);
diff --git a/src/com/android/settings/core/TouchOverlayManager.java b/src/com/android/settings/core/TouchOverlayManager.java
new file mode 100644
index 0000000..f69d1bf
--- /dev/null
+++ b/src/com/android/settings/core/TouchOverlayManager.java
@@ -0,0 +1,40 @@
+/*
+ * 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.core;
+
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.os.Binder;
+import android.os.IBinder;
+
+public class TouchOverlayManager {
+
+    private final Context mContext;
+    private final IBinder mToken = new Binder();
+
+    public TouchOverlayManager(Context context) {
+        mContext = context;
+    }
+
+    public void setOverlayAllowed(boolean allowed) {
+        final AppOpsManager aom = mContext.getSystemService(AppOpsManager.class);
+        if (aom != null) {
+            aom.setUserRestriction(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, !allowed, mToken);
+            aom.setUserRestriction(AppOpsManager.OP_TOAST_WINDOW, !allowed, mToken);
+        }
+    }
+}
diff --git a/src/com/android/settings/enterprise/AlwaysOnVpnPrimaryUserPreferenceController.java b/src/com/android/settings/enterprise/AlwaysOnVpnCurrentUserPreferenceController.java
similarity index 90%
rename from src/com/android/settings/enterprise/AlwaysOnVpnPrimaryUserPreferenceController.java
rename to src/com/android/settings/enterprise/AlwaysOnVpnCurrentUserPreferenceController.java
index e5823fe..e98ece8 100644
--- a/src/com/android/settings/enterprise/AlwaysOnVpnPrimaryUserPreferenceController.java
+++ b/src/com/android/settings/enterprise/AlwaysOnVpnCurrentUserPreferenceController.java
@@ -21,13 +21,13 @@
 import com.android.settings.core.lifecycle.Lifecycle;
 import com.android.settings.overlay.FeatureFactory;
 
-public class AlwaysOnVpnPrimaryUserPreferenceController
+public class AlwaysOnVpnCurrentUserPreferenceController
         extends DynamicAvailabilityPreferenceController {
 
     private static final String KEY_ALWAYS_ON_VPN_PRIMARY_USER = "always_on_vpn_primary_user";
     private final EnterprisePrivacyFeatureProvider mFeatureProvider;
 
-    public AlwaysOnVpnPrimaryUserPreferenceController(Context context, Lifecycle lifecycle) {
+    public AlwaysOnVpnCurrentUserPreferenceController(Context context, Lifecycle lifecycle) {
         super(context, lifecycle);
         mFeatureProvider = FeatureFactory.getFactory(context)
                 .getEnterprisePrivacyFeatureProvider(context);
@@ -42,7 +42,7 @@
 
     @Override
     public boolean isAvailable() {
-        return mFeatureProvider.isAlwaysOnVpnSetInPrimaryUser();
+        return mFeatureProvider.isAlwaysOnVpnSetInCurrentUser();
     }
 
     @Override
diff --git a/src/com/android/settings/enterprise/DevicePolicyManagerWrapper.java b/src/com/android/settings/enterprise/DevicePolicyManagerWrapper.java
index a154a2f..babf90e 100644
--- a/src/com/android/settings/enterprise/DevicePolicyManagerWrapper.java
+++ b/src/com/android/settings/enterprise/DevicePolicyManagerWrapper.java
@@ -52,13 +52,6 @@
     ComponentName getDeviceOwnerComponentOnAnyUser();
 
     /**
-     * Calls {@code DevicePolicyManager.getDeviceOwnerUserId()}.
-     *
-     * @see android.app.admin.DevicePolicyManager#getDeviceOwnerUserId
-     */
-    int getDeviceOwnerUserId();
-
-    /**
      * Calls {@code DevicePolicyManager.getProfileOwnerAsUser()}.
      *
      * @see android.app.admin.DevicePolicyManager#getProfileOwnerAsUser
diff --git a/src/com/android/settings/enterprise/DevicePolicyManagerWrapperImpl.java b/src/com/android/settings/enterprise/DevicePolicyManagerWrapperImpl.java
index 95a154b..7906310 100644
--- a/src/com/android/settings/enterprise/DevicePolicyManagerWrapperImpl.java
+++ b/src/com/android/settings/enterprise/DevicePolicyManagerWrapperImpl.java
@@ -47,11 +47,6 @@
     }
 
     @Override
-    public int getDeviceOwnerUserId() {
-        return mDpm.getDeviceOwnerUserId();
-    }
-
-    @Override
     public @Nullable ComponentName getProfileOwnerAsUser(final int userId) {
         return mDpm.getProfileOwnerAsUser(userId);
     }
diff --git a/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProvider.java b/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProvider.java
index 4ad0f2e..391db83 100644
--- a/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProvider.java
+++ b/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProvider.java
@@ -32,9 +32,9 @@
     boolean isInCompMode();
 
     /**
-     * Returns the name of the organization managing the device via a Device Owner app. If the device
-     * is not managed by a Device Owner app or the name of the managing organization was not set,
-     * returns {@code null}.
+     * Returns the name of the organization managing the device via a Device Owner app. If the
+     * device is not managed by a Device Owner app or the name of the managing organization was not
+     * set, returns {@code null}.
      */
     String getDeviceOwnerOrganizationName();
 
@@ -74,12 +74,13 @@
     boolean isNetworkLoggingEnabled();
 
     /**
-     * Returns whether the Device Owner in the primary user set an always-on VPN.
+     * Returns whether the Device Owner or Profile Owner in the current user set an always-on VPN.
      */
-    boolean isAlwaysOnVpnSetInPrimaryUser();
+    boolean isAlwaysOnVpnSetInCurrentUser();
 
     /**
-     * Returns whether the Profile Owner in the managed profile (if any) set an always-on VPN.
+     * Returns whether the Profile Owner in the current user's managed profile (if any) set an
+     * always-on VPN.
      */
     boolean isAlwaysOnVpnSetInManagedProfile();
 
@@ -89,10 +90,10 @@
     boolean isGlobalHttpProxySet();
 
     /**
-     * Returns the number of failed login attempts that the Device Owner allows before the entire
-     * device is wiped, or zero if no such limit is set.
+     * Returns the number of failed login attempts that the Device Owner or Profile Owner allows
+     * before the current user is wiped, or zero if no such limit is set.
      */
-    int getMaximumFailedPasswordsBeforeWipeInPrimaryUser();
+    int getMaximumFailedPasswordsBeforeWipeInCurrentUser();
 
     /**
      * Returns the number of failed login attempts that the Profile Owner allows before the current
diff --git a/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java b/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java
index 6d038dc..5817cf2 100644
--- a/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java
+++ b/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java
@@ -142,7 +142,7 @@
     }
 
     @Override
-    public boolean isAlwaysOnVpnSetInPrimaryUser() {
+    public boolean isAlwaysOnVpnSetInCurrentUser() {
         return VpnUtils.isAlwaysOnVpnSet(mCm, MY_USER_ID);
     }
 
@@ -159,12 +159,12 @@
     }
 
     @Override
-    public int getMaximumFailedPasswordsBeforeWipeInPrimaryUser() {
-        final ComponentName deviceOwner = mDpm.getDeviceOwnerComponentOnAnyUser();
-        if (deviceOwner == null) {
+    public int getMaximumFailedPasswordsBeforeWipeInCurrentUser() {
+        final ComponentName profileOwner = mDpm.getProfileOwnerAsUser(MY_USER_ID);
+        if (profileOwner == null) {
             return 0;
         }
-        return mDpm.getMaximumFailedPasswordsForWipe(deviceOwner, mDpm.getDeviceOwnerUserId());
+        return mDpm.getMaximumFailedPasswordsForWipe(profileOwner, MY_USER_ID);
     }
 
     @Override
diff --git a/src/com/android/settings/enterprise/EnterprisePrivacySettings.java b/src/com/android/settings/enterprise/EnterprisePrivacySettings.java
index 9649d84..a80dec0 100644
--- a/src/com/android/settings/enterprise/EnterprisePrivacySettings.java
+++ b/src/com/android/settings/enterprise/EnterprisePrivacySettings.java
@@ -70,11 +70,11 @@
         controllers.add(new AdminGrantedCameraPermissionPreferenceController(context, lifecycle,
                 async));
         controllers.add(new EnterpriseSetDefaultAppsPreferenceController(context, lifecycle));
-        controllers.add(new AlwaysOnVpnPrimaryUserPreferenceController(context, lifecycle));
+        controllers.add(new AlwaysOnVpnCurrentUserPreferenceController(context, lifecycle));
         controllers.add(new AlwaysOnVpnManagedProfilePreferenceController(context, lifecycle));
         controllers.add(new GlobalHttpProxyPreferenceController(context, lifecycle));
         controllers.add(new CaCertsPreferenceController(context, lifecycle));
-        controllers.add(new FailedPasswordWipePrimaryUserPreferenceController(context, lifecycle));
+        controllers.add(new FailedPasswordWipeCurrentUserPreferenceController(context, lifecycle));
         controllers.add(new FailedPasswordWipeManagedProfilePreferenceController(context,
                 lifecycle));
         controllers.add(new ImePreferenceController(context, lifecycle));
diff --git a/src/com/android/settings/enterprise/FailedPasswordWipePrimaryUserPreferenceController.java b/src/com/android/settings/enterprise/FailedPasswordWipeCurrentUserPreferenceController.java
similarity index 77%
rename from src/com/android/settings/enterprise/FailedPasswordWipePrimaryUserPreferenceController.java
rename to src/com/android/settings/enterprise/FailedPasswordWipeCurrentUserPreferenceController.java
index 2e18f89..d3f9a98 100644
--- a/src/com/android/settings/enterprise/FailedPasswordWipePrimaryUserPreferenceController.java
+++ b/src/com/android/settings/enterprise/FailedPasswordWipeCurrentUserPreferenceController.java
@@ -17,23 +17,23 @@
 
 import com.android.settings.core.lifecycle.Lifecycle;
 
-public class FailedPasswordWipePrimaryUserPreferenceController
+public class FailedPasswordWipeCurrentUserPreferenceController
         extends FailedPasswordWipePreferenceControllerBase {
 
-    private static final String KEY_FAILED_PASSWORD_WIPE_PRIMARY_USER
-            = "failed_password_wipe_primary_user";
+    private static final String KEY_FAILED_PASSWORD_WIPE_CURRENT_USER
+            = "failed_password_wipe_current_user";
 
-    public FailedPasswordWipePrimaryUserPreferenceController(Context context, Lifecycle lifecycle) {
+    public FailedPasswordWipeCurrentUserPreferenceController(Context context, Lifecycle lifecycle) {
         super(context, lifecycle);
     }
 
     @Override
     protected int getMaximumFailedPasswordsBeforeWipe() {
-        return mFeatureProvider.getMaximumFailedPasswordsBeforeWipeInPrimaryUser();
+        return mFeatureProvider.getMaximumFailedPasswordsBeforeWipeInCurrentUser();
     }
 
     @Override
     public String getPreferenceKey() {
-        return KEY_FAILED_PASSWORD_WIPE_PRIMARY_USER;
+        return KEY_FAILED_PASSWORD_WIPE_CURRENT_USER;
     }
 }
diff --git a/src/com/android/settings/fuelgauge/BatteryMeterView.java b/src/com/android/settings/fuelgauge/BatteryMeterView.java
index 9127782..dcbf472 100644
--- a/src/com/android/settings/fuelgauge/BatteryMeterView.java
+++ b/src/com/android/settings/fuelgauge/BatteryMeterView.java
@@ -46,7 +46,7 @@
 
         mDrawable = new BatteryMeterDrawable(context, frameColor);
         mDrawable.setColorFilter(new PorterDuffColorFilter(tintColor, PorterDuff.Mode.SRC_IN));
-        mDrawable.setShowPercent(true);
+        mDrawable.setShowPercent(false);
         setImageDrawable(mDrawable);
     }
 
diff --git a/src/com/android/settings/fuelgauge/PowerGaugePreference.java b/src/com/android/settings/fuelgauge/PowerGaugePreference.java
index d4f2dd2..bdadf4c 100644
--- a/src/com/android/settings/fuelgauge/PowerGaugePreference.java
+++ b/src/com/android/settings/fuelgauge/PowerGaugePreference.java
@@ -29,8 +29,11 @@
 import com.android.settings.Utils;
 
 /**
- * Custom preference for displaying power consumption as a bar and an icon on
+ * Custom preference for displaying battery usage info as a bar and an icon on
  * the left for the subsystem/app type.
+ *
+ * The battery usage info could be usage percentage or usage time. The preference
+ * won't show any icon if it is null.
  */
 public class PowerGaugePreference extends TintablePreference {
     private final int mIconSize;
@@ -41,7 +44,20 @@
 
     public PowerGaugePreference(Context context, Drawable icon, CharSequence contentDescription,
             BatteryEntry info) {
-        super(context, null);
+        this(context, null, icon, contentDescription, info);
+    }
+
+    public PowerGaugePreference(Context context) {
+        this(context, null, null, null, null);
+    }
+
+    public PowerGaugePreference(Context context, AttributeSet attrs) {
+        this(context, attrs, null, null, null);
+    }
+
+    private PowerGaugePreference(Context context, AttributeSet attrs, Drawable icon,
+            CharSequence contentDescription, BatteryEntry info) {
+        super(context, attrs);
         setIcon(icon != null ? icon : new ColorDrawable(0));
         setWidgetLayoutResource(R.layout.preference_widget_summary);
         mInfo = info;
@@ -49,10 +65,6 @@
         mIconSize = context.getResources().getDimensionPixelSize(R.dimen.app_icon_size);
     }
 
-    public PowerGaugePreference(Context context) {
-        this(context, null, null, null);
-    }
-
     public void setContentDescription(String name) {
         mContentDescription = name;
         notifyChanged();
@@ -67,6 +79,11 @@
         return mProgress.toString();
     }
 
+    public void setSubtitle(String subtitle) {
+        mProgress = subtitle;
+        notifyChanged();
+    }
+
     BatteryEntry getInfo() {
         return mInfo;
     }
diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
index 96141f9..2c1fd78 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
@@ -16,7 +16,6 @@
 
 package com.android.settings.fuelgauge;
 
-import android.annotation.StringRes;
 import android.app.Activity;
 import android.content.Context;
 import android.graphics.drawable.Drawable;
@@ -26,6 +25,7 @@
 import android.os.Handler;
 import android.os.Message;
 import android.os.Process;
+import android.os.SystemClock;
 import android.os.UserHandle;
 import android.provider.SearchIndexableResource;
 import android.support.annotation.VisibleForTesting;
@@ -39,7 +39,6 @@
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
-import android.view.View;
 import android.widget.TextView;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -60,6 +59,7 @@
 import com.android.settings.display.TimeoutPreferenceController;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.widget.FooterPreferenceMixin;
 import com.android.settingslib.BatteryInfo;
 
 import java.util.ArrayList;
@@ -87,8 +87,7 @@
     private static final int SECONDS_IN_HOUR = 60 * 60;
 
     private static final String KEY_SCREEN_USAGE = "screen_usage";
-    private static final String KEY_SCREEN_CONSUMPTION = "screen_consumption";
-    private static final String KEY_CELLULAR_NETWORK = "cellular_network";
+    private static final String KEY_TIME_SINCE_LAST_FULL_CHARGE = "last_full_charge";
 
 
     private static final int MENU_STATS_TYPE = Menu.FIRST;
@@ -100,14 +99,15 @@
     static final int MENU_TOGGLE_APPS = Menu.FIRST + 5;
     private static final int MENU_HELP = Menu.FIRST + 6;
 
+    private final FooterPreferenceMixin mFooterPreferenceMixin =
+            new FooterPreferenceMixin(this, getLifecycle());
+
     @VisibleForTesting
     boolean mShowAllApps = false;
     @VisibleForTesting
-    Preference mScreenUsagePref;
+    PowerGaugePreference mScreenUsagePref;
     @VisibleForTesting
-    Preference mScreenConsumptionPref;
-    @VisibleForTesting
-    Preference mCellularNetworkPref;
+    PowerGaugePreference mLastFullChargePref;
     @VisibleForTesting
     PowerUsageFeatureProvider mPowerFeatureProvider;
 
@@ -122,9 +122,10 @@
 
         mBatteryLayoutPref = (LayoutPreference) findPreference(KEY_BATTERY_HEADER);
         mAppListGroup = (PreferenceGroup) findPreference(KEY_APP_LIST);
-        mScreenUsagePref = findPreference(KEY_SCREEN_USAGE);
-        mScreenConsumptionPref = findPreference(KEY_SCREEN_CONSUMPTION);
-        mCellularNetworkPref = findPreference(KEY_CELLULAR_NETWORK);
+        mScreenUsagePref = (PowerGaugePreference) findPreference(KEY_SCREEN_USAGE);
+        mLastFullChargePref = (PowerGaugePreference) findPreference(
+                KEY_TIME_SINCE_LAST_FULL_CHARGE);
+        mFooterPreferenceMixin.createFooterPreference().setTitle(R.string.battery_footer_summary);
 
         initFeatureProvider();
     }
@@ -417,8 +418,11 @@
         final int dischargeAmount = USE_FAKE_DATA ? 5000
                 : stats != null ? stats.getDischargeAmount(mStatsType) : 0;
 
-        updateScreenPreference(dischargeAmount);
-        updateCellularPreference(dischargeAmount);
+        final long runningTime = calculateRunningTimeBasedOnStatsType();
+        updateScreenPreference();
+        updateLastFullChargePreference(runningTime);
+        mAppListGroup.setTitle(getString(R.string.power_usage_list_summary,
+                Utils.formatElapsedTime(context, runningTime, false)));
 
         if (averagePower >= MIN_AVERAGE_POWER_THRESHOLD_MILLI_AMP || USE_FAKE_DATA) {
             final List<BatterySipper> usageList = getCoalescedUsageList(
@@ -527,28 +531,27 @@
     }
 
     @VisibleForTesting
-    void updateScreenPreference(final int dischargeAmount) {
+    void updateScreenPreference() {
         final BatterySipper sipper = findBatterySipperByType(
                 mStatsHelper.getUsageList(), DrainType.SCREEN);
         final Context context = getContext();
-        final double totalPowerMah = sipper != null ? sipper.totalPowerMah : 0;
         final long usageTimeMs = sipper != null ? sipper.usageTimeMs : 0;
-        final double percentOfTotal = calculatePercentage(totalPowerMah, dischargeAmount);
 
-        mScreenUsagePref.setSummary(getString(R.string.battery_used_for,
-                Utils.formatElapsedTime(context, usageTimeMs, false)));
-        mScreenConsumptionPref.setSummary(getString(R.string.battery_overall_usage,
-                Utils.formatPercentage(percentOfTotal, true)));
+        mScreenUsagePref.setSubtitle(Utils.formatElapsedTime(context, usageTimeMs, false));
     }
 
     @VisibleForTesting
-    void updateCellularPreference(final int dischargeAmount) {
-        final BatterySipper sipper = findBatterySipperByType(
-                mStatsHelper.getUsageList(), DrainType.CELL);
-        final double totalPowerMah = sipper != null ? sipper.totalPowerMah : 0;
-        final double percentOfTotal = calculatePercentage(totalPowerMah, dischargeAmount);
-        mCellularNetworkPref.setSummary(getString(R.string.battery_overall_usage,
-                Utils.formatPercentage(percentOfTotal, true)));
+    void updateLastFullChargePreference(long timeMs) {
+        mLastFullChargePref.setSubtitle(getString(R.string.power_last_full_charge_summary,
+                Utils.formatElapsedTime(getContext(), timeMs, false)));
+    }
+
+    @VisibleForTesting
+    long calculateRunningTimeBasedOnStatsType() {
+        final long elapsedRealtimeUs = SystemClock.elapsedRealtime() * 1000;
+        // Return the battery time (millisecond) on status mStatsType
+        return mStatsHelper.getStats().computeBatteryRealtime(elapsedRealtimeUs,
+                mStatsType /* STATS_SINCE_CHARGED */) / 1000;
     }
 
     @VisibleForTesting
@@ -559,22 +562,15 @@
         }
         final BatteryMeterView batteryView = (BatteryMeterView) mBatteryLayoutPref
                 .findViewById(R.id.battery_header_icon);
-        final TextView timeText = (TextView) mBatteryLayoutPref.findViewById(R.id.time);
+        final TextView timeText = (TextView) mBatteryLayoutPref.findViewById(R.id.battery_percent);
         final TextView summary1 = (TextView) mBatteryLayoutPref.findViewById(R.id.summary1);
-        final TextView summary2 = (TextView) mBatteryLayoutPref.findViewById(R.id.summary2);
-        final int visible = info.remainingTimeUs != 0 ? View.VISIBLE : View.INVISIBLE;
-        final int summaryResId = info.mDischarging ?
-                R.string.estimated_time_left : R.string.estimated_charging_time_left;
-
-        if (info.remainingTimeUs != 0) {
-            timeText.setText(Utils.formatElapsedTime(context, info.remainingTimeUs / 1000, false));
+        timeText.setText(Utils.formatPercentage(info.mBatteryLevel));
+        if (info.remainingLabel == null ) {
+            summary1.setText(info.statusLabel);
         } else {
-            timeText.setText(info.statusLabel);
+            summary1.setText(info.remainingLabel);
         }
 
-        summary1.setText(summaryResId);
-        summary1.setVisibility(visible);
-        summary2.setVisibility(visible);
         batteryView.setBatteryInfo(info.mBatteryLevel);
     }
 
diff --git a/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragment.java b/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragment.java
index a6df7a3..a7862ae 100644
--- a/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragment.java
+++ b/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragment.java
@@ -43,12 +43,11 @@
 import com.android.settings.search.Indexable;
 import com.android.settings.search.SearchIndexableRaw;
 import com.android.settingslib.inputmethod.InputMethodAndSubtypeUtil;
+import com.android.settingslib.inputmethod.InputMethodPreference;
 import com.android.settingslib.inputmethod.InputMethodSettingValuesWrapper;
 
 import java.text.Collator;
 import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
 import java.util.List;
 
 public final class AvailableVirtualKeyboardFragment extends SettingsPreferenceFragment
@@ -115,7 +114,7 @@
     private static Drawable getInputMethodIcon(@NonNull final PackageManager packageManager,
             @NonNull final InputMethodInfo imi) {
         final ServiceInfo si = imi.getServiceInfo();
-        final ApplicationInfo ai = si.applicationInfo;
+        final ApplicationInfo ai = si != null ? si.applicationInfo : null;
         final String packageName = imi.getPackageName();
         if (si == null || ai == null || packageName == null) {
             return new ColorDrawable(Color.TRANSPARENT);
@@ -151,8 +150,8 @@
         final Context context = getPrefContext();
         final PackageManager packageManager = getActivity().getPackageManager();
         final List<InputMethodInfo> imis = mInputMethodSettingValues.getInputMethodList();
-        final int N = (imis == null ? 0 : imis.size());
-        for (int i = 0; i < N; ++i) {
+        final int numImis = (imis == null ? 0 : imis.size());
+        for (int i = 0; i < numImis; ++i) {
             final InputMethodInfo imi = imis.get(i);
             final boolean isAllowedByOrganization = permittedList == null
                     || permittedList.contains(imi.getPackageName());
@@ -162,14 +161,9 @@
             mInputMethodPreferenceList.add(pref);
         }
         final Collator collator = Collator.getInstance();
-        Collections.sort(mInputMethodPreferenceList, new Comparator<InputMethodPreference>() {
-            @Override
-            public int compare(InputMethodPreference lhs, InputMethodPreference rhs) {
-                return lhs.compareTo(rhs, collator);
-            }
-        });
+        mInputMethodPreferenceList.sort((lhs, rhs) -> lhs.compareTo(rhs, collator));
         getPreferenceScreen().removeAll();
-        for (int i = 0; i < N; ++i) {
+        for (int i = 0; i < numImis; ++i) {
             final InputMethodPreference pref = mInputMethodPreferenceList.get(i);
             pref.setOrder(i);
             getPreferenceScreen().addPreference(pref);
@@ -190,8 +184,6 @@
     static List<SearchIndexableRaw> buildSearchIndexOfInputMethods(final Context context,
             final List<InputMethodInfo> inputMethods, final String screenTitle) {
         final List<SearchIndexableRaw> indexes = new ArrayList<>();
-        final InputMethodManager imm = (InputMethodManager) context.getSystemService(
-                Context.INPUT_METHOD_SERVICE);
         for (int i = 0; i < inputMethods.size(); i++) {
             final InputMethodInfo imi = inputMethods.get(i);
             final ServiceInfo serviceInfo = imi.getServiceInfo();
@@ -207,7 +199,7 @@
         return indexes;
     }
 
-    public static Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+    public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
             new BaseSearchIndexProvider() {
         @Override
         public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) {
diff --git a/src/com/android/settings/inputmethod/InputMethodPreference.java b/src/com/android/settings/inputmethod/InputMethodPreference.java
deleted file mode 100755
index 463a043..0000000
--- a/src/com/android/settings/inputmethod/InputMethodPreference.java
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.inputmethod;
-
-import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
-
-import android.app.AlertDialog;
-import android.content.ActivityNotFoundException;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.os.UserHandle;
-import android.support.v7.preference.Preference;
-import android.support.v7.preference.Preference.OnPreferenceChangeListener;
-import android.support.v7.preference.Preference.OnPreferenceClickListener;
-import android.text.TextUtils;
-import android.util.Log;
-import android.view.inputmethod.InputMethodInfo;
-import android.view.inputmethod.InputMethodManager;
-import android.view.inputmethod.InputMethodSubtype;
-import android.widget.Toast;
-
-import com.android.internal.inputmethod.InputMethodUtils;
-import com.android.settings.R;
-import com.android.settingslib.RestrictedLockUtils;
-import com.android.settingslib.RestrictedSwitchPreference;
-import com.android.settingslib.inputmethod.InputMethodAndSubtypeUtil;
-import com.android.settingslib.inputmethod.InputMethodSettingValuesWrapper;
-
-import java.text.Collator;
-import java.util.List;
-
-/**
- * Input method preference.
- *
- * This preference represents an IME. It is used for two purposes. 1) An instance with a switch
- * is used to enable or disable the IME. 2) An instance without a switch is used to invoke the
- * setting activity of the IME.
- */
-class InputMethodPreference extends RestrictedSwitchPreference implements OnPreferenceClickListener,
-        OnPreferenceChangeListener {
-    private static final String TAG = InputMethodPreference.class.getSimpleName();
-    private static final String EMPTY_TEXT = "";
-    private static final int NO_WIDGET = 0;
-
-    interface OnSavePreferenceListener {
-        /**
-         * Called when this preference needs to be saved its state.
-         *
-         * Note that this preference is non-persistent and needs explicitly to be saved its state.
-         * Because changing one IME state may change other IMEs' state, this is a place to update
-         * other IMEs' state as well.
-         *
-         * @param pref This preference.
-         */
-        public void onSaveInputMethodPreference(InputMethodPreference pref);
-    }
-
-    private final InputMethodInfo mImi;
-    private final boolean mHasPriorityInSorting;
-    private final OnSavePreferenceListener mOnSaveListener;
-    private final InputMethodSettingValuesWrapper mInputMethodSettingValues;
-    private final boolean mIsAllowedByOrganization;
-
-    private AlertDialog mDialog = null;
-
-    /**
-     * A preference entry of an input method.
-     *
-     * @param context The Context this is associated with.
-     * @param imi The {@link InputMethodInfo} of this preference.
-     * @param isImeEnabler true if this preference is the IME enabler that has enable/disable
-     *     switches for all available IMEs, not the list of enabled IMEs.
-     * @param isAllowedByOrganization false if the IME has been disabled by a device or profile
-     *     owner.
-     * @param onSaveListener The listener called when this preference has been changed and needs
-     *     to save the state to shared preference.
-     */
-    InputMethodPreference(final Context context, final InputMethodInfo imi,
-            final boolean isImeEnabler, final boolean isAllowedByOrganization,
-            final OnSavePreferenceListener onSaveListener) {
-        super(context);
-        setPersistent(false);
-        mImi = imi;
-        mIsAllowedByOrganization = isAllowedByOrganization;
-        mOnSaveListener = onSaveListener;
-        if (!isImeEnabler) {
-            // Remove switch widget.
-            setWidgetLayoutResource(NO_WIDGET);
-        }
-        // Disable on/off switch texts.
-        setSwitchTextOn(EMPTY_TEXT);
-        setSwitchTextOff(EMPTY_TEXT);
-        setKey(imi.getId());
-        setTitle(imi.loadLabel(context.getPackageManager()));
-        final String settingsActivity = imi.getSettingsActivity();
-        if (TextUtils.isEmpty(settingsActivity)) {
-            setIntent(null);
-        } else {
-            // Set an intent to invoke settings activity of an input method.
-            final Intent intent = new Intent(Intent.ACTION_MAIN);
-            intent.setClassName(imi.getPackageName(), settingsActivity);
-            setIntent(intent);
-        }
-        mInputMethodSettingValues = InputMethodSettingValuesWrapper.getInstance(context);
-        mHasPriorityInSorting = InputMethodUtils.isSystemIme(imi)
-                && mInputMethodSettingValues.isValidSystemNonAuxAsciiCapableIme(imi, context);
-        setOnPreferenceClickListener(this);
-        setOnPreferenceChangeListener(this);
-    }
-
-    public InputMethodInfo getInputMethodInfo() {
-        return mImi;
-    }
-
-    private boolean isImeEnabler() {
-        // If this {@link SwitchPreference} doesn't have a widget layout, we explicitly hide the
-        // switch widget at constructor.
-        return getWidgetLayoutResource() != NO_WIDGET;
-    }
-
-    @Override
-    public boolean onPreferenceChange(final Preference preference, final Object newValue) {
-        // Always returns false to prevent default behavior.
-        // See {@link TwoStatePreference#onClick()}.
-        if (!isImeEnabler()) {
-            // Prevent disabling an IME because this preference is for invoking a settings activity.
-            return false;
-        }
-        if (isChecked()) {
-            // Disable this IME.
-            setCheckedInternal(false);
-            return false;
-        }
-        if (InputMethodUtils.isSystemIme(mImi)) {
-            // Enable a system IME. No need to show a security warning dialog,
-            // but we might need to prompt if it's not Direct Boot aware.
-            if (mImi.getServiceInfo().directBootAware) {
-                setCheckedInternal(true);
-            } else {
-                showDirectBootWarnDialog();
-            }
-        } else {
-            // Once security is confirmed, we might prompt if the IME isn't
-            // Direct Boot aware.
-            showSecurityWarnDialog();
-        }
-        return false;
-    }
-
-    @Override
-    public boolean onPreferenceClick(final Preference preference) {
-        // Always returns true to prevent invoking an intent without catching exceptions.
-        // See {@link Preference#performClick(PreferenceScreen)}/
-        if (isImeEnabler()) {
-            // Prevent invoking a settings activity because this preference is for enabling and
-            // disabling an input method.
-            return true;
-        }
-        final Context context = getContext();
-        try {
-            final Intent intent = getIntent();
-            if (intent != null) {
-                // Invoke a settings activity of an input method.
-                context.startActivity(intent);
-            }
-        } catch (final ActivityNotFoundException e) {
-            Log.d(TAG, "IME's Settings Activity Not Found", e);
-            final String message = context.getString(
-                    R.string.failed_to_open_app_settings_toast,
-                    mImi.loadLabel(context.getPackageManager()));
-            Toast.makeText(context, message, Toast.LENGTH_LONG).show();
-        }
-        return true;
-    }
-
-    void updatePreferenceViews() {
-        final boolean isAlwaysChecked = mInputMethodSettingValues.isAlwaysCheckedIme(
-                mImi, getContext());
-        // When this preference has a switch and an input method should be always enabled,
-        // this preference should be disabled to prevent accidentally disabling an input method.
-        // This preference should also be disabled in case the admin does not allow this input
-        // method.
-        if (isAlwaysChecked && isImeEnabler()) {
-            setDisabledByAdmin(null);
-            setEnabled(false);
-        } else if (!mIsAllowedByOrganization) {
-            EnforcedAdmin admin =
-                    RestrictedLockUtils.checkIfInputMethodDisallowed(getContext(),
-                            mImi.getPackageName(), UserHandle.myUserId());
-            setDisabledByAdmin(admin);
-        } else {
-            setEnabled(true);
-        }
-        setChecked(mInputMethodSettingValues.isEnabledImi(mImi));
-        if (!isDisabledByAdmin()) {
-            setSummary(getSummaryString());
-        }
-    }
-
-    private InputMethodManager getInputMethodManager() {
-        return (InputMethodManager)getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
-    }
-
-    private String getSummaryString() {
-        final InputMethodManager imm = getInputMethodManager();
-        final List<InputMethodSubtype> subtypes = imm.getEnabledInputMethodSubtypeList(mImi, true);
-        return InputMethodAndSubtypeUtil.getSubtypeLocaleNameListAsSentence(
-                subtypes, getContext(), mImi);
-    }
-
-    private void setCheckedInternal(boolean checked) {
-        super.setChecked(checked);
-        mOnSaveListener.onSaveInputMethodPreference(InputMethodPreference.this);
-        notifyChanged();
-    }
-
-    private void showSecurityWarnDialog() {
-        if (mDialog != null && mDialog.isShowing()) {
-            mDialog.dismiss();
-        }
-        final Context context = getContext();
-        final AlertDialog.Builder builder = new AlertDialog.Builder(context);
-        builder.setCancelable(true /* cancelable */);
-        builder.setTitle(android.R.string.dialog_alert_title);
-        final CharSequence label = mImi.getServiceInfo().applicationInfo.loadLabel(
-                context.getPackageManager());
-        builder.setMessage(context.getString(R.string.ime_security_warning, label));
-        builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
-            @Override
-            public void onClick(final DialogInterface dialog, final int which) {
-                // The user confirmed to enable a 3rd party IME, but we might
-                // need to prompt if it's not Direct Boot aware.
-                if (mImi.getServiceInfo().directBootAware) {
-                    setCheckedInternal(true);
-                } else {
-                    showDirectBootWarnDialog();
-                }
-            }
-        });
-        builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
-            @Override
-            public void onClick(final DialogInterface dialog, final int which) {
-                // The user canceled to enable a 3rd party IME.
-                setCheckedInternal(false);
-            }
-        });
-        mDialog = builder.create();
-        mDialog.show();
-    }
-
-    private void showDirectBootWarnDialog() {
-        if (mDialog != null && mDialog.isShowing()) {
-            mDialog.dismiss();
-        }
-        final Context context = getContext();
-        final AlertDialog.Builder builder = new AlertDialog.Builder(context);
-        builder.setCancelable(true /* cancelable */);
-        builder.setMessage(context.getText(R.string.direct_boot_unaware_dialog_message));
-        builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
-            @Override
-            public void onClick(final DialogInterface dialog, final int which) {
-                setCheckedInternal(true);
-            }
-        });
-        builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
-            @Override
-            public void onClick(final DialogInterface dialog, final int which) {
-                setCheckedInternal(false);
-            }
-        });
-        mDialog = builder.create();
-        mDialog.show();
-    }
-
-    int compareTo(final InputMethodPreference rhs, final Collator collator) {
-        if (this == rhs) {
-            return 0;
-        }
-        if (mHasPriorityInSorting == rhs.mHasPriorityInSorting) {
-            final CharSequence t0 = getTitle();
-            final CharSequence t1 = rhs.getTitle();
-            if (TextUtils.isEmpty(t0)) {
-                return 1;
-            }
-            if (TextUtils.isEmpty(t1)) {
-                return -1;
-            }
-            return collator.compare(t0.toString(), t1.toString());
-        }
-        // Prefer always checked system IMEs
-        return mHasPriorityInSorting ? -1 : 1;
-    }
-}
diff --git a/src/com/android/settings/inputmethod/VirtualKeyboardFragment.java b/src/com/android/settings/inputmethod/VirtualKeyboardFragment.java
index c362389..7b7c599 100644
--- a/src/com/android/settings/inputmethod/VirtualKeyboardFragment.java
+++ b/src/com/android/settings/inputmethod/VirtualKeyboardFragment.java
@@ -35,6 +35,7 @@
 import com.android.settings.search.Indexable;
 import com.android.settings.search.SearchIndexableRaw;
 import com.android.settingslib.inputmethod.InputMethodAndSubtypeUtil;
+import com.android.settingslib.inputmethod.InputMethodPreference;
 
 import java.text.Collator;
 import java.util.ArrayList;
@@ -104,12 +105,7 @@
             mInputMethodPreferenceList.add(pref);
         }
         final Collator collator = Collator.getInstance();
-        Collections.sort(mInputMethodPreferenceList, new Comparator<InputMethodPreference>() {
-            @Override
-            public int compare(InputMethodPreference lhs, InputMethodPreference rhs) {
-                return lhs.compareTo(rhs, collator);
-            }
-        });
+        mInputMethodPreferenceList.sort((lhs, rhs) -> lhs.compareTo(rhs, collator));
         getPreferenceScreen().removeAll();
         for (int i = 0; i < N; ++i) {
             final InputMethodPreference pref = mInputMethodPreferenceList.get(i);
diff --git a/src/com/android/settings/users/EditUserPhotoController.java b/src/com/android/settings/users/EditUserPhotoController.java
index 03b959a..c348b4aa 100644
--- a/src/com/android/settings/users/EditUserPhotoController.java
+++ b/src/com/android/settings/users/EditUserPhotoController.java
@@ -240,6 +240,7 @@
 
             @Override
             protected void onPostExecute(Void result) {
+                if (!mFragment.isAdded()) return;
                 cropPhoto();
             }
         }.execute();
diff --git a/src/com/android/settings/vpn2/ManageablePreference.java b/src/com/android/settings/vpn2/ManageablePreference.java
index b45ae45..11da758 100644
--- a/src/com/android/settings/vpn2/ManageablePreference.java
+++ b/src/com/android/settings/vpn2/ManageablePreference.java
@@ -87,7 +87,7 @@
         final String[] states = res.getStringArray(R.array.vpn_states);
         String summary = (mState == STATE_NONE ? "" : states[mState]);
         if (mIsAlwaysOn) {
-            final String alwaysOnString = res.getString(R.string.vpn_always_on_active);
+            final String alwaysOnString = res.getString(R.string.vpn_always_on_summary_active);
             summary = TextUtils.isEmpty(summary) ? alwaysOnString : res.getString(
                     R.string.join_two_unrelated_items, summary, alwaysOnString);
         }
diff --git a/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java b/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java
index b9ffcaf..1a60256 100644
--- a/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java
+++ b/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java
@@ -20,7 +20,9 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.icu.text.Collator;
+import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiManager;
+import android.net.wifi.hotspot2.PasspointConfiguration;
 import android.os.Bundle;
 import android.provider.SearchIndexableResource;
 import android.support.v7.preference.Preference;
@@ -64,6 +66,18 @@
         }
     };
 
+    private final WifiManager.ActionListener mForgetListener = new WifiManager.ActionListener() {
+        @Override
+        public void onSuccess() {
+            initPreferences();
+        }
+
+        @Override
+        public void onFailure(int reason) {
+            initPreferences();
+        }
+    };
+
     private WifiDialog mDialog;
     private WifiManager mWifiManager;
     private AccessPoint mDlgAccessPoint;
@@ -110,8 +124,7 @@
         PreferenceScreen preferenceScreen = getPreferenceScreen();
         final Context context = getPrefContext();
 
-        final List<AccessPoint> accessPoints = WifiTracker.getCurrentAccessPoints(context, true,
-                false, true);
+        final List<AccessPoint> accessPoints = getSavedConfigs(context, mWifiManager);
         Collections.sort(accessPoints, SAVED_NETWORK_COMPARATOR);
         preferenceScreen.removeAll();
 
@@ -129,6 +142,39 @@
         }
     }
 
+    /**
+     * Retrieved the list of saved network configurations from {@link WifiManager}.
+     * Each configuration is represented by {@link AccessPoint}.
+     *
+     * @param context The application context
+     * @param wifiManager An instance of {@link WifiManager}
+     * @return List of {@link AccessPoint}
+     */
+    private static List<AccessPoint> getSavedConfigs(Context context, WifiManager wifiManager) {
+        List<AccessPoint> savedConfigs = new ArrayList<>();
+        List<WifiConfiguration> savedNetworks = wifiManager.getConfiguredNetworks();
+        for (WifiConfiguration network : savedNetworks) {
+            // Configuration for Passpoint network is configured temporary by WifiService for
+            // connection attempt only.  The underlying configuration is saved as Passpoint
+            // configuration, which will be retrieved with WifiManager#getPasspointConfiguration
+            // call below.
+            if (network.isPasspoint()) {
+                continue;
+            }
+            savedConfigs.add(new AccessPoint(context, network));
+        }
+        try {
+            List<PasspointConfiguration> savedPasspointConfigs =
+                    wifiManager.getPasspointConfigurations();
+            for (PasspointConfiguration config : savedPasspointConfigs) {
+                savedConfigs.add(new AccessPoint(context, config));
+            }
+        } catch (UnsupportedOperationException e) {
+            // Passpoint not supported.
+        }
+        return savedConfigs;
+    }
+
     private void showDialog(LongPressAccessPointPreference accessPoint, boolean edit) {
         if (mDialog != null) {
             removeDialog(WifiSettings.WIFI_DIALOG_ID);
@@ -187,9 +233,20 @@
     @Override
     public void onForget(WifiDialog dialog) {
         if (mSelectedAccessPoint != null) {
-            mWifiManager.forget(mSelectedAccessPoint.getConfig().networkId, null);
+            if (mSelectedAccessPoint.isPasspointConfig()) {
+                try {
+                    mWifiManager.removePasspointConfiguration(
+                            mSelectedAccessPoint.getPasspointFqdn());
+                } catch (RuntimeException e) {
+                    Log.e(TAG, "Failed to remove Passpoint configuration for "
+                            + mSelectedAccessPoint.getConfigName());
+                }
+                initPreferences();
+            } else {
+                // mForgetListener will call initPreferences upon completion
+                mWifiManager.forget(mSelectedAccessPoint.getConfig().networkId, mForgetListener);
+            }
             mSelectedAccessPoint = null;
-            initPreferences();
         }
     }
 
@@ -235,8 +292,8 @@
                 result.add(data);
 
                 // Add available Wi-Fi access points
-                final List<AccessPoint> accessPoints = WifiTracker.getCurrentAccessPoints(context,
-                        true, false, true);
+                final List<AccessPoint> accessPoints =
+                        getSavedConfigs(context, context.getSystemService(WifiManager.class));
 
                 final int accessPointsSize = accessPoints.size();
                 for (int i = 0; i < accessPointsSize; ++i){
diff --git a/src/com/android/settings/wifi/WifiConfigController.java b/src/com/android/settings/wifi/WifiConfigController.java
index 460d210..4380cbe 100644
--- a/src/com/android/settings/wifi/WifiConfigController.java
+++ b/src/com/android/settings/wifi/WifiConfigController.java
@@ -217,7 +217,11 @@
 
             mConfigUi.setSubmitButton(res.getString(R.string.wifi_save));
         } else {
-            mConfigUi.setTitle(mAccessPoint.getSsid());
+            if (!mAccessPoint.isPasspointConfig()) {
+                mConfigUi.setTitle(mAccessPoint.getSsid());
+            } else {
+                mConfigUi.setTitle(mAccessPoint.getConfigName());
+            }
 
             ViewGroup group = (ViewGroup) mView.findViewById(R.id.info);
 
@@ -258,7 +262,8 @@
                 }
             }
 
-            if ((!mAccessPoint.isSaved() && !mAccessPoint.isActive())
+            if ((!mAccessPoint.isSaved() && !mAccessPoint.isActive()
+                    && !mAccessPoint.isPasspointConfig())
                     || mMode != WifiConfigUiBase.MODE_VIEW) {
                 showSecurityFields();
                 showIpConfigFields();
@@ -326,7 +331,8 @@
                     addRow(group, R.string.wifi_security, mAccessPoint.getSecurityString(false));
                     mView.findViewById(R.id.ip_fields).setVisibility(View.GONE);
                 }
-                if (mAccessPoint.isSaved() || mAccessPoint.isActive()) {
+                if (mAccessPoint.isSaved() || mAccessPoint.isActive()
+                        || mAccessPoint.isPasspointConfig()) {
                     mConfigUi.setForgetButton(res.getString(R.string.wifi_forget));
                 }
             }
diff --git a/src/com/android/settings/wifi/WifiEnabler.java b/src/com/android/settings/wifi/WifiEnabler.java
index e0e6a1a..abab154 100644
--- a/src/com/android/settings/wifi/WifiEnabler.java
+++ b/src/com/android/settings/wifi/WifiEnabler.java
@@ -57,8 +57,7 @@
         public void onReceive(Context context, Intent intent) {
             String action = intent.getAction();
             if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {
-                handleWifiStateChanged(intent.getIntExtra(
-                        WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN));
+                handleWifiStateChanged(mWifiManager.getWifiState());
             } else if (WifiManager.SUPPLICANT_STATE_CHANGED_ACTION.equals(action)) {
                 if (!mConnected.get()) {
                     handleStateChanged(WifiInfo.getDetailedStateOf((SupplicantState)
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index 20f723c..38f5a43 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -196,7 +196,6 @@
 
         mConnectedAccessPointPreferenceCategory =
                 (PreferenceCategory) findPreference(PREF_KEY_CONNECTED_ACCESS_POINTS);
-
         mAccessPointsPreferenceCategory =
                 (PreferenceCategory) findPreference(PREF_KEY_ACCESS_POINTS);
         mAdditionalSettingsPreferenceCategory =
@@ -204,10 +203,6 @@
         mConfigureWifiSettingsPreference = findPreference(PREF_KEY_CONFIGURE_WIFI_SETTINGS);
         mSavedNetworksPreference = findPreference(PREF_KEY_SAVED_NETWORKS);
 
-        if (isUiRestricted()) {
-            getPreferenceScreen().removePreference(mAdditionalSettingsPreferenceCategory);
-        }
-
         Context prefContext = getPrefContext();
         mAddPreference = new Preference(prefContext);
         mAddPreference.setIcon(R.drawable.ic_menu_add_inset);
@@ -216,6 +211,11 @@
 
         mUserBadgeCache = new AccessPointPreference.UserBadgeCache(getPackageManager());
 
+        if (isUiRestricted()) {
+            getPreferenceScreen().removePreference(mAdditionalSettingsPreferenceCategory);
+            addMessagePreference(R.string.wifi_empty_list_user_restricted);
+        }
+
         mBgThread = new HandlerThread(TAG, Process.THREAD_PRIORITY_BACKGROUND);
         mBgThread.start();
     }
@@ -314,7 +314,7 @@
 
         if (intent.hasExtra(EXTRA_START_CONNECT_SSID)) {
             mOpenSsid = intent.getStringExtra(EXTRA_START_CONNECT_SSID);
-            onAccessPointsChanged();
+            updateAccessPointsDelayed();
         }
     }
 
@@ -516,7 +516,10 @@
             if (mSelectedAccessPoint.isActive()) {
                 return super.onPreferenceTreeClick(preference);
             }
-            /** Bypass dialog and connect to unsecured or previously connected saved networks. */
+            /**
+             * Bypass dialog and connect to unsecured networks, or previously connected saved
+             * networks, or Passpoint provided networks.
+             */
             WifiConfiguration config = mSelectedAccessPoint.getConfig();
             if (mSelectedAccessPoint.getSecurity() == AccessPoint.SECURITY_NONE) {
                 mSelectedAccessPoint.generateOpenNetworkConfig();
@@ -525,6 +528,10 @@
                     && config.getNetworkSelectionStatus() != null
                     && config.getNetworkSelectionStatus().getHasEverConnected()) {
                 connect(config, true /* isSavedNetwork */);
+            } else if (mSelectedAccessPoint.isPasspoint()) {
+                // Access point provided by an installed Passpoint provider, connect using
+                // the associated config.
+                connect(config, true /* isSavedNetwork */);
             } else {
                 showDialog(mSelectedAccessPoint, WifiConfigUiBase.MODE_CONNECT);
             }
@@ -614,53 +621,75 @@
     }
 
     /**
-     * Shows the latest access points available with supplemental information like
-     * the strength of network and the security for it.
+     * Called to indicate the list of AccessPoints has been updated and
+     * getAccessPoints should be called to get the latest information.
      */
     @Override
     public void onAccessPointsChanged() {
+        updateAccessPointsDelayed();
+    }
+
+    /**
+     * Updates access points from {@link WifiManager#getScanResults()}. Adds a delay to have
+     * progress bar displayed before starting to modify APs.
+     */
+    private void updateAccessPointsDelayed() {
         // Safeguard from some delayed event handling
-        if (getActivity() == null) return;
-        final int wifiState = mWifiManager.getWifiState();
+        if (getActivity() != null && !isUiRestricted() && mWifiManager.isWifiEnabled()) {
+            setProgressBarVisible(true);
+            getView().postDelayed(mUpdateAccessPointsRunnable, 300 /* delay milliseconds */);
+        }
+    }
+
+    /** Called when the state of Wifi has changed. */
+    @Override
+    public void onWifiStateChanged(int state) {
         if (isUiRestricted()) {
-            removeConnectedAccessPointPreference();
-            mAccessPointsPreferenceCategory.removeAll();
-            if (!isUiRestrictedByOnlyAdmin()) {
-                if (wifiState == WifiManager.WIFI_AP_STATE_DISABLED) {
-                    setOffMessage();
-                } else {
-                    addMessagePreference(R.string.wifi_empty_list_user_restricted);
-                }
-            }
             return;
         }
 
+        final int wifiState = mWifiManager.getWifiState();
         switch (wifiState) {
             case WifiManager.WIFI_STATE_ENABLED:
-                setProgressBarVisible(true);
-                // Have the progress bar displayed before starting to modify APs
-                getView().postDelayed(mUpdateAccessPointsRunnable, 300 /* delay milliseconds */);
+                updateAccessPointsDelayed();
                 break;
 
             case WifiManager.WIFI_STATE_ENABLING:
                 removeConnectedAccessPointPreference();
                 mAccessPointsPreferenceCategory.removeAll();
+                addMessagePreference(R.string.wifi_starting);
                 setProgressBarVisible(true);
                 break;
 
             case WifiManager.WIFI_STATE_DISABLING:
+                removeConnectedAccessPointPreference();
+                mAccessPointsPreferenceCategory.removeAll();
                 addMessagePreference(R.string.wifi_stopping);
                 break;
 
             case WifiManager.WIFI_STATE_DISABLED:
                 setOffMessage();
-                setConfigureWifiSettingsVisibility();
                 setProgressBarVisible(false);
                 break;
         }
     }
 
+    /**
+     * Called when the connection state of wifi has changed and isConnected
+     * should be called to get the updated state.
+     */
+    @Override
+    public void onConnectedChanged() {
+        updateAccessPointsDelayed();
+        changeNextButtonState(mWifiTracker.isConnected());
+    }
+
+
     private void updateAccessPointPreferences() {
+        // in case state has changed
+        if (!mWifiManager.isWifiEnabled()) {
+            return;
+        }
         // AccessPoints are sorted by the WifiTracker
         final List<AccessPoint> accessPoints = mWifiTracker.getAccessPoints();
 
@@ -796,10 +825,6 @@
     }
 
     private void setConfigureWifiSettingsVisibility() {
-        if (isUiRestricted()) {
-            mAdditionalSettingsPreferenceCategory.removeAll();
-            return;
-        }
         mAdditionalSettingsPreferenceCategory.addPreference(mConfigureWifiSettingsPreference);
         boolean wifiWakeupEnabled = Settings.Global.getInt(
                 getContentResolver(), Settings.Global.WIFI_WAKEUP_ENABLED, 0) == 1;
@@ -818,32 +843,24 @@
     }
 
     private void setOffMessage() {
-        final CharSequence briefText = getText(R.string.wifi_empty_list_wifi_off);
-
+        final CharSequence title = getText(R.string.wifi_empty_list_wifi_off);
         // Don't use WifiManager.isScanAlwaysAvailable() to check the Wi-Fi scanning mode. Instead,
         // read the system settings directly. Because when the device is in Airplane mode, even if
         // Wi-Fi scanning mode is on, WifiManager.isScanAlwaysAvailable() still returns "off".
-        final ContentResolver resolver = getActivity().getContentResolver();
-        final boolean wifiScanningMode = !isUiRestricted() && Settings.Global.getInt(
-                resolver, Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 0) == 1;
-
-        if (!wifiScanningMode) {
-            // Show only the brief text if the user is not allowed to configure scanning settings,
-            // or the scanning mode has been turned off.
-            mStatusMessagePreference.setTitle(briefText);
-        } else {
-            LinkifyUtils.OnClickListener clickListener = new LinkifyUtils.OnClickListener() {
-                @Override
-                public void onClick() {
-                    final SettingsActivity activity = (SettingsActivity) getActivity();
-                    activity.startPreferencePanel(WifiSettings.this,
-                            ScanningSettings.class.getName(),
-                            null, R.string.location_scanning_screen_title, null, null, 0);
-                }
-            };
-            mStatusMessagePreference.setText(
-                    briefText, getText(R.string.wifi_scan_notify_text), clickListener);
-        }
+        final boolean wifiScanningMode = Settings.Global.getInt(getActivity().getContentResolver(),
+                Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 0) == 1;
+        final CharSequence description = wifiScanningMode ? getText(R.string.wifi_scan_notify_text)
+                : getText(R.string.wifi_scan_notify_text_scanning_off);
+        final LinkifyUtils.OnClickListener clickListener = new LinkifyUtils.OnClickListener() {
+            @Override
+            public void onClick() {
+                final SettingsActivity activity = (SettingsActivity) getActivity();
+                activity.startPreferencePanel(WifiSettings.this,
+                        ScanningSettings.class.getName(),
+                        null, R.string.location_scanning_screen_title, null, null, 0);
+            }
+        };
+        mStatusMessagePreference.setText(title, description, clickListener);
         removeConnectedAccessPointPreference();
         mAccessPointsPreferenceCategory.removeAll();
         mAccessPointsPreferenceCategory.addPreference(mStatusMessagePreference);
@@ -858,32 +875,10 @@
 
     protected void setProgressBarVisible(boolean visible) {
         if (mProgressHeader != null) {
-            mProgressHeader.setVisibility(
-                    visible && !isUiRestricted() ? View.VISIBLE : View.INVISIBLE);
+            mProgressHeader.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
         }
     }
 
-    @Override
-    public void onWifiStateChanged(int state) {
-        switch (state) {
-            case WifiManager.WIFI_STATE_ENABLING:
-                addMessagePreference(R.string.wifi_starting);
-                setProgressBarVisible(true);
-                break;
-
-            case WifiManager.WIFI_STATE_DISABLED:
-                setOffMessage();
-                setProgressBarVisible(false);
-                break;
-        }
-    }
-
-    @Override
-    public void onConnectedChanged() {
-        onAccessPointsChanged();
-        changeNextButtonState(mWifiTracker.isConnected());
-    }
-
     /**
      * Renames/replaces "Next" button when appropriate. "Next" button usually exists in
      * Wifi setup screens, not in usual wifi settings screen.
diff --git a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
index 85c0929..92e12b0 100644
--- a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
+++ b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
@@ -106,6 +106,7 @@
         mSignalStr = context.getResources().getStringArray(R.array.wifi_signal);
         mWifiConfig = accessPoint.getConfig();
         mWifiManager = wifiManager;
+        mWifiInfo = wifiManager.getConnectionInfo();
 
         lifecycle.addObserver(this);
     }
@@ -266,15 +267,24 @@
     }
 
     /**
+     * Returns whether the network represented by this preference can be forgotten.
+     */
+    public boolean canForgetNetwork() {
+        return mWifiInfo != null && mWifiInfo.isEphemeral() || mWifiConfig != null;
+    }
+
+    /**
      * 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 */);
+        if (mWifiInfo != null && mWifiInfo.isEphemeral()) {
+            mWifiManager.disableEphemeralNetwork(mWifiInfo.getSSID());
+        } else if (mWifiConfig != null) {
+            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 ade9d6a..7ebde38 100644
--- a/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
+++ b/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
@@ -16,10 +16,8 @@
 package com.android.settings.wifi.details;
 
 import android.content.Context;
-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;
@@ -63,8 +61,9 @@
 
         // Header Title set automatically from launching Preference
 
-        mForgetButton = (Button) ((LayoutPreference) findPreference(KEY_FORGET_BUTTON))
-                .findViewById(R.id.button);
+        LayoutPreference forgetPreference = ((LayoutPreference) findPreference(KEY_FORGET_BUTTON));
+        forgetPreference.setVisible(mWifiDetailPreferenceController.canForgetNetwork());
+        mForgetButton = (Button) forgetPreference.findViewById(R.id.button);
         mForgetButton.setText(R.string.forget);
         mForgetButton.setOnClickListener(view -> forgetNetwork());
     }
@@ -72,7 +71,7 @@
     private void forgetNetwork() {
         mMetricsFeatureProvider.action(getActivity(), MetricsProto.MetricsEvent.ACTION_WIFI_FORGET);
         mWifiDetailPreferenceController.forgetNetwork();
-        mForgetButton.setEnabled(false);
+        getActivity().finish();
     }
 
     @Override
diff --git a/tests/app/src/com/android/settings/wifi/WifiSettingsUiTest.java b/tests/app/src/com/android/settings/wifi/WifiSettingsUiTest.java
new file mode 100644
index 0000000..11a49fc
--- /dev/null
+++ b/tests/app/src/com/android/settings/wifi/WifiSettingsUiTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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.wifi;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.action.ViewActions.click;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
+
+import android.app.Instrumentation;
+import android.content.Context;
+import android.content.Intent;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.settings.R;
+import com.android.settings.Settings.WifiSettingsActivity;
+import com.android.settingslib.wifi.WifiTracker;
+import com.android.settingslib.wifi.WifiTrackerFactory;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidJUnit4.class)
+public class WifiSettingsUiTest {
+
+    // TODO(sghuman): Investigate why resource ids are not resolving correctly in the test apk,
+    // then remove this manual string entry
+    private static final String WIFI_PREFERENCES = "Wi\\u2011Fi preferences";
+
+    @Mock private WifiTracker mockWifiTracker;
+
+    @Rule
+    public ActivityTestRule<WifiSettingsActivity> mActivityRule =
+            new ActivityTestRule<>(WifiSettingsActivity.class, true);
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        WifiTrackerFactory.setTestingWifiTracker(mockWifiTracker);
+    }
+
+    private void launchActivity() {
+        mActivityRule.launchActivity(new Intent("android.settings.WIFI_SETTINGS"));
+    }
+
+    @Test
+    public void launchActivityShouldSucceed() {
+        launchActivity();
+    }
+
+    @Test
+    public void shouldShowWifiPreferences() {
+        launchActivity();
+        onView(withText(WIFI_PREFERENCES)).perform(click());
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/applications/AppHeaderControllerTest.java b/tests/robotests/src/com/android/settings/applications/AppHeaderControllerTest.java
index 79f452a..0d878ed 100644
--- a/tests/robotests/src/com/android/settings/applications/AppHeaderControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/AppHeaderControllerTest.java
@@ -28,6 +28,7 @@
 import android.support.v7.preference.Preference;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.widget.ImageView;
 import android.widget.TextView;
 
 import com.android.settings.R;
@@ -276,6 +277,17 @@
                 .isEqualTo(View.GONE);
     }
 
+    // Ensure that the instant app label does not show up when we haven't told the controller the
+    // app is instant.
+    @Test
+    public void instantApps_normalAppsDontGetInstantAppsBadge() {
+        final View appHeader = mLayoutInflater.inflate(R.layout.app_details, null /* root */);
+        mController = new AppHeaderController(mContext, mFragment, appHeader);
+        mController.done();
+        assertThat(appHeader.findViewById(R.id.app_icon_instant_apps_badge).getVisibility())
+                .isEqualTo(View.GONE);
+    }
+
     // Test that the "instant apps" label is present in the header when we have an instant app.
     @Test
     public void instantApps_expectedHeaderItem() {
@@ -284,9 +296,13 @@
         mController.setIsInstantApp(true);
         mController.done();
         TextView label = (TextView)appHeader.findViewById(R.id.install_type);
+        ImageView badgeView = appHeader.findViewById(R.id.app_icon_instant_apps_badge);
+        assertThat(badgeView.getVisibility()).isEqualTo(View.VISIBLE);
         assertThat(label.getVisibility()).isEqualTo(View.VISIBLE);
         assertThat(label.getText()).isEqualTo(
                 appHeader.getResources().getString(R.string.install_type_instant));
+        assertThat(appHeader.findViewById(R.id.app_detail_summary).getVisibility())
+                .isEqualTo(View.GONE);
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/applications/AppWithAdminGrantedPermissionsCounterTest.java b/tests/robotests/src/com/android/settings/applications/AppWithAdminGrantedPermissionsCounterTest.java
index dfef3b8..aeb3826 100644
--- a/tests/robotests/src/com/android/settings/applications/AppWithAdminGrantedPermissionsCounterTest.java
+++ b/tests/robotests/src/com/android/settings/applications/AppWithAdminGrantedPermissionsCounterTest.java
@@ -22,6 +22,7 @@
 import android.content.pm.UserInfo;
 import android.os.Build;
 import android.os.UserHandle;
+import android.os.UserManager;
 
 import com.android.settings.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
@@ -35,7 +36,6 @@
 import org.robolectric.shadows.ShadowApplication;
 
 import java.util.Arrays;
-import java.util.List;
 
 import static com.android.settings.testutils.ApplicationTestUtils.buildInfo;
 import static com.google.common.truth.Truth.assertThat;
@@ -76,24 +76,25 @@
     private final String PERMISSION_2 = "some.permission.2";
     private final String[] PERMISSIONS = {PERMISSION_1, PERMISSION_2};
 
+    @Mock private UserManager mUserManager;
     @Mock private Context mContext;
     @Mock private PackageManagerWrapper mPackageManager;
     @Mock private IPackageManagerWrapper mPackageManagerService;
     @Mock private DevicePolicyManagerWrapper mDevicePolicyManager;
-    private List<UserInfo> mUsersToCount;
 
     private int mAppCount = -1;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
+        when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
     }
 
-    private void verifyCountInstalledAppsAcrossAllUsers(boolean async) throws Exception {
+    private void verifyCountInstalledApps(boolean async) throws Exception {
         // There are two users.
-        mUsersToCount = Arrays.asList(
+        when(mUserManager.getProfiles(UserHandle.myUserId())).thenReturn(Arrays.asList(
                 new UserInfo(MAIN_USER_ID, "main", UserInfo.FLAG_ADMIN),
-                new UserInfo(MANAGED_PROFILE_ID, "managed profile", 0));
+                new UserInfo(MANAGED_PROFILE_ID, "managed profile", 0)));
 
         // The first user has five apps installed:
         // * app1 uses run-time permissions. It has been granted one of the permissions by the
@@ -190,8 +191,8 @@
         }
         assertThat(mAppCount).isEqualTo(3);
 
-        // Verify that installed packages were retrieved for the users returned by
-        // InstalledAppCounterTestable.getUsersToCount() only.
+        // Verify that installed packages were retrieved the current user and the user's managed
+        // profile only.
         verify(mPackageManager).getInstalledApplicationsAsUser(anyInt(), eq(MAIN_USER_ID));
         verify(mPackageManager).getInstalledApplicationsAsUser(anyInt(),
                 eq(MANAGED_PROFILE_ID));
@@ -200,13 +201,13 @@
     }
 
     @Test
-    public void testCountInstalledAppsAcrossAllUsersSync() throws Exception {
-        verifyCountInstalledAppsAcrossAllUsers(false /* async */);
+    public void testCountInstalledAppsSync() throws Exception {
+        verifyCountInstalledApps(false /* async */);
     }
 
     @Test
-    public void testCountInstalledAppsAcrossAllUsersAync() throws Exception {
-        verifyCountInstalledAppsAcrossAllUsers(true /* async */);
+    public void testCountInstalledAppsAync() throws Exception {
+        verifyCountInstalledApps(true /* async */);
     }
 
     private class AppWithAdminGrantedPermissionsCounterTestable extends
@@ -220,10 +221,5 @@
         protected void onCountComplete(int num) {
             mAppCount = num;
         }
-
-        @Override
-        protected List<UserInfo> getUsersToCount() {
-            return mUsersToCount;
-        }
     }
 }
diff --git a/tests/robotests/src/com/android/settings/applications/ApplicationFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/applications/ApplicationFeatureProviderImplTest.java
index f946780..f46bb90 100644
--- a/tests/robotests/src/com/android/settings/applications/ApplicationFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/applications/ApplicationFeatureProviderImplTest.java
@@ -190,7 +190,7 @@
     }
 
     private void setUpUsersAndInstalledApps() {
-        when(mUserManager.getUsers(true)).thenReturn(Arrays.asList(
+        when(mUserManager.getProfiles(UserHandle.myUserId())).thenReturn(Arrays.asList(
                 new UserInfo(MAIN_USER_ID, "main", UserInfo.FLAG_ADMIN),
                 new UserInfo(MANAGED_PROFILE_ID, "managed profile", 0)));
 
diff --git a/tests/robotests/src/com/android/settings/applications/DrawOverlayDetailsTest.java b/tests/robotests/src/com/android/settings/applications/DrawOverlayDetailsTest.java
index a5306a2..ef6351a 100644
--- a/tests/robotests/src/com/android/settings/applications/DrawOverlayDetailsTest.java
+++ b/tests/robotests/src/com/android/settings/applications/DrawOverlayDetailsTest.java
@@ -19,10 +19,11 @@
 import android.content.Context;
 
 import com.android.internal.logging.nano.MetricsProto;
-import com.android.internal.telephony.SmsUsageMonitor;
 import com.android.settings.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
+import com.android.settings.core.TouchOverlayManager;
 import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.shadow.ShadowPreferenceFragment;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -32,6 +33,7 @@
 import org.mockito.MockitoAnnotations;
 import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowApplication;
+import org.robolectric.util.ReflectionHelpers;
 
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.eq;
@@ -47,17 +49,22 @@
     private FakeFeatureFactory mFeatureFactory;
     private DrawOverlayDetails mFragment;
 
+    @Mock
+    private TouchOverlayManager mTouchOverlayManager;
+
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         FakeFeatureFactory.setupForTest(mContext);
         mFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
+
         mFragment = new DrawOverlayDetails();
-        mFragment.onAttach(ShadowApplication.getInstance().getApplicationContext());
+        ReflectionHelpers.setField(mFragment, "mTouchOverlayManager", mTouchOverlayManager);
     }
 
     @Test
     public void logSpecialPermissionChange() {
+        mFragment.onAttach(ShadowApplication.getInstance().getApplicationContext());
         mFragment.logSpecialPermissionChange(true, "app");
         verify(mFeatureFactory.metricsFeatureProvider).action(any(Context.class),
                 eq(MetricsProto.MetricsEvent.APP_SPECIAL_PERMISSION_APPDRAW_ALLOW), eq("app"));
@@ -66,4 +73,18 @@
         verify(mFeatureFactory.metricsFeatureProvider).action(any(Context.class),
                 eq(MetricsProto.MetricsEvent.APP_SPECIAL_PERMISSION_APPDRAW_DENY), eq("app"));
     }
+
+    @Test
+    @Config(shadows = ShadowPreferenceFragment.class)
+    public void onStart_disableOverlay() {
+        mFragment.onStart();
+        verify(mTouchOverlayManager).setOverlayAllowed(false);
+    }
+
+    @Test
+    @Config(shadows = ShadowPreferenceFragment.class)
+    public void onStop_enableOverlay() {
+        mFragment.onStop();
+        verify(mTouchOverlayManager).setOverlayAllowed(true);
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/applications/ExternalSourcesDetailsTest.java b/tests/robotests/src/com/android/settings/applications/ExternalSourcesDetailsTest.java
deleted file mode 100644
index 5b2f8e0..0000000
--- a/tests/robotests/src/com/android/settings/applications/ExternalSourcesDetailsTest.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * 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 static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-
-import com.android.settings.R;
-import com.android.settings.SettingsRobolectricTestRunner;
-import com.android.settings.TestConfig;
-import com.android.settingslib.applications.ApplicationsState;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
-
-@RunWith(SettingsRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
-public class ExternalSourcesDetailsTest {
-
-    @Mock
-    private Context mContext;
-    @Mock
-    private AppStateInstallAppsBridge.InstallAppsState mInstallAppsStateAllowed;
-    @Mock
-    private AppStateInstallAppsBridge.InstallAppsState mInstallAppsStateBlocked;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        when(mInstallAppsStateAllowed.canInstallApps()).thenReturn(true);
-        when(mInstallAppsStateBlocked.canInstallApps()).thenReturn(false);
-    }
-
-    @Test
-    public void testGetPreferenceSummary() {
-        ApplicationsState.AppEntry appEntry = mock(ApplicationsState.AppEntry.class);
-        appEntry.extraInfo = mInstallAppsStateBlocked;
-        ExternalSourcesDetails.getPreferenceSummary(mContext, appEntry);
-        verify(mContext).getString(R.string.external_source_untrusted);
-        appEntry.extraInfo = mInstallAppsStateAllowed;
-        ExternalSourcesDetails.getPreferenceSummary(mContext, appEntry);
-        verify(mContext).getString(R.string.external_source_trusted);
-    }
-}
diff --git a/tests/robotests/src/com/android/settings/applications/InstalledAppCounterTest.java b/tests/robotests/src/com/android/settings/applications/InstalledAppCounterTest.java
index 1134ec5..46a3359 100644
--- a/tests/robotests/src/com/android/settings/applications/InstalledAppCounterTest.java
+++ b/tests/robotests/src/com/android/settings/applications/InstalledAppCounterTest.java
@@ -78,7 +78,6 @@
     @Mock private UserManager mUserManager;
     @Mock private Context mContext;
     @Mock private PackageManagerWrapper mPackageManager;
-    private List<UserInfo> mUsersToCount;
 
     private int mInstalledAppCount = -1;
 
@@ -99,9 +98,9 @@
 
     private void testCountInstalledAppsAcrossAllUsers(boolean async) {
         // There are two users.
-        mUsersToCount = Arrays.asList(
+        when(mUserManager.getProfiles(UserHandle.myUserId())).thenReturn(Arrays.asList(
                 new UserInfo(MAIN_USER_ID, "main", UserInfo.FLAG_ADMIN),
-                new UserInfo(MANAGED_PROFILE_ID, "managed profile", 0));
+                new UserInfo(MANAGED_PROFILE_ID, "managed profile", 0)));
 
         // The first user has four apps installed:
         // * app1 is an updated system app. It should be counted.
@@ -159,8 +158,8 @@
         count(InstalledAppCounter.IGNORE_INSTALL_REASON, async);
         assertThat(mInstalledAppCount).isEqualTo(5);
 
-        // Verify that installed packages were retrieved for the users returned by
-        // InstalledAppCounterTestable.getUsersToCount() only.
+        // Verify that installed packages were retrieved the current user and the user's managed
+        // profile only.
         verify(mPackageManager).getInstalledApplicationsAsUser(anyInt(), eq(MAIN_USER_ID));
         verify(mPackageManager).getInstalledApplicationsAsUser(anyInt(),
                 eq(MANAGED_PROFILE_ID));
@@ -205,11 +204,6 @@
         protected void onCountComplete(int num) {
             mInstalledAppCount = num;
         }
-
-        @Override
-        protected List<UserInfo> getUsersToCount() {
-            return mUsersToCount;
-        }
     }
 
     private static class IsLaunchIntentFor extends ArgumentMatcher<Intent> {
diff --git a/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java b/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java
index 209cdeb..a33a8c8 100644
--- a/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java
+++ b/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java
@@ -18,16 +18,21 @@
 
 
 import android.app.Activity;
+import android.app.AlertDialog;
 import android.app.admin.DevicePolicyManager;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
+import android.os.BatteryStats;
 import android.os.UserManager;
 import android.support.v7.preference.Preference;
 import android.view.View;
 import android.widget.Button;
 
+import com.android.internal.os.BatterySipper;
+import com.android.internal.os.BatteryStatsHelper;
 import com.android.settings.R;
+import com.android.settings.SettingsActivity;
 import com.android.settings.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
 import com.android.settings.applications.instantapps.InstantAppButtonsController;
@@ -48,10 +53,14 @@
 import org.robolectric.util.ReflectionHelpers;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -61,23 +70,37 @@
 public final class InstalledAppDetailsTest {
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private Context mContext;
-
     @Mock
     ApplicationFeatureProvider mApplicationFeatureProvider;
-
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private UserManager mUserManager;
     @Mock
-    private Activity mActivity;
+    private SettingsActivity mActivity;
     @Mock
     private DevicePolicyManager mDevicePolicyManager;
+    @Mock
+    private Preference mBatteryPreference;
+    @Mock
+    private BatterySipper mBatterySipper;
+    @Mock
+    private BatteryStatsHelper mBatteryStatsHelper;
+    @Mock
+    private BatteryStats.Uid mUid;
 
     private InstalledAppDetails mAppDetail;
+    private Context mShadowContext;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mAppDetail = new InstalledAppDetails();
+        mShadowContext = RuntimeEnvironment.application;
+
+        mAppDetail = spy(new InstalledAppDetails());
+
+        mBatterySipper.drainType = BatterySipper.DrainType.IDLE;
+        mBatterySipper.uidObj = mUid;
+        doReturn(mActivity).when(mAppDetail).getActivity();
+        doReturn(mShadowContext).when(mAppDetail).getContext();
 
         // Default to not considering any apps to be instant (individual tests can override this).
         ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
@@ -124,7 +147,7 @@
         when(stats.getTotalBytes()).thenReturn(1L);
 
         assertThat(InstalledAppDetails.getStorageSummary(context, stats, true))
-                .isEqualTo("1.00B used in External storage");
+                .isEqualTo("1.00B used in external storage");
     }
 
     @Test
@@ -134,7 +157,7 @@
         when(stats.getTotalBytes()).thenReturn(1L);
 
         assertThat(InstalledAppDetails.getStorageSummary(context, stats, false))
-                .isEqualTo("1.00B used in Internal storage");
+                .isEqualTo("1.00B used in internal storage");
     }
 
     @Test
@@ -154,6 +177,16 @@
         verify(mActivity, never()).finishAndRemoveTask();
     }
 
+    @Test
+    public void launchPowerUsageDetailFragment_shouldNotCrash() {
+        mAppDetail.mBatteryPreference = mBatteryPreference;
+        mAppDetail.mSipper = mBatterySipper;
+        mAppDetail.mBatteryHelper = mBatteryStatsHelper;
+
+        // Should not crash
+        mAppDetail.onPreferenceClick(mBatteryPreference);
+    }
+
     // Tests that we don't show the "uninstall for all users" button for instant apps.
     @Test
     public void instantApps_noUninstallForAllButton() {
@@ -181,7 +214,7 @@
     public void instantApps_noUninstallButton() {
         // Make this app appear to be instant.
         ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
-                                         (InstantAppDataProvider) (i -> true));
+                (InstantAppDataProvider) (i -> true));
         final ApplicationInfo info = new ApplicationInfo();
         info.flags = ApplicationInfo.FLAG_INSTALLED;
         info.enabled = true;
@@ -222,6 +255,20 @@
         verify(forceStopButton).setVisibility(View.GONE);
     }
 
+    @Test
+    public void instantApps_buttonControllerHandlesDialog() {
+        InstantAppButtonsController mockController = mock(InstantAppButtonsController.class);
+        ReflectionHelpers.setField(
+                mAppDetail, "mInstantAppButtonsController", mockController);
+        // Make sure first that button controller is not called for supported dialog id
+        AlertDialog mockDialog = mock(AlertDialog.class);
+        when(mockController.createDialog(InstantAppButtonsController.DLG_CLEAR_APP))
+                .thenReturn(mockDialog);
+        assertThat(mAppDetail.createDialog(InstantAppButtonsController.DLG_CLEAR_APP, 0))
+                .isEqualTo(mockDialog);
+        verify(mockController).createDialog(InstantAppButtonsController.DLG_CLEAR_APP);
+    }
+
     // A helper class for testing the InstantAppButtonsController - it lets us look up the
     // preference associated with a key for instant app buttons and get back a mock
     // LayoutPreference (to avoid a null pointer exception).
@@ -261,8 +308,8 @@
         FakeFeatureFactory.setupForTest(mContext);
         FakeFeatureFactory factory =
                 (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
-        when(factory.applicationFeatureProvider.newInstantAppButtonsController(any(),
-                any())).thenReturn(buttonsController);
+        when(factory.applicationFeatureProvider.newInstantAppButtonsController(
+                any(), any(), any())).thenReturn(buttonsController);
 
         fragment.maybeAddInstantAppButtons();
         verify(buttonsController).setPackageName(anyString());
diff --git a/tests/robotests/src/com/android/settings/applications/instantapps/InstantAppButtonsControllerTest.java b/tests/robotests/src/com/android/settings/applications/instantapps/InstantAppButtonsControllerTest.java
new file mode 100644
index 0000000..13040a2
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/applications/instantapps/InstantAppButtonsControllerTest.java
@@ -0,0 +1,180 @@
+/*
+ * 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.instantapps;
+
+import static com.android.settings.applications.instantapps.InstantAppButtonsController
+        .ShowDialogDelegate;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.isNull;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+import android.annotation.SuppressLint;
+import android.app.Fragment;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.view.View;
+import android.widget.Button;
+
+import com.android.settings.R;
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import com.android.settings.applications.PackageManagerWrapper;
+import com.android.settings.backup.BackupSettingsActivityTest;
+import com.android.settings.core.instrumentation.MetricsFeatureProvider;
+import com.android.settings.testutils.FakeFeatureFactory;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowUserManager;
+import org.robolectric.util.ReflectionHelpers;
+
+/** Tests for the InstantAppButtonsController. */
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = 23)
+public class InstantAppButtonsControllerTest {
+
+    private static final String TEST_INSTALLER_PACKAGE_NAME = "com.installer";
+    private static final String TEST_INSTALLER_ACTIVITY_NAME = "com.installer.InstallerActivity";
+    private static final ComponentName TEST_INSTALLER_COMPONENT =
+            new ComponentName(
+                    TEST_INSTALLER_PACKAGE_NAME,
+                    TEST_INSTALLER_ACTIVITY_NAME);
+    private static final String TEST_AIA_PACKAGE_NAME = "test.aia.package";
+
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    Context mockContext;
+    @Mock
+    PackageManager mockPackageManager;
+    @Mock
+    PackageManagerWrapper mockPackageManagerWrapper;
+    @Mock
+    View mockView;
+    @Mock
+    ShowDialogDelegate mockShowDialogDelegate;
+    @Mock
+    Button mockInstallButton;
+    @Mock
+    Button mockClearButton;
+    @Mock
+    MetricsFeatureProvider mockMetricsFeatureProvider;
+    @Mock
+    ResolveInfo mockResolveInfo;
+    @Mock
+    ActivityInfo mockActivityInfo;
+
+    private PackageManager stubPackageManager;
+
+    private FakeFeatureFactory fakeFeatureFactory;
+    private TestFragment testFragment;
+    private InstantAppButtonsController controller;
+
+
+    private View.OnClickListener receivedListener;
+
+    @Before
+    public void init() {
+        MockitoAnnotations.initMocks(this);
+        testFragment = new TestFragment();
+        when(mockView.findViewById(R.id.install)).thenReturn(mockInstallButton);
+        when(mockView.findViewById(R.id.clear_data)).thenReturn(mockClearButton);
+        mockResolveInfo.activityInfo = mockActivityInfo;
+        mockActivityInfo.packageName = TEST_INSTALLER_PACKAGE_NAME;
+        mockActivityInfo.name = TEST_INSTALLER_ACTIVITY_NAME;
+        when(mockContext.getPackageManager()).thenReturn(mockPackageManager);
+        when(mockPackageManager.resolveActivity(any(), anyInt())).thenReturn(mockResolveInfo);
+        controller = new InstantAppButtonsController(
+                mockContext, testFragment, mockView, mockShowDialogDelegate);
+        controller.setPackageName(TEST_AIA_PACKAGE_NAME);
+        ReflectionHelpers.setField(
+                controller, "mPackageManagerWrapper", mockPackageManagerWrapper);
+        FakeFeatureFactory.setupForTest(mockContext);
+    }
+
+    @Test
+    public void testInstallListenerTriggersInstall() {
+        doAnswer(invocation -> {
+            receivedListener = (View.OnClickListener) invocation.getArguments()[0];
+            return null;
+        }).when(mockInstallButton).setOnClickListener(any());
+        controller.bindButtons();
+
+        assertThat(receivedListener).isNotNull();
+        receivedListener.onClick(mockInstallButton);
+        assertThat(testFragment.getStartActivityIntent()).isNotNull();
+        assertThat(testFragment.getStartActivityIntent().getComponent())
+                .isEqualTo(TEST_INSTALLER_COMPONENT);
+    }
+
+    @Test
+    public void testClearListenerShowsDialog() {
+        doAnswer(invocation -> {
+            receivedListener = (View.OnClickListener) invocation.getArguments()[0];
+            return null;
+        }).when(mockClearButton).setOnClickListener(any());
+        controller.bindButtons();
+        assertThat(receivedListener).isNotNull();
+        receivedListener.onClick(mockClearButton);
+        verify(mockShowDialogDelegate).showDialog(InstantAppButtonsController.DLG_CLEAR_APP);
+    }
+
+    @Test
+    public void testDialogInterfaceOnClick_positiveClearsApp() {
+        controller.onClick(mock(DialogInterface.class), DialogInterface.BUTTON_POSITIVE);
+        verify(mockPackageManagerWrapper)
+                .deletePackageAsUser(eq(TEST_AIA_PACKAGE_NAME), any(), anyInt(),anyInt());
+    }
+
+    @Test
+    public void testDialogInterfaceOnClick_nonPositiveDoesNothing() {
+        controller.onClick(mock(DialogInterface.class), DialogInterface.BUTTON_NEGATIVE);
+        controller.onClick(mock(DialogInterface.class), DialogInterface.BUTTON_NEUTRAL);
+        verifyZeroInteractions(mockPackageManagerWrapper);
+    }
+    @SuppressLint("ValidFragment")
+    private class TestFragment extends Fragment {
+
+        private Intent startActivityIntent;
+
+        public Intent getStartActivityIntent() {
+            return startActivityIntent;
+        }
+
+        @Override
+        public void startActivity(Intent intent) {
+            startActivityIntent = intent;
+        }
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/StorageSettingsTest.java b/tests/robotests/src/com/android/settings/deviceinfo/StorageSettingsTest.java
index 84d3b98..95f9fbe 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/StorageSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/StorageSettingsTest.java
@@ -18,6 +18,7 @@
 
 
 import android.app.Activity;
+import android.app.usage.StorageStatsManager;
 import android.icu.text.NumberFormat;
 import android.os.storage.VolumeInfo;
 import android.text.format.Formatter;
@@ -40,6 +41,7 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
@@ -73,9 +75,14 @@
         final SummaryLoader.SummaryProvider provider =
                 StorageSettings.SUMMARY_PROVIDER_FACTORY.createSummaryProvider(mActivity, loader);
         final VolumeInfo volumeInfo = mVolumes.get(0);
+        when(volumeInfo.isMountedReadable()).thenReturn(true);
         when(volumeInfo.getType()).thenReturn(VolumeInfo.TYPE_PRIVATE);
-        when(volumeInfo.getPath().getTotalSpace()).thenReturn(500L);
-        when(volumeInfo.getPath().getFreeSpace()).thenReturn(0L);
+        when(mStorageManagerVolumeProvider.getTotalBytes(
+                        any(StorageStatsManager.class), any(VolumeInfo.class)))
+                .thenReturn(500L);
+        when(mStorageManagerVolumeProvider.getFreeBytes(
+                        any(StorageStatsManager.class), any(VolumeInfo.class)))
+                .thenReturn(0L);
 
         ReflectionHelpers.setField(
                 provider, "mStorageManagerVolumeProvider", mStorageManagerVolumeProvider);
diff --git a/tests/robotests/src/com/android/settings/enterprise/AlwaysOnVpnPrimaryUserPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/enterprise/AlwaysOnVpnCurrentUserPreferenceControllerTest.java
similarity index 90%
rename from tests/robotests/src/com/android/settings/enterprise/AlwaysOnVpnPrimaryUserPreferenceControllerTest.java
rename to tests/robotests/src/com/android/settings/enterprise/AlwaysOnVpnCurrentUserPreferenceControllerTest.java
index 12fdb4f..9d1bd58 100644
--- a/tests/robotests/src/com/android/settings/enterprise/AlwaysOnVpnPrimaryUserPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/enterprise/AlwaysOnVpnCurrentUserPreferenceControllerTest.java
@@ -36,11 +36,11 @@
 import static org.mockito.Mockito.when;
 
 /**
- * Tests for {@link AlwaysOnVpnPrimaryUserPreferenceController}.
+ * Tests for {@link AlwaysOnVpnCurrentUserPreferenceController}.
  */
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
-public final class AlwaysOnVpnPrimaryUserPreferenceControllerTest {
+public final class AlwaysOnVpnCurrentUserPreferenceControllerTest {
 
     private final String VPN_SET_DEVICE = "VPN set";
     private final String VPN_SET_PERSONAL = "VPN set in personal profile";
@@ -49,14 +49,14 @@
     private Context mContext;
     private FakeFeatureFactory mFeatureFactory;
 
-    private AlwaysOnVpnPrimaryUserPreferenceController mController;
+    private AlwaysOnVpnCurrentUserPreferenceController mController;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         FakeFeatureFactory.setupForTest(mContext);
         mFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
-        mController = new AlwaysOnVpnPrimaryUserPreferenceController(mContext,
+        mController = new AlwaysOnVpnCurrentUserPreferenceController(mContext,
                 null /* lifecycle */);
         when(mContext.getString(R.string.enterprise_privacy_always_on_vpn_device))
                 .thenReturn(VPN_SET_DEVICE);
@@ -68,7 +68,7 @@
     public void testUpdateState() {
         final Preference preference = new Preference(mContext, null, 0, 0);
 
-        when(mFeatureFactory.enterprisePrivacyFeatureProvider.isAlwaysOnVpnSetInPrimaryUser())
+        when(mFeatureFactory.enterprisePrivacyFeatureProvider.isAlwaysOnVpnSetInCurrentUser())
                 .thenReturn(true);
 
         when(mFeatureFactory.enterprisePrivacyFeatureProvider.isInCompMode()).thenReturn(false);
@@ -82,11 +82,11 @@
 
     @Test
     public void testIsAvailable() {
-        when(mFeatureFactory.enterprisePrivacyFeatureProvider.isAlwaysOnVpnSetInPrimaryUser())
+        when(mFeatureFactory.enterprisePrivacyFeatureProvider.isAlwaysOnVpnSetInCurrentUser())
                 .thenReturn(false);
         assertThat(mController.isAvailable()).isFalse();
 
-        when(mFeatureFactory.enterprisePrivacyFeatureProvider.isAlwaysOnVpnSetInPrimaryUser())
+        when(mFeatureFactory.enterprisePrivacyFeatureProvider.isAlwaysOnVpnSetInCurrentUser())
                 .thenReturn(true);
         assertThat(mController.isAvailable()).isTrue();
     }
diff --git a/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImplTest.java
index 8d78ef7..5e46216 100644
--- a/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImplTest.java
@@ -195,13 +195,13 @@
     }
 
     @Test
-    public void testIsAlwaysOnVpnSetInPrimaryUser() {
+    public void testIsAlwaysOnVpnSetInCurrentUser() {
         when(mConnectivityManger.getAlwaysOnVpnPackageForUser(MY_USER_ID)).thenReturn(null);
-        assertThat(mProvider.isAlwaysOnVpnSetInPrimaryUser()).isFalse();
+        assertThat(mProvider.isAlwaysOnVpnSetInCurrentUser()).isFalse();
 
         when(mConnectivityManger.getAlwaysOnVpnPackageForUser(MY_USER_ID))
                 .thenReturn(VPN_PACKAGE_ID);
-        assertThat(mProvider.isAlwaysOnVpnSetInPrimaryUser()).isTrue();
+        assertThat(mProvider.isAlwaysOnVpnSetInCurrentUser()).isTrue();
     }
 
     @Test
@@ -230,16 +230,14 @@
     }
 
     @Test
-    public void testGetMaximumFailedPasswordsForWipeInPrimaryUser() {
-        when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()).thenReturn(null);
-        when(mDevicePolicyManager.getDeviceOwnerUserId()).thenReturn(UserHandle.USER_NULL);
-        assertThat(mProvider.getMaximumFailedPasswordsBeforeWipeInPrimaryUser()).isEqualTo(0);
-
-        when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()).thenReturn(OWNER);
-        when(mDevicePolicyManager.getDeviceOwnerUserId()).thenReturn(UserHandle.USER_SYSTEM);
-        when(mDevicePolicyManager.getMaximumFailedPasswordsForWipe(OWNER, UserHandle.USER_SYSTEM))
+    public void testGetMaximumFailedPasswordsForWipeInCurrentUser() {
+        when(mDevicePolicyManager.getProfileOwnerAsUser(MY_USER_ID)).thenReturn(null);
+        when(mDevicePolicyManager.getMaximumFailedPasswordsForWipe(OWNER, MY_USER_ID))
                 .thenReturn(10);
-        assertThat(mProvider.getMaximumFailedPasswordsBeforeWipeInPrimaryUser()).isEqualTo(10);
+        assertThat(mProvider.getMaximumFailedPasswordsBeforeWipeInCurrentUser()).isEqualTo(0);
+
+        when(mDevicePolicyManager.getProfileOwnerAsUser(MY_USER_ID)).thenReturn(OWNER);
+        assertThat(mProvider.getMaximumFailedPasswordsBeforeWipeInCurrentUser()).isEqualTo(10);
     }
 
     @Test
@@ -247,7 +245,6 @@
         when(mDevicePolicyManager.getProfileOwnerAsUser(MANAGED_PROFILE_USER_ID)).thenReturn(OWNER);
         when(mDevicePolicyManager.getMaximumFailedPasswordsForWipe(OWNER, MANAGED_PROFILE_USER_ID))
                 .thenReturn(10);
-
         assertThat(mProvider.getMaximumFailedPasswordsBeforeWipeInManagedProfile()).isEqualTo(0);
 
         mProfiles.add(new UserInfo(MANAGED_PROFILE_USER_ID, "", "", UserInfo.FLAG_MANAGED_PROFILE));
diff --git a/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacySettingsTest.java b/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacySettingsTest.java
index 2225687..d41be75 100644
--- a/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacySettingsTest.java
+++ b/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacySettingsTest.java
@@ -134,7 +134,7 @@
         assertThat(controllers.get(position++)).isInstanceOf(
                 EnterpriseSetDefaultAppsPreferenceController.class);
         assertThat(controllers.get(position++)).isInstanceOf(
-                AlwaysOnVpnPrimaryUserPreferenceController.class);
+                AlwaysOnVpnCurrentUserPreferenceController.class);
         assertThat(controllers.get(position++)).isInstanceOf(
                 AlwaysOnVpnManagedProfilePreferenceController.class);
         assertThat(controllers.get(position++)).isInstanceOf(
@@ -142,7 +142,7 @@
         assertThat(controllers.get(position++)).isInstanceOf(
                 CaCertsPreferenceController.class);
         assertThat(controllers.get(position++)).isInstanceOf(
-                FailedPasswordWipePrimaryUserPreferenceController.class);
+                FailedPasswordWipeCurrentUserPreferenceController.class);
         assertThat(controllers.get(position++)).isInstanceOf(
                 FailedPasswordWipeManagedProfilePreferenceController.class);
         assertThat(controllers.get(position++)).isInstanceOf(ImePreferenceController.class);
diff --git a/tests/robotests/src/com/android/settings/enterprise/FailedPasswordWipePrimaryUserPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/enterprise/FailedPasswordWipeCurrentUserPreferenceControllerTest.java
similarity index 80%
rename from tests/robotests/src/com/android/settings/enterprise/FailedPasswordWipePrimaryUserPreferenceControllerTest.java
rename to tests/robotests/src/com/android/settings/enterprise/FailedPasswordWipeCurrentUserPreferenceControllerTest.java
index d74b9b8..b2f4fa7 100644
--- a/tests/robotests/src/com/android/settings/enterprise/FailedPasswordWipePrimaryUserPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/enterprise/FailedPasswordWipeCurrentUserPreferenceControllerTest.java
@@ -27,29 +27,29 @@
 import static org.mockito.Mockito.when;
 
 /**
- * Tests for {@link FailedPasswordWipePrimaryUserPreferenceController}.
+ * Tests for {@link FailedPasswordWipeCurrentUserPreferenceController}.
  */
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
-public final class FailedPasswordWipePrimaryUserPreferenceControllerTest extends
+public final class FailedPasswordWipeCurrentUserPreferenceControllerTest extends
         FailedPasswordWipePreferenceControllerTestBase {
 
     private int mMaximumFailedPasswordsBeforeWipe = 0;
 
-    public FailedPasswordWipePrimaryUserPreferenceControllerTest() {
-        super("failed_password_wipe_primary_user");
+    public FailedPasswordWipeCurrentUserPreferenceControllerTest() {
+        super("failed_password_wipe_current_user");
     }
 
     @Override
     public void setUp() {
         super.setUp();
-        mController = new FailedPasswordWipePrimaryUserPreferenceController(mContext,
+        mController = new FailedPasswordWipeCurrentUserPreferenceController(mContext,
                 null /* lifecycle */);
     }
 
     @Override
     public void setMaximumFailedPasswordsBeforeWipe(int maximum) {
         when(mFeatureFactory.enterprisePrivacyFeatureProvider
-                .getMaximumFailedPasswordsBeforeWipeInPrimaryUser()).thenReturn(maximum);
+                .getMaximumFailedPasswordsBeforeWipeInCurrentUser()).thenReturn(maximum);
     }
 }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
index a6e0943..5f2d54f 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
@@ -15,19 +15,17 @@
  */
 package com.android.settings.fuelgauge;
 
-import android.app.Activity;
 import android.content.Context;
 import android.content.Intent;
 import android.os.PowerManager;
 import android.os.Process;
-import android.support.v7.preference.Preference;
 import android.text.TextUtils;
 import android.text.format.DateUtils;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
-import android.view.View;
 import android.widget.TextView;
+
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.internal.os.BatterySipper;
 import com.android.internal.os.BatteryStatsHelper;
@@ -40,6 +38,7 @@
 import com.android.settings.applications.LayoutPreference;
 import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settingslib.BatteryInfo;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -53,13 +52,15 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import static com.android.settings.fuelgauge.PowerUsageBase.MENU_STATS_REFRESH;
 import static com.android.settings.fuelgauge.PowerUsageSummary.MENU_ADDITIONAL_BATTERY_INFO;
 import static com.android.settings.fuelgauge.PowerUsageSummary.MENU_HIGH_POWER_APPS;
 import static com.android.settings.fuelgauge.PowerUsageSummary.MENU_TOGGLE_APPS;
+
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyLong;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.doReturn;
@@ -77,9 +78,13 @@
 public class PowerUsageSummaryTest {
     private static final String[] PACKAGE_NAMES = {"com.app1", "com.app2"};
     private static final String TIME_LEFT = "2h30min";
+    private static final int BATTERY_LEVEL = 55;
     private static final int UID = 123;
     private static final int POWER_MAH = 100;
     private static final long REMAINING_TIME_US = 100000;
+    private static final long TIME_SINCE_LAST_FULL_CHARGE_MS = 25000;
+    private static final long TIME_SINCE_LAST_FULL_CHARGE_US =
+            TIME_SINCE_LAST_FULL_CHARGE_MS * 1000;
     private static final int DISCHARGE_AMOUNT = 100;
     private static final long USAGE_TIME_MS = 10000;
     private static final double TOTAL_POWER = 200;
@@ -117,20 +122,16 @@
     @Mock
     private BatteryMeterView mBatteryMeterView;
     @Mock
-    private TextView mTimeText;
+    private TextView mBatteryPercentText;
     @Mock
     private TextView mSummary1;
     @Mock
-    private TextView mSummary2;
-    @Mock
     private BatteryInfo mBatteryInfo;
     @Mock
-    private Preference mScreenUsagePref;
+    private PowerGaugePreference mScreenUsagePref;
     @Mock
-    private Preference mScreenConsumptionPref;
-    @Mock
-    private Preference mCellularNetworkPref;
-    @Mock
+    private PowerGaugePreference mLastFullChargePref;
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private BatteryStatsHelper mBatteryHelper;
     @Mock
     private PowerManager mPowerManager;
@@ -153,7 +154,7 @@
 
         mFragment = spy(new TestFragment(mContext));
         mFragment.initFeatureProvider();
-        
+
         when(mFragment.getActivity()).thenReturn(mSettingsActivity);
         when(mAdditionalBatteryInfoMenu.getItemId())
                 .thenReturn(MENU_ADDITIONAL_BATTERY_INFO);
@@ -162,6 +163,8 @@
         when(mFeatureFactory.powerUsageFeatureProvider.getAdditionalBatteryInfoIntent())
                 .thenReturn(ADDITIONAL_BATTERY_INFO_INTENT);
         when(mBatteryHelper.getTotalPower()).thenReturn(TOTAL_POWER);
+        when(mBatteryHelper.getStats().computeBatteryRealtime(anyLong(), anyInt())).thenReturn(
+                TIME_SINCE_LAST_FULL_CHARGE_US);
 
         when(mNormalBatterySipper.getPackages()).thenReturn(PACKAGE_NAMES);
         when(mNormalBatterySipper.getUid()).thenReturn(UID);
@@ -172,8 +175,7 @@
         mCellBatterySipper.totalPowerMah = POWER_MAH;
 
         when(mBatteryLayoutPref.findViewById(R.id.summary1)).thenReturn(mSummary1);
-        when(mBatteryLayoutPref.findViewById(R.id.summary2)).thenReturn(mSummary2);
-        when(mBatteryLayoutPref.findViewById(R.id.time)).thenReturn(mTimeText);
+        when(mBatteryLayoutPref.findViewById(R.id.battery_percent)).thenReturn(mBatteryPercentText);
         when(mBatteryLayoutPref.findViewById(R.id.battery_header_icon))
                 .thenReturn(mBatteryMeterView);
         mFragment.setBatteryLayoutPreference(mBatteryLayoutPref);
@@ -194,8 +196,9 @@
         mFragment.mStatsHelper = mBatteryHelper;
         when(mBatteryHelper.getUsageList()).thenReturn(mUsageList);
         mFragment.mScreenUsagePref = mScreenUsagePref;
-        mFragment.mScreenConsumptionPref = mScreenConsumptionPref;
-        mFragment.mCellularNetworkPref = mCellularNetworkPref;
+        mFragment.mLastFullChargePref = mLastFullChargePref;
+
+        mBatteryInfo.mBatteryLevel = BATTERY_LEVEL;
     }
 
     @Test
@@ -226,7 +229,7 @@
     }
 
     @Test
-    public void testOptionsMenu_MenuHighPower_MetricEventInvoked() {
+    public void testOptionsMenu_menuHighPower_metricEventInvoked() {
         mFragment.onOptionsItemSelected(mHighPowerMenu);
 
         verify(mFeatureFactory.metricsFeatureProvider).action(mContext,
@@ -234,7 +237,7 @@
     }
 
     @Test
-    public void testOptionsMenu_MenuAdditionalBattery_MetricEventInvoked() {
+    public void testOptionsMenu_menuAdditionalBattery_metricEventInvoked() {
         mFragment.onOptionsItemSelected(mAdditionalBatteryInfoMenu);
 
         verify(mFeatureFactory.metricsFeatureProvider).action(mContext,
@@ -242,7 +245,7 @@
     }
 
     @Test
-    public void testOptionsMenu_MenuAppToggle_MetricEventInvoked() {
+    public void testOptionsMenu_menuAppToggle_metricEventInvoked() {
         mFragment.onOptionsItemSelected(mToggleAppsMenu);
         mFragment.mShowAllApps = false;
 
@@ -251,7 +254,7 @@
     }
 
     @Test
-    public void testOptionsMenu_ToggleAppsEnabled() {
+    public void testOptionsMenu_toggleAppsEnabled() {
         when(mFeatureFactory.powerUsageFeatureProvider.isPowerAccountingToggleEnabled())
                 .thenReturn(true);
         mFragment.mShowAllApps = false;
@@ -262,13 +265,13 @@
     }
 
     @Test
-    public void testOptionsMenu_ClickToggleAppsMenu_DataChanged() {
+    public void testOptionsMenu_clickToggleAppsMenu_dataChanged() {
         testToggleAllApps(true);
         testToggleAllApps(false);
     }
 
     @Test
-    public void testExtractKeyFromSipper_TypeAPPUidObjectNull_ReturnPackageNames() {
+    public void testExtractKeyFromSipper_typeAPPUidObjectNull_returnPackageNames() {
         mNormalBatterySipper.uidObj = null;
         mNormalBatterySipper.drainType = BatterySipper.DrainType.APP;
 
@@ -277,7 +280,7 @@
     }
 
     @Test
-    public void testExtractKeyFromSipper_TypeOther_ReturnDrainType() {
+    public void testExtractKeyFromSipper_typeOther_returnDrainType() {
         mNormalBatterySipper.uidObj = null;
         mNormalBatterySipper.drainType = BatterySipper.DrainType.BLUETOOTH;
 
@@ -286,7 +289,7 @@
     }
 
     @Test
-    public void testExtractKeyFromSipper_TypeAPPUidObjectNotNull_ReturnUid() {
+    public void testExtractKeyFromSipper_typeAPPUidObjectNotNull_returnUid() {
         mNormalBatterySipper.uidObj = new BatteryStatsImpl.Uid(new BatteryStatsImpl(), UID);
         mNormalBatterySipper.drainType = BatterySipper.DrainType.APP;
 
@@ -295,7 +298,7 @@
     }
 
     @Test
-    public void testRemoveHiddenBatterySippers_ContainsHiddenSippers_RemoveAndReturnValue() {
+    public void testRemoveHiddenBatterySippers_containsHiddenSippers_removeAndReturnValue() {
         final List<BatterySipper> sippers = new ArrayList<>();
         sippers.add(mNormalBatterySipper);
         sippers.add(mScreenBatterySipper);
@@ -309,37 +312,37 @@
     }
 
     @Test
-    public void testShouldHideSipper_TypeIdle_ReturnTrue() {
+    public void testShouldHideSipper_typeIdle_returnTrue() {
         mNormalBatterySipper.drainType = BatterySipper.DrainType.IDLE;
         assertThat(mFragment.shouldHideSipper(mNormalBatterySipper)).isTrue();
     }
 
     @Test
-    public void testShouldHideSipper_TypeWifi_ReturnTrue() {
+    public void testShouldHideSipper_typeWifi_returnTrue() {
         mNormalBatterySipper.drainType = BatterySipper.DrainType.WIFI;
         assertThat(mFragment.shouldHideSipper(mNormalBatterySipper)).isTrue();
     }
 
     @Test
-    public void testShouldHideSipper_TypeCell_ReturnTrue() {
+    public void testShouldHideSipper_typeCell_returnTrue() {
         mNormalBatterySipper.drainType = BatterySipper.DrainType.CELL;
         assertThat(mFragment.shouldHideSipper(mNormalBatterySipper)).isTrue();
     }
 
     @Test
-    public void testShouldHideSipper_TypeScreen_ReturnTrue() {
+    public void testShouldHideSipper_typeScreen_returnTrue() {
         mNormalBatterySipper.drainType = BatterySipper.DrainType.SCREEN;
         assertThat(mFragment.shouldHideSipper(mNormalBatterySipper)).isTrue();
     }
 
     @Test
-    public void testShouldHideSipper_TypeBluetooth_ReturnTrue() {
+    public void testShouldHideSipper_typeBluetooth_returnTrue() {
         mNormalBatterySipper.drainType = BatterySipper.DrainType.BLUETOOTH;
         assertThat(mFragment.shouldHideSipper(mNormalBatterySipper)).isTrue();
     }
 
     @Test
-    public void testShouldHideSipper_TypeSystem_ReturnTrue() {
+    public void testShouldHideSipper_typeSystem_returnTrue() {
         mNormalBatterySipper.drainType = BatterySipper.DrainType.APP;
         when(mNormalBatterySipper.getUid()).thenReturn(Process.ROOT_UID);
         when(mFeatureFactory.powerUsageFeatureProvider.isTypeSystem(Matchers.<BatterySipper>any()))
@@ -348,14 +351,14 @@
     }
 
     @Test
-    public void testShouldHideSipper_UidNormal_ReturnFalse() {
+    public void testShouldHideSipper_uidNormal_returnFalse() {
         mNormalBatterySipper.drainType = BatterySipper.DrainType.APP;
         when(mNormalBatterySipper.getUid()).thenReturn(UID);
         assertThat(mFragment.shouldHideSipper(mNormalBatterySipper)).isFalse();
     }
 
     @Test
-    public void testShouldHideSipper_TypeService_ReturnTrue() {
+    public void testShouldHideSipper_typeService_returnTrue() {
         mNormalBatterySipper.drainType = BatterySipper.DrainType.APP;
         when(mNormalBatterySipper.getUid()).thenReturn(UID);
         when(mFeatureFactory.powerUsageFeatureProvider.isTypeService(Matchers.<BatterySipper>any()))
@@ -365,7 +368,7 @@
     }
 
     @Test
-    public void testSetUsageSummary_TimeLessThanOneMinute_DoNotSetSummary() {
+    public void testSetUsageSummary_timeLessThanOneMinute_doNotSetSummary() {
         final long usageTimeMs = 59 * DateUtils.SECOND_IN_MILLIS;
 
         mFragment.setUsageSummary(mPreference, "", usageTimeMs);
@@ -373,7 +376,7 @@
     }
 
     @Test
-    public void testSetUsageSummary_TimeMoreThanOneMinute_SetSummary() {
+    public void testSetUsageSummary_timeMoreThanOneMinute_setSummary() {
         final long usageTimeMs = 2 * DateUtils.MINUTE_IN_MILLIS;
 
         mFragment.setUsageSummary(mPreference, "", usageTimeMs);
@@ -381,45 +384,25 @@
     }
 
     @Test
-    public void testUpdatePreference_NoEstimatedTime_DoNotShowSummary() {
-        mBatteryInfo.remainingTimeUs = 0;
+    public void testUpdatePreference_hasRemainingTime_showRemainingLabel() {
         mBatteryInfo.remainingLabel = TIME_LEFT;
+
         mFragment.updateHeaderPreference(mBatteryInfo);
 
-        verify(mSummary1).setVisibility(View.INVISIBLE);
-        verify(mSummary2).setVisibility(View.INVISIBLE);
+        verify(mSummary1).setText(mBatteryInfo.remainingLabel);
     }
 
     @Test
-    public void testUpdatePreference_HasEstimatedTime_ShowSummary() {
-        mBatteryInfo.remainingTimeUs = REMAINING_TIME_US;
-        mBatteryInfo.remainingLabel = TIME_LEFT;
+    public void testUpdatePreference_noRemainingTime_showStatusLabel() {
+        mBatteryInfo.remainingLabel = null;
+
         mFragment.updateHeaderPreference(mBatteryInfo);
 
-        verify(mSummary1).setVisibility(View.VISIBLE);
-        verify(mSummary2).setVisibility(View.VISIBLE);
+        verify(mSummary1).setText(mBatteryInfo.statusLabel);
     }
 
     @Test
-    public void testUpdatePreference_Charging_ShowChargingTimeLeft() {
-        mBatteryInfo.remainingTimeUs = REMAINING_TIME_US;
-        mBatteryInfo.mDischarging = false;
-
-        mFragment.updateHeaderPreference(mBatteryInfo);
-        verify(mSummary1).setText(R.string.estimated_charging_time_left);
-    }
-
-    @Test
-    public void testUpdatePreference_NotCharging_ShowTimeLeft() {
-        mBatteryInfo.remainingTimeUs = REMAINING_TIME_US;
-        mBatteryInfo.mDischarging = true;
-
-        mFragment.updateHeaderPreference(mBatteryInfo);
-        verify(mSummary1).setText(R.string.estimated_time_left);
-    }
-
-    @Test
-    public void testUpdateHeaderPreference_AsyncUpdate_ShouldNotCrash() {
+    public void testUpdateHeaderPreference_asyncUpdate_shouldNotCrash() {
         when(mFragment.getContext()).thenReturn(null);
         mBatteryInfo.remainingTimeUs = REMAINING_TIME_US;
 
@@ -451,43 +434,36 @@
     }
 
     @Test
-    public void testUpdateCellularPreference_ShowCorrectSummary() {
-        final double percent = POWER_MAH / TOTAL_POWER * DISCHARGE_AMOUNT;
-        final String expectedSummary = mRealContext.getString(R.string.battery_overall_usage,
-                Utils.formatPercentage((int) percent));
-        doReturn(expectedSummary).when(mFragment)
-                .getString(eq(R.string.battery_overall_usage), anyInt());
-        mFragment.updateCellularPreference(DISCHARGE_AMOUNT);
+    public void testUpdateScreenPreference_showCorrectSummary() {
+        final String expectedUsedTime = Utils.formatElapsedTime(mRealContext, USAGE_TIME_MS, false);
+        doReturn(mScreenBatterySipper).when(mFragment).findBatterySipperByType(any(), any());
+        doReturn(mRealContext).when(mFragment).getContext();
 
-        verify(mCellularNetworkPref).setSummary(expectedSummary);
+        mFragment.updateScreenPreference();
+
+        verify(mScreenUsagePref).setSubtitle(expectedUsedTime);
     }
 
     @Test
-    public void testUpdateScreenPreference_ShowCorrectSummary() {
-        final String expectedUsedTime = mRealContext.getString(R.string.battery_used_for,
-                Utils.formatElapsedTime(mRealContext, USAGE_TIME_MS, false));
-        final double percent = BATTERY_SCREEN_USAGE / TOTAL_POWER * DISCHARGE_AMOUNT;
-        final String expectedOverallUsage = mRealContext.getString(R.string.battery_overall_usage,
-                Utils.formatPercentage((int) percent));
-        doReturn(expectedUsedTime).when(mFragment).getString(
-                eq(R.string.battery_used_for), anyInt());
-        doReturn(expectedOverallUsage).when(mFragment).getString(
-                eq(R.string.battery_overall_usage), anyInt());
+    public void testUpdateLastFullChargePreference_showCorrectSummary() {
+        doReturn(mRealContext).when(mFragment).getContext();
+        final String expected = mRealContext.getString(R.string.power_last_full_charge_summary,
+                Utils.formatElapsedTime(mRealContext, TIME_SINCE_LAST_FULL_CHARGE_MS, false));
+        doReturn(expected).when(mFragment).getString(eq(R.string.power_last_full_charge_summary),
+                any());
 
-        mFragment.updateScreenPreference(DISCHARGE_AMOUNT);
+        mFragment.updateLastFullChargePreference(TIME_SINCE_LAST_FULL_CHARGE_MS);
 
-        verify(mScreenUsagePref).setSummary(expectedUsedTime);
-        verify(mScreenConsumptionPref).setSummary(expectedOverallUsage);
+        verify(mLastFullChargePref).setSubtitle(expected);
     }
 
     @Test
-    public void testUpdatePreference_UsageListEmpty_ShouldNotCrash() {
+    public void testUpdatePreference_usageListEmpty_shouldNotCrash() {
         when(mBatteryHelper.getUsageList()).thenReturn(new ArrayList<BatterySipper>());
-        doReturn("").when(mFragment).getString(anyInt(), Matchers.anyObject());
+        doReturn("").when(mFragment).getString(anyInt(), any());
 
         // Should not crash when update
-        mFragment.updateScreenPreference(DISCHARGE_AMOUNT);
-        mFragment.updateCellularPreference(DISCHARGE_AMOUNT);
+        mFragment.updateScreenPreference();
     }
 
     @Test
@@ -496,6 +472,12 @@
         assertThat(percent).isWithin(PRECISION).of(POWER_USAGE_PERCENTAGE);
     }
 
+    @Test
+    public void testCalculateRunningTimeBasedOnStatsType() {
+        assertThat(mFragment.calculateRunningTimeBasedOnStatsType()).isEqualTo(
+                TIME_SINCE_LAST_FULL_CHARGE_MS);
+    }
+
     public static class TestFragment extends PowerUsageSummary {
 
         private Context mContext;
diff --git a/tests/robotests/src/com/android/settings/suggestions/SettingsSuggestionsTest.java b/tests/robotests/src/com/android/settings/suggestions/SettingsSuggestionsTest.java
new file mode 100644
index 0000000..3780d35
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/suggestions/SettingsSuggestionsTest.java
@@ -0,0 +1,100 @@
+/*
+ * 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.suggestions;
+
+import static com.android.settings.TestConfig.MANIFEST_PATH;
+import static com.google.common.truth.Truth.assertThat;
+
+import android.annotation.StringRes;
+import android.content.Context;
+import com.android.settings.R;
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.manifest.ActivityData;
+import org.robolectric.manifest.AndroidManifest;
+import org.robolectric.manifest.IntentFilterData;
+import org.robolectric.shadows.ShadowApplication;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class SettingsSuggestionsTest {
+
+  @Test
+  public void zenModeAutomationSuggestion_isValid() {
+    assertSuggestionEquals("Settings$ZenModeAutomationSuggestionActivity",
+        R.string.zen_mode_automation_suggestion_title,
+        R.string.zen_mode_automation_suggestion_summary);
+  }
+
+  @Test
+  public void wallpaperSuggestion_isValid() {
+    assertSuggestionEquals("com.android.settings.wallpaper.WallpaperSuggestionActivity",
+        R.string.wallpaper_suggestion_title, R.string.wallpaper_suggestion_summary);
+  }
+
+  @Test
+  public void nightDisplaySettings_isValid() {
+    assertSuggestionEquals("Settings$NightDisplaySettingsActivity",
+        R.string.night_display_suggestion_title, R.string.night_display_suggestion_summary);
+  }
+
+  @Test
+  public void fingerprintSuggestion_isValid() {
+    assertSuggestionEquals("com.android.settings.Settings$FingerprintSuggestionActivity",
+        R.string.suggestion_additional_fingerprints,
+        R.string.suggestion_additional_fingerprints_summary);
+  }
+
+  @Test
+  public void wifiCallingSuggestion_isValid() {
+    assertSuggestionEquals("Settings$WifiCallingSuggestionActivity",
+        R.string.wifi_calling_suggestion_title, R.string.wifi_calling_suggestion_summary);
+  }
+
+  private void assertSuggestionEquals(String activityName, @StringRes int title,
+      @StringRes int summary) {
+    final AndroidManifest androidManifest = ShadowApplication.getInstance().getAppManifest();
+    final ActivityData activityData = androidManifest.getActivityData(activityName);
+    final Map<String, Object> metaData = activityData.getMetaData().getValueMap();
+    final Context context = RuntimeEnvironment.application;
+    final String expectedTitle = context.getString(title);
+    final String expectedSummary = context.getString(summary);
+
+    final String pName= context.getPackageName();
+    final String actualTitle = context.getString(context.getResources().getIdentifier(
+        ((String) metaData.get("com.android.settings.title")).substring(8), "string", pName));
+    final String actualSummary = context.getString(context.getResources().getIdentifier(
+        ((String) metaData.get("com.android.settings.summary")).substring(8), "string", pName));
+    assertThat(actualTitle).isEqualTo(expectedTitle);
+    assertThat(actualSummary).isEqualTo(expectedSummary);
+
+    final List<IntentFilterData> intentFilters = activityData.getIntentFilters();
+    final List<String> categories = new ArrayList<>();
+    for (IntentFilterData intentFilter : intentFilters) {
+      categories.addAll(intentFilter.getCategories());
+    }
+
+    assertThat(categories).contains("com.android.settings.suggested.category.SETTINGS_ONLY");
+  }
+}
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowPreferenceFragment.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowPreferenceFragment.java
new file mode 100644
index 0000000..cfd0ce9
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowPreferenceFragment.java
@@ -0,0 +1,35 @@
+/*
+ * 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.support.v14.preference.PreferenceFragment;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+@Implements(PreferenceFragment.class)
+public class ShadowPreferenceFragment {
+
+    @Implementation
+    public void onStart() {
+        // No-op.
+    }
+
+    @Implementation
+    public void onStop() {
+        // No-op.
+    }
+}
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 0a12ebf..f60c106 100644
--- a/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
@@ -18,6 +18,7 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -93,14 +94,14 @@
         when(mockAccessPoint.getRssi()).thenReturn(RSSI);
         when(mockAccessPoint.getSecurityString(false)).thenReturn(SECURITY);
 
+        when(mockWifiInfo.getLinkSpeed()).thenReturn(LINK_SPEED);
+        when(mockWifiInfo.getRssi()).thenReturn(RSSI);
+        when(mockWifiManager.getConnectionInfo()).thenReturn(mockWifiInfo);
+
         mController = new WifiDetailPreferenceController(
                 mockAccessPoint, mContext, mLifecycle, mockWifiManager);
 
         setupMockedPreferenceScreen();
-
-        when(mockWifiInfo.getRssi()).thenReturn(RSSI);
-        when(mockWifiInfo.getLinkSpeed()).thenReturn(LINK_SPEED);
-        when(mockWifiManager.getConnectionInfo()).thenReturn(mockWifiInfo);
     }
 
     private void setupMockedPreferenceScreen() {
@@ -143,7 +144,8 @@
     public void latestWifiInfoAndConfig_shouldBeFetchedOnResume() {
         mController.onResume();
 
-        verify(mockWifiManager).getConnectionInfo();
+        // Once in construction, once in onResume
+        verify(mockWifiManager, times(2)).getConnectionInfo();
     }
 
     @Test
@@ -193,19 +195,41 @@
     }
 
     @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);
+    public void canForgetNetwork_noNetwork() {
+        when(mockAccessPoint.getConfig()).thenReturn(null);
 
         mController = new WifiDetailPreferenceController(
                 mockAccessPoint, mContext, mLifecycle, mockWifiManager);
 
+        assertThat(mController.canForgetNetwork()).isFalse();
+    }
+
+    @Test
+    public void canForgetNetwork_ephemeral() {
+        when(mockWifiInfo.isEphemeral()).thenReturn(true);
+        when(mockAccessPoint.getConfig()).thenReturn(null);
+
+        mController = new WifiDetailPreferenceController(
+                mockAccessPoint, mContext, mLifecycle, mockWifiManager);
+
+        assertThat(mController.canForgetNetwork()).isTrue();
+    }
+
+    @Test
+    public void canForgetNetwork_saved() {
+        assertThat(mController.canForgetNetwork()).isTrue();
+    }
+
+    @Test
+    public void forgetNetwork_ephemeral() {
+        String ssid = "ssid";
+
+        when(mockWifiInfo.isEphemeral()).thenReturn(true);
+        when(mockWifiInfo.getSSID()).thenReturn(ssid);
+
         mController.forgetNetwork();
 
-        verify(mockWifiManager).disableEphemeralNetwork(wifiConfiguration.SSID);
+        verify(mockWifiManager).disableEphemeralNetwork(ssid);
     }
 
     @Test