Merge "Change to use setupcompat and setupdesign for suw pages"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 7807f0e..caca444 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -3054,6 +3054,14 @@
             </intent-filter>
         </activity>
 
+        <activity
+            android:name=".wifi.dpp.WifiDppEnrolleeActivity">
+            <intent-filter>
+                <action android:name="android.settings.WIFI_DPP_ENROLLEE_QR_CODE_SCANNER"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+            </intent-filter>
+        </activity>
+
         <activity android:name=".homepage.contextualcards.ContextualCardFeedbackDialog"
                   android:theme="@android:style/Theme.DeviceDefault.Light.Dialog.Alert" />
         <!-- This is the longest AndroidManifest.xml ever. -->
diff --git a/res/drawable/ic_qrcode_24dp.xml b/res/drawable/ic_qrcode_24dp.xml
new file mode 100644
index 0000000..ff7806f
--- /dev/null
+++ b/res/drawable/ic_qrcode_24dp.xml
@@ -0,0 +1,39 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M7,4v3H4V4H7M9,2H2v7h7V2L9,2z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M15,11l-8,0l0,2l8,0l0,-2z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M13,2l-2,0l0,11l2,0l0,-11z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M22,15l-11,0l0,2l11,0l0,-2z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M13,17l-2,0l0,5l2,0l0,-5z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M17,13l-2,0l0,9l2,0l0,-9z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M22,19l-3,0l0,3l3,0l0,-3z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M5,11l-3,0l0,2l3,0l0,-2z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M22,11l-5,0l0,2l5,0l0,-2z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M20,4v3h-3V4H20M22,2h-7v7h7V2L22,2z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M7,17v3H4v-3H7M9,15H2v7h7V15L9,15z"/>
+</vector>
diff --git a/res/drawable/ic_scan_24dp.xml b/res/drawable/ic_scan_24dp.xml
new file mode 100644
index 0000000..bcef8e3
--- /dev/null
+++ b/res/drawable/ic_scan_24dp.xml
@@ -0,0 +1,33 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M9,2l-7,0l0,2l7,0l0,-2z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M22,2l-7,0l0,2l7,0l0,-2z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M22,11l-20,0l0,2l20,0l0,-2z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M22,2l-2,0l0,7l2,0l0,-7z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M4,2l-2,0l0,7l2,0l0,-7z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M9,20l-7,0l0,2l7,0l0,-2z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M22,20l-7,0l0,2l7,0l0,-2z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M22,15l-2,0l0,7l2,0l0,-7z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M4,15l-2,0l0,7l2,0l0,-7z"/>
+</vector>
diff --git a/res/layout/enable_accessibility_service_dialog_content.xml b/res/layout/enable_accessibility_service_dialog_content.xml
index f212eb1..e16dc65 100644
--- a/res/layout/enable_accessibility_service_dialog_content.xml
+++ b/res/layout/enable_accessibility_service_dialog_content.xml
@@ -38,20 +38,13 @@
             android:textAppearance="?android:attr/textAppearanceMedium"/>
 
         <TextView
-            android:id="@+id/capabilities_header"
+            android:id="@+id/accessibility_service_warning"
             android:layout_width="fill_parent"
             android:layout_height="wrap_content"
             android:padding="10dip"
             android:textAlignment="viewStart"
             android:textAppearance="?android:attr/textAppearanceMedium"/>
 
-        <LinearLayout
-            android:id="@+id/capabilities"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:orientation="vertical"
-            android:padding="10dip"/>
-
     </LinearLayout>
 
 </ScrollView>
diff --git a/res/layout/wifi_button_preference_widget.xml b/res/layout/wifi_button_preference_widget.xml
new file mode 100644
index 0000000..55078c2
--- /dev/null
+++ b/res/layout/wifi_button_preference_widget.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+
+<ImageButton xmlns:android="http://schemas.android.com/apk/res/android"
+           android:id="@+id/button_icon"
+           android:layout_width="wrap_content"
+           android:layout_height="wrap_content"
+           android:layout_gravity="center"
+           android:background="@null"
+           android:visibility="gone"
+           android:contentDescription="@string/wifi_add_network" />
diff --git a/res/layout/wifi_dialog.xml b/res/layout/wifi_dialog.xml
index bb2946d..2a395b6 100644
--- a/res/layout/wifi_dialog.xml
+++ b/res/layout/wifi_dialog.xml
@@ -50,13 +50,28 @@
                         android:text="@string/wifi_ssid"
                         android:textDirection="locale" />
 
-                <EditText android:id="@+id/ssid"
+                <RelativeLayout
                         android:layout_width="match_parent"
+                        android:layout_height="wrap_content" >
+                    <EditText android:id="@+id/ssid"
+                            android:layout_width="match_parent"
+                            android:layout_height="wrap_content"
+                            style="@style/wifi_item_edit_content"
+                            android:hint="@string/wifi_ssid_hint"
+                            android:singleLine="true"
+                            android:inputType="textNoSuggestions" />
+                    <ImageButton
+                        android:id="@+id/ssid_scanner_button"
+                        android:layout_width="wrap_content"
                         android:layout_height="wrap_content"
-                        style="@style/wifi_item_edit_content"
-                        android:hint="@string/wifi_ssid_hint"
-                        android:singleLine="true"
-                        android:inputType="textNoSuggestions" />
+                        android:layout_alignParentRight="true"
+                        android:layout_centerVertical="true"
+                        android:layout_margin="5dp"
+                        android:background="@null"
+                        android:src="@drawable/ic_qrcode_24dp"
+                        android:visibility="gone"
+                        android:contentDescription="@string/wifi_add_network" />
+                </RelativeLayout>
 
                 <LinearLayout android:id="@+id/ssid_too_long_warning"
                               android:layout_width="match_parent"
@@ -270,12 +285,28 @@
                         style="@style/wifi_item_label"
                         android:text="@string/wifi_password" />
 
-                <EditText android:id="@+id/password"
-                        android:layout_width="match_parent"
+                <RelativeLayout
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content" >
+                    <EditText android:id="@+id/password"
+                              android:layout_width="match_parent"
+                              android:layout_height="wrap_content"
+                              style="@style/wifi_item_edit_content"
+                              android:singleLine="true"
+                              android:password="true" />
+
+                    <ImageButton
+                        android:id="@+id/password_scanner_button"
+                        android:layout_width="wrap_content"
                         android:layout_height="wrap_content"
-                        style="@style/wifi_item_edit_content"
-                        android:singleLine="true"
-                        android:password="true" />
+                        android:layout_alignParentRight="true"
+                        android:layout_centerVertical="true"
+                        android:layout_margin="5dp"
+                        android:background="@null"
+                        android:src="@drawable/ic_qrcode_24dp"
+                        android:visibility="gone"
+                        android:contentDescription="@string/wifi_add_network" />
+                </RelativeLayout>
             </LinearLayout>
 
             <LinearLayout android:id="@+id/show_password_layout"
diff --git a/res/layout/wifi_dpp_qrcode_scanner_fragment.xml b/res/layout/wifi_dpp_qrcode_scanner_fragment.xml
index ab38ac1..0beacff 100644
--- a/res/layout/wifi_dpp_qrcode_scanner_fragment.xml
+++ b/res/layout/wifi_dpp_qrcode_scanner_fragment.xml
@@ -44,8 +44,5 @@
         android:layout_height="wrap_content"
         android:layout_gravity="center"/>
 
-    <include layout="@layout/wifi_dpp_fragment_footer"
-        android:gravity="center|bottom"/>
-
 </LinearLayout>
 
diff --git a/res/values/strings.xml b/res/values/strings.xml
index cbb5e3b..6aacb0a 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -653,6 +653,8 @@
     <string name="done">Done</string>
     <!-- Button label for generic apply action [CHAR LIMIT=20] -->
     <string name="apply">Apply</string>
+    <!-- Button label for generic share action [CHAR LIMIT=20] -->
+    <string name="share">Share</string>
 
     <!-- Title of the Settings activity shown within the application itself. -->
     <string name="settings_label">Settings</string>
@@ -2054,6 +2056,14 @@
     <string name="wifi_dpp_add_device_to_network">Add a device to this network</string>
     <!-- Hint for the user to center another device's QR code in the below camera window [CHAR LIMIT=120] -->
     <string name="wifi_dpp_center_qr_code">Center the device\u2019s QR code below to add device to \u201c<xliff:g id="ssid" example="OfficeWifi">%1$s</xliff:g>\u201d</string>
+    <!-- Title for the fragment to scan QR code [CHAR LIMIT=50]  -->
+    <string name="wifi_dpp_scan_qr_code">Scan QR code</string>
+    <!-- Hint for the user to center another device's QR code in the below camera window [CHAR LIMIT=NONE] -->
+    <string name="wifi_dpp_scan_qr_code_join_network">Join \u201c<xliff:g id="ssid" example="OfficeWifi">%1$s</xliff:g>\u201d by scanning a QR code</string>
+    <!-- Title for the fragment to share Wi-Fi [CHAR LIMIT=50]  -->
+    <string name="wifi_dpp_share_wifi">Share Wi\u2011Fi</string>
+    <!-- Hint for the user to use another device to scan QR code on screen to join Wi-Fi [CHAR LIMIT=NONE] -->
+    <string name="wifi_dpp_scan_qr_code_with_another_device">Scan this QR code with another device to join \u201c<xliff:g id="ssid" example="OfficeWifi">%1$s</xliff:g>\u201d</string>
     <!-- Label for the check box to share a network with other users on the same device -->
     <string name="wifi_shared">Share with other device users</string>
     <!-- Hint for unchanged fields -->
@@ -3765,6 +3775,8 @@
     <string name="lockpassword_choose_your_pattern_header_for_face">To use face authentication, set pattern</string>
     <!-- Header on first screen of choose password/PIN as backup for face authentication flow. If this string cannot be translated in under 40 characters, please translate "Set face authentication backup" [CHAR LIMIT=40] -->
     <string name="lockpassword_choose_your_pin_header_for_face">To use face authentication, set PIN</string>
+    <!-- Message on Wi-Fi Sharing screen [CHAR LIMIT=NONE] -->
+    <string name="wifi_sharing_message">Your Wi\u2011Fi name and password for \"<xliff:g id="SSID" example="GoogleGuest">%1$s</xliff:g>\" will be shared.</string>
 
     <!-- Message to be used to explain the user that he needs to enter his pattern to continue a
          particular operation. [CHAR LIMIT=70]-->
@@ -4826,11 +4838,12 @@
         example="TalkBack">%1$s</xliff:g> affects data encryption, you need to confirm your password.
     </string>
 
-    <!-- Title for the capability of an accessibility service to receive events and keys. -->
-    <string name="capability_title_receiveAccessibilityEvents">Observe your actions</string>
-    <!-- Description for the capability of an accessibility service to receive events and keys. -->
-    <string name="capability_desc_receiveAccessibilityEvents">Receive notifications when you\u2019re
-        interacting with an app.</string>
+    <!-- Warning that explains that accessibility services have a lot of access to user data [CHAR LIMIT=NONE] -->
+    <string name="accessibility_service_warning"><xliff:g id="service"
+        example="TalkBack">%1$s</xliff:g> is requesting full control of this device. The service
+        can read the screen and act on behalf of users with accessibility needs.
+        This level of control is not appropriate for most apps.
+    </string>
 
     <!-- Title for a warning about disabling an accessibility service. [CHAR LIMIT=NONE] -->
     <string name="disable_service_title">Stop <xliff:g id="service" example="TalkBack">%1$s</xliff:g>?</string>
@@ -5417,11 +5430,23 @@
     <!-- Battery saver: Label for preference to indicate there is no battery saver schedule [CHAR_LIMIT=40] -->
     <string name="battery_saver_auto_no_schedule">No schedule</string>
 
+    <!-- Battery saver: Label for preference to indicate there is a routine based schedule [CHAR_LIMIT=40] -->
+    <string name="battery_saver_auto_routine">Based on your routine</string>
+
+    <!-- Battery saver: Label for preference to indicate there is a percentage based schedule [CHAR_LIMIT=40] -->
+    <string name="battery_saver_auto_percentage">Based on percentage</string>
+
+    <!-- Battery saver: Summary for preference to describe what is meant by a routine based schedule [CHAR_LIMIT=NONE] -->
+    <string name="battery_saver_auto_routine_summary">Battery Saver turns on if your battery is likely to run out before your next typical charge</string>
+
+    <!-- Battery saver: Label for seekbar to change battery saver threshold [CHAR_LIMIT=40] -->
+    <string name="battery_saver_auto_percentage_summary">Will turn on at <xliff:g id="percent" example="52%">%1$s</xliff:g></string>
+
     <!-- Battery saver: Title for battery saver schedule screen [CHAR_LIMIT=40] -->
     <string name="battery_saver_schedule_settings_title">Set a schedule</string>
 
     <!-- Battery saver: Label for seekbar to change battery saver threshold [CHAR_LIMIT=40] -->
-    <string name="battery_saver_seekbar_title">At <xliff:g id="percent">%1$s</xliff:g></string>
+    <string name="battery_saver_seekbar_title"><xliff:g id="percent">%1$s</xliff:g></string>
 
     <!-- Battery saver: Placeholder label for seekbar to change battery saver threshold [CHAR_LIMIT=40] -->
     <string name="battery_saver_seekbar_title_placeholder">Turn on</string>
@@ -7137,6 +7162,9 @@
     <!--  Do not disturb: Delete text button presented in a dialog to confirm the user would like to delete the selected DND rules. [CHAR LIMIT=30] -->
     <string name="zen_mode_schedule_delete">Delete</string>
 
+    <!--  Do not disturb: Edit label for button that allows user to edit the dnd schedule name. [CHAR LIMIT=30] -->
+    <string name="zen_mode_rule_name_edit">Edit</string>
+
     <!--  Do not disturb: Title for the zen mode automatic rules page in settings. [CHAR LIMIT=30] -->
     <string name="zen_mode_automation_settings_page_title">Schedules</string>
 
@@ -7907,7 +7935,7 @@
         <item quantity="other"><xliff:g id="num_people" example="3">%d</xliff:g> others</item>
     </plurals>
 
-    <!-- [CHAR LIMIT=20] Zen mode settings: Messages option -->
+    <!-- [CHAR LIMIT=40] Zen mode settings: Messages option -->
     <string name="zen_mode_messages">Allow text messages</string>
 
     <!-- Do not disturb settings, messages, events and reminders footer [CHAR LIMIT=NONE]-->
@@ -8384,6 +8412,12 @@
     <!--  Title for Default Phone app settings [CHAR LIMIT=30] -->
     <string name="default_phone_title">Phone app</string>
 
+    <!--
+     ~ STOPSHIP(b/110557011): Remove once the new UI is ready.
+     -->
+    <!-- Title for Roles settings [CHAR LIMIT=30] -->
+    <string name="roles_title">Roles</string>
+
     <!-- Label of default app for current setting [CHAR LIMIT=40] -->
     <string name="default_app">(Default)</string>
 
@@ -10248,7 +10282,9 @@
     <!-- Message for Network connection timeout Dialog [CHAR LIMIT=NONE] -->
     <string name="network_connection_timeout_dialog_message">No devices found. Make sure the device is turned on and available to connect.</string>
     <!-- OK button for Network connection timeout Dialog [CHAR LIMIT=30] -->
-    <string name="network_connection_timeout_dialog_ok">Scan again</string>
+    <string name="network_connection_timeout_dialog_ok">Try again</string>
+    <!-- Message for Network connection error state Dialog [CHAR LIMIT=NONE] -->
+    <string name="network_connection_errorstate_dialog_message">Something came up. The application has cancelled the request to choose a device.</string>
 
     <!-- Summary for bluetooth devices count in Bluetooth devices slice. [CHAR LIMIT=NONE] -->
     <plurals name="show_bluetooth_devices">
diff --git a/res/values/themes.xml b/res/values/themes.xml
index 1e24770..9a05bfc 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -198,6 +198,7 @@
         <item name="android:windowLightStatusBar">true</item>
         <item name="android:navigationBarDividerColor">@*android:color/ripple_material_light</item>
         <item name="android:navigationBarColor">@android:color/white</item>
+        <item name="android:windowBackground">@android:color/white</item>
         <item name="android:windowLightNavigationBar">true</item>
     </style>
 
diff --git a/res/xml/app_default_settings.xml b/res/xml/app_default_settings.xml
index a993aa1..c26c069 100644
--- a/res/xml/app_default_settings.xml
+++ b/res/xml/app_default_settings.xml
@@ -79,6 +79,14 @@
         android:fragment="com.android.settings.applications.managedomainurls.ManageDomainUrls"
         settings:keywords="@string/keywords_default_links"/>
 
+    <!--
+     ~ STOPSHIP(b/110557011): Remove once the new UI is ready.
+     -->
+    <Preference
+        android:key="roles"
+        android:title="@string/roles_title"
+        settings:controller="com.android.settings.applications.defaultapps.RolesPreferenceController" />
+
     <com.android.settings.widget.WorkOnlyCategory
         android:key="work_app_defaults"
         android:title="@string/default_for_work">
diff --git a/res/xml/battery_saver_settings.xml b/res/xml/battery_saver_settings.xml
index eb4954f..a086018 100644
--- a/res/xml/battery_saver_settings.xml
+++ b/res/xml/battery_saver_settings.xml
@@ -20,6 +20,12 @@
     android:title="@string/battery_saver"
     android:key="battery_saver_page">
 
+    <Preference
+        android:key="battery_saver_schedule"
+        android:fragment="com.android.settings.fuelgauge.batterysaver.BatterySaverScheduleSettings"
+        android:title="@string/battery_saver_schedule_settings_title"
+        settings:controller="com.android.settings.fuelgauge.batterysaver.BatterySaverSchedulePreferenceController"/>
+
     <!-- Turn on automatically -->
     <SwitchPreference
         android:key="auto_battery_saver"
diff --git a/res/xml/zen_mode_event_rule_settings.xml b/res/xml/zen_mode_event_rule_settings.xml
index c871fe1..a70b46c 100644
--- a/res/xml/zen_mode_event_rule_settings.xml
+++ b/res/xml/zen_mode_event_rule_settings.xml
@@ -17,12 +17,17 @@
 
 <PreferenceScreen
     xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:settings="http://schemas.android.com/apk/res-auto"
     android:key="zen_mode_event_rule_settings"
     android:title="@string/zen_mode_automatic_rule_settings_page_title">
 
     <com.android.settingslib.widget.LayoutPreference
         android:key="pref_app_header"
-        android:layout="@layout/settings_entity_header" />
+        android:layout="@layout/settings_entity_header"
+        settings:allowDividerBelow="true" />
+
+    <com.android.settingslib.widget.ActionButtonsPreference
+        android:key="zen_action_buttons" />
 
     <com.android.settingslib.widget.LayoutPreference
         android:key="zen_automatic_rule_switch"
diff --git a/res/xml/zen_mode_schedule_rule_settings.xml b/res/xml/zen_mode_schedule_rule_settings.xml
index c257d87..7de10b3 100644
--- a/res/xml/zen_mode_schedule_rule_settings.xml
+++ b/res/xml/zen_mode_schedule_rule_settings.xml
@@ -17,12 +17,17 @@
 
 <PreferenceScreen
     xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:settings="http://schemas.android.com/apk/res-auto"
     android:key="zen_mode_schedule_rule_settings"
     android:title="@string/zen_mode_automatic_rule_settings_page_title">
 
     <com.android.settingslib.widget.LayoutPreference
         android:key="pref_app_header"
-        android:layout="@layout/settings_entity_header" />
+        android:layout="@layout/settings_entity_header"
+        settings:allowDividerBelow="true"/>
+
+    <com.android.settingslib.widget.ActionButtonsPreference
+        android:key="zen_action_buttons"/>
 
     <com.android.settingslib.widget.LayoutPreference
         android:key="zen_automatic_rule_switch"
diff --git a/src/com/android/settings/accessibility/AccessibilityServiceWarning.java b/src/com/android/settings/accessibility/AccessibilityServiceWarning.java
index 6360d42..e0f1747 100644
--- a/src/com/android/settings/accessibility/AccessibilityServiceWarning.java
+++ b/src/com/android/settings/accessibility/AccessibilityServiceWarning.java
@@ -43,8 +43,8 @@
 import java.util.Locale;
 
 /**
- * Utility class for creating the dialog that asks users for explicit permission to grant
- * all of the requested capabilities to an accessibility service before the service is enabled
+ * Utility class for creating the dialog that asks users for explicit permission for an
+ * accessibility service to access user data before the service is enabled
  */
 public class AccessibilityServiceWarning {
     public static Dialog createCapabilitiesDialog(Activity parentActivity,
@@ -117,60 +117,9 @@
             encryptionWarningView.setVisibility(View.GONE);
         }
 
-        TextView capabilitiesHeaderView = (TextView) content.findViewById(
-                R.id.capabilities_header);
-        capabilitiesHeaderView.setText(context.getString(R.string.capabilities_list_title,
-                getServiceName(context, info)));
-
-        LinearLayout capabilitiesView = (LinearLayout) content.findViewById(R.id.capabilities);
-
-        // This capability is implicit for all services.
-        View capabilityView = inflater.inflate(
-                com.android.internal.R.layout.app_permission_item_old, null);
-
-        ImageView imageView = (ImageView) capabilityView.findViewById(
-                com.android.internal.R.id.perm_icon);
-        imageView.setImageDrawable(context.getDrawable(
-                com.android.internal.R.drawable.ic_text_dot));
-
-        TextView labelView = (TextView) capabilityView.findViewById(
-                com.android.internal.R.id.permission_group);
-        labelView.setText(context.getString(
-                R.string.capability_title_receiveAccessibilityEvents));
-
-        TextView descriptionView = (TextView) capabilityView.findViewById(
-                com.android.internal.R.id.permission_list);
-        descriptionView.setText(
-                context.getString(R.string.capability_desc_receiveAccessibilityEvents));
-
-        List<AccessibilityServiceInfo.CapabilityInfo> capabilities =
-                info.getCapabilityInfos(context);
-
-        capabilitiesView.addView(capabilityView);
-
-        // Service-specific capabilities.
-        final int capabilityCount = capabilities.size();
-        for (int i = 0; i < capabilityCount; i++) {
-            AccessibilityServiceInfo.CapabilityInfo capability = capabilities.get(i);
-
-            capabilityView = inflater.inflate(
-                    com.android.internal.R.layout.app_permission_item_old, null);
-
-            imageView = (ImageView) capabilityView.findViewById(
-                    com.android.internal.R.id.perm_icon);
-            imageView.setImageDrawable(context.getDrawable(
-                    com.android.internal.R.drawable.ic_text_dot));
-
-            labelView = (TextView) capabilityView.findViewById(
-                    com.android.internal.R.id.permission_group);
-            labelView.setText(context.getString(capability.titleResId));
-
-            descriptionView = (TextView) capabilityView.findViewById(
-                    com.android.internal.R.id.permission_list);
-            descriptionView.setText(context.getString(capability.descResId));
-
-            capabilitiesView.addView(capabilityView);
-        }
+        TextView serviceWarningTextView = content.findViewById(R.id.accessibility_service_warning);
+        serviceWarningTextView.setText(context.getString(R.string.accessibility_service_warning,
+            getServiceName(context, info)));
 
         return content;
     }
diff --git a/src/com/android/settings/applications/defaultapps/RolesPreferenceController.java b/src/com/android/settings/applications/defaultapps/RolesPreferenceController.java
new file mode 100644
index 0000000..59166dd
--- /dev/null
+++ b/src/com/android/settings/applications/defaultapps/RolesPreferenceController.java
@@ -0,0 +1,62 @@
+/*
+ * 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.applications.defaultapps;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.provider.Settings;
+import android.text.TextUtils;
+
+import androidx.preference.Preference;
+
+import com.android.settings.core.BasePreferenceController;
+
+/**
+ * STOPSHIP(b/110557011): Remove once the new UI is ready.
+ */
+public class RolesPreferenceController extends BasePreferenceController {
+
+    private Intent mIntent;
+
+    public RolesPreferenceController(Context context, String preferenceKey) {
+        super(context, preferenceKey);
+
+        PackageManager packageManager = context.getPackageManager();
+        String packageName = packageManager.getPermissionControllerPackageName();
+        if (packageName != null) {
+            mIntent = new Intent(Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS)
+                    .setPackage(packageName);
+        }
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return mIntent != null ? AVAILABLE_UNSEARCHABLE : UNSUPPORTED_ON_DEVICE;
+    }
+
+    @Override
+    public boolean handlePreferenceTreeClick(Preference preference) {
+        if (TextUtils.equals(preference.getKey(), mPreferenceKey)) {
+            if (mIntent != null) {
+                mContext.startActivity(mIntent);
+            }
+            return true;
+        }
+        return false;
+    }
+}
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollSidecar.java b/src/com/android/settings/biometrics/face/FaceEnrollSidecar.java
index 7b445e5..2433fcb 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollSidecar.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollSidecar.java
@@ -43,8 +43,9 @@
         if (mUserId != UserHandle.USER_NULL) {
             mFaceManager.setActiveUser(mUserId);
         }
+        // TODO: Send the list of disabled features
         mFaceManager.enroll(mToken, mEnrollmentCancel,
-                0 /* flags */, mUserId, mEnrollmentCallback);
+                mEnrollmentCallback, new int[0] /* disabledFeatures */);
     }
 
     private FaceManager.EnrollmentCallback mEnrollmentCallback
diff --git a/src/com/android/settings/biometrics/face/FaceSettingsAttentionPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsAttentionPreferenceController.java
index 9c4f964..2e32bf3 100644
--- a/src/com/android/settings/biometrics/face/FaceSettingsAttentionPreferenceController.java
+++ b/src/com/android/settings/biometrics/face/FaceSettingsAttentionPreferenceController.java
@@ -48,7 +48,6 @@
 
     public void setToken(byte[] token) {
         mToken = token;
-        mPreference.setChecked(mFaceManager.getRequireAttention(mToken));
     }
 
     /**
@@ -64,18 +63,13 @@
     public boolean isChecked() {
         if (!FaceSettings.isAvailable(mContext)) {
             return true;
-        } else if (mToken == null) {
-            // The token will be null when the controller is first created, since CC has not been
-            // completed by the user. Once it's completed, FaceSettings will use setToken which
-            // will retrieve the correct value from FaceService
-            return true;
         }
-        return mFaceManager.getRequireAttention(mToken);
+        return mFaceManager.getFeature(FaceManager.FEATURE_REQUIRE_ATTENTION);
     }
 
     @Override
     public boolean setChecked(boolean isChecked) {
-        mFaceManager.setRequireAttention(isChecked, mToken);
+        mFaceManager.setFeature(FaceManager.FEATURE_REQUIRE_ATTENTION, isChecked, mToken);
         return true;
     }
 
diff --git a/src/com/android/settings/core/FeatureFlags.java b/src/com/android/settings/core/FeatureFlags.java
index daa1e7b..b350778 100644
--- a/src/com/android/settings/core/FeatureFlags.java
+++ b/src/com/android/settings/core/FeatureFlags.java
@@ -26,4 +26,5 @@
     public static final String MOBILE_NETWORK_V2 = "settings_mobile_network_v2";
     public static final String WIFI_MAC_RANDOMIZATION = "settings_wifi_mac_randomization";
     public static final String NETWORK_INTERNET_V2 = "settings_network_and_internet_v2";
+    public static final String WIFI_SHARING = "settings_wifi_sharing";
 }
diff --git a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverSchedulePreferenceController.java b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverSchedulePreferenceController.java
new file mode 100644
index 0000000..cc6aa00
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverSchedulePreferenceController.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.fuelgauge.batterysaver;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.os.PowerManager;
+import android.provider.Settings;
+import android.provider.Settings.Global;
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+import com.android.settings.R;
+import com.android.settings.Utils;
+import com.android.settings.core.BasePreferenceController;
+
+public class BatterySaverSchedulePreferenceController extends BasePreferenceController {
+
+    @VisibleForTesting
+    Preference mBatterySaverSchedulePreference;
+    public static final String KEY_BATTERY_SAVER_SCHEDULE = "battery_saver_schedule";
+
+
+    public BatterySaverSchedulePreferenceController(Context context) {
+        super(context, KEY_BATTERY_SAVER_SCHEDULE);
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return KEY_BATTERY_SAVER_SCHEDULE;
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        mBatterySaverSchedulePreference = screen.findPreference(KEY_BATTERY_SAVER_SCHEDULE);
+    }
+
+    @Override
+    public CharSequence getSummary() {
+        final ContentResolver resolver = mContext.getContentResolver();
+        final int mode = Settings.Global.getInt(resolver, Global.AUTOMATIC_POWER_SAVER_MODE,
+                PowerManager.POWER_SAVER_MODE_PERCENTAGE);
+        if (mode == PowerManager.POWER_SAVER_MODE_PERCENTAGE) {
+            final int threshold =
+                    Settings.Global.getInt(resolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
+            if (threshold <= 0) {
+                return mContext.getText(R.string.battery_saver_auto_no_schedule);
+            } else {
+                return mContext.getString(R.string.battery_saver_auto_percentage_summary,
+                        Utils.formatPercentage(threshold));
+            }
+        } else {
+            return mContext.getText(R.string.battery_saver_auto_routine);
+        }
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return AVAILABLE;
+    }
+}
diff --git a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSettings.java b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSettings.java
new file mode 100644
index 0000000..fad9f31
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSettings.java
@@ -0,0 +1,138 @@
+/*
+ * 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.batterysaver;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.view.View;
+import androidx.preference.PreferenceScreen;
+import com.android.settings.widget.RadioButtonPickerFragment;
+import com.android.settings.R;
+import com.android.settings.widget.RadioButtonPreference;
+import com.android.settings.widget.SeekBarPreference;
+import com.android.settingslib.widget.CandidateInfo;
+import com.google.common.collect.Lists;
+import java.util.List;
+
+public class BatterySaverScheduleSettings extends RadioButtonPickerFragment {
+
+    private static final String KEY_NO_SCHEDULE = "key_battery_saver_no_schedule";
+    private static final String KEY_ROUTINE = "key_battery_saver_routine";
+    private static final String KEY_PERCENTAGE = "key_battery_saver_percentage";
+    public static final int MAX_SEEKBAR_VALUE = 15;
+    public static final int MIN_SEEKBAR_VALUE = 1;
+    public static final String KEY_BATTERY_SAVER_SEEK_BAR = "battery_saver_seek_bar";
+
+    @Override
+    protected int getPreferenceScreenResId() {
+        return R.xml.battery_saver_schedule_settings;
+    }
+
+    @Override
+    protected List<? extends CandidateInfo> getCandidates() {
+        Context context = getContext();
+        List<CandidateInfo> candidates = Lists.newArrayList();
+        candidates.add(new BatterySaverScheduleCandidateInfo(
+                context.getText(R.string.battery_saver_auto_no_schedule),
+                /* summary */ null,
+                KEY_NO_SCHEDULE,
+                /* enabled */ true));
+        candidates.add(new BatterySaverScheduleCandidateInfo(
+                context.getText(R.string.battery_saver_auto_routine),
+                context.getText(R.string.battery_saver_auto_routine_summary),
+                KEY_ROUTINE,
+                /* enabled */ true));
+        candidates.add(new BatterySaverScheduleCandidateInfo(
+                context.getText(R.string.battery_saver_auto_percentage),
+                /* summary */ null,
+                KEY_PERCENTAGE,
+                /* enabled */ true));
+
+        return candidates;
+    }
+
+    @Override
+    public void bindPreferenceExtra(RadioButtonPreference pref, String key, CandidateInfo info,
+            String defaultKey, String systemDefaultKey) {
+        final BatterySaverScheduleCandidateInfo candidateInfo =
+                (BatterySaverScheduleCandidateInfo) info;
+        final CharSequence summary = candidateInfo.getSummary();
+        if (summary != null) {
+            pref.setSummary(summary);
+            pref.setAppendixVisibility(View.GONE);
+        }
+    }
+
+    @Override
+    protected void addStaticPreferences(PreferenceScreen screen) {
+        SeekBarPreference seekbar = new SeekBarPreference(getContext());
+        seekbar.setMax(MAX_SEEKBAR_VALUE);
+        seekbar.setMin(MIN_SEEKBAR_VALUE);
+        seekbar.setTitle(R.string.battery_saver_seekbar_title_placeholder);
+        seekbar.setKey(KEY_BATTERY_SAVER_SEEK_BAR);
+        screen.addPreference(seekbar);
+    }
+
+    @Override
+    protected String getDefaultKey() {
+        return null;
+    }
+
+    @Override
+    protected boolean setDefaultKey(String key) {
+        return false;
+    }
+
+    @Override
+    public int getMetricsCategory() {
+        return 0;
+    }
+
+    static class BatterySaverScheduleCandidateInfo extends CandidateInfo {
+
+        private final CharSequence mLabel;
+        private final CharSequence mSummary;
+        private final String mKey;
+
+        BatterySaverScheduleCandidateInfo(CharSequence label, CharSequence summary, String key,
+                boolean enabled) {
+            super(enabled);
+            mLabel = label;
+            mKey = key;
+            mSummary = summary;
+        }
+
+        @Override
+        public CharSequence loadLabel() {
+            return mLabel;
+        }
+
+        @Override
+        public Drawable loadIcon() {
+            return null;
+        }
+
+        @Override
+        public String getKey() {
+            return mKey;
+        }
+
+        public CharSequence getSummary() {
+            return mSummary;
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/network/SubscriptionsChangeListener.java b/src/com/android/settings/network/SubscriptionsChangeListener.java
new file mode 100644
index 0000000..c3bb22b
--- /dev/null
+++ b/src/com/android/settings/network/SubscriptionsChangeListener.java
@@ -0,0 +1,97 @@
+/*
+ * 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.network;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.provider.Settings;
+import android.telephony.SubscriptionManager;
+import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
+
+import com.android.internal.telephony.TelephonyIntents;
+
+/** Helper class for listening to changes in availability of telephony subscriptions */
+public class SubscriptionsChangeListener extends ContentObserver {
+
+    public interface SubscriptionsChangeListenerClient {
+        void onAirplaneModeChanged(boolean airplaneModeEnabled);
+        void onSubscriptionsChanged();
+    }
+
+    private Context mContext;
+    private SubscriptionsChangeListenerClient mClient;
+    private SubscriptionManager mSubscriptionManager;
+    private OnSubscriptionsChangedListener mSubscriptionsChangedListener;
+    private Uri mAirplaneModeSettingUri;
+    private BroadcastReceiver mBroadcastReceiver;
+
+    public SubscriptionsChangeListener(Context context, SubscriptionsChangeListenerClient client) {
+        super(new Handler());
+        mContext = context;
+        mClient = client;
+        mSubscriptionManager = mContext.getSystemService(SubscriptionManager.class);
+        mSubscriptionsChangedListener = new OnSubscriptionsChangedListener() {
+            @Override
+            public void onSubscriptionsChanged() {
+                subscriptionsChangedCallback();
+            }
+        };
+        mAirplaneModeSettingUri = Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON);
+        mBroadcastReceiver = new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                subscriptionsChangedCallback();
+            }
+        };
+    }
+
+    public void start() {
+        mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionsChangedListener);
+        mContext.getContentResolver()
+                .registerContentObserver(mAirplaneModeSettingUri, false, this);
+        final IntentFilter radioTechnologyChangedFilter = new IntentFilter(
+                TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED);
+        mContext.registerReceiver(mBroadcastReceiver, radioTechnologyChangedFilter);
+    }
+
+    public void stop() {
+        mSubscriptionManager.removeOnSubscriptionsChangedListener(mSubscriptionsChangedListener);
+        mContext.getContentResolver().unregisterContentObserver(this);
+        mContext.unregisterReceiver(mBroadcastReceiver);
+    }
+
+    public boolean isAirplaneModeOn() {
+        return Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.AIRPLANE_MODE_ON, 0) != 0;
+    }
+
+    private void subscriptionsChangedCallback() {
+        mClient.onSubscriptionsChanged();
+    }
+
+    @Override
+    public void onChange(boolean selfChange, Uri uri) {
+        if (uri.equals(mAirplaneModeSettingUri)) {
+            mClient.onAirplaneModeChanged(isAirplaneModeOn());
+        }
+    }
+}
diff --git a/src/com/android/settings/notification/ZenAutomaticRuleHeaderPreferenceController.java b/src/com/android/settings/notification/ZenAutomaticRuleHeaderPreferenceController.java
index c2db773..5fa3954 100644
--- a/src/com/android/settings/notification/ZenAutomaticRuleHeaderPreferenceController.java
+++ b/src/com/android/settings/notification/ZenAutomaticRuleHeaderPreferenceController.java
@@ -76,14 +76,6 @@
                 mController = EntityHeaderController
                         .newInstance(mFragment.getActivity(), mFragment,
                                 pref.findViewById(R.id.entity_header));
-
-                mController.setEditListener(new View.OnClickListener() {
-                    @Override
-                    public void onClick(View v) {
-                        ZenRuleNameDialog.show(mFragment, mRule.getName(), null,
-                                new RuleNameChangeListener());
-                    }
-                });
             }
 
             pref = mController.setIcon(getIcon())
@@ -123,20 +115,4 @@
         mRule = rule;
         mId = id;
     }
-
-    public class RuleNameChangeListener implements ZenRuleNameDialog.PositiveClickListener {
-        public RuleNameChangeListener() {}
-
-        @Override
-        public void onOk(String ruleName, Fragment parent) {
-            if (TextUtils.equals(ruleName, mRule.getName())) {
-                return;
-            }
-            mMetricsFeatureProvider.action(mContext,
-                    MetricsProto.MetricsEvent.ACTION_ZEN_MODE_RULE_NAME_CHANGE_OK);
-            mRule.setName(ruleName);
-            mRule.setModified(true);
-            mBackend.updateZenRule(mId, mRule);
-        }
-    }
 }
diff --git a/src/com/android/settings/notification/ZenModeAutomationSettings.java b/src/com/android/settings/notification/ZenModeAutomationSettings.java
index c559a28..d6a7d72 100644
--- a/src/com/android/settings/notification/ZenModeAutomationSettings.java
+++ b/src/com/android/settings/notification/ZenModeAutomationSettings.java
@@ -20,6 +20,7 @@
 import android.app.AutomaticZenRule;
 import android.content.Context;
 import android.content.DialogInterface;
+import android.os.Bundle;
 import android.provider.SearchIndexableResource;
 import android.service.notification.ConditionProviderService;
 import android.view.Menu;
@@ -44,12 +45,23 @@
 
 @SearchIndexable
 public class ZenModeAutomationSettings extends ZenModeSettingsBase {
+    public static final String DELETE = "DELETE_RULE";
     protected final ManagedServiceSettings.Config CONFIG = getConditionProviderConfig();
     private CharSequence[] mDeleteDialogRuleNames;
     private String[] mDeleteDialogRuleIds;
     private boolean[] mDeleteDialogChecked;
 
     @Override
+    public void onAttach(Context context) {
+        super.onAttach(context);
+        Bundle bundle = getArguments();
+        if (bundle != null && bundle.containsKey(DELETE)) {
+            mBackend.removeZenRule(bundle.getString(DELETE));
+            bundle.remove(DELETE);
+        }
+    }
+
+    @Override
     protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
         ZenServiceListing serviceListing = new ZenServiceListing(getContext(), CONFIG);
         serviceListing.reloadApprovedServices();
diff --git a/src/com/android/settings/notification/ZenModeEventRuleSettings.java b/src/com/android/settings/notification/ZenModeEventRuleSettings.java
index c11a672..ee3ed1c 100644
--- a/src/com/android/settings/notification/ZenModeEventRuleSettings.java
+++ b/src/com/android/settings/notification/ZenModeEventRuleSettings.java
@@ -27,6 +27,11 @@
 import android.service.notification.ZenModeConfig;
 import android.service.notification.ZenModeConfig.EventInfo;
 
+import androidx.preference.DropDownPreference;
+import androidx.preference.Preference;
+import androidx.preference.Preference.OnPreferenceChangeListener;
+import androidx.preference.PreferenceScreen;
+
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settings.R;
@@ -38,11 +43,6 @@
 import java.util.List;
 import java.util.Objects;
 
-import androidx.preference.DropDownPreference;
-import androidx.preference.Preference;
-import androidx.preference.Preference.OnPreferenceChangeListener;
-import androidx.preference.PreferenceScreen;
-
 public class ZenModeEventRuleSettings extends ZenModeRuleSettingsBase {
     private static final String KEY_CALENDAR = "calendar";
     private static final String KEY_REPLY = "reply";
@@ -85,9 +85,12 @@
         List<AbstractPreferenceController> controllers = new ArrayList<>();
         mHeader = new ZenAutomaticRuleHeaderPreferenceController(context, this,
                 getSettingsLifecycle());
+        mActionButtons = new ZenRuleButtonsPreferenceController(context, this,
+                getSettingsLifecycle());
         mSwitch = new ZenAutomaticRuleSwitchPreferenceController(context, this,
                 getSettingsLifecycle());
         controllers.add(mHeader);
+        controllers.add(mActionButtons);
         controllers.add(mSwitch);
         return controllers;
     }
@@ -107,8 +110,16 @@
                 mEvent.calendarId = calendar.calendarId;
             }
         }
-        mCalendar.setEntries(entries.toArray(new CharSequence[entries.size()]));
-        mCalendar.setEntryValues(values.toArray(new CharSequence[values.size()]));
+
+        CharSequence[] entriesArr = entries.toArray(new CharSequence[entries.size()]);
+        CharSequence[] valuesArr = values.toArray(new CharSequence[values.size()]);
+        if (!Objects.equals(mCalendar.getEntries(), entriesArr)) {
+            mCalendar.setEntries(entriesArr);
+        }
+
+        if (!Objects.equals(mCalendar.getEntryValues(), valuesArr)) {
+            mCalendar.setEntryValues(valuesArr);
+        }
     }
 
     @Override
@@ -159,8 +170,12 @@
 
     @Override
     protected void updateControlsInternal() {
-        mCalendar.setValue(key(mEvent));
-        mReply.setValue(Integer.toString(mEvent.reply));
+        if (!Objects.equals(mCalendar.getValue(), key(mEvent))) {
+            mCalendar.setValue(key(mEvent));
+        }
+        if (!Objects.equals(mReply.getValue(), Integer.toString(mEvent.reply))) {
+            mReply.setValue(Integer.toString(mEvent.reply));
+        }
     }
 
     @Override
@@ -233,7 +248,7 @@
 
     private static String key(int userId, Long calendarId, String displayName) {
         return EventInfo.resolveUserId(userId) + ":" + (calendarId == null ? "" : calendarId)
-                + ":" + displayName;
+                + ":" + (displayName == null ? "" : displayName);
     }
 
     private static final Comparator<CalendarInfo> CALENDAR_NAME = new Comparator<CalendarInfo>() {
diff --git a/src/com/android/settings/notification/ZenModeRuleSettingsBase.java b/src/com/android/settings/notification/ZenModeRuleSettingsBase.java
index 11b8084..e573884 100644
--- a/src/com/android/settings/notification/ZenModeRuleSettingsBase.java
+++ b/src/com/android/settings/notification/ZenModeRuleSettingsBase.java
@@ -43,6 +43,7 @@
     protected String mId;
 
     protected ZenAutomaticRuleHeaderPreferenceController mHeader;
+    protected ZenRuleButtonsPreferenceController mActionButtons;
     protected ZenAutomaticRuleSwitchPreferenceController mSwitch;
 
     abstract protected void onCreateInternal();
@@ -104,6 +105,10 @@
         mHeader.onResume(mRule, mId);
         mHeader.displayPreference(screen);
         updatePreference(mHeader);
+
+        mActionButtons.onResume(mRule, mId);
+        mActionButtons.displayPreference(screen);
+        updatePreference(mActionButtons);
     }
 
     private void updatePreference(AbstractPreferenceController controller) {
@@ -147,7 +152,8 @@
 
     private void toastAndFinish() {
         Toast.makeText(mContext, R.string.zen_mode_rule_not_found_text, Toast.LENGTH_SHORT)
-                    .show();
+                .show();
+
         getActivity().finish();
     }
 
diff --git a/src/com/android/settings/notification/ZenModeScheduleRuleSettings.java b/src/com/android/settings/notification/ZenModeScheduleRuleSettings.java
index 0b2e1bc..8aa993f 100644
--- a/src/com/android/settings/notification/ZenModeScheduleRuleSettings.java
+++ b/src/com/android/settings/notification/ZenModeScheduleRuleSettings.java
@@ -199,10 +199,12 @@
         List<AbstractPreferenceController> controllers = new ArrayList<>();
         mHeader = new ZenAutomaticRuleHeaderPreferenceController(context, this,
                 getSettingsLifecycle());
+        mActionButtons = new ZenRuleButtonsPreferenceController(context, this,
+                getSettingsLifecycle());
         mSwitch = new ZenAutomaticRuleSwitchPreferenceController(context, this,
                 getSettingsLifecycle());
-
         controllers.add(mHeader);
+        controllers.add(mActionButtons);
         controllers.add(mSwitch);
         return controllers;
     }
diff --git a/src/com/android/settings/notification/ZenModeSettingsBase.java b/src/com/android/settings/notification/ZenModeSettingsBase.java
index 2aecae4..b9a14ee 100644
--- a/src/com/android/settings/notification/ZenModeSettingsBase.java
+++ b/src/com/android/settings/notification/ZenModeSettingsBase.java
@@ -52,9 +52,14 @@
     }
 
     @Override
-    public void onCreate(Bundle icicle) {
-        mContext = getActivity();
+    public void onAttach(Context context) {
+        super.onAttach(context);
+        mContext = context;
         mBackend = ZenModeBackend.getInstance(mContext);
+    }
+
+    @Override
+    public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
         updateZenMode(false /*fireChanged*/);
     }
diff --git a/src/com/android/settings/notification/ZenRuleButtonsPreferenceController.java b/src/com/android/settings/notification/ZenRuleButtonsPreferenceController.java
new file mode 100644
index 0000000..1d43f6d
--- /dev/null
+++ b/src/com/android/settings/notification/ZenRuleButtonsPreferenceController.java
@@ -0,0 +1,124 @@
+/*
+ * 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.notification;
+
+import android.app.AutomaticZenRule;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.View;
+
+import androidx.fragment.app.Fragment;
+import androidx.preference.PreferenceFragmentCompat;
+import androidx.preference.PreferenceScreen;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.R;
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settings.core.SubSettingLauncher;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.widget.ActionButtonsPreference;
+
+public class ZenRuleButtonsPreferenceController extends AbstractZenModePreferenceController
+    implements PreferenceControllerMixin {
+    public static final String KEY = "zen_action_buttons";
+
+    private AutomaticZenRule mRule;
+    private String mId;
+    private PreferenceFragmentCompat mFragment;
+    private ActionButtonsPreference mButtonsPref;
+
+
+    public ZenRuleButtonsPreferenceController(Context context, PreferenceFragmentCompat fragment,
+            Lifecycle lc) {
+        super(context, KEY, lc);
+        mFragment = fragment;
+    }
+
+
+    @Override
+    public boolean isAvailable() {
+        return mRule != null;
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        if (isAvailable()) {
+            mButtonsPref = ((ActionButtonsPreference) screen.findPreference(KEY))
+                    .setButton1Text(R.string.zen_mode_rule_name_edit)
+                    .setButton1Icon(R.drawable.ic_mode_edit)
+                    .setButton1OnClickListener(new EditRuleNameClickListener())
+                    .setButton2Text(R.string.zen_mode_delete_rule_button)
+                    .setButton2Icon(R.drawable.ic_settings_delete)
+                    .setButton2OnClickListener(new DeleteRuleClickListener());
+        }
+    }
+
+    public class EditRuleNameClickListener implements View.OnClickListener {
+        public EditRuleNameClickListener() {}
+
+        @Override
+        public void onClick(View v) {
+            ZenRuleNameDialog.show(mFragment, mRule.getName(), null,
+                    new ZenRuleNameDialog.PositiveClickListener() {
+                        @Override
+                        public void onOk(String ruleName, Fragment parent) {
+                            if (TextUtils.equals(ruleName, mRule.getName())) {
+                                return;
+                            }
+                            mMetricsFeatureProvider.action(mContext,
+                                    MetricsProto.MetricsEvent.ACTION_ZEN_MODE_RULE_NAME_CHANGE_OK);
+                            mRule.setName(ruleName);
+                            mRule.setModified(true);
+                            mBackend.updateZenRule(mId, mRule);
+                        }
+                    });
+        }
+    }
+
+    public class DeleteRuleClickListener implements View.OnClickListener {
+        public DeleteRuleClickListener() {}
+
+        @Override
+        public void onClick(View v) {
+            ZenDeleteRuleDialog.show(mFragment, mRule.getName(), mId,
+                    new ZenDeleteRuleDialog.PositiveClickListener() {
+                        @Override
+                        public void onOk(String id) {
+                            Bundle bundle = new Bundle();
+                            bundle.putString(ZenModeAutomationSettings.DELETE, id);
+                            mMetricsFeatureProvider.action(mContext,
+                                    MetricsProto.MetricsEvent.ACTION_ZEN_DELETE_RULE_OK);
+                            new SubSettingLauncher(mContext)
+                                    .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
+                                    .setDestination(ZenModeAutomationSettings.class.getName())
+                                    .setSourceMetricsCategory(MetricsProto.MetricsEvent
+                                            .NOTIFICATION_ZEN_MODE_AUTOMATION)
+                                    .setArguments(bundle)
+                                    .launch();
+                        }
+            });
+        }
+    }
+
+    protected void onResume(AutomaticZenRule rule, String id) {
+        mRule = rule;
+        mId = id;
+    }
+}
diff --git a/src/com/android/settings/widget/RadioButtonPreference.java b/src/com/android/settings/widget/RadioButtonPreference.java
index ed7f905..512fe4e 100644
--- a/src/com/android/settings/widget/RadioButtonPreference.java
+++ b/src/com/android/settings/widget/RadioButtonPreference.java
@@ -44,6 +44,8 @@
     }
 
     private OnClickListener mListener = null;
+    private View appendix;
+    private int appendixVisibility = -1;
 
     public RadioButtonPreference(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
@@ -81,6 +83,10 @@
         if (summaryContainer != null) {
             summaryContainer.setVisibility(
                 TextUtils.isEmpty(getSummary()) ? View.GONE : View.VISIBLE);
+            appendix = view.findViewById(R.id.appendix);
+            if (appendix != null && appendixVisibility != -1) {
+                appendix.setVisibility(appendixVisibility);
+            }
         }
 
         TextView title = (TextView) view.findViewById(android.R.id.title);
@@ -89,4 +95,11 @@
             title.setMaxLines(3);
         }
     }
+
+    public void setAppendixVisibility(int visibility) {
+        if (appendix != null) {
+            appendix.setVisibility(visibility);
+        }
+        appendixVisibility = visibility;
+    }
 }
diff --git a/src/com/android/settings/wifi/AddNetworkFragment.java b/src/com/android/settings/wifi/AddNetworkFragment.java
index 814b358..72d878b 100644
--- a/src/com/android/settings/wifi/AddNetworkFragment.java
+++ b/src/com/android/settings/wifi/AddNetworkFragment.java
@@ -23,12 +23,14 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.Button;
+import android.widget.ImageButton;
 
 import androidx.annotation.VisibleForTesting;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settings.R;
 import com.android.settings.core.InstrumentedFragment;
+import com.android.settings.wifi.dpp.WifiDppUtils;
 
 public class AddNetworkFragment extends InstrumentedFragment implements WifiConfigUiBase,
         View.OnClickListener {
@@ -64,6 +66,18 @@
         mCancelBtn.setOnClickListener(this);
         mUIController = new WifiConfigController(this, rootView, null, getMode());
 
+        if (WifiDppUtils.isSharingNetworkEnabled(getContext())) {
+            final ImageButton scannerButton = rootView.findViewById(R.id.ssid_scanner_button);
+            if (scannerButton != null) {
+                scannerButton.setVisibility(View.VISIBLE);
+                scannerButton.setOnClickListener((View v) -> {
+                    // Launch QR code scanner to join a network.
+                    getContext().startActivity(
+                            WifiDppUtils.getConfiguratorQRCodeScannerIntent(/* ssid */ null));
+                });
+            }
+        }
+
         return rootView;
     }
 
diff --git a/src/com/android/settings/wifi/ButtonPreference.java b/src/com/android/settings/wifi/ButtonPreference.java
new file mode 100644
index 0000000..62e8caf
--- /dev/null
+++ b/src/com/android/settings/wifi/ButtonPreference.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.wifi;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+import android.widget.ImageButton;
+
+import com.android.settings.R;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.annotation.DrawableRes;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceViewHolder;
+
+/**
+ * This preference provides one button layout with Settings style.
+ * It looks like below
+ *
+ * --------------------------------------------------------------
+ * | icon | title                                    |  button  |
+ * --------------------------------------------------------------
+ *
+ * User can set icon / click listener for button.
+ * By default, the button is invisible.
+ */
+public class ButtonPreference extends Preference {
+
+    private static final String TAG = "ButtonPreference";
+
+    private ImageButton mImageButton;
+    private Drawable mButtonIcon;
+    private View.OnClickListener mClickListener;
+
+    // Used for dummy pref.
+    public ButtonPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        setWidgetLayoutResource(R.layout.wifi_button_preference_widget);
+        mImageButton = null;
+        mButtonIcon = null;
+        mClickListener = null;
+    }
+
+    public ButtonPreference(Context context) {
+        this(context, /* attrs */ null);
+    }
+
+    @Override
+    public void onBindViewHolder(final PreferenceViewHolder view) {
+        super.onBindViewHolder(view);
+        initButton(view);
+    }
+
+    @Override
+    public void setOrder(int order) {
+        super.setOrder(order);
+        setButtonVisibility();
+    }
+
+    @VisibleForTesting
+    protected void initButton(final PreferenceViewHolder view) {
+        if (mImageButton == null) {
+            mImageButton = (ImageButton) view.findViewById(R.id.button_icon);
+        }
+        if (mImageButton != null) {
+            mImageButton.setImageDrawable(mButtonIcon);
+            mImageButton.setOnClickListener(mClickListener);
+        }
+        setButtonVisibility();
+    }
+
+    private void setButtonVisibility() {
+        if(mImageButton != null) {
+            mImageButton.setVisibility(mButtonIcon == null ? View.GONE : View.VISIBLE);
+        }
+    }
+
+    /**
+     * Sets the drawable to be displayed in button.
+     */
+    public ButtonPreference setButtonIcon(@DrawableRes int iconResId) {
+        if (iconResId == 0) {
+            return this;
+        }
+
+        try {
+            mButtonIcon = getContext().getDrawable(iconResId);
+            notifyChanged();
+        } catch (Resources.NotFoundException exception) {
+            Log.e(TAG, "Resource does not exist: " + iconResId);
+        }
+        return this;
+    }
+
+    /**
+     * Register a callback to be invoked when button is clicked.
+     */
+    public ButtonPreference setButtonOnClickListener(View.OnClickListener listener) {
+        if (listener != mClickListener) {
+            mClickListener = listener;
+            notifyChanged();
+        }
+        return this;
+    }
+}
diff --git a/src/com/android/settings/wifi/NetworkRequestDialogFragment.java b/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
index a1d8620..efb3f8c 100644
--- a/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
+++ b/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
@@ -44,12 +44,18 @@
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.R;
 import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+import com.android.settings.wifi.NetworkRequestErrorDialogFragment.ERROR_DIALOG_TYPE;
 import com.android.settingslib.Utils;
 import com.android.settingslib.wifi.AccessPoint;
 
 import java.util.ArrayList;
 import java.util.List;
 
+/**
+ * The Fragment sets up callback {@link NetworkRequestMatchCallback} with framework. To handle most
+ * behaviors of the callback when requesting wifi network, except for error message. When error
+ * happens, {@link NetworkRequestErrorDialogFragment} will be called to display error message.
+ */
 public class NetworkRequestDialogFragment extends InstrumentedDialogFragment implements
         DialogInterface.OnClickListener, NetworkRequestMatchCallback {
 
@@ -131,7 +137,7 @@
     @Override
     public void onCancel(@NonNull DialogInterface dialog) {
         super.onCancel(dialog);
-        // Finishes activity when user clicks back key or outside of dialog.
+        // Finishes the activity when user clicks back key or outside of the dialog.
         getActivity().finish();
     }
 
@@ -166,7 +172,7 @@
             switch (msg.what) {
                 case MESSAGE_STOP_SCAN_WIFI_LIST:
                     removeMessages(MESSAGE_STOP_SCAN_WIFI_LIST);
-                    stopScanningAndPopTimeoutDialog();
+                    stopScanningAndPopErrorDialog(ERROR_DIALOG_TYPE.TIME_OUT);
                     break;
                 default:
                     // Do nothing.
@@ -175,14 +181,18 @@
         }
     };
 
-    protected void stopScanningAndPopTimeoutDialog() {
+    protected void stopScanningAndPopErrorDialog(ERROR_DIALOG_TYPE type) {
         // Dismisses current dialog.
         dismiss();
 
         // Throws new timeout dialog.
-        final NetworkRequestTimeoutDialogFragment fragment = NetworkRequestTimeoutDialogFragment
+        final NetworkRequestErrorDialogFragment fragment = NetworkRequestErrorDialogFragment
                 .newInstance();
-        fragment.show(getActivity().getSupportFragmentManager(), null);
+        final Bundle bundle = new Bundle();
+        bundle.putSerializable(NetworkRequestErrorDialogFragment.DIALOG_TYPE, type);
+        fragment.setArguments(bundle);
+        fragment.show(getActivity().getSupportFragmentManager(),
+                NetworkRequestDialogFragment.class.getSimpleName());
     }
 
     @Override
@@ -239,7 +249,7 @@
 
     @Override
     public void onAbort() {
-        // TODO(b/117399926): We should have a UI notify user here.
+        stopScanningAndPopErrorDialog(ERROR_DIALOG_TYPE.ABORT);
     }
 
     @Override
diff --git a/src/com/android/settings/wifi/NetworkRequestErrorDialogFragment.java b/src/com/android/settings/wifi/NetworkRequestErrorDialogFragment.java
new file mode 100644
index 0000000..762b467
--- /dev/null
+++ b/src/com/android/settings/wifi/NetworkRequestErrorDialogFragment.java
@@ -0,0 +1,86 @@
+/*
+ * 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.wifi;
+
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.os.Bundle;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.R;
+import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+
+/**
+ * The dialog shows an error message when requesting network {@link NetworkRequestDialogFragment}.
+ * Contains multi-error types in {@code ERROR_DIALOG_TYPE}.
+ */
+public class NetworkRequestErrorDialogFragment extends InstrumentedDialogFragment {
+
+    public static final String DIALOG_TYPE = "DIALOG_ERROR_TYPE";
+
+    public enum ERROR_DIALOG_TYPE {TIME_OUT, ABORT}
+
+    public static NetworkRequestErrorDialogFragment newInstance() {
+        return new NetworkRequestErrorDialogFragment();
+    }
+
+    private NetworkRequestErrorDialogFragment() {
+        super();
+    }
+
+    @Override
+    public void onCancel(@NonNull DialogInterface dialog) {
+        super.onCancel(dialog);
+        // Wants to finish the activity when user clicks back key or outside of the dialog.
+        getActivity().finish();
+    }
+
+    @Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        // Gets error type to construct dialog. Default is TIME_OUT dialog.
+        ERROR_DIALOG_TYPE msgType = ERROR_DIALOG_TYPE.TIME_OUT;
+        if (getArguments() != null) {
+            msgType = (ERROR_DIALOG_TYPE) getArguments().getSerializable(DIALOG_TYPE);
+        }
+
+        final AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
+        if (msgType == ERROR_DIALOG_TYPE.TIME_OUT) {
+            builder.setMessage(R.string.network_connection_timeout_dialog_message)
+                    .setPositiveButton(R.string.network_connection_timeout_dialog_ok,
+                            (dialog, which) -> startScanningDialog())
+                    .setNegativeButton(R.string.cancel, (dialog, which) -> getActivity().finish());
+        } else {
+            builder.setMessage(R.string.network_connection_errorstate_dialog_message)
+                    .setPositiveButton(R.string.okay, (dialog, which) -> getActivity().finish());
+        }
+        return builder.create();
+    }
+
+    @Override
+    public int getMetricsCategory() {
+        return MetricsProto.MetricsEvent.WIFI_SCANNING_NEEDED_DIALOG;
+    }
+
+    protected void startScanningDialog() {
+        final NetworkRequestDialogFragment fragment = NetworkRequestDialogFragment.newInstance();
+        fragment.show(getActivity().getSupportFragmentManager(),
+                NetworkRequestErrorDialogFragment.class.getSimpleName());
+    }
+}
diff --git a/src/com/android/settings/wifi/NetworkRequestTimeoutDialogFragment.java b/src/com/android/settings/wifi/NetworkRequestTimeoutDialogFragment.java
deleted file mode 100644
index 08f285b..0000000
--- a/src/com/android/settings/wifi/NetworkRequestTimeoutDialogFragment.java
+++ /dev/null
@@ -1,66 +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 com.android.settings.wifi;
-
-import android.app.Dialog;
-import android.content.DialogInterface;
-import android.os.Bundle;
-import androidx.appcompat.app.AlertDialog;
-import com.android.internal.logging.nano.MetricsProto;
-import com.android.settings.R;
-import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
-
-public class NetworkRequestTimeoutDialogFragment extends InstrumentedDialogFragment implements
-    DialogInterface.OnClickListener {
-
-  public static NetworkRequestTimeoutDialogFragment newInstance() {
-    NetworkRequestTimeoutDialogFragment fragment = new NetworkRequestTimeoutDialogFragment();
-    return fragment;
-  }
-
-  @Override
-  public Dialog onCreateDialog(Bundle savedInstanceState) {
-    AlertDialog.Builder builder = new AlertDialog.Builder(getContext())
-        .setMessage(R.string.network_connection_timeout_dialog_message)
-        .setPositiveButton(R.string.network_connection_timeout_dialog_ok, this)
-        .setNegativeButton(R.string.cancel, null);
-    return builder.create();
-  }
-
-  @Override
-  public int getMetricsCategory() {
-    return MetricsProto.MetricsEvent.WIFI_SCANNING_NEEDED_DIALOG;
-  }
-
-  @Override
-  public void onClick(DialogInterface dialog, int which) {
-    switch (which) {
-      case DialogInterface.BUTTON_POSITIVE:
-        startScanningDialog();
-        break;
-      case DialogInterface.BUTTON_NEGATIVE:
-      default:
-        // Do nothing.
-        break;
-    }
-  }
-
-  protected void startScanningDialog() {
-    NetworkRequestDialogFragment fragment = NetworkRequestDialogFragment.newInstance();
-    fragment.show(getActivity().getSupportFragmentManager(), null);
-  }
-}
diff --git a/src/com/android/settings/wifi/WifiDialog.java b/src/com/android/settings/wifi/WifiDialog.java
index 2b8fb2d..0e2ca60 100644
--- a/src/com/android/settings/wifi/WifiDialog.java
+++ b/src/com/android/settings/wifi/WifiDialog.java
@@ -21,10 +21,13 @@
 import android.os.Bundle;
 import android.view.View;
 import android.widget.Button;
+import android.widget.ImageButton;
 
 import androidx.appcompat.app.AlertDialog;
 
 import com.android.settings.R;
+import com.android.settings.wifi.dpp.WifiDppUtils;
+
 import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.wifi.AccessPoint;
@@ -77,7 +80,18 @@
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
-        mView = getLayoutInflater().inflate(R.layout.wifi_dialog, null);
+        mView = getLayoutInflater().inflate(R.layout.wifi_dialog, /* root */ null);
+        if (WifiDppUtils.isSharingNetworkEnabled(getContext())) {
+            final ImageButton scannerButton = mView.findViewById(R.id.password_scanner_button);
+            if (scannerButton != null) {
+                scannerButton.setVisibility(View.VISIBLE);
+                scannerButton.setOnClickListener((View v) -> {
+                    // Launch QR code scanner to join a network.
+                    getContext().startActivity(
+                            WifiDppUtils.getConfiguratorQRCodeScannerIntent(/* ssid */ null));
+                });
+            }
+        }
         setView(mView);
         mController = new WifiConfigController(this, mView, mAccessPoint, mMode);
         super.onCreate(savedInstanceState);
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index 1c9a5e1..54de28d 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -66,6 +66,7 @@
 import com.android.settings.widget.SummaryUpdater.OnSummaryChangeListener;
 import com.android.settings.widget.SwitchBarController;
 import com.android.settings.wifi.details.WifiNetworkDetailsFragment;
+import com.android.settings.wifi.dpp.WifiDppUtils;
 import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.search.SearchIndexable;
@@ -175,7 +176,7 @@
 
     private PreferenceCategory mConnectedAccessPointPreferenceCategory;
     private PreferenceCategory mAccessPointsPreferenceCategory;
-    private Preference mAddPreference;
+    private ButtonPreference mAddPreference;
     @VisibleForTesting
     Preference mConfigureWifiSettingsPreference;
     @VisibleForTesting
@@ -235,9 +236,17 @@
         mSavedNetworksPreference = findPreference(PREF_KEY_SAVED_NETWORKS);
 
         Context prefContext = getPrefContext();
-        mAddPreference = new Preference(prefContext);
+        mAddPreference = new ButtonPreference(prefContext);
         mAddPreference.setIcon(R.drawable.ic_menu_add);
         mAddPreference.setTitle(R.string.wifi_add_network);
+        if (WifiDppUtils.isSharingNetworkEnabled(getContext())) {
+            mAddPreference.setButtonIcon(R.drawable.ic_qrcode_24dp);
+            mAddPreference.setButtonOnClickListener((View v) -> {
+                // Launch QR code scanner to join a network.
+                getContext().startActivity(
+                        WifiDppUtils.getConfiguratorQRCodeScannerIntent(/* ssid */ null));
+            });
+        }
         mStatusMessagePreference = (LinkablePreference) findPreference(PREF_KEY_STATUS_MESSAGE);
 
         mUserBadgeCache = new AccessPointPreference.UserBadgeCache(getPackageManager());
diff --git a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
index a676bfa..e1179f8 100644
--- a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
+++ b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
@@ -20,6 +20,7 @@
 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
 
 import android.app.Activity;
+import android.app.KeyguardManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -40,6 +41,7 @@
 import android.net.wifi.WifiManager;
 import android.os.Handler;
 import android.text.TextUtils;
+import android.util.FeatureFlagUtils;
 import android.util.Log;
 import android.widget.ImageView;
 import android.widget.Toast;
@@ -54,8 +56,11 @@
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.R;
 import com.android.settings.Utils;
+import com.android.settings.core.FeatureFlags;
 import com.android.settings.core.PreferenceControllerMixin;
 import com.android.settings.widget.EntityHeaderController;
+import com.android.settings.wifi.dpp.WifiDppConfiguratorActivity;
+import com.android.settings.wifi.dpp.WifiDppUtils;
 import com.android.settings.wifi.WifiDialog;
 import com.android.settings.wifi.WifiDialog.WifiDialogListener;
 import com.android.settings.wifi.WifiUtils;
@@ -280,7 +285,10 @@
                 .setButton1Icon(R.drawable.ic_settings_delete)
                 .setButton1OnClickListener(view -> forgetNetwork())
                 .setButton2Text(R.string.wifi_sign_in_button_text)
-                .setButton2OnClickListener(view -> signIntoNetwork());
+                .setButton2OnClickListener(view -> signIntoNetwork())
+                .setButton3Text(R.string.share)
+                .setButton3Icon(R.drawable.ic_qrcode_24dp)
+                .setButton3OnClickListener(view -> shareNetwork());
 
         mSignalStrengthPref = screen.findPreference(KEY_SIGNAL_STRENGTH_PREF);
         mLinkSpeedPref = screen.findPreference(KEY_LINK_SPEED);
@@ -296,7 +304,7 @@
         mIpv6Category = (PreferenceCategory) screen.findPreference(KEY_IPV6_CATEGORY);
         mIpv6AddressPref = screen.findPreference(KEY_IPV6_ADDRESSES_PREF);
 
-        mSecurityPref.setSummary(mAccessPoint.getSecurityString(false /* concise */));
+        mSecurityPref.setSummary(mAccessPoint.getSecurityString(/* concise */ false));
     }
 
     private void setupEntityHeader(PreferenceScreen screen) {
@@ -425,7 +433,9 @@
 
     private void updateIpLayerInfo() {
         mButtonsPref.setButton2Visible(canSignIntoNetwork());
-        mButtonsPref.setVisible(canSignIntoNetwork() || canForgetNetwork());
+        mButtonsPref.setButton3Visible(isSharingNetworkEnabled());
+        mButtonsPref.setVisible(
+                canSignIntoNetwork() || canForgetNetwork() || isSharingNetworkEnabled());
 
         if (mNetwork == null || mLinkProperties == null) {
             mIpAddressPref.setVisible(false);
@@ -511,6 +521,13 @@
     }
 
     /**
+     * Returns whether the user can share the network represented by this preference with QR code.
+     */
+    private boolean isSharingNetworkEnabled() {
+        return FeatureFlagUtils.isEnabled(mContext, FeatureFlags.WIFI_SHARING);
+    }
+
+    /**
      * Forgets the wifi network associated with this preference.
      */
     private void forgetNetwork() {
@@ -529,6 +546,42 @@
     }
 
     /**
+     * Show QR code to share the network represented by this preference.
+     */
+    public void launchQRCodeGenerator() {
+        final Intent intent = new Intent(
+                WifiDppConfiguratorActivity.ACTION_CONFIGURATOR_QR_CODE_GENERATOR);
+        intent.putExtra(WifiDppUtils.EXTRA_WIFI_SECURITY,
+                mAccessPoint.getSecurityString(/* concise */ false));
+        intent.putExtra(WifiDppUtils.EXTRA_WIFI_SSID, mAccessPoint.getSsidStr());
+        mContext.startActivity(intent);
+    }
+
+    /**
+     * Share the wifi network with QR code.
+     */
+    private void shareNetwork() {
+        final KeyguardManager keyguardManager = (KeyguardManager) mContext.getSystemService(
+                Context.KEYGUARD_SERVICE);
+        if (keyguardManager.isKeyguardSecure()) {
+            // Show authentication screen to confirm credentials (pin, pattern or password) for
+            // the current user of the device.
+            final String description = String.format(
+                    mContext.getString(R.string.wifi_sharing_message),
+                    mAccessPoint.getSsidStr());
+            final Intent intent = keyguardManager.createConfirmDeviceCredentialIntent(
+                    mContext.getString(R.string.lockpassword_confirm_your_pattern_header),
+                    description);
+            if (intent != null) {
+                mFragment.startActivityForResult(intent,
+                        WifiNetworkDetailsFragment.REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS);
+            }
+        } else {
+            launchQRCodeGenerator();
+        }
+    }
+
+    /**
      * Sign in to the captive portal found on this wifi network associated with this preference.
      */
     private void signIntoNetwork() {
diff --git a/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java b/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
index 7f0e8ee..9814486 100644
--- a/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
+++ b/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
@@ -17,8 +17,10 @@
 
 import static com.android.settings.wifi.WifiSettings.WIFI_DIALOG_ID;
 
+import android.app.Activity;
 import android.app.Dialog;
 import android.content.Context;
+import android.content.Intent;
 import android.net.ConnectivityManager;
 import android.net.wifi.WifiManager;
 import android.os.Bundle;
@@ -52,6 +54,8 @@
 
     private static final String TAG = "WifiNetworkDetailsFrg";
 
+    public static final int REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS = 1;
+
     private AccessPoint mAccessPoint;
     private WifiDetailPreferenceController mWifiDetailPreferenceController;
 
@@ -142,4 +146,14 @@
 
         return controllers;
     }
+
+    @Override
+    public void onActivityResult(int requestCode, int resultCode, Intent data) {
+        super.onActivityResult(requestCode, resultCode, data);
+
+        if (requestCode == REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS
+                && resultCode == Activity.RESULT_OK) {
+            mWifiDetailPreferenceController.launchQRCodeGenerator();
+        }
+    }
 }
diff --git a/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java b/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java
index d81c19b..e4ae292 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java
@@ -31,8 +31,26 @@
 import com.android.settings.core.InstrumentedActivity;
 import com.android.settings.R;
 
+/**
+ * To provision "other" device with specified Wi-Fi network.
+ *
+ * Uses different intents to specify different provisioning ways.
+ *
+ * For intent action {@code ACTION_CONFIGURATOR_QR_CODE_SCANNER} and
+ * {@code android.settings.WIFI_DPP_CONFIGURATOR_QR_CODE_GENERATOR}, specify the Wi-Fi network to be
+ * provisioned in:
+ *
+ * {@code WifiDppUtils.EXTRA_WIFI_SECURITY}
+ * {@code WifiDppUtils.EXTRA_WIFI_SSID}
+ * {@code WifiDppUtils.EXTRA_WIFI_PRE_SHARED_KEY}
+ * {@code WifiDppUtils.EXTRA_WIFI_HIDDEN_SSID}
+ *
+ * For intent action {@code ACTION_CONFIGURATOR_CHOOSE_SAVED_WIFI_NETWORK}, specify Wi-Fi (DPP)
+ * QR code in {@code WifiDppUtils.EXTRA_QR_CODE}
+ */
 public class WifiDppConfiguratorActivity extends InstrumentedActivity implements
-        WifiNetworkConfig.Retriever {
+        WifiNetworkConfig.Retriever,
+        WifiDppQrCodeGeneratorFragment.OnQrCodeGeneratorFragmentAddButtonClickedListener {
     private static final String TAG = "WifiDppConfiguratorActivity";
 
     public static final String ACTION_CONFIGURATOR_QR_CODE_SCANNER =
@@ -43,7 +61,6 @@
             "android.settings.WIFI_DPP_CONFIGURATOR_CHOOSE_SAVED_WIFI_NETWORK";
 
     private FragmentManager mFragmentManager;
-    private FragmentTransaction mFragmentTransaction;
 
     /** The Wi-Fi network which will be configured */
     private WifiNetworkConfig mWifiNetworkConfig;
@@ -57,12 +74,20 @@
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+
         setContentView(R.layout.wifi_dpp_activity);
-
         mFragmentManager = getSupportFragmentManager();
-        mFragmentTransaction = getSupportFragmentManager().beginTransaction();
 
-        Intent intent = getIntent();
+        handleIntent(getIntent());
+
+        ActionBar actionBar = getActionBar();
+        if (actionBar != null) {
+            actionBar.setElevation(0);
+            actionBar.setDisplayShowTitleEnabled(false);
+        }
+    }
+
+    private void handleIntent(Intent intent) {
         boolean cancelActivity = false;
         WifiNetworkConfig config;
         switch (intent.getAction()) {
@@ -72,7 +97,7 @@
                     cancelActivity = true;
                 } else {
                     mWifiNetworkConfig = config;
-                    addQrCodeScannerFragment(/* addToBackStack= */ false);
+                    showQrCodeScannerFragment(/* addToBackStack= */ false);
                 }
                 break;
             case ACTION_CONFIGURATOR_QR_CODE_GENERATOR:
@@ -81,11 +106,11 @@
                     cancelActivity = true;
                 } else {
                     mWifiNetworkConfig = config;
-                    addQrCodeGeneratorFragment();
+                    showQrCodeGeneratorFragment();
                 }
                 break;
             case ACTION_CONFIGURATOR_CHOOSE_SAVED_WIFI_NETWORK:
-                addChooseSavedWifiNetworkFragment(/* addToBackStack */ false);
+                showChooseSavedWifiNetworkFragment(/* addToBackStack */ false);
                 break;
             default:
                 cancelActivity = true;
@@ -98,45 +123,55 @@
         }
     }
 
-    private void addQrCodeScannerFragment(boolean addToBackStack) {
-        WifiDppQrCodeScannerFragment fragment = new WifiDppQrCodeScannerFragment();
-        mFragmentTransaction.add(R.id.fragment_container, fragment);
-        if (addToBackStack) {
-            mFragmentTransaction.addToBackStack(/* name */ null);
+    private void showQrCodeScannerFragment(boolean addToBackStack) {
+        // Avoid to replace the same fragment during configuration change
+        if (mFragmentManager.findFragmentByTag(WifiDppUtils.TAG_FRAGMENT_QR_CODE_SCANNER) != null) {
+            return;
         }
-        mFragmentTransaction.commit();
+
+        WifiDppQrCodeScannerFragment fragment = new WifiDppQrCodeScannerFragment();
+        FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
+
+        fragmentTransaction.replace(R.id.fragment_container, fragment,
+                WifiDppUtils.TAG_FRAGMENT_QR_CODE_SCANNER);
+        if (addToBackStack) {
+            fragmentTransaction.addToBackStack(/* name */ null);
+        }
+        fragmentTransaction.commit();
     }
 
-    private void addQrCodeGeneratorFragment() {
+    private void showQrCodeGeneratorFragment() {
+        // Avoid to replace the same fragment during configuration change
+        if (mFragmentManager.findFragmentByTag(
+                WifiDppUtils.TAG_FRAGMENT_QR_CODE_GENERATOR) != null) {
+            return;
+        }
+
         WifiDppQrCodeGeneratorFragment fragment = new WifiDppQrCodeGeneratorFragment();
-        mFragmentTransaction.add(R.id.fragment_container, fragment);
-        mFragmentTransaction.commit();
+        FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
+
+        fragmentTransaction.replace(R.id.fragment_container, fragment,
+                WifiDppUtils.TAG_FRAGMENT_QR_CODE_GENERATOR);
+        fragmentTransaction.commit();
     }
 
-    private void addChooseSavedWifiNetworkFragment(boolean addToBackStack) {
-        ActionBar action = getActionBar();
-        if (action != null) {
-            action.hide();
+    private void showChooseSavedWifiNetworkFragment(boolean addToBackStack) {
+        // Avoid to replace the same fragment during configuration change
+        if (mFragmentManager.findFragmentByTag(
+                WifiDppUtils.TAG_FRAGMENT_CHOOSE_SAVED_WIFI_NETWORK) != null) {
+            return;
         }
 
         WifiDppChooseSavedWifiNetworkFragment fragment =
                 new WifiDppChooseSavedWifiNetworkFragment();
-        mFragmentTransaction.add(R.id.fragment_container, fragment);
+        FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
+
+        fragmentTransaction.replace(R.id.fragment_container, fragment,
+                WifiDppUtils.TAG_FRAGMENT_CHOOSE_SAVED_WIFI_NETWORK);
         if (addToBackStack) {
-            mFragmentTransaction.addToBackStack(/* name */ null);
+            fragmentTransaction.addToBackStack(/* name */ null);
         }
-        mFragmentTransaction.commit();
-    }
-
-    @Override
-    protected void onStop() {
-        Fragment fragment = mFragmentManager.findFragmentById(R.id.fragment_container);
-        if (fragment != null) {
-            // Remove it to prevent stacking multiple fragments after screen rotated.
-            mFragmentManager.beginTransaction().remove(fragment).commit();
-        }
-
-        super.onStop();
+        fragmentTransaction.commit();
     }
 
     @Override
@@ -153,4 +188,22 @@
             return true;
         }
     }
+
+    @Override
+    public boolean onNavigateUp(){
+        Fragment fragment = mFragmentManager.findFragmentById(R.id.fragment_container);
+        if (fragment instanceof WifiDppQrCodeGeneratorFragment) {
+            setResult(Activity.RESULT_CANCELED);
+            finish();
+            return true;
+        } else if (fragment instanceof WifiDppQrCodeScannerFragment) {
+            mFragmentManager.popBackStackImmediate();
+        }
+
+        return false;
+    }
+
+    @Override public void onQrCodeGeneratorFragmentAddButtonClicked() {
+        showQrCodeScannerFragment(/* addToBackStack */ true);
+    }
 }
diff --git a/src/com/android/settings/wifi/dpp/WifiDppEnrolleeActivity.java b/src/com/android/settings/wifi/dpp/WifiDppEnrolleeActivity.java
new file mode 100644
index 0000000..7c58fd5
--- /dev/null
+++ b/src/com/android/settings/wifi/dpp/WifiDppEnrolleeActivity.java
@@ -0,0 +1,106 @@
+/*
+ * 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.wifi.dpp;
+
+import android.app.ActionBar;
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentTransaction;
+
+import com.android.internal.logging.nano.MetricsProto;
+
+import com.android.settings.core.InstrumentedActivity;
+import com.android.settings.R;
+
+/**
+ * To provision "this" device with specified Wi-Fi network.
+ *
+ * To use intent action {@code ACTION_ENROLLEE_QR_CODE_SCANNER}, specify the SSID string of the
+ * Wi-Fi network to be provisioned in {@code WifiDppUtils.EXTRA_QR_CODE}.
+ */
+public class WifiDppEnrolleeActivity extends InstrumentedActivity {
+    private static final String TAG = "WifiDppEnrolleeActivity";
+
+    public static final String ACTION_ENROLLEE_QR_CODE_SCANNER =
+            "android.settings.WIFI_DPP_ENROLLEE_QR_CODE_SCANNER";
+
+    private FragmentManager mFragmentManager;
+
+    @Override
+    public int getMetricsCategory() {
+        //TODO:Should we use a new metrics category for Wi-Fi DPP?
+        return MetricsProto.MetricsEvent.WIFI_NETWORK_DETAILS;
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.wifi_dpp_activity);
+        mFragmentManager = getSupportFragmentManager();
+
+        handleIntent(getIntent());
+
+        ActionBar actionBar = getActionBar();
+        if (actionBar != null) {
+            actionBar.setElevation(0);
+            actionBar.setDisplayShowTitleEnabled(false);
+        }
+    }
+
+    private void handleIntent(Intent intent) {
+        switch (intent.getAction()) {
+            case ACTION_ENROLLEE_QR_CODE_SCANNER:
+                String ssid = intent.getStringExtra(WifiDppUtils.EXTRA_WIFI_SSID);
+                showQrCodeScannerFragment(/* addToBackStack */ false, ssid);
+                break;
+            default:
+                Log.e(TAG, "Launch with an invalid action");
+                setResult(Activity.RESULT_CANCELED);
+                finish();
+        }
+    }
+
+    private void showQrCodeScannerFragment(boolean addToBackStack, String ssid) {
+        // Avoid to replace the same fragment during configuration change
+        if (mFragmentManager.findFragmentByTag(WifiDppUtils.TAG_FRAGMENT_QR_CODE_SCANNER) != null) {
+            return;
+        }
+
+        WifiDppQrCodeScannerFragment fragment = new WifiDppQrCodeScannerFragment(ssid);
+        FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
+
+        fragmentTransaction.replace(R.id.fragment_container, fragment,
+                WifiDppUtils.TAG_FRAGMENT_QR_CODE_SCANNER);
+        if (addToBackStack) {
+            fragmentTransaction.addToBackStack(/* name */ null);
+        }
+        fragmentTransaction.commit();
+    }
+
+    @Override
+    public boolean onNavigateUp(){
+        setResult(Activity.RESULT_CANCELED);
+        finish();
+        return true;
+    }
+}
diff --git a/src/com/android/settings/wifi/dpp/WifiDppQrCodeBaseFragment.java b/src/com/android/settings/wifi/dpp/WifiDppQrCodeBaseFragment.java
index c86fc98..cddd55c 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppQrCodeBaseFragment.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppQrCodeBaseFragment.java
@@ -34,6 +34,10 @@
 import com.android.settings.R;
 
 /**
+ * TODO: Should refine code to only initiate UI component in each child fragment.
+ */
+
+/**
  * There are below 4 fragments for Wi-Fi DPP UI flow, to reduce redundant code of UI components,
  * this parent fragment instantiates all UI components and provides setting APIs for them.
  *
@@ -58,11 +62,9 @@
     private ImageView mWifiApPictureView;   //optional, for WifiDppAddDeviceFragment
     private TextView mChooseDifferentNetwork;//optional, for WifiDppAddDeviceFragment
 
-    private Button mButtonLeft;             //optional, for WifiDppQrCodeScannerFragment,
-                                            //              WifiDppChooseSavedWifiNetworkFragment,
+    private Button mButtonLeft;             //optional, for WifiDppChooseSavedWifiNetworkFragment,
                                             //              WifiDppAddDeviceFragment
-    private Button mButtonRight;            //optional, for WifiDppQrCodeScannerFragment,
-                                            //              WifiDppChooseSavedWifiNetworkFragment,
+    private Button mButtonRight;            //optional, for WifiDppChooseSavedWifiNetworkFragment,
                                             //              WifiDppAddDeviceFragment
 
     abstract protected int getLayout();
@@ -122,8 +124,7 @@
     }
 
     /**
-     * optional, for WifiDppQrCodeScannerFragment,
-     *               WifiDppChooseSavedWifiNetworkFragment,
+     * optional, for WifiDppChooseSavedWifiNetworkFragment,
      *               WifiDppAddDeviceFragment
      */
     protected void setLeftButtonText(String text) {
@@ -133,8 +134,7 @@
     }
 
     /**
-     * optional, for WifiDppQrCodeScannerFragment,
-     *               WifiDppChooseSavedWifiNetworkFragment,
+     * optional, for WifiDppChooseSavedWifiNetworkFragment,
      *               WifiDppAddDeviceFragment
      */
     protected void setRightButtonText(String text) {
@@ -144,8 +144,7 @@
     }
 
     /**
-     * optional, for WifiDppQrCodeScannerFragment,
-     *               WifiDppChooseSavedWifiNetworkFragment,
+     * optional, for WifiDppChooseSavedWifiNetworkFragment,
      *               WifiDppAddDeviceFragment
      */
     protected void hideLeftButton() {
@@ -155,8 +154,7 @@
     }
 
     /**
-     * optional, for WifiDppQrCodeScannerFragment,
-     *               WifiDppChooseSavedWifiNetworkFragment,
+     * optional, for WifiDppChooseSavedWifiNetworkFragment,
      *               WifiDppAddDeviceFragment
      */
     protected void hideRightButton() {
@@ -166,8 +164,7 @@
     }
 
     /**
-     * optional, for WifiDppQrCodeScannerFragment,
-     *               WifiDppChooseSavedWifiNetworkFragment,
+     * optional, for WifiDppChooseSavedWifiNetworkFragment,
      *               WifiDppAddDeviceFragment
      */
     protected void setLeftButtonOnClickListener(View.OnClickListener listener) {
@@ -177,8 +174,7 @@
     }
 
     /**
-     * optional, for WifiDppQrCodeScannerFragment,
-     *               WifiDppChooseSavedWifiNetworkFragment,
+     * optional, for WifiDppChooseSavedWifiNetworkFragment,
      *               WifiDppAddDeviceFragment
      */
     protected void setRightButtonOnClickListener(View.OnClickListener listener) {
diff --git a/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java b/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java
index 9935bf2..b064253 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java
@@ -16,7 +16,12 @@
 
 package com.android.settings.wifi.dpp;
 
+import android.app.ActionBar;
+import android.content.Context;
 import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
 
 import com.android.settings.R;
 
@@ -30,8 +35,64 @@
         return R.layout.wifi_dpp_qrcode_generator_fragment;
     }
 
+    // Container Activity must implement this interface
+    public interface OnQrCodeGeneratorFragmentAddButtonClickedListener {
+        public void onQrCodeGeneratorFragmentAddButtonClicked();
+    }
+    OnQrCodeGeneratorFragmentAddButtonClickedListener mListener;
+
     @Override
-    public void onActivityCreated (Bundle savedInstanceState) {
+    public void onActivityCreated(Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
+
+        WifiNetworkConfig wifiNetworkConfig = ((WifiNetworkConfig.Retriever) getActivity())
+                .getWifiNetworkConfig();
+        if (!WifiNetworkConfig.isValidConfig(wifiNetworkConfig)) {
+            throw new IllegalArgumentException("Invalid Wi-Fi network for configuring");
+        }
+        setTitle(getString(R.string.wifi_dpp_share_wifi));
+        setDescription(getString(R.string.wifi_dpp_scan_qr_code_with_another_device,
+                wifiNetworkConfig.getSsid()));
+
+        setHasOptionsMenu(true);
+        ActionBar actionBar = getActivity().getActionBar();
+        if (actionBar != null) {
+            actionBar.setDisplayHomeAsUpEnabled(true);
+            actionBar.show();
+        }
+    }
+
+    @Override
+    public void onAttach(Context context) {
+        super.onAttach(context);
+
+        mListener = (OnQrCodeGeneratorFragmentAddButtonClickedListener) context;
+    }
+
+    @Override
+    public void onDetach() {
+        mListener = null;
+
+        super.onDetach();
+    }
+
+    @Override
+    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+        MenuItem item = menu.add(0, Menu.FIRST, 0, R.string.next_label);
+        item.setIcon(R.drawable.ic_menu_add);
+        item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
+
+        super.onCreateOptionsMenu(menu, inflater);
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem menuItem) {
+        switch (menuItem.getItemId()) {
+            case Menu.FIRST:
+                mListener.onQrCodeGeneratorFragmentAddButtonClicked();
+                return true;
+            default:
+                return super.onOptionsItemSelected(menuItem);
+        }
     }
 }
diff --git a/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java b/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java
index 70dade5..5689c56 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java
@@ -17,12 +17,15 @@
 package com.android.settings.wifi.dpp;
 
 import android.annotation.Nullable;
+import android.app.ActionBar;
 import android.app.Activity;
+import android.content.Context;
 import android.content.Intent;
 import android.graphics.Rect;
 import android.os.Bundle;
-import android.text.TextUtils;
 import android.util.Size;
+import android.view.Menu;
+import android.view.MenuInflater;
 import android.view.SurfaceHolder;
 import android.view.SurfaceView;
 import android.view.View;
@@ -38,32 +41,60 @@
     private SurfaceView mSurfaceView;
     private QrDecorateView mDecorateView;
 
+    /** true if the fragment working for configurator, false enrollee*/
+    private final boolean mConfiguratorMode;
+
+    /** The SSID of the Wi-Fi network which the user specify to enroll */
+    private String mSsid;
+
     @Override
     protected int getLayout() {
         return R.layout.wifi_dpp_qrcode_scanner_fragment;
     }
 
+    /**
+     * Configurator container activity of the fragment should create instance with this constructor.
+     */
+    public WifiDppQrCodeScannerFragment() {
+        super();
+
+        mConfiguratorMode = true;
+    }
+
+    /**
+     * Enrollee container activity of the fragment should create instance with this constructor and
+     * specify the SSID string of the WI-Fi network to be provisioned.
+     */
+    public WifiDppQrCodeScannerFragment(String ssid) {
+        super();
+
+        mConfiguratorMode = false;
+        mSsid = ssid;
+    }
+
     @Override
     public void onActivityCreated(Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
 
-        setTitle(getString(R.string.wifi_dpp_add_device_to_network));
+        if (mConfiguratorMode) {
+            setTitle(getString(R.string.wifi_dpp_add_device_to_network));
 
-        WifiNetworkConfig wifiNetworkConfig = ((WifiNetworkConfig.Retriever) getActivity())
+            WifiNetworkConfig wifiNetworkConfig = ((WifiNetworkConfig.Retriever) getActivity())
                 .getWifiNetworkConfig();
-        if (!WifiNetworkConfig.isValidConfig(wifiNetworkConfig)) {
-            throw new IllegalArgumentException("Invalid Wi-Fi network for configuring");
+            if (!WifiNetworkConfig.isValidConfig(wifiNetworkConfig)) {
+                throw new IllegalArgumentException("Invalid Wi-Fi network for configuring");
+            }
+            setDescription(getString(R.string.wifi_dpp_center_qr_code, wifiNetworkConfig.getSsid()));
+        } else {
+            setTitle(getString(R.string.wifi_dpp_scan_qr_code));
+            setDescription(getString(R.string.wifi_dpp_scan_qr_code_join_network, mSsid));
         }
-        setDescription(getString(R.string.wifi_dpp_center_qr_code, wifiNetworkConfig.getSsid()));
 
-        hideRightButton();
-
-        setLeftButtonText(getString(android.R.string.cancel));
-
-        setLeftButtonOnClickListener((view) -> {
-            getActivity().setResult(Activity.RESULT_CANCELED);
-            getActivity().finish();
-        });
+        ActionBar actionBar = getActivity().getActionBar();
+        if (actionBar != null) {
+            actionBar.setDisplayHomeAsUpEnabled(true);
+            actionBar.show();
+        }
     }
 
     @Override
@@ -79,6 +110,21 @@
     }
 
     @Override
+    public void onDestroyView() {
+        SurfaceHolder surfaceHolder = mSurfaceView.getHolder();
+        surfaceHolder.removeCallback(this);
+
+        super.onDestroyView();
+    }
+
+    @Override
+    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+        menu.removeItem(Menu.FIRST);
+
+        super.onCreateOptionsMenu(menu, inflater);
+    }
+
+    @Override
     public void surfaceCreated(final SurfaceHolder holder) {
         initCamera(holder);
     }
diff --git a/src/com/android/settings/wifi/dpp/WifiDppUtils.java b/src/com/android/settings/wifi/dpp/WifiDppUtils.java
index 70ef3a8..dc0ff84 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppUtils.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppUtils.java
@@ -16,12 +16,36 @@
 
 package com.android.settings.wifi.dpp;
 
+import android.content.Context;
 import android.content.Intent;
+import android.text.TextUtils;
+import android.util.FeatureFlagUtils;
 
 /**
  * Here are the items shared by both WifiDppConfiguratorActivity & WifiDppEnrolleeActivity
  */
 public class WifiDppUtils {
+    /**
+     * The fragment tag specified to FragmentManager for container activities to manage fragments.
+     */
+    public static final String TAG_FRAGMENT_QR_CODE_SCANNER = "qr_code_scanner_fragment";
+
+    /**
+     * @see #TAG_FRAGMENT_QR_CODE_SCANNER
+     */
+    public static final String TAG_FRAGMENT_QR_CODE_GENERATOR = "qr_code_generator_fragment";
+
+    /**
+     * @see #TAG_FRAGMENT_QR_CODE_SCANNER
+     */
+    public static final String TAG_FRAGMENT_CHOOSE_SAVED_WIFI_NETWORK =
+            "choose_saved_wifi_network_fragment";
+
+    /**
+     * @see #TAG_FRAGMENT_QR_CODE_SCANNER
+     */
+    public static final String TAG_FRAGMENT_ADD_DEVICE = "add_device_fragment";
+
     /** The data is from {@code com.android.settingslib.wifi.AccessPoint.securityToString} */
     public static final String EXTRA_WIFI_SECURITY = "security";
 
@@ -54,4 +78,46 @@
      * H         true       Optional. True if the network SSID is hidden.
      */
     public static final String EXTRA_QR_CODE = "qrCode";
+
+    /**
+     * Returns whether the user can share the network represented by this preference with QR code.
+     */
+    public static boolean isSharingNetworkEnabled(Context context) {
+        return FeatureFlagUtils.isEnabled(context,
+                com.android.settings.core.FeatureFlags.WIFI_SHARING);
+    }
+
+    /**
+     * Returns an intent to launch QR code scanner.
+     *
+     * @param ssid The data corresponding to {@code WifiConfiguration} SSID
+     * @return Intent for launching QR code scanner
+     */
+    public static Intent getConfiguratorQRCodeScannerIntent(String ssid) {
+        final Intent intent = new Intent(
+                WifiDppConfiguratorActivity.ACTION_CONFIGURATOR_QR_CODE_SCANNER);
+        if (!TextUtils.isEmpty(ssid)) {
+            intent.putExtra(EXTRA_WIFI_SSID, ssid);
+        }
+        return intent;
+    }
+
+    /**
+     * Returns an intent to launch QR code generator.
+     *
+     * @param ssid     The data corresponding to {@code WifiConfiguration} SSID
+     * @param Security The data is from {@code AccessPoint.securityToString}
+     * @return Intent for launching QR code generator
+     */
+    public static Intent getConfiguratorQRCodeGeneratorIntent(String ssid, String Security) {
+        final Intent intent = new Intent(
+                WifiDppConfiguratorActivity.ACTION_CONFIGURATOR_QR_CODE_GENERATOR);
+        if (!TextUtils.isEmpty(ssid)) {
+            intent.putExtra(EXTRA_WIFI_SSID, ssid);
+        }
+        if (!TextUtils.isEmpty(Security)) {
+            intent.putExtra(EXTRA_WIFI_SECURITY, Security);
+        }
+        return intent;
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/applications/defaultapps/RolesPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/defaultapps/RolesPreferenceControllerTest.java
new file mode 100644
index 0000000..0946f37
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/applications/defaultapps/RolesPreferenceControllerTest.java
@@ -0,0 +1,136 @@
+/*
+ * 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.applications.defaultapps;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.provider.Settings;
+
+import androidx.preference.Preference;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class RolesPreferenceControllerTest {
+
+    private static final String PREFERENCE_KEY = "roles";
+    private static final String DIFFERENT_PREFERENCE_KEY = "different";
+    private static final String PERMISSION_CONTROLLER_PACKAGE_NAME =
+            "com.android.permissioncontroller";
+
+    @Mock
+    private Context mContext;
+    @Mock
+    private PackageManager mPackageManager;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        when(mContext.getPackageManager()).thenReturn(mPackageManager);
+    }
+
+    @Test
+    public void getAvailabilityStatus_noPermissionController_shouldReturnUnsupportedOnDevice() {
+        when(mPackageManager.getPermissionControllerPackageName()).thenReturn(null);
+        RolesPreferenceController controller = new RolesPreferenceController(mContext,
+                PREFERENCE_KEY);
+
+        assertThat(controller.getAvailabilityStatus())
+                .isEqualTo(BasePreferenceController.UNSUPPORTED_ON_DEVICE);
+    }
+
+    @Test
+    public void getAvailabilityStatus_hasPermissionController_shouldReturnAvailableUnsearchable() {
+        when(mPackageManager.getPermissionControllerPackageName())
+                .thenReturn(PERMISSION_CONTROLLER_PACKAGE_NAME);
+        RolesPreferenceController controller = new RolesPreferenceController(mContext,
+                PREFERENCE_KEY);
+
+        assertThat(controller.getAvailabilityStatus())
+                .isEqualTo(BasePreferenceController.AVAILABLE_UNSEARCHABLE);
+    }
+
+    @Test
+    public void handlePreferenceTreeClick_differentKey_shouldReturnFalse() {
+        when(mPackageManager.getPermissionControllerPackageName())
+                .thenReturn(PERMISSION_CONTROLLER_PACKAGE_NAME);
+        RolesPreferenceController controller = new RolesPreferenceController(mContext,
+                PREFERENCE_KEY);
+        Preference preference = mock(Preference.class);
+        when(preference.getKey()).thenReturn(DIFFERENT_PREFERENCE_KEY);
+
+        assertThat(controller.handlePreferenceTreeClick(preference)).isFalse();
+    }
+
+    @Test
+    public void handlePreferenceTreeClick_sameKey_shouldReturnTrue() {
+        when(mPackageManager.getPermissionControllerPackageName())
+                .thenReturn(PERMISSION_CONTROLLER_PACKAGE_NAME);
+        RolesPreferenceController controller = new RolesPreferenceController(mContext,
+                PREFERENCE_KEY);
+        Preference preference = mock(Preference.class);
+        when(preference.getKey()).thenReturn(PREFERENCE_KEY);
+
+        assertThat(controller.handlePreferenceTreeClick(preference)).isTrue();
+    }
+
+    @Test
+    public void handlePreferenceTreeClick_noPermissionController_shouldNotStartActivity() {
+        when(mPackageManager.getPermissionControllerPackageName()).thenReturn(null);
+        RolesPreferenceController controller = new RolesPreferenceController(mContext,
+                PREFERENCE_KEY);
+        Preference preference = mock(Preference.class);
+        when(preference.getKey()).thenReturn(PREFERENCE_KEY);
+        controller.handlePreferenceTreeClick(preference);
+
+        verify(mContext, never()).startActivity(any(Intent.class));
+    }
+
+    @Test
+    public void handlePreferenceTreeClick_hasPermissionController_shouldStartActivityWithIntent() {
+        when(mPackageManager.getPermissionControllerPackageName())
+                .thenReturn(PERMISSION_CONTROLLER_PACKAGE_NAME);
+        RolesPreferenceController controller = new RolesPreferenceController(mContext,
+                PREFERENCE_KEY);
+        Preference preference = mock(Preference.class);
+        when(preference.getKey()).thenReturn(PREFERENCE_KEY);
+        controller.handlePreferenceTreeClick(preference);
+        ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class);
+
+        verify(mContext).startActivity(intent.capture());
+        assertThat(intent.getValue().getAction())
+                .isEqualTo(Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS);
+        assertThat(intent.getValue().getPackage()).isEqualTo(PERMISSION_CONTROLLER_PACKAGE_NAME);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/AutoBatterySeekBarPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/AutoBatterySeekBarPreferenceControllerTest.java
index 5a92ce7..5d2ac62 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/AutoBatterySeekBarPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/AutoBatterySeekBarPreferenceControllerTest.java
@@ -86,7 +86,7 @@
         mController.updateState(mPreference);
 
         assertThat(mPreference.isVisible()).isTrue();
-        assertThat(mPreference.getTitle()).isEqualTo("At 20%");
+        assertThat(mPreference.getTitle()).isEqualTo("20%");
         assertThat(mPreference.getProgress()).isEqualTo(TRIGGER_LEVEL / INTERVAL);
     }
 
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverSchedulePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverSchedulePreferenceControllerTest.java
new file mode 100644
index 0000000..c4d4c87
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverSchedulePreferenceControllerTest.java
@@ -0,0 +1,94 @@
+/*
+ * 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.batterysaver;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.os.PowerManager;
+import android.provider.Settings;
+import android.provider.Settings.Global;
+import androidx.preference.Preference;
+import com.android.settings.R;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.SettingsShadowResources;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(shadows = SettingsShadowResources.class)
+public class BatterySaverSchedulePreferenceControllerTest {
+
+    private static final int TRIGGER_LEVEL = 20;
+    private static final int DEFAULT_LEVEL = 15;
+
+    private BatterySaverSchedulePreferenceController mController;
+    private Context mContext;
+    private Preference mPreference;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        SettingsShadowResources.overrideResource(
+                com.android.internal.R.integer.config_lowBatteryWarningLevel, DEFAULT_LEVEL);
+        mContext = RuntimeEnvironment.application;
+        mController = new BatterySaverSchedulePreferenceController(mContext);
+        mPreference = new Preference(mContext);
+        mController.mBatterySaverSchedulePreference = mPreference;
+    }
+
+    @Test
+    public void testPreference_lowPowerLevelZero_percentageMode_summaryNoSchedule() {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Global.AUTOMATIC_POWER_SAVER_MODE, PowerManager.POWER_SAVER_MODE_PERCENTAGE);
+
+        mController.updateState(mPreference);
+
+        assertThat(mPreference.getSummary()).isEqualTo("No schedule");
+    }
+
+    @Test
+    public void testPreference_lowPowerLevelNonZero_percentageMode_summaryPercentage() {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, TRIGGER_LEVEL);
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Global.AUTOMATIC_POWER_SAVER_MODE, PowerManager.POWER_SAVER_MODE_PERCENTAGE);
+
+        mController.updateState(mPreference);
+
+        assertThat(mPreference.getSummary()).isEqualTo("Will turn on at 20%");
+    }
+
+    @Test
+    public void testPreference_percentageRoutine_summaryRoutine() {
+        // It doesn't matter what this is set to for routine mode
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, TRIGGER_LEVEL);
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Global.AUTOMATIC_POWER_SAVER_MODE, PowerManager.POWER_SAVER_MODE_DYNAMIC);
+
+        mController.updateState(mPreference);
+
+        assertThat(mPreference.getSummary()).isEqualTo("Based on your routine");
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/network/SubscriptionsChangeListenerTest.java b/tests/robotests/src/com/android/settings/network/SubscriptionsChangeListenerTest.java
new file mode 100644
index 0000000..88ea2ea
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/network/SubscriptionsChangeListenerTest.java
@@ -0,0 +1,129 @@
+/*
+ * 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.network;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.AdditionalMatchers.eq;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.provider.Settings;
+import android.telephony.SubscriptionManager;
+
+import com.android.settings.network.SubscriptionsChangeListener.SubscriptionsChangeListenerClient;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class SubscriptionsChangeListenerTest {
+
+    @Mock
+    private SubscriptionsChangeListenerClient mClient;
+    @Mock
+    private SubscriptionManager mSubscriptionManager;
+
+    private Context mContext;
+    private SubscriptionsChangeListener mListener;
+    private Uri mAirplaneModeUri;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = spy(RuntimeEnvironment.application);
+        when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager);
+
+        mAirplaneModeUri = Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON);
+    }
+
+    private void initListener(boolean alsoStart) {
+        mListener = new SubscriptionsChangeListener(mContext, mClient);
+        if (alsoStart) {
+            mListener.start();
+        }
+    }
+
+    @Test
+    public void whenStartNotCalled_noListeningWasSetup() {
+        final ContentResolver contentResolver = mock(ContentResolver.class);
+        when(mContext.getContentResolver()).thenReturn(contentResolver);
+        initListener(false);
+        verify(contentResolver, never()).registerContentObserver(any(Uri.class), anyBoolean(),
+                any(ContentObserver.class));
+        verify(mSubscriptionManager, never()).addOnSubscriptionsChangedListener(any());
+        verify(mContext, never()).registerReceiver(any(), any());
+    }
+
+    @Test
+    public void onSubscriptionsChangedEvent_subscriptionManagerFires_eventDeliveredToUs() {
+        initListener(true);
+        final ArgumentCaptor<SubscriptionManager.OnSubscriptionsChangedListener> captor =
+                ArgumentCaptor.forClass(SubscriptionManager.OnSubscriptionsChangedListener.class);
+        verify(mSubscriptionManager).addOnSubscriptionsChangedListener(captor.capture());
+        captor.getValue().onSubscriptionsChanged();
+        verify(mClient).onSubscriptionsChanged();
+    }
+
+    @Test
+    public void onSubscriptionsChangedEvent_radioTechnologyChangedBroadcast_eventDeliveredToUs() {
+        initListener(true);
+        final ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
+                ArgumentCaptor.forClass(BroadcastReceiver.class);
+        verify(mContext).registerReceiver(broadcastReceiverCaptor.capture(), any());
+        broadcastReceiverCaptor.getValue().onReceive(mContext, null);
+        verify(mClient).onSubscriptionsChanged();
+    }
+
+    @Test
+    public void onAirplaneModeChangedEvent_becameTrue_eventFires() {
+        initListener(true);
+        Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1);
+        mListener.onChange(false, mAirplaneModeUri);
+        verify(mClient).onAirplaneModeChanged(true);
+        assertThat(mListener.isAirplaneModeOn()).isTrue();
+    }
+
+    @Test
+    public void onAirplaneModeChangedEvent_becameFalse_eventFires() {
+        initListener(true);
+        Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0);
+        mListener.onChange(false, mAirplaneModeUri);
+        verify(mClient).onAirplaneModeChanged(false);
+        assertThat(mListener.isAirplaneModeOn()).isFalse();
+    }
+
+}
diff --git a/tests/robotests/src/com/android/settings/widget/RadioButtonPreferenceTest.java b/tests/robotests/src/com/android/settings/widget/RadioButtonPreferenceTest.java
index 5d914a2..8a6aabf 100644
--- a/tests/robotests/src/com/android/settings/widget/RadioButtonPreferenceTest.java
+++ b/tests/robotests/src/com/android/settings/widget/RadioButtonPreferenceTest.java
@@ -24,6 +24,7 @@
 import static org.mockito.Mockito.when;
 
 import android.app.Application;
+import android.view.LayoutInflater;
 import android.view.View;
 
 import androidx.preference.PreferenceViewHolder;
@@ -93,4 +94,13 @@
         mPreference.onBindViewHolder(preferenceViewHolder);
         assertEquals(View.GONE, summaryContainer.getVisibility());
     }
+
+    @Test
+    public void hideAppendix_shouldBeGone() {
+        mPreference.setAppendixVisibility(View.GONE);
+        View view = LayoutInflater.from(mContext).inflate(R.layout.preference_radio, null);
+        PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(view);
+        mPreference.onBindViewHolder(holder);
+        assertThat(holder.findViewById(R.id.appendix).getVisibility()).isEqualTo(View.GONE);
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/wifi/ButtonPreferenceTest.java b/tests/robotests/src/com/android/settings/wifi/ButtonPreferenceTest.java
new file mode 100644
index 0000000..3dc109f
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/wifi/ButtonPreferenceTest.java
@@ -0,0 +1,82 @@
+/*
+ * 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.wifi;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.view.View;
+import android.widget.ImageButton;
+
+import com.android.settings.R;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import androidx.preference.PreferenceViewHolder;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class ButtonPreferenceTest {
+
+    private Context mContext;
+    private View mRootView;
+    private ButtonPreference mPref;
+    private PreferenceViewHolder mHolder;
+    private boolean mClicked;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mContext = RuntimeEnvironment.application;
+        mPref = new ButtonPreference(mContext);
+        mRootView = View.inflate(mContext, R.layout.wifi_button_preference_widget, /* parent */
+                null);
+        mHolder = PreferenceViewHolder.createInstanceForTests(mRootView);
+    }
+
+    @Test
+    public void initButton_noIcon_shouldInvisible() {
+        mPref.initButton(mHolder);
+        assertThat(mRootView.findViewById(R.id.button_icon).getVisibility()).isEqualTo(View.GONE);
+    }
+
+    @Test
+    public void initButton_withIcon_shouldVisible() {
+        mPref.setButtonIcon(R.drawable.ic_qrcode_24dp);
+        mPref.initButton(mHolder);
+        assertThat(mRootView.findViewById(R.id.button_icon).getVisibility()).isEqualTo(
+                View.VISIBLE);
+    }
+
+    @Test
+    public void initButton_whenClick_shouldCallback() {
+        mClicked = false;
+        mPref.setButtonIcon(R.drawable.ic_qrcode_24dp);
+        mPref.setButtonOnClickListener((View v) -> {
+            mClicked = true;
+        });
+        mPref.initButton(mHolder);
+        ImageButton button = (ImageButton) mRootView.findViewById(R.id.button_icon);
+        button.performClick();
+        assertThat(mClicked).isTrue();
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogFragmentTest.java b/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogFragmentTest.java
index 2e806dd..8cf02b8 100644
--- a/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogFragmentTest.java
@@ -17,6 +17,7 @@
 package com.android.settings.wifi;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
@@ -32,213 +33,220 @@
 import android.net.wifi.WifiManager.NetworkRequestUserSelectionCallback;
 import android.os.Bundle;
 import android.widget.Button;
+
 import androidx.appcompat.app.AlertDialog;
 import androidx.fragment.app.FragmentActivity;
+
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.testutils.shadow.SettingsShadowResourcesImpl;
 import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
+import com.android.settings.wifi.NetworkRequestErrorDialogFragment.ERROR_DIALOG_TYPE;
 import com.android.settingslib.wifi.AccessPoint;
+
 import java.util.ArrayList;
 import java.util.List;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.Robolectric;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
+
 import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
+
 import org.robolectric.shadows.ShadowLooper;
 
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(shadows = {SettingsShadowResourcesImpl.class, ShadowAlertDialogCompat.class})
 public class NetworkRequestDialogFragmentTest {
 
-  final String KEY_SSID = "key_ssid";
+    final String KEY_SSID = "key_ssid";
 
-  private FragmentActivity mActivity;
-  private NetworkRequestDialogFragment networkRequestDialogFragment;
-  private Context mContext;
+    private FragmentActivity mActivity;
+    private NetworkRequestDialogFragment networkRequestDialogFragment;
+    private Context mContext;
 
-  @Before
-  public void setUp() {
-    mActivity = Robolectric.setupActivity(FragmentActivity.class);
-    networkRequestDialogFragment = spy(NetworkRequestDialogFragment.newInstance());
-    mContext = spy(RuntimeEnvironment.application);
-  }
-
-  @Test
-  public void display_shouldShowTheDialog() {
-    networkRequestDialogFragment.show(mActivity.getSupportFragmentManager(), null);
-    AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
-    assertThat(alertDialog).isNotNull();
-    assertThat(alertDialog.isShowing()).isTrue();
-  }
-
-  @Test
-  public void clickPositiveButton_shouldCloseTheDialog() {
-    networkRequestDialogFragment.show(mActivity.getSupportFragmentManager(), null);
-    AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
-    assertThat(alertDialog.isShowing()).isTrue();
-
-    Button positiveButton = alertDialog.getButton(DialogInterface.BUTTON_POSITIVE);
-    assertThat(positiveButton).isNotNull();
-
-    positiveButton.performClick();
-    assertThat(alertDialog.isShowing()).isFalse();
-  }
-
-  @Test
-  public void onResumeAndWaitTimeout_shouldCallTimeoutDialog() {
-    FakeNetworkRequestDialogFragment fakeFragment = new FakeNetworkRequestDialogFragment();
-    FakeNetworkRequestDialogFragment spyFakeFragment = spy(fakeFragment);
-    spyFakeFragment.show(mActivity.getSupportFragmentManager(), null);
-
-    assertThat(fakeFragment.bCalledStopAndPop).isFalse();
-
-    ShadowLooper.getShadowMainLooper().runToEndOfTasks();
-
-    assertThat(fakeFragment.bCalledStopAndPop).isTrue();
-  }
-
-  class FakeNetworkRequestDialogFragment extends NetworkRequestDialogFragment {
-    boolean bCalledStopAndPop = false;
-
-    @Override
-    public void stopScanningAndPopTimeoutDialog() {
-      bCalledStopAndPop = true;
+    @Before
+    public void setUp() {
+        mActivity = Robolectric.setupActivity(FragmentActivity.class);
+        networkRequestDialogFragment = spy(NetworkRequestDialogFragment.newInstance());
+        mContext = spy(RuntimeEnvironment.application);
     }
-  }
 
-  @Test
-  public void onResume_shouldRegisterCallback() {
-    when(networkRequestDialogFragment.getContext()).thenReturn(mContext);
-    Context applicationContext = spy(RuntimeEnvironment.application.getApplicationContext());
-    when(mContext.getApplicationContext()).thenReturn(applicationContext);
-    WifiManager wifiManager = mock(WifiManager.class);
-    when(applicationContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(wifiManager);
+    @Test
+    public void display_shouldShowTheDialog() {
+        networkRequestDialogFragment.show(mActivity.getSupportFragmentManager(), null);
+        AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
+        assertThat(alertDialog).isNotNull();
+        assertThat(alertDialog.isShowing()).isTrue();
+    }
 
-    networkRequestDialogFragment.onResume();
+    @Test
+    public void clickPositiveButton_shouldCloseTheDialog() {
+        networkRequestDialogFragment.show(mActivity.getSupportFragmentManager(), null);
+        AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
+        assertThat(alertDialog.isShowing()).isTrue();
 
-    verify(wifiManager).registerNetworkRequestMatchCallback(any(), any());
-  }
+        Button positiveButton = alertDialog.getButton(DialogInterface.BUTTON_POSITIVE);
+        assertThat(positiveButton).isNotNull();
 
-  @Test
-  public void onPause_shouldUnRegisterCallback() {
-    when(networkRequestDialogFragment.getContext()).thenReturn(mContext);
-    Context applicationContext = spy(RuntimeEnvironment.application.getApplicationContext());
-    when(mContext.getApplicationContext()).thenReturn(applicationContext);
-    WifiManager wifiManager = mock(WifiManager.class);
-    when(applicationContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(wifiManager);
+        positiveButton.performClick();
+        assertThat(alertDialog.isShowing()).isFalse();
+    }
 
-    networkRequestDialogFragment.onPause();
+    @Test
+    public void onResumeAndWaitTimeout_shouldCallTimeoutDialog() {
+        FakeNetworkRequestDialogFragment fakeFragment = new FakeNetworkRequestDialogFragment();
+        FakeNetworkRequestDialogFragment spyFakeFragment = spy(fakeFragment);
+        spyFakeFragment.show(mActivity.getSupportFragmentManager(), null);
 
-    verify(wifiManager).unregisterNetworkRequestMatchCallback(networkRequestDialogFragment);
-  }
+        assertThat(fakeFragment.bCalledStopAndPop).isFalse();
 
-  @Test
-  public void updateAccessPointList_onUserSelectionConnectSuccess_updateCorrectly() {
-    List<AccessPoint> accessPointList = spy(new ArrayList<>());
-    Bundle bundle = new Bundle();
-    bundle.putString(KEY_SSID, "Test AP 1");
-    accessPointList.add(new AccessPoint(mContext, bundle));
-    bundle.putString(KEY_SSID, "Test AP 2");
-    accessPointList.add(new AccessPoint(mContext, bundle));
-    bundle.putString(KEY_SSID, "Test AP 3");
-    accessPointList.add(new AccessPoint(mContext, bundle));
-    bundle.putString(KEY_SSID, "Test AP 4");
-    accessPointList.add(new AccessPoint(mContext, bundle));
+        ShadowLooper.getShadowMainLooper().runToEndOfTasks();
 
-    when(networkRequestDialogFragment.getAccessPointList()).thenReturn(accessPointList);
-    networkRequestDialogFragment.show(mActivity.getSupportFragmentManager(), null);
+        assertThat(fakeFragment.bCalledStopAndPop).isTrue();
+    }
 
-    // Test if config would update list.
-    WifiConfiguration config = new WifiConfiguration();
-    config.SSID = "Test AP 3";
-    networkRequestDialogFragment.onUserSelectionConnectSuccess(config);
+    class FakeNetworkRequestDialogFragment extends NetworkRequestDialogFragment {
+        boolean bCalledStopAndPop = false;
 
-    AccessPoint verifyAccessPoint = new AccessPoint(mContext, config);
-    verify(accessPointList, times(1)).set(2, verifyAccessPoint);
-  }
+        @Override
+        public void stopScanningAndPopErrorDialog(ERROR_DIALOG_TYPE type) {
+            bCalledStopAndPop = true;
+        }
+    }
 
-  @Test
-  public void updateAccessPointList_onUserSelectionConnectFailure_updateCorrectly() {
-    List<AccessPoint> accessPointList = spy(new ArrayList<>());
-    Bundle bundle = new Bundle();
-    bundle.putString(KEY_SSID, "Test AP 1");
-    accessPointList.add(new AccessPoint(mContext, bundle));
-    bundle.putString(KEY_SSID, "Test AP 2");
-    accessPointList.add(new AccessPoint(mContext, bundle));
-    bundle.putString(KEY_SSID, "Test AP 3");
-    accessPointList.add(new AccessPoint(mContext, bundle));
-    bundle.putString(KEY_SSID, "Test AP 4");
-    accessPointList.add(new AccessPoint(mContext, bundle));
+    @Test
+    public void onResume_shouldRegisterCallback() {
+        when(networkRequestDialogFragment.getContext()).thenReturn(mContext);
+        Context applicationContext = spy(RuntimeEnvironment.application.getApplicationContext());
+        when(mContext.getApplicationContext()).thenReturn(applicationContext);
+        WifiManager wifiManager = mock(WifiManager.class);
+        when(applicationContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(wifiManager);
 
-    when(networkRequestDialogFragment.getAccessPointList()).thenReturn(accessPointList);
-    networkRequestDialogFragment.show(mActivity.getSupportFragmentManager(), null);
+        networkRequestDialogFragment.onResume();
 
-    // Test if config would update list.
-    WifiConfiguration config = new WifiConfiguration();
-    config.SSID = "Test AP 3";
-    networkRequestDialogFragment.onUserSelectionConnectFailure(config);
+        verify(wifiManager).registerNetworkRequestMatchCallback(any(), any());
+    }
 
-    AccessPoint verifyAccessPoint = new AccessPoint(mContext, config);
-    verify(accessPointList, times(1)).set(2, verifyAccessPoint);
-  }
+    @Test
+    public void onPause_shouldUnRegisterCallback() {
+        when(networkRequestDialogFragment.getContext()).thenReturn(mContext);
+        Context applicationContext = spy(RuntimeEnvironment.application.getApplicationContext());
+        when(mContext.getApplicationContext()).thenReturn(applicationContext);
+        WifiManager wifiManager = mock(WifiManager.class);
+        when(applicationContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(wifiManager);
 
-  @Test
-  public void onUserSelectionCallbackRegistration_shouldCallSelect() {
-    List<AccessPoint> accessPointList = spy(new ArrayList<>());
-    Bundle bundle = new Bundle();
-    bundle.putString(KEY_SSID, "Test AP 1");
-    accessPointList.add(new AccessPoint(mContext, bundle));
-    bundle.putString(KEY_SSID, "Test AP 2");
-    accessPointList.add(new AccessPoint(mContext, bundle));
-    bundle.putString(KEY_SSID, "Test AP 3");
-    AccessPoint clickedAccessPoint = new AccessPoint(mContext, bundle);
-    accessPointList.add(clickedAccessPoint);
-    bundle.putString(KEY_SSID, "Test AP 4");
-    accessPointList.add(new AccessPoint(mContext, bundle));
-    when(networkRequestDialogFragment.getAccessPointList()).thenReturn(accessPointList);
+        networkRequestDialogFragment.onPause();
 
-    NetworkRequestUserSelectionCallback selectionCallback = mock(
-        NetworkRequestUserSelectionCallback.class);
-    AlertDialog dialog = mock(AlertDialog.class);
-    networkRequestDialogFragment.onUserSelectionCallbackRegistration(selectionCallback);
+        verify(wifiManager).unregisterNetworkRequestMatchCallback(networkRequestDialogFragment);
+    }
 
-    networkRequestDialogFragment.onClick(dialog, 2);
+    @Test
+    public void updateAccessPointList_onUserSelectionConnectSuccess_updateCorrectly() {
+        List<AccessPoint> accessPointList = spy(new ArrayList<>());
+        Bundle bundle = new Bundle();
+        bundle.putString(KEY_SSID, "Test AP 1");
+        accessPointList.add(new AccessPoint(mContext, bundle));
+        bundle.putString(KEY_SSID, "Test AP 2");
+        accessPointList.add(new AccessPoint(mContext, bundle));
+        bundle.putString(KEY_SSID, "Test AP 3");
+        accessPointList.add(new AccessPoint(mContext, bundle));
+        bundle.putString(KEY_SSID, "Test AP 4");
+        accessPointList.add(new AccessPoint(mContext, bundle));
 
-    verify(selectionCallback, times(1)).select(clickedAccessPoint.getConfig());
-  }
+        when(networkRequestDialogFragment.getAccessPointList()).thenReturn(accessPointList);
+        networkRequestDialogFragment.show(mActivity.getSupportFragmentManager(), null);
 
-  @Test
-  public void onMatch_shouldUpdatedList() {
-    // Prepares WifiManager.
-    when(networkRequestDialogFragment.getContext()).thenReturn(mContext);
-    Context applicationContext = spy(RuntimeEnvironment.application.getApplicationContext());
-    when(mContext.getApplicationContext()).thenReturn(applicationContext);
-    WifiManager wifiManager = mock(WifiManager.class);
-    when(applicationContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(wifiManager);
+        // Test if config would update list.
+        WifiConfiguration config = new WifiConfiguration();
+        config.SSID = "Test AP 3";
+        networkRequestDialogFragment.onUserSelectionConnectSuccess(config);
 
-    List<WifiConfiguration> wifiConfigurationList = new ArrayList<>();
-    WifiConfiguration config = new WifiConfiguration();
-    final String SSID_AP1 = "Test AP 1";
-    config.SSID = SSID_AP1;
-    wifiConfigurationList.add(config);
-    config = new WifiConfiguration();
-    final String SSID_AP2 = "Test AP 2";
-    config.SSID = SSID_AP2;
-    wifiConfigurationList.add(config);
+        AccessPoint verifyAccessPoint = new AccessPoint(mContext, config);
+        verify(accessPointList, times(1)).set(2, verifyAccessPoint);
+    }
 
-    // Prepares callback converted data.
-    List<ScanResult> scanResults = new ArrayList<>();
-    when(wifiManager.getAllMatchingWifiConfigs(scanResults)).thenReturn(wifiConfigurationList);
+    @Test
+    public void updateAccessPointList_onUserSelectionConnectFailure_updateCorrectly() {
+        List<AccessPoint> accessPointList = spy(new ArrayList<>());
+        Bundle bundle = new Bundle();
+        bundle.putString(KEY_SSID, "Test AP 1");
+        accessPointList.add(new AccessPoint(mContext, bundle));
+        bundle.putString(KEY_SSID, "Test AP 2");
+        accessPointList.add(new AccessPoint(mContext, bundle));
+        bundle.putString(KEY_SSID, "Test AP 3");
+        accessPointList.add(new AccessPoint(mContext, bundle));
+        bundle.putString(KEY_SSID, "Test AP 4");
+        accessPointList.add(new AccessPoint(mContext, bundle));
 
-    networkRequestDialogFragment.onMatch(scanResults);
+        when(networkRequestDialogFragment.getAccessPointList()).thenReturn(accessPointList);
+        networkRequestDialogFragment.show(mActivity.getSupportFragmentManager(), null);
 
-    List<AccessPoint> accessPointList = networkRequestDialogFragment.getAccessPointList();
-    assertThat(accessPointList).isNotEmpty();
-    assertThat(accessPointList.size()).isEqualTo(2);
-    assertThat(accessPointList.get(0).getSsid()).isEqualTo(SSID_AP1);
-    assertThat(accessPointList.get(1).getSsid()).isEqualTo(SSID_AP2);
-  }
+        // Test if config would update list.
+        WifiConfiguration config = new WifiConfiguration();
+        config.SSID = "Test AP 3";
+        networkRequestDialogFragment.onUserSelectionConnectFailure(config);
+
+        AccessPoint verifyAccessPoint = new AccessPoint(mContext, config);
+        verify(accessPointList, times(1)).set(2, verifyAccessPoint);
+    }
+
+    @Test
+    public void onUserSelectionCallbackRegistration_shouldCallSelect() {
+        List<AccessPoint> accessPointList = spy(new ArrayList<>());
+        Bundle bundle = new Bundle();
+        bundle.putString(KEY_SSID, "Test AP 1");
+        accessPointList.add(new AccessPoint(mContext, bundle));
+        bundle.putString(KEY_SSID, "Test AP 2");
+        accessPointList.add(new AccessPoint(mContext, bundle));
+        bundle.putString(KEY_SSID, "Test AP 3");
+        AccessPoint clickedAccessPoint = new AccessPoint(mContext, bundle);
+        accessPointList.add(clickedAccessPoint);
+        bundle.putString(KEY_SSID, "Test AP 4");
+        accessPointList.add(new AccessPoint(mContext, bundle));
+        when(networkRequestDialogFragment.getAccessPointList()).thenReturn(accessPointList);
+
+        NetworkRequestUserSelectionCallback selectionCallback = mock(
+                NetworkRequestUserSelectionCallback.class);
+        AlertDialog dialog = mock(AlertDialog.class);
+        networkRequestDialogFragment.onUserSelectionCallbackRegistration(selectionCallback);
+
+        networkRequestDialogFragment.onClick(dialog, 2);
+
+        verify(selectionCallback, times(1)).select(clickedAccessPoint.getConfig());
+    }
+
+    @Test
+    public void onMatch_shouldUpdatedList() {
+        // Prepares WifiManager.
+        when(networkRequestDialogFragment.getContext()).thenReturn(mContext);
+        Context applicationContext = spy(RuntimeEnvironment.application.getApplicationContext());
+        when(mContext.getApplicationContext()).thenReturn(applicationContext);
+        WifiManager wifiManager = mock(WifiManager.class);
+        when(applicationContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(wifiManager);
+
+        List<WifiConfiguration> wifiConfigurationList = new ArrayList<>();
+        WifiConfiguration config = new WifiConfiguration();
+        final String SSID_AP1 = "Test AP 1";
+        config.SSID = SSID_AP1;
+        wifiConfigurationList.add(config);
+        config = new WifiConfiguration();
+        final String SSID_AP2 = "Test AP 2";
+        config.SSID = SSID_AP2;
+        wifiConfigurationList.add(config);
+
+        // Prepares callback converted data.
+        List<ScanResult> scanResults = new ArrayList<>();
+        when(wifiManager.getAllMatchingWifiConfigs(scanResults)).thenReturn(wifiConfigurationList);
+
+        networkRequestDialogFragment.onMatch(scanResults);
+
+        List<AccessPoint> accessPointList = networkRequestDialogFragment.getAccessPointList();
+        assertThat(accessPointList).isNotEmpty();
+        assertThat(accessPointList.size()).isEqualTo(2);
+        assertThat(accessPointList.get(0).getSsid()).isEqualTo(SSID_AP1);
+        assertThat(accessPointList.get(1).getSsid()).isEqualTo(SSID_AP2);
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/wifi/NetworkRequestErrorDialogFragmentTest.java b/tests/robotests/src/com/android/settings/wifi/NetworkRequestErrorDialogFragmentTest.java
new file mode 100644
index 0000000..c6659a5
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/wifi/NetworkRequestErrorDialogFragmentTest.java
@@ -0,0 +1,117 @@
+/*
+ * 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.wifi;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.internal.verification.VerificationModeFactory.times;
+
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.widget.Button;
+
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.FragmentActivity;
+
+import com.android.settings.R;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.SettingsShadowResourcesImpl;
+import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
+import com.android.settings.wifi.NetworkRequestErrorDialogFragment.ERROR_DIALOG_TYPE;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.Robolectric;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(shadows = {SettingsShadowResourcesImpl.class, ShadowAlertDialogCompat.class})
+public class NetworkRequestErrorDialogFragmentTest {
+
+    private FragmentActivity mActivity;
+    private NetworkRequestErrorDialogFragment mFragment;
+
+    @Before
+    public void setUp() {
+        mActivity = Robolectric.setupActivity(FragmentActivity.class);
+        mFragment = spy(NetworkRequestErrorDialogFragment.newInstance());
+        mFragment.show(mActivity.getSupportFragmentManager(), null);
+    }
+
+    @Test
+    public void display_shouldShowTimeoutDialog() {
+        AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
+
+        assertThat(alertDialog).isNotNull();
+        assertThat(alertDialog.isShowing()).isTrue();
+
+        ShadowAlertDialogCompat shadowAlertDialog = ShadowAlertDialogCompat.shadowOf(alertDialog);
+        assertThat(RuntimeEnvironment.application
+                .getString(R.string.network_connection_timeout_dialog_message))
+                .isEqualTo(shadowAlertDialog.getMessage());
+    }
+
+    @Test
+    public void display_shouldShowAbortDialog() {
+        mFragment = spy(NetworkRequestErrorDialogFragment.newInstance());
+        Bundle bundle = new Bundle();
+        bundle.putSerializable(NetworkRequestErrorDialogFragment.DIALOG_TYPE,
+                ERROR_DIALOG_TYPE.ABORT);
+        mFragment.setArguments(bundle);
+        mFragment.show(mActivity.getSupportFragmentManager(), null);
+
+        AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
+
+        assertThat(alertDialog).isNotNull();
+        assertThat(alertDialog.isShowing()).isTrue();
+
+        ShadowAlertDialogCompat shadowAlertDialog = ShadowAlertDialogCompat.shadowOf(alertDialog);
+        assertThat(RuntimeEnvironment.application
+                .getString(R.string.network_connection_errorstate_dialog_message))
+                .isEqualTo(shadowAlertDialog.getMessage());
+    }
+
+    @Test
+    public void clickPositiveButton_shouldCallStartScanningDialog() {
+        AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
+        assertThat(alertDialog.isShowing()).isTrue();
+
+        Button positiveButton = alertDialog.getButton(DialogInterface.BUTTON_POSITIVE);
+        assertThat(positiveButton).isNotNull();
+
+        positiveButton.performClick();
+        verify(mFragment, times(1)).startScanningDialog();
+    }
+
+    @Test
+    public void clickNegativeButton_shouldCloseTheDialog() {
+        AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
+        assertThat(alertDialog.isShowing()).isTrue();
+
+        Button negativeButton = alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE);
+        assertThat(negativeButton).isNotNull();
+
+        negativeButton.performClick();
+        assertThat(alertDialog.isShowing()).isFalse();
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/wifi/NetworkRequestTimeoutDialogFragmentTest.java b/tests/robotests/src/com/android/settings/wifi/NetworkRequestTimeoutDialogFragmentTest.java
deleted file mode 100644
index ed28e60..0000000
--- a/tests/robotests/src/com/android/settings/wifi/NetworkRequestTimeoutDialogFragmentTest.java
+++ /dev/null
@@ -1,90 +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 com.android.settings.wifi;
-
-import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.internal.verification.VerificationModeFactory.times;
-
-import android.content.DialogInterface;
-import android.widget.Button;
-import androidx.appcompat.app.AlertDialog;
-import androidx.fragment.app.FragmentActivity;
-import com.android.settings.R;
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
-import com.android.settings.testutils.shadow.SettingsShadowResourcesImpl;
-import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.Robolectric;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
-
-@RunWith(SettingsRobolectricTestRunner.class)
-@Config(shadows = {SettingsShadowResourcesImpl.class, ShadowAlertDialogCompat.class})
-public class NetworkRequestTimeoutDialogFragmentTest {
-
-  private FragmentActivity mActivity;
-  private NetworkRequestTimeoutDialogFragment mFragment;
-
-  @Before
-  public void setUp() {
-    mActivity = Robolectric.setupActivity(FragmentActivity.class);
-    mFragment = spy(NetworkRequestTimeoutDialogFragment.newInstance());
-    mFragment.show(mActivity.getSupportFragmentManager(), null);
-  }
-
-  @Test
-  public void display_shouldShowTheDialog() {
-    AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
-
-    assertThat(alertDialog).isNotNull();
-    assertThat(alertDialog.isShowing()).isTrue();
-
-    ShadowAlertDialogCompat shadowAlertDialog = ShadowAlertDialogCompat.shadowOf(alertDialog);
-    assertThat(RuntimeEnvironment.application
-        .getString(R.string.network_connection_timeout_dialog_message))
-        .isEqualTo(shadowAlertDialog.getMessage());
-  }
-
-  @Test
-  public void clickPositiveButton_shouldCallStartScanningDialog() {
-    AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
-    assertThat(alertDialog.isShowing()).isTrue();
-
-    Button positiveButton = alertDialog.getButton(DialogInterface.BUTTON_POSITIVE);
-    assertThat(positiveButton).isNotNull();
-
-    positiveButton.performClick();
-    verify(mFragment, times(1)).startScanningDialog();
-  }
-
-  @Test
-  public void clickNegativeButton_shouldCloseTheDialog() {
-    AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
-    assertThat(alertDialog.isShowing()).isTrue();
-
-    Button negativeButton = alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE);
-    assertThat(negativeButton).isNotNull();
-
-    negativeButton.performClick();
-    assertThat(alertDialog.isShowing()).isFalse();
-  }
-}
diff --git a/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
index 39215c1..eab9e51 100644
--- a/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
@@ -865,6 +865,12 @@
         when(pref.setButton2Visible(anyBoolean())).thenReturn(pref);
         when(pref.setButton2OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
 
+        when(pref.setButton3Text(anyInt())).thenReturn(pref);
+        when(pref.setButton3Icon(anyInt())).thenReturn(pref);
+        when(pref.setButton3Enabled(anyBoolean())).thenReturn(pref);
+        when(pref.setButton3Visible(anyBoolean())).thenReturn(pref);
+        when(pref.setButton3OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
+
         return pref;
     }
 }
diff --git a/tests/unit/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivityTest.java b/tests/unit/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivityTest.java
index 70e9587..2f95fa5 100644
--- a/tests/unit/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivityTest.java
+++ b/tests/unit/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivityTest.java
@@ -73,4 +73,12 @@
 
         assertThat(activity instanceof WifiNetworkConfig.Retriever).isEqualTo(true);
     }
+
+    @Test
+    public void testActivity_shouldImplementsQrCodeGeneratorFragmentCallback() {
+        WifiDppConfiguratorActivity activity = mActivityRule.getActivity();
+
+        assertThat(activity instanceof WifiDppQrCodeGeneratorFragment
+                .OnQrCodeGeneratorFragmentAddButtonClickedListener).isEqualTo(true);
+    }
 }
diff --git a/tests/unit/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragmentTest.java b/tests/unit/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragmentTest.java
new file mode 100644
index 0000000..d3f667f
--- /dev/null
+++ b/tests/unit/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragmentTest.java
@@ -0,0 +1,54 @@
+/*
+ * 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.wifi.dpp;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.settings.R;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class WifiDppQrCodeGeneratorFragmentTest {
+    @Rule
+    public final ActivityTestRule<WifiDppConfiguratorActivity> mActivityRule =
+            new ActivityTestRule<>(WifiDppConfiguratorActivity.class, true);
+
+    @Before
+    public void setUp() {
+        Intent intent =
+                new Intent(WifiDppConfiguratorActivity.ACTION_CONFIGURATOR_QR_CODE_GENERATOR);
+        intent.putExtra(WifiDppUtils.EXTRA_WIFI_SECURITY, "WEP");
+        intent.putExtra(WifiDppUtils.EXTRA_WIFI_SSID, "GoogleGuest");
+        mActivityRule.launchActivity(intent);
+    }
+
+    @Test
+    public void rotateScreen_shouldNotCrash() {
+        mActivityRule.getActivity().setRequestedOrientation(
+                ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
+        mActivityRule.getActivity().setRequestedOrientation(
+                ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+    }
+}
diff --git a/tests/unit/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragmentTest.java b/tests/unit/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragmentTest.java
index 98742ed..70cfc2d 100644
--- a/tests/unit/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragmentTest.java
+++ b/tests/unit/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragmentTest.java
@@ -16,12 +16,6 @@
 
 package com.android.settings.wifi.dpp;
 
-import static android.support.test.espresso.action.ViewActions.click;
-import static android.support.test.espresso.matcher.ViewMatchers.withText;
-import static android.support.test.espresso.Espresso.onView;
-
-import static com.google.common.truth.Truth.assertThat;
-
 import android.app.Activity;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;