Merge "Add SettingsMultiSelectListPreference style" into pi-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index dbe231b..feb1b05 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -2955,7 +2955,7 @@
                        android:value="com.android.settings.applications.appinfo.ExternalSourcesDetails" />
         </activity>
 
-        <activity android:name="ShowAdminSupportDetailsDialog"
+        <activity android:name=".enterprise.ActionDisabledByAdminDialog"
                 android:theme="@style/Transparent"
                 android:excludeFromRecents="true"
                 android:launchMode="singleTop">
diff --git a/res/layout/admin_support_details_content.xml b/res/layout/admin_support_details_content.xml
deleted file mode 100644
index 7c756c4..0000000
--- a/res/layout/admin_support_details_content.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<merge xmlns:android="http://schemas.android.com/apk/res/android">
-    <TextView android:id="@+id/admin_support_msg"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:textAppearance="@android:style/TextAppearance.Material.Subhead"
-            android:text="@string/default_admin_support_msg"
-            android:maxLength="200"
-            android:autoLink="email|phone|web"
-            android:textColor="?android:attr/textColorSecondary" />
-    <TextView android:id="@+id/admins_policies_list"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:paddingTop="@dimen/admin_details_dialog_link_padding_top"
-            android:text="@string/admin_support_more_info"
-            android:textAppearance="@android:style/TextAppearance.Material.Subhead"
-            android:textColor="?android:attr/colorAccent"
-            android:clickable="true"
-            android:background="?android:attr/selectableItemBackground" />
-</merge>
\ No newline at end of file
diff --git a/res/layout/admin_support_details_dialog.xml b/res/layout/admin_support_details_dialog.xml
index c83add3..7de91d0 100644
--- a/res/layout/admin_support_details_dialog.xml
+++ b/res/layout/admin_support_details_dialog.xml
@@ -23,7 +23,7 @@
             android:layout_height="wrap_content"
             android:orientation="horizontal"
             android:gravity="center_vertical"
-            android:paddingBottom="@dimen/admin_details_dialog_padding">
+            android:paddingBottom="@dimen/admin_details_dialog_title_bottom_padding">
         <ImageView android:id="@+id/admin_support_icon"
                 android:layout_width="@dimen/admin_details_dialog_icon_size"
                 android:layout_height="@dimen/admin_details_dialog_icon_size"
@@ -46,7 +46,14 @@
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:orientation="vertical">
-            <include layout="@layout/admin_support_details_content" />
+            <TextView android:id="@+id/admin_support_msg"
+                      android:layout_width="match_parent"
+                      android:layout_height="wrap_content"
+                      android:textAppearance="@android:style/TextAppearance.Material.Subhead"
+                      android:text="@string/default_admin_support_msg"
+                      android:maxLength="200"
+                      android:autoLink="email|phone|web"
+                      android:textColor="?android:attr/textColorSecondary"/>
         </LinearLayout>
     </ScrollView>
 </LinearLayout>
diff --git a/res/layout/admin_support_details_empty_view.xml b/res/layout/admin_support_details_empty_view.xml
deleted file mode 100644
index bbbbbbc..0000000
--- a/res/layout/admin_support_details_empty_view.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<!-- Layout used for displaying admin support details in empty preference fragments. -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:id="@+id/admin_support_details"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:padding="@*android:dimen/preference_fragment_padding_side"
-        android:gravity="center_vertical"
-        android:orientation="vertical"
-        android:visibility="gone">
-    <include layout="@layout/admin_support_details_content" />
-</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/preference_list_fragment.xml b/res/layout/preference_list_fragment.xml
index b84aa38..eeea9c4 100644
--- a/res/layout/preference_list_fragment.xml
+++ b/res/layout/preference_list_fragment.xml
@@ -62,8 +62,6 @@
         android:gravity="center_vertical"
         android:visibility="gone" />
 
-    <include layout="@layout/admin_support_details_empty_view" />
-
     <RelativeLayout android:id="@+id/button_bar"
         android:layout_height="wrap_content"
         android:layout_width="match_parent"
diff --git a/res/layout/time_zone_search_item.xml b/res/layout/time_zone_search_item.xml
new file mode 100644
index 0000000..bb75226
--- /dev/null
+++ b/res/layout/time_zone_search_item.xml
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2018 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.
+-->
+<!-- similar to preference_material.xml but textview for emoji country flag
+instead of an ImageView -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="horizontal"
+    android:minHeight="?android:attr/listPreferredItemHeightSmall"
+    android:gravity="center_vertical"
+    android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
+    android:paddingRight="?android:attr/listPreferredItemPaddingRight"
+    android:background="?android:attr/selectableItemBackground"
+    android:clipToPadding="false">
+
+    <LinearLayout
+        android:id="@+id/icon_frame"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="-4dp"
+        android:minWidth="60dp"
+        android:gravity="start|center_vertical"
+        android:orientation="horizontal"
+        android:paddingRight="12dp"
+        android:paddingTop="4dp"
+        android:paddingBottom="4dp">
+        <!-- It's not ImageView because the icon is Unicode emoji. -->
+        <TextView
+            android:id="@+id/icon_text"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:singleLine="true"
+            android:contentDescription=""
+            android:textAppearance="?android:attr/textAppearanceLarge"
+            android:textColor="?android:attr/textColorPrimary"
+            android:importantForAccessibility="no"/>
+    </LinearLayout>
+
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:orientation="vertical"
+        android:paddingTop="16dp"
+        android:paddingBottom="16dp">
+
+        <TextView android:id="@android:id/title"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:singleLine="true"
+            android:textAppearance="@style/Preference_TextAppearanceMaterialSubhead"
+            android:ellipsize="marquee" />
+
+        <RelativeLayout
+            android:id="@+id/summary_frame"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_below="@android:id/title"
+            android:layout_alignLeft="@android:id/title">
+
+            <TextView
+                android:id="@+id/current_time"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textAppearance="?android:attr/textAppearanceSmall"
+                android:textColor="?android:attr/textColorSecondary"
+                android:layout_alignParentEnd="true"/>
+
+            <!-- Use layout_alignParentStart and layout_toStartOf to make the TextView multi-lines
+                if needed -->
+            <TextView
+                android:id="@android:id/summary"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textAppearance="?android:attr/textAppearanceSmall"
+                android:textColor="?android:attr/textColorSecondary"
+                android:maxLines="10"
+                android:layout_alignParentStart="true"
+                android:layout_toStartOf="@+id/current_time"/>
+
+        </RelativeLayout>
+
+    </LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/res/menu/time_zone_base_search_menu.xml b/res/menu/time_zone_base_search_menu.xml
new file mode 100644
index 0000000..92241af
--- /dev/null
+++ b/res/menu/time_zone_base_search_menu.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2018 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.
+-->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:id="@+id/time_zone_search_menu"
+        android:title="@string/search_settings"
+        android:icon="@*android:drawable/ic_search_api_material"
+        android:showAsAction="always|collapseActionView"
+        android:actionViewClass="android.widget.SearchView" />
+
+</menu>
\ No newline at end of file
diff --git a/res/values-en-rCA/arrays.xml b/res/values-en-rCA/arrays.xml
index 9546b09..fe5e71e 100644
--- a/res/values-en-rCA/arrays.xml
+++ b/res/values-en-rCA/arrays.xml
@@ -138,12 +138,14 @@
     <item msgid="477015974247590543">"1 hour"</item>
     <item msgid="5198271470953124739">"Never time out"</item>
   </string-array>
-    <!-- no translation found for bluetooth_max_connected_audio_devices:0 (834764606877643762) -->
-    <!-- no translation found for bluetooth_max_connected_audio_devices:1 (4428462068012149533) -->
-    <!-- no translation found for bluetooth_max_connected_audio_devices:2 (2620881722754455257) -->
-    <!-- no translation found for bluetooth_max_connected_audio_devices:3 (402831176731135702) -->
-    <!-- no translation found for bluetooth_max_connected_audio_devices:4 (4923580285404888038) -->
-    <!-- no translation found for bluetooth_max_connected_audio_devices:5 (3643103044864989283) -->
+  <string-array name="bluetooth_max_connected_audio_devices">
+    <item msgid="834764606877643762">"Use System Default: <xliff:g id="DEFAULT_BLUETOOTH_MAX_CONNECTED_AUDIO_DEVICES">%1$d</xliff:g>"</item>
+    <item msgid="4428462068012149533">"1"</item>
+    <item msgid="2620881722754455257">"2"</item>
+    <item msgid="402831176731135702">"3"</item>
+    <item msgid="4923580285404888038">"4"</item>
+    <item msgid="3643103044864989283">"5"</item>
+  </string-array>
   <string-array name="wifi_signal">
     <item msgid="2245412278046491293">"Poor"</item>
     <item msgid="2042505933058940139">"Poor"</item>
diff --git a/res/values-en-rCA/strings.xml b/res/values-en-rCA/strings.xml
index aa5af66..a3d5b54 100644
--- a/res/values-en-rCA/strings.xml
+++ b/res/values-en-rCA/strings.xml
@@ -291,10 +291,10 @@
     <string name="settings_label_launcher" msgid="8344735489639482340">"Settings"</string>
     <string name="settings_shortcut" msgid="3936651951364030415">"Settings shortcut"</string>
     <string name="activity_list_empty" msgid="6428823323471264836">"No matching activities found."</string>
-    <string name="airplane_mode" msgid="8837269988154128601">"Aeroplane mode"</string>
+    <string name="airplane_mode" msgid="8837269988154128601">"Airplane mode"</string>
     <string name="radio_controls_title" msgid="3447085191369779032">"More"</string>
     <string name="wireless_networks_settings_title" msgid="3643009077742794212">"Wireless &amp; networks"</string>
-    <string name="radio_controls_summary" msgid="1838624369870907268">"Manage Wi‑Fi, Bluetooth, aeroplane mode, mobile networks, &amp; VPNs"</string>
+    <string name="radio_controls_summary" msgid="1838624369870907268">"Manage Wi‑Fi, Bluetooth, airplane mode, mobile networks, &amp; VPNs"</string>
     <string name="cellular_data_title" msgid="6835451574385496662">"Mobile data"</string>
     <string name="calls_title" msgid="3544471959217176768">"Calls"</string>
     <string name="sms_messages_title" msgid="1778636286080572535">"SMS messages"</string>
@@ -750,7 +750,7 @@
     <string name="wifi_stopping" msgid="8952524572499500804">"Turning off Wi‑Fi…"</string>
     <string name="wifi_error" msgid="3207971103917128179">"Error"</string>
     <string name="wifi_sap_no_channel_error" msgid="3108445199311817111">"5 GHz band not available in this country"</string>
-    <string name="wifi_in_airplane_mode" msgid="8652520421778203796">"In aeroplane mode"</string>
+    <string name="wifi_in_airplane_mode" msgid="8652520421778203796">"In Airplane mode"</string>
     <string name="wifi_notify_open_networks" msgid="76298880708051981">"Open network notification"</string>
     <string name="wifi_notify_open_networks_summary" msgid="2761326999921366960">"Notify when a high‑quality public network is available"</string>
     <string name="wifi_wakeup" msgid="8815640989361538036">"Turn on Wi‑Fi automatically"</string>
@@ -925,7 +925,7 @@
     <string name="wifi_hotspot_configure_ap_text" msgid="5478614731464220432">"Wi‑Fi hotspot setup"</string>
     <string name="wifi_hotspot_configure_ap_text_summary" msgid="5560680057727007011">"AndroidAP WPA2 PSK hotspot"</string>
     <string name="wifi_tether_configure_ssid_default" msgid="8467525402622138547">"Android Hotspot"</string>
-    <string name="wifi_tether_disabled_by_airplane" msgid="414480185654767932">"Unavailable because aeroplane mode is turned on"</string>
+    <string name="wifi_tether_disabled_by_airplane" msgid="414480185654767932">"Unavailable because airplane mode is turned on"</string>
     <string name="wifi_calling_settings_title" msgid="4102921303993404577">"Wi-Fi Calling"</string>
     <string name="wifi_calling_suggestion_title" msgid="7766895085362824508">"Extend call coverage with Wi‑Fi"</string>
     <string name="wifi_calling_suggestion_summary" msgid="6460250990899143406">"Turn on Wi‑Fi calling"</string>
@@ -1443,8 +1443,7 @@
     <string name="managed_profile_location_switch_title" msgid="6712332547063039683">"Location for work profile"</string>
     <string name="location_app_level_permissions" msgid="1825588230817081339">"App-level permissions"</string>
     <string name="location_category_recent_location_requests" msgid="1938721350424447421">"Recent location requests"</string>
-    <!-- no translation found for location_recent_location_requests_see_all (9063541547120162593) -->
-    <skip />
+    <string name="location_recent_location_requests_see_all" msgid="9063541547120162593">"See all"</string>
     <string name="location_no_recent_apps" msgid="2800907699722178041">"No apps have requested location recently"</string>
     <string name="location_category_location_services" msgid="7437150886946685979">"Location services"</string>
     <string name="location_high_battery_use" msgid="517199943258508020">"High battery use"</string>
@@ -2160,7 +2159,7 @@
     <string name="battery_desc_standby" product="tablet" msgid="6284747418668280364">"Battery used when tablet is idle"</string>
     <string name="battery_desc_standby" product="default" msgid="3009080001948091424">"Battery used when phone is idle"</string>
     <string name="battery_desc_radio" msgid="5479196477223185367">"Battery used by mobile radio"</string>
-    <string name="battery_sugg_radio" msgid="8211336978326295047">"Switch to aeroplane mode to save power in areas with no mobile coverage"</string>
+    <string name="battery_sugg_radio" msgid="8211336978326295047">"Switch to airplane mode to save power in areas with no cell coverage"</string>
     <string name="battery_desc_flashlight" msgid="2908579430841025494">"Battery used by the flashlight"</string>
     <string name="battery_desc_camera" msgid="7375389919760613499">"Battery used by the camera"</string>
     <string name="battery_desc_display" msgid="5432795282958076557">"Battery used by the display and backlight"</string>
@@ -2317,8 +2316,7 @@
     <string name="credentials_configure_lock_screen_hint" msgid="8058230497337529036">"Before you can use credential storage, your device needs to have a secure lock screen"</string>
     <string name="credentials_configure_lock_screen_button" msgid="253239765216055321">"SET LOCK"</string>
     <string name="usage_access_title" msgid="332333405495457839">"Apps with usage access"</string>
-    <!-- no translation found for emergency_tone_title (254495218194925271) -->
-    <skip />
+    <string name="emergency_tone_title" msgid="254495218194925271">"Emergency dialling signal"</string>
     <string name="emergency_tone_summary" msgid="722259232924572153">"Set behaviour when an emergency call is placed"</string>
     <string name="privacy_settings_title" msgid="2978878794187459190">"Backup"</string>
     <string name="backup_section_title" msgid="7952232291452882740">"Backup &amp; restore"</string>
@@ -2927,12 +2925,9 @@
     <string name="dock_audio_media_title" msgid="1346838179626123900">"Dock speaker plays"</string>
     <string name="dock_audio_media_disabled" msgid="3430953622491538080">"All audio"</string>
     <string name="dock_audio_media_enabled" msgid="667849382924908673">"Media audio only"</string>
-    <!-- no translation found for emergency_tone_silent (3750231842974733677) -->
-    <skip />
-    <!-- no translation found for emergency_tone_alert (8523447641290736852) -->
-    <skip />
-    <!-- no translation found for emergency_tone_vibrate (2278872257053690683) -->
-    <skip />
+    <string name="emergency_tone_silent" msgid="3750231842974733677">"Silence"</string>
+    <string name="emergency_tone_alert" msgid="8523447641290736852">"Tones"</string>
+    <string name="emergency_tone_vibrate" msgid="2278872257053690683">"Vibrations"</string>
     <string name="boot_sounds_title" msgid="567029107382343709">"Power on sounds"</string>
     <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Never"</string>
     <plurals name="zen_mode_settings_summary_on" formatted="false" msgid="7346979080337117366">
@@ -3112,9 +3107,7 @@
     <string name="zen_mode_choose_rule_type" msgid="5423746638871953459">"Choose rule type"</string>
     <string name="zen_mode_delete_rule_confirmation" msgid="6237882294348570283">"Delete \"<xliff:g id="RULE">%1$s</xliff:g>\" rule?"</string>
     <string name="zen_mode_delete_rule_button" msgid="4248741120307752294">"Delete"</string>
-    <string name="zen_mode_rule_type" msgid="2289413469580142888">"Rule type"</string>
     <string name="zen_mode_rule_type_unknown" msgid="3049377282766700600">"Unknown"</string>
-    <string name="zen_mode_configure_rule" msgid="8865785428056490305">"Configure rule"</string>
     <string name="zen_mode_app_set_behavior" msgid="1534429320064381355">"These settings can\'t be changed at the moment. An app (<xliff:g id="APP_NAME">%1$s</xliff:g>) has automatically turned on Do Not Disturb with custom behaviour."</string>
     <string name="zen_mode_unknown_app_set_behavior" msgid="2558968232814237874">"These settings can\'t be changed at the moment. An app has automatically turned on Do Not Disturb with custom behaviour."</string>
     <string name="zen_mode_qs_set_behavior" msgid="6200424436456086312">"These settings can\'t be changed at the moment. Do Not Disturb was manually turned on with custom behaviour."</string>
@@ -3512,7 +3505,7 @@
     <string name="condition_expand_hide" msgid="948507739223760667">"Hide"</string>
     <string name="condition_hotspot_title" msgid="7778958849468560027">"Hotspot is on"</string>
     <string name="condition_hotspot_summary" msgid="3433182779269409683">"Portable Wi-Fi hotspot <xliff:g id="ID_1">%1$s</xliff:g> is active, Wi-Fi for this device is turned off."</string>
-    <string name="condition_airplane_title" msgid="287356299107070503">"Aeroplane mode is on"</string>
+    <string name="condition_airplane_title" msgid="287356299107070503">"Airplane mode is on"</string>
     <string name="condition_airplane_summary" msgid="3738805058182535606">"Wi-Fi, Bluetooth and mobile network are turned off. You can\'t make phone calls or connect to the Internet."</string>
     <string name="condition_zen_title" msgid="2897779738211625">"Do Not Disturb is on"</string>
     <string name="condition_battery_title" msgid="3272131008388575349">"Battery Saver is on"</string>
@@ -3863,14 +3856,9 @@
     <string name="bluetooth_on_while_driving_pref" msgid="2460847604498343330">"Use Bluetooth when driving"</string>
     <string name="bluetooth_on_while_driving_summary" msgid="3196190732516898541">"Turn on Bluetooth automatically when driving"</string>
     <string name="dev_android_o_battery_settings_title" msgid="2926578228655006762">"See Android 8.0 battery settings"</string>
-    <!-- no translation found for change_wifi_state_title (2640523995824431999) -->
-    <skip />
-    <!-- no translation found for keywords_change_wifi_state (1439807171750715923) -->
-    <skip />
-    <!-- no translation found for change_wifi_state_app_detail_title (1022360625069880993) -->
-    <skip />
-    <!-- no translation found for change_wifi_state_app_detail_switch (724818064600933957) -->
-    <skip />
-    <!-- no translation found for change_wifi_state_app_detail_summary (2511212187129042304) -->
-    <skip />
+    <string name="change_wifi_state_title" msgid="2640523995824431999">"Toggle Wi-Fi on and off"</string>
+    <string name="keywords_change_wifi_state" msgid="1439807171750715923">"toggle Wi-Fi on and off"</string>
+    <string name="change_wifi_state_app_detail_title" msgid="1022360625069880993">"Toggle Wi-Fi on and off"</string>
+    <string name="change_wifi_state_app_detail_switch" msgid="724818064600933957">"Allow toggle Wi-Fi"</string>
+    <string name="change_wifi_state_app_detail_summary" msgid="2511212187129042304">"Allow this app to change Wi-Fi state including connecting to Wi-Fi and turing Wi-Fi on and off."</string>
 </resources>
diff --git a/res/values-en-rXC/arrays.xml b/res/values-en-rXC/arrays.xml
index a04f1ad..3dfcf58 100644
--- a/res/values-en-rXC/arrays.xml
+++ b/res/values-en-rXC/arrays.xml
@@ -138,12 +138,14 @@
     <item msgid="477015974247590543">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‏‏‏‎‏‎‎‏‏‏‏‎‏‎‏‏‎‎‏‏‏‎‎‎‎‎‎‎‎‏‎‏‎‎‎‏‎‎‏‏‎‏‏‎‏‏‏‎‏‎‏‎‏‎‎‎‏‏‏‏‎1 hour‎‏‎‎‏‎"</item>
     <item msgid="5198271470953124739">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‎‎‎‎‎‏‎‎‎‏‏‏‏‏‏‏‎‎‎‎‏‎‏‏‏‎‎‎‏‏‏‏‎‎‎‎‎‏‏‎‏‎‏‎‏‎‏‎‎‏‏‏‎‎‎‎‎‏‏‎Never time out‎‏‎‎‏‎"</item>
   </string-array>
-    <!-- no translation found for bluetooth_max_connected_audio_devices:0 (834764606877643762) -->
-    <!-- no translation found for bluetooth_max_connected_audio_devices:1 (4428462068012149533) -->
-    <!-- no translation found for bluetooth_max_connected_audio_devices:2 (2620881722754455257) -->
-    <!-- no translation found for bluetooth_max_connected_audio_devices:3 (402831176731135702) -->
-    <!-- no translation found for bluetooth_max_connected_audio_devices:4 (4923580285404888038) -->
-    <!-- no translation found for bluetooth_max_connected_audio_devices:5 (3643103044864989283) -->
+  <string-array name="bluetooth_max_connected_audio_devices">
+    <item msgid="834764606877643762">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‎‏‏‏‎‎‏‎‏‎‏‏‎‏‎‏‏‎‏‏‏‏‏‏‏‎‎‏‎‏‏‏‎‎‎‎‎‎‎‎‎‏‎‏‎‏‏‎‎‏‏‏‏‏‏‎‎‏‎‎Use System Default: ‎‏‎‎‏‏‎<xliff:g id="DEFAULT_BLUETOOTH_MAX_CONNECTED_AUDIO_DEVICES">%1$d</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</item>
+    <item msgid="4428462068012149533">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‏‎‏‎‏‏‏‎‏‎‏‎‎‎‎‏‏‏‎‏‏‎‎‏‎‎‏‏‎‏‏‎‎‎‏‎‎‏‎‎‏‏‏‏‏‏‎‏‎‏‏‎‎‎‏‏‏‎‏‎1‎‏‎‎‏‎"</item>
+    <item msgid="2620881722754455257">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‎‏‏‏‏‏‎‎‎‎‎‏‎‏‎‎‏‏‏‎‎‏‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‏‎‏‏‎‏‏‎‎‏‎2‎‏‎‎‏‎"</item>
+    <item msgid="402831176731135702">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‏‏‎‏‏‎‎‏‎‏‏‏‎‎‏‎‎‏‎‎‏‏‎‏‎‎‏‎‎‎‏‎‏‎‎‏‏‎‎‎‎‎‏‏‎‎‎‎‏‏‏‎‏‏‎‏‎‏‏‎‎3‎‏‎‎‏‎"</item>
+    <item msgid="4923580285404888038">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‏‎‎‎‏‎‏‎‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‏‏‎‏‏‏‎‏‎‏‎‏‏‎‎‏‎‏‏‏‎‏‏‏‏‏‎‎‏‏‎‎4‎‏‎‎‏‎"</item>
+    <item msgid="3643103044864989283">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‎‏‎‏‎‎‎‏‏‏‎‏‏‏‎‎‏‏‎‏‏‏‎‏‎‏‎‏‏‎‏‎‏‎‏‎‏‎‏‎‎‏‎‎‏‎‏‏‎‎‎‎‏‏‎‎‎‏‏‎5‎‏‎‎‏‎"</item>
+  </string-array>
   <string-array name="wifi_signal">
     <item msgid="2245412278046491293">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‏‏‏‎‎‏‎‏‎‎‏‎‏‎‎‏‏‏‎‏‎‎‏‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‎‎‎‏‏‎‎‎‎‎‎‏‎‏‎‎‏‏‏‎‏‎Poor‎‏‎‎‏‎"</item>
     <item msgid="2042505933058940139">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‏‎‎‎‏‎‏‏‎‎‎‎‏‏‏‎‎‎‎‎‏‎‏‎‎‏‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‏‏‎‎‎‏‏‏‎‎‏‏‏‎‏‎‏‏‎Poor‎‏‎‎‏‎"</item>
diff --git a/res/values-en-rXC/strings.xml b/res/values-en-rXC/strings.xml
index 0c46a91..3568cbf 100644
--- a/res/values-en-rXC/strings.xml
+++ b/res/values-en-rXC/strings.xml
@@ -1442,8 +1442,7 @@
     <string name="managed_profile_location_switch_title" msgid="6712332547063039683">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‏‎‏‎‎‏‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‏‎‎‎‏‏‎‏‎‏‏‎‎‏‏‏‏‏‏‏‎‎‎‏‎‎‎‏‏‎‏‏‎‎‎‎‏‏‎Location for work profile‎‏‎‎‏‎"</string>
     <string name="location_app_level_permissions" msgid="1825588230817081339">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‎‎‏‎‏‎‏‎‏‎‏‏‏‎‎‏‎‏‎‏‏‎‏‎‎‏‎‏‏‎‏‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‏‏‏‏‏‏‏‏‎‏‏‎App-level permissions‎‏‎‎‏‎"</string>
     <string name="location_category_recent_location_requests" msgid="1938721350424447421">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‎‏‎‏‏‏‎‎‏‏‏‏‎‏‏‏‎‎‎‏‏‎‎‏‎‏‏‏‏‏‎‎‎‏‎‏‎‎‎‎‎‏‏‏‏‎‎‏‎‎‏‏‎‏‏‏‏‎‏‎Recent location requests‎‏‎‎‏‎"</string>
-    <!-- no translation found for location_recent_location_requests_see_all (9063541547120162593) -->
-    <skip />
+    <string name="location_recent_location_requests_see_all" msgid="9063541547120162593">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‎‎‎‎‎‏‎‏‎‏‏‎‎‎‎‎‏‎‎‎‎‏‏‎‎‏‏‎‎‎‏‎‏‏‏‎‏‏‏‎‏‏‏‎‎‏‎‎‎‎‏‎See all‎‏‎‎‏‎"</string>
     <string name="location_no_recent_apps" msgid="2800907699722178041">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‏‎‏‏‎‏‏‏‏‎‏‏‎‏‎‎‏‎‏‎‏‏‎‏‏‎‏‎‎‎‏‎‏‎‏‎‎‏‏‎‎‎‏‏‎‎‏‏‎‏‏‏‏‏‏‎‎‏‎No apps have requested location recently‎‏‎‎‏‎"</string>
     <string name="location_category_location_services" msgid="7437150886946685979">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‏‎‏‏‎‎‎‎‏‎‎‎‏‎‏‎‏‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‏‎‎‎‎‎‏‏‎‏‏‎Location services‎‏‎‎‏‎"</string>
     <string name="location_high_battery_use" msgid="517199943258508020">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‏‏‏‏‎‎‏‎‏‏‎‏‎‏‏‏‎‏‏‎‏‎‎‏‏‎‏‏‏‎‏‎‏‏‏‏‏‏‎‎‎‏‏‎‏‎‎‎‏‎‏‎‏‏‏‏‎‏‎‎‎High battery use‎‏‎‎‏‎"</string>
@@ -2316,8 +2315,7 @@
     <string name="credentials_configure_lock_screen_hint" msgid="8058230497337529036">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‏‎‏‎‏‎‎‏‎‎‏‎‏‎‏‏‏‏‏‎‎‎‏‎‏‏‎‏‎‎‎‎‎‎‎‎‏‎‏‏‏‎‏‎‎‏‎‏‏‎‎‏‏‎‎‎Before you can use credential storage, your device need to have a secure lock screen‎‏‎‎‏‎"</string>
     <string name="credentials_configure_lock_screen_button" msgid="253239765216055321">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‎‏‏‏‎‎‎‎‎‏‏‏‎‏‏‎‎‎‎‎‎‏‏‏‎‎‏‏‎‎‎‏‎‎‎‏‎‏‏‎‏‎‎‏‏‎‏‎‎‎‎‎‎‎‏‏‎‎‏‎SET LOCK‎‏‎‎‏‎"</string>
     <string name="usage_access_title" msgid="332333405495457839">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‏‏‎‎‏‎‎‏‏‏‎‎‏‎‏‎‏‏‏‏‎‏‏‏‏‎‎‎‏‎‏‏‎‏‎‏‏‎‎‎‏‏‎‏‎‏‏‏‏‎‎‎‎‎‏‎‏‏‏‏‎Apps with usage access‎‏‎‎‏‎"</string>
-    <!-- no translation found for emergency_tone_title (254495218194925271) -->
-    <skip />
+    <string name="emergency_tone_title" msgid="254495218194925271">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‎‏‏‏‎‎‎‏‎‎‎‎‎‏‎‎‏‏‎‎‎‎‎‏‏‎‏‎‏‏‏‎‏‎‏‏‎‎‎‏‎‏‏‎‏‎‎‎‏‏‎‏‏‎‏‎‏‏‏‎Emergency dialing signal‎‏‎‎‏‎"</string>
     <string name="emergency_tone_summary" msgid="722259232924572153">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‎‏‎‎‎‎‎‎‏‎‏‏‏‏‏‏‎‏‎‏‏‏‏‎‎‏‎‎‎‎‏‎‏‏‎‎‎‏‏‎‏‏‏‎‎‎‏‏‎‎‏‏‏‏‏‏‎‎‏‎Set behavior when an emergency call is placed‎‏‎‎‏‎"</string>
     <string name="privacy_settings_title" msgid="2978878794187459190">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‎‎‏‎‏‎‏‎‏‏‏‎‎‎‏‏‎‏‎‎‏‏‏‏‎‏‏‎‎‎‎‎‏‎‎‎‏‏‏‏‏‎‎‏‏‎‎‏‎‏‎‎‏‏‏‎‏‏‎‎Backup‎‏‎‎‏‎"</string>
     <string name="backup_section_title" msgid="7952232291452882740">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‎‏‏‏‎‎‎‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‎‏‏‏‎‏‏‏‎‎‎‎‏‎‎‎‏‏‏‏‎‎‏‏‎‏‎‎‎Backup &amp; restore‎‏‎‎‏‎"</string>
@@ -2926,12 +2924,9 @@
     <string name="dock_audio_media_title" msgid="1346838179626123900">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎‏‎‏‎‏‏‎‎‎‎‏‏‏‎‏‏‏‎‎‎‏‏‎‎‎‎‎‏‎‎‎‎‏‎‏‎‎‎‏‏‎‎‏‎‎‎‎‎‏‎‎‏‏‏‏‏‎‎‎Dock speaker plays‎‏‎‎‏‎"</string>
     <string name="dock_audio_media_disabled" msgid="3430953622491538080">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‏‏‏‏‎‎‏‏‏‎‏‎‎‏‏‎‎‏‎‎‎‏‎‎‏‎‎‎‏‎‎‎‏‎‏‎‏‏‏‎‎‏‎‏‎‏‎‎‎‏‎‏‎‏‎‎‎‎‎‎All audio‎‏‎‎‏‎"</string>
     <string name="dock_audio_media_enabled" msgid="667849382924908673">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‎‎‏‎‏‎‎‎‏‎‎‏‎‏‎‏‏‎‏‎‏‏‏‏‎‎‏‏‎‏‏‎‎‎‎‏‎‏‏‎‎‏‏‏‏‏‏‏‎‎‎‏‎‎‎‎‎‎‏‎Media audio only‎‏‎‎‏‎"</string>
-    <!-- no translation found for emergency_tone_silent (3750231842974733677) -->
-    <skip />
-    <!-- no translation found for emergency_tone_alert (8523447641290736852) -->
-    <skip />
-    <!-- no translation found for emergency_tone_vibrate (2278872257053690683) -->
-    <skip />
+    <string name="emergency_tone_silent" msgid="3750231842974733677">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‏‎‎‎‎‎‎‏‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‏‎‎‏‏‏‎‏‏‏‏‎‎‎‎‏‎‏‎‏‎‏‏‎‏‏‎‏‎Silence‎‏‎‎‏‎"</string>
+    <string name="emergency_tone_alert" msgid="8523447641290736852">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‎‎‏‎‎‏‎‏‎‏‏‏‏‎‎‏‏‏‏‎‎‎‎‏‏‏‏‎‎‎‏‏‎‎‎‏‏‎‏‎‎‎‎‏‎‎‏‏‎‏‎‏‎‎‎Tones‎‏‎‎‏‎"</string>
+    <string name="emergency_tone_vibrate" msgid="2278872257053690683">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‏‏‏‏‎‏‎‎‎‎‎‎‎‏‎‏‏‏‎‎‎‏‏‏‏‏‎‎‏‏‎‏‎‏‎‎‎‏‎‏‏‎‏‏‎‎‎‏‎‏‏‎‎‏‏‏‎‏‏‎Vibrations‎‏‎‎‏‎"</string>
     <string name="boot_sounds_title" msgid="567029107382343709">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‏‏‏‏‏‏‎‏‏‏‏‎‎‏‏‏‏‏‎‏‏‏‏‏‏‎‎‎‎‎‎‎‏‎‏‎‏‏‎‏‎‏‎‎‏‏‎‏‏‎‎‎‎‎‎‏‏‏‎‏‎Power on sounds‎‏‎‎‏‎"</string>
     <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‏‎‎‏‏‏‎‏‏‏‎‎‎‏‏‏‎‎‎‏‏‎‏‏‎‎‎‎‏‎‏‎‎‎‏‏‎‏‏‎‏‏‎‏‏‎‏‏‏‏‏‎‎‏‏‎‏‏‎‎Never‎‏‎‎‏‎"</string>
     <plurals name="zen_mode_settings_summary_on" formatted="false" msgid="7346979080337117366">
@@ -3111,9 +3106,7 @@
     <string name="zen_mode_choose_rule_type" msgid="5423746638871953459">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‎‏‏‎‏‎‎‎‏‎‏‎‎‎‎‎‏‎‎‏‏‎‏‎‏‎‎‏‏‏‏‎‎‎‏‏‎‏‎‏‏‏‎‏‎‎‎‎‎‎‎‎‎‏‏‎‎‏‏‎Choose rule type‎‏‎‎‏‎"</string>
     <string name="zen_mode_delete_rule_confirmation" msgid="6237882294348570283">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‏‎‎‎‏‎‏‏‎‏‎‎‎‏‏‏‎‎‏‎‏‏‎‏‎‎‎‎‏‎‏‎‏‏‎‎‎‎‏‎‏‏‏‏‎‏‎‏‎‏‎‏‏‎Delete “‎‏‎‎‏‏‎<xliff:g id="RULE">%1$s</xliff:g>‎‏‎‎‏‏‏‎” rule?‎‏‎‎‏‎"</string>
     <string name="zen_mode_delete_rule_button" msgid="4248741120307752294">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‏‎‏‏‏‏‎‏‏‎‏‎‎‎‏‏‏‏‏‎‎‎‏‎‎‏‏‏‎‎‎‎‏‎‏‎‎‎‏‎‎‏‏‏‏‎‏‏‎‏‎‏‏‎‎‏‏‎‎Delete‎‏‎‎‏‎"</string>
-    <string name="zen_mode_rule_type" msgid="2289413469580142888">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‏‎‏‎‎‎‎‏‎‏‏‎‏‎‏‏‏‎‏‏‎‏‏‎‎‏‎‏‎‎‎‏‏‎‏‎‏‎‎‏‎‎‏‎‏‎‎‎‎Rule type‎‏‎‎‏‎"</string>
     <string name="zen_mode_rule_type_unknown" msgid="3049377282766700600">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‎‏‎‎‏‎‏‎‎‎‏‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‏‎‏‏‏‏‏‎‏‎‏‏‏‎‏‎‎‏‎‎‎‎‎‎‎‎‎‏‏‏‎‎‎‎Unknown‎‏‎‎‏‎"</string>
-    <string name="zen_mode_configure_rule" msgid="8865785428056490305">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‏‎‎‏‏‎‎‏‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‎‏‏‎‎‎‏‎‎‏‎‎‎‏‎‎‎‎‎‏‎‏‎‎‎‎‎‏‎Configure rule‎‏‎‎‏‎"</string>
     <string name="zen_mode_app_set_behavior" msgid="1534429320064381355">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‏‎‏‎‏‎‎‏‎‏‏‎‏‏‎‎‎‏‏‎‏‎‏‎‏‏‎‎‎‏‏‏‎‏‏‎‏‏‎‎‎‎‏‏‎‏‏‎‎‎‏‏‎‏‎‏‎‏‏‎These settings can\'t be changed right now. An app (‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎) has automatically turned on Do Not Disturb with custom behavior.‎‏‎‎‏‎"</string>
     <string name="zen_mode_unknown_app_set_behavior" msgid="2558968232814237874">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‏‏‏‎‎‎‎‎‏‏‎‏‎‎‏‎‎‎‎‎‎‎‏‏‎‎‏‎‏‏‏‏‎‎‎‏‏‎‎‏‏‎‏‏‎‏‏‎‎‎‏‎‏‏‎‎‏‎‎These settings can\'t be changed right now. An app has automatically turned on Do Not Disturb with custom behavior.‎‏‎‎‏‎"</string>
     <string name="zen_mode_qs_set_behavior" msgid="6200424436456086312">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‏‏‎‎‎‎‎‏‏‎‎‎‏‎‏‎‏‎‏‎‎‏‎‏‏‎‎‎‏‏‏‎‏‏‏‏‎‎‏‏‏‎‏‏‏‎‏‏‎‏‏‎‎‏‎‏‎‎‎‎These settings can\'t be changed right now. Do Not Disturb was manually turned on with custom behavior.‎‏‎‎‏‎"</string>
@@ -3862,14 +3855,9 @@
     <string name="bluetooth_on_while_driving_pref" msgid="2460847604498343330">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‏‎‎‎‏‎‎‏‏‎‏‎‏‎‏‏‏‏‏‏‎‏‏‎‏‏‏‎‏‏‎‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‏‎‏‏‎‏‎‎‎‏‎‎Use Bluetooth when driving‎‏‎‎‏‎"</string>
     <string name="bluetooth_on_while_driving_summary" msgid="3196190732516898541">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‏‎‎‎‏‎‏‏‎‏‏‎‎‏‎‎‏‏‎‏‎‎‎‏‎‎‏‎‏‏‏‏‏‏‎‎‎‎‏‎‎‎‎‏‎‏‏‎‏‏‎‏‏‏‎‏‏‎‏‎Turn on Bluetooth automatically when driving‎‏‎‎‏‎"</string>
     <string name="dev_android_o_battery_settings_title" msgid="2926578228655006762">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‎‎‎‏‎‎‏‏‏‎‏‎‏‎‎‏‎‏‏‎‏‏‎‎‏‎‎‏‎‏‎‏‏‏‎‎‏‎‏‏‏‏‏‏‎‏‎‎‏‎‎‎‎‏‎‏‎‏‎‎See Android 8.0 battery settings‎‏‎‎‏‎"</string>
-    <!-- no translation found for change_wifi_state_title (2640523995824431999) -->
-    <skip />
-    <!-- no translation found for keywords_change_wifi_state (1439807171750715923) -->
-    <skip />
-    <!-- no translation found for change_wifi_state_app_detail_title (1022360625069880993) -->
-    <skip />
-    <!-- no translation found for change_wifi_state_app_detail_switch (724818064600933957) -->
-    <skip />
-    <!-- no translation found for change_wifi_state_app_detail_summary (2511212187129042304) -->
-    <skip />
+    <string name="change_wifi_state_title" msgid="2640523995824431999">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‎‎‏‎‏‎‎‏‎‏‎‎‎‎‎‏‏‎‏‎‎‏‎‏‎‏‏‎‎‎‏‎‎‎‎‎‎‎‎‎‏‎‏‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎Toggle wifi on and off‎‏‎‎‏‎"</string>
+    <string name="keywords_change_wifi_state" msgid="1439807171750715923">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎‏‏‏‏‏‏‏‎‏‏‎‎‏‏‏‎‎‎‏‏‏‏‏‏‏‎‏‎‎‎‏‎‎‏‎‏‎‎‎‎‏‎‏‏‏‎‎‎‏‎‎‎‎‏‎‎‏‏‎toggle wifi on and off‎‏‎‎‏‎"</string>
+    <string name="change_wifi_state_app_detail_title" msgid="1022360625069880993">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‏‏‎‎‎‏‏‎‎‎‎‎‎‏‎‎‏‏‏‏‎‎‏‎‎‏‎‎‏‏‎‎‎‎‏‏‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‏‎‏‎‎‎‎‏‎Toggle wifi on and off‎‏‎‎‏‎"</string>
+    <string name="change_wifi_state_app_detail_switch" msgid="724818064600933957">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‎‏‎‎‎‎‎‏‏‏‏‎‎‎‏‎‎‏‎‎‎‏‏‎‎‎‎‏‎‎‎‎‎‏‏‎‏‎‏‎‎‏‏‎‎‏‎‎‏‏‎‎‏‎‎‎‏‎‏‎Allow toggle wifi‎‏‎‎‏‎"</string>
+    <string name="change_wifi_state_app_detail_summary" msgid="2511212187129042304">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‏‎‏‏‎‏‏‎‎‏‏‎‎‏‏‏‏‎‎‎‏‎‏‏‎‏‏‏‏‎‎‎‎‏‎‏‏‏‎‏‎‏‎‏‎‏‎‏‎‏‏‎‎‎‎‎‎‎‎Allow this app to change wifi state including connecting to wifi and turing wifi on and off.‎‏‎‎‏‎"</string>
 </resources>
diff --git a/res/values-fr/arrays.xml b/res/values-fr/arrays.xml
index ca1ae44..fbe981d 100644
--- a/res/values-fr/arrays.xml
+++ b/res/values-fr/arrays.xml
@@ -138,12 +138,14 @@
     <item msgid="477015974247590543">"Une heure"</item>
     <item msgid="5198271470953124739">"Aucun délai"</item>
   </string-array>
-    <!-- no translation found for bluetooth_max_connected_audio_devices:0 (834764606877643762) -->
-    <!-- no translation found for bluetooth_max_connected_audio_devices:1 (4428462068012149533) -->
-    <!-- no translation found for bluetooth_max_connected_audio_devices:2 (2620881722754455257) -->
-    <!-- no translation found for bluetooth_max_connected_audio_devices:3 (402831176731135702) -->
-    <!-- no translation found for bluetooth_max_connected_audio_devices:4 (4923580285404888038) -->
-    <!-- no translation found for bluetooth_max_connected_audio_devices:5 (3643103044864989283) -->
+  <string-array name="bluetooth_max_connected_audio_devices">
+    <item msgid="834764606877643762">"Utiliser la valeur par défaut du système : <xliff:g id="DEFAULT_BLUETOOTH_MAX_CONNECTED_AUDIO_DEVICES">%1$d</xliff:g>"</item>
+    <item msgid="4428462068012149533">"1"</item>
+    <item msgid="2620881722754455257">"2"</item>
+    <item msgid="402831176731135702">"3"</item>
+    <item msgid="4923580285404888038">"4"</item>
+    <item msgid="3643103044864989283">"5"</item>
+  </string-array>
   <string-array name="wifi_signal">
     <item msgid="2245412278046491293">"Faible"</item>
     <item msgid="2042505933058940139">"Faible"</item>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index 0bf750e..68c374c 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -1443,8 +1443,7 @@
     <string name="managed_profile_location_switch_title" msgid="6712332547063039683">"Emplacement du profil pro"</string>
     <string name="location_app_level_permissions" msgid="1825588230817081339">"Autorisations au niveau applis"</string>
     <string name="location_category_recent_location_requests" msgid="1938721350424447421">"Demandes de localisation récentes"</string>
-    <!-- no translation found for location_recent_location_requests_see_all (9063541547120162593) -->
-    <skip />
+    <string name="location_recent_location_requests_see_all" msgid="9063541547120162593">"Tout afficher"</string>
     <string name="location_no_recent_apps" msgid="2800907699722178041">"Aucune demande d\'accès à votre position n\'a récemment été envoyée pour une application."</string>
     <string name="location_category_location_services" msgid="7437150886946685979">"Services de localisation"</string>
     <string name="location_high_battery_use" msgid="517199943258508020">"Forte utilisation de la batterie"</string>
@@ -2317,8 +2316,7 @@
     <string name="credentials_configure_lock_screen_hint" msgid="8058230497337529036">"Avant de pouvoir utiliser le stockage des identifiants, vous devez définir un écran de verrouillage sécurisé sur votre appareil"</string>
     <string name="credentials_configure_lock_screen_button" msgid="253239765216055321">"DÉFINIR VERROUILLAGE"</string>
     <string name="usage_access_title" msgid="332333405495457839">"Applis accédant aux infos utilisation"</string>
-    <!-- no translation found for emergency_tone_title (254495218194925271) -->
-    <skip />
+    <string name="emergency_tone_title" msgid="254495218194925271">"Signal de numérotation d\'urgence"</string>
     <string name="emergency_tone_summary" msgid="722259232924572153">"Définir le comportement en cas d\'appel d\'urgence"</string>
     <string name="privacy_settings_title" msgid="2978878794187459190">"Sauvegarde"</string>
     <string name="backup_section_title" msgid="7952232291452882740">"Sauvegarde et restauration"</string>
@@ -2927,12 +2925,9 @@
     <string name="dock_audio_media_title" msgid="1346838179626123900">"Sons haut-parleurs sta. accueil"</string>
     <string name="dock_audio_media_disabled" msgid="3430953622491538080">"Tout l\'audio"</string>
     <string name="dock_audio_media_enabled" msgid="667849382924908673">"Audio des contenus multimédias seulement"</string>
-    <!-- no translation found for emergency_tone_silent (3750231842974733677) -->
-    <skip />
-    <!-- no translation found for emergency_tone_alert (8523447641290736852) -->
-    <skip />
-    <!-- no translation found for emergency_tone_vibrate (2278872257053690683) -->
-    <skip />
+    <string name="emergency_tone_silent" msgid="3750231842974733677">"Silence"</string>
+    <string name="emergency_tone_alert" msgid="8523447641290736852">"Tonalités"</string>
+    <string name="emergency_tone_vibrate" msgid="2278872257053690683">"Vibrations"</string>
     <string name="boot_sounds_title" msgid="567029107382343709">"Sons de mise en route"</string>
     <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Jamais"</string>
     <plurals name="zen_mode_settings_summary_on" formatted="false" msgid="7346979080337117366">
@@ -3112,9 +3107,7 @@
     <string name="zen_mode_choose_rule_type" msgid="5423746638871953459">"Sélectionner le type de règle"</string>
     <string name="zen_mode_delete_rule_confirmation" msgid="6237882294348570283">"Supprimer la règle \"<xliff:g id="RULE">%1$s</xliff:g>\" ?"</string>
     <string name="zen_mode_delete_rule_button" msgid="4248741120307752294">"Supprimer"</string>
-    <string name="zen_mode_rule_type" msgid="2289413469580142888">"Type de règle"</string>
     <string name="zen_mode_rule_type_unknown" msgid="3049377282766700600">"Inconnu"</string>
-    <string name="zen_mode_configure_rule" msgid="8865785428056490305">"Configurer une règle"</string>
     <string name="zen_mode_app_set_behavior" msgid="1534429320064381355">"Vous ne pouvez pas modifier ces paramètres pour le moment. Une application (<xliff:g id="APP_NAME">%1$s</xliff:g>) a activé le mode Ne pas déranger automatiquement avec un comportement personnalisé."</string>
     <string name="zen_mode_unknown_app_set_behavior" msgid="2558968232814237874">"Vous ne pouvez pas modifier ces paramètres pour le moment. Une application a activé le mode Ne pas déranger automatiquement avec un comportement personnalisé."</string>
     <string name="zen_mode_qs_set_behavior" msgid="6200424436456086312">"Vous ne pouvez pas modifier ces paramètres pour le moment. Le mode Ne pas déranger a été activé automatiquement avec un comportement personnalisé."</string>
@@ -3863,14 +3856,9 @@
     <string name="bluetooth_on_while_driving_pref" msgid="2460847604498343330">"Utiliser le Bluetooth en conduisant"</string>
     <string name="bluetooth_on_while_driving_summary" msgid="3196190732516898541">"Activer automatiquement le Bluetooth lorsque vous conduisez"</string>
     <string name="dev_android_o_battery_settings_title" msgid="2926578228655006762">"Afficher les paramètres de batterie d\'Android 8.0"</string>
-    <!-- no translation found for change_wifi_state_title (2640523995824431999) -->
-    <skip />
-    <!-- no translation found for keywords_change_wifi_state (1439807171750715923) -->
-    <skip />
-    <!-- no translation found for change_wifi_state_app_detail_title (1022360625069880993) -->
-    <skip />
-    <!-- no translation found for change_wifi_state_app_detail_switch (724818064600933957) -->
-    <skip />
-    <!-- no translation found for change_wifi_state_app_detail_summary (2511212187129042304) -->
-    <skip />
+    <string name="change_wifi_state_title" msgid="2640523995824431999">"Activer/Désactiver le Wi-Fi"</string>
+    <string name="keywords_change_wifi_state" msgid="1439807171750715923">"activer/désactiver le Wi-Fi"</string>
+    <string name="change_wifi_state_app_detail_title" msgid="1022360625069880993">"Activer/Désactiver le Wi-Fi"</string>
+    <string name="change_wifi_state_app_detail_switch" msgid="724818064600933957">"Autoriser l\'activation et la désactivation du Wi-Fi"</string>
+    <string name="change_wifi_state_app_detail_summary" msgid="2511212187129042304">"Autoriser cette application à modifier l\'état du Wi-Fi, y compris la connexion au Wi-Fi, ainsi que l\'activation et la désactivation de ce dernier"</string>
 </resources>
diff --git a/res/values-pt-rBR/arrays.xml b/res/values-pt-rBR/arrays.xml
index 72ec75e..55420eb 100644
--- a/res/values-pt-rBR/arrays.xml
+++ b/res/values-pt-rBR/arrays.xml
@@ -138,12 +138,14 @@
     <item msgid="477015974247590543">"Uma hora"</item>
     <item msgid="5198271470953124739">"Nunca definir tempo limite"</item>
   </string-array>
-    <!-- no translation found for bluetooth_max_connected_audio_devices:0 (834764606877643762) -->
-    <!-- no translation found for bluetooth_max_connected_audio_devices:1 (4428462068012149533) -->
-    <!-- no translation found for bluetooth_max_connected_audio_devices:2 (2620881722754455257) -->
-    <!-- no translation found for bluetooth_max_connected_audio_devices:3 (402831176731135702) -->
-    <!-- no translation found for bluetooth_max_connected_audio_devices:4 (4923580285404888038) -->
-    <!-- no translation found for bluetooth_max_connected_audio_devices:5 (3643103044864989283) -->
+  <string-array name="bluetooth_max_connected_audio_devices">
+    <item msgid="834764606877643762">"Usar padrão do sistema: <xliff:g id="DEFAULT_BLUETOOTH_MAX_CONNECTED_AUDIO_DEVICES">%1$d</xliff:g>"</item>
+    <item msgid="4428462068012149533">"1"</item>
+    <item msgid="2620881722754455257">"2"</item>
+    <item msgid="402831176731135702">"3"</item>
+    <item msgid="4923580285404888038">"4"</item>
+    <item msgid="3643103044864989283">"5"</item>
+  </string-array>
   <string-array name="wifi_signal">
     <item msgid="2245412278046491293">"Ruim"</item>
     <item msgid="2042505933058940139">"Fraca"</item>
diff --git a/res/values-pt-rBR/strings.xml b/res/values-pt-rBR/strings.xml
index a437cce..eea65f4 100644
--- a/res/values-pt-rBR/strings.xml
+++ b/res/values-pt-rBR/strings.xml
@@ -1443,8 +1443,7 @@
     <string name="managed_profile_location_switch_title" msgid="6712332547063039683">"Local do perfil de trabalho"</string>
     <string name="location_app_level_permissions" msgid="1825588230817081339">"Permissões no nível do app"</string>
     <string name="location_category_recent_location_requests" msgid="1938721350424447421">"Solicitações recentes"</string>
-    <!-- no translation found for location_recent_location_requests_see_all (9063541547120162593) -->
-    <skip />
+    <string name="location_recent_location_requests_see_all" msgid="9063541547120162593">"Ver tudo"</string>
     <string name="location_no_recent_apps" msgid="2800907699722178041">"Nenhum app solicitou a localização recentemente"</string>
     <string name="location_category_location_services" msgid="7437150886946685979">"Serviços de localização"</string>
     <string name="location_high_battery_use" msgid="517199943258508020">"Uso da bateria elevado"</string>
@@ -2317,8 +2316,7 @@
     <string name="credentials_configure_lock_screen_hint" msgid="8058230497337529036">"Para que você possa usar o armazenamento de credenciais, seu dispositivo precisa ter uma tela de bloqueio"</string>
     <string name="credentials_configure_lock_screen_button" msgid="253239765216055321">"DEFINIR BLOQUEIO"</string>
     <string name="usage_access_title" msgid="332333405495457839">"Apps com acesso ao uso"</string>
-    <!-- no translation found for emergency_tone_title (254495218194925271) -->
-    <skip />
+    <string name="emergency_tone_title" msgid="254495218194925271">"Sinal de discagem de emergência"</string>
     <string name="emergency_tone_summary" msgid="722259232924572153">"Definir comportamento durante uma chamada de emergência"</string>
     <string name="privacy_settings_title" msgid="2978878794187459190">"Backup"</string>
     <string name="backup_section_title" msgid="7952232291452882740">"Backup e restauração"</string>
@@ -2927,12 +2925,9 @@
     <string name="dock_audio_media_title" msgid="1346838179626123900">"Repr. de alto-falante em dock"</string>
     <string name="dock_audio_media_disabled" msgid="3430953622491538080">"Todo o áudio"</string>
     <string name="dock_audio_media_enabled" msgid="667849382924908673">"Somente áudio de mídia"</string>
-    <!-- no translation found for emergency_tone_silent (3750231842974733677) -->
-    <skip />
-    <!-- no translation found for emergency_tone_alert (8523447641290736852) -->
-    <skip />
-    <!-- no translation found for emergency_tone_vibrate (2278872257053690683) -->
-    <skip />
+    <string name="emergency_tone_silent" msgid="3750231842974733677">"Silêncio"</string>
+    <string name="emergency_tone_alert" msgid="8523447641290736852">"Tons"</string>
+    <string name="emergency_tone_vibrate" msgid="2278872257053690683">"Vibrações"</string>
     <string name="boot_sounds_title" msgid="567029107382343709">"Ativar sons"</string>
     <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Nunca"</string>
     <plurals name="zen_mode_settings_summary_on" formatted="false" msgid="7346979080337117366">
@@ -3112,9 +3107,7 @@
     <string name="zen_mode_choose_rule_type" msgid="5423746638871953459">"Escolher tipo de regra"</string>
     <string name="zen_mode_delete_rule_confirmation" msgid="6237882294348570283">"Excluir a regra \"<xliff:g id="RULE">%1$s</xliff:g>\"?"</string>
     <string name="zen_mode_delete_rule_button" msgid="4248741120307752294">"Excluir"</string>
-    <string name="zen_mode_rule_type" msgid="2289413469580142888">"Tipo de regra"</string>
     <string name="zen_mode_rule_type_unknown" msgid="3049377282766700600">"Desconhecido"</string>
-    <string name="zen_mode_configure_rule" msgid="8865785428056490305">"Configurar regra"</string>
     <string name="zen_mode_app_set_behavior" msgid="1534429320064381355">"Não é possível alterar essas configurações no momento. Um app (<xliff:g id="APP_NAME">%1$s</xliff:g>) ativou automaticamente o modo \"Não perturbe\" com comportamento personalizado."</string>
     <string name="zen_mode_unknown_app_set_behavior" msgid="2558968232814237874">"Não é possível alterar essas configurações no momento. Um app ativou automaticamente o modo \"Não perturbe\" com comportamento personalizado."</string>
     <string name="zen_mode_qs_set_behavior" msgid="6200424436456086312">"Não é possível alterar essas configurações no momento. O modo \"Não perturbe\" foi ativado manualmente com comportamento personalizado."</string>
@@ -3863,14 +3856,9 @@
     <string name="bluetooth_on_while_driving_pref" msgid="2460847604498343330">"Usar Bluetooth ao dirigir"</string>
     <string name="bluetooth_on_while_driving_summary" msgid="3196190732516898541">"Ativar Bluetooth automaticamente ao dirigir"</string>
     <string name="dev_android_o_battery_settings_title" msgid="2926578228655006762">"Ver configurações de bateria do Android 8.0"</string>
-    <!-- no translation found for change_wifi_state_title (2640523995824431999) -->
-    <skip />
-    <!-- no translation found for keywords_change_wifi_state (1439807171750715923) -->
-    <skip />
-    <!-- no translation found for change_wifi_state_app_detail_title (1022360625069880993) -->
-    <skip />
-    <!-- no translation found for change_wifi_state_app_detail_switch (724818064600933957) -->
-    <skip />
-    <!-- no translation found for change_wifi_state_app_detail_summary (2511212187129042304) -->
-    <skip />
+    <string name="change_wifi_state_title" msgid="2640523995824431999">"Ativar e desativar o Wi-Fi"</string>
+    <string name="keywords_change_wifi_state" msgid="1439807171750715923">"ativar e desativar o Wi-Fi"</string>
+    <string name="change_wifi_state_app_detail_title" msgid="1022360625069880993">"Ativar e desativar o Wi-Fi"</string>
+    <string name="change_wifi_state_app_detail_switch" msgid="724818064600933957">"Permitir alternância do Wi-Fi"</string>
+    <string name="change_wifi_state_app_detail_summary" msgid="2511212187129042304">"Permitir que esse app altere o estado do Wi-Fi, inclusive se conectando ao Wi-Fi e ativando-o ou desativando-o."</string>
 </resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index c684dc6..9fddbcd 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -239,8 +239,12 @@
 
     <!-- Admin support contact details dialog. -->
     <dimen name="admin_details_dialog_padding">24dp</dimen>
+    <dimen name="admin_details_dialog_title_bottom_padding">20dp</dimen>
     <dimen name="admin_details_dialog_icon_size">48dp</dimen>
     <dimen name="admin_details_dialog_link_padding_top">36dp</dimen>
+    <dimen name="admin_details_dialog_learn_more_button_top_margin">24dp</dimen>
+    <dimen name="admin_details_dialog_learn_more_button_padding">8dp</dimen>
+    <dimen name="admin_details_dialog_learn_more_button_minWidth">88dp</dimen>
 
     <!-- Button bar padding for unmount button. -->
     <dimen name="unmount_button_padding">8dp</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 4e81b7a..e5c7cec 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -748,20 +748,34 @@
     <string name="date_time_set_date_title">Date</string>
     <!-- Date & time setting screen setting option title -->
     <string name="date_time_set_date">Set date</string>
+    <!-- Setting option title to select region in time zone setting screen [CHAR LIMIT=30] -->
+    <string name="date_time_select_region">Region</string>
+    <!-- Setting option title to select time zone in time zone setting screen [CHAR LIMIT=30]-->
+    <string name="date_time_select_zone">Time Zone</string>
+    <!-- Setting option title in time zone setting screen [CHAR LIMIT=30] -->
+    <string name="date_time_select_fixed_offset_time_zones">Select UTC offset</string>
     <!-- Menu item on Select time zone screen -->
     <string name="zone_list_menu_sort_alphabetically">Sort alphabetically</string>
     <!-- Menu item on Select time zone screen -->
     <string name="zone_list_menu_sort_by_timezone">Sort by time zone</string>
     <!-- Label describing when a given time zone changes to DST or standard time -->
     <string name="zone_change_to_from_dst"><xliff:g id="time_type" example="Pacific Summer Time">%1$s</xliff:g> starts on <xliff:g id="transition_date" example="Mar 11 2018">%2$s</xliff:g>.</string>
+    <!-- Label describing a exemplar location and time zone offset[CHAR LIMIT=NONE] -->
+    <string name="zone_info_exemplar_location_and_offset"><xliff:g id="exemplar_location" example="Los Angeles">%1$s</xliff:g> (<xliff:g id="offset" example="GMT-08:00">%2$s</xliff:g>)</string>
+    <!-- Label describing a time zone offset and name[CHAR LIMIT=NONE] -->
+    <string name="zone_info_offset_and_name"><xliff:g id="time_type" example="Pacific Time">%2$s</xliff:g> (<xliff:g id="offset" example="GMT-08:00">%1$s</xliff:g>)</string>
+    <!-- Label describing a time zone and changes to DST or standard time [CHAR LIMIT=NONE] -->
+    <string name="zone_info_footer">Uses <xliff:g id="offset_and_name" example="Pacific Time (GMT-08:00)">%1$s</xliff:g>. <xliff:g id="dst_time_type" example="Pacific Daylight Time">%2$s</xliff:g> starts on <xliff:g id="transition_date" example="Mar 11 2018">%3$s</xliff:g>.</string>
+    <!-- Label describing a time zone without DST [CHAR LIMIT=NONE] -->
+    <string name="zone_info_footer_no_dst">Uses <xliff:g id="offset_and_name" example="GMT-08:00 Pacific Time">%1$s</xliff:g>. No daylight savings time.</string>
     <!-- Describes the time type "daylight savings time" (used in zone_change_to_from_dst, when no zone specific name is available) -->
     <string name="zone_time_type_dst">Daylight savings time</string>
     <!-- Describes the time type "standard time" (used in zone_change_to_from_dst, when no zone specific name is available) -->
     <string name="zone_time_type_standard">Standard time</string>
     <!-- The menu item to switch to selecting a time zone by region (default) -->
-    <string name="zone_menu_by_region">Time zone by region</string>
+    <string name="zone_menu_by_region">Show time zones by region</string>
     <!-- The menu item to switch to selecting a time zone with a fixed offset (such as UTC or GMT+0200) -->
-    <string name="zone_menu_by_offset">Fixed offset time zones</string>
+    <string name="zone_menu_by_offset">Show time zones by UTC offset</string>
 
     <!-- Title string shown above DatePicker, letting a user select system date
          [CHAR LIMIT=20] -->
@@ -819,8 +833,10 @@
     <string name="encryption_and_credential_settings_title">Encryption &amp; credentials</string>
     <!-- Security Settings screen Encryption and crendential summary -->
     <string name="encryption_and_credential_settings_summary" product="default">Phone encrypted</string>
+    <string name="decryption_settings_summary" product="default">Phone not encrypted</string>
     <!-- Security Settings screen Encryption and crendential summary -->
     <string name="encryption_and_credential_settings_summary" product="tablet">Device encrypted</string>
+    <string name="decryption_settings_summary" product="tablet">Device not encrypted</string>
     <!-- Security Settings screen setting option title for the item to take you to the lock screen preference screen [CHAR LIMIT=60] -->
     <string name="lockscreen_settings_title">Lock screen preferences</string>
 
@@ -4898,6 +4914,11 @@
         <item quantity="other">%1$d apps</item>
     </plurals>
 
+    <!-- Title for auto restriction toggle -->
+    <string name="battery_auto_restriction_title">Restrict apps automatically</string>
+    <!-- Summary for auto restriction toggle -->
+    <string name="battery_auto_restriction_summary">Prevent apps from using extra battery in the background</string>
+
     <!-- Title for force stop dialog [CHAR LIMIT=30] -->
     <string name="dialog_stop_title">Stop app?</string>
     <!-- Message body for force stop dialog [CHAR LIMIT=NONE] -->
@@ -9387,4 +9408,22 @@
     <!-- Apps > App Details > Wifi access > Description. [CHAR LIMIT=NONE] -->
     <string name="change_wifi_state_app_detail_summary">Allow this app to change wifi state including connecting to wifi and turing wifi on and off.</string>
 
+    <!-- Title for media output settings -->
+    <string name="media_output_title">Play media to</string>
+
+    <!-- Summary for media output settings. (phone) -->
+    <string name="media_output_summary" product="default">Phone</string>
+
+    <!-- Summary for media output settings. (tablet) -->
+    <string name="media_output_summary" product="tablet">Tablet</string>
+
+    <!-- Summary for media output settings. (device) -->
+    <string name="media_output_summary" product="device">Device</string>
+
+    <!-- Summary for media output settings when device is in ongoing call state. -->
+    <string name="media_out_summary_ongoing_call_state">Unavailable during calls</string>
+
+    <!-- Summary for media output settings when the media stream is being captured by something else. -->
+    <string name="media_output_summary_unavailable">Unavailable</string>
+
 </resources>
diff --git a/res/xml/app_and_notification.xml b/res/xml/app_and_notification.xml
index 05739b8..85a766e 100644
--- a/res/xml/app_and_notification.xml
+++ b/res/xml/app_and_notification.xml
@@ -32,19 +32,14 @@
         <Preference
             android:title="@string/applications_settings"
             android:key="all_app_info"
-            android:order="20">
-            <intent
-                android:action="android.intent.action.MAIN"
-                android:targetPackage="com.android.settings"
-                android:targetClass="com.android.settings.Settings$ManageApplicationsActivity">
-            </intent>
-        </Preference>
+            android:fragment="com.android.settings.applications.manageapplications.ManageApplications"
+            android:order="20" />
     </PreferenceCategory>
 
     <!-- Empty category to draw divider -->
     <PreferenceCategory
         android:key="all_app_info_divider"
-        android:order="-190"/>
+        android:order="-190" />
 
     <!-- Notifications (appears before manage_perms), default apps (appears after) -->
     <PreferenceCategory
diff --git a/res/xml/power_usage_advanced.xml b/res/xml/power_usage_advanced.xml
index b31eb40..d32611c 100644
--- a/res/xml/power_usage_advanced.xml
+++ b/res/xml/power_usage_advanced.xml
@@ -25,7 +25,7 @@
         android:key="battery_graph"/>
 
     <PreferenceCategory
-        android:key="battery_usage_list"
-        android:title="@string/battery_detail_since_full_charge"/>
+        android:key="app_list"
+        android:title="@string/power_usage_list_summary"/>
 
 </PreferenceScreen>
diff --git a/res/xml/power_usage_advanced_legacy.xml b/res/xml/power_usage_advanced_legacy.xml
new file mode 100644
index 0000000..26be727
--- /dev/null
+++ b/res/xml/power_usage_advanced_legacy.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.
+-->
+
+<PreferenceScreen
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:settings="http://schemas.android.com/apk/res-auto"
+    android:key="power_usage_advanced_screen_legacy"
+    android:title="@string/advanced_battery_title"
+    settings:keywords="@string/keywords_battery">
+
+    <com.android.settings.fuelgauge.BatteryHistoryPreference
+        android:key="battery_graph_legacy"/>
+
+    <PreferenceCategory
+        android:key="battery_usage_list_legacy"
+        android:title="@string/battery_detail_since_full_charge"/>
+
+</PreferenceScreen>
diff --git a/res/xml/power_usage_summary.xml b/res/xml/power_usage_summary.xml
index d89653a..ac96151 100644
--- a/res/xml/power_usage_summary.xml
+++ b/res/xml/power_usage_summary.xml
@@ -66,8 +66,4 @@
 
     </PreferenceCategory>
 
-    <PreferenceCategory
-        android:key="app_list"
-        android:title="@string/power_usage_list_summary"/>
-
 </PreferenceScreen>
diff --git a/res/xml/smart_battery_detail.xml b/res/xml/smart_battery_detail.xml
index a236cb8..e7fb9f7 100644
--- a/res/xml/smart_battery_detail.xml
+++ b/res/xml/smart_battery_detail.xml
@@ -15,7 +15,9 @@
   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-auto"
     android:key="smart_battery_detail"
     android:title="@string/smart_battery_manager_title">
 
@@ -32,6 +34,12 @@
         android:title="@string/smart_battery_title"
         android:summary="@string/smart_battery_summary"/>
 
+    <SwitchPreference
+        android:key="auto_restriction"
+        android:title="@string/battery_auto_restriction_title"
+        android:summary="@string/battery_auto_restriction_summary"
+        settings:controller="com.android.settings.fuelgauge.AutoRestrictionPreferenceController"/>
+
     <Preference
         android:key="restricted_app"
         android:title="@string/restricted_app_title"/>
diff --git a/src/com/android/settings/MasterClear.java b/src/com/android/settings/MasterClear.java
index 9ad32e2..46e0d41 100644
--- a/src/com/android/settings/MasterClear.java
+++ b/src/com/android/settings/MasterClear.java
@@ -57,6 +57,7 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settings.core.InstrumentedFragment;
 import com.android.settings.core.SubSettingLauncher;
+import com.android.settings.enterprise.ActionDisabledByAdminDialogHelper;
 import com.android.settings.password.ChooseLockSettingsHelper;
 import com.android.settings.password.ConfirmLockPattern;
 import com.android.settingslib.RestrictedLockUtils;
@@ -503,10 +504,11 @@
         if (disallow && !Utils.isDemoUser(context)) {
             return inflater.inflate(R.layout.master_clear_disallowed_screen, null);
         } else if (admin != null) {
-            View view = inflater.inflate(R.layout.admin_support_details_empty_view, null);
-            ShowAdminSupportDetailsDialog.setAdminSupportDetails(getActivity(), view, admin, false);
-            view.setVisibility(View.VISIBLE);
-            return view;
+            new ActionDisabledByAdminDialogHelper(getActivity())
+                    .prepareDialogBuilder(UserManager.DISALLOW_FACTORY_RESET, admin)
+                    .setOnDismissListener(__ -> getActivity().finish())
+                    .show();
+            return new View(getContext());
         }
 
         mContentView = inflater.inflate(R.layout.master_clear, null);
diff --git a/src/com/android/settings/MasterClearConfirm.java b/src/com/android/settings/MasterClearConfirm.java
index 59736fd..a92c8f8 100644
--- a/src/com/android/settings/MasterClearConfirm.java
+++ b/src/com/android/settings/MasterClearConfirm.java
@@ -34,6 +34,7 @@
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settings.core.InstrumentedFragment;
+import com.android.settings.enterprise.ActionDisabledByAdminDialogHelper;
 import com.android.settingslib.RestrictedLockUtils;
 
 import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
@@ -151,10 +152,11 @@
                 UserManager.DISALLOW_FACTORY_RESET, UserHandle.myUserId())) {
             return inflater.inflate(R.layout.master_clear_disallowed_screen, null);
         } else if (admin != null) {
-            View view = inflater.inflate(R.layout.admin_support_details_empty_view, null);
-            ShowAdminSupportDetailsDialog.setAdminSupportDetails(getActivity(), view, admin, false);
-            view.setVisibility(View.VISIBLE);
-            return view;
+            new ActionDisabledByAdminDialogHelper(getActivity())
+                    .prepareDialogBuilder(UserManager.DISALLOW_FACTORY_RESET, admin)
+                    .setOnDismissListener(__ -> getActivity().finish())
+                    .show();
+            return new View(getActivity());
         }
         mContentView = inflater.inflate(R.layout.master_clear_confirm, null);
         establishFinalConfirmationState();
@@ -167,9 +169,9 @@
         TextView confirmationMessage =
                 (TextView) mContentView.findViewById(R.id.master_clear_confirm);
         if (confirmationMessage != null) {
-            String accessibileText = new StringBuilder(currentTitle).append(",").append(
+            String accessibleText = new StringBuilder(currentTitle).append(",").append(
                     confirmationMessage.getText()).toString();
-            getActivity().setTitle(Utils.createAccessibleSequence(currentTitle, accessibileText));
+            getActivity().setTitle(Utils.createAccessibleSequence(currentTitle, accessibleText));
         }
     }
 
diff --git a/src/com/android/settings/ResetNetwork.java b/src/com/android/settings/ResetNetwork.java
index 8043750..591ce0a 100644
--- a/src/com/android/settings/ResetNetwork.java
+++ b/src/com/android/settings/ResetNetwork.java
@@ -45,6 +45,7 @@
 import com.android.internal.telephony.PhoneConstants;
 import com.android.settings.core.InstrumentedFragment;
 import com.android.settings.core.SubSettingLauncher;
+import com.android.settings.enterprise.ActionDisabledByAdminDialogHelper;
 import com.android.settings.password.ChooseLockSettingsHelper;
 import com.android.settings.password.ConfirmLockPattern;
 import com.android.settingslib.RestrictedLockUtils;
@@ -245,10 +246,11 @@
                 UserManager.DISALLOW_NETWORK_RESET, UserHandle.myUserId())) {
             return inflater.inflate(R.layout.network_reset_disallowed_screen, null);
         } else if (admin != null) {
-            View view = inflater.inflate(R.layout.admin_support_details_empty_view, null);
-            ShowAdminSupportDetailsDialog.setAdminSupportDetails(getActivity(), view, admin, false);
-            view.setVisibility(View.VISIBLE);
-            return view;
+            new ActionDisabledByAdminDialogHelper(getActivity())
+                    .prepareDialogBuilder(UserManager.DISALLOW_NETWORK_RESET, admin)
+                    .setOnDismissListener(__ -> getActivity().finish())
+                    .show();
+            return new View(getContext());
         }
 
         mContentView = inflater.inflate(R.layout.reset_network, null);
diff --git a/src/com/android/settings/ResetNetworkConfirm.java b/src/com/android/settings/ResetNetworkConfirm.java
index edded11..d735c06 100644
--- a/src/com/android/settings/ResetNetworkConfirm.java
+++ b/src/com/android/settings/ResetNetworkConfirm.java
@@ -27,7 +27,6 @@
 import android.net.wifi.WifiManager;
 import android.os.AsyncTask;
 import android.os.Bundle;
-import android.os.RecoverySystem;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.support.annotation.VisibleForTesting;
@@ -42,6 +41,7 @@
 import com.android.ims.ImsManager;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.telephony.PhoneConstants;
+import com.android.settings.enterprise.ActionDisabledByAdminDialogHelper;
 import com.android.settings.wrapper.RecoverySystemWrapper;
 import com.android.settings.core.InstrumentedFragment;
 import com.android.settingslib.RestrictedLockUtils;
@@ -197,10 +197,11 @@
                 UserManager.DISALLOW_NETWORK_RESET, UserHandle.myUserId())) {
             return inflater.inflate(R.layout.network_reset_disallowed_screen, null);
         } else if (admin != null) {
-            View view = inflater.inflate(R.layout.admin_support_details_empty_view, null);
-            ShowAdminSupportDetailsDialog.setAdminSupportDetails(getActivity(), view, admin, false);
-            view.setVisibility(View.VISIBLE);
-            return view;
+            new ActionDisabledByAdminDialogHelper(getActivity())
+                    .prepareDialogBuilder(UserManager.DISALLOW_NETWORK_RESET, admin)
+                    .setOnDismissListener(__ -> getActivity().finish())
+                    .show();
+            return new View(getContext());
         }
         mContentView = inflater.inflate(R.layout.reset_network_confirm, null);
         establishFinalConfirmationState();
diff --git a/src/com/android/settings/RestrictedSettingsFragment.java b/src/com/android/settings/RestrictedSettingsFragment.java
index bbb317b..b17ca84 100644
--- a/src/com/android/settings/RestrictedSettingsFragment.java
+++ b/src/com/android/settings/RestrictedSettingsFragment.java
@@ -17,6 +17,7 @@
 package com.android.settings;
 
 import android.app.Activity;
+import android.app.AlertDialog;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -30,6 +31,7 @@
 import android.widget.TextView;
 
 import com.android.settings.dashboard.RestrictedDashboardFragment;
+import com.android.settings.enterprise.ActionDisabledByAdminDialogHelper;
 import com.android.settingslib.RestrictedLockUtils;
 
 import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
@@ -67,7 +69,6 @@
     private RestrictionsManager mRestrictionsManager;
 
     private final String mRestrictionKey;
-    private View mAdminSupportDetails;
     private EnforcedAdmin mEnforcedAdmin;
     private TextView mEmptyTextView;
 
@@ -85,6 +86,8 @@
         }
     };
 
+    private AlertDialog mActionDisabledDialog;
+
     /**
      * @param restrictionKey The restriction key to check before pin protecting
      *            this settings page. Pass in {@link RESTRICT_IF_OVERRIDABLE} if it should
@@ -116,7 +119,6 @@
     @Override
     public void onActivityCreated(Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
-        mAdminSupportDetails = initAdminSupportDetailsView();
         mEmptyTextView = initEmptyTextView();
     }
 
@@ -204,10 +206,6 @@
         return restricted && mRestrictionsManager.hasRestrictionsProvider();
     }
 
-    private View initAdminSupportDetailsView() {
-        return getActivity().findViewById(R.id.admin_support_details);
-    }
-
     protected TextView initEmptyTextView() {
         TextView emptyView = (TextView) getActivity().findViewById(android.R.id.empty);
         return emptyView;
@@ -229,11 +227,14 @@
     @Override
     protected void onDataSetChanged() {
         highlightPreferenceIfNeeded();
-        if (mAdminSupportDetails != null && isUiRestrictedByOnlyAdmin()) {
+        if (isUiRestrictedByOnlyAdmin()
+                && (mActionDisabledDialog == null || !mActionDisabledDialog.isShowing())) {
             final EnforcedAdmin admin = getRestrictionEnforcedAdmin();
-            ShowAdminSupportDetailsDialog.setAdminSupportDetails(getActivity(),
-                    mAdminSupportDetails, admin, false);
-            setEmptyView(mAdminSupportDetails);
+            mActionDisabledDialog = new ActionDisabledByAdminDialogHelper(getActivity())
+                    .prepareDialogBuilder(mRestrictionKey, admin)
+                    .setOnDismissListener(__ -> getActivity().finish())
+                    .show();
+            setEmptyView(new View(getContext()));
         } else if (mEmptyTextView != null) {
             setEmptyView(mEmptyTextView);
         }
diff --git a/src/com/android/settings/ShowAdminSupportDetailsDialog.java b/src/com/android/settings/ShowAdminSupportDetailsDialog.java
deleted file mode 100644
index 321f93d..0000000
--- a/src/com/android/settings/ShowAdminSupportDetailsDialog.java
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.AppGlobals;
-import android.app.admin.DevicePolicyManager;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.pm.ActivityInfo;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.os.Process;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import com.android.settingslib.RestrictedLockUtils;
-import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
-
-import java.util.Objects;
-
-public class ShowAdminSupportDetailsDialog extends Activity
-        implements DialogInterface.OnDismissListener {
-
-    private static final String TAG = "AdminSupportDialog";
-
-    private EnforcedAdmin mEnforcedAdmin;
-    private View mDialogView;
-    private String mRestriction = null;
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        mEnforcedAdmin = getAdminDetailsFromIntent(getIntent());
-        mRestriction = getRestrictionFromIntent(getIntent());
-
-        AlertDialog.Builder builder = new AlertDialog.Builder(this);
-        mDialogView = LayoutInflater.from(builder.getContext()).inflate(
-                R.layout.admin_support_details_dialog, null);
-        initializeDialogViews(mDialogView, mEnforcedAdmin.component, mEnforcedAdmin.userId,
-                mRestriction);
-        builder.setOnDismissListener(this)
-                .setPositiveButton(R.string.okay, null)
-                .setView(mDialogView)
-                .show();
-    }
-
-    @Override
-    public void onNewIntent(Intent intent) {
-        super.onNewIntent(intent);
-        EnforcedAdmin admin = getAdminDetailsFromIntent(intent);
-        String restriction = getRestrictionFromIntent(intent);
-        if (!mEnforcedAdmin.equals(admin) || !Objects.equals(mRestriction, restriction)) {
-            mEnforcedAdmin = admin;
-            mRestriction = restriction;
-            initializeDialogViews(mDialogView, mEnforcedAdmin.component, mEnforcedAdmin.userId,
-                    mRestriction);
-        }
-    }
-
-    private EnforcedAdmin getAdminDetailsFromIntent(Intent intent) {
-        EnforcedAdmin admin = new EnforcedAdmin(null, UserHandle.myUserId());
-        if (intent == null) {
-            return admin;
-        }
-        admin.component = intent.getParcelableExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN);
-        admin.userId = intent.getIntExtra(Intent.EXTRA_USER_ID, UserHandle.myUserId());
-        return admin;
-    }
-
-    private String getRestrictionFromIntent(Intent intent) {
-        if (intent == null) return null;
-        return intent.getStringExtra(DevicePolicyManager.EXTRA_RESTRICTION);
-    }
-
-    private void initializeDialogViews(View root, ComponentName admin, int userId,
-                                               String restriction) {
-        if (admin != null) {
-            if (!RestrictedLockUtils.isAdminInCurrentUserOrProfile(this, admin)
-                    || !RestrictedLockUtils.isCurrentUserOrProfile(this, userId)) {
-                admin = null;
-            } else {
-                ActivityInfo ai = null;
-                try {
-                    ai = AppGlobals.getPackageManager().getReceiverInfo(admin, 0 /* flags */,
-                            userId);
-                } catch (RemoteException e) {
-                    Log.w(TAG, "Missing reciever info", e);
-                }
-                if (ai != null) {
-                    Drawable icon = ai.loadIcon(getPackageManager());
-                    Drawable badgedIcon = getPackageManager().getUserBadgedIcon(
-                            icon, new UserHandle(userId));
-                    ((ImageView) root.findViewById(R.id.admin_support_icon)).setImageDrawable(
-                            badgedIcon);
-                }
-            }
-        }
-
-        setAdminSupportTitle(root, restriction);
-        setAdminSupportDetails(this, root, new EnforcedAdmin(admin, userId), true);
-    }
-
-    private void setAdminSupportTitle(View root, String restriction) {
-        final TextView titleView = (TextView) root.findViewById(R.id.admin_support_dialog_title);
-        if (titleView == null) {
-            return;
-        }
-        if (restriction == null) {
-            titleView.setText(R.string.disabled_by_policy_title);
-            return;
-        }
-        switch(restriction) {
-            case UserManager.DISALLOW_ADJUST_VOLUME:
-                titleView.setText(R.string.disabled_by_policy_title_adjust_volume);
-                break;
-            case UserManager.DISALLOW_OUTGOING_CALLS:
-                titleView.setText(R.string.disabled_by_policy_title_outgoing_calls);
-                break;
-            case UserManager.DISALLOW_SMS:
-                titleView.setText(R.string.disabled_by_policy_title_sms);
-                break;
-            case DevicePolicyManager.POLICY_DISABLE_CAMERA:
-                titleView.setText(R.string.disabled_by_policy_title_camera);
-                break;
-            case DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE:
-                titleView.setText(R.string.disabled_by_policy_title_screen_capture);
-                break;
-            case DevicePolicyManager.POLICY_MANDATORY_BACKUPS:
-                titleView.setText(R.string.disabled_by_policy_title_turn_off_backups);
-                break;
-            default:
-                // Use general text if no specialized title applies
-                titleView.setText(R.string.disabled_by_policy_title);
-        }
-    }
-
-    public static void setAdminSupportDetails(final Activity activity, View root,
-            final EnforcedAdmin enforcedAdmin, final boolean finishActivity) {
-        if (enforcedAdmin == null) {
-            return;
-        }
-
-        if (enforcedAdmin.component != null) {
-            DevicePolicyManager dpm = (DevicePolicyManager) activity.getSystemService(
-                    Context.DEVICE_POLICY_SERVICE);
-            if (!RestrictedLockUtils.isAdminInCurrentUserOrProfile(activity,
-                    enforcedAdmin.component) || !RestrictedLockUtils.isCurrentUserOrProfile(
-                    activity, enforcedAdmin.userId)) {
-                enforcedAdmin.component = null;
-            } else {
-                if (enforcedAdmin.userId == UserHandle.USER_NULL) {
-                    enforcedAdmin.userId = UserHandle.myUserId();
-                }
-                CharSequence supportMessage = null;
-                if (UserHandle.isSameApp(Process.myUid(), Process.SYSTEM_UID)) {
-                    supportMessage = dpm.getShortSupportMessageForUser(
-                            enforcedAdmin.component, enforcedAdmin.userId);
-                }
-                if (supportMessage != null) {
-                    TextView textView = (TextView) root.findViewById(R.id.admin_support_msg);
-                    textView.setText(supportMessage);
-                }
-            }
-        }
-
-        root.findViewById(R.id.admins_policies_list).setOnClickListener(
-                new View.OnClickListener() {
-                    @Override
-                    public void onClick(View view) {
-                        Intent intent = new Intent();
-                        if (enforcedAdmin.component != null) {
-                            intent.setClass(activity, DeviceAdminAdd.class);
-                            intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN,
-                                    enforcedAdmin.component);
-                            intent.putExtra(DeviceAdminAdd.EXTRA_CALLED_FROM_SUPPORT_DIALOG, true);
-                            // DeviceAdminAdd class may need to run as managed profile.
-                            activity.startActivityAsUser(intent,
-                                    new UserHandle(enforcedAdmin.userId));
-                        } else {
-                            intent.setClass(activity, Settings.DeviceAdminSettingsActivity.class);
-                            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-                            // Activity merges both managed profile and parent users
-                            // admins so show as same user as this activity.
-                            activity.startActivity(intent);
-                        }
-                        if (finishActivity) {
-                            activity.finish();
-                        }
-                    }
-                });
-    }
-
-    @Override
-    public void onDismiss(DialogInterface dialog) {
-        finish();
-    }
-}
diff --git a/src/com/android/settings/applications/appinfo/InstantAppButtonsPreferenceController.java b/src/com/android/settings/applications/appinfo/InstantAppButtonsPreferenceController.java
index df64d76..d2515a3 100644
--- a/src/com/android/settings/applications/appinfo/InstantAppButtonsPreferenceController.java
+++ b/src/com/android/settings/applications/appinfo/InstantAppButtonsPreferenceController.java
@@ -147,7 +147,10 @@
         if (!TextUtils.isEmpty(mLaunchUri)) {
             installButton.setVisibility(View.GONE);
             final Intent intent = new Intent(Intent.ACTION_VIEW);
+            intent.addCategory(Intent.CATEGORY_BROWSABLE);
+            intent.setPackage(mPackageName);
             intent.setData(Uri.parse(mLaunchUri));
+            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
             launchButton.setOnClickListener(v -> mParent.startActivity(intent));
         } else {
             launchButton.setVisibility(View.GONE);
diff --git a/src/com/android/settings/applications/manageapplications/ManageApplications.java b/src/com/android/settings/applications/manageapplications/ManageApplications.java
index 8f4cbe3..b0857c5 100644
--- a/src/com/android/settings/applications/manageapplications/ManageApplications.java
+++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java
@@ -96,9 +96,7 @@
 import com.android.settings.applications.appinfo.DrawOverlayDetails;
 import com.android.settings.applications.appinfo.ExternalSourcesDetails;
 import com.android.settings.applications.appinfo.WriteSettingsDetails;
-
-import com.android.settings.core.FeatureFlags;
-import com.android.settings.core.InstrumentedPreferenceFragment;
+import com.android.settings.core.InstrumentedFragment;
 import com.android.settings.core.SubSettingLauncher;
 import com.android.settings.dashboard.SummaryLoader;
 import com.android.settings.fuelgauge.HighPowerDetail;
@@ -132,7 +130,7 @@
  * can be launched through Settings or via the ACTION_MANAGE_PACKAGE_STORAGE
  * intent.
  */
-public class ManageApplications extends InstrumentedPreferenceFragment
+public class ManageApplications extends InstrumentedFragment
         implements View.OnClickListener, OnItemSelectedListener {
 
     static final String TAG = "ManageApplications";
@@ -286,6 +284,9 @@
             mListType = LIST_TYPE_WIFI_ACCESS;
             screenTitle = R.string.change_wifi_state_title;
         } else {
+            if (screenTitle == -1) {
+                screenTitle = R.string.application_info_label;
+            }
             mListType = LIST_TYPE_MAIN;
         }
         final AppFilterRegistry appFilterRegistry = AppFilterRegistry.getInstance();
@@ -551,14 +552,15 @@
                 startAppInfoFragment(DirectoryAccessDetails.class, R.string.directory_access);
                 break;
             case LIST_TYPE_WIFI_ACCESS:
-                startAppInfoFragment(ChangeWifiStateDetails.class, R.string.change_wifi_state_title);
+                startAppInfoFragment(ChangeWifiStateDetails.class,
+                        R.string.change_wifi_state_title);
                 break;
             // TODO: Figure out if there is a way where we can spin up the profile's settings
             // process ahead of time, to avoid a long load of data when user clicks on a managed
             // app. Maybe when they load the list of apps that contains managed profile apps.
             default:
                 startAppInfoFragment(
-                    AppInfoDashboardFragment.class, R.string.application_info_label);
+                        AppInfoDashboardFragment.class, R.string.application_info_label);
                 break;
         }
     }
@@ -1234,8 +1236,8 @@
                 case LIST_TYPE_NOTIFICATION:
                     if (entry.extraInfo != null) {
                         holder.setSummary(
-                            AppNotificationPreferenceController.getNotificationSummary(
-                                (AppRow) entry.extraInfo, mContext));
+                                AppNotificationPreferenceController.getNotificationSummary(
+                                        (AppRow) entry.extraInfo, mContext));
                     } else {
                         holder.setSummary(null);
                     }
diff --git a/src/com/android/settings/dashboard/DashboardAdapter.java b/src/com/android/settings/dashboard/DashboardAdapter.java
index 99de73e..879a4b8 100644
--- a/src/com/android/settings/dashboard/DashboardAdapter.java
+++ b/src/com/android/settings/dashboard/DashboardAdapter.java
@@ -17,7 +17,6 @@
 
 import android.app.Activity;
 import android.content.Context;
-import android.graphics.Typeface;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
 import android.os.Bundle;
@@ -27,7 +26,6 @@
 import android.support.v7.widget.LinearLayoutManager;
 import android.support.v7.widget.RecyclerView;
 import android.text.TextUtils;
-import android.util.ArrayMap;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -56,8 +54,8 @@
 import java.util.List;
 
 public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.DashboardItemHolder>
-    implements SummaryLoader.SummaryConsumer, SuggestionAdapter.Callback, LifecycleObserver,
-    OnSaveInstanceState {
+        implements SummaryLoader.SummaryConsumer, SuggestionAdapter.Callback, LifecycleObserver,
+        OnSaveInstanceState {
     public static final String TAG = "DashboardAdapter";
     private static final String STATE_CATEGORY_LIST = "category_list";
 
@@ -84,8 +82,8 @@
     };
 
     public DashboardAdapter(Context context, Bundle savedInstanceState,
-        List<Condition> conditions, SuggestionControllerMixin suggestionControllerMixin,
-        Lifecycle lifecycle) {
+            List<Condition> conditions, SuggestionControllerMixin suggestionControllerMixin,
+            Lifecycle lifecycle) {
 
         DashboardCategory category = null;
         boolean conditionExpanded = false;
@@ -96,14 +94,14 @@
         mDashboardFeatureProvider = factory.getDashboardFeatureProvider(context);
         mCache = new IconCache(context);
         mSuggestionAdapter = new SuggestionAdapter(mContext, suggestionControllerMixin,
-            savedInstanceState, this /* callback */, lifecycle);
+                savedInstanceState, this /* callback */, lifecycle);
 
         setHasStableIds(true);
 
         if (savedInstanceState != null) {
             category = savedInstanceState.getParcelable(STATE_CATEGORY_LIST);
             conditionExpanded = savedInstanceState.getBoolean(
-                STATE_CONDITION_EXPANDED, conditionExpanded);
+                    STATE_CONDITION_EXPANDED, conditionExpanded);
         }
 
         if (lifecycle != null) {
@@ -111,18 +109,18 @@
         }
 
         mDashboardData = new DashboardData.Builder()
-            .setConditions(conditions)
-            .setSuggestions(mSuggestionAdapter.getSuggestions())
-            .setCategory(category)
-            .setConditionExpanded(conditionExpanded)
-            .build();
+                .setConditions(conditions)
+                .setSuggestions(mSuggestionAdapter.getSuggestions())
+                .setCategory(category)
+                .setConditionExpanded(conditionExpanded)
+                .build();
     }
 
     public void setSuggestions(List<Suggestion> data) {
         final DashboardData prevData = mDashboardData;
         mDashboardData = new DashboardData.Builder(prevData)
-            .setSuggestions(data)
-            .build();
+                .setSuggestions(data)
+                .build();
         notifyDashboardDataChanged(prevData);
     }
 
@@ -130,8 +128,8 @@
         final DashboardData prevData = mDashboardData;
         Log.d(TAG, "adapter setCategory called");
         mDashboardData = new DashboardData.Builder(prevData)
-            .setCategory(category)
-            .build();
+                .setCategory(category)
+                .build();
         notifyDashboardDataChanged(prevData);
     }
 
@@ -139,8 +137,8 @@
         final DashboardData prevData = mDashboardData;
         Log.d(TAG, "adapter setConditions called");
         mDashboardData = new DashboardData.Builder(prevData)
-            .setConditions(conditions)
-            .build();
+                .setConditions(conditions)
+                .build();
         notifyDashboardDataChanged(prevData);
     }
 
@@ -155,8 +153,8 @@
             // remain as the dashboard item. Need to refresh the dashboard list.
             setSuggestions(null);
         } else {
-            mSuggestionAdapter.removeSuggestion(suggestion);
-            notifyItemChanged(0, null);
+            list.remove(suggestion);
+            setSuggestions(list);
         }
     }
 
@@ -203,15 +201,15 @@
                 break;
             case R.layout.condition_header:
                 onBindConditionHeader((ConditionHeaderHolder) holder,
-                    (ConditionHeaderData) mDashboardData.getItemEntityByPosition(position));
+                        (ConditionHeaderData) mDashboardData.getItemEntityByPosition(position));
                 break;
             case R.layout.condition_footer:
                 holder.itemView.setOnClickListener(v -> {
                     mMetricsFeatureProvider.action(mContext,
-                        MetricsEvent.ACTION_SETTINGS_CONDITION_EXPAND, false);
+                            MetricsEvent.ACTION_SETTINGS_CONDITION_EXPAND, false);
                     DashboardData prevData = mDashboardData;
                     mDashboardData = new DashboardData.Builder(prevData).
-                        setConditionExpanded(false).build();
+                            setConditionExpanded(false).build();
                     notifyDashboardDataChanged(prevData);
                     scrollToTopOfConditions();
                 });
@@ -254,7 +252,7 @@
     void notifyDashboardDataChanged(DashboardData prevData) {
         if (mFirstFrameDrawn && prevData != null) {
             final DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new DashboardData
-                .ItemsDataDiffCallback(prevData.getItemList(), mDashboardData.getItemList()));
+                    .ItemsDataDiffCallback(prevData.getItemList(), mDashboardData.getItemList()));
             diffResult.dispatchUpdatesTo(this);
         } else {
             mFirstFrameDrawn = true;
@@ -272,17 +270,17 @@
         } else {
             holder.title.setText(null);
             holder.summary.setText(
-                mContext.getString(R.string.condition_summary, data.conditionCount));
+                    mContext.getString(R.string.condition_summary, data.conditionCount));
             updateConditionIcons(data.conditionIcons, holder.icons);
             holder.icons.setVisibility(View.VISIBLE);
         }
 
         holder.itemView.setOnClickListener(v -> {
             mMetricsFeatureProvider.action(mContext,
-                MetricsEvent.ACTION_SETTINGS_CONDITION_EXPAND, true);
+                    MetricsEvent.ACTION_SETTINGS_CONDITION_EXPAND, true);
             final DashboardData prevData = mDashboardData;
             mDashboardData = new DashboardData.Builder(prevData)
-                .setConditionExpanded(true).build();
+                    .setConditionExpanded(true).build();
             notifyDashboardDataChanged(prevData);
             scrollToTopOfConditions();
         });
@@ -291,8 +289,8 @@
     @VisibleForTesting
     void onBindCondition(final ConditionContainerHolder holder, int position) {
         final ConditionAdapter adapter = new ConditionAdapter(mContext,
-            (List<Condition>) mDashboardData.getItemEntityByPosition(position),
-            mDashboardData.isConditionExpanded());
+                (List<Condition>) mDashboardData.getItemEntityByPosition(position),
+                mDashboardData.isConditionExpanded());
         adapter.addDismissHandling(holder.data);
         holder.data.setAdapter(adapter);
         holder.data.setLayoutManager(new LinearLayoutManager(mContext));
@@ -303,7 +301,7 @@
         // If there is suggestions to show, it will be at position 0 as we don't show the suggestion
         // header anymore.
         final List<Suggestion> suggestions =
-            (List<Suggestion>) mDashboardData.getItemEntityByPosition(position);
+                (List<Suggestion>) mDashboardData.getItemEntityByPosition(position);
         if (suggestions != null && suggestions.size() > 0) {
             mSuggestionAdapter.setSuggestions(suggestions);
             holder.data.setAdapter(mSuggestionAdapter);
@@ -316,7 +314,8 @@
     @VisibleForTesting
     void onBindTile(DashboardItemHolder holder, Tile tile) {
         Drawable icon = mCache.getIcon(tile.icon);
-        if (!TextUtils.equals(tile.icon.getResPackage(), mContext.getPackageName())) {
+        if (!TextUtils.equals(tile.icon.getResPackage(), mContext.getPackageName())
+                && !(icon instanceof RoundedHomepageIcon)) {
             icon = new RoundedHomepageIcon(mContext, icon);
             mCache.updateIcon(tile.icon, icon);
         }
diff --git a/src/com/android/settings/dashboard/DashboardData.java b/src/com/android/settings/dashboard/DashboardData.java
index 45aab9a..113caba 100644
--- a/src/com/android/settings/dashboard/DashboardData.java
+++ b/src/com/android/settings/dashboard/DashboardData.java
@@ -246,7 +246,11 @@
         if (suggestions.size() <= MAX_SUGGESTION_COUNT) {
             return suggestions;
         }
-        return suggestions.subList(0, MAX_SUGGESTION_COUNT);
+        final List<Suggestion> suggestionsToShow = new ArrayList<>(MAX_SUGGESTION_COUNT);
+        for (int i = 0; i < MAX_SUGGESTION_COUNT; i++) {
+            suggestionsToShow.add(suggestions.get(i));
+        }
+        return suggestionsToShow;
     }
 
     /**
diff --git a/src/com/android/settings/dashboard/RestrictedDashboardFragment.java b/src/com/android/settings/dashboard/RestrictedDashboardFragment.java
index 99aaff4..de0b396 100644
--- a/src/com/android/settings/dashboard/RestrictedDashboardFragment.java
+++ b/src/com/android/settings/dashboard/RestrictedDashboardFragment.java
@@ -19,6 +19,7 @@
 import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
 
 import android.app.Activity;
+import android.app.AlertDialog;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -31,9 +32,9 @@
 import android.view.View;
 import android.widget.TextView;
 
+import com.android.settings.enterprise.ActionDisabledByAdminDialogHelper;
 import com.android.settings.R;
 import com.android.settings.RestrictedSettingsFragment;
-import com.android.settings.ShowAdminSupportDetailsDialog;
 import com.android.settingslib.RestrictedLockUtils;
 
 /**
@@ -69,7 +70,6 @@
     private RestrictionsManager mRestrictionsManager;
 
     private final String mRestrictionKey;
-    private View mAdminSupportDetails;
     private EnforcedAdmin mEnforcedAdmin;
     private TextView mEmptyTextView;
 
@@ -86,6 +86,7 @@
             }
         }
     };
+    private AlertDialog mActionDisabledDialog;
 
     /**
      * @param restrictionKey The restriction key to check before pin protecting
@@ -118,7 +119,6 @@
     @Override
     public void onActivityCreated(Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
-        mAdminSupportDetails = initAdminSupportDetailsView();
         mEmptyTextView = initEmptyTextView();
     }
 
@@ -206,10 +206,6 @@
         return restricted && mRestrictionsManager.hasRestrictionsProvider();
     }
 
-    private View initAdminSupportDetailsView() {
-        return getActivity().findViewById(R.id.admin_support_details);
-    }
-
     protected TextView initEmptyTextView() {
         TextView emptyView = (TextView) getActivity().findViewById(android.R.id.empty);
         return emptyView;
@@ -231,11 +227,14 @@
     @Override
     protected void onDataSetChanged() {
         highlightPreferenceIfNeeded();
-        if (mAdminSupportDetails != null && isUiRestrictedByOnlyAdmin()) {
+        if (isUiRestrictedByOnlyAdmin()
+                && (mActionDisabledDialog == null || !mActionDisabledDialog.isShowing())) {
             final EnforcedAdmin admin = getRestrictionEnforcedAdmin();
-            ShowAdminSupportDetailsDialog.setAdminSupportDetails(getActivity(),
-                    mAdminSupportDetails, admin, false);
-            setEmptyView(mAdminSupportDetails);
+            mActionDisabledDialog = new ActionDisabledByAdminDialogHelper(getActivity())
+                    .prepareDialogBuilder(mRestrictionKey, admin)
+                    .setOnDismissListener(__ -> getActivity().finish())
+                    .show();
+            setEmptyView(new View(getContext()));
         } else if (mEmptyTextView != null) {
             setEmptyView(mEmptyTextView);
         }
diff --git a/src/com/android/settings/datetime/timezone/BaseTimeZoneAdapter.java b/src/com/android/settings/datetime/timezone/BaseTimeZoneAdapter.java
new file mode 100644
index 0000000..effa948
--- /dev/null
+++ b/src/com/android/settings/datetime/timezone/BaseTimeZoneAdapter.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2018 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.datetime.timezone;
+
+import android.icu.text.BreakIterator;
+import android.support.annotation.NonNull;
+import android.support.annotation.WorkerThread;
+import android.support.v7.widget.RecyclerView;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Filter;
+import android.widget.TextView;
+
+import com.android.settings.R;
+import com.android.settings.datetime.timezone.BaseTimeZonePicker.OnListItemClickListener;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+/**
+ * Used with {@class BaseTimeZonePicker}. It renders text in each item into list view. A list of
+ * {@class AdapterItem} must be provided when an instance is created.
+ */
+public class BaseTimeZoneAdapter<T extends BaseTimeZoneAdapter.AdapterItem>
+        extends RecyclerView.Adapter<BaseTimeZoneAdapter.ItemViewHolder> {
+
+    private final List<T> mOriginalItems;
+    private final OnListItemClickListener mOnListItemClickListener;
+    private final Locale mLocale;
+    private final boolean mShowItemSummary;
+
+    private List<T> mItems;
+    private ArrayFilter mFilter;
+
+    public BaseTimeZoneAdapter(List<T> items, OnListItemClickListener
+            onListItemClickListener, Locale locale, boolean showItemSummary) {
+        mOriginalItems = items;
+        mItems = items;
+        mOnListItemClickListener = onListItemClickListener;
+        mLocale = locale;
+        mShowItemSummary = showItemSummary;
+        setHasStableIds(true);
+    }
+
+    @NonNull
+    @Override
+    public ItemViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+        final View view = LayoutInflater.from(parent.getContext())
+                .inflate(R.layout.time_zone_search_item, parent, false);
+        return new ItemViewHolder(view, mOnListItemClickListener);
+    }
+
+    @Override
+    public void onBindViewHolder(@NonNull ItemViewHolder holder, int position) {
+        final AdapterItem item = mItems.get(position);
+        holder.mSummaryFrame.setVisibility(
+                mShowItemSummary ? View.VISIBLE : View.GONE);
+        holder.mTitleView.setText(item.getTitle());
+        holder.mIconTextView.setText(item.getIconText());
+        holder.mSummaryView.setText(item.getSummary());
+        holder.mTimeView.setText(item.getCurrentTime());
+        holder.setPosition(position);
+    }
+
+    @Override
+    public long getItemId(int position) {
+        return getItem(position).getItemId();
+    }
+
+    @Override
+    public int getItemCount() {
+        return mItems.size();
+    }
+
+    public  @NonNull
+    Filter getFilter() {
+        if (mFilter == null) {
+            mFilter = new ArrayFilter();
+        }
+        return mFilter;
+    }
+
+    public T getItem(int position) {
+        return mItems.get(position);
+    }
+
+    public interface AdapterItem {
+        CharSequence getTitle();
+        CharSequence getSummary();
+        String getIconText();
+        String getCurrentTime();
+        long getItemId();
+        String[] getSearchKeys();
+    }
+
+    public static class ItemViewHolder extends RecyclerView.ViewHolder
+            implements View.OnClickListener{
+
+        final OnListItemClickListener mOnListItemClickListener;
+        final View mSummaryFrame;
+        final TextView mTitleView;
+        final TextView mIconTextView;
+        final TextView mSummaryView;
+        final TextView mTimeView;
+        private int mPosition;
+
+        public ItemViewHolder(View itemView, OnListItemClickListener onListItemClickListener) {
+            super(itemView);
+            itemView.setOnClickListener(this);
+            mSummaryFrame = itemView.findViewById(R.id.summary_frame);
+            mTitleView = itemView.findViewById(android.R.id.title);
+            mIconTextView = itemView.findViewById(R.id.icon_text);
+            mSummaryView = itemView.findViewById(android.R.id.summary);
+            mTimeView = itemView.findViewById(R.id.current_time);
+            mOnListItemClickListener = onListItemClickListener;
+        }
+
+        public void setPosition(int position) {
+            mPosition = position;
+        }
+
+        @Override
+        public void onClick(View v) {
+            mOnListItemClickListener.onListItemClick(mPosition);
+        }
+    }
+
+    /**
+     * <p>An array filter constrains the content of the array adapter with
+     * a prefix. Each item that does not start with the supplied prefix
+     * is removed from the list.</p>
+     *
+     * The filtering operation is not optimized, due to small data size (~260 regions),
+     * require additional pre-processing. Potentially, a trie structure can be used to match
+     * prefixes of the search keys.
+     */
+    private class ArrayFilter extends Filter {
+
+        private BreakIterator mBreakIterator = BreakIterator.getWordInstance(mLocale);
+
+        @WorkerThread
+        @Override
+        protected FilterResults performFiltering(CharSequence prefix) {
+            final List<T> newItems;
+            if (TextUtils.isEmpty(prefix)) {
+                newItems = mOriginalItems;
+            } else {
+                final String prefixString = prefix.toString().toLowerCase(mLocale);
+                newItems = new ArrayList<>();
+
+                for (T item : mOriginalItems) {
+                    outer:
+                    for (String searchKey : item.getSearchKeys()) {
+                        searchKey = searchKey.toLowerCase(mLocale);
+                        // First match against the whole, non-splitted value
+                        if (searchKey.startsWith(prefixString)) {
+                            newItems.add(item);
+                            break outer;
+                        } else {
+                            mBreakIterator.setText(searchKey);
+                            for (int wordStart = 0, wordLimit = mBreakIterator.next();
+                                    wordLimit != BreakIterator.DONE;
+                                    wordStart = wordLimit,
+                                            wordLimit = mBreakIterator.next()) {
+                                if (mBreakIterator.getRuleStatus() != BreakIterator.WORD_NONE
+                                        && searchKey.startsWith(prefixString, wordStart)) {
+                                    newItems.add(item);
+                                    break outer;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+
+            final FilterResults results = new FilterResults();
+            results.values = newItems;
+            results.count = newItems.size();
+
+            return results;
+        }
+
+        @Override
+        protected void publishResults(CharSequence constraint, FilterResults results) {
+            mItems = (List<T>) results.values;
+            notifyDataSetChanged();
+        }
+    }
+}
diff --git a/src/com/android/settings/datetime/timezone/BaseTimeZoneInfoPicker.java b/src/com/android/settings/datetime/timezone/BaseTimeZoneInfoPicker.java
new file mode 100644
index 0000000..b133582
--- /dev/null
+++ b/src/com/android/settings/datetime/timezone/BaseTimeZoneInfoPicker.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2018 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.datetime.timezone;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.icu.text.DateFormat;
+import android.icu.text.SimpleDateFormat;
+import android.icu.util.Calendar;
+
+import com.android.settings.R;
+import com.android.settings.datetime.timezone.model.TimeZoneData;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+
+/**
+ * Render a list of {@class TimeZoneInfo} into the list view in {@class BaseTimeZonePicker}
+ */
+public abstract class BaseTimeZoneInfoPicker extends BaseTimeZonePicker {
+    protected static final String TAG = "RegionZoneSearchPicker";
+    protected ZoneAdapter mAdapter;
+
+    protected BaseTimeZoneInfoPicker(int titleResId, int searchHintResId,
+            boolean searchEnabled, boolean defaultExpandSearch) {
+        super(titleResId, searchHintResId, searchEnabled, defaultExpandSearch);
+    }
+
+    @Override
+    protected BaseTimeZoneAdapter createAdapter(TimeZoneData timeZoneData) {
+        mAdapter = new ZoneAdapter(getContext(), getAllTimeZoneInfos(timeZoneData),
+                this::onListItemClick, getLocale());
+        return mAdapter;
+    }
+
+    private void onListItemClick(int position) {
+        final TimeZoneInfo timeZoneInfo = mAdapter.getItem(position).mTimeZoneInfo;
+        getActivity().setResult(Activity.RESULT_OK, prepareResultData(timeZoneInfo));
+        getActivity().finish();
+    }
+
+    protected Intent prepareResultData(TimeZoneInfo selectedTimeZoneInfo) {
+        return new Intent().putExtra(EXTRA_RESULT_TIME_ZONE_ID, selectedTimeZoneInfo.getId());
+    }
+
+    public abstract List<TimeZoneInfo> getAllTimeZoneInfos(TimeZoneData timeZoneData);
+
+    protected static class ZoneAdapter extends BaseTimeZoneAdapter<TimeZoneInfoItem> {
+
+        public ZoneAdapter(Context context, List<TimeZoneInfo> timeZones,
+                OnListItemClickListener onListItemClickListener, Locale locale) {
+            super(createTimeZoneInfoItems(context, timeZones, locale),
+                    onListItemClickListener, locale,  true /* showItemSummary */);
+        }
+
+        private static List<TimeZoneInfoItem> createTimeZoneInfoItems(Context context,
+                List<TimeZoneInfo> timeZones, Locale locale) {
+            final DateFormat currentTimeFormat = new SimpleDateFormat(
+                    android.text.format.DateFormat.getTimeFormatString(context), locale);
+            final ArrayList<TimeZoneInfoItem> results = new ArrayList<>(timeZones.size());
+            final Resources resources = context.getResources();
+            long i = 0;
+            for (TimeZoneInfo timeZone : timeZones) {
+                results.add(new TimeZoneInfoItem(i++, timeZone, resources, currentTimeFormat));
+            }
+            return results;
+        }
+    }
+
+    private static class TimeZoneInfoItem implements BaseTimeZoneAdapter.AdapterItem {
+        private final long mItemId;
+        private final TimeZoneInfo mTimeZoneInfo;
+        private final Resources mResources;
+        private final DateFormat mTimeFormat;
+        private final String mTitle;
+        private final String[] mSearchKeys;
+
+        private TimeZoneInfoItem(long itemId, TimeZoneInfo timeZoneInfo, Resources resources,
+                DateFormat timeFormat) {
+            mItemId = itemId;
+            mTimeZoneInfo = timeZoneInfo;
+            mResources = resources;
+            mTimeFormat = timeFormat;
+            mTitle = createTitle(timeZoneInfo);
+            mSearchKeys = new String[] { mTitle };
+        }
+
+        private static String createTitle(TimeZoneInfo timeZoneInfo) {
+            String name = timeZoneInfo.getExemplarLocation();
+            if (name == null) {
+                name = timeZoneInfo.getGenericName();
+            }
+            if (name == null && timeZoneInfo.getTimeZone().inDaylightTime(new Date())) {
+                name = timeZoneInfo.getDaylightName();
+            }
+            if (name == null) {
+                name = timeZoneInfo.getStandardName();
+            }
+            if (name == null) {
+                name = String.valueOf(timeZoneInfo.getGmtOffset());
+            }
+            return name;
+        }
+
+        @Override
+        public CharSequence getTitle() {
+            return mTitle;
+        }
+
+        @Override
+        public CharSequence getSummary() {
+            String name = mTimeZoneInfo.getGenericName();
+            if (name == null) {
+                if (mTimeZoneInfo.getTimeZone().inDaylightTime(new Date())) {
+                    name = mTimeZoneInfo.getDaylightName();
+                } else {
+                    name = mTimeZoneInfo.getStandardName();
+                }
+            }
+            if (name == null) {
+                return mTimeZoneInfo.getGmtOffset();
+            } else {
+                return SpannableUtil.getResourcesText(mResources,
+                        R.string.zone_info_offset_and_name, mTimeZoneInfo.getGmtOffset(), name);
+            }
+        }
+
+        @Override
+        public String getIconText() {
+            return null;
+        }
+
+        @Override
+        public String getCurrentTime() {
+            return mTimeFormat.format(Calendar.getInstance(mTimeZoneInfo.getTimeZone()));
+        }
+
+        @Override
+        public long getItemId() {
+            return mItemId;
+        }
+
+        @Override
+        public String[] getSearchKeys() {
+            return mSearchKeys;
+        }
+    }
+}
diff --git a/src/com/android/settings/datetime/timezone/BaseTimeZonePicker.java b/src/com/android/settings/datetime/timezone/BaseTimeZonePicker.java
new file mode 100644
index 0000000..c5e1ccb
--- /dev/null
+++ b/src/com/android/settings/datetime/timezone/BaseTimeZonePicker.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2018 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.datetime.timezone;
+
+import android.os.Bundle;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.SearchView;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settings.R;
+import com.android.settings.core.InstrumentedFragment;
+import com.android.settings.datetime.timezone.model.TimeZoneData;
+import com.android.settings.datetime.timezone.model.TimeZoneDataLoader;
+
+import java.util.Locale;
+
+/**
+ * It's abstract class. Subclass should use it with {@class BaseTimeZoneAdapter} and
+ * {@class AdapterItem} to provide a list view with text search capability.
+ * The search matches the prefix of words in the search text.
+ */
+public abstract class BaseTimeZonePicker extends InstrumentedFragment
+        implements SearchView.OnQueryTextListener{
+
+    public static final String EXTRA_RESULT_REGION_ID =
+            "com.android.settings.datetime.timezone.result_region_id";
+    public static final String EXTRA_RESULT_TIME_ZONE_ID =
+            "com.android.settings.datetime.timezone.result_time_zone_id";
+    private final int mTitleResId;
+    private final int mSearchHintResId;
+    private final boolean mSearchEnabled;
+    private final boolean mDefaultExpandSearch;
+
+    protected Locale mLocale;
+    private BaseTimeZoneAdapter mAdapter;
+    private RecyclerView mRecyclerView;
+    private TimeZoneData mTimeZoneData;
+
+    private SearchView mSearchView;
+
+    /**
+     * Constructor called by subclass.
+     * @param defaultExpandSearch whether expand the search view when first launching the fragment
+     */
+    protected BaseTimeZonePicker(int titleResId, int searchHintResId,
+            boolean searchEnabled, boolean defaultExpandSearch) {
+        mTitleResId = titleResId;
+        mSearchHintResId = searchHintResId;
+        mSearchEnabled = searchEnabled;
+        mDefaultExpandSearch = defaultExpandSearch;
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setHasOptionsMenu(true);
+        getActivity().setTitle(mTitleResId);
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        final View view = inflater.inflate(R.layout.recycler_view, container, false);
+        mRecyclerView = view.findViewById(R.id.recycler_view);
+        mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext(),
+                LinearLayoutManager.VERTICAL, /* reverseLayout */ false));
+        mRecyclerView.setAdapter(mAdapter);
+
+        // Initialize TimeZoneDataLoader only when mRecyclerView is ready to avoid race
+        // during onDateLoaderReady callback.
+        getLoaderManager().initLoader(0, null, new TimeZoneDataLoader.LoaderCreator(
+                getContext(), this::onTimeZoneDataReady));
+        return view;
+    }
+
+    public void onTimeZoneDataReady(TimeZoneData timeZoneData) {
+        if (mTimeZoneData == null && timeZoneData != null) {
+            mTimeZoneData = timeZoneData;
+            mAdapter = createAdapter(mTimeZoneData);
+            if (mRecyclerView != null) {
+                mRecyclerView.setAdapter(mAdapter);
+            }
+        }
+    }
+
+    protected Locale getLocale() {
+        return getContext().getResources().getConfiguration().getLocales().get(0);
+    }
+
+    /**
+     * Called when TimeZoneData is ready.
+     */
+    protected abstract BaseTimeZoneAdapter createAdapter(TimeZoneData timeZoneData);
+
+    @Override
+    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+        if (mSearchEnabled) {
+            inflater.inflate(R.menu.time_zone_base_search_menu, menu);
+
+            final MenuItem searchMenuItem = menu.findItem(R.id.time_zone_search_menu);
+            mSearchView = (SearchView) searchMenuItem.getActionView();
+
+            mSearchView.setQueryHint(getText(mSearchHintResId));
+            mSearchView.setOnQueryTextListener(this);
+
+            if (mDefaultExpandSearch) {
+                searchMenuItem.expandActionView();
+                mSearchView.setIconified(false);
+                mSearchView.setActivated(true);
+                mSearchView.setQuery("", true /* submit */);
+            }
+        }
+    }
+
+    @Override
+    public boolean onQueryTextSubmit(String query) {
+        return false;
+    }
+
+    @Override
+    public boolean onQueryTextChange(String newText) {
+        if (mAdapter != null) {
+            mAdapter.getFilter().filter(newText);
+        }
+        return false;
+    }
+
+    @Override
+    public int getMetricsCategory() {
+        // TODO: use a new metrics id?
+        return MetricsEvent.ZONE_PICKER;
+    }
+
+    public interface OnListItemClickListener {
+        void onListItemClick(int position);
+    }
+
+}
diff --git a/src/com/android/settings/datetime/timezone/FixedOffsetPicker.java b/src/com/android/settings/datetime/timezone/FixedOffsetPicker.java
new file mode 100644
index 0000000..3d8b826
--- /dev/null
+++ b/src/com/android/settings/datetime/timezone/FixedOffsetPicker.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2018 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.datetime.timezone;
+
+import android.icu.util.TimeZone;
+
+import com.android.settings.R;
+import com.android.settings.datetime.timezone.model.TimeZoneData;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+
+/**
+ * Render a list of fixed offset time zone {@class TimeZoneInfo} into a list view.
+ */
+public class FixedOffsetPicker extends BaseTimeZoneInfoPicker {
+    /**
+     * Range of integer fixed UTC offsets shown in the pickers.
+     */
+    private static final int MIN_HOURS_OFFSET = -14;
+    private static final int MAX_HOURS_OFFSET = +12;
+
+    public FixedOffsetPicker() {
+        super(R.string.date_time_select_fixed_offset_time_zones,
+                R.string.search_settings, false, false);
+    }
+
+    @Override
+    public List<TimeZoneInfo> getAllTimeZoneInfos(TimeZoneData timeZoneData) {
+        return loadFixedOffsets();
+    }
+
+    /**
+     * Returns a {@link TimeZoneInfo} for each fixed offset time zone, such as UTC or GMT+4. The
+     * returned list will be sorted in a reasonable way for display.
+     */
+    private List<TimeZoneInfo> loadFixedOffsets() {
+        final TimeZoneInfo.Formatter formatter = new TimeZoneInfo.Formatter(getLocale(),
+                new Date());
+        final List<TimeZoneInfo> timeZoneInfos = new ArrayList<>();
+        timeZoneInfos.add(formatter.format(TimeZone.getFrozenTimeZone("Etc/UTC")));
+        for (int hoursOffset = MAX_HOURS_OFFSET; hoursOffset >= MIN_HOURS_OFFSET; --hoursOffset) {
+            if (hoursOffset == 0) {
+                // UTC is handled above, so don't add GMT +/-0 again.
+                continue;
+            }
+            final String id = String.format(Locale.US, "Etc/GMT%+d", hoursOffset);
+            timeZoneInfos.add(formatter.format(TimeZone.getFrozenTimeZone(id)));
+        }
+        return Collections.unmodifiableList(timeZoneInfos);
+    }
+}
diff --git a/src/com/android/settings/datetime/timezone/RegionSearchPicker.java b/src/com/android/settings/datetime/timezone/RegionSearchPicker.java
new file mode 100644
index 0000000..1381b20
--- /dev/null
+++ b/src/com/android/settings/datetime/timezone/RegionSearchPicker.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2018 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.datetime.timezone;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.graphics.Paint;
+import android.icu.text.Collator;
+import android.icu.text.LocaleDisplayNames;
+import android.os.Bundle;
+import android.util.Log;
+
+import com.android.settings.R;
+import com.android.settings.core.SubSettingLauncher;
+import com.android.settings.datetime.timezone.model.FilteredCountryTimeZones;
+import com.android.settings.datetime.timezone.model.TimeZoneData;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ * Render a list of regions into a list view.
+ */
+public class RegionSearchPicker extends BaseTimeZonePicker {
+    private static final int REQUEST_CODE_ZONE_PICKER = 1;
+    private static final String TAG = "RegionSearchPicker";
+
+    private BaseTimeZoneAdapter<RegionItem> mAdapter;
+    private TimeZoneData mTimeZoneData;
+
+    public RegionSearchPicker() {
+        super(R.string.date_time_select_region, R.string.search_settings, true, true);
+    }
+
+    @Override
+    protected BaseTimeZoneAdapter createAdapter(TimeZoneData timeZoneData) {
+        mTimeZoneData = timeZoneData;
+        mAdapter = new BaseTimeZoneAdapter<>(createAdapterItem(timeZoneData.getRegionIds()),
+                this::onListItemClick, getLocale(), false);
+        return mAdapter;
+    }
+
+    private void onListItemClick(int position) {
+        final String regionId = mAdapter.getItem(position).getId();
+        final FilteredCountryTimeZones countryTimeZones = mTimeZoneData.lookupCountryTimeZones(
+                regionId);
+        final Activity activity = getActivity();
+        if (countryTimeZones == null || countryTimeZones.getTimeZoneIds().isEmpty()) {
+            Log.e(TAG, "Region has no time zones: " + regionId);
+            activity.setResult(Activity.RESULT_CANCELED);
+            activity.finish();
+            return;
+        }
+
+        List<String> timeZoneIds = countryTimeZones.getTimeZoneIds();
+        // Choose the time zone associated the region if there is only one time zone in that region
+        if (timeZoneIds.size() == 1) {
+            final Intent resultData = new Intent()
+                    .putExtra(EXTRA_RESULT_REGION_ID, regionId)
+                    .putExtra(EXTRA_RESULT_TIME_ZONE_ID, timeZoneIds.get(0));
+            getActivity().setResult(Activity.RESULT_OK, resultData);
+            getActivity().finish();
+        } else {
+            // Launch the zone picker and let the user choose a time zone from the list of
+            // time zones associated with the region.
+            final Bundle args = new Bundle();
+            args.putString(RegionZonePicker.EXTRA_REGION_ID, regionId);
+            new SubSettingLauncher(getContext())
+                    .setDestination(RegionZonePicker.class.getCanonicalName())
+                    .setArguments(args)
+                    .setSourceMetricsCategory(getMetricsCategory())
+                    .setResultListener(this, REQUEST_CODE_ZONE_PICKER)
+                    .launch();
+        }
+    }
+
+    @Override
+    public void onActivityResult(int requestCode, int resultCode, Intent data) {
+        if (requestCode == REQUEST_CODE_ZONE_PICKER) {
+            if (resultCode == Activity.RESULT_OK) {
+                getActivity().setResult(Activity.RESULT_OK, data);
+            }
+            getActivity().finish();
+        }
+    }
+
+    private List<RegionItem> createAdapterItem(Set<String> regionIds) {
+        final Collator collator = Collator.getInstance(getLocale());
+        final TreeSet<RegionItem> items = new TreeSet<>(new RegionInfoComparator(collator));
+        final Paint paint = new Paint();
+        final LocaleDisplayNames localeDisplayNames = LocaleDisplayNames.getInstance(getLocale());
+        long i = 0;
+        for (String regionId : regionIds) {
+            String name = localeDisplayNames.regionDisplayName(regionId);
+            String regionalIndicator = createRegionalIndicator(regionId, paint);
+            items.add(new RegionItem(i++, regionId, name, regionalIndicator));
+        }
+        return new ArrayList<>(items);
+    }
+
+    /**
+     * Create a Unicode Region Indicator Symbol for a given region id (a.k.a flag emoji). If the
+     * system can't render a flag for this region or the input is not a region id, this returns
+     * {@code null}.
+     *
+     * @param id the two-character region id.
+     * @param paint Paint contains the glyph
+     * @return a String representing the flag of the region or {@code null}.
+     */
+    private static String createRegionalIndicator(String id, Paint paint) {
+        if (id.length() != 2) {
+            return null;
+        }
+        final char c1 = id.charAt(0);
+        final char c2 = id.charAt(1);
+        if ('A' > c1 || c1 > 'Z' || 'A' > c2 || c2 > 'Z') {
+            return null;
+        }
+        // Regional Indicator A is U+1F1E6 which is 0xD83C 0xDDE6 in UTF-16.
+        final String regionalIndicator = new String(
+            new char[]{0xd83c, (char) (0xdde6 - 'A' + c1), 0xd83c, (char) (0xdde6 - 'A' + c2)});
+        if (!paint.hasGlyph(regionalIndicator)) {
+            return null;
+        }
+        return regionalIndicator;
+    }
+
+    private static class RegionItem implements BaseTimeZoneAdapter.AdapterItem {
+
+        private final String mId;
+        private final String mName;
+        private final String mRegionalIndicator;
+        private final long mItemId;
+        private final String[] mSearchKeys;
+
+        RegionItem(long itemId, String id, String name, String regionalIndicator) {
+            mId = id;
+            mName = name;
+            mRegionalIndicator = regionalIndicator;
+            mItemId = itemId;
+            // Allow to search with ISO_3166-1 alpha-2 code. It's handy for english users in some
+            // countries, e.g. US for United States. It's not best search keys for users, but
+            // ICU doesn't have the data for the alias names of a region.
+            mSearchKeys = new String[] {mId, mName};
+        }
+
+        public String getId() {
+            return mId;
+        }
+
+        @Override
+        public CharSequence getTitle() {
+            return mName;
+        }
+
+        @Override
+        public CharSequence getSummary() {
+            return null;
+        }
+
+        @Override
+        public String getIconText() {
+            return mRegionalIndicator;
+        }
+
+        @Override
+        public String getCurrentTime() {
+            return null;
+        }
+
+        @Override
+        public long getItemId() {
+            return mItemId;
+        }
+
+        @Override
+        public String[] getSearchKeys() {
+            return mSearchKeys;
+        }
+    }
+
+    private static class RegionInfoComparator implements Comparator<RegionItem> {
+        private final Collator mCollator;
+
+        RegionInfoComparator(Collator collator) {
+            mCollator = collator;
+        }
+
+        @Override
+        public int compare(RegionItem r1, RegionItem r2) {
+            return mCollator.compare(r1.getTitle(), r2.getTitle());
+        }
+    }
+}
diff --git a/src/com/android/settings/datetime/timezone/RegionZonePicker.java b/src/com/android/settings/datetime/timezone/RegionZonePicker.java
new file mode 100644
index 0000000..7805241
--- /dev/null
+++ b/src/com/android/settings/datetime/timezone/RegionZonePicker.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2018 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.datetime.timezone;
+
+import android.content.Intent;
+import android.icu.text.Collator;
+import android.icu.util.TimeZone;
+import android.support.annotation.VisibleForTesting;
+import android.util.Log;
+
+import com.android.settings.R;
+import com.android.settings.datetime.timezone.model.FilteredCountryTimeZones;
+import com.android.settings.datetime.timezone.model.TimeZoneData;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.List;
+import java.util.TreeSet;
+
+/**
+ * Given a region, render a list of time zone {@class TimeZoneInfo} into a list view.
+ */
+public class RegionZonePicker extends BaseTimeZoneInfoPicker {
+
+    public static final String EXTRA_REGION_ID =
+            "com.android.settings.datetime.timezone.region_id";
+
+    public RegionZonePicker() {
+        super(R.string.date_time_select_zone, R.string.search_settings, true, false);
+    }
+
+    /**
+     * Add the extra region id into the result.
+     */
+    @Override
+    protected Intent prepareResultData(TimeZoneInfo selectedTimeZoneInfo) {
+        final Intent intent = super.prepareResultData(selectedTimeZoneInfo);
+        intent.putExtra(EXTRA_RESULT_REGION_ID, getArguments().getString(EXTRA_REGION_ID));
+        return intent;
+    }
+
+    @Override
+    public List<TimeZoneInfo> getAllTimeZoneInfos(TimeZoneData timeZoneData) {
+        if (getArguments() == null) {
+            Log.e(TAG, "getArguments() == null");
+            getActivity().finish();
+        }
+        String regionId = getArguments().getString(EXTRA_REGION_ID);
+
+        FilteredCountryTimeZones filteredCountryTimeZones = timeZoneData.lookupCountryTimeZones(
+                regionId);
+        if (filteredCountryTimeZones == null) {
+            Log.e(TAG, "region id is not valid: " + regionId);
+            getActivity().finish();
+        }
+
+        // It could be a timely operations if there are many time zones. A region in time zone data
+        // contains a maximum of 29 time zones currently. It may change in the future, but it's
+        // unlikely to be changed drastically.
+        return getRegionTimeZoneInfo(filteredCountryTimeZones.getTimeZoneIds());
+    }
+
+    /**
+     * Returns a list of {@link TimeZoneInfo} objects. The returned list will be sorted properly for
+     * display in the locale.It may be smaller than the input collection, if equivalent IDs are
+     * passed in.
+     *
+     * @param timeZoneIds a list of Olson IDs.
+     */
+    public List<TimeZoneInfo> getRegionTimeZoneInfo(Collection<String> timeZoneIds) {
+        final TimeZoneInfo.Formatter formatter = new TimeZoneInfo.Formatter(getLocale(),
+                new Date());
+        final TreeSet<TimeZoneInfo> timeZoneInfos =
+                new TreeSet<>(new TimeZoneInfoComparator(Collator.getInstance(getLocale()),
+                        new Date()));
+
+        for (final String timeZoneId : timeZoneIds) {
+            final TimeZone timeZone = TimeZone.getFrozenTimeZone(timeZoneId);
+            // Skip time zone ICU isn't aware.
+            if (timeZone.getID().equals(TimeZone.UNKNOWN_ZONE_ID)) {
+                continue;
+            }
+            timeZoneInfos.add(formatter.format(timeZone));
+        }
+        return Collections.unmodifiableList(new ArrayList<>(timeZoneInfos));
+    }
+
+    @VisibleForTesting
+    static class TimeZoneInfoComparator implements Comparator<TimeZoneInfo> {
+        private Collator mCollator;
+        private final Date mNow;
+
+        @VisibleForTesting
+        TimeZoneInfoComparator(Collator collator, Date now) {
+            mCollator = collator;
+            mNow = now;
+        }
+
+        @Override
+        public int compare(TimeZoneInfo tzi1, TimeZoneInfo tzi2) {
+            int result = Integer.compare(tzi1.getTimeZone().getOffset(mNow.getTime()),
+                    tzi2.getTimeZone().getOffset(mNow.getTime()));
+            if (result == 0) {
+                result = Integer.compare(tzi1.getTimeZone().getRawOffset(),
+                    tzi2.getTimeZone().getRawOffset());
+            }
+            if (result == 0) {
+                result = mCollator.compare(tzi1.getExemplarLocation(), tzi2.getExemplarLocation());
+            }
+            if (result == 0 && tzi1.getGenericName() != null && tzi2.getGenericName() != null) {
+                result = mCollator.compare(tzi1.getGenericName(), tzi2.getGenericName());
+            }
+            return result;
+        }
+    }
+}
diff --git a/src/com/android/settings/datetime/timezone/SpannableUtil.java b/src/com/android/settings/datetime/timezone/SpannableUtil.java
new file mode 100644
index 0000000..49c3e7d
--- /dev/null
+++ b/src/com/android/settings/datetime/timezone/SpannableUtil.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2018 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.datetime.timezone;
+
+import android.annotation.StringRes;
+import android.content.res.Resources;
+import android.text.Spannable;
+import android.text.SpannableStringBuilder;
+
+import java.util.Formatter;
+import java.util.Locale;
+
+
+public class SpannableUtil {
+
+    /**
+     * {@class Resources} has no method to format string resource with {@class Spannable} a
+     * rguments. It's a helper method for this purpose.
+     */
+    public static Spannable getResourcesText(Resources res, @StringRes int resId,
+            Object... args) {
+        final Locale locale = res.getConfiguration().getLocales().get(0);
+        final SpannableStringBuilder builder = new SpannableStringBuilder();
+        new Formatter(builder, locale).format(res.getString(resId), args);
+        return builder;
+    }
+}
diff --git a/src/com/android/settings/datetime/timezone/model/TimeZoneData.java b/src/com/android/settings/datetime/timezone/model/TimeZoneData.java
index a863bfc..b78534d 100644
--- a/src/com/android/settings/datetime/timezone/model/TimeZoneData.java
+++ b/src/com/android/settings/datetime/timezone/model/TimeZoneData.java
@@ -57,7 +57,7 @@
     }
 
     @VisibleForTesting
-    TimeZoneData(CountryZonesFinder countryZonesFinder) {
+    public TimeZoneData(CountryZonesFinder countryZonesFinder) {
         mCountryZonesFinder = countryZonesFinder;
         mRegionIds = getNormalizedRegionIds(mCountryZonesFinder.lookupAllCountryIsoCodes());
     }
diff --git a/src/com/android/settings/enterprise/ActionDisabledByAdminDialog.java b/src/com/android/settings/enterprise/ActionDisabledByAdminDialog.java
new file mode 100644
index 0000000..37c5124
--- /dev/null
+++ b/src/com/android/settings/enterprise/ActionDisabledByAdminDialog.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2018 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.enterprise;
+
+import android.app.Activity;
+import android.app.admin.DevicePolicyManager;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.UserHandle;
+
+import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+
+public class ActionDisabledByAdminDialog extends Activity
+        implements DialogInterface.OnDismissListener {
+
+    private ActionDisabledByAdminDialogHelper mDialogHelper;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        final RestrictedLockUtils.EnforcedAdmin enforcedAdmin =
+                getAdminDetailsFromIntent(getIntent());
+        final String restriction = getRestrictionFromIntent(getIntent());
+        mDialogHelper = new ActionDisabledByAdminDialogHelper(this);
+        mDialogHelper.prepareDialogBuilder(restriction, enforcedAdmin)
+                .setOnDismissListener(this)
+                .show();
+    }
+
+    @Override
+    public void onNewIntent(Intent intent) {
+        super.onNewIntent(intent);
+        final EnforcedAdmin admin = getAdminDetailsFromIntent(intent);
+        final String restriction = getRestrictionFromIntent(intent);
+        mDialogHelper.updateDialog(restriction, admin);
+    }
+
+    @android.support.annotation.VisibleForTesting
+    EnforcedAdmin getAdminDetailsFromIntent(Intent intent) {
+        final EnforcedAdmin admin = new EnforcedAdmin(null, UserHandle.myUserId());
+        if (intent == null) {
+            return admin;
+        }
+        admin.component = intent.getParcelableExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN);
+        admin.userId = intent.getIntExtra(Intent.EXTRA_USER_ID, UserHandle.myUserId());
+        return admin;
+    }
+
+    @android.support.annotation.VisibleForTesting
+    String getRestrictionFromIntent(Intent intent) {
+        if (intent == null) return null;
+        return intent.getStringExtra(DevicePolicyManager.EXTRA_RESTRICTION);
+    }
+
+    @Override
+    public void onDismiss(DialogInterface dialog) {
+        finish();
+    }
+}
diff --git a/src/com/android/settings/enterprise/ActionDisabledByAdminDialogHelper.java b/src/com/android/settings/enterprise/ActionDisabledByAdminDialogHelper.java
new file mode 100644
index 0000000..3429957
--- /dev/null
+++ b/src/com/android/settings/enterprise/ActionDisabledByAdminDialogHelper.java
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2018 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.enterprise;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.AppGlobals;
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.graphics.drawable.Drawable;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.support.annotation.VisibleForTesting;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.settings.DeviceAdminAdd;
+import com.android.settings.R;
+import com.android.settings.Settings;
+import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+
+import java.util.Objects;
+
+/**
+ * Helper class for {@link ActionDisabledByAdminDialog} which sets up the dialog.
+ */
+public class ActionDisabledByAdminDialogHelper {
+
+    private static final String TAG = ActionDisabledByAdminDialogHelper.class.getName();
+    private EnforcedAdmin mEnforcedAdmin;
+    private ViewGroup mDialogView;
+    private String mRestriction = null;
+    private Activity mActivity;
+
+    public ActionDisabledByAdminDialogHelper(Activity activity) {
+        mActivity = activity;
+    }
+
+    public AlertDialog.Builder prepareDialogBuilder(String restriction,
+            EnforcedAdmin enforcedAdmin) {
+        mEnforcedAdmin = enforcedAdmin;
+        mRestriction = restriction;
+
+        final AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
+        mDialogView = (ViewGroup) LayoutInflater.from(builder.getContext()).inflate(
+                R.layout.admin_support_details_dialog, null);
+        initializeDialogViews(mDialogView, mEnforcedAdmin.component, mEnforcedAdmin.userId,
+                mRestriction);
+        return builder
+            .setPositiveButton(R.string.okay, null)
+            .setNeutralButton(R.string.admin_more_details,
+                    (dialog, which) -> {
+                        showAdminPolicies(mEnforcedAdmin, mActivity);
+                        mActivity.finish();
+                    })
+            .setView(mDialogView);
+    }
+
+    public void updateDialog(String restriction, EnforcedAdmin admin) {
+        if (mEnforcedAdmin.equals(admin) && Objects.equals(mRestriction, restriction)) {
+            return;
+        }
+        mEnforcedAdmin = admin;
+        mRestriction = restriction;
+        initializeDialogViews(mDialogView, mEnforcedAdmin.component, mEnforcedAdmin.userId,
+                mRestriction);
+    }
+
+    private void initializeDialogViews(View root, ComponentName admin, int userId,
+            String restriction) {
+        if (admin == null) {
+            return;
+        }
+        if (!RestrictedLockUtils.isAdminInCurrentUserOrProfile(mActivity, admin)
+                || !RestrictedLockUtils.isCurrentUserOrProfile(mActivity, userId)) {
+            admin = null;
+        } else {
+            ActivityInfo ai = null;
+            try {
+                ai = AppGlobals.getPackageManager().getReceiverInfo(admin, 0 /* flags */,
+                        userId);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Missing reciever info", e);
+            }
+            if (ai != null) {
+                final Drawable icon = ai.loadIcon(mActivity.getPackageManager());
+                final Drawable badgedIcon = mActivity.getPackageManager().getUserBadgedIcon(
+                        icon, new UserHandle(userId));
+                ((ImageView) root.findViewById(R.id.admin_support_icon)).setImageDrawable(
+                        badgedIcon);
+            }
+        }
+
+        setAdminSupportTitle(root, restriction);
+        setAdminSupportDetails(mActivity, root, new EnforcedAdmin(admin, userId));
+    }
+
+    @VisibleForTesting
+    void setAdminSupportTitle(View root, String restriction) {
+        final TextView titleView = root.findViewById(R.id.admin_support_dialog_title);
+        if (titleView == null) {
+            return;
+        }
+        if (restriction == null) {
+            titleView.setText(R.string.disabled_by_policy_title);
+            return;
+        }
+        switch (restriction) {
+            case UserManager.DISALLOW_ADJUST_VOLUME:
+                titleView.setText(R.string.disabled_by_policy_title_adjust_volume);
+                break;
+            case UserManager.DISALLOW_OUTGOING_CALLS:
+                titleView.setText(R.string.disabled_by_policy_title_outgoing_calls);
+                break;
+            case UserManager.DISALLOW_SMS:
+                titleView.setText(R.string.disabled_by_policy_title_sms);
+                break;
+            case DevicePolicyManager.POLICY_DISABLE_CAMERA:
+                titleView.setText(R.string.disabled_by_policy_title_camera);
+                break;
+            case DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE:
+                titleView.setText(R.string.disabled_by_policy_title_screen_capture);
+                break;
+            case DevicePolicyManager.POLICY_MANDATORY_BACKUPS:
+                titleView.setText(R.string.disabled_by_policy_title_turn_off_backups);
+                break;
+            default:
+                // Use general text if no specialized title applies
+                titleView.setText(R.string.disabled_by_policy_title);
+        }
+    }
+
+    @VisibleForTesting
+    void setAdminSupportDetails(final Activity activity, final View root,
+            final EnforcedAdmin enforcedAdmin) {
+        if (enforcedAdmin == null || enforcedAdmin.component == null) {
+            return;
+        }
+        final DevicePolicyManager dpm = (DevicePolicyManager) activity.getSystemService(
+                Context.DEVICE_POLICY_SERVICE);
+        if (!RestrictedLockUtils.isAdminInCurrentUserOrProfile(activity,
+                enforcedAdmin.component) || !RestrictedLockUtils.isCurrentUserOrProfile(
+                activity, enforcedAdmin.userId)) {
+            enforcedAdmin.component = null;
+        } else {
+            if (enforcedAdmin.userId == UserHandle.USER_NULL) {
+                enforcedAdmin.userId = UserHandle.myUserId();
+            }
+            CharSequence supportMessage = null;
+            if (UserHandle.isSameApp(Process.myUid(), Process.SYSTEM_UID)) {
+                supportMessage = dpm.getShortSupportMessageForUser(
+                        enforcedAdmin.component, enforcedAdmin.userId);
+            }
+            if (supportMessage != null) {
+                final TextView textView = root.findViewById(R.id.admin_support_msg);
+                textView.setText(supportMessage);
+            }
+        }
+    }
+
+    @VisibleForTesting
+    void showAdminPolicies(final EnforcedAdmin enforcedAdmin, final Activity activity) {
+        final Intent intent = new Intent();
+        if (enforcedAdmin.component != null) {
+            intent.setClass(activity, DeviceAdminAdd.class);
+            intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN,
+                    enforcedAdmin.component);
+            intent.putExtra(DeviceAdminAdd.EXTRA_CALLED_FROM_SUPPORT_DIALOG, true);
+            // DeviceAdminAdd class may need to run as managed profile.
+            activity.startActivityAsUser(intent,
+                    new UserHandle(enforcedAdmin.userId));
+        } else {
+            intent.setClass(activity, Settings.DeviceAdminSettingsActivity.class);
+            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            // Activity merges both managed profile and parent users
+            // admins so show as same user as this activity.
+            activity.startActivity(intent);
+        }
+    }
+}
diff --git a/src/com/android/settings/enterprise/OWNERS b/src/com/android/settings/enterprise/OWNERS
index bab2fe2..5811673 100644
--- a/src/com/android/settings/enterprise/OWNERS
+++ b/src/com/android/settings/enterprise/OWNERS
@@ -1,4 +1,7 @@
 # Default reviewers for this and subdirectories.
 sandness@google.com
+tonymak@google.com
+yuemingw@google.com
+arangelov@google.com
 
 # Emergency approvers in case the above are not available
\ No newline at end of file
diff --git a/src/com/android/settings/fuelgauge/AppButtonsPreferenceController.java b/src/com/android/settings/fuelgauge/AppButtonsPreferenceController.java
index 4094e1f..854b855 100644
--- a/src/com/android/settings/fuelgauge/AppButtonsPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/AppButtonsPreferenceController.java
@@ -297,7 +297,9 @@
 
     @Override
     public void onPackageListChanged() {
-        refreshUi();
+        if (isAvailable()) {
+            refreshUi();
+        }
     }
 
     @Override
diff --git a/src/com/android/settings/fuelgauge/AutoRestrictionPreferenceController.java b/src/com/android/settings/fuelgauge/AutoRestrictionPreferenceController.java
new file mode 100644
index 0000000..e8e5ad9
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/AutoRestrictionPreferenceController.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.fuelgauge;
+
+import android.content.Context;
+import android.provider.Settings;
+import android.support.v14.preference.SwitchPreference;
+import android.support.v7.preference.Preference;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.overlay.FeatureFactory;
+
+/**
+ * Controller to change and update the auto restriction toggle
+ */
+public class AutoRestrictionPreferenceController extends BasePreferenceController implements
+        Preference.OnPreferenceChangeListener {
+    private static final String KEY_SMART_BATTERY = "auto_restriction";
+    private static final int ON = 1;
+    private static final int OFF = 0;
+    private PowerUsageFeatureProvider mPowerUsageFeatureProvider;
+
+    public AutoRestrictionPreferenceController(Context context) {
+        super(context, KEY_SMART_BATTERY);
+        mPowerUsageFeatureProvider = FeatureFactory.getFactory(
+                context).getPowerUsageFeatureProvider(context);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return mPowerUsageFeatureProvider.isSmartBatterySupported()
+                ? DISABLED_UNSUPPORTED
+                : AVAILABLE;
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        super.updateState(preference);
+        final boolean smartBatteryOn = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.APP_AUTO_RESTRICTION_ENABLED, ON) == ON;
+        ((SwitchPreference) preference).setChecked(smartBatteryOn);
+    }
+
+    @Override
+    public boolean onPreferenceChange(Preference preference, Object newValue) {
+        final boolean smartBatteryOn = (Boolean) newValue;
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.APP_AUTO_RESTRICTION_ENABLED,
+                smartBatteryOn ? ON : OFF);
+        return true;
+    }
+}
diff --git a/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java b/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java
index 3ba5ee4..de01533 100644
--- a/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java
@@ -22,6 +22,7 @@
 import android.graphics.drawable.Drawable;
 import android.os.BatteryStats;
 import android.os.Handler;
+import android.os.Looper;
 import android.os.Message;
 import android.os.Process;
 import android.os.UserHandle;
@@ -81,7 +82,7 @@
     private Context mPrefContext;
     SparseArray<List<Anomaly>> mAnomalySparseArray;
 
-    private Handler mHandler = new Handler() {
+    private Handler mHandler = new Handler(Looper.getMainLooper()) {
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
@@ -149,7 +150,7 @@
 
     @Override
     public boolean isAvailable() {
-        return FeatureFlagUtils.isEnabled(mContext, FeatureFlags.BATTERY_DISPLAY_APP_LIST);
+        return true;
     }
 
     @Override
@@ -186,12 +187,17 @@
         }
     }
 
-    public void refreshAppListGroup(BatteryStatsHelper statsHelper, boolean showAllApps,
-            CharSequence timeSequence) {
+    public void refreshAppListGroup(BatteryStatsHelper statsHelper, boolean showAllApps) {
         if (!isAvailable()) {
             return;
         }
+
         mBatteryStatsHelper = statsHelper;
+        final long lastFullChargeTime = mBatteryUtils.calculateLastFullChargeTime(
+                mBatteryStatsHelper, System.currentTimeMillis());
+        final CharSequence timeSequence = StringUtil.formatRelativeTime(mContext,
+                lastFullChargeTime,
+                false);
         final int resId = showAllApps ? R.string.power_usage_list_summary_device
                 : R.string.power_usage_list_summary;
         mAppListGroup.setTitle(TextUtils.expandTemplate(mContext.getText(resId), timeSequence));
@@ -361,7 +367,7 @@
         final long usageTimeMs = sipper.usageTimeMs;
         if (usageTimeMs >= DateUtils.MINUTE_IN_MILLIS) {
             final CharSequence timeSequence =
-                StringUtil.formatElapsedTime(mContext, usageTimeMs, false);
+                    StringUtil.formatElapsedTime(mContext, usageTimeMs, false);
             preference.setSummary(
                     (sipper.drainType != DrainType.APP || mBatteryUtils.shouldHideSipper(sipper))
                             ? timeSequence
diff --git a/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java b/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java
index 2e94e2c..327a6c5 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java
@@ -13,134 +13,58 @@
  */
 package com.android.settings.fuelgauge;
 
-import android.app.Activity;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.pm.PackageManager;
-import android.content.pm.UserInfo;
 import android.os.BatteryManager;
-import android.os.BatteryStats;
 import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.os.UserManager;
 import android.provider.SearchIndexableResource;
-import android.support.annotation.ColorInt;
-import android.support.annotation.IntDef;
-import android.support.annotation.NonNull;
-import android.support.annotation.StringRes;
 import android.support.annotation.VisibleForTesting;
-import android.support.v7.preference.Preference;
-import android.support.v7.preference.PreferenceGroup;
-import android.text.TextUtils;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
 
 import com.android.internal.logging.nano.MetricsProto;
-import com.android.internal.os.BatterySipper;
-import com.android.internal.os.BatterySipper.DrainType;
-import com.android.internal.os.BatteryStatsHelper;
 import com.android.settings.R;
-import com.android.settings.Utils;
-import com.android.settings.datausage.DataUsageUtils;
-import com.android.settings.fuelgauge.PowerUsageAdvanced.PowerUsageData.UsageType;
+import com.android.settings.SettingsActivity;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settingslib.core.AbstractPreferenceController;
-
 import com.android.settingslib.utils.StringUtil;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
+
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 
 public class PowerUsageAdvanced extends PowerUsageBase {
     private static final String TAG = "AdvancedBatteryUsage";
     private static final String KEY_BATTERY_GRAPH = "battery_graph";
-    private static final String KEY_BATTERY_USAGE_LIST = "battery_usage_list";
-    private static final int STATUS_TYPE = BatteryStats.STATS_SINCE_CHARGED;
+    private static final String KEY_APP_LIST = "app_list";
+    private static final String KEY_SHOW_ALL_APPS = "show_all_apps";
+    @VisibleForTesting
+    static final int MENU_TOGGLE_APPS = Menu.FIRST + 1;
 
     @VisibleForTesting
-    final int[] mUsageTypes = {
-            UsageType.WIFI,
-            UsageType.CELL,
-            UsageType.SYSTEM,
-            UsageType.BLUETOOTH,
-            UsageType.USER,
-            UsageType.IDLE,
-            UsageType.APP,
-            UsageType.UNACCOUNTED,
-            UsageType.OVERCOUNTED};
-
-    @VisibleForTesting BatteryHistoryPreference mHistPref;
-    @VisibleForTesting PreferenceGroup mUsageListGroup;
+    BatteryHistoryPreference mHistPref;
     private BatteryUtils mBatteryUtils;
     private PowerUsageFeatureProvider mPowerUsageFeatureProvider;
-    private PackageManager mPackageManager;
-    private UserManager mUserManager;
-    private Map<Integer, PowerUsageData> mBatteryDataMap;
-
-    Handler mHandler = new Handler() {
-
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case BatteryEntry.MSG_UPDATE_NAME_ICON:
-                    final int dischargeAmount = mStatsHelper.getStats().getDischargeAmount(
-                            STATUS_TYPE);
-                    final double totalPower = mStatsHelper.getTotalPower();
-                    final BatteryEntry entry = (BatteryEntry) msg.obj;
-                    final int usageType = extractUsageType(entry.sipper);
-
-                    PowerUsageData usageData = mBatteryDataMap.get(usageType);
-                    Preference pref = findPreference(String.valueOf(usageType));
-                    if (pref != null && usageData != null) {
-                        updateUsageDataSummary(usageData, totalPower, dischargeAmount);
-                        pref.setSummary(usageData.summary);
-                    }
-                    break;
-                case BatteryEntry.MSG_REPORT_FULLY_DRAWN:
-                    Activity activity = getActivity();
-                    if (activity != null) {
-                        activity.reportFullyDrawn();
-                    }
-                    break;
-            }
-            super.handleMessage(msg);
-        }
-    };
+    private BatteryAppListPreferenceController mBatteryAppListPreferenceController;
+    @VisibleForTesting
+    boolean mShowAllApps = false;
 
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
+        final Context context = getContext();
 
         mHistPref = (BatteryHistoryPreference) findPreference(KEY_BATTERY_GRAPH);
-        mUsageListGroup = (PreferenceGroup) findPreference(KEY_BATTERY_USAGE_LIST);
-
-        final Context context = getContext();
         mPowerUsageFeatureProvider = FeatureFactory.getFactory(context)
                 .getPowerUsageFeatureProvider(context);
-        mPackageManager = context.getPackageManager();
-        mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
         mBatteryUtils = BatteryUtils.getInstance(context);
 
         // init the summary so other preferences won't have unnecessary move
         updateHistPrefSummary(context);
-    }
-
-    @Override
-    public void onResume() {
-        super.onResume();
-    }
-
-    @Override
-    public void onPause() {
-        BatteryEntry.stopRequestQueue();
-        mHandler.removeMessages(BatteryEntry.MSG_UPDATE_NAME_ICON);
-        super.onPause();
+        restoreSavedInstance(icicle);
     }
 
     @Override
@@ -167,23 +91,62 @@
     }
 
     @Override
+    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+        menu.add(Menu.NONE, MENU_TOGGLE_APPS, Menu.NONE,
+                mShowAllApps ? R.string.hide_extra_apps : R.string.show_all_apps);
+        super.onCreateOptionsMenu(menu, inflater);
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        switch (item.getItemId()) {
+            case MENU_TOGGLE_APPS:
+                mShowAllApps = !mShowAllApps;
+                item.setTitle(mShowAllApps ? R.string.hide_extra_apps : R.string.show_all_apps);
+                mMetricsFeatureProvider.action(getContext(),
+                        MetricsProto.MetricsEvent.ACTION_SETTINGS_MENU_BATTERY_APPS_TOGGLE,
+                        mShowAllApps);
+                restartBatteryStatsLoader();
+                return true;
+            default:
+                return super.onOptionsItemSelected(item);
+        }
+    }
+
+    @VisibleForTesting
+    void restoreSavedInstance(Bundle savedInstance) {
+        if (savedInstance != null) {
+            mShowAllApps = savedInstance.getBoolean(KEY_SHOW_ALL_APPS, false);
+        }
+    }
+
+    @Override
+    public void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+        outState.putBoolean(KEY_SHOW_ALL_APPS, mShowAllApps);
+    }
+
+    @Override
     protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
-        return null;
+        final List<AbstractPreferenceController> controllers = new ArrayList<>();
+
+        mBatteryAppListPreferenceController = new BatteryAppListPreferenceController(context,
+                KEY_APP_LIST, getLifecycle(), (SettingsActivity) getActivity(), this);
+        controllers.add(mBatteryAppListPreferenceController);
+
+        return controllers;
     }
 
     @Override
     protected void refreshUi() {
-        final long startTime = System.currentTimeMillis();
         final Context context = getContext();
         if (context == null) {
             return;
         }
         updatePreference(mHistPref);
-        refreshPowerUsageDataList(mStatsHelper, mUsageListGroup);
         updateHistPrefSummary(context);
 
-        BatteryEntry.startRequestQueue();
-        BatteryUtils.logRuntime(TAG, "refreshUI", startTime);
+        mBatteryAppListPreferenceController.refreshAppListGroup(mStatsHelper, mShowAllApps);
     }
 
     private void updateHistPrefSummary(Context context) {
@@ -199,278 +162,6 @@
         }
     }
 
-    @VisibleForTesting
-    void refreshPowerUsageDataList(BatteryStatsHelper statsHelper,
-            PreferenceGroup preferenceGroup) {
-        List<PowerUsageData> dataList = parsePowerUsageData(statsHelper);
-        preferenceGroup.removeAll();
-        for (int i = 0, size = dataList.size(); i < size; i++) {
-            final PowerUsageData batteryData = dataList.get(i);
-            if (shouldHideCategory(batteryData)) {
-                continue;
-            }
-            final PowerGaugePreference pref = new PowerGaugePreference(getPrefContext());
-
-            pref.setKey(String.valueOf(batteryData.usageType));
-            pref.setTitle(batteryData.titleResId);
-            pref.setSummary(batteryData.summary);
-            pref.setPercent(batteryData.percentage);
-            pref.setSelectable(false);
-            preferenceGroup.addPreference(pref);
-        }
-    }
-
-    @VisibleForTesting
-    @UsageType
-    int extractUsageType(BatterySipper sipper) {
-        final DrainType drainType = sipper.drainType;
-        final int uid = sipper.getUid();
-
-        if (drainType == DrainType.WIFI) {
-            return UsageType.WIFI;
-        } else if (drainType == DrainType.BLUETOOTH) {
-            return UsageType.BLUETOOTH;
-        } else if (drainType == DrainType.IDLE) {
-            return UsageType.IDLE;
-        } else if (drainType == DrainType.USER) {
-            return UsageType.USER;
-        } else if (drainType == DrainType.CELL) {
-            return UsageType.CELL;
-        } else if (drainType == DrainType.UNACCOUNTED) {
-            return UsageType.UNACCOUNTED;
-        } else if (drainType == DrainType.OVERCOUNTED) {
-            return UsageType.OVERCOUNTED;
-        } else if (mPowerUsageFeatureProvider.isTypeSystem(sipper)
-                || mPowerUsageFeatureProvider.isTypeService(sipper)) {
-            return UsageType.SYSTEM;
-        } else {
-            return UsageType.APP;
-        }
-    }
-
-    @VisibleForTesting
-    boolean shouldHideCategory(PowerUsageData powerUsageData) {
-        return powerUsageData.usageType == UsageType.UNACCOUNTED
-                || powerUsageData.usageType == UsageType.OVERCOUNTED
-                || (powerUsageData.usageType == UsageType.USER && isSingleNormalUser())
-                || (powerUsageData.usageType == UsageType.CELL
-                && !DataUsageUtils.hasMobileData(getContext()));
-    }
-
-    @VisibleForTesting
-    boolean shouldShowBatterySipper(BatterySipper batterySipper) {
-        return batterySipper.drainType != DrainType.SCREEN;
-    }
-
-    @VisibleForTesting
-    List<PowerUsageData> parsePowerUsageData(BatteryStatsHelper statusHelper) {
-        final List<BatterySipper> batterySippers = statusHelper.getUsageList();
-        final Map<Integer, PowerUsageData> batteryDataMap = new HashMap<>();
-
-        for (final @UsageType Integer type : mUsageTypes) {
-            batteryDataMap.put(type, new PowerUsageData(type));
-        }
-
-        // Accumulate power usage based on usage type
-        for (final BatterySipper sipper : batterySippers) {
-            sipper.mPackages = mPackageManager.getPackagesForUid(sipper.getUid());
-            final PowerUsageData usageData = batteryDataMap.get(extractUsageType(sipper));
-            usageData.totalPowerMah += sipper.totalPowerMah;
-            if (sipper.drainType == DrainType.APP && sipper.usageTimeMs != 0) {
-                sipper.usageTimeMs = mBatteryUtils.getProcessTimeMs(
-                        BatteryUtils.StatusType.FOREGROUND, sipper.uidObj, STATUS_TYPE);
-            }
-            usageData.totalUsageTimeMs += sipper.usageTimeMs;
-            if (shouldShowBatterySipper(sipper)) {
-                usageData.usageList.add(sipper);
-            }
-        }
-
-        final List<PowerUsageData> batteryDataList = new ArrayList<>(batteryDataMap.values());
-        final int dischargeAmount = statusHelper.getStats().getDischargeAmount(STATUS_TYPE);
-        final double totalPower = statusHelper.getTotalPower();
-        final double hiddenPower = calculateHiddenPower(batteryDataList);
-        for (final PowerUsageData usageData : batteryDataList) {
-            usageData.percentage = mBatteryUtils.calculateBatteryPercent(usageData.totalPowerMah,
-                    totalPower, hiddenPower, dischargeAmount);
-            updateUsageDataSummary(usageData, totalPower, dischargeAmount);
-        }
-
-        Collections.sort(batteryDataList);
-
-        mBatteryDataMap = batteryDataMap;
-        return batteryDataList;
-    }
-
-    @VisibleForTesting
-    double calculateHiddenPower(List<PowerUsageData> batteryDataList) {
-        for (final PowerUsageData usageData : batteryDataList) {
-            if (usageData.usageType == UsageType.UNACCOUNTED) {
-                return usageData.totalPowerMah;
-            }
-        }
-
-        return 0;
-    }
-
-    @VisibleForTesting
-    void updateUsageDataSummary(PowerUsageData usageData, double totalPower, int dischargeAmount) {
-        if (shouldHideSummary(usageData)) {
-            return;
-        }
-        if (usageData.usageList.size() <= 1) {
-            CharSequence timeSequence = StringUtil.formatElapsedTime(getContext(),
-                    usageData.totalUsageTimeMs, false);
-            usageData.summary = usageData.usageType == UsageType.IDLE ? timeSequence
-                    : TextUtils.expandTemplate(getText(R.string.battery_used_for), timeSequence);
-        } else {
-            BatterySipper sipper = findBatterySipperWithMaxBatteryUsage(usageData.usageList);
-            BatteryEntry batteryEntry = new BatteryEntry(getContext(), mHandler, mUserManager,
-                    sipper);
-            final double percentage = (sipper.totalPowerMah / totalPower) * dischargeAmount;
-            usageData.summary = getString(R.string.battery_used_by,
-                    Utils.formatPercentage(percentage, true), batteryEntry.name);
-        }
-    }
-
-    @VisibleForTesting
-    boolean shouldHideSummary(PowerUsageData powerUsageData) {
-        @UsageType final int usageType = powerUsageData.usageType;
-
-        return usageType == UsageType.CELL
-                || usageType == UsageType.BLUETOOTH
-                || usageType == UsageType.WIFI
-                || usageType == UsageType.APP
-                || usageType == UsageType.SYSTEM;
-    }
-
-    @VisibleForTesting
-    BatterySipper findBatterySipperWithMaxBatteryUsage(List<BatterySipper> usageList) {
-        BatterySipper sipper = usageList.get(0);
-        for (int i = 1, size = usageList.size(); i < size; i++) {
-            final BatterySipper comparedSipper = usageList.get(i);
-            if (comparedSipper.totalPowerMah > sipper.totalPowerMah) {
-                sipper = comparedSipper;
-            }
-        }
-
-        return sipper;
-    }
-
-    @VisibleForTesting
-    void setPackageManager(PackageManager packageManager) {
-        mPackageManager = packageManager;
-    }
-
-    @VisibleForTesting
-    void setPowerUsageFeatureProvider(PowerUsageFeatureProvider provider) {
-        mPowerUsageFeatureProvider = provider;
-    }
-    @VisibleForTesting
-    void setUserManager(UserManager userManager) {
-        mUserManager = userManager;
-    }
-    @VisibleForTesting
-    void setBatteryUtils(BatteryUtils batteryUtils) {
-        mBatteryUtils = batteryUtils;
-    }
-
-    @VisibleForTesting
-    boolean isSingleNormalUser() {
-        int count = 0;
-        for (UserInfo userInfo : mUserManager.getUsers()) {
-            if (userInfo.isEnabled() && !userInfo.isManagedProfile()) {
-                count++;
-            }
-        }
-
-        return count == 1;
-    }
-
-    /**
-     * Class that contains data used in {@link PowerGaugePreference}.
-     */
-    @VisibleForTesting
-    static class PowerUsageData implements Comparable<PowerUsageData> {
-
-        @Retention(RetentionPolicy.SOURCE)
-        @IntDef({UsageType.APP,
-                UsageType.WIFI,
-                UsageType.CELL,
-                UsageType.SYSTEM,
-                UsageType.BLUETOOTH,
-                UsageType.USER,
-                UsageType.IDLE,
-                UsageType.UNACCOUNTED,
-                UsageType.OVERCOUNTED})
-        public @interface UsageType {
-            int APP = 0;
-            int WIFI = 1;
-            int CELL = 2;
-            int SYSTEM = 3;
-            int BLUETOOTH = 4;
-            int USER = 5;
-            int IDLE = 6;
-            int UNACCOUNTED = 7;
-            int OVERCOUNTED = 8;
-        }
-
-        @StringRes
-        public int titleResId;
-        public CharSequence summary;
-        public double percentage;
-        public double totalPowerMah;
-        public long totalUsageTimeMs;
-        @ColorInt
-        public int iconColor;
-        @UsageType
-        public int usageType;
-        public List<BatterySipper> usageList;
-
-        public PowerUsageData(@UsageType int usageType) {
-            this(usageType, 0);
-        }
-
-        public PowerUsageData(@UsageType int usageType, double totalPower) {
-            this.usageType = usageType;
-            totalPowerMah = 0;
-            totalUsageTimeMs = 0;
-            titleResId = getTitleResId(usageType);
-            totalPowerMah = totalPower;
-            usageList = new ArrayList<>();
-        }
-
-        private int getTitleResId(@UsageType int usageType) {
-            switch (usageType) {
-                case UsageType.WIFI:
-                    return R.string.power_wifi;
-                case UsageType.CELL:
-                    return R.string.power_cell;
-                case UsageType.SYSTEM:
-                    return R.string.power_system;
-                case UsageType.BLUETOOTH:
-                    return R.string.power_bluetooth;
-                case UsageType.USER:
-                    return R.string.power_user;
-                case UsageType.IDLE:
-                    return R.string.power_idle;
-                case UsageType.UNACCOUNTED:
-                    return R.string.power_unaccounted;
-                case UsageType.OVERCOUNTED:
-                    return R.string.power_overcounted;
-                case UsageType.APP:
-                default:
-                    return R.string.power_apps;
-            }
-        }
-
-        @Override
-        public int compareTo(@NonNull PowerUsageData powerUsageData) {
-            final int diff = Double.compare(powerUsageData.totalPowerMah, totalPowerMah);
-            return diff != 0 ? diff : usageType - powerUsageData.usageType;
-        }
-    }
-
     public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
             new BaseSearchIndexProvider() {
                 @Override
@@ -480,6 +171,16 @@
                     sir.xmlResId = R.xml.power_usage_advanced;
                     return Arrays.asList(sir);
                 }
+
+                @Override
+                public List<AbstractPreferenceController> createPreferenceControllers(
+                        Context context) {
+                    final List<AbstractPreferenceController> controllers = new ArrayList<>();
+                    controllers.add(new BatteryAppListPreferenceController(context,
+                            KEY_APP_LIST, null /* lifecycle */, null /* activity */,
+                            null /* fragment */));
+                    return controllers;
+                }
             };
 
 }
diff --git a/src/com/android/settings/fuelgauge/PowerUsageAdvancedLegacy.java b/src/com/android/settings/fuelgauge/PowerUsageAdvancedLegacy.java
new file mode 100644
index 0000000..a4e3fef
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/PowerUsageAdvancedLegacy.java
@@ -0,0 +1,485 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+package com.android.settings.fuelgauge;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.content.pm.UserInfo;
+import android.os.BatteryManager;
+import android.os.BatteryStats;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.UserManager;
+import android.provider.SearchIndexableResource;
+import android.support.annotation.ColorInt;
+import android.support.annotation.IntDef;
+import android.support.annotation.NonNull;
+import android.support.annotation.StringRes;
+import android.support.annotation.VisibleForTesting;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceGroup;
+import android.text.TextUtils;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.internal.os.BatterySipper;
+import com.android.internal.os.BatterySipper.DrainType;
+import com.android.internal.os.BatteryStatsHelper;
+import com.android.settings.R;
+import com.android.settings.Utils;
+import com.android.settings.datausage.DataUsageUtils;
+import com.android.settings.fuelgauge.PowerUsageAdvancedLegacy.PowerUsageData.UsageType;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settingslib.core.AbstractPreferenceController;
+
+import com.android.settingslib.utils.StringUtil;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class PowerUsageAdvancedLegacy extends PowerUsageBase {
+    private static final String TAG = "AdvancedBatteryUsage";
+    private static final String KEY_BATTERY_GRAPH = "battery_graph_legacy";
+    private static final String KEY_BATTERY_USAGE_LIST = "battery_usage_list_legacy";
+    private static final int STATUS_TYPE = BatteryStats.STATS_SINCE_CHARGED;
+
+    @VisibleForTesting
+    final int[] mUsageTypes = {
+            UsageType.WIFI,
+            UsageType.CELL,
+            UsageType.SYSTEM,
+            UsageType.BLUETOOTH,
+            UsageType.USER,
+            UsageType.IDLE,
+            UsageType.APP,
+            UsageType.UNACCOUNTED,
+            UsageType.OVERCOUNTED};
+
+    @VisibleForTesting BatteryHistoryPreference mHistPref;
+    @VisibleForTesting PreferenceGroup mUsageListGroup;
+    private BatteryUtils mBatteryUtils;
+    private PowerUsageFeatureProvider mPowerUsageFeatureProvider;
+    private PackageManager mPackageManager;
+    private UserManager mUserManager;
+    private Map<Integer, PowerUsageData> mBatteryDataMap;
+
+    Handler mHandler = new Handler() {
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case BatteryEntry.MSG_UPDATE_NAME_ICON:
+                    final int dischargeAmount = mStatsHelper.getStats().getDischargeAmount(
+                            STATUS_TYPE);
+                    final double totalPower = mStatsHelper.getTotalPower();
+                    final BatteryEntry entry = (BatteryEntry) msg.obj;
+                    final int usageType = extractUsageType(entry.sipper);
+
+                    PowerUsageData usageData = mBatteryDataMap.get(usageType);
+                    Preference pref = findPreference(String.valueOf(usageType));
+                    if (pref != null && usageData != null) {
+                        updateUsageDataSummary(usageData, totalPower, dischargeAmount);
+                        pref.setSummary(usageData.summary);
+                    }
+                    break;
+                case BatteryEntry.MSG_REPORT_FULLY_DRAWN:
+                    Activity activity = getActivity();
+                    if (activity != null) {
+                        activity.reportFullyDrawn();
+                    }
+                    break;
+            }
+            super.handleMessage(msg);
+        }
+    };
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        mHistPref = (BatteryHistoryPreference) findPreference(KEY_BATTERY_GRAPH);
+        mUsageListGroup = (PreferenceGroup) findPreference(KEY_BATTERY_USAGE_LIST);
+
+        final Context context = getContext();
+        mPowerUsageFeatureProvider = FeatureFactory.getFactory(context)
+                .getPowerUsageFeatureProvider(context);
+        mPackageManager = context.getPackageManager();
+        mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+        mBatteryUtils = BatteryUtils.getInstance(context);
+
+        // init the summary so other preferences won't have unnecessary move
+        updateHistPrefSummary(context);
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+    }
+
+    @Override
+    public void onPause() {
+        BatteryEntry.stopRequestQueue();
+        mHandler.removeMessages(BatteryEntry.MSG_UPDATE_NAME_ICON);
+        super.onPause();
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        if (getActivity().isChangingConfigurations()) {
+            BatteryEntry.clearUidCache();
+        }
+    }
+
+    @Override
+    public int getMetricsCategory() {
+        return MetricsProto.MetricsEvent.FUELGAUGE_BATTERY_HISTORY_DETAIL;
+    }
+
+    @Override
+    protected String getLogTag() {
+        return TAG;
+    }
+
+    @Override
+    protected int getPreferenceScreenResId() {
+        return R.xml.power_usage_advanced_legacy;
+    }
+
+    @Override
+    protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
+        return null;
+    }
+
+    @Override
+    protected void refreshUi() {
+        final long startTime = System.currentTimeMillis();
+        final Context context = getContext();
+        if (context == null) {
+            return;
+        }
+        updatePreference(mHistPref);
+        refreshPowerUsageDataList(mStatsHelper, mUsageListGroup);
+        updateHistPrefSummary(context);
+
+        BatteryEntry.startRequestQueue();
+        BatteryUtils.logRuntime(TAG, "refreshUI", startTime);
+    }
+
+    private void updateHistPrefSummary(Context context) {
+        Intent batteryIntent =
+                context.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
+        final boolean plugged = batteryIntent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1) != 0;
+
+        if (mPowerUsageFeatureProvider.isEnhancedBatteryPredictionEnabled(context) && !plugged) {
+            mHistPref.setBottomSummary(
+                    mPowerUsageFeatureProvider.getAdvancedUsageScreenInfoString());
+        } else {
+            mHistPref.hideBottomSummary();
+        }
+    }
+
+    @VisibleForTesting
+    void refreshPowerUsageDataList(BatteryStatsHelper statsHelper,
+            PreferenceGroup preferenceGroup) {
+        List<PowerUsageData> dataList = parsePowerUsageData(statsHelper);
+        preferenceGroup.removeAll();
+        for (int i = 0, size = dataList.size(); i < size; i++) {
+            final PowerUsageData batteryData = dataList.get(i);
+            if (shouldHideCategory(batteryData)) {
+                continue;
+            }
+            final PowerGaugePreference pref = new PowerGaugePreference(getPrefContext());
+
+            pref.setKey(String.valueOf(batteryData.usageType));
+            pref.setTitle(batteryData.titleResId);
+            pref.setSummary(batteryData.summary);
+            pref.setPercent(batteryData.percentage);
+            pref.setSelectable(false);
+            preferenceGroup.addPreference(pref);
+        }
+    }
+
+    @VisibleForTesting
+    @UsageType
+    int extractUsageType(BatterySipper sipper) {
+        final DrainType drainType = sipper.drainType;
+        final int uid = sipper.getUid();
+
+        if (drainType == DrainType.WIFI) {
+            return UsageType.WIFI;
+        } else if (drainType == DrainType.BLUETOOTH) {
+            return UsageType.BLUETOOTH;
+        } else if (drainType == DrainType.IDLE) {
+            return UsageType.IDLE;
+        } else if (drainType == DrainType.USER) {
+            return UsageType.USER;
+        } else if (drainType == DrainType.CELL) {
+            return UsageType.CELL;
+        } else if (drainType == DrainType.UNACCOUNTED) {
+            return UsageType.UNACCOUNTED;
+        } else if (drainType == DrainType.OVERCOUNTED) {
+            return UsageType.OVERCOUNTED;
+        } else if (mPowerUsageFeatureProvider.isTypeSystem(sipper)
+                || mPowerUsageFeatureProvider.isTypeService(sipper)) {
+            return UsageType.SYSTEM;
+        } else {
+            return UsageType.APP;
+        }
+    }
+
+    @VisibleForTesting
+    boolean shouldHideCategory(PowerUsageData powerUsageData) {
+        return powerUsageData.usageType == UsageType.UNACCOUNTED
+                || powerUsageData.usageType == UsageType.OVERCOUNTED
+                || (powerUsageData.usageType == UsageType.USER && isSingleNormalUser())
+                || (powerUsageData.usageType == UsageType.CELL
+                && !DataUsageUtils.hasMobileData(getContext()));
+    }
+
+    @VisibleForTesting
+    boolean shouldShowBatterySipper(BatterySipper batterySipper) {
+        return batterySipper.drainType != DrainType.SCREEN;
+    }
+
+    @VisibleForTesting
+    List<PowerUsageData> parsePowerUsageData(BatteryStatsHelper statusHelper) {
+        final List<BatterySipper> batterySippers = statusHelper.getUsageList();
+        final Map<Integer, PowerUsageData> batteryDataMap = new HashMap<>();
+
+        for (final @UsageType Integer type : mUsageTypes) {
+            batteryDataMap.put(type, new PowerUsageData(type));
+        }
+
+        // Accumulate power usage based on usage type
+        for (final BatterySipper sipper : batterySippers) {
+            sipper.mPackages = mPackageManager.getPackagesForUid(sipper.getUid());
+            final PowerUsageData usageData = batteryDataMap.get(extractUsageType(sipper));
+            usageData.totalPowerMah += sipper.totalPowerMah;
+            if (sipper.drainType == DrainType.APP && sipper.usageTimeMs != 0) {
+                sipper.usageTimeMs = mBatteryUtils.getProcessTimeMs(
+                        BatteryUtils.StatusType.FOREGROUND, sipper.uidObj, STATUS_TYPE);
+            }
+            usageData.totalUsageTimeMs += sipper.usageTimeMs;
+            if (shouldShowBatterySipper(sipper)) {
+                usageData.usageList.add(sipper);
+            }
+        }
+
+        final List<PowerUsageData> batteryDataList = new ArrayList<>(batteryDataMap.values());
+        final int dischargeAmount = statusHelper.getStats().getDischargeAmount(STATUS_TYPE);
+        final double totalPower = statusHelper.getTotalPower();
+        final double hiddenPower = calculateHiddenPower(batteryDataList);
+        for (final PowerUsageData usageData : batteryDataList) {
+            usageData.percentage = mBatteryUtils.calculateBatteryPercent(usageData.totalPowerMah,
+                    totalPower, hiddenPower, dischargeAmount);
+            updateUsageDataSummary(usageData, totalPower, dischargeAmount);
+        }
+
+        Collections.sort(batteryDataList);
+
+        mBatteryDataMap = batteryDataMap;
+        return batteryDataList;
+    }
+
+    @VisibleForTesting
+    double calculateHiddenPower(List<PowerUsageData> batteryDataList) {
+        for (final PowerUsageData usageData : batteryDataList) {
+            if (usageData.usageType == UsageType.UNACCOUNTED) {
+                return usageData.totalPowerMah;
+            }
+        }
+
+        return 0;
+    }
+
+    @VisibleForTesting
+    void updateUsageDataSummary(PowerUsageData usageData, double totalPower, int dischargeAmount) {
+        if (shouldHideSummary(usageData)) {
+            return;
+        }
+        if (usageData.usageList.size() <= 1) {
+            CharSequence timeSequence = StringUtil.formatElapsedTime(getContext(),
+                    usageData.totalUsageTimeMs, false);
+            usageData.summary = usageData.usageType == UsageType.IDLE ? timeSequence
+                    : TextUtils.expandTemplate(getText(R.string.battery_used_for), timeSequence);
+        } else {
+            BatterySipper sipper = findBatterySipperWithMaxBatteryUsage(usageData.usageList);
+            BatteryEntry batteryEntry = new BatteryEntry(getContext(), mHandler, mUserManager,
+                    sipper);
+            final double percentage = (sipper.totalPowerMah / totalPower) * dischargeAmount;
+            usageData.summary = getString(R.string.battery_used_by,
+                    Utils.formatPercentage(percentage, true), batteryEntry.name);
+        }
+    }
+
+    @VisibleForTesting
+    boolean shouldHideSummary(PowerUsageData powerUsageData) {
+        @UsageType final int usageType = powerUsageData.usageType;
+
+        return usageType == UsageType.CELL
+                || usageType == UsageType.BLUETOOTH
+                || usageType == UsageType.WIFI
+                || usageType == UsageType.APP
+                || usageType == UsageType.SYSTEM;
+    }
+
+    @VisibleForTesting
+    BatterySipper findBatterySipperWithMaxBatteryUsage(List<BatterySipper> usageList) {
+        BatterySipper sipper = usageList.get(0);
+        for (int i = 1, size = usageList.size(); i < size; i++) {
+            final BatterySipper comparedSipper = usageList.get(i);
+            if (comparedSipper.totalPowerMah > sipper.totalPowerMah) {
+                sipper = comparedSipper;
+            }
+        }
+
+        return sipper;
+    }
+
+    @VisibleForTesting
+    void setPackageManager(PackageManager packageManager) {
+        mPackageManager = packageManager;
+    }
+
+    @VisibleForTesting
+    void setPowerUsageFeatureProvider(PowerUsageFeatureProvider provider) {
+        mPowerUsageFeatureProvider = provider;
+    }
+    @VisibleForTesting
+    void setUserManager(UserManager userManager) {
+        mUserManager = userManager;
+    }
+    @VisibleForTesting
+    void setBatteryUtils(BatteryUtils batteryUtils) {
+        mBatteryUtils = batteryUtils;
+    }
+
+    @VisibleForTesting
+    boolean isSingleNormalUser() {
+        int count = 0;
+        for (UserInfo userInfo : mUserManager.getUsers()) {
+            if (userInfo.isEnabled() && !userInfo.isManagedProfile()) {
+                count++;
+            }
+        }
+
+        return count == 1;
+    }
+
+    /**
+     * Class that contains data used in {@link PowerGaugePreference}.
+     */
+    @VisibleForTesting
+    static class PowerUsageData implements Comparable<PowerUsageData> {
+
+        @Retention(RetentionPolicy.SOURCE)
+        @IntDef({UsageType.APP,
+                UsageType.WIFI,
+                UsageType.CELL,
+                UsageType.SYSTEM,
+                UsageType.BLUETOOTH,
+                UsageType.USER,
+                UsageType.IDLE,
+                UsageType.UNACCOUNTED,
+                UsageType.OVERCOUNTED})
+        public @interface UsageType {
+            int APP = 0;
+            int WIFI = 1;
+            int CELL = 2;
+            int SYSTEM = 3;
+            int BLUETOOTH = 4;
+            int USER = 5;
+            int IDLE = 6;
+            int UNACCOUNTED = 7;
+            int OVERCOUNTED = 8;
+        }
+
+        @StringRes
+        public int titleResId;
+        public CharSequence summary;
+        public double percentage;
+        public double totalPowerMah;
+        public long totalUsageTimeMs;
+        @ColorInt
+        public int iconColor;
+        @UsageType
+        public int usageType;
+        public List<BatterySipper> usageList;
+
+        public PowerUsageData(@UsageType int usageType) {
+            this(usageType, 0);
+        }
+
+        public PowerUsageData(@UsageType int usageType, double totalPower) {
+            this.usageType = usageType;
+            totalPowerMah = 0;
+            totalUsageTimeMs = 0;
+            titleResId = getTitleResId(usageType);
+            totalPowerMah = totalPower;
+            usageList = new ArrayList<>();
+        }
+
+        private int getTitleResId(@UsageType int usageType) {
+            switch (usageType) {
+                case UsageType.WIFI:
+                    return R.string.power_wifi;
+                case UsageType.CELL:
+                    return R.string.power_cell;
+                case UsageType.SYSTEM:
+                    return R.string.power_system;
+                case UsageType.BLUETOOTH:
+                    return R.string.power_bluetooth;
+                case UsageType.USER:
+                    return R.string.power_user;
+                case UsageType.IDLE:
+                    return R.string.power_idle;
+                case UsageType.UNACCOUNTED:
+                    return R.string.power_unaccounted;
+                case UsageType.OVERCOUNTED:
+                    return R.string.power_overcounted;
+                case UsageType.APP:
+                default:
+                    return R.string.power_apps;
+            }
+        }
+
+        @Override
+        public int compareTo(@NonNull PowerUsageData powerUsageData) {
+            final int diff = Double.compare(powerUsageData.totalPowerMah, totalPowerMah);
+            return diff != 0 ? diff : usageType - powerUsageData.usageType;
+        }
+    }
+
+    public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+            new BaseSearchIndexProvider() {
+                @Override
+                public List<SearchIndexableResource> getXmlResourcesToIndex(
+                        Context context, boolean enabled) {
+                    final SearchIndexableResource sir = new SearchIndexableResource(context);
+                    sir.xmlResId = R.xml.power_usage_advanced_legacy;
+                    return Arrays.asList(sir);
+                }
+            };
+
+}
diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
index 79675cb..861ee56 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
@@ -118,4 +118,9 @@
      * the caller
      */
     boolean getEarlyWarningSignal(Context context, String id);
+
+    /**
+     * Checks whether smart battery feature is supported in this device
+     */
+    boolean isSmartBatterySupported();
 }
diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
index 93c4e03..6c3897d 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
@@ -136,4 +136,9 @@
     public boolean getEarlyWarningSignal(Context context, String id) {
         return false;
     }
+
+    @Override
+    public boolean isSmartBatterySupported() {
+        return false;
+    }
 }
diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
index bf0b627..b64dc52 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
@@ -39,6 +39,7 @@
 import com.android.settings.SettingsActivity;
 import com.android.settings.Utils;
 import com.android.settings.applications.LayoutPreference;
+import com.android.settings.core.SubSettingLauncher;
 import com.android.settings.dashboard.SummaryLoader;
 import com.android.settings.display.BatteryPercentagePreferenceController;
 import com.android.settings.fuelgauge.anomaly.Anomaly;
@@ -49,7 +50,6 @@
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settingslib.core.AbstractPreferenceController;
-import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 import com.android.settingslib.utils.PowerUtil;
 import com.android.settingslib.utils.StringUtil;
@@ -68,7 +68,6 @@
     static final String TAG = "PowerUsageSummary";
 
     private static final boolean DEBUG = false;
-    private static final String KEY_APP_LIST = "app_list";
     private static final String KEY_BATTERY_HEADER = "battery_header";
     private static final String KEY_BATTERY_TIP = "battery_tip";
 
@@ -80,7 +79,10 @@
     static final int BATTERY_INFO_LOADER = 1;
     @VisibleForTesting
     static final int BATTERY_TIP_LOADER = 2;
-    private static final int MENU_STATS_TYPE = Menu.FIRST;
+    @VisibleForTesting
+    static final int MENU_STATS_TYPE = Menu.FIRST;
+    @VisibleForTesting
+    static final int MENU_ADVANCED_BATTERY = Menu.FIRST + 1;
     public static final int DEBUG_INFO_LOADER = 3;
 
     @VisibleForTesting
@@ -101,7 +103,6 @@
     SparseArray<List<Anomaly>> mAnomalySparseArray;
     @VisibleForTesting
     BatteryHeaderPreferenceController mBatteryHeaderPreferenceController;
-    private BatteryAppListPreferenceController mBatteryAppListPreferenceController;
     private BatteryTipPreferenceController mBatteryTipPreferenceController;
     private int mStatsType = BatteryStats.STATS_SINCE_CHARGED;
 
@@ -231,9 +232,6 @@
         mBatteryHeaderPreferenceController = new BatteryHeaderPreferenceController(
                 context, activity, this /* host */, lifecycle);
         controllers.add(mBatteryHeaderPreferenceController);
-        mBatteryAppListPreferenceController = new BatteryAppListPreferenceController(context,
-                KEY_APP_LIST, lifecycle, activity, this);
-        controllers.add(mBatteryAppListPreferenceController);
         mBatteryTipPreferenceController = new BatteryTipPreferenceController(context,
                 KEY_BATTERY_TIP, (SettingsActivity) getActivity(), this /* fragment */, this /*
                 BatteryTipListener */);
@@ -250,6 +248,8 @@
                     .setAlphabeticShortcut('t');
         }
 
+        menu.add(Menu.NONE, MENU_ADVANCED_BATTERY, Menu.NONE, R.string.advanced_battery_title);
+
         super.onCreateOptionsMenu(menu, inflater);
     }
 
@@ -260,11 +260,6 @@
 
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
-        final SettingsActivity sa = (SettingsActivity) getActivity();
-        final Context context = getContext();
-        final MetricsFeatureProvider metricsFeatureProvider =
-                FeatureFactory.getFactory(context).getMetricsFeatureProvider();
-
         switch (item.getItemId()) {
             case MENU_STATS_TYPE:
                 if (mStatsType == BatteryStats.STATS_SINCE_CHARGED) {
@@ -274,6 +269,13 @@
                 }
                 refreshUi();
                 return true;
+            case MENU_ADVANCED_BATTERY:
+                new SubSettingLauncher(getContext())
+                        .setDestination(PowerUsageAdvanced.class.getName())
+                        .setSourceMetricsCategory(getMetricsCategory())
+                        .setTitle(R.string.advanced_battery_title)
+                        .launch();
+                return true;
             default:
                 return super.onOptionsItemSelected(item);
         }
@@ -294,11 +296,6 @@
         updateLastFullChargePreference(lastFullChargeTime);
         mScreenUsagePref.setSubtitle(StringUtil.formatElapsedTime(getContext(),
                 mBatteryUtils.calculateScreenUsageTime(mStatsHelper), false));
-
-        final CharSequence timeSequence = StringUtil.formatRelativeTime(context, lastFullChargeTime,
-                false);
-        mBatteryAppListPreferenceController.refreshAppListGroup(mStatsHelper,
-                false /* showAllApps */, timeSequence);
     }
 
     @VisibleForTesting
diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummaryLegacy.java b/src/com/android/settings/fuelgauge/PowerUsageSummaryLegacy.java
index 79425cb..d321bb7 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageSummaryLegacy.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageSummaryLegacy.java
@@ -415,7 +415,7 @@
     private void performBatteryHeaderClick() {
         if (mPowerFeatureProvider.isAdvancedUiEnabled()) {
             new SubSettingLauncher(getContext())
-                    .setDestination(PowerUsageAdvanced.class.getName())
+                    .setDestination(PowerUsageAdvancedLegacy.class.getName())
                     .setSourceMetricsCategory(getMetricsCategory())
                     .setTitle(R.string.advanced_battery_title)
                     .launch();
diff --git a/src/com/android/settings/fuelgauge/SmartBatteryPreferenceController.java b/src/com/android/settings/fuelgauge/SmartBatteryPreferenceController.java
index ee5279e..8b99a43 100644
--- a/src/com/android/settings/fuelgauge/SmartBatteryPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/SmartBatteryPreferenceController.java
@@ -19,12 +19,11 @@
 
 import android.content.Context;
 import android.provider.Settings;
-import android.support.annotation.VisibleForTesting;
 import android.support.v14.preference.SwitchPreference;
 import android.support.v7.preference.Preference;
 
-import com.android.settings.applications.LayoutPreference;
 import com.android.settings.core.BasePreferenceController;
+import com.android.settings.overlay.FeatureFactory;
 
 /**
  * Controller to change and update the smart battery toggle
@@ -34,15 +33,19 @@
     private static final String KEY_SMART_BATTERY = "smart_battery";
     private static final int ON = 1;
     private static final int OFF = 0;
+    private PowerUsageFeatureProvider mPowerUsageFeatureProvider;
 
     public SmartBatteryPreferenceController(Context context) {
         super(context, KEY_SMART_BATTERY);
+        mPowerUsageFeatureProvider = FeatureFactory.getFactory(context)
+                .getPowerUsageFeatureProvider(context);
     }
 
     @Override
     public int getAvailabilityStatus() {
-        // TODO(b/71502850): get Availability from API. The device may not support it.
-        return AVAILABLE;
+        return mPowerUsageFeatureProvider.isSmartBatterySupported()
+                ? AVAILABLE
+                : DISABLED_UNSUPPORTED;
     }
 
     @Override
diff --git a/src/com/android/settings/nfc/AndroidBeam.java b/src/com/android/settings/nfc/AndroidBeam.java
index 8377f14..4e90680 100644
--- a/src/com/android/settings/nfc/AndroidBeam.java
+++ b/src/com/android/settings/nfc/AndroidBeam.java
@@ -28,11 +28,11 @@
 import android.widget.Switch;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settings.enterprise.ActionDisabledByAdminDialogHelper;
 import com.android.settingslib.HelpUtils;
 import com.android.settings.core.InstrumentedFragment;
 import com.android.settings.R;
 import com.android.settings.SettingsActivity;
-import com.android.settings.ShowAdminSupportDetailsDialog;
 import com.android.settings.widget.SwitchBar;
 import com.android.settingslib.RestrictedLockUtils;
 
@@ -70,11 +70,10 @@
         mBeamDisallowedByBase = RestrictedLockUtils.hasBaseUserRestriction(getActivity(),
                 UserManager.DISALLOW_OUTGOING_BEAM, UserHandle.myUserId());
         if (!mBeamDisallowedByBase && admin != null) {
-            View view = inflater.inflate(R.layout.admin_support_details_empty_view, null);
-            ShowAdminSupportDetailsDialog.setAdminSupportDetails(getActivity(), view, admin, false);
-            view.setVisibility(View.VISIBLE);
+            new ActionDisabledByAdminDialogHelper(getActivity())
+                    .prepareDialogBuilder(UserManager.DISALLOW_OUTGOING_BEAM, admin).show();
             mBeamDisallowedByOnlyAdmin = true;
-            return view;
+            return new View(getContext());
         }
         mView = inflater.inflate(R.layout.android_beam, container, false);
         return mView;
diff --git a/src/com/android/settings/search/SearchIndexableResourcesImpl.java b/src/com/android/settings/search/SearchIndexableResourcesImpl.java
index 87c2a91..1798d34 100644
--- a/src/com/android/settings/search/SearchIndexableResourcesImpl.java
+++ b/src/com/android/settings/search/SearchIndexableResourcesImpl.java
@@ -49,8 +49,9 @@
 import com.android.settings.display.ScreenZoomSettings;
 import com.android.settings.dream.DreamSettings;
 import com.android.settings.enterprise.EnterprisePrivacySettings;
-import com.android.settings.fuelgauge.batterysaver.BatterySaverSettings;
 import com.android.settings.fuelgauge.PowerUsageAdvanced;
+import com.android.settings.fuelgauge.PowerUsageAdvancedLegacy;
+import com.android.settings.fuelgauge.batterysaver.BatterySaverSettings;
 import com.android.settings.fuelgauge.PowerUsageSummary;
 import com.android.settings.fuelgauge.SmartBatterySettings;
 import com.android.settings.gestures.AssistGestureSettings;
@@ -122,6 +123,7 @@
         addIndex(ZenModeSettings.class);
         addIndex(StorageSettings.class);
         addIndex(PowerUsageAdvanced.class);
+        addIndex(PowerUsageAdvancedLegacy.class);
         addIndex(DefaultAppSettings.class);
         addIndex(ManageAssist.class);
         addIndex(SpecialAccessSettings.class);
diff --git a/src/com/android/settings/security/EncryptionStatusPreferenceController.java b/src/com/android/settings/security/EncryptionStatusPreferenceController.java
index 0978935..2341248 100644
--- a/src/com/android/settings/security/EncryptionStatusPreferenceController.java
+++ b/src/com/android/settings/security/EncryptionStatusPreferenceController.java
@@ -56,7 +56,7 @@
             if (TextUtils.equals(getPreferenceKey(), PREF_KEY_ENCRYPTION_DETAIL_PAGE)) {
                 preference.setFragment(CryptKeeperSettings.class.getName());
             }
-            preference.setSummary(R.string.summary_placeholder);
+            preference.setSummary(R.string.decryption_settings_summary);
         }
 
     }
diff --git a/tests/robotests/res/xml-mcc998/location_settings.xml b/tests/robotests/res/xml-mcc998/location_settings.xml
index 993af86..f61ca63 100644
--- a/tests/robotests/res/xml-mcc998/location_settings.xml
+++ b/tests/robotests/res/xml-mcc998/location_settings.xml
@@ -18,14 +18,20 @@
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
                   xmlns:settings="http://schemas.android.com/apk/res-auto"
                   android:key="fake_title_key"
-                  android:title="screen_title"
-                  settings:controller="com.android.settings.slices.FakePreferenceController">
+                  android:title="screen_title">
 
     <Preference
-        android:key="key"
+        android:key="key1"
         android:title="title"
         android:icon="@drawable/ic_android"
-        android:summary="summary"
+        android:summary="summary1"
         settings:controller="com.android.settings.core.BadPreferenceController"/>
 
+    <Preference
+        android:key="key2"
+        android:title="title"
+        android:icon="@drawable/ic_android"
+        android:summary="summary2"
+        settings:controller="com.android.settings.slices.FakePreferenceController"/>
+
 </PreferenceScreen>
\ No newline at end of file
diff --git a/tests/robotests/res/xml-mcc999/location_settings.xml b/tests/robotests/res/xml-mcc999/location_settings.xml
index 5619c77..de77bfa 100644
--- a/tests/robotests/res/xml-mcc999/location_settings.xml
+++ b/tests/robotests/res/xml-mcc999/location_settings.xml
@@ -17,8 +17,7 @@
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
                   xmlns:settings="http://schemas.android.com/apk/res-auto"
                   android:key="fake_title_key"
-                  android:title="screen_title"
-                  settings:controller="com.android.settings.slices.FakePreferenceController">
+                  android:title="screen_title">
 
     <Preference
         android:key="key"
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/InstantAppButtonsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/InstantAppButtonsPreferenceControllerTest.java
index 8a85d70..ad0a9fe 100644
--- a/tests/robotests/src/com/android/settings/applications/appinfo/InstantAppButtonsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/InstantAppButtonsPreferenceControllerTest.java
@@ -262,6 +262,9 @@
 
         verify(mFragment).startActivity(argThat(intent-> intent != null
             && intent.getAction().equals(Intent.ACTION_VIEW)
+            && intent.hasCategory(Intent.CATEGORY_BROWSABLE)
+            && (intent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) != 0
+            && TextUtils.equals(intent.getPackage(), TEST_AIA_PACKAGE_NAME)
             && TextUtils.equals(intent.getDataString(), launchUri)));
     }
 
diff --git a/tests/robotests/src/com/android/settings/dashboard/DashboardAdapterTest.java b/tests/robotests/src/com/android/settings/dashboard/DashboardAdapterTest.java
index e28e89d..5256ac4 100644
--- a/tests/robotests/src/com/android/settings/dashboard/DashboardAdapterTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/DashboardAdapterTest.java
@@ -16,8 +16,8 @@
 package com.android.settings.dashboard;
 
 import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
@@ -93,15 +93,16 @@
         mConditionList.add(mCondition);
         when(mCondition.shouldShow()).thenReturn(true);
         mDashboardAdapter = new DashboardAdapter(mContext, null /* savedInstanceState */,
-            mConditionList, null /* suggestionControllerMixin */, null /* lifecycle */);
+                mConditionList, null /* suggestionControllerMixin */, null /* lifecycle */);
         when(mView.getTag()).thenReturn(mCondition);
     }
 
     @Test
     public void testSuggestionDismissed_notOnlySuggestion_updateSuggestionOnly() {
         final DashboardAdapter adapter =
-            spy(new DashboardAdapter(mContext, null /* savedInstanceState */,
-                null /* conditions */, null /* suggestionControllerMixin */, null /* lifecycle */));
+                spy(new DashboardAdapter(mContext, null /* savedInstanceState */,
+                        null /* conditions */, null /* suggestionControllerMixin */,
+                        null /* lifecycle */));
         final List<Suggestion> suggestions = makeSuggestionsV2("pkg1", "pkg2", "pkg3");
         adapter.setSuggestions(suggestions);
 
@@ -114,7 +115,7 @@
         when(itemView.findViewById(android.R.id.summary)).thenReturn(mock(TextView.class));
         when(itemView.findViewById(android.R.id.title)).thenReturn(mock(TextView.class));
         final DashboardAdapter.SuggestionContainerHolder holder =
-            new DashboardAdapter.SuggestionContainerHolder(itemView);
+                new DashboardAdapter.SuggestionContainerHolder(itemView);
 
         adapter.onBindSuggestion(holder, 0);
 
@@ -124,17 +125,17 @@
         final Suggestion suggestionToRemove = suggestions.get(1);
         adapter.onSuggestionClosed(suggestionToRemove);
 
-        assertThat(adapter.mDashboardData).isEqualTo(dashboardData);
         assertThat(suggestions.size()).isEqualTo(2);
         assertThat(suggestions.contains(suggestionToRemove)).isFalse();
-        verify(adapter, never()).notifyDashboardDataChanged(any());
+        verify(adapter).notifyDashboardDataChanged(any());
     }
 
     @Test
     public void testSuggestionDismissed_onlySuggestion_updateDashboardData() {
         DashboardAdapter adapter =
-            spy(new DashboardAdapter(mContext, null /* savedInstanceState */,
-                null /* conditions */, null /* suggestionControllerMixin */, null /* lifecycle */));
+                spy(new DashboardAdapter(mContext, null /* savedInstanceState */,
+                        null /* conditions */, null /* suggestionControllerMixin */,
+                        null /* lifecycle */));
         final List<Suggestion> suggestions = makeSuggestionsV2("pkg1");
         adapter.setSuggestions(suggestions);
         final DashboardData dashboardData = adapter.mDashboardData;
@@ -149,7 +150,7 @@
     @Test
     public void testBindSuggestion_shouldSetSuggestionAdapterAndNoCrash() {
         mDashboardAdapter = new DashboardAdapter(mContext, null /* savedInstanceState */,
-            null /* conditions */, null /* suggestionControllerMixin */, null /* lifecycle */);
+                null /* conditions */, null /* suggestionControllerMixin */, null /* lifecycle */);
         final List<Suggestion> suggestions = makeSuggestionsV2("pkg1");
 
         mDashboardAdapter.setSuggestions(suggestions);
@@ -163,7 +164,7 @@
         when(itemView.findViewById(android.R.id.summary)).thenReturn(mock(TextView.class));
         when(itemView.findViewById(android.R.id.title)).thenReturn(mock(TextView.class));
         final DashboardAdapter.SuggestionContainerHolder holder =
-            new DashboardAdapter.SuggestionContainerHolder(itemView);
+                new DashboardAdapter.SuggestionContainerHolder(itemView);
 
         mDashboardAdapter.onBindSuggestion(holder, 0);
 
@@ -176,14 +177,14 @@
         final Context context = RuntimeEnvironment.application;
         final View view = LayoutInflater.from(context).inflate(R.layout.dashboard_tile, null);
         final DashboardAdapter.DashboardItemHolder holder =
-            new DashboardAdapter.DashboardItemHolder(view);
+                new DashboardAdapter.DashboardItemHolder(view);
         final Tile tile = new Tile();
         tile.icon = Icon.createWithResource(context, R.drawable.ic_settings);
         final IconCache iconCache = mock(IconCache.class);
         when(iconCache.getIcon(tile.icon)).thenReturn(context.getDrawable(R.drawable.ic_settings));
 
         mDashboardAdapter = new DashboardAdapter(context, null /* savedInstanceState */,
-            null /* conditions */, null /* suggestionControllerMixin */, null /* lifecycle */);
+                null /* conditions */, null /* suggestionControllerMixin */, null /* lifecycle */);
         ReflectionHelpers.setField(mDashboardAdapter, "mCache", iconCache);
         mDashboardAdapter.onBindTile(holder, tile);
 
@@ -191,11 +192,11 @@
     }
 
     @Test
-    public void onBindTile_externalTile_shouldNotUseGenericBackgroundIcon() {
+    public void onBindTile_externalTile_shouldUpdateIcon() {
         final Context context = RuntimeEnvironment.application;
         final View view = LayoutInflater.from(context).inflate(R.layout.dashboard_tile, null);
         final DashboardAdapter.DashboardItemHolder holder =
-            new DashboardAdapter.DashboardItemHolder(view);
+                new DashboardAdapter.DashboardItemHolder(view);
         final Tile tile = new Tile();
         tile.icon = mock(Icon.class);
         when(tile.icon.getResPackage()).thenReturn("another.package");
@@ -204,13 +205,36 @@
         when(iconCache.getIcon(tile.icon)).thenReturn(context.getDrawable(R.drawable.ic_settings));
 
         mDashboardAdapter = new DashboardAdapter(context, null /* savedInstanceState */,
-            null /* conditions */, null /* suggestionControllerMixin */, null /* lifecycle */);
+                null /* conditions */, null /* suggestionControllerMixin */, null /* lifecycle */);
         ReflectionHelpers.setField(mDashboardAdapter, "mCache", iconCache);
+
         mDashboardAdapter.onBindTile(holder, tile);
 
         verify(iconCache).updateIcon(eq(tile.icon), any(RoundedHomepageIcon.class));
     }
 
+    @Test
+    public void onBindTile_externalTile_usingRoundedHomepageIcon_shouldNotUpdateIcon() {
+        final Context context = RuntimeEnvironment.application;
+        final View view = LayoutInflater.from(context).inflate(R.layout.dashboard_tile, null);
+        final DashboardAdapter.DashboardItemHolder holder =
+                new DashboardAdapter.DashboardItemHolder(view);
+        final Tile tile = new Tile();
+        tile.icon = mock(Icon.class);
+        when(tile.icon.getResPackage()).thenReturn("another.package");
+
+        final IconCache iconCache = mock(IconCache.class);
+        when(iconCache.getIcon(tile.icon)).thenReturn(mock(RoundedHomepageIcon.class));
+
+        mDashboardAdapter = new DashboardAdapter(context, null /* savedInstanceState */,
+                null /* conditions */, null /* suggestionControllerMixin */, null /* lifecycle */);
+        ReflectionHelpers.setField(mDashboardAdapter, "mCache", iconCache);
+
+        mDashboardAdapter.onBindTile(holder, tile);
+
+        verify(iconCache, never()).updateIcon(eq(tile.icon), any(RoundedHomepageIcon.class));
+    }
+
     private List<Suggestion> makeSuggestionsV2(String... pkgNames) {
         final List<Suggestion> suggestions = new ArrayList<>();
         for (String pkgName : pkgNames) {
diff --git a/tests/robotests/src/com/android/settings/datetime/timezone/BaseTimeZoneAdapterTest.java b/tests/robotests/src/com/android/settings/datetime/timezone/BaseTimeZoneAdapterTest.java
new file mode 100644
index 0000000..c85c598
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/datetime/timezone/BaseTimeZoneAdapterTest.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2018 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.datetime.timezone;
+
+import android.support.v7.widget.RecyclerView.AdapterDataObserver;
+
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import static com.google.common.truth.Truth.assertThat;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class BaseTimeZoneAdapterTest {
+
+    @Test
+    public void testFilter() throws InterruptedException {
+        TestItem US = new TestItem("United States");
+        TestItem HK = new TestItem("Hong Kong");
+        TestItem UK = new TestItem("United Kingdom", new String[] { "United Kingdom",
+                "Great Britain"});
+        TestItem secretCountry = new TestItem("no name", new String[] { "Secret"});
+        List<TestItem> items = new ArrayList<>();
+        items.add(US);
+        items.add(HK);
+        items.add(UK);
+        items.add(secretCountry);
+
+        TestTimeZoneAdapter adapter = new TestTimeZoneAdapter(items);
+        assertSearch(adapter, "", items.toArray(new TestItem[items.size()]));
+        assertSearch(adapter, "Unit", US, UK);
+        assertSearch(adapter, "kon", HK);
+        assertSearch(adapter, "brit", UK);
+        assertSearch(adapter, "sec", secretCountry);
+    }
+
+    private void assertSearch(TestTimeZoneAdapter adapter , String searchText, TestItem... items)
+            throws InterruptedException {
+        Observer observer = new Observer(adapter);
+        adapter.getFilter().filter(searchText);
+        observer.await();
+        assertThat(adapter.getItemCount()).isEqualTo(items.length);
+        for (int i = 0; i < items.length; i++) {
+            assertThat(adapter.getItem(i)).isEqualTo(items[i]);
+        }
+    }
+
+    private static class Observer extends AdapterDataObserver {
+
+        private final CountDownLatch mLatch = new CountDownLatch(1);
+        private final TestTimeZoneAdapter mAdapter;
+
+        public Observer(TestTimeZoneAdapter adapter) {
+            mAdapter = adapter;
+            mAdapter.registerAdapterDataObserver(this);
+        }
+
+        @Override
+        public void onChanged() {
+            mAdapter.unregisterAdapterDataObserver(this);
+            mLatch.countDown();
+        }
+
+        public void await() throws InterruptedException {
+            mLatch.await(2L, TimeUnit.SECONDS);
+        }
+    }
+
+    private static class TestTimeZoneAdapter extends BaseTimeZoneAdapter<TestItem> {
+
+        public TestTimeZoneAdapter(List<TestItem> items) {
+            super(items, position -> {}, Locale.US, false);
+        }
+    }
+
+    private static class TestItem implements BaseTimeZoneAdapter.AdapterItem {
+
+        private final String mTitle;
+        private final String[] mSearchKeys;
+
+        TestItem(String title) {
+            this(title, new String[] { title });
+        }
+
+        TestItem(String title, String[] searchKeys) {
+            mTitle = title;
+            mSearchKeys = searchKeys;
+        }
+
+        @Override
+        public CharSequence getTitle() {
+            return mTitle;
+        }
+
+        @Override
+        public CharSequence getSummary() {
+            return null;
+        }
+
+        @Override
+        public String getIconText() {
+            return null;
+        }
+
+        @Override
+        public String getCurrentTime() {
+            return null;
+        }
+
+        @Override
+        public long getItemId() {
+            return 0;
+        }
+
+        @Override
+        public String[] getSearchKeys() {
+            return mSearchKeys;
+        }
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/datetime/timezone/BaseTimeZoneInfoPickerTest.java b/tests/robotests/src/com/android/settings/datetime/timezone/BaseTimeZoneInfoPickerTest.java
new file mode 100644
index 0000000..0d47a3a
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/datetime/timezone/BaseTimeZoneInfoPickerTest.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2018 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.datetime.timezone;
+
+import android.content.Context;
+import android.icu.util.TimeZone;
+
+import com.android.settings.datetime.timezone.model.TimeZoneData;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import com.google.common.truth.Truth;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+
+import static org.mockito.Mockito.mock;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(shadows = { BaseTimeZoneInfoPickerTest.ShadowDataFormat.class })
+public class BaseTimeZoneInfoPickerTest {
+    @Implements(android.text.format.DateFormat.class)
+    public static class ShadowDataFormat {
+
+        public static String sTimeFormatString = "";
+
+        @Implementation
+        public static String getTimeFormatString(Context context) {
+            return sTimeFormatString;
+        }
+    }
+
+    /**
+     * Verify the summary, title, and time label in a time zone item are formatted properly.
+     */
+    @Test
+    public void createAdapter_matchTimeZoneInfoAndOrder() {
+        ShadowDataFormat.sTimeFormatString = "HH:MM";
+        BaseTimeZoneInfoPicker picker = new TestBaseTimeZoneInfoPicker();
+        BaseTimeZoneAdapter adapter = picker.createAdapter(mock(TimeZoneData.class));
+        Truth.assertThat(adapter.getItemCount()).isEqualTo(2);
+
+        BaseTimeZoneAdapter.AdapterItem item1 = adapter.getItem(0);
+        Truth.assertThat(item1.getTitle().toString()).isEqualTo("Los Angeles");
+        Truth.assertThat(item1.getSummary().toString()).isEqualTo("Pacific Time (GMT-08:00)");
+        Truth.assertThat(item1.getCurrentTime())
+                .hasLength(ShadowDataFormat.sTimeFormatString.length());
+
+        BaseTimeZoneAdapter.AdapterItem item2 = adapter.getItem(1);
+        Truth.assertThat(item2.getTitle().toString()).isEqualTo("New York");
+        Truth.assertThat(item2.getSummary().toString()).isEqualTo("Eastern Time (GMT-05:00)");
+        Truth.assertThat(item2.getCurrentTime())
+                .hasLength(ShadowDataFormat.sTimeFormatString.length());
+    }
+
+    public static class TestBaseTimeZoneInfoPicker extends BaseTimeZoneInfoPicker {
+
+        public TestBaseTimeZoneInfoPicker() {
+            super(0, 0, false, false);
+        }
+
+        @Override
+        public List<TimeZoneInfo> getAllTimeZoneInfos(TimeZoneData timeZoneData) {
+            TimeZoneInfo zone1 = new TimeZoneInfo.Builder(
+                    TimeZone.getFrozenTimeZone("America/Los_Angeles"))
+                    .setGenericName("Pacific Time")
+                    .setStandardName("Pacific Standard Time")
+                    .setDaylightName("Pacific Daylight Time")
+                    .setExemplarLocation("Los Angeles")
+                    .setGmtOffset("GMT-08:00")
+                    .setItemId(0)
+                    .build();
+            TimeZoneInfo zone2 = new TimeZoneInfo.Builder(
+                    TimeZone.getFrozenTimeZone("America/New_York"))
+                    .setGenericName("Eastern Time")
+                    .setStandardName("Eastern Standard Time")
+                    .setDaylightName("Eastern Daylight Time")
+                    .setExemplarLocation("New York")
+                    .setGmtOffset("GMT-05:00")
+                    .setItemId(1)
+                    .build();
+
+            return Arrays.asList(zone1, zone2);
+        }
+
+        // Make the method public
+        @Override
+        public BaseTimeZoneAdapter createAdapter(TimeZoneData timeZoneData) {
+            return super.createAdapter(timeZoneData);
+        }
+
+        @Override
+        protected Locale getLocale() {
+            return Locale.US;
+        }
+
+        @Override
+        public Context getContext() {
+            return RuntimeEnvironment.application;
+        }
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/datetime/timezone/FixedOffsetPickerTest.java b/tests/robotests/src/com/android/settings/datetime/timezone/FixedOffsetPickerTest.java
new file mode 100644
index 0000000..1c555b0
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/datetime/timezone/FixedOffsetPickerTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2018 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.datetime.timezone;
+
+import com.android.settings.datetime.timezone.model.TimeZoneData;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import libcore.util.CountryZonesFinder;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+import java.util.stream.Collectors;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class FixedOffsetPickerTest {
+
+    @Test
+    public void getAllTimeZoneInfos_containsUtcAndGmtZones() {
+        List regionList = Collections.emptyList();
+        CountryZonesFinder finder = mock(CountryZonesFinder.class);
+        when(finder.lookupAllCountryIsoCodes()).thenReturn(regionList);
+
+        FixedOffsetPicker picker = new FixedOffsetPicker() {
+            @Override
+            protected Locale getLocale() {
+                return Locale.US;
+            }
+        };
+        List<TimeZoneInfo> infos = picker.getAllTimeZoneInfos(new TimeZoneData(finder));
+        List<String> tzIds = infos.stream().map(info -> info.getId()).collect(Collectors.toList());
+        tzIds.contains("Etc/Utc");
+        tzIds.contains("Etc/GMT-12");
+        tzIds.contains("Etc/GMT+14");
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/datetime/timezone/RegionSearchPickerTest.java b/tests/robotests/src/com/android/settings/datetime/timezone/RegionSearchPickerTest.java
new file mode 100644
index 0000000..b2c7f03
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/datetime/timezone/RegionSearchPickerTest.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2018 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.datetime.timezone;
+
+import com.android.settings.datetime.timezone.BaseTimeZoneAdapter.AdapterItem;
+import com.android.settings.datetime.timezone.model.TimeZoneData;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import libcore.util.CountryZonesFinder;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class RegionSearchPickerTest {
+
+    @Test
+    public void createAdapter_matchRegionName() {
+        List regionList = new ArrayList();
+        regionList.add("US");
+        CountryZonesFinder finder = mock(CountryZonesFinder.class);
+        when(finder.lookupAllCountryIsoCodes()).thenReturn(regionList);
+
+        RegionSearchPicker picker = new RegionSearchPicker() {
+            @Override
+            protected Locale getLocale() {
+                return Locale.US;
+            }
+        };
+        BaseTimeZoneAdapter adapter = picker.createAdapter(new TimeZoneData(finder));
+        assertEquals(1, adapter.getItemCount());
+        AdapterItem item = adapter.getItem(0);
+        assertEquals("United States", item.getTitle().toString());
+        assertThat(Arrays.asList(item.getSearchKeys())).contains("United States");
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/datetime/timezone/RegionZonePickerTest.java b/tests/robotests/src/com/android/settings/datetime/timezone/RegionZonePickerTest.java
new file mode 100644
index 0000000..e527270
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/datetime/timezone/RegionZonePickerTest.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2018 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.datetime.timezone;
+
+import android.icu.text.Collator;
+
+import com.android.settings.datetime.timezone.RegionZonePicker.TimeZoneInfoComparator;
+import com.android.settings.datetime.timezone.TimeZoneInfo.Formatter;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+
+import static com.google.common.truth.Truth.assertThat;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class RegionZonePickerTest {
+
+    @Test
+    public void compareTimeZoneInfo_matchGmtOrder() {
+        Date now = new Date(0); // 00:00 1, Jan 1970
+        Formatter formatter = new Formatter(Locale.US, now);
+        TimeZoneInfo timeZone1 = formatter.format("Pacific/Honolulu");
+        TimeZoneInfo timeZone2 = formatter.format("America/Los_Angeles");
+        TimeZoneInfo timeZone3 = formatter.format("America/Indiana/Marengo");
+        TimeZoneInfo timeZone4 = formatter.format("America/New_York");
+
+        TimeZoneInfoComparator comparator =
+                new TimeZoneInfoComparator(Collator.getInstance(Locale.US), now);
+
+        // Verify the sorted order
+        List<TimeZoneInfo> list = Arrays.asList(timeZone4, timeZone2, timeZone3, timeZone1);
+        Collections.sort(list, comparator);
+        assertThat(list).isEqualTo(Arrays.asList(timeZone1, timeZone2, timeZone3, timeZone4));
+    }
+
+}
diff --git a/tests/robotests/src/com/android/settings/datetime/timezone/SpannableUtilTest.java b/tests/robotests/src/com/android/settings/datetime/timezone/SpannableUtilTest.java
new file mode 100644
index 0000000..5517907
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/datetime/timezone/SpannableUtilTest.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2018 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.datetime.timezone;
+
+import android.text.Spannable;
+
+import com.android.settings.R;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+
+import static com.google.common.truth.Truth.assertThat;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class SpannableUtilTest {
+
+    @Test
+    public void testFormat() {
+        Spannable spannable = SpannableUtil.getResourcesText(
+                RuntimeEnvironment.application.getResources(), R.string.zone_info_offset_and_name,
+                "GMT+00:00", "UTC");
+        assertThat(spannable.toString()).isEqualTo("UTC (GMT+00:00)");
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/datetime/timezone/model/TimeZoneDataTest.java b/tests/robotests/src/com/android/settings/datetime/timezone/model/TimeZoneDataTest.java
index e6073a8..4a624b7 100644
--- a/tests/robotests/src/com/android/settings/datetime/timezone/model/TimeZoneDataTest.java
+++ b/tests/robotests/src/com/android/settings/datetime/timezone/model/TimeZoneDataTest.java
@@ -73,13 +73,13 @@
         CountryTimeZones US = mock(CountryTimeZones.class);
         when(US.getCountryIso()).thenReturn("us");
         when(US.getTimeZoneMappings()).thenReturn(Arrays.asList(
-           new CountryTimeZones.TimeZoneMapping("Unknown/Secret_City", true),
-           new CountryTimeZones.TimeZoneMapping("Unknown/Secret_City2", false)
+           TimeZoneMapping.createForTests("Unknown/Secret_City", true),
+           TimeZoneMapping.createForTests("Unknown/Secret_City2", false)
         ));
         CountryTimeZones GB = mock(CountryTimeZones.class);
         when(GB.getCountryIso()).thenReturn("gb");
         when(GB.getTimeZoneMappings()).thenReturn(Collections.singletonList(
-            new TimeZoneMapping("Unknown/Secret_City", true)
+            TimeZoneMapping.createForTests("Unknown/Secret_City", true)
         ));
         when(mCountryZonesFinder.lookupCountryTimeZonesForZoneId("Unknown/Secret_City"))
                 .thenReturn(Arrays.asList(US, GB));
diff --git a/tests/robotests/src/com/android/settings/enterprise/ActionDisabledByAdminDialogHelperTest.java b/tests/robotests/src/com/android/settings/enterprise/ActionDisabledByAdminDialogHelperTest.java
new file mode 100644
index 0000000..981ce13
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/enterprise/ActionDisabledByAdminDialogHelperTest.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2018 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.enterprise;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.app.Activity;
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.UserInfo;
+import android.os.Process;
+import android.os.UserManager;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.widget.TextView;
+
+import com.android.settings.DeviceAdminAdd;
+import com.android.settings.R;
+import com.android.settings.Settings;
+import com.android.settings.testutils.CustomActivity;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.ShadowActivity;
+import com.android.settings.testutils.shadow.ShadowDevicePolicyManager;
+import com.android.settings.testutils.shadow.ShadowProcess;
+import com.android.settings.testutils.shadow.ShadowUserManager;
+import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.Robolectric;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.Shadows;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadow.api.Shadow;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(shadows = {
+        ShadowDevicePolicyManager.class,
+        ShadowUserManager.class,
+        ShadowActivity.class,
+        ShadowProcess.class
+})
+public class ActionDisabledByAdminDialogHelperTest {
+    private ActionDisabledByAdminDialogHelper mHelper;
+    private Activity mActivity;
+    private org.robolectric.shadows.ShadowActivity mActivityShadow;
+
+    @Before
+    public void setUp() {
+        mActivity = Robolectric.buildActivity(CustomActivity.class).get();
+        mActivityShadow = Shadow.extract(mActivity);
+        mHelper = new ActionDisabledByAdminDialogHelper(mActivity);
+    }
+
+    @Test
+    public void testShowAdminPoliciesWithComponent() {
+        final int userId = 123;
+        final ComponentName component = new ComponentName("some.package.name",
+                "some.package.name.SomeClass");
+        final EnforcedAdmin admin = new EnforcedAdmin(component, userId);
+
+        mHelper.showAdminPolicies(admin, mActivity);
+
+        final Intent intent = mActivityShadow.getNextStartedActivity();
+        assertTrue(
+                intent.getBooleanExtra(DeviceAdminAdd.EXTRA_CALLED_FROM_SUPPORT_DIALOG, false));
+        assertEquals(component,
+                intent.getParcelableExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN));
+    }
+
+    @Test
+    public void testShowAdminPoliciesWithoutComponent() {
+        final int userId = 123;
+        final EnforcedAdmin admin = new EnforcedAdmin(null, userId);
+        mHelper.showAdminPolicies(admin, mActivity);
+        final Intent intent = mActivityShadow.getNextStartedActivity();
+        assertEquals(intent.getComponent(), new ComponentName(mActivity,
+                        Settings.DeviceAdminSettingsActivity.class.getName()));
+    }
+
+    @Test
+    public void testSetAdminSupportTitle() {
+        final ViewGroup view = new FrameLayout(mActivity);
+        final TextView textView = new TextView(mActivity);
+        textView.setId(R.id.admin_support_dialog_title);
+        view.addView(textView);
+
+        mHelper.setAdminSupportTitle(view, UserManager.DISALLOW_ADJUST_VOLUME);
+        assertEquals(Shadows.shadowOf(textView).innerText(),
+                mActivity.getString(R.string.disabled_by_policy_title_adjust_volume));
+
+        mHelper.setAdminSupportTitle(view, UserManager.DISALLOW_OUTGOING_CALLS);
+        assertEquals(Shadows.shadowOf(textView).innerText(),
+                mActivity.getString(R.string.disabled_by_policy_title_outgoing_calls));
+
+        mHelper.setAdminSupportTitle(view, UserManager.DISALLOW_SMS);
+        assertEquals(Shadows.shadowOf(textView).innerText(),
+                mActivity.getString(R.string.disabled_by_policy_title_sms));
+
+        mHelper.setAdminSupportTitle(view, DevicePolicyManager.POLICY_DISABLE_CAMERA);
+        assertEquals(Shadows.shadowOf(textView).innerText(),
+                mActivity.getString(R.string.disabled_by_policy_title_camera));
+
+        mHelper.setAdminSupportTitle(view, DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE);
+        assertEquals(Shadows.shadowOf(textView).innerText(),
+                mActivity.getString(R.string.disabled_by_policy_title_screen_capture));
+
+        mHelper.setAdminSupportTitle(view, DevicePolicyManager.POLICY_MANDATORY_BACKUPS);
+        assertEquals(Shadows.shadowOf(textView).innerText(),
+                mActivity.getString(R.string.disabled_by_policy_title_turn_off_backups));
+
+        mHelper.setAdminSupportTitle(view, "another restriction");
+        assertEquals(Shadows.shadowOf(textView).innerText(),
+                mActivity.getString(R.string.disabled_by_policy_title));
+
+        mHelper.setAdminSupportTitle(view, null);
+        assertEquals(Shadows.shadowOf(textView).innerText(),
+                mActivity.getString(R.string.disabled_by_policy_title));
+    }
+
+    @Test
+    public void testSetAdminSupportDetails() {
+        final DevicePolicyManager dpm = RuntimeEnvironment.application.getSystemService(
+                DevicePolicyManager.class);
+        final ShadowDevicePolicyManager dpmShadow = Shadow.extract(dpm);
+        final UserManager userManager = RuntimeEnvironment.application.getSystemService(
+                UserManager.class);
+        final ShadowUserManager userManagerShadow = Shadow.extract(userManager);
+        final ViewGroup view = new FrameLayout(mActivity);
+        final ComponentName component = new ComponentName("some.package.name",
+                "some.package.name.SomeClass");
+        final EnforcedAdmin admin = new EnforcedAdmin(component, 123);
+        final TextView textView = new TextView(mActivity);
+
+        textView.setId(R.id.admin_support_msg);
+        view.addView(textView);
+        dpmShadow.setShortSupportMessageForUser(component, 123, "some message");
+        dpmShadow.setIsAdminActiveAsUser(true);
+        userManagerShadow.addProfile(new UserInfo(123, null, 0));
+        ShadowProcess.setMyUid(Process.SYSTEM_UID);
+
+        mHelper.setAdminSupportDetails(mActivity, view, admin);
+        assertNotNull(admin.component);
+        assertEquals("some message", Shadows.shadowOf(textView).innerText());
+    }
+
+    @Test
+    public void testSetAdminSupportDetailsNotAdmin() {
+        final DevicePolicyManager dpm = RuntimeEnvironment.application.getSystemService(
+                DevicePolicyManager.class);
+        final ShadowDevicePolicyManager dpmShadow = Shadow.extract(dpm);
+        final UserManager userManager = RuntimeEnvironment.application.getSystemService(
+                UserManager.class);
+        final ShadowUserManager userManagerShadow = Shadow.extract(userManager);
+        final ComponentName component = new ComponentName("some.package.name",
+                "some.package.name.SomeClass");
+        final EnforcedAdmin admin = new EnforcedAdmin(component, 123);
+
+        dpmShadow.setShortSupportMessageForUser(component, 123, "some message");
+        dpmShadow.setIsAdminActiveAsUser(false);
+        userManagerShadow.addProfile(new UserInfo(123, null, 0));
+
+        mHelper.setAdminSupportDetails(mActivity, null, admin);
+        assertNull(admin.component);
+    }
+}
+
diff --git a/tests/robotests/src/com/android/settings/enterprise/ActionDisabledByAdminDialogTest.java b/tests/robotests/src/com/android/settings/enterprise/ActionDisabledByAdminDialogTest.java
new file mode 100644
index 0000000..ebdfad6
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/enterprise/ActionDisabledByAdminDialogTest.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2018 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.enterprise;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.os.UserHandle;
+
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class ActionDisabledByAdminDialogTest {
+
+    private ActionDisabledByAdminDialog mDialog;
+
+    @Before
+    public void setUp() {
+        mDialog = new ActionDisabledByAdminDialog();
+    }
+
+    @Test
+    public void testGetAdminDetailsFromIntent() {
+        final int userId = 123;
+        final ComponentName component = new ComponentName("com.some.package", ".SomeClass");
+        final EnforcedAdmin expectedAdmin = new EnforcedAdmin(component, userId);
+
+        final Intent intent = new Intent();
+        intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, component);
+        intent.putExtra(Intent.EXTRA_USER_ID, userId);
+        Assert.assertEquals(expectedAdmin, mDialog.getAdminDetailsFromIntent(intent));
+    }
+
+    @Test
+    public void testGetAdminDetailsFromNullIntent() {
+        final int userId = UserHandle.myUserId();
+        final EnforcedAdmin expectedAdmin = new EnforcedAdmin(null, userId);
+
+        Assert.assertEquals(expectedAdmin, mDialog.getAdminDetailsFromIntent(null));
+    }
+
+    @Test
+    public void testGetRestrictionFromIntent() {
+        final String restriction = "someRestriction";
+        final Intent intent = new Intent();
+
+        intent.putExtra(DevicePolicyManager.EXTRA_RESTRICTION, restriction);
+        Assert.assertEquals(restriction, mDialog.getRestrictionFromIntent(intent));
+    }
+
+    @Test
+    public void testGetRestrictionFromNullIntent() {
+        Assert.assertEquals(null, mDialog.getRestrictionFromIntent(null));
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/AppButtonsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/AppButtonsPreferenceControllerTest.java
index d2252a7..eebccd8 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/AppButtonsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/AppButtonsPreferenceControllerTest.java
@@ -26,6 +26,7 @@
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.doThrow;
 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;
@@ -137,7 +138,7 @@
     }
 
     @Test
-    public void testRetrieveAppEntry_hasAppEntry_notNull()
+    public void retrieveAppEntry_hasAppEntry_notNull()
             throws PackageManager.NameNotFoundException {
         doReturn(mPackageInfo).when(mPackageManger).getPackageInfo(anyString(), anyInt());
 
@@ -148,7 +149,7 @@
     }
 
     @Test
-    public void testRetrieveAppEntry_noAppEntry_null() throws PackageManager.NameNotFoundException {
+    public void retrieveAppEntry_noAppEntry_null() throws PackageManager.NameNotFoundException {
         doReturn(null).when(mState).getEntry(eq(PACKAGE_NAME), anyInt());
         doReturn(mPackageInfo).when(mPackageManger).getPackageInfo(anyString(), anyInt());
 
@@ -159,7 +160,7 @@
     }
 
     @Test
-    public void testRetrieveAppEntry_throwException_null() throws
+    public void retrieveAppEntry_throwException_null() throws
             PackageManager.NameNotFoundException {
         doReturn(mAppEntry).when(mState).getEntry(anyString(), anyInt());
         doThrow(new PackageManager.NameNotFoundException()).when(mPackageManger).getPackageInfo(
@@ -172,7 +173,7 @@
     }
 
     @Test
-    public void testUpdateUninstallButton_isSystemApp_handleAsDisableableButton() {
+    public void updateUninstallButton_isSystemApp_handleAsDisableableButton() {
         doReturn(false).when(mController).handleDisableable();
         mAppInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
 
@@ -183,7 +184,7 @@
     }
 
     @Test
-    public void testIsAvailable_nonInstantApp() throws Exception {
+    public void isAvailable_nonInstantApp() throws Exception {
         mController.mAppEntry = mAppEntry;
         ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
                 new InstantAppDataProvider() {
@@ -196,7 +197,7 @@
     }
 
     @Test
-    public void testIsAvailable_instantApp() throws Exception {
+    public void isAvailable_instantApp() throws Exception {
         mController.mAppEntry = mAppEntry;
         ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
                 new InstantAppDataProvider() {
@@ -209,7 +210,7 @@
     }
 
     @Test
-    public void testUpdateUninstallButton_isDeviceAdminApp_setButtonDisable() {
+    public void updateUninstallButton_isDeviceAdminApp_setButtonDisable() {
         doReturn(true).when(mController).handleDisableable();
         mAppInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
         doReturn(true).when(mDpm).packageHasActiveAdmins(anyString());
@@ -221,7 +222,7 @@
     }
 
     @Test
-    public void testUpdateUninstallButton_isProfileOrDeviceOwner_setButtonDisable() {
+    public void updateUninstallButton_isProfileOrDeviceOwner_setButtonDisable() {
         doReturn(true).when(mDpm).isDeviceOwnerAppOnAnyUser(anyString());
 
         mController.updateUninstallButton();
@@ -230,7 +231,7 @@
     }
 
     @Test
-    public void testUpdateUninstallButton_isDeviceProvisioningApp_setButtonDisable() {
+    public void updateUninstallButton_isDeviceProvisioningApp_setButtonDisable() {
         doReturn(true).when(mDpm).isDeviceOwnerAppOnAnyUser(anyString());
         when(mSettingsActivity.getResources().getString(anyInt())).thenReturn(PACKAGE_NAME);
 
@@ -240,7 +241,7 @@
     }
 
     @Test
-    public void testUpdateUninstallButton_isUninstallInQueue_setButtonDisable() {
+    public void updateUninstallButton_isUninstallInQueue_setButtonDisable() {
         doReturn(true).when(mDpm).isUninstallInQueue(any());
 
         mController.updateUninstallButton();
@@ -249,7 +250,7 @@
     }
 
     @Test
-    public void testUpdateUninstallButton_isHomeAppAndBundled_setButtonDisable() {
+    public void updateUninstallButton_isHomeAppAndBundled_setButtonDisable() {
         mAppInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
         mController.mHomePackages.add(PACKAGE_NAME);
 
@@ -259,7 +260,7 @@
     }
 
     @Test
-    public void testUpdateForceStopButton_HasActiveAdmins_setButtonDisable() {
+    public void updateForceStopButton_HasActiveAdmins_setButtonDisable() {
         doReturn(true).when(mDpm).packageHasActiveAdmins(anyString());
 
         mController.updateForceStopButton();
@@ -268,14 +269,14 @@
     }
 
     @Test
-    public void testUpdateForceStopButton_AppNotStopped_setButtonEnable() {
+    public void updateForceStopButton_AppNotStopped_setButtonEnable() {
         mController.updateForceStopButton();
 
         verify(mController).updateForceStopButtonInner(true);
     }
 
     @Test
-    public void testUninstallPkg_intentSent() {
+    public void uninstallPkg_intentSent() {
         mController.uninstallPkg(PACKAGE_NAME, ALL_USERS, DISABLE_AFTER_INSTALL);
 
         verify(mFragment).startActivityForResult(any(), eq(REQUEST_UNINSTALL));
@@ -287,7 +288,7 @@
     }
 
     @Test
-    public void testForceStopPackage_methodInvokedAndUpdated() {
+    public void forceStopPackage_methodInvokedAndUpdated() {
         final ApplicationsState.AppEntry appEntry = mock(ApplicationsState.AppEntry.class);
         doReturn(appEntry).when(mState).getEntry(anyString(), anyInt());
         doNothing().when(mController).updateForceStopButton();
@@ -300,7 +301,7 @@
     }
 
     @Test
-    public void testHandleDisableable_isHomeApp_notControllable() {
+    public void handleDisableable_isHomeApp_notControllable() {
         mController.mHomePackages.add(PACKAGE_NAME);
 
         final boolean controllable = mController.handleDisableable();
@@ -310,7 +311,7 @@
     }
 
     @Test
-    public void testHandleDisableable_isAppEnabled_controllable() {
+    public void handleDisableable_isAppEnabled_controllable() {
         mAppEntry.info.enabled = true;
         mAppEntry.info.enabledSetting = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
         doReturn(false).when(mController).isSystemPackage(any(), any(), any());
@@ -322,7 +323,7 @@
     }
 
     @Test
-    public void testHandleDisableable_isAppDisabled_controllable() {
+    public void handleDisableable_isAppDisabled_controllable() {
         mAppEntry.info.enabled = false;
         mAppEntry.info.enabledSetting = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
         doReturn(false).when(mController).isSystemPackage(any(), any(), any());
@@ -334,13 +335,33 @@
     }
 
     @Test
-    public void testRefreshUi_packageNull_shouldNotCrash() {
+    public void refreshUi_packageNull_shouldNotCrash() {
         mController.mPackageName = null;
 
         // Should not crash in this method
         assertThat(mController.refreshUi()).isFalse();
     }
 
+    @Test
+    public void onPackageListChanged_available_shouldRefreshUi() {
+        doReturn(true).when(mController).isAvailable();
+        doReturn(true).when(mController).refreshUi();
+
+        mController.onPackageListChanged();
+
+        verify(mController).refreshUi();
+    }
+
+    @Test
+    public void onPackageListChanged_notAvailable_shouldNotRefreshUiAndNoCrash() {
+        doReturn(false).when(mController).isAvailable();
+
+        mController.onPackageListChanged();
+
+        verify(mController, never()).refreshUi();
+        // Should not crash in this method
+    }
+
     /**
      * The test fragment which implements
      * {@link ButtonActionDialogFragment.AppButtonsDialogListener}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/AutoRestrictionPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/AutoRestrictionPreferenceControllerTest.java
new file mode 100644
index 0000000..241f550
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/AutoRestrictionPreferenceControllerTest.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.fuelgauge;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doReturn;
+
+import android.content.Context;
+import android.provider.Settings;
+import android.support.v14.preference.SwitchPreference;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.testutils.FakeFeatureFactory;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class AutoRestrictionPreferenceControllerTest {
+    private static final int ON = 1;
+    private static final int OFF = 0;
+
+    private AutoRestrictionPreferenceController mController;
+    private SwitchPreference mPreference;
+    private Context mContext;
+    private FakeFeatureFactory mFeatureFactory;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mFeatureFactory = FakeFeatureFactory.setupForTest();
+        mContext = RuntimeEnvironment.application;
+        mController = new AutoRestrictionPreferenceController(mContext);
+        mPreference = new SwitchPreference(mContext);
+    }
+
+    @Test
+    public void testUpdateState_AutoRestrictionOn_preferenceChecked() {
+        putAutoRestrictionValue(ON);
+
+        mController.updateState(mPreference);
+
+        assertThat(mPreference.isChecked()).isTrue();
+    }
+
+    @Test
+    public void testUpdateState_AutoRestrictionOff_preferenceUnchecked() {
+        putAutoRestrictionValue(OFF);
+
+        mController.updateState(mPreference);
+
+        assertThat(mPreference.isChecked()).isFalse();
+    }
+
+    @Test
+    public void testUpdateState_checkPreference_autoRestrictionOn() {
+        mController.onPreferenceChange(mPreference, true);
+
+        assertThat(getAutoRestrictionValue()).isEqualTo(ON);
+    }
+
+    @Test
+    public void testUpdateState_unCheckPreference_autoRestrictionOff() {
+        mController.onPreferenceChange(mPreference, false);
+
+        assertThat(getAutoRestrictionValue()).isEqualTo(OFF);
+    }
+
+    @Test
+    public void testGetAvailabilityStatus_smartBatterySupported_returnDisabled() {
+        doReturn(true).when(mFeatureFactory.powerUsageFeatureProvider).isSmartBatterySupported();
+
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(
+                BasePreferenceController.DISABLED_UNSUPPORTED);
+    }
+
+    @Test
+    public void testGetAvailabilityStatus_smartBatteryUnSupported_returnAvailable() {
+        doReturn(false).when(mFeatureFactory.powerUsageFeatureProvider).isSmartBatterySupported();
+
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(
+                BasePreferenceController.AVAILABLE);
+    }
+
+    private void putAutoRestrictionValue(int value) {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.APP_AUTO_RESTRICTION_ENABLED,
+                value);
+    }
+
+    private int getAutoRestrictionValue() {
+        return Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.APP_AUTO_RESTRICTION_ENABLED, ON);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryAppListPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryAppListPreferenceControllerTest.java
index b223a10..8156428 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryAppListPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryAppListPreferenceControllerTest.java
@@ -203,20 +203,6 @@
     }
 
     @Test
-    public void testIsAvailable_featureOn_returnTrue() {
-        FeatureFlagUtils.setEnabled(mContext, FeatureFlags.BATTERY_DISPLAY_APP_LIST, true);
-
-        assertThat(mPreferenceController.isAvailable()).isTrue();
-    }
-
-    @Test
-    public void testIsAvailable_featureOff_returnFalse() {
-        FeatureFlagUtils.setEnabled(mContext, FeatureFlags.BATTERY_DISPLAY_APP_LIST, false);
-
-        assertThat(mPreferenceController.isAvailable()).isFalse();
-    }
-
-    @Test
     public void testNeverUseFakeData() {
         assertThat(BatteryAppListPreferenceController.USE_FAKE_DATA).isFalse();
     }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageAdvancedLegacyTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageAdvancedLegacyTest.java
new file mode 100644
index 0000000..756d913
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageAdvancedLegacyTest.java
@@ -0,0 +1,437 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settings.fuelgauge;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.UserInfo;
+import android.net.ConnectivityManager;
+import android.os.UserManager;
+import android.support.v7.preference.PreferenceCategory;
+import android.support.v7.preference.PreferenceGroup;
+import android.support.v7.preference.PreferenceManager;
+
+import com.android.internal.os.BatterySipper;
+import com.android.internal.os.BatterySipper.DrainType;
+import com.android.internal.os.BatteryStatsHelper;
+import com.android.settings.R;
+import com.android.settings.Utils;
+import com.android.settings.testutils.BatteryTestUtils;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.fuelgauge.PowerUsageAdvancedLegacy.PowerUsageData;
+import com.android.settings.fuelgauge.PowerUsageAdvancedLegacy.PowerUsageData.UsageType;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class PowerUsageAdvancedLegacyTest {
+    private static final int FAKE_UID_1 = 50;
+    private static final int FAKE_UID_2 = 100;
+    private static final int DISCHARGE_AMOUNT = 60;
+    private static final double TYPE_APP_USAGE = 80;
+    private static final double TYPE_BLUETOOTH_USAGE = 50;
+    private static final double TYPE_WIFI_USAGE = 0;
+    private static final double TOTAL_USAGE = TYPE_APP_USAGE * 2 + TYPE_BLUETOOTH_USAGE
+            + TYPE_WIFI_USAGE;
+    private static final double TOTAL_POWER = 500;
+    private static final double PRECISION = 0.001;
+    private static final String STUB_STRING = "stub_string";
+    @Mock
+    private BatterySipper mNormalBatterySipper;
+    @Mock
+    private BatterySipper mMaxBatterySipper;
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private BatteryStatsHelper mBatteryStatsHelper;
+    @Mock
+    private PowerUsageFeatureProvider mPowerUsageFeatureProvider;
+    @Mock
+    private PackageManager mPackageManager;
+    @Mock
+    private UserManager mUserManager;
+    @Mock
+    private BatteryHistoryPreference mHistPref;
+    @Mock
+    private PreferenceGroup mUsageListGroup;
+    @Mock
+    private ConnectivityManager mConnectivityManager;
+    @Mock
+    private UserInfo mNormalUserInfo;
+    @Mock
+    private UserInfo mManagedUserInfo;
+    private PowerUsageAdvancedLegacy mPowerUsageAdvanced;
+    private PowerUsageData mPowerUsageData;
+    private Context mShadowContext;
+    private Intent mDischargingBatteryIntent;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mShadowContext = spy(RuntimeEnvironment.application);
+        mPowerUsageAdvanced = spy(new PowerUsageAdvancedLegacy());
+
+        List<BatterySipper> batterySippers = new ArrayList<>();
+        batterySippers.add(new BatterySipper(DrainType.APP,
+                new FakeUid(FAKE_UID_1), TYPE_APP_USAGE));
+        batterySippers.add(new BatterySipper(DrainType.APP,
+                new FakeUid(FAKE_UID_2), TYPE_APP_USAGE));
+        batterySippers.add(new BatterySipper(DrainType.BLUETOOTH, new FakeUid(FAKE_UID_1),
+                TYPE_BLUETOOTH_USAGE));
+        batterySippers.add(new BatterySipper(DrainType.WIFI, new FakeUid(FAKE_UID_1),
+                TYPE_WIFI_USAGE));
+
+        mDischargingBatteryIntent = BatteryTestUtils.getDischargingIntent();
+        doReturn(mDischargingBatteryIntent).when(mShadowContext).registerReceiver(any(), any());
+        when(mBatteryStatsHelper.getStats().getDischargeAmount(anyInt())).thenReturn(
+                DISCHARGE_AMOUNT);
+        when(mBatteryStatsHelper.getUsageList()).thenReturn(batterySippers);
+        when(mBatteryStatsHelper.getTotalPower()).thenReturn(TOTAL_USAGE);
+        when(mPowerUsageAdvanced.getContext()).thenReturn(mShadowContext);
+        doReturn(STUB_STRING).when(mPowerUsageAdvanced).getString(anyInt(), any(), any());
+        doReturn(STUB_STRING).when(mPowerUsageAdvanced).getString(anyInt(), any());
+        doReturn(mShadowContext.getText(R.string.battery_used_for)).when(
+                mPowerUsageAdvanced).getText(R.string.battery_used_for);
+        mPowerUsageAdvanced.setPackageManager(mPackageManager);
+        mPowerUsageAdvanced.setPowerUsageFeatureProvider(mPowerUsageFeatureProvider);
+        mPowerUsageAdvanced.setUserManager(mUserManager);
+        mPowerUsageAdvanced.setBatteryUtils(BatteryUtils.getInstance(mShadowContext));
+        when(mShadowContext.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(
+                mConnectivityManager);
+
+        mPowerUsageData = new PowerUsageData(UsageType.USER);
+        mMaxBatterySipper.totalPowerMah = TYPE_BLUETOOTH_USAGE;
+        mMaxBatterySipper.drainType = DrainType.BLUETOOTH;
+        mNormalBatterySipper.drainType = DrainType.SCREEN;
+
+        doReturn(true).when(mNormalUserInfo).isEnabled();
+        doReturn(false).when(mNormalUserInfo).isManagedProfile();
+        doReturn(true).when(mManagedUserInfo).isEnabled();
+        doReturn(true).when(mManagedUserInfo).isManagedProfile();
+    }
+
+    @Test
+    public void testPrefs_shouldNotBeSelectable() {
+        PreferenceManager pm = new PreferenceManager(mShadowContext);
+        when(mPowerUsageAdvanced.getPreferenceManager()).thenReturn(pm);
+        PreferenceGroup prefGroup = spy(new PreferenceCategory(mShadowContext));
+        when(prefGroup.getPreferenceManager()).thenReturn(pm);
+
+        mPowerUsageAdvanced.refreshPowerUsageDataList(mBatteryStatsHelper, prefGroup);
+        assertThat(prefGroup.getPreferenceCount()).isAtLeast(1);
+        for (int i = 0, count = prefGroup.getPreferenceCount(); i < count; i++) {
+            PowerGaugePreference pref = (PowerGaugePreference) prefGroup.getPreference(i);
+            assertThat(pref.isSelectable()).isFalse();
+        }
+    }
+
+    @Test
+    public void testExtractUsageType_TypeSystem_ReturnSystem() {
+        mNormalBatterySipper.drainType = DrainType.APP;
+        when(mPowerUsageFeatureProvider.isTypeSystem(any())).thenReturn(true);
+
+        assertThat(mPowerUsageAdvanced.extractUsageType(mNormalBatterySipper))
+                .isEqualTo(UsageType.SYSTEM);
+    }
+
+    @Test
+    public void testExtractUsageType_TypeEqualsToDrainType_ReturnRelevantType() {
+        final DrainType drainTypes[] = {DrainType.WIFI, DrainType.BLUETOOTH, DrainType.IDLE,
+                DrainType.USER, DrainType.CELL, DrainType.UNACCOUNTED};
+        final int usageTypes[] = {UsageType.WIFI, UsageType.BLUETOOTH, UsageType.IDLE,
+                UsageType.USER, UsageType.CELL, UsageType.UNACCOUNTED};
+
+        assertThat(drainTypes.length).isEqualTo(usageTypes.length);
+        for (int i = 0, size = drainTypes.length; i < size; i++) {
+            mNormalBatterySipper.drainType = drainTypes[i];
+            assertThat(mPowerUsageAdvanced.extractUsageType(mNormalBatterySipper))
+                    .isEqualTo(usageTypes[i]);
+        }
+    }
+
+    @Test
+    public void testExtractUsageType_TypeService_ReturnSystem() {
+        mNormalBatterySipper.drainType = DrainType.APP;
+        when(mNormalBatterySipper.getUid()).thenReturn(FAKE_UID_1);
+        when(mPowerUsageFeatureProvider.isTypeService(any())).thenReturn(true);
+
+        assertThat(mPowerUsageAdvanced.extractUsageType(mNormalBatterySipper))
+                .isEqualTo(UsageType.SYSTEM);
+    }
+
+    @Test
+    public void testParsePowerUsageData_PercentageCalculatedCorrectly() {
+        final double percentApp = TYPE_APP_USAGE * 2 / TOTAL_USAGE * DISCHARGE_AMOUNT;
+        final double percentWifi = TYPE_WIFI_USAGE / TOTAL_USAGE * DISCHARGE_AMOUNT;
+        final double percentBluetooth = TYPE_BLUETOOTH_USAGE / TOTAL_USAGE * DISCHARGE_AMOUNT;
+
+        List<PowerUsageData> batteryData =
+                mPowerUsageAdvanced.parsePowerUsageData(mBatteryStatsHelper);
+        for (PowerUsageData data : batteryData) {
+            switch (data.usageType) {
+                case UsageType.WIFI:
+                    assertThat(data.percentage).isWithin(PRECISION).of(percentWifi);
+                    break;
+                case UsageType.APP:
+                    assertThat(data.percentage).isWithin(PRECISION).of(percentApp);
+                    break;
+                case UsageType.BLUETOOTH:
+                    assertThat(data.percentage).isWithin(PRECISION).of(percentBluetooth);
+                    break;
+                default:
+                    break;
+            }
+        }
+    }
+
+    @Test
+    public void testUpdateUsageDataSummary_onlyOneApp_showUsageTime() {
+        final String expectedSummary = "Used for 0m";
+        mPowerUsageData.usageList.add(mNormalBatterySipper);
+
+        mPowerUsageAdvanced.updateUsageDataSummary(mPowerUsageData, TOTAL_POWER, DISCHARGE_AMOUNT);
+
+        assertThat(mPowerUsageData.summary.toString()).isEqualTo(expectedSummary);
+    }
+
+    @Test
+    public void testUpdateUsageDataSummary_typeIdle_showUsageTime() {
+        mPowerUsageData.usageType = UsageType.IDLE;
+        mPowerUsageData.usageList.add(mNormalBatterySipper);
+
+        mPowerUsageAdvanced.updateUsageDataSummary(mPowerUsageData, TOTAL_POWER, DISCHARGE_AMOUNT);
+
+        assertThat(mPowerUsageData.summary.toString()).isEqualTo("0m");
+    }
+
+    @Test
+    public void testUpdateUsageDataSummary_moreThanOneApp_showMaxUsageApp() {
+        mPowerUsageData.usageList.add(mNormalBatterySipper);
+        mPowerUsageData.usageList.add(mMaxBatterySipper);
+        doReturn(mMaxBatterySipper).when(mPowerUsageAdvanced)
+            .findBatterySipperWithMaxBatteryUsage(mPowerUsageData.usageList);
+        final double percentage = (TYPE_BLUETOOTH_USAGE / TOTAL_POWER) * DISCHARGE_AMOUNT;
+        mPowerUsageAdvanced.updateUsageDataSummary(mPowerUsageData, TOTAL_POWER, DISCHARGE_AMOUNT);
+
+        verify(mPowerUsageAdvanced).getString(eq(R.string.battery_used_by),
+                eq(Utils.formatPercentage(percentage, true)), any());
+    }
+
+    @Test
+    public void testFindBatterySipperWithMaxBatteryUsage_findCorrectOne() {
+        mPowerUsageData.usageList.add(mNormalBatterySipper);
+        mPowerUsageData.usageList.add(mMaxBatterySipper);
+        BatterySipper sipper =
+            mPowerUsageAdvanced.findBatterySipperWithMaxBatteryUsage(mPowerUsageData.usageList);
+
+        assertThat(sipper).isEqualTo(mMaxBatterySipper);
+    }
+
+    @Test
+    public void testInit_ContainsAllUsageType() {
+        final int[] usageTypeSet = mPowerUsageAdvanced.mUsageTypes;
+
+        assertThat(usageTypeSet).asList().containsExactly(UsageType.APP, UsageType.WIFI,
+                UsageType.CELL, UsageType.BLUETOOTH, UsageType.IDLE, UsageType.USER,
+                UsageType.SYSTEM, UsageType.UNACCOUNTED, UsageType.OVERCOUNTED);
+    }
+
+    @Test
+    public void testPowerUsageData_SortedByUsage() {
+        List<PowerUsageData> dataList = new ArrayList<>();
+
+        dataList.add(new PowerUsageData(UsageType.WIFI, TYPE_WIFI_USAGE));
+        dataList.add(new PowerUsageData(UsageType.BLUETOOTH, TYPE_BLUETOOTH_USAGE));
+        dataList.add(new PowerUsageData(UsageType.APP, TYPE_APP_USAGE));
+        Collections.sort(dataList);
+
+        for (int i = 1, size = dataList.size(); i < size; i++) {
+            assertThat(dataList.get(i - 1).totalPowerMah).isAtLeast(dataList.get(i).totalPowerMah);
+        }
+    }
+
+    @Test
+    public void testShouldHideCategory_typeUnAccounted_returnTrue() {
+        mPowerUsageData.usageType = UsageType.UNACCOUNTED;
+
+        assertThat(mPowerUsageAdvanced.shouldHideCategory(mPowerUsageData)).isTrue();
+    }
+
+    @Test
+    public void testShouldHideCategory_typeOverCounted_returnTrue() {
+        mPowerUsageData.usageType = UsageType.OVERCOUNTED;
+
+        assertThat(mPowerUsageAdvanced.shouldHideCategory(mPowerUsageData)).isTrue();
+    }
+
+    @Test
+    public void testShouldHideCategory_typeUserAndOnlyOneNormalUser_returnTrue() {
+        mPowerUsageData.usageType = UsageType.USER;
+        List<UserInfo> userInfos = new ArrayList<>();
+        userInfos.add(mNormalUserInfo);
+        userInfos.add(mManagedUserInfo);
+        doReturn(userInfos).when(mUserManager).getUsers();
+
+        assertThat(mPowerUsageAdvanced.shouldHideCategory(mPowerUsageData)).isTrue();
+    }
+
+    @Test
+    public void testShouldHideCategory_typeCellWhileNotSupported_returnTrue() {
+        mPowerUsageData.usageType = UsageType.CELL;
+        doReturn(false).when(mConnectivityManager)
+            .isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
+
+        assertThat(mPowerUsageAdvanced.shouldHideCategory(mPowerUsageData)).isTrue();
+    }
+
+    @Test
+    public void testShouldHideCategory_typeCellWhileSupported_returnFalse() {
+        mPowerUsageData.usageType = UsageType.CELL;
+        doReturn(true).when(mConnectivityManager).isNetworkSupported(
+                ConnectivityManager.TYPE_MOBILE);
+
+        assertThat(mPowerUsageAdvanced.shouldHideCategory(mPowerUsageData)).isFalse();
+    }
+
+    @Test
+    public void testShouldHideCategory_typeUserAndMoreThanOne_returnFalse() {
+        mPowerUsageData.usageType = UsageType.USER;
+        List<UserInfo> userInfos = new ArrayList<>();
+        userInfos.add(mNormalUserInfo);
+        userInfos.add(mNormalUserInfo);
+        doReturn(userInfos).when(mUserManager).getUsers();
+
+        assertThat(mPowerUsageAdvanced.shouldHideCategory(mPowerUsageData)).isFalse();
+    }
+
+    @Test
+    public void testShouldHideCategory_typeNormal_returnFalse() {
+        mPowerUsageData.usageType = UsageType.APP;
+
+        assertThat(mPowerUsageAdvanced.shouldHideCategory(mPowerUsageData)).isFalse();
+    }
+
+    @Test
+    public void testShouldHideSummary_typeCell_returnTrue() {
+        mPowerUsageData.usageType = UsageType.CELL;
+
+        assertThat(mPowerUsageAdvanced.shouldHideSummary(mPowerUsageData)).isTrue();
+    }
+
+    @Test
+    public void testShouldHideSummary_typeSystem_returnTrue() {
+        mPowerUsageData.usageType = UsageType.SYSTEM;
+
+        assertThat(mPowerUsageAdvanced.shouldHideSummary(mPowerUsageData)).isTrue();
+    }
+
+    @Test
+    public void testShouldHideSummary_typeWifi_returnTrue() {
+        mPowerUsageData.usageType = UsageType.WIFI;
+
+        assertThat(mPowerUsageAdvanced.shouldHideSummary(mPowerUsageData)).isTrue();
+    }
+
+    @Test
+    public void testShouldHideSummary_typeBluetooth_returnTrue() {
+        mPowerUsageData.usageType = UsageType.BLUETOOTH;
+
+        assertThat(mPowerUsageAdvanced.shouldHideSummary(mPowerUsageData)).isTrue();
+    }
+
+    @Test
+    public void testShouldHideSummary_typeApp_returnTrue() {
+        mPowerUsageData.usageType = UsageType.APP;
+
+        assertThat(mPowerUsageAdvanced.shouldHideSummary(mPowerUsageData)).isTrue();
+    }
+
+    @Test
+    public void testShouldHideSummary_typeNormal_returnFalse() {
+        mPowerUsageData.usageType = UsageType.IDLE;
+
+        assertThat(mPowerUsageAdvanced.shouldHideSummary(mPowerUsageData)).isFalse();
+    }
+
+    @Test
+    public void testShouldShowBatterySipper_typeScreen_returnFalse() {
+        mNormalBatterySipper.drainType = DrainType.SCREEN;
+
+        assertThat(mPowerUsageAdvanced.shouldShowBatterySipper(mNormalBatterySipper)).isFalse();
+    }
+
+    @Test
+    public void testShouldShowBatterySipper_typeNormal_returnTrue() {
+        mNormalBatterySipper.drainType = DrainType.APP;
+
+        assertThat(mPowerUsageAdvanced.shouldShowBatterySipper(mNormalBatterySipper)).isTrue();
+    }
+
+    @Test
+    public void testCalculateHiddenPower_returnCorrectPower() {
+        List<PowerUsageData> powerUsageDataList = new ArrayList<>();
+        final double unaccountedPower = 100;
+        final double normalPower = 150;
+        powerUsageDataList.add(new PowerUsageData(UsageType.UNACCOUNTED, unaccountedPower));
+        powerUsageDataList.add(new PowerUsageData(UsageType.APP, normalPower));
+        powerUsageDataList.add(new PowerUsageData(UsageType.CELL, normalPower));
+
+        assertThat(mPowerUsageAdvanced.calculateHiddenPower(powerUsageDataList))
+            .isWithin(PRECISION).of(unaccountedPower);
+    }
+
+    @Test
+    public void testRefreshUi_addsSubtextWhenAppropriate() {
+        // Mock out all the battery stuff
+        mPowerUsageAdvanced.mHistPref = mHistPref;
+        mPowerUsageAdvanced.mStatsHelper = mBatteryStatsHelper;
+        doReturn(new ArrayList<PowerUsageData>())
+                .when(mPowerUsageAdvanced).parsePowerUsageData(any());
+        doReturn("").when(mPowerUsageAdvanced).getString(anyInt());
+        mPowerUsageAdvanced.mUsageListGroup = mUsageListGroup;
+
+        // refresh the ui and check that text was not updated when enhanced prediction disabled
+        when(mPowerUsageFeatureProvider.isEnhancedBatteryPredictionEnabled(any()))
+                .thenReturn(false);
+        mPowerUsageAdvanced.refreshUi();
+        verify(mHistPref, never()).setBottomSummary(any());
+
+        // refresh the ui and check that text was updated when enhanced prediction enabled
+        when(mPowerUsageFeatureProvider.isEnhancedBatteryPredictionEnabled(any())).thenReturn(true);
+        mPowerUsageAdvanced.refreshUi();
+        verify(mHistPref, atLeastOnce()).setBottomSummary(any());
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageAdvancedTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageAdvancedTest.java
index 81d40a3..4a905b4 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageAdvancedTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageAdvancedTest.java
@@ -16,34 +16,25 @@
 package com.android.settings.fuelgauge;
 
 import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
+
+import static org.mockito.ArgumentMatchers.nullable;
 import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.UserInfo;
-import android.net.ConnectivityManager;
-import android.os.UserManager;
-import android.support.v7.preference.PreferenceCategory;
-import android.support.v7.preference.PreferenceGroup;
-import android.support.v7.preference.PreferenceManager;
+import android.os.Bundle;
+import android.support.v7.preference.PreferenceScreen;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
 
-import com.android.internal.os.BatterySipper;
-import com.android.internal.os.BatterySipper.DrainType;
-import com.android.internal.os.BatteryStatsHelper;
+import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.R;
-import com.android.settings.Utils;
-import com.android.settings.fuelgauge.PowerUsageAdvanced.PowerUsageData;
-import com.android.settings.fuelgauge.PowerUsageAdvanced.PowerUsageData.UsageType;
-import com.android.settings.testutils.BatteryTestUtils;
+import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 
 import org.junit.Before;
@@ -54,385 +45,64 @@
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RuntimeEnvironment;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
 @RunWith(SettingsRobolectricTestRunner.class)
 public class PowerUsageAdvancedTest {
-
-    private static final int FAKE_UID_1 = 50;
-    private static final int FAKE_UID_2 = 100;
-    private static final int DISCHARGE_AMOUNT = 60;
-    private static final double TYPE_APP_USAGE = 80;
-    private static final double TYPE_BLUETOOTH_USAGE = 50;
-    private static final double TYPE_WIFI_USAGE = 0;
-    private static final double TOTAL_USAGE = TYPE_APP_USAGE * 2 + TYPE_BLUETOOTH_USAGE
-            + TYPE_WIFI_USAGE;
-    private static final double TOTAL_POWER = 500;
-    private static final double PRECISION = 0.001;
-    private static final String STUB_STRING = "stub_string";
     @Mock
-    private BatterySipper mNormalBatterySipper;
-    @Mock
-    private BatterySipper mMaxBatterySipper;
+    private PreferenceScreen mPreferenceScreen;
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
-    private BatteryStatsHelper mBatteryStatsHelper;
+    private Menu mMenu;
     @Mock
-    private PowerUsageFeatureProvider mPowerUsageFeatureProvider;
+    private MenuInflater mMenuInflater;
     @Mock
-    private PackageManager mPackageManager;
-    @Mock
-    private UserManager mUserManager;
-    @Mock
-    private BatteryHistoryPreference mHistPref;
-    @Mock
-    private PreferenceGroup mUsageListGroup;
-    @Mock
-    private ConnectivityManager mConnectivityManager;
-    @Mock
-    private UserInfo mNormalUserInfo;
-    @Mock
-    private UserInfo mManagedUserInfo;
-    private PowerUsageAdvanced mPowerUsageAdvanced;
-    private PowerUsageData mPowerUsageData;
-    private Context mShadowContext;
-    private Intent mDischargingBatteryIntent;
+    private MenuItem mToggleAppsMenu;
+    private Context mContext;
+    private PowerUsageAdvanced mFragment;
+    private FakeFeatureFactory mFeatureFactory;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mShadowContext = spy(RuntimeEnvironment.application);
-        mPowerUsageAdvanced = spy(new PowerUsageAdvanced());
 
-        List<BatterySipper> batterySippers = new ArrayList<>();
-        batterySippers.add(new BatterySipper(DrainType.APP,
-                new FakeUid(FAKE_UID_1), TYPE_APP_USAGE));
-        batterySippers.add(new BatterySipper(DrainType.APP,
-                new FakeUid(FAKE_UID_2), TYPE_APP_USAGE));
-        batterySippers.add(new BatterySipper(DrainType.BLUETOOTH, new FakeUid(FAKE_UID_1),
-                TYPE_BLUETOOTH_USAGE));
-        batterySippers.add(new BatterySipper(DrainType.WIFI, new FakeUid(FAKE_UID_1),
-                TYPE_WIFI_USAGE));
+        mContext = RuntimeEnvironment.application;
+        mFeatureFactory = FakeFeatureFactory.setupForTest();
+        when(mToggleAppsMenu.getItemId()).thenReturn(PowerUsageAdvanced.MENU_TOGGLE_APPS);
 
-        mDischargingBatteryIntent = BatteryTestUtils.getDischargingIntent();
-        doReturn(mDischargingBatteryIntent).when(mShadowContext).registerReceiver(any(), any());
-        when(mBatteryStatsHelper.getStats().getDischargeAmount(anyInt())).thenReturn(
-                DISCHARGE_AMOUNT);
-        when(mBatteryStatsHelper.getUsageList()).thenReturn(batterySippers);
-        when(mBatteryStatsHelper.getTotalPower()).thenReturn(TOTAL_USAGE);
-        when(mPowerUsageAdvanced.getContext()).thenReturn(mShadowContext);
-        doReturn(STUB_STRING).when(mPowerUsageAdvanced).getString(anyInt(), any(), any());
-        doReturn(STUB_STRING).when(mPowerUsageAdvanced).getString(anyInt(), any());
-        doReturn(mShadowContext.getText(R.string.battery_used_for)).when(
-                mPowerUsageAdvanced).getText(R.string.battery_used_for);
-        mPowerUsageAdvanced.setPackageManager(mPackageManager);
-        mPowerUsageAdvanced.setPowerUsageFeatureProvider(mPowerUsageFeatureProvider);
-        mPowerUsageAdvanced.setUserManager(mUserManager);
-        mPowerUsageAdvanced.setBatteryUtils(BatteryUtils.getInstance(mShadowContext));
-        when(mShadowContext.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(
-                mConnectivityManager);
-
-        mPowerUsageData = new PowerUsageData(UsageType.USER);
-        mMaxBatterySipper.totalPowerMah = TYPE_BLUETOOTH_USAGE;
-        mMaxBatterySipper.drainType = DrainType.BLUETOOTH;
-        mNormalBatterySipper.drainType = DrainType.SCREEN;
-
-        doReturn(true).when(mNormalUserInfo).isEnabled();
-        doReturn(false).when(mNormalUserInfo).isManagedProfile();
-        doReturn(true).when(mManagedUserInfo).isEnabled();
-        doReturn(true).when(mManagedUserInfo).isManagedProfile();
+        mFragment = spy(new PowerUsageAdvanced());
+        mFragment.onAttach(mContext);
     }
 
     @Test
-    public void testPrefs_shouldNotBeSelectable() {
-        PreferenceManager pm = new PreferenceManager(mShadowContext);
-        when(mPowerUsageAdvanced.getPreferenceManager()).thenReturn(pm);
-        PreferenceGroup prefGroup = spy(new PreferenceCategory(mShadowContext));
-        when(prefGroup.getPreferenceManager()).thenReturn(pm);
+    public void testSaveInstanceState_showAllAppsRestored() {
+        Bundle bundle = new Bundle();
+        mFragment.mShowAllApps = true;
+        doReturn(mPreferenceScreen).when(mFragment).getPreferenceScreen();
 
-        mPowerUsageAdvanced.refreshPowerUsageDataList(mBatteryStatsHelper, prefGroup);
-        assertThat(prefGroup.getPreferenceCount()).isAtLeast(1);
-        for (int i = 0, count = prefGroup.getPreferenceCount(); i < count; i++) {
-            PowerGaugePreference pref = (PowerGaugePreference) prefGroup.getPreference(i);
-            assertThat(pref.isSelectable()).isFalse();
-        }
+        mFragment.onSaveInstanceState(bundle);
+        mFragment.restoreSavedInstance(bundle);
+
+        assertThat(mFragment.mShowAllApps).isTrue();
     }
 
     @Test
-    public void testExtractUsageType_TypeSystem_ReturnSystem() {
-        mNormalBatterySipper.drainType = DrainType.APP;
-        when(mPowerUsageFeatureProvider.isTypeSystem(any())).thenReturn(true);
+    public void testOptionsMenu_menuAppToggle_metricEventInvoked() {
+        mFragment.mShowAllApps = false;
+        doNothing().when(mFragment).restartBatteryStatsLoader();
 
-        assertThat(mPowerUsageAdvanced.extractUsageType(mNormalBatterySipper))
-                .isEqualTo(UsageType.SYSTEM);
+        mFragment.onOptionsItemSelected(mToggleAppsMenu);
+
+        verify(mFeatureFactory.metricsFeatureProvider).action(nullable(Context.class),
+                eq(MetricsProto.MetricsEvent.ACTION_SETTINGS_MENU_BATTERY_APPS_TOGGLE), eq(true));
     }
 
     @Test
-    public void testExtractUsageType_TypeEqualsToDrainType_ReturnRelevantType() {
-        final DrainType drainTypes[] = {DrainType.WIFI, DrainType.BLUETOOTH, DrainType.IDLE,
-                DrainType.USER, DrainType.CELL, DrainType.UNACCOUNTED};
-        final int usageTypes[] = {UsageType.WIFI, UsageType.BLUETOOTH, UsageType.IDLE,
-                UsageType.USER, UsageType.CELL, UsageType.UNACCOUNTED};
+    public void testOptionsMenu_toggleAppsEnabled() {
+        when(mFeatureFactory.powerUsageFeatureProvider.isPowerAccountingToggleEnabled())
+                .thenReturn(true);
+        mFragment.mShowAllApps = false;
 
-        assertThat(drainTypes.length).isEqualTo(usageTypes.length);
-        for (int i = 0, size = drainTypes.length; i < size; i++) {
-            mNormalBatterySipper.drainType = drainTypes[i];
-            assertThat(mPowerUsageAdvanced.extractUsageType(mNormalBatterySipper))
-                    .isEqualTo(usageTypes[i]);
-        }
-    }
+        mFragment.onCreateOptionsMenu(mMenu, mMenuInflater);
 
-    @Test
-    public void testExtractUsageType_TypeService_ReturnSystem() {
-        mNormalBatterySipper.drainType = DrainType.APP;
-        when(mNormalBatterySipper.getUid()).thenReturn(FAKE_UID_1);
-        when(mPowerUsageFeatureProvider.isTypeService(any())).thenReturn(true);
-
-        assertThat(mPowerUsageAdvanced.extractUsageType(mNormalBatterySipper))
-                .isEqualTo(UsageType.SYSTEM);
-    }
-
-    @Test
-    public void testParsePowerUsageData_PercentageCalculatedCorrectly() {
-        final double percentApp = TYPE_APP_USAGE * 2 / TOTAL_USAGE * DISCHARGE_AMOUNT;
-        final double percentWifi = TYPE_WIFI_USAGE / TOTAL_USAGE * DISCHARGE_AMOUNT;
-        final double percentBluetooth = TYPE_BLUETOOTH_USAGE / TOTAL_USAGE * DISCHARGE_AMOUNT;
-
-        List<PowerUsageData> batteryData =
-                mPowerUsageAdvanced.parsePowerUsageData(mBatteryStatsHelper);
-        for (PowerUsageData data : batteryData) {
-            switch (data.usageType) {
-                case UsageType.WIFI:
-                    assertThat(data.percentage).isWithin(PRECISION).of(percentWifi);
-                    break;
-                case UsageType.APP:
-                    assertThat(data.percentage).isWithin(PRECISION).of(percentApp);
-                    break;
-                case UsageType.BLUETOOTH:
-                    assertThat(data.percentage).isWithin(PRECISION).of(percentBluetooth);
-                    break;
-                default:
-                    break;
-            }
-        }
-    }
-
-    @Test
-    public void testUpdateUsageDataSummary_onlyOneApp_showUsageTime() {
-        final String expectedSummary = "Used for 0m";
-        mPowerUsageData.usageList.add(mNormalBatterySipper);
-
-        mPowerUsageAdvanced.updateUsageDataSummary(mPowerUsageData, TOTAL_POWER, DISCHARGE_AMOUNT);
-
-        assertThat(mPowerUsageData.summary.toString()).isEqualTo(expectedSummary);
-    }
-
-    @Test
-    public void testUpdateUsageDataSummary_typeIdle_showUsageTime() {
-        mPowerUsageData.usageType = UsageType.IDLE;
-        mPowerUsageData.usageList.add(mNormalBatterySipper);
-
-        mPowerUsageAdvanced.updateUsageDataSummary(mPowerUsageData, TOTAL_POWER, DISCHARGE_AMOUNT);
-
-        assertThat(mPowerUsageData.summary.toString()).isEqualTo("0m");
-    }
-
-    @Test
-    public void testUpdateUsageDataSummary_moreThanOneApp_showMaxUsageApp() {
-        mPowerUsageData.usageList.add(mNormalBatterySipper);
-        mPowerUsageData.usageList.add(mMaxBatterySipper);
-        doReturn(mMaxBatterySipper).when(mPowerUsageAdvanced)
-            .findBatterySipperWithMaxBatteryUsage(mPowerUsageData.usageList);
-        final double percentage = (TYPE_BLUETOOTH_USAGE / TOTAL_POWER) * DISCHARGE_AMOUNT;
-        mPowerUsageAdvanced.updateUsageDataSummary(mPowerUsageData, TOTAL_POWER, DISCHARGE_AMOUNT);
-
-        verify(mPowerUsageAdvanced).getString(eq(R.string.battery_used_by),
-                eq(Utils.formatPercentage(percentage, true)), any());
-    }
-
-    @Test
-    public void testFindBatterySipperWithMaxBatteryUsage_findCorrectOne() {
-        mPowerUsageData.usageList.add(mNormalBatterySipper);
-        mPowerUsageData.usageList.add(mMaxBatterySipper);
-        BatterySipper sipper =
-            mPowerUsageAdvanced.findBatterySipperWithMaxBatteryUsage(mPowerUsageData.usageList);
-
-        assertThat(sipper).isEqualTo(mMaxBatterySipper);
-    }
-
-    @Test
-    public void testInit_ContainsAllUsageType() {
-        final int[] usageTypeSet = mPowerUsageAdvanced.mUsageTypes;
-
-        assertThat(usageTypeSet).asList().containsExactly(UsageType.APP, UsageType.WIFI,
-                UsageType.CELL, UsageType.BLUETOOTH, UsageType.IDLE, UsageType.USER,
-                UsageType.SYSTEM, UsageType.UNACCOUNTED, UsageType.OVERCOUNTED);
-    }
-
-    @Test
-    public void testPowerUsageData_SortedByUsage() {
-        List<PowerUsageData> dataList = new ArrayList<>();
-
-        dataList.add(new PowerUsageData(UsageType.WIFI, TYPE_WIFI_USAGE));
-        dataList.add(new PowerUsageData(UsageType.BLUETOOTH, TYPE_BLUETOOTH_USAGE));
-        dataList.add(new PowerUsageData(UsageType.APP, TYPE_APP_USAGE));
-        Collections.sort(dataList);
-
-        for (int i = 1, size = dataList.size(); i < size; i++) {
-            assertThat(dataList.get(i - 1).totalPowerMah).isAtLeast(dataList.get(i).totalPowerMah);
-        }
-    }
-
-    @Test
-    public void testShouldHideCategory_typeUnAccounted_returnTrue() {
-        mPowerUsageData.usageType = UsageType.UNACCOUNTED;
-
-        assertThat(mPowerUsageAdvanced.shouldHideCategory(mPowerUsageData)).isTrue();
-    }
-
-    @Test
-    public void testShouldHideCategory_typeOverCounted_returnTrue() {
-        mPowerUsageData.usageType = UsageType.OVERCOUNTED;
-
-        assertThat(mPowerUsageAdvanced.shouldHideCategory(mPowerUsageData)).isTrue();
-    }
-
-    @Test
-    public void testShouldHideCategory_typeUserAndOnlyOneNormalUser_returnTrue() {
-        mPowerUsageData.usageType = UsageType.USER;
-        List<UserInfo> userInfos = new ArrayList<>();
-        userInfos.add(mNormalUserInfo);
-        userInfos.add(mManagedUserInfo);
-        doReturn(userInfos).when(mUserManager).getUsers();
-
-        assertThat(mPowerUsageAdvanced.shouldHideCategory(mPowerUsageData)).isTrue();
-    }
-
-    @Test
-    public void testShouldHideCategory_typeCellWhileNotSupported_returnTrue() {
-        mPowerUsageData.usageType = UsageType.CELL;
-        doReturn(false).when(mConnectivityManager)
-            .isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
-
-        assertThat(mPowerUsageAdvanced.shouldHideCategory(mPowerUsageData)).isTrue();
-    }
-
-    @Test
-    public void testShouldHideCategory_typeCellWhileSupported_returnFalse() {
-        mPowerUsageData.usageType = UsageType.CELL;
-        doReturn(true).when(mConnectivityManager).isNetworkSupported(
-                ConnectivityManager.TYPE_MOBILE);
-
-        assertThat(mPowerUsageAdvanced.shouldHideCategory(mPowerUsageData)).isFalse();
-    }
-
-    @Test
-    public void testShouldHideCategory_typeUserAndMoreThanOne_returnFalse() {
-        mPowerUsageData.usageType = UsageType.USER;
-        List<UserInfo> userInfos = new ArrayList<>();
-        userInfos.add(mNormalUserInfo);
-        userInfos.add(mNormalUserInfo);
-        doReturn(userInfos).when(mUserManager).getUsers();
-
-        assertThat(mPowerUsageAdvanced.shouldHideCategory(mPowerUsageData)).isFalse();
-    }
-
-    @Test
-    public void testShouldHideCategory_typeNormal_returnFalse() {
-        mPowerUsageData.usageType = UsageType.APP;
-
-        assertThat(mPowerUsageAdvanced.shouldHideCategory(mPowerUsageData)).isFalse();
-    }
-
-    @Test
-    public void testShouldHideSummary_typeCell_returnTrue() {
-        mPowerUsageData.usageType = UsageType.CELL;
-
-        assertThat(mPowerUsageAdvanced.shouldHideSummary(mPowerUsageData)).isTrue();
-    }
-
-    @Test
-    public void testShouldHideSummary_typeSystem_returnTrue() {
-        mPowerUsageData.usageType = UsageType.SYSTEM;
-
-        assertThat(mPowerUsageAdvanced.shouldHideSummary(mPowerUsageData)).isTrue();
-    }
-
-    @Test
-    public void testShouldHideSummary_typeWifi_returnTrue() {
-        mPowerUsageData.usageType = UsageType.WIFI;
-
-        assertThat(mPowerUsageAdvanced.shouldHideSummary(mPowerUsageData)).isTrue();
-    }
-
-    @Test
-    public void testShouldHideSummary_typeBluetooth_returnTrue() {
-        mPowerUsageData.usageType = UsageType.BLUETOOTH;
-
-        assertThat(mPowerUsageAdvanced.shouldHideSummary(mPowerUsageData)).isTrue();
-    }
-
-    @Test
-    public void testShouldHideSummary_typeApp_returnTrue() {
-        mPowerUsageData.usageType = UsageType.APP;
-
-        assertThat(mPowerUsageAdvanced.shouldHideSummary(mPowerUsageData)).isTrue();
-    }
-
-    @Test
-    public void testShouldHideSummary_typeNormal_returnFalse() {
-        mPowerUsageData.usageType = UsageType.IDLE;
-
-        assertThat(mPowerUsageAdvanced.shouldHideSummary(mPowerUsageData)).isFalse();
-    }
-
-    @Test
-    public void testShouldShowBatterySipper_typeScreen_returnFalse() {
-        mNormalBatterySipper.drainType = DrainType.SCREEN;
-
-        assertThat(mPowerUsageAdvanced.shouldShowBatterySipper(mNormalBatterySipper)).isFalse();
-    }
-
-    @Test
-    public void testShouldShowBatterySipper_typeNormal_returnTrue() {
-        mNormalBatterySipper.drainType = DrainType.APP;
-
-        assertThat(mPowerUsageAdvanced.shouldShowBatterySipper(mNormalBatterySipper)).isTrue();
-    }
-
-    @Test
-    public void testCalculateHiddenPower_returnCorrectPower() {
-        List<PowerUsageData> powerUsageDataList = new ArrayList<>();
-        final double unaccountedPower = 100;
-        final double normalPower = 150;
-        powerUsageDataList.add(new PowerUsageData(UsageType.UNACCOUNTED, unaccountedPower));
-        powerUsageDataList.add(new PowerUsageData(UsageType.APP, normalPower));
-        powerUsageDataList.add(new PowerUsageData(UsageType.CELL, normalPower));
-
-        assertThat(mPowerUsageAdvanced.calculateHiddenPower(powerUsageDataList))
-            .isWithin(PRECISION).of(unaccountedPower);
-    }
-
-    @Test
-    public void testRefreshUi_addsSubtextWhenAppropriate() {
-        // Mock out all the battery stuff
-        mPowerUsageAdvanced.mHistPref = mHistPref;
-        mPowerUsageAdvanced.mStatsHelper = mBatteryStatsHelper;
-        doReturn(new ArrayList<PowerUsageData>())
-                .when(mPowerUsageAdvanced).parsePowerUsageData(any());
-        doReturn("").when(mPowerUsageAdvanced).getString(anyInt());
-        mPowerUsageAdvanced.mUsageListGroup = mUsageListGroup;
-
-        // refresh the ui and check that text was not updated when enhanced prediction disabled
-        when(mPowerUsageFeatureProvider.isEnhancedBatteryPredictionEnabled(any()))
-                .thenReturn(false);
-        mPowerUsageAdvanced.refreshUi();
-        verify(mHistPref, never()).setBottomSummary(any());
-
-        // refresh the ui and check that text was updated when enhanced prediction enabled
-        when(mPowerUsageFeatureProvider.isEnhancedBatteryPredictionEnabled(any())).thenReturn(true);
-        mPowerUsageAdvanced.refreshUi();
-        verify(mHistPref, atLeastOnce()).setBottomSummary(any());
+        verify(mMenu).add(Menu.NONE, PowerUsageAdvanced.MENU_TOGGLE_APPS, Menu.NONE,
+                R.string.show_all_apps);
     }
 }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java
index f37d607..70acb73 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java
@@ -136,4 +136,9 @@
     public void testIsPowerAccountingToggleEnabled_returnTrue() {
         assertThat(mPowerFeatureProvider.isPowerAccountingToggleEnabled()).isTrue();
     }
+
+    @Test
+    public void testIsSmartBatterySupported_returnFalse() {
+        assertThat(mPowerFeatureProvider.isSmartBatterySupported()).isFalse();
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
index 7f6e39d..6176bef 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
@@ -15,6 +15,8 @@
  */
 package com.android.settings.fuelgauge;
 
+import static com.android.settings.fuelgauge.PowerUsageSummary.MENU_ADVANCED_BATTERY;
+
 import static com.google.common.truth.Truth.assertThat;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyInt;
@@ -35,6 +37,8 @@
 import android.content.Intent;
 import android.os.Bundle;
 import android.util.SparseArray;
+import android.view.Menu;
+import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
 import android.widget.TextView;
@@ -53,7 +57,6 @@
 
 import org.junit.Before;
 import org.junit.BeforeClass;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Answers;
@@ -114,6 +117,12 @@
     private LoaderManager mLoaderManager;
     @Mock
     private BatteryHeaderPreferenceController mBatteryHeaderPreferenceController;
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private Menu mMenu;
+    @Mock
+    private MenuInflater mMenuInflater;
+    @Mock
+    private MenuItem mAdvancedPageMenu;
 
     private List<BatterySipper> mUsageList;
     private Context mRealContext;
@@ -122,12 +131,13 @@
     private BatteryMeterView mBatteryMeterView;
     private PowerGaugePreference mScreenUsagePref;
     private PowerGaugePreference mLastFullChargePref;
+    private Intent mIntent;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
 
-        mRealContext = RuntimeEnvironment.application;
+        mRealContext = spy(RuntimeEnvironment.application);
         mFeatureFactory = FakeFeatureFactory.setupForTest();
         mScreenUsagePref = new PowerGaugePreference(mRealContext);
         mLastFullChargePref = new PowerGaugePreference(mRealContext);
@@ -137,6 +147,7 @@
         mBatteryMeterView.mDrawable = new BatteryMeterView.BatteryMeterDrawable(mRealContext, 0);
         doNothing().when(mFragment).restartBatteryStatsLoader();
         doReturn(mock(LoaderManager.class)).when(mFragment).getLoaderManager();
+        doReturn(MENU_ADVANCED_BATTERY).when(mAdvancedPageMenu).getItemId();
 
         when(mFragment.getActivity()).thenReturn(mSettingsActivity);
         when(mFeatureFactory.powerUsageFeatureProvider.getAdditionalBatteryInfoIntent())
@@ -294,6 +305,35 @@
         verify(mBatteryHeaderPreferenceController, never()).quickUpdateHeaderPreference();
     }
 
+    @Test
+    public void testOptionsMenu_advancedPageEnabled() {
+        when(mFeatureFactory.powerUsageFeatureProvider.isPowerAccountingToggleEnabled())
+                .thenReturn(true);
+
+        mFragment.onCreateOptionsMenu(mMenu, mMenuInflater);
+
+        verify(mMenu).add(Menu.NONE, MENU_ADVANCED_BATTERY, Menu.NONE,
+                R.string.advanced_battery_title);
+    }
+
+    @Test
+    public void testOptionsMenu_clickAdvancedPage_fireIntent() {
+        final ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
+        doAnswer(invocation -> {
+            // Get the intent in which it has the app info bundle
+            mIntent = captor.getValue();
+            return true;
+        }).when(mRealContext).startActivity(captor.capture());
+
+        mFragment.onOptionsItemSelected(mAdvancedPageMenu);
+
+        assertThat(mIntent.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT)).isEqualTo(
+                PowerUsageAdvanced.class.getName());
+        assertThat(
+                mIntent.getIntExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_TITLE_RESID, 0)).isEqualTo(
+                R.string.advanced_battery_title);
+    }
+
     public static class TestFragment extends PowerUsageSummary {
         private Context mContext;
 
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/SmartBatteryPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/SmartBatteryPreferenceControllerTest.java
index 494d563..fbbc6f9 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/SmartBatteryPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/SmartBatteryPreferenceControllerTest.java
@@ -18,10 +18,16 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.Mockito.doReturn;
+
 import android.content.ContentResolver;
+import android.content.Context;
 import android.provider.Settings;
 import android.support.v14.preference.SwitchPreference;
 
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.testutils.FakeFeatureFactory;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -38,11 +44,15 @@
     private SmartBatteryPreferenceController mController;
     private SwitchPreference mPreference;
     private ContentResolver mContentResolver;
+    private Context mContext;
+    private FakeFeatureFactory mFeatureFactory;
+
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
 
+        mFeatureFactory = FakeFeatureFactory.setupForTest();
         mContentResolver = RuntimeEnvironment.application.getContentResolver();
         mController = new SmartBatteryPreferenceController(RuntimeEnvironment.application);
         mPreference = new SwitchPreference(RuntimeEnvironment.application);
@@ -80,6 +90,22 @@
         assertThat(getSmartBatteryValue()).isEqualTo(OFF);
     }
 
+    @Test
+    public void testGetAvailabilityStatus_smartBatterySupported_returnAvailable() {
+        doReturn(true).when(mFeatureFactory.powerUsageFeatureProvider).isSmartBatterySupported();
+
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(
+                BasePreferenceController.AVAILABLE);
+    }
+
+    @Test
+    public void testGetAvailabilityStatus_smartBatteryUnSupported_returnDisabled() {
+        doReturn(false).when(mFeatureFactory.powerUsageFeatureProvider).isSmartBatterySupported();
+
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(
+                BasePreferenceController.DISABLED_UNSUPPORTED);
+    }
+
     private void putSmartBatteryValue(int value) {
         Settings.Global.putInt(mContentResolver, Settings.Global.APP_STANDBY_ENABLED, value);
     }
diff --git a/tests/robotests/src/com/android/settings/search/BaseSearchIndexProviderTest.java b/tests/robotests/src/com/android/settings/search/BaseSearchIndexProviderTest.java
index 905361c..df60654 100644
--- a/tests/robotests/src/com/android/settings/search/BaseSearchIndexProviderTest.java
+++ b/tests/robotests/src/com/android/settings/search/BaseSearchIndexProviderTest.java
@@ -116,7 +116,7 @@
         final List<AbstractPreferenceController> controllers =
                 provider.getPreferenceControllers(mContext);
 
-        assertThat(controllers).hasSize(3);
+        assertThat(controllers).hasSize(2);
     }
 
     public static class NotAvailablePreferenceController
diff --git a/tests/robotests/src/com/android/settings/security/EncryptionStatusPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/security/EncryptionStatusPreferenceControllerTest.java
index 6f736b1..ee6d33a 100644
--- a/tests/robotests/src/com/android/settings/security/EncryptionStatusPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/security/EncryptionStatusPreferenceControllerTest.java
@@ -84,7 +84,7 @@
 
         mController.updateState(mPreference);
 
-        final CharSequence summary = mContext.getText(R.string.summary_placeholder);
+        final CharSequence summary = mContext.getText(R.string.decryption_settings_summary);
         assertThat(mPreference.getSummary()).isEqualTo(summary);
         assertThat(mController.getPreferenceKey()).isNotEqualTo(PREF_KEY_ENCRYPTION_SECURITY_PAGE);
         assertThat(mPreference.getFragment()).isEqualTo(CryptKeeperSettings.class.getName());
@@ -98,7 +98,7 @@
 
         mController.updateState(mPreference);
 
-        final CharSequence summary = mContext.getText(R.string.summary_placeholder);
+        final CharSequence summary = mContext.getText(R.string.decryption_settings_summary);
         assertThat(mPreference.getSummary()).isEqualTo(summary);
 
         assertThat(mPreference.getFragment()).isNotEqualTo(CryptKeeperSettings.class.getName());
diff --git a/tests/robotests/src/com/android/settings/testutils/CustomActivity.java b/tests/robotests/src/com/android/settings/testutils/CustomActivity.java
new file mode 100644
index 0000000..d4c7341
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/testutils/CustomActivity.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2018 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;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.UserHandle;
+
+public class CustomActivity extends Activity {
+    @Override
+    public void startActivityAsUser(Intent intent, UserHandle user) {}
+}
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowActivity.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowActivity.java
new file mode 100644
index 0000000..0f67bbf
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowActivity.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2018 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.content.Intent;
+import android.os.UserHandle;
+
+import com.android.settings.testutils.CustomActivity;
+
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+import org.robolectric.shadows.ShadowApplication;
+
+@Implements(CustomActivity.class)
+public class ShadowActivity extends org.robolectric.shadows.ShadowActivity {
+
+    @Implementation
+    public void startActivityAsUser(Intent intent, UserHandle user) {
+        ShadowApplication.getInstance().startActivity(intent);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDevicePolicyManager.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDevicePolicyManager.java
new file mode 100644
index 0000000..77daae0
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDevicePolicyManager.java
@@ -0,0 +1,41 @@
+package com.android.settings.testutils.shadow;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * This shadow if using {@link ShadowDevicePolicyManagerWrapper} is not possible.
+ */
+@Implements(DevicePolicyManager.class)
+public class ShadowDevicePolicyManager extends org.robolectric.shadows.ShadowDevicePolicyManager {
+    private Map<Integer, CharSequence> mSupportMessagesMap = new HashMap<>();
+    private boolean mIsAdminActiveAsUser = false;
+
+    public void setShortSupportMessageForUser(ComponentName admin, int userHandle, String message) {
+        mSupportMessagesMap.put(Objects.hash(admin, userHandle), message);
+    }
+
+    @Implementation
+    public @Nullable CharSequence getShortSupportMessageForUser(@NonNull ComponentName admin,
+            int userHandle) {
+        return mSupportMessagesMap.get(Objects.hash(admin, userHandle));
+    }
+
+    @Implementation
+    public boolean isAdminActiveAsUser(@NonNull ComponentName admin, int userId) {
+        return mIsAdminActiveAsUser;
+    }
+
+    public void setIsAdminActiveAsUser(boolean active) {
+        mIsAdminActiveAsUser = active;
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowProcess.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowProcess.java
new file mode 100644
index 0000000..eea3ee8
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowProcess.java
@@ -0,0 +1,18 @@
+package com.android.settings.testutils.shadow;
+
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+@Implements(android.os.Process.class)
+public class ShadowProcess {
+    private static int sUid;
+
+    public static void setMyUid(int uid) {
+        sUid = uid;
+    }
+
+    @Implementation
+    public static int myUid() {
+        return sUid;
+    }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java
index dfd4b7f..9979ddb 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java
@@ -17,7 +17,6 @@
 package com.android.settings.testutils.shadow;
 
 import android.annotation.UserIdInt;
-import android.content.Context;
 import android.content.pm.UserInfo;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -31,7 +30,6 @@
 import org.robolectric.shadow.api.Shadow;
 
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -42,10 +40,12 @@
     private SparseArray<UserInfo> mUserInfos = new SparseArray<>();
     private final List<String> mRestrictions = new ArrayList<>();
     private final Map<String, List<EnforcingUser>> mRestrictionSources = new HashMap<>();
+    private List<UserInfo> mUserProfileInfos = new ArrayList<>();
 
     @Resetter
     public void reset() {
         mRestrictions.clear();
+        mUserProfileInfos.clear();
     }
 
     public void setUserInfo(int userHandle, UserInfo userInfo) {
@@ -57,9 +57,13 @@
         return mUserInfos.get(userHandle);
     }
 
+    public void addProfile(UserInfo userInfo) {
+        mUserProfileInfos.add(userInfo);
+    }
+
     @Implementation
     public List<UserInfo> getProfiles(@UserIdInt int userHandle) {
-        return Collections.emptyList();
+        return mUserProfileInfos;
     }
 
     @Implementation
diff --git a/tests/robotests/src/libcore/util/CountryTimeZones.java b/tests/robotests/src/libcore/util/CountryTimeZones.java
deleted file mode 100644
index 2087848..0000000
--- a/tests/robotests/src/libcore/util/CountryTimeZones.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2018 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 libcore.util;
-
-import java.util.List;
-
-/**
- * Empty implementation of CountryTimeZones for Robolectric test.
- */
-public class CountryTimeZones {
-    public CountryTimeZones() {
-    }
-
-    public final static class TimeZoneMapping {
-        public final String timeZoneId;
-        public final boolean showInPicker;
-
-        public TimeZoneMapping(String timeZoneId, boolean showInPicker) {
-            this.timeZoneId = timeZoneId;
-            this.showInPicker = showInPicker;
-        }
-    }
-
-    public List<TimeZoneMapping> getTimeZoneMappings() {
-        return null;
-    }
-
-    public String getCountryIso() {
-        return null;
-    }
-}
diff --git a/tests/robotests/src/libcore/util/CountryZonesFinder.java b/tests/robotests/src/libcore/util/CountryZonesFinder.java
deleted file mode 100644
index 51149ec..0000000
--- a/tests/robotests/src/libcore/util/CountryZonesFinder.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2018 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 libcore.util;
-
-import java.util.List;
-
-/**
- * Empty implementation of CountryZonesFinder for Robolectric test.
- */
-public class CountryZonesFinder {
-    public CountryZonesFinder(List<CountryTimeZones> countryTimeZonesList) {}
-
-    public List<String> lookupAllCountryIsoCodes() {
-        return null;
-    }
-
-    public List<CountryTimeZones> lookupCountryTimeZonesForZoneId(String zoneId) {
-        return null;
-    }
-
-    public CountryTimeZones lookupCountryTimeZones(String countryIso) {
-        return null;
-    }
-}