Merge "Remove method that used to get rainbow bt icon"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 9f6cdb5..651ef48 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -620,8 +620,7 @@
 
         <activity
             android:name="Settings$ManageAssistActivity"
-            android:label="@string/assist_and_voice_input_title"
-            android:parentActivityName="Settings">
+            android:label="@string/assist_and_voice_input_title">
             <intent-filter android:priority="1">
                 <action android:name="android.settings.VOICE_INPUT_SETTINGS" />
                 <category android:name="android.intent.category.DEFAULT" />
@@ -795,7 +794,8 @@
 
         <activity android:name="Settings$WallpaperSettingsActivity"
                   android:label="@string/wallpaper_settings_fragment_title"
-                  android:icon="@drawable/ic_wallpaper">
+                  android:icon="@drawable/ic_wallpaper"
+                  android:exported="true">
             <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
                        android:value="com.android.settings.wallpaper.WallpaperTypeSettings" />
         </activity>
@@ -2455,6 +2455,18 @@
         </activity>
 
         <activity
+            android:name="Settings$AppBubbleNotificationSettingsActivity"
+            android:label="@string/bubbles_app_toggle_title"
+            android:parentActivityName="Settings$NotificationAppListActivity">
+            <intent-filter android:priority="1">
+                <action android:name="android.settings.APP_NOTIFICATION_BUBBLE_SETTINGS" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                       android:value="com.android.settings.notification.AppBubbleNotificationSettings" />
+        </activity>
+
+        <activity
             android:name="Settings$SoundSettingsActivity"
             android:label="@string/sound_settings"
             android:icon="@drawable/ic_homepage_sound"
@@ -2566,7 +2578,7 @@
 
         <receiver android:name=".sim.SimSelectNotification">
             <intent-filter>
-                <action android:name="android.intent.action.PRIMARY_SUBSCRIPTION_LIST_CHANGED"/>
+                <action android:name="android.telephony.action.PRIMARY_SUBSCRIPTION_LIST_CHANGED"/>
             </intent-filter>
         </receiver>
 
diff --git a/res/layout-land/wifi_dpp_qrcode_scanner_fragment.xml b/res/layout-land/wifi_dpp_qrcode_scanner_fragment.xml
index c408a97..887d0fb 100644
--- a/res/layout-land/wifi_dpp_qrcode_scanner_fragment.xml
+++ b/res/layout-land/wifi_dpp_qrcode_scanner_fragment.xml
@@ -43,7 +43,7 @@
                 android:layout_marginBottom="8dp"
                 style="?android:attr/progressBarStyleHorizontal"/>
 
-            <com.android.settings.wifi.qrcode.QrPreviewLayout
+            <FrameLayout
                 android:layout_width="@dimen/qrcode_preview_size"
                 android:layout_height="@dimen/qrcode_preview_size">
                 <TextureView
@@ -54,7 +54,7 @@
                     android:id="@+id/decorate_view"
                     android:layout_width="wrap_content"
                     android:layout_height="match_parent"/>
-            </com.android.settings.wifi.qrcode.QrPreviewLayout>
+            </FrameLayout>
 
             <TextView
                 android:id="@+id/error_message"
diff --git a/res/layout/homepage_condition_header.xml b/res/layout/homepage_condition_header.xml
index 5460be9..30b9033 100644
--- a/res/layout/homepage_condition_header.xml
+++ b/res/layout/homepage_condition_header.xml
@@ -19,6 +19,7 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
+    android:contentDescription="@string/condition_expand_show"
     style="@style/ContextualCardStyle">
 
     <LinearLayout
diff --git a/res/layout/wifi_dpp_qrcode_scanner_fragment.xml b/res/layout/wifi_dpp_qrcode_scanner_fragment.xml
index 9bd742a..68ba277 100644
--- a/res/layout/wifi_dpp_qrcode_scanner_fragment.xml
+++ b/res/layout/wifi_dpp_qrcode_scanner_fragment.xml
@@ -43,18 +43,21 @@
                 android:layout_marginBottom="8dp"
                 style="?android:attr/progressBarStyleHorizontal"/>
 
-            <com.android.settings.wifi.qrcode.QrPreviewLayout
-                android:layout_width="match_parent"
-                android:layout_height="match_parent">
+            <androidx.constraintlayout.widget.ConstraintLayout
+                xmlns:app="http://schemas.android.com/apk/res-auto"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content">
                 <TextureView
                     android:id="@+id/preview_view"
                     android:layout_width="match_parent"
-                    android:layout_height="wrap_content"/>
+                    android:layout_height="0dp"
+                    app:layout_constraintDimensionRatio="1:1"/>
                 <com.android.settings.wifi.qrcode.QrDecorateView
                     android:id="@+id/decorate_view"
                     android:layout_width="match_parent"
-                    android:layout_height="wrap_content"/>
-            </com.android.settings.wifi.qrcode.QrPreviewLayout>
+                    android:layout_height="0dp"
+                    app:layout_constraintDimensionRatio="1:1"/>
+            </androidx.constraintlayout.widget.ConstraintLayout>
 
             <TextView
                 android:id="@+id/error_message"
diff --git a/res/values-night/colors.xml b/res/values-night/colors.xml
index 617feb3..8a6b697 100644
--- a/res/values-night/colors.xml
+++ b/res/values-night/colors.xml
@@ -16,7 +16,6 @@
 
 <resources>
   <color name="switchbar_text_color">@android:color/black</color>
-  <color name="switch_bar_background">#dadce0</color>
   <color name="switchbar_switch_track_tint">#82000000</color>
   <color name="switchbar_switch_thumb_tint">@android:color/black</color>
   <color name="homepage_accessibility_background">#783BE5</color>
diff --git a/res/values-night/themes.xml b/res/values-night/themes.xml
index 8deae1c..2227b88 100644
--- a/res/values-night/themes.xml
+++ b/res/values-night/themes.xml
@@ -29,9 +29,7 @@
         <item name="android:colorControlNormal">?android:attr/colorAccent</item>
     </style>
 
-    <style name="Theme.SubSettings" parent="Theme.SubSettings.Base">
-        <item name="android:colorControlNormal">?android:attr/colorAccent</item>
-    </style>
+    <style name="Theme.SubSettings" parent="Theme.SubSettings.Base"/>
 
     <style name="Theme.AlertDialog.Base" parent="@style/Theme.AppCompat.DayNight.Dialog.Alert">
         <item name="colorAccent">@*android:color/accent_device_default_dark</item>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index b547b5d..9f99755 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -56,7 +56,6 @@
     <color name="material_blue_700">#3367D6</color>
     <color name="material_grey_100">#f5f5f5</color>
     <color name="material_grey_200">#ffffff</color>
-    <color name="switch_bar_background">#757575</color>
 
     <color name="message_text_incoming">#ffffffff</color>
     <color name="message_text_outgoing">#ff323232</color>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 886f558..60724c3 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -346,6 +346,7 @@
     <dimen name="homepage_card_icon_padding_start">14dp</dimen>
     <dimen name="homepage_card_text_padding_start">16dp</dimen>
     <dimen name="homepage_card_padding_end">16dp</dimen>
+    <dimen name="homepage_card_corner_radius">@*android:dimen/config_dialogCornerRadius</dimen>
     <dimen name="homepage_full_card_padding_end">12dp</dimen>
     <dimen name="homepage_half_card_padding_top">12dp</dimen>
     <dimen name="homepage_half_card_padding_bottom">16dp</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 2e2320d..b27e9d0 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -2284,6 +2284,8 @@
     </plurals>
     <!-- Wi-Fi settings screen, advanced, settings section.  This is a header shown above advanced wifi settings. [CHAR LIMIT=30] -->
     <string name="wifi_advanced_titlebar">Advanced Wi\u2011Fi</string>
+    <!-- Wi-Fi settings screen, advanced, title of the item to show the Wi-Fi device's SSID. [CHAR LIMIT=20] -->
+    <string name="wifi_advanced_ssid_title">SSID</string>
     <!-- Wi-Fi settings screen, advanced, title of the item to show the Wi-Fi device's MAC address. -->
     <string name="wifi_advanced_mac_address_title">MAC address</string>
     <!-- Title of the screen to adjust IP settings -->
@@ -7789,9 +7791,9 @@
     <string name="notification_badging_title">Allow notification dots</string>
 
     <!-- Configure Notifications: Title for the notification bubbles option. [CHAR LIMIT=60] -->
-    <string name="notification_bubbles_title">Allow bubbles</string>
+    <string name="notification_bubbles_title">Bubbles</string>
     <!-- Configure Notifications: Summary for the notification bubbles option. [CHAR LIMIT=NONE] -->
-    <string name="notification_bubbles_summary">Allow apps to show some notifications as bubbles</string>
+    <string name="notification_bubbles_summary">Quickly access app content from anywhere using floating shortcuts</string>
     <!-- Feature education for bubbles. [CHAR LIMIT=NONE] -->
     <string name="bubbles_feature_education">Some notifications and other content can appear as bubbles on the screen. To open a bubble, tap it. To dismiss it, drag it down the screen.</string>
     <!-- Title for the toggle shown on the app-level bubbles page  [CHAR LIMIT=60] -->
@@ -11013,11 +11015,11 @@
     <!-- Message for forget passpoint dialog [CHAR LIMIT=none] -->
     <string name="forget_passpoint_dialog_message">You may lose access to any remaining time or data. Check with your provider before removing.</string>
 
-    <!-- Keywords for Content Capture feature [CHAR_LIMIT=32] -->
-    <string name="keywords_content_capture">content capture</string>
+    <!-- Keywords for Content Capture / Smart Suggestions feature [CHAR_LIMIT=none] -->
+    <string name="keywords_content_capture">content capture, smart suggestions</string>
     <!-- Title of the 'Content Capture' feature toggle in the Settings -> Privacy screen [CHAR LIMIT=none]-->
-    <string name="content_capture">Content Capture</string>
-    <!-- Description of the 'Content Capture' feature toggle in the Settings -> Privacy screen [CHAR LIMIT=NONE]-->
+    <string name="content_capture">Smart Suggestions</string>
+    <!-- Description of the 'Content Capture / Smart Suggestions' feature toggle in the Settings -> Privacy screen [CHAR LIMIT=NONE]-->
     <string name="content_capture_summary">Allow Android to save information seen on your screen or heard in video or audio content. Android makes helpful suggestions based on your device activity.</string>
 
     <!-- Title for the button to initiate a heap dump for the system server. [CHAR LIMIT=NONE] -->
@@ -11030,4 +11032,7 @@
     <string name="automatic_system_heap_dump_title">Automatically capture system heap dumps</string>
     <!-- Summary of toggle for whether to enable automatic heap dumps for the system server or not. [CHAR LIMIT=NONE] -->
     <string name="automatic_system_heap_dump_summary">Automatically capture a heap dump for Android System when it uses too much memory</string>
+
+    <!-- Button label to disconnect a Wi-Fi network. [CHAR LIMIT=40] -->
+    <string name="wifi_disconnect_button_text">Disconnect</string>
 </resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 02db995..8cd22fe 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -418,7 +418,7 @@
         <item name="android:layout_marginStart">@dimen/homepage_card_side_margin</item>
         <item name="android:layout_marginEnd">@dimen/homepage_card_side_margin</item>
         <item name="cardBackgroundColor">@color/contextual_card_background</item>
-        <item name="cardCornerRadius">@*android:dimen/config_dialogCornerRadius</item>
+        <item name="cardCornerRadius">@dimen/homepage_card_corner_radius</item>
         <item name="cardElevation">0dp</item>
         <item name="strokeColor">@color/homepage_card_stroke_color</item>
         <item name="strokeWidth">1dp</item>
diff --git a/res/values/themes.xml b/res/values/themes.xml
index a8ae506..59b2b9e 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -94,7 +94,7 @@
     <style name="ThemeOverlay.SwitchBar.Settings" parent="@android:style/ThemeOverlay.Material.ActionBar">
         <item name="switchBarMarginStart">@dimen/switchbar_subsettings_margin_start</item>
         <item name="switchBarMarginEnd">@dimen/switchbar_subsettings_margin_end</item>
-        <item name="switchBarBackgroundColor">@color/switch_bar_background</item>
+        <item name="switchBarBackgroundColor">?android:attr/textColorSecondary</item>
         <item name="switchBarBackgroundActivatedColor">?android:attr/colorAccent</item>
         <item name="switchBarRestrictionIcon">@*android:drawable/ic_info</item>
     </style>
@@ -103,6 +103,7 @@
         <item name="android:trackTint">@color/switchbar_switch_track_tint</item>
         <item name="android:thumbTint">@color/switchbar_switch_thumb_tint</item>
         <item name="android:minHeight">@dimen/min_tap_target_size</item>
+        <item name="android:minWidth">@dimen/min_tap_target_size</item>
     </style>
 
     <style name="Theme.CryptKeeper" parent="@android:style/Theme.Material.NoActionBar">
diff --git a/res/xml/accessibility_settings.xml b/res/xml/accessibility_settings.xml
index 1efe2c2..0e417c9 100644
--- a/res/xml/accessibility_settings.xml
+++ b/res/xml/accessibility_settings.xml
@@ -58,12 +58,10 @@
             android:title="@string/screen_zoom_title"
             settings:searchable="false"/>
 
-        <ListPreference
+        <Preference
             android:key="dark_ui_mode_accessibility"
+            android:fragment="com.android.settings.display.DarkUISettings"
             android:title="@string/dark_ui_mode"
-            android:dialogTitle="@string/dark_ui_mode_title"
-            android:entries="@array/dark_ui_mode_entries"
-            android:entryValues="@array/dark_ui_mode_values"
             settings:searchable="false" />
 
         <Preference
diff --git a/res/xml/app_and_notification.xml b/res/xml/app_and_notification.xml
index 2996afa..fd3725a 100644
--- a/res/xml/app_and_notification.xml
+++ b/res/xml/app_and_notification.xml
@@ -20,7 +20,7 @@
     xmlns:settings="http://schemas.android.com/apk/res-auto"
     android:key="apps_and_notification_screen"
     android:title="@string/app_and_notification_dashboard_title"
-    settings:initialExpandedChildrenCount="8">
+    settings:initialExpandedChildrenCount="3">
     <!-- the initial count should include the dynamic tiles -->
 
     <Preference
diff --git a/res/xml/app_bubble_notification_settings.xml b/res/xml/app_bubble_notification_settings.xml
new file mode 100644
index 0000000..8d97f8f
--- /dev/null
+++ b/res/xml/app_bubble_notification_settings.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+                  xmlns:settings="http://schemas.android.com/apk/res-auto"
+                  android:title="@string/bubbles_app_toggle_title"
+                  android:key="app_bubble_notification_settings">
+        <com.android.settingslib.widget.LayoutPreference
+            android:key="pref_app_header"
+            android:layout="@layout/settings_entity_header"/>
+
+        <com.android.settingslib.RestrictedSwitchPreference
+            android:key="bubble_pref"
+            android:title="@string/notification_bubbles_title"/>
+
+        <com.android.settingslib.widget.FooterPreference
+            android:key="notification_bubbles_footer"
+            android:title="@string/bubbles_feature_education"
+            android:selectable="false" />
+
+</PreferenceScreen>
diff --git a/res/xml/app_notification_settings.xml b/res/xml/app_notification_settings.xml
index faad649..fedd3cc 100644
--- a/res/xml/app_notification_settings.xml
+++ b/res/xml/app_notification_settings.xml
@@ -60,11 +60,10 @@
             settings:useAdditionalSummary="true"
             android:order="1001"
             settings:restrictedSwitchSummary="@string/enabled_by_admin" />
-        <com.android.settingslib.RestrictedSwitchPreference
-            android:key="bubble_pref"
+        <Preference
+            android:key="bubble_link_pref"
             android:title="@string/notification_bubbles_title"
-            android:order="1002"
-            settings:restrictedSwitchSummary="@string/enabled_by_admin" />
+            android:order="1002" />
         <Preference
             android:key="app_link"
             android:order="1003"
diff --git a/res/xml/bubble_notification_settings.xml b/res/xml/bubble_notification_settings.xml
new file mode 100644
index 0000000..20783fa
--- /dev/null
+++ b/res/xml/bubble_notification_settings.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+                  xmlns:settings="http://schemas.android.com/apk/res-auto"
+                  android:title="@string/bubbles_app_toggle_title"
+                  android:key="bubble_notification_settings">
+        <!-- Notification bubbles -->
+        <SwitchPreference
+            android:key="global_notification_bubbles"
+            android:title="@string/notification_bubbles_title"
+            android:summary="@string/notification_bubbles_summary"
+            settings:controller="com.android.settings.notification.BubbleNotificationPreferenceController"/>
+
+        <com.android.settingslib.widget.FooterPreference
+            android:key="notification_bubbles_footer"
+            android:title="@string/bubbles_feature_education"
+            android:selectable="false" />
+
+</PreferenceScreen>
diff --git a/res/xml/channel_notification_settings.xml b/res/xml/channel_notification_settings.xml
index 3158819..14e0366 100644
--- a/res/xml/channel_notification_settings.xml
+++ b/res/xml/channel_notification_settings.xml
@@ -63,8 +63,7 @@
             android:dialogTitle="@string/notification_channel_sound_title"
             android:order="11"
             android:showSilent="true"
-            android:showDefault="true"
-            android:ringtoneType="notification" />
+            android:showDefault="true"/>
 
         <!-- Vibration -->
         <com.android.settingslib.RestrictedSwitchPreference
diff --git a/res/xml/configure_notification_settings.xml b/res/xml/configure_notification_settings.xml
index e48ddc1..97a4182 100644
--- a/res/xml/configure_notification_settings.xml
+++ b/res/xml/configure_notification_settings.xml
@@ -70,11 +70,11 @@
             settings:controller="com.android.settings.notification.BadgingNotificationPreferenceController"/>
 
         <!-- Notification bubbles -->
-        <SwitchPreference
+        <Preference
             android:key="notification_bubbles"
             android:title="@string/notification_bubbles_title"
-            android:summary="@string/notification_bubbles_summary"
-            settings:controller="com.android.settings.notification.BubbleNotificationPreferenceController"/>
+            settings:controller="com.android.settings.notification.BubbleSummaryNotificationPreferenceController"
+            android:fragment="com.android.settings.notification.BubbleNotificationSettings"/>
 
         <!-- Pulse notification light -->
         <SwitchPreference
diff --git a/res/xml/network_and_internet_v2.xml b/res/xml/network_and_internet_v2.xml
index 44c3121..f004d06 100644
--- a/res/xml/network_and_internet_v2.xml
+++ b/res/xml/network_and_internet_v2.xml
@@ -23,6 +23,7 @@
     <PreferenceCategory
         android:key="multi_network_header"
         android:title="@string/summary_placeholder"
+        android:layout="@layout/preference_category_no_label"
         settings:allowDividerBelow="true"
         android:order="-40"
         settings:controller="com.android.settings.network.MultiNetworkHeaderController"/>
diff --git a/res/xml/power_usage_summary.xml b/res/xml/power_usage_summary.xml
index 94ead86..88f88f1 100644
--- a/res/xml/power_usage_summary.xml
+++ b/res/xml/power_usage_summary.xml
@@ -26,13 +26,11 @@
         android:title="@string/summary_placeholder"
         android:selectable="false"
         android:layout="@layout/battery_header"
-        settings:allowDividerBelow="true"
         settings:controller="com.android.settings.fuelgauge.BatteryHeaderPreferenceController" />
 
     <com.android.settings.widget.CardPreference
         android:key="battery_tip"
         android:title="@string/summary_placeholder"
-        settings:allowDividerAbove="true"
         settings:controller="com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController" />
 
     <Preference
diff --git a/res/xml/privacy_dashboard_settings.xml b/res/xml/privacy_dashboard_settings.xml
index f39880c..45b9d19 100644
--- a/res/xml/privacy_dashboard_settings.xml
+++ b/res/xml/privacy_dashboard_settings.xml
@@ -62,26 +62,6 @@
         android:summary="@string/summary_placeholder"
         settings:searchable="false"/>
 
-    <!-- Content Capture -->
-
-    <!-- NOTE: content capture has a different preference, depending whether or not the
-         ContentCaptureService implementations defines a custom settings activitiy on its manifest.
-         Hence, we show both here, but the controller itself will decide if it's available or not.
-    -->
-
-    <SwitchPreference
-        android:key="content_capture"
-        android:title="@string/content_capture"
-        android:summary="@string/content_capture_summary"
-        settings:controller="com.android.settings.privacy.EnableContentCapturePreferenceController"/>
-
-    <com.android.settings.widget.MasterSwitchPreference
-        android:key="content_capture_custom_settings"
-        android:title="@string/content_capture"
-        android:summary="@string/content_capture_summary"
-        settings:controller="com.android.settings.privacy.EnableContentCaptureWithServiceSettingsPreferenceController">
-    </com.android.settings.widget.MasterSwitchPreference>
-
     <!-- Privacy Service -->
     <PreferenceCategory
         android:key="privacy_services"/>
@@ -105,4 +85,24 @@
             settings:searchable="false"/>
     </PreferenceCategory>
 
+    <!-- Content Capture -->
+
+    <!-- NOTE: content capture has a different preference, depending whether or not the
+         ContentCaptureService implementations defines a custom settings activitiy on its manifest.
+         Hence, we show both here, but the controller itself will decide if it's available or not.
+    -->
+
+    <SwitchPreference
+        android:key="content_capture"
+        android:title="@string/content_capture"
+        android:summary="@string/content_capture_summary"
+        settings:controller="com.android.settings.privacy.EnableContentCapturePreferenceController"/>
+
+    <com.android.settings.widget.MasterSwitchPreference
+        android:key="content_capture_custom_settings"
+        android:title="@string/content_capture"
+        android:summary="@string/content_capture_summary"
+        settings:controller="com.android.settings.privacy.EnableContentCaptureWithServiceSettingsPreferenceController">
+    </com.android.settings.widget.MasterSwitchPreference>
+
 </PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/wifi_network_details_fragment.xml b/res/xml/wifi_network_details_fragment.xml
index 782a7cf..8fb19cb 100644
--- a/res/xml/wifi_network_details_fragment.xml
+++ b/res/xml/wifi_network_details_fragment.xml
@@ -85,6 +85,11 @@
             android:key="ip_details_category"
             android:title="@string/wifi_setup_detail">
         <Preference
+                android:key="ssid"
+                android:title="@string/wifi_advanced_ssid_title"
+                android:selectable="false"
+                settings:enableCopying="true"/>
+        <Preference
                 android:key="mac_address"
                 android:title="@string/wifi_advanced_mac_address_title"
                 android:selectable="false"
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index bdb5889..e1c9aff 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -113,6 +113,7 @@
     public static class ZenModeEventRuleSettingsActivity extends SettingsActivity { /* empty */ }
     public static class SoundSettingsActivity extends SettingsActivity { /* empty */ }
     public static class ConfigureNotificationSettingsActivity extends SettingsActivity { /* empty */ }
+    public static class AppBubbleNotificationSettingsActivity extends SettingsActivity { /* empty */ }
     public static class NotificationAssistantSettingsActivity extends SettingsActivity{ /* empty */ }
     public static class NotificationAppListActivity extends SettingsActivity { /* empty */ }
     public static class AppNotificationSettingsActivity extends SettingsActivity { /* empty */ }
diff --git a/src/com/android/settings/SetupWizardUtils.java b/src/com/android/settings/SetupWizardUtils.java
index 70ee2ca..7a2fe80 100644
--- a/src/com/android/settings/SetupWizardUtils.java
+++ b/src/com/android/settings/SetupWizardUtils.java
@@ -30,46 +30,59 @@
         if (theme == null) {
             theme = SetupWizardProperties.theme().orElse("");
         }
+        // TODO(yukl): Move to ThemeResolver and add any additional required attributes in
+        // onApplyThemeResource using Theme overlays
         if (theme != null) {
-            switch (theme) {
-                case ThemeHelper.THEME_GLIF_V3_LIGHT:
-                    return R.style.GlifV3Theme_Light;
-                case ThemeHelper.THEME_GLIF_V3:
-                    return R.style.GlifV3Theme;
-                case ThemeHelper.THEME_GLIF_V2_LIGHT:
-                    return R.style.GlifV2Theme_Light;
-                case ThemeHelper.THEME_GLIF_V2:
-                    return R.style.GlifV2Theme;
-                case ThemeHelper.THEME_GLIF_LIGHT:
-                    return R.style.GlifTheme_Light;
-                case ThemeHelper.THEME_GLIF:
-                    return R.style.GlifTheme;
+            if (WizardManagerHelper.isAnySetupWizard(intent)) {
+                switch (theme) {
+                    case ThemeHelper.THEME_GLIF_V3_LIGHT:
+                        return R.style.GlifV3Theme_Light;
+                    case ThemeHelper.THEME_GLIF_V3:
+                        return R.style.GlifV3Theme;
+                    case ThemeHelper.THEME_GLIF_V2_LIGHT:
+                        return R.style.GlifV2Theme_Light;
+                    case ThemeHelper.THEME_GLIF_V2:
+                        return R.style.GlifV2Theme;
+                    case ThemeHelper.THEME_GLIF_LIGHT:
+                        return R.style.GlifTheme_Light;
+                    case ThemeHelper.THEME_GLIF:
+                        return R.style.GlifTheme;
+                }
+            } else {
+                switch (theme) {
+                    case ThemeHelper.THEME_GLIF_V3_LIGHT:
+                    case ThemeHelper.THEME_GLIF_V3:
+                        return R.style.GlifV3Theme;
+                    case ThemeHelper.THEME_GLIF_V2_LIGHT:
+                    case ThemeHelper.THEME_GLIF_V2:
+                        return R.style.GlifV2Theme;
+                    case ThemeHelper.THEME_GLIF_LIGHT:
+                    case ThemeHelper.THEME_GLIF:
+                        return R.style.GlifTheme;
+                }
             }
         }
-        return R.style.GlifTheme_Light;
+        return R.style.GlifTheme;
     }
 
     public static int getTransparentTheme(Intent intent) {
         final int suwTheme = getTheme(intent);
-        int wifiDialogTheme = R.style.GlifV2Theme_Light_Transparent;
+        int transparentTheme = R.style.GlifV2Theme_Light_Transparent;
         if (suwTheme == R.style.GlifV3Theme) {
-            wifiDialogTheme = R.style.GlifV3Theme_Transparent;
+            transparentTheme = R.style.GlifV3Theme_Transparent;
         } else if (suwTheme == R.style.GlifV3Theme_Light) {
-            wifiDialogTheme = R.style.GlifV3Theme_Light_Transparent;
+            transparentTheme = R.style.GlifV3Theme_Light_Transparent;
         } else if (suwTheme == R.style.GlifV2Theme) {
-            wifiDialogTheme = R.style.GlifV2Theme_Transparent;
+            transparentTheme = R.style.GlifV2Theme_Transparent;
         } else if (suwTheme == R.style.GlifTheme_Light) {
-            wifiDialogTheme = R.style.SetupWizardTheme_Light_Transparent;
+            transparentTheme = R.style.SetupWizardTheme_Light_Transparent;
         } else if (suwTheme == R.style.GlifTheme) {
-            wifiDialogTheme = R.style.SetupWizardTheme_Transparent;
+            transparentTheme = R.style.SetupWizardTheme_Transparent;
         }
-        return wifiDialogTheme;
+        return transparentTheme;
     }
 
     public static void copySetupExtras(Intent fromIntent, Intent toIntent) {
-        toIntent.putExtra(WizardManagerHelper.EXTRA_THEME,
-                fromIntent.getStringExtra(WizardManagerHelper.EXTRA_THEME));
-        toIntent.putExtra(WizardManagerHelper.EXTRA_USE_IMMERSIVE_MODE,
-                fromIntent.getBooleanExtra(WizardManagerHelper.EXTRA_USE_IMMERSIVE_MODE, false));
+        WizardManagerHelper.copyWizardManagerExtras(fromIntent, toIntent);
     }
 }
diff --git a/src/com/android/settings/accessibility/AccessibilitySettings.java b/src/com/android/settings/accessibility/AccessibilitySettings.java
index 4ba605f..efa14f6 100644
--- a/src/com/android/settings/accessibility/AccessibilitySettings.java
+++ b/src/com/android/settings/accessibility/AccessibilitySettings.java
@@ -244,7 +244,7 @@
     private SwitchPreference mToggleInversionPreference;
     private ColorInversionPreferenceController mInversionPreferenceController;
     private AccessibilityHearingAidPreferenceController mHearingAidPreferenceController;
-    private ListPreference mDarkUIModePreference;
+    private Preference mDarkUIModePreference;
     private DarkUIPreferenceController mDarkUIPreferenceController;
     private LiveCaptionPreferenceController mLiveCaptionPreferenceController;
 
diff --git a/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java b/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java
index d9ddc2f..56d5335 100644
--- a/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java
+++ b/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java
@@ -33,13 +33,10 @@
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Bundle;
-import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.util.Log;
 import android.view.View;
-import android.webkit.IWebViewUpdateService;
 
 import androidx.annotation.VisibleForTesting;
 import androidx.fragment.app.Fragment;
@@ -438,10 +435,6 @@
             enabled = false;
         }
 
-        if (isFallbackPackage(mAppEntry.info.packageName)) {
-            enabled = false;
-        }
-
         mButtonsPref.setButton2Enabled(enabled);
     }
 
@@ -467,22 +460,6 @@
     }
 
     @VisibleForTesting
-    boolean isFallbackPackage(String packageName) {
-        try {
-            IWebViewUpdateService webviewUpdateService =
-                    IWebViewUpdateService.Stub.asInterface(
-                            ServiceManager.getService("webviewupdate"));
-            if (webviewUpdateService.isFallbackPackage(packageName)) {
-                return true;
-            }
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-
-        return false;
-    }
-
-    @VisibleForTesting
     void updateForceStopButton() {
         if (mDpm.packageHasActiveAdmins(mPackageInfo.packageName)) {
             // User can't force stop device admin.
diff --git a/src/com/android/settings/applications/manageapplications/ResetAppsHelper.java b/src/com/android/settings/applications/manageapplications/ResetAppsHelper.java
index 3af3500..92c0958 100644
--- a/src/com/android/settings/applications/manageapplications/ResetAppsHelper.java
+++ b/src/com/android/settings/applications/manageapplications/ResetAppsHelper.java
@@ -32,7 +32,6 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
-import android.webkit.IWebViewUpdateService;
 
 import androidx.appcompat.app.AlertDialog;
 
@@ -48,7 +47,6 @@
     private final PackageManager mPm;
     private final IPackageManager mIPm;
     private final INotificationManager mNm;
-    private final IWebViewUpdateService mWvus;
     private final NetworkPolicyManager mNpm;
     private final AppOpsManager mAom;
     private final Context mContext;
@@ -61,7 +59,6 @@
         mIPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
         mNm = INotificationManager.Stub.asInterface(
                 ServiceManager.getService(Context.NOTIFICATION_SERVICE));
-        mWvus = IWebViewUpdateService.Stub.asInterface(ServiceManager.getService("webviewupdate"));
         mNpm = NetworkPolicyManager.from(context);
         mAom = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
     }
@@ -122,8 +119,7 @@
                     }
                     if (!app.enabled) {
                         if (mPm.getApplicationEnabledSetting(app.packageName)
-                                == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER
-                                && !isNonEnableableFallback(app.packageName)) {
+                                == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
                             mPm.setApplicationEnabledSetting(app.packageName,
                                     PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
                                     PackageManager.DONT_KILL_APP);
@@ -147,12 +143,4 @@
             }
         });
     }
-
-    private boolean isNonEnableableFallback(String packageName) {
-        try {
-            return mWvus.isFallbackPackage(packageName);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
 }
diff --git a/src/com/android/settings/aware/AwareFeatureProvider.java b/src/com/android/settings/aware/AwareFeatureProvider.java
index a24233f..bda27c7 100644
--- a/src/com/android/settings/aware/AwareFeatureProvider.java
+++ b/src/com/android/settings/aware/AwareFeatureProvider.java
@@ -18,10 +18,15 @@
 
 import android.content.Context;
 
+import androidx.fragment.app.Fragment;
+
 public interface AwareFeatureProvider {
     /** Returns true if the aware sensor is supported. */
     boolean isSupported(Context context);
 
     /** Returns true if the aware feature is enabled. */
     boolean isEnabled(Context context);
+
+    /** Show information dialog. */
+    void showRestrictionDialog(Fragment parent);
 }
diff --git a/src/com/android/settings/aware/AwareFeatureProviderImpl.java b/src/com/android/settings/aware/AwareFeatureProviderImpl.java
index 44ec31b..5d16031 100644
--- a/src/com/android/settings/aware/AwareFeatureProviderImpl.java
+++ b/src/com/android/settings/aware/AwareFeatureProviderImpl.java
@@ -18,6 +18,8 @@
 
 import android.content.Context;
 
+import androidx.fragment.app.Fragment;
+
 public class AwareFeatureProviderImpl implements AwareFeatureProvider {
     @Override
     public boolean isSupported(Context context) {
@@ -28,4 +30,8 @@
     public boolean isEnabled(Context context) {
         return false;
     }
+
+    @Override
+    public void showRestrictionDialog(Fragment parent) {
+    }
 }
diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java
index 31d54f9..30f6afc 100644
--- a/src/com/android/settings/core/gateway/SettingsGateway.java
+++ b/src/com/android/settings/core/gateway/SettingsGateway.java
@@ -101,7 +101,9 @@
 import com.android.settings.network.NetworkDashboardFragment;
 import com.android.settings.nfc.AndroidBeam;
 import com.android.settings.nfc.PaymentSettings;
+import com.android.settings.notification.AppBubbleNotificationSettings;
 import com.android.settings.notification.AppNotificationSettings;
+import com.android.settings.notification.BubbleNotificationSettings;
 import com.android.settings.notification.ChannelGroupNotificationSettings;
 import com.android.settings.notification.ChannelNotificationSettings;
 import com.android.settings.notification.ConfigureNotificationSettings;
@@ -211,6 +213,8 @@
             DreamSettings.class.getName(),
             UserSettings.class.getName(),
             NotificationAccessSettings.class.getName(),
+            BubbleNotificationSettings.class.getName(),
+            AppBubbleNotificationSettings.class.getName(),
             ZenAccessSettings.class.getName(),
             ZenAccessDetails.class.getName(),
             ZenModeAutomationSettings.class.getName(),
diff --git a/src/com/android/settings/deviceinfo/hardwareinfo/DeviceModelPreferenceController.java b/src/com/android/settings/deviceinfo/hardwareinfo/DeviceModelPreferenceController.java
index 42c7b01..fbd1e9e 100644
--- a/src/com/android/settings/deviceinfo/hardwareinfo/DeviceModelPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/hardwareinfo/DeviceModelPreferenceController.java
@@ -39,4 +39,9 @@
     public boolean isSliceable() {
         return true;
     }
+
+    @Override
+    public CharSequence getSummary() {
+        return HardwareInfoPreferenceController.getDeviceModel();
+    }
 }
diff --git a/src/com/android/settings/enterprise/ActionDisabledByAdminDialogHelper.java b/src/com/android/settings/enterprise/ActionDisabledByAdminDialogHelper.java
index 5bdf587..5599a94 100644
--- a/src/com/android/settings/enterprise/ActionDisabledByAdminDialogHelper.java
+++ b/src/com/android/settings/enterprise/ActionDisabledByAdminDialogHelper.java
@@ -55,7 +55,7 @@
 public class ActionDisabledByAdminDialogHelper {
 
     private static final String TAG = ActionDisabledByAdminDialogHelper.class.getName();
-    private EnforcedAdmin mEnforcedAdmin;
+    @VisibleForTesting EnforcedAdmin mEnforcedAdmin;
     private ViewGroup mDialogView;
     private String mRestriction = null;
     private Activity mActivity;
@@ -80,20 +80,28 @@
             EnforcedAdmin enforcedAdmin) {
         mEnforcedAdmin = enforcedAdmin;
         mRestriction = restriction;
-
         final AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
         mDialogView = (ViewGroup) LayoutInflater.from(builder.getContext()).inflate(
                 R.layout.admin_support_details_dialog, null);
         initializeDialogViews(mDialogView, mEnforcedAdmin.component, getEnforcementAdminUserId(),
                 mRestriction);
-        return builder
-            .setPositiveButton(R.string.okay, null)
-            .setNeutralButton(R.string.learn_more,
-                    (dialog, which) -> {
-                        showAdminPolicies(mEnforcedAdmin, mActivity);
-                        mActivity.finish();
-                    })
-            .setView(mDialogView);
+        builder.setPositiveButton(R.string.okay, null).setView(mDialogView);
+        maybeSetLearnMoreButton(builder);
+        return builder;
+    }
+
+    @VisibleForTesting
+    void maybeSetLearnMoreButton(AlertDialog.Builder builder) {
+        // The "Learn more" button appears only if the restriction is enforced by an admin in the
+        // same profile group. Otherwise the admin package and its policies are not accessible to
+        // the current user.
+        final UserManager um = UserManager.get(mActivity.getApplicationContext());
+        if (um.isSameProfileGroup(getEnforcementAdminUserId(mEnforcedAdmin), um.getUserHandle())) {
+            builder.setNeutralButton(R.string.learn_more, (dialog, which) -> {
+                showAdminPolicies(mEnforcedAdmin, mActivity);
+                mActivity.finish();
+            });
+        }
     }
 
     public void updateDialog(String restriction, EnforcedAdmin admin) {
diff --git a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleRadioButtonsController.java b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleRadioButtonsController.java
index 796df46..57bae45 100644
--- a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleRadioButtonsController.java
+++ b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleRadioButtonsController.java
@@ -20,6 +20,8 @@
 import android.os.PowerManager;
 import android.provider.Settings;
 import android.provider.Settings.Global;
+import android.text.TextUtils;
+import com.android.settingslib.fuelgauge.BatterySaverUtils;
 
 /**
  * Responds to user actions in the Settings > Battery > Set a Schedule Screen
@@ -66,24 +68,34 @@
 
     public boolean setDefaultKey(String key) {
         final ContentResolver resolver = mContext.getContentResolver();
-        switch(key) {
-            case KEY_NO_SCHEDULE:
-                Settings.Global.putInt(resolver, Global.AUTOMATIC_POWER_SAVE_MODE,
-                        PowerManager.POWER_SAVE_MODE_TRIGGER_PERCENTAGE);
-                Settings.Global.putInt(resolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
-                break;
-            case KEY_PERCENTAGE:
-                Settings.Global.putInt(resolver, Global.AUTOMATIC_POWER_SAVE_MODE,
-                        PowerManager.POWER_SAVE_MODE_TRIGGER_PERCENTAGE);
-                Settings.Global.putInt(resolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 5);
-                break;
-            case KEY_ROUTINE:
-                Settings.Global.putInt(resolver, Global.AUTOMATIC_POWER_SAVE_MODE,
-                        PowerManager.POWER_SAVE_MODE_TRIGGER_DYNAMIC);
-                break;
-            default:
-                throw new IllegalStateException(
-                        "Not a valid key for " + this.getClass().getSimpleName());
+
+        int mode = PowerManager.POWER_SAVE_MODE_TRIGGER_PERCENTAGE;
+        int triggerLevel = 0;
+        if (!TextUtils.equals(key, KEY_NO_SCHEDULE)
+                && BatterySaverUtils.maybeShowBatterySaverConfirmation(
+                        mContext, true /* confirmOnly */)) {
+            return true;
+        } else {
+            switch (key) {
+                case KEY_NO_SCHEDULE:
+                    break;
+                case KEY_PERCENTAGE:
+                    triggerLevel = 5;
+                    break;
+                case KEY_ROUTINE:
+                    mode = PowerManager.POWER_SAVE_MODE_TRIGGER_DYNAMIC;
+                    break;
+                default:
+                    throw new IllegalStateException(
+                            "Not a valid key for " + this.getClass().getSimpleName());
+            }
+        }
+
+        // Trigger level is intentionally left alone when going between dynamic and percentage modes
+        // so that a users percentage based schedule is preserved when they toggle between the two.
+        Settings.Global.putInt(resolver, Global.AUTOMATIC_POWER_SAVE_MODE, mode);
+        if (mode != PowerManager.POWER_SAVE_MODE_TRIGGER_DYNAMIC) {
+            Settings.Global.putInt(resolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, triggerLevel);
         }
         mSeekBarController.updateSeekBar();
         return true;
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCard.java b/src/com/android/settings/homepage/contextualcards/ContextualCard.java
index 7b8a0c3..ede12fb 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCard.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCard.java
@@ -71,6 +71,7 @@
     private final Drawable mIconDrawable;
     @LayoutRes
     private final int mViewType;
+    private final boolean mIsPendingDismiss;
 
     public String getName() {
         return mName;
@@ -156,6 +157,10 @@
         return mViewType;
     }
 
+    public boolean isPendingDismiss() {
+        return mIsPendingDismiss;
+    }
+
     public Builder mutate() {
         return mBuilder;
     }
@@ -181,6 +186,7 @@
         mIconDrawable = builder.mIconDrawable;
         mIsLargeCard = builder.mIsLargeCard;
         mViewType = builder.mViewType;
+        mIsPendingDismiss = builder.mIsPendingDismiss;
     }
 
     ContextualCard(Cursor c) {
@@ -226,6 +232,8 @@
         mBuilder.setIconDrawable(mIconDrawable);
         mViewType = getViewTypeByCardType(mCardType);
         mBuilder.setViewType(mViewType);
+        mIsPendingDismiss = false;
+        mBuilder.setIsPendingDismiss(mIsPendingDismiss);
     }
 
     @Override
@@ -277,6 +285,7 @@
         private boolean mIsLargeCard;
         @LayoutRes
         private int mViewType;
+        private boolean mIsPendingDismiss;
 
         public Builder setName(String name) {
             mName = name;
@@ -373,6 +382,11 @@
             return this;
         }
 
+        public Builder setIsPendingDismiss(boolean isPendingDismiss) {
+            mIsPendingDismiss = isPendingDismiss;
+            return this;
+        }
+
         public ContextualCard build() {
             return new ContextualCard(this);
         }
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardsAdapter.java b/src/com/android/settings/homepage/contextualcards/ContextualCardsAdapter.java
index d6df380..7be0e8e 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardsAdapter.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardsAdapter.java
@@ -28,7 +28,7 @@
 import androidx.recyclerview.widget.RecyclerView;
 
 import com.android.settings.homepage.contextualcards.conditional.ConditionContextualCardRenderer;
-import com.android.settings.homepage.contextualcards.slices.SwipeDismissalDelegate.DismissalItemTouchHelperListener;
+import com.android.settings.homepage.contextualcards.slices.SwipeDismissalDelegate;
 import com.android.settings.homepage.contextualcards.slices.SliceContextualCardRenderer;
 
 import java.util.ArrayList;
@@ -36,7 +36,7 @@
 import java.util.Map;
 
 public class ContextualCardsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
-        implements ContextualCardUpdateListener, DismissalItemTouchHelperListener {
+        implements ContextualCardUpdateListener, SwipeDismissalDelegate.Listener {
     static final int SPAN_COUNT = 2;
 
     private static final String TAG = "ContextualCardsAdapter";
@@ -140,6 +140,9 @@
 
     @Override
     public void onSwiped(int position) {
-
+        final ContextualCard card = mContextualCards.get(position).mutate()
+                .setIsPendingDismiss(true).build();
+        mContextualCards.set(position, card);
+        notifyItemChanged(position);
     }
 }
diff --git a/src/com/android/settings/homepage/contextualcards/slices/NotificationChannelSlice.java b/src/com/android/settings/homepage/contextualcards/slices/NotificationChannelSlice.java
index d174156..0278f90 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/NotificationChannelSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/NotificationChannelSlice.java
@@ -176,15 +176,10 @@
                 .setSubtitle(getSubTitle(mPackageName, mUid))
                 .setPrimaryAction(getPrimarySliceAction(icon, title, getIntent())));
 
-        // Get rows by notification channel.
+        // Add notification channel rows.
         final List<ListBuilder.RowBuilder> rows = getNotificationChannelRows(packageInfo, icon);
-
-        // Get displayable notification channel count.
-        final int channelCount = Math.min(rows.size(), DEFAULT_EXPANDED_ROW_COUNT);
-
-        // According to the displayable channel count to add rows.
-        for (int i = 0; i < channelCount; i++) {
-            listBuilder.addRow(rows.get(i));
+        for (ListBuilder.RowBuilder rowBuilder : rows) {
+            listBuilder.addRow(rowBuilder);
         }
 
         return listBuilder.build();
@@ -279,10 +274,9 @@
     private List<ListBuilder.RowBuilder> getNotificationChannelRows(PackageInfo packageInfo,
             IconCompat icon) {
         final List<ListBuilder.RowBuilder> notificationChannelRows = new ArrayList<>();
-        final List<NotificationChannel> enabledChannels = getEnabledChannels(mPackageName, mUid,
-                mAppRow);
+        final List<NotificationChannel> displayableChannels = getDisplayableChannels(mAppRow);
 
-        for (NotificationChannel channel : enabledChannels) {
+        for (NotificationChannel channel : displayableChannels) {
             notificationChannelRows.add(new ListBuilder.RowBuilder()
                     .setTitle(channel.getName())
                     .setSubtitle(NotificationBackend.getSentSummary(
@@ -356,10 +350,9 @@
                 title);
     }
 
-    private List<NotificationChannel> getEnabledChannels(String packageName, int uid,
-            NotificationBackend.AppRow appRow) {
+    private List<NotificationChannel> getDisplayableChannels(NotificationBackend.AppRow appRow) {
         final List<NotificationChannelGroup> channelGroupList =
-                mNotificationBackend.getGroups(packageName, uid).getList();
+                mNotificationBackend.getGroups(appRow.pkg, appRow.uid).getList();
         final List<NotificationChannel> channels = channelGroupList.stream()
                 .flatMap(group -> group.getChannels().stream().filter(
                         channel -> isChannelEnabled(group, channel, appRow)))
@@ -376,8 +369,11 @@
         }
 
         // Sort the notification channels with notification sent count by descending.
-        return channelStates.stream().sorted(CHANNEL_STATE_COMPARATOR).map(
-                state -> state.getNotificationChannel()).collect(Collectors.toList());
+        return channelStates.stream()
+                .sorted(CHANNEL_STATE_COMPARATOR)
+                .map(state -> state.getNotificationChannel())
+                .limit(DEFAULT_EXPANDED_ROW_COUNT)
+                .collect(Collectors.toList());
     }
 
     private PackageInfo getMaxSentNotificationsPackage(List<PackageInfo> packageInfoList) {
@@ -391,10 +387,14 @@
         for (PackageInfo packageInfo : packageInfoList) {
             final NotificationBackend.AppRow appRow = mNotificationBackend.loadAppRow(mContext,
                     mContext.getPackageManager(), packageInfo);
+            // Ignore packages which are banned notifications or block all displayable channels.
+            if (appRow.banned || isAllChannelsBlocked(getDisplayableChannels(appRow))) {
+                continue;
+            }
+
             // Get sent notification count from app.
             final int sentCount = appRow.sentByApp.sentCount;
-            if (!appRow.banned && sentCount >= MIN_NOTIFICATION_SENT_COUNT
-                    && sentCount > maxSentCount) {
+            if (sentCount >= MIN_NOTIFICATION_SENT_COUNT && sentCount > maxSentCount) {
                 maxSentCount = sentCount;
                 maxSentCountPackage = packageInfo;
                 mAppRow = appRow;
@@ -404,6 +404,15 @@
         return maxSentCountPackage;
     }
 
+    private boolean isAllChannelsBlocked(List<NotificationChannel> channels) {
+        for (NotificationChannel channel : channels) {
+            if (channel.getImportance() != IMPORTANCE_NONE) {
+                return false;
+            }
+        }
+        return true;
+    }
+
     protected CharSequence getSubTitle(String packageName, int uid) {
         final int channelCount = mNotificationBackend.getChannelCount(packageName, uid);
 
diff --git a/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java b/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java
index 3ecfcae..590afd2 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java
@@ -135,23 +135,19 @@
                 // Deferred setup is never dismissible.
                 break;
             case VIEW_TYPE_HALF_WIDTH:
-                initDismissalActions(holder, card, R.id.content);
+                initDismissalActions(holder, card);
                 break;
             default:
-                initDismissalActions(holder, card, R.id.slice_view);
+                initDismissalActions(holder, card);
+        }
+
+        if (card.isPendingDismiss()) {
+            flipCardToDismissalView(holder);
+            mFlippedCardSet.add(holder);
         }
     }
 
-    private void initDismissalActions(RecyclerView.ViewHolder holder, ContextualCard card,
-            int initialViewId) {
-        // initialView is the first view in the ViewFlipper.
-        final View initialView = holder.itemView.findViewById(initialViewId);
-        initialView.setOnLongClickListener(v -> {
-            flipCardToDismissalView(holder);
-            mFlippedCardSet.add(holder);
-            return true;
-        });
-
+    private void initDismissalActions(RecyclerView.ViewHolder holder, ContextualCard card) {
         final Button btnKeep = holder.itemView.findViewById(R.id.keep);
         btnKeep.setOnClickListener(v -> {
             mFlippedCardSet.remove(holder);
diff --git a/src/com/android/settings/homepage/contextualcards/slices/SwipeDismissalDelegate.java b/src/com/android/settings/homepage/contextualcards/slices/SwipeDismissalDelegate.java
index a4186b0..3564189 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/SwipeDismissalDelegate.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/SwipeDismissalDelegate.java
@@ -18,31 +18,74 @@
 
 import android.content.Context;
 import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.RectF;
+import android.graphics.drawable.Drawable;
+import android.view.View;
+import android.widget.ViewFlipper;
 
 import androidx.annotation.NonNull;
 import androidx.recyclerview.widget.ItemTouchHelper;
 import androidx.recyclerview.widget.RecyclerView;
 
+import com.android.settings.R;
+import com.android.settings.homepage.contextualcards.ContextualCard;
+
 public class SwipeDismissalDelegate extends ItemTouchHelper.Callback {
 
-    private static final String TAG = "DismissItemTouchHelper";
+    private static final String TAG = "SwipeDismissalDelegate";
 
-    public interface DismissalItemTouchHelperListener {
+    public interface Listener {
         void onSwiped(int position);
     }
 
     private final Context mContext;
-    private final DismissalItemTouchHelperListener mListener;
+    private final SwipeDismissalDelegate.Listener mListener;
+    private final Drawable mIconDelete;
+    private final Paint mBgPaint;
+    private final int mBgCornerRadius;
 
-    public SwipeDismissalDelegate(Context context, DismissalItemTouchHelperListener listener) {
+    public SwipeDismissalDelegate(Context context, SwipeDismissalDelegate.Listener listener) {
         mContext = context;
         mListener = listener;
+        mIconDelete = mContext.getDrawable(R.drawable.ic_delete);
+        mBgPaint = new Paint();
+        mBgPaint.setColor(mContext.getColor(R.color.homepage_card_dismissal_background));
+        mBgCornerRadius = mContext.getResources()
+                .getDimensionPixelSize(R.dimen.homepage_card_corner_radius);
     }
 
+    /**
+     * Determine whether the ability to drag or swipe should be enabled or not.
+     *
+     * Only allow swipe on {@link ContextualCard} built with view type
+     * {@link SliceContextualCardRenderer#VIEW_TYPE_FULL_WIDTH} or
+     * {@link SliceContextualCardRenderer#VIEW_TYPE_HALF_WIDTH}.
+     *
+     * When the dismissal view is displayed, the swipe will also be disabled.
+     */
     @Override
     public int getMovementFlags(@NonNull RecyclerView recyclerView,
             @NonNull RecyclerView.ViewHolder viewHolder) {
-        return 0;
+        switch (viewHolder.getItemViewType()) {
+            case SliceContextualCardRenderer.VIEW_TYPE_FULL_WIDTH:
+            case SliceContextualCardRenderer.VIEW_TYPE_HALF_WIDTH:
+                //TODO(b/129438972): Convert this to a regular view.
+                final ViewFlipper viewFlipper = viewHolder.itemView.findViewById(R.id.view_flipper);
+
+                // As we are using ViewFlipper to switch between the initial view and
+                // dismissal view, here we are making sure the current displayed view is the
+                // initial view of either slice full card or half card, and only allow swipe on
+                // these two types.
+                if (viewFlipper.getCurrentView().getId() != getInitialViewId(viewHolder)) {
+                    // Disable swiping when we are in the dismissal view
+                    return 0;
+                }
+                return makeMovementFlags(0 /*dragFlags*/,
+                        ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT /*swipeFlags*/);
+            default:
+                return 0;
+        }
     }
 
     @Override
@@ -62,5 +105,36 @@
             @NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState,
             boolean isCurrentlyActive) {
         super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
+
+        final View itemView = viewHolder.itemView;
+        final int iconMargin = mContext.getResources()
+                .getDimensionPixelSize(R.dimen.homepage_card_dismissal_side_margin);
+        final int iconTop =
+                itemView.getTop() + (itemView.getHeight() - mIconDelete.getIntrinsicHeight()) / 2;
+        final int iconBottom = iconTop + mIconDelete.getIntrinsicHeight();
+
+        if (dX > 0) { //swipe to the right
+            final int iconLeft = itemView.getLeft() + iconMargin;
+            final int iconRight = iconLeft + mIconDelete.getIntrinsicWidth();
+            final RectF rect = new RectF(itemView.getLeft(), itemView.getTop(),
+                    itemView.getLeft() + ((int) dX) + mBgCornerRadius, itemView.getBottom());
+            mIconDelete.setBounds(iconLeft, iconTop, iconRight, iconBottom);
+            c.drawRoundRect(rect, mBgCornerRadius, mBgCornerRadius, mBgPaint);
+        } else if (dX < 0) {
+            final int iconRight = itemView.getRight() - iconMargin;
+            final int iconLeft = iconRight - mIconDelete.getIntrinsicWidth();
+            final RectF rect = new RectF(itemView.getRight() + ((int) dX), itemView.getTop(),
+                    itemView.getRight(), itemView.getBottom());
+            mIconDelete.setBounds(iconLeft, iconTop, iconRight, iconBottom);
+            c.drawRoundRect(rect, mBgCornerRadius, mBgCornerRadius, mBgPaint);
+        }
+        mIconDelete.draw(c);
+    }
+
+    private int getInitialViewId(RecyclerView.ViewHolder viewHolder) {
+        if (viewHolder.getItemViewType() == SliceContextualCardRenderer.VIEW_TYPE_HALF_WIDTH) {
+            return R.id.content;
+        }
+        return R.id.slice_view;
     }
 }
\ No newline at end of file
diff --git a/src/com/android/settings/media/MediaOutputSlice.java b/src/com/android/settings/media/MediaOutputSlice.java
index e76bc88..53324e9 100644
--- a/src/com/android/settings/media/MediaOutputSlice.java
+++ b/src/com/android/settings/media/MediaOutputSlice.java
@@ -18,11 +18,11 @@
 
 import static com.android.settings.slices.CustomSliceRegistry.MEDIA_OUTPUT_SLICE_URI;
 
-import android.annotation.ColorInt;
 import android.app.PendingIntent;
 import android.bluetooth.BluetoothAdapter;
 import android.content.Context;
 import android.content.Intent;
+import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.text.TextUtils;
 import android.util.Log;
@@ -82,10 +82,9 @@
         }
 
         final List<MediaDevice> devices = getMediaDevices();
-        @ColorInt final int color = Utils.getColorAccentDefaultColor(mContext);
 
         final MediaDevice connectedDevice = getWorker().getCurrentConnectedMediaDevice();
-        final ListBuilder listBuilder = buildActiveDeviceHeader(color, connectedDevice);
+        final ListBuilder listBuilder = buildActiveDeviceHeader(connectedDevice);
 
         for (MediaDevice device : devices) {
             if (!TextUtils.equals(connectedDevice.getId(), device.getId())) {
@@ -96,9 +95,9 @@
         return listBuilder.build();
     }
 
-    private ListBuilder buildActiveDeviceHeader(@ColorInt int color, MediaDevice device) {
+    private ListBuilder buildActiveDeviceHeader(MediaDevice device) {
         final String title = device.getName();
-        final IconCompat icon = IconCompat.createWithResource(mContext, device.getIcon());
+        final IconCompat icon = getDeviceIconCompat(device);
 
         final PendingIntent broadcastAction =
                 getBroadcastIntent(mContext, device.getId(), device.hashCode());
@@ -107,7 +106,7 @@
 
         final ListBuilder listBuilder = new ListBuilder(mContext, MEDIA_OUTPUT_SLICE_URI,
                 ListBuilder.INFINITY)
-                .setAccentColor(color)
+                .setAccentColor(COLOR_NOT_TINTED)
                 .addRow(new ListBuilder.RowBuilder()
                         .setTitleItem(icon, ListBuilder.ICON_IMAGE)
                         .setTitle(title)
@@ -117,6 +116,17 @@
         return listBuilder;
     }
 
+    private IconCompat getDeviceIconCompat(MediaDevice device) {
+        Drawable drawable = device.getIcon();
+        if (drawable == null) {
+            Log.d(TAG, "getDeviceIconCompat() device : " + device.getName() + ", drawable is null");
+            // Use default Bluetooth device icon to handle getIcon() is null case.
+            drawable = mContext.getDrawable(com.android.internal.R.drawable.ic_bt_headphones_a2dp);
+        }
+
+        return Utils.createIconWithDrawable(drawable);
+    }
+
     private MediaDeviceUpdateWorker getWorker() {
         if (mWorker == null) {
             mWorker = (MediaDeviceUpdateWorker) SliceBackgroundWorker.getInstance(getUri());
@@ -136,7 +146,8 @@
         final String title = device.getName();
         final PendingIntent broadcastAction =
                 getBroadcastIntent(mContext, device.getId(), device.hashCode());
-        final IconCompat deviceIcon = IconCompat.createWithResource(mContext, device.getIcon());
+        final IconCompat deviceIcon = getDeviceIconCompat(device);
+
         final ListBuilder.RowBuilder rowBuilder = new ListBuilder.RowBuilder()
                 .setTitleItem(deviceIcon, ListBuilder.ICON_IMAGE)
                 .setPrimaryAction(SliceAction.create(broadcastAction, deviceIcon,
diff --git a/src/com/android/settings/notification/AppBubbleNotificationSettings.java b/src/com/android/settings/notification/AppBubbleNotificationSettings.java
new file mode 100644
index 0000000..17909c0
--- /dev/null
+++ b/src/com/android/settings/notification/AppBubbleNotificationSettings.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2019 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.settings.SettingsEnums;
+import android.content.Context;
+import android.provider.SearchIndexableResource;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.settings.R;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.search.SearchIndexable;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+@SearchIndexable
+public class AppBubbleNotificationSettings extends NotificationSettingsBase {
+    private static final String TAG = "AppBubNotiSettings";
+
+    @Override
+    public int getMetricsCategory() {
+        return SettingsEnums.APP_BUBBLE_SETTINGS;
+    }
+
+    @Override
+    protected String getLogTag() {
+        return TAG;
+    }
+
+    @Override
+    protected int getPreferenceScreenResId() {
+        return R.xml.app_bubble_notification_settings;
+    }
+
+    @Override
+    protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
+        mControllers = getPreferenceControllers(context, this);
+        return new ArrayList<>(mControllers);
+    }
+
+    protected static List<NotificationPreferenceController> getPreferenceControllers(
+            Context context, AppBubbleNotificationSettings fragment) {
+        List<NotificationPreferenceController> controllers = new ArrayList<>();
+        controllers.add(new HeaderPreferenceController(context, fragment));
+        controllers.add(new BubblePreferenceController(context, new NotificationBackend()));
+        return controllers;
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+
+        if (mUid < 0 || TextUtils.isEmpty(mPkg) || mPkgInfo == null) {
+            Log.w(TAG, "Missing package or uid or packageinfo");
+            finish();
+            return;
+        }
+
+        for (NotificationPreferenceController controller : mControllers) {
+            controller.onResume(mAppRow, mChannel, mChannelGroup, mSuspendedAppsAdmin);
+            controller.displayPreference(getPreferenceScreen());
+        }
+        updatePreferenceStates();
+    }
+
+    /**
+     * For Search.
+     */
+    public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+            new BaseSearchIndexProvider() {
+                @Override
+                public List<SearchIndexableResource> getXmlResourcesToIndex(
+                        Context context, boolean enabled) {
+                    final SearchIndexableResource sir = new SearchIndexableResource(context);
+                    sir.xmlResId = R.xml.app_bubble_notification_settings;
+                    return Arrays.asList(sir);
+                }
+
+                @Override
+                public List<AbstractPreferenceController> createPreferenceControllers(Context
+                        context) {
+                    return new ArrayList<>(AppBubbleNotificationSettings.getPreferenceControllers(
+                            context, null));
+                }
+            };
+}
diff --git a/src/com/android/settings/notification/AppNotificationSettings.java b/src/com/android/settings/notification/AppNotificationSettings.java
index 3ccca00..24d85e2 100644
--- a/src/com/android/settings/notification/AppNotificationSettings.java
+++ b/src/com/android/settings/notification/AppNotificationSettings.java
@@ -152,7 +152,7 @@
         mControllers.add(new DescriptionPreferenceController(context));
         mControllers.add(new NotificationsOffPreferenceController(context));
         mControllers.add(new DeletedChannelsPreferenceController(context, mBackend));
-        mControllers.add(new BubblePreferenceController(context, mBackend));
+        mControllers.add(new BubbleSummaryPreferenceController(context, mBackend));
         return new ArrayList<>(mControllers);
     }
 
diff --git a/src/com/android/settings/notification/BubbleNotificationPreferenceController.java b/src/com/android/settings/notification/BubbleNotificationPreferenceController.java
index caba7d9..83e73e9 100644
--- a/src/com/android/settings/notification/BubbleNotificationPreferenceController.java
+++ b/src/com/android/settings/notification/BubbleNotificationPreferenceController.java
@@ -56,7 +56,7 @@
     @Override
     public void displayPreference(PreferenceScreen screen) {
         super.displayPreference(screen);
-        Preference preference = screen.findPreference(NOTIFICATION_BUBBLES);
+        Preference preference = screen.findPreference(getPreferenceKey());
         if (preference != null) {
             mSettingObserver = new SettingObserver(preference);
         }
diff --git a/src/com/android/settings/notification/BubbleNotificationSettings.java b/src/com/android/settings/notification/BubbleNotificationSettings.java
new file mode 100644
index 0000000..7044293
--- /dev/null
+++ b/src/com/android/settings/notification/BubbleNotificationSettings.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2019 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.settings.SettingsEnums;
+import android.content.Context;
+import android.provider.SearchIndexableResource;
+
+import com.android.settings.R;
+import com.android.settings.core.OnActivityResultListener;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settingslib.search.SearchIndexable;
+
+import java.util.Arrays;
+import java.util.List;
+
+@SearchIndexable
+public class BubbleNotificationSettings extends DashboardFragment implements
+        OnActivityResultListener {
+    private static final String TAG = "BubbleNotiSettings";
+
+    @Override
+    public int getMetricsCategory() {
+        return SettingsEnums.BUBBLE_SETTINGS;
+    }
+
+    @Override
+    protected String getLogTag() {
+        return TAG;
+    }
+
+    @Override
+    protected int getPreferenceScreenResId() {
+        return R.xml.bubble_notification_settings;
+    }
+
+    /**
+     * For Search.
+     */
+    public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+            new BaseSearchIndexProvider() {
+                @Override
+                public List<SearchIndexableResource> getXmlResourcesToIndex(
+                        Context context, boolean enabled) {
+                    final SearchIndexableResource sir = new SearchIndexableResource(context);
+                    sir.xmlResId = R.xml.bubble_notification_settings;
+                    return Arrays.asList(sir);
+                }
+            };
+}
diff --git a/src/com/android/settings/notification/BubblePreferenceController.java b/src/com/android/settings/notification/BubblePreferenceController.java
index 5b3be44..5dab374 100644
--- a/src/com/android/settings/notification/BubblePreferenceController.java
+++ b/src/com/android/settings/notification/BubblePreferenceController.java
@@ -21,6 +21,7 @@
 import android.content.Context;
 import android.provider.Settings;
 
+import com.android.settings.R;
 import com.android.settings.core.PreferenceControllerMixin;
 import com.android.settingslib.RestrictedSwitchPreference;
 
@@ -74,6 +75,8 @@
                 pref.setEnabled(isChannelConfigurable() && !pref.isDisabledByAdmin());
             } else {
                 pref.setChecked(mAppRow.allowBubbles);
+                pref.setSummary(mContext.getString(
+                        R.string.bubbles_app_toggle_summary, mAppRow.label));
             }
         }
     }
diff --git a/src/com/android/settings/notification/BubbleSummaryNotificationPreferenceController.java b/src/com/android/settings/notification/BubbleSummaryNotificationPreferenceController.java
new file mode 100644
index 0000000..e26d9a8
--- /dev/null
+++ b/src/com/android/settings/notification/BubbleSummaryNotificationPreferenceController.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2019 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 static android.provider.Settings.Secure.NOTIFICATION_BUBBLES;
+
+import android.content.Context;
+import android.provider.Settings;
+
+import com.android.settings.R;
+import com.android.settings.core.BasePreferenceController;
+
+import androidx.annotation.VisibleForTesting;
+
+public class BubbleSummaryNotificationPreferenceController extends BasePreferenceController {
+
+    @VisibleForTesting
+    static final int ON = 1;
+
+    public BubbleSummaryNotificationPreferenceController(Context context, String preferenceKey) {
+        super(context, preferenceKey);
+    }
+
+    @Override
+    public CharSequence getSummary() {
+        return mContext.getString(
+                areBubblesEnabled() ? R.string.switch_on_text : R.string.switch_off_text);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return AVAILABLE;
+    }
+
+    private boolean areBubblesEnabled() {
+        return Settings.Secure.getInt(mContext.getContentResolver(),
+                NOTIFICATION_BUBBLES, ON) == ON;
+    }
+}
diff --git a/src/com/android/settings/notification/BubbleSummaryPreferenceController.java b/src/com/android/settings/notification/BubbleSummaryPreferenceController.java
new file mode 100644
index 0000000..708bbcd
--- /dev/null
+++ b/src/com/android/settings/notification/BubbleSummaryPreferenceController.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2019 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 static android.provider.Settings.Secure.NOTIFICATION_BUBBLES;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.os.Bundle;
+import android.provider.Settings;
+
+import com.android.settings.R;
+import com.android.settings.applications.AppInfoBase;
+import com.android.settings.core.SubSettingLauncher;
+
+import androidx.preference.Preference;
+
+public class BubbleSummaryPreferenceController extends NotificationPreferenceController {
+
+    private static final String KEY = "bubble_link_pref";
+    private static final int SYSTEM_WIDE_ON = 1;
+    private static final int SYSTEM_WIDE_OFF = 0;
+
+    public BubbleSummaryPreferenceController(Context context, NotificationBackend backend) {
+        super(context, backend);
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return KEY;
+    }
+
+    @Override
+    public boolean isAvailable() {
+        if (!super.isAvailable()) {
+            return false;
+        }
+        if (mAppRow == null && mChannel == null) {
+            return false;
+        }
+        if (Settings.Secure.getInt(mContext.getContentResolver(),
+                NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON) == SYSTEM_WIDE_OFF) {
+            return false;
+        }
+        if (mChannel != null) {
+            if (isDefaultChannel()) {
+                return true;
+            } else {
+                return mAppRow == null ? false : mAppRow.allowBubbles;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        super.updateState(preference);
+
+        if (mAppRow != null) {
+            Bundle args = new Bundle();
+            args.putString(AppInfoBase.ARG_PACKAGE_NAME, mAppRow.pkg);
+            args.putInt(AppInfoBase.ARG_PACKAGE_UID, mAppRow.uid);
+
+            preference.setIntent(new SubSettingLauncher(mContext)
+                    .setDestination(AppBubbleNotificationSettings.class.getName())
+                    .setArguments(args)
+                    .setSourceMetricsCategory(
+                            SettingsEnums.NOTIFICATION_APP_NOTIFICATION)
+                    .toIntent());
+        }
+    }
+
+    @Override
+    public CharSequence getSummary() {
+        boolean canBubble = false;
+        if (mAppRow != null) {
+            if (mChannel != null) {
+                canBubble |= mChannel.canBubble();
+            } else {
+               canBubble |= mAppRow.allowBubbles;
+            }
+        }
+        return mContext.getString(canBubble ? R.string.switch_on_text : R.string.switch_off_text);
+    }
+}
diff --git a/src/com/android/settings/notification/NotificationPreferenceController.java b/src/com/android/settings/notification/NotificationPreferenceController.java
index 3f535fb..d2b7c43 100644
--- a/src/com/android/settings/notification/NotificationPreferenceController.java
+++ b/src/com/android/settings/notification/NotificationPreferenceController.java
@@ -126,6 +126,11 @@
                 return mChannel.getImportance() == IMPORTANCE_NONE;
             }
 
+            if (mChannel.isImportanceLockedByOEM()
+                    || mChannel.isImportanceLockedByCriticalDeviceFunction()) {
+                return false;
+            }
+
             return mChannel.isBlockableSystem() || !mAppRow.systemApp
                     || mChannel.getImportance() == IMPORTANCE_NONE;
         }
diff --git a/src/com/android/settings/notification/SoundPreferenceController.java b/src/com/android/settings/notification/SoundPreferenceController.java
index e53a560..73cbad3 100644
--- a/src/com/android/settings/notification/SoundPreferenceController.java
+++ b/src/com/android/settings/notification/SoundPreferenceController.java
@@ -16,10 +16,14 @@
 
 package com.android.settings.notification;
 
+import static android.media.AudioAttributes.USAGE_ALARM;
+import static android.media.AudioAttributes.USAGE_NOTIFICATION_RINGTONE;
+
 import android.app.NotificationChannel;
 import android.app.NotificationManager;
 import android.content.Context;
 import android.content.Intent;
+import android.media.RingtoneManager;
 import android.net.Uri;
 import android.preference.PreferenceManager;
 
@@ -91,6 +95,16 @@
     public boolean handlePreferenceTreeClick(Preference preference) {
         if (KEY_SOUND.equals(preference.getKey()) && mFragment != null) {
             NotificationSoundPreference pref = (NotificationSoundPreference) preference;
+            if (mChannel != null && mChannel.getAudioAttributes() != null) {
+                if (USAGE_ALARM == mChannel.getAudioAttributes().getUsage()) {
+                    pref.setRingtoneType(RingtoneManager.TYPE_ALARM);
+                } else if (USAGE_NOTIFICATION_RINGTONE
+                        == mChannel.getAudioAttributes().getUsage()) {
+                    pref.setRingtoneType(RingtoneManager.TYPE_RINGTONE);
+                } else {
+                    pref.setRingtoneType(RingtoneManager.TYPE_NOTIFICATION);
+                }
+            }
             pref.onPrepareRingtonePickerIntent(pref.getIntent());
             mFragment.startActivityForResult(preference.getIntent(), CODE);
             return true;
diff --git a/src/com/android/settings/notification/VibrateWhenRingPreferenceController.java b/src/com/android/settings/notification/VibrateWhenRingPreferenceController.java
index cbf909f..b043cb1 100644
--- a/src/com/android/settings/notification/VibrateWhenRingPreferenceController.java
+++ b/src/com/android/settings/notification/VibrateWhenRingPreferenceController.java
@@ -39,6 +39,8 @@
 public class VibrateWhenRingPreferenceController extends TogglePreferenceController
         implements LifecycleObserver, OnResume, OnPause {
 
+    /** Flag for whether or not to apply ramping ringer on incoming phone calls. */
+    private static final String RAMPING_RINGER_ENABLED = "ramping_ringer_enabled";
     private static final String KEY_VIBRATE_WHEN_RINGING = "vibrate_when_ringing";
     private final int DEFAULT_VALUE = 0;
     private final int NOTIFICATION_VIBRATE_WHEN_RINGING = 1;
@@ -130,8 +132,8 @@
     }
 
     private boolean isRampingRingerEnabled() {
-        return DeviceConfig.getBoolean(DeviceConfig.Telephony.NAMESPACE,
-                DeviceConfig.Telephony.RAMPING_RINGER_ENABLED, false);
+        return DeviceConfig.getBoolean(
+                DeviceConfig.NAMESPACE_TELEPHONY, RAMPING_RINGER_ENABLED, false);
     }
 
 }
diff --git a/src/com/android/settings/password/ChooseLockGeneric.java b/src/com/android/settings/password/ChooseLockGeneric.java
index 4a758be..580c7ba 100644
--- a/src/com/android/settings/password/ChooseLockGeneric.java
+++ b/src/com/android/settings/password/ChooseLockGeneric.java
@@ -183,6 +183,7 @@
             super.onCreate(savedInstanceState);
             final Activity activity = getActivity();
             if (!Utils.isDeviceProvisioned(activity) && !canRunBeforeDeviceProvisioned()) {
+                Log.i(TAG, "Refusing to start because device is not provisioned");
                 activity.finish();
                 return;
             }
diff --git a/src/com/android/settings/privacy/PermissionBarChartPreferenceController.java b/src/com/android/settings/privacy/PermissionBarChartPreferenceController.java
index b47ad9c..9358392 100644
--- a/src/com/android/settings/privacy/PermissionBarChartPreferenceController.java
+++ b/src/com/android/settings/privacy/PermissionBarChartPreferenceController.java
@@ -16,6 +16,10 @@
 
 package com.android.settings.privacy;
 
+import static android.Manifest.permission_group.CAMERA;
+import static android.Manifest.permission_group.LOCATION;
+import static android.Manifest.permission_group.MICROPHONE;
+
 import static com.android.settingslib.widget.BarChartPreference.MAXIMUM_BAR_VIEWS;
 
 import static java.util.concurrent.TimeUnit.DAYS;
@@ -131,8 +135,28 @@
 
     @Override
     public void onPermissionUsageResult(@NonNull List<RuntimePermissionUsageInfo> usageInfos) {
-        usageInfos.sort(Comparator.comparingInt(
-                RuntimePermissionUsageInfo::getAppAccessCount).reversed());
+        usageInfos.sort((x, y) -> {
+            int usageDiff = y.getAppAccessCount() - x.getAppAccessCount();
+            if (usageDiff != 0) {
+                return usageDiff;
+            }
+            String xName = x.getName();
+            String yName = y.getName();
+            if (xName.equals(LOCATION)) {
+                return -1;
+            } else if (yName.equals(LOCATION)) {
+                return 1;
+            } else if (xName.equals(MICROPHONE)) {
+                return -1;
+            } else if (yName.equals(MICROPHONE)) {
+                return 1;
+            } else if (xName.equals(CAMERA)) {
+                return -1;
+            } else if (yName.equals(CAMERA)) {
+                return 1;
+            }
+            return x.getName().compareTo(y.getName());
+        });
 
         // If the result is different, we need to update bar views.
         if (!areSamePermissionGroups(usageInfos)) {
@@ -176,6 +200,7 @@
             barViewInfos[index].setClickListener((View v) -> {
                 final Intent intent = new Intent(Intent.ACTION_REVIEW_PERMISSION_USAGE);
                 intent.putExtra(Intent.EXTRA_PERMISSION_GROUP_NAME, permissionGroupInfo.getName());
+                intent.putExtra(Intent.EXTRA_DURATION_MILLIS, DAYS.toMillis(1));
                 mContext.startActivity(intent);
             });
         }
diff --git a/src/com/android/settings/sim/SimDialogActivity.java b/src/com/android/settings/sim/SimDialogActivity.java
index 13148c8..487dace 100644
--- a/src/com/android/settings/sim/SimDialogActivity.java
+++ b/src/com/android/settings/sim/SimDialogActivity.java
@@ -254,7 +254,7 @@
                 builder.setTitle(R.string.select_sim_for_calls);
                 break;
             case SMS_PICK:
-                builder.setTitle(R.string.sim_card_select_title);
+                builder.setTitle(R.string.select_sim_for_sms);
                 break;
             default:
                 throw new IllegalArgumentException("Invalid dialog type "
diff --git a/src/com/android/settings/sim/SimSelectNotification.java b/src/com/android/settings/sim/SimSelectNotification.java
index 4f3b9bc..a1e942a 100644
--- a/src/com/android/settings/sim/SimSelectNotification.java
+++ b/src/com/android/settings/sim/SimSelectNotification.java
@@ -30,6 +30,7 @@
 import android.content.Intent;
 import android.content.res.Resources;
 import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
 
 import com.android.settings.R;
 import com.android.settings.Settings.SimSettingsActivity;
@@ -45,6 +46,9 @@
 
     @Override
     public void onReceive(Context context, Intent intent) {
+        if (!TelephonyManager.ACTION_PRIMARY_SUBSCRIPTION_LIST_CHANGED.equals(intent.getAction())) {
+            return;
+        }
         // Cancel any previous notifications
         cancelNotification(context);
         // Create a notification to tell the user that some defaults are missing
diff --git a/src/com/android/settings/system/SystemDashboardFragment.java b/src/com/android/settings/system/SystemDashboardFragment.java
index 5c642b2..3ab31e3 100644
--- a/src/com/android/settings/system/SystemDashboardFragment.java
+++ b/src/com/android/settings/system/SystemDashboardFragment.java
@@ -20,12 +20,14 @@
 import android.os.Bundle;
 import android.provider.SearchIndexableResource;
 
+import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceGroup;
 import androidx.preference.PreferenceScreen;
 
 import com.android.settings.R;
 import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.search.Indexable;
 import com.android.settingslib.search.SearchIndexable;
@@ -40,6 +42,8 @@
 
     private static final String KEY_RESET = "reset_dashboard";
 
+    public static final String EXTRA_SHOW_AWARE_DISABLED = "show_aware_dialog_disabled";
+
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
@@ -49,6 +53,17 @@
         if (getVisiblePreferenceCount(screen) == screen.getInitialExpandedChildrenCount() + 1) {
             screen.setInitialExpandedChildrenCount(Integer.MAX_VALUE);
         }
+
+        showRestrictionDialog();
+    }
+
+    @VisibleForTesting
+    public void showRestrictionDialog() {
+        final Bundle args = getArguments();
+        if (args != null && args.getBoolean(EXTRA_SHOW_AWARE_DISABLED, false)) {
+            FeatureFactory.getFactory(getContext()).getAwareFeatureProvider()
+                    .showRestrictionDialog(this);
+        }
     }
 
     @Override
diff --git a/src/com/android/settings/vpn2/ConfigDialog.java b/src/com/android/settings/vpn2/ConfigDialog.java
index 07e957d..9f2176c 100644
--- a/src/com/android/settings/vpn2/ConfigDialog.java
+++ b/src/com/android/settings/vpn2/ConfigDialog.java
@@ -143,6 +143,7 @@
         }
         mMppe.setChecked(mProfile.mppe);
         mL2tpSecret.setText(mProfile.l2tpSecret);
+        mL2tpSecret.setTextAppearance(android.R.style.TextAppearance_DeviceDefault_Medium);
         mIpsecIdentifier.setText(mProfile.ipsecIdentifier);
         mIpsecSecret.setText(mProfile.ipsecSecret);
         loadCertificates(mIpsecUserCert, Credentials.USER_PRIVATE_KEY, 0, mProfile.ipsecUserCert);
@@ -152,6 +153,7 @@
                 R.string.vpn_no_server_cert, mProfile.ipsecServerCert);
         mSaveLogin.setChecked(mProfile.saveLogin);
         mAlwaysOnVpn.setChecked(mProfile.key.equals(VpnUtils.getLockdownVpn()));
+        mPassword.setTextAppearance(android.R.style.TextAppearance_DeviceDefault_Medium);
 
         // Hide lockdown VPN on devices that require IMS authentication
         if (SystemProperties.getBoolean("persist.radio.imsregrequired", false)) {
diff --git a/src/com/android/settings/wallpaper/WallpaperSuggestionActivity.java b/src/com/android/settings/wallpaper/WallpaperSuggestionActivity.java
index 14564b1..0713872 100644
--- a/src/com/android/settings/wallpaper/WallpaperSuggestionActivity.java
+++ b/src/com/android/settings/wallpaper/WallpaperSuggestionActivity.java
@@ -28,10 +28,18 @@
 
 import com.android.settings.R;
 import com.android.settings.core.SubSettingLauncher;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.search.Indexable;
+import com.android.settings.search.SearchIndexableRaw;
+import com.android.settingslib.search.SearchIndexable;
 
 import com.google.android.setupcompat.util.WizardManagerHelper;
 
-public class WallpaperSuggestionActivity extends Activity {
+import java.util.ArrayList;
+import java.util.List;
+
+@SearchIndexable
+public class WallpaperSuggestionActivity extends Activity implements Indexable {
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -79,4 +87,30 @@
         return context.getResources().getBoolean(
                 com.android.internal.R.bool.config_enableWallpaperService);
     }
+
+    public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+            new BaseSearchIndexProvider() {
+                private static final String SUPPORT_SEARCH_INDEX_KEY = "wallpaper_type";
+
+                @Override
+                public List<SearchIndexableRaw> getRawDataToIndex(Context context,
+                        boolean enabled) {
+
+                    final List<SearchIndexableRaw> result = new ArrayList<>();
+
+                    SearchIndexableRaw data = new SearchIndexableRaw(context);
+                    data.title = context.getString(R.string.wallpaper_settings_fragment_title);
+                    data.screenTitle = context.getString(
+                            R.string.wallpaper_settings_fragment_title);
+                    data.intentTargetPackage = context.getString(
+                            R.string.config_wallpaper_picker_package);
+                    data.intentTargetClass = context.getString(
+                            R.string.config_wallpaper_picker_class);
+                    data.intentAction = Intent.ACTION_MAIN;
+                    data.key = SUPPORT_SEARCH_INDEX_KEY;
+                    result.add(data);
+
+                    return result;
+                }
+            };
 }
diff --git a/src/com/android/settings/wallpaper/WallpaperTypeSettings.java b/src/com/android/settings/wallpaper/WallpaperTypeSettings.java
index 0e0f8df..2d4a16f 100644
--- a/src/com/android/settings/wallpaper/WallpaperTypeSettings.java
+++ b/src/com/android/settings/wallpaper/WallpaperTypeSettings.java
@@ -17,21 +17,11 @@
 package com.android.settings.wallpaper;
 
 import android.app.settings.SettingsEnums;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
 
 import com.android.settings.R;
 import com.android.settings.dashboard.DashboardFragment;
-import com.android.settings.search.BaseSearchIndexProvider;
-import com.android.settings.search.SearchIndexableRaw;
-import com.android.settingslib.search.SearchIndexable;
 
-import java.util.ArrayList;
-import java.util.List;
 
-@SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
 public class WallpaperTypeSettings extends DashboardFragment {
     private static final String TAG = "WallpaperTypeSettings";
 
@@ -54,42 +44,4 @@
     protected int getPreferenceScreenResId() {
         return R.xml.wallpaper_settings;
     }
-
-    public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
-        new BaseSearchIndexProvider() {
-            @Override
-            public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) {
-                final List<SearchIndexableRaw> result = new ArrayList<>();
-
-                final Intent intent = new Intent(Intent.ACTION_SET_WALLPAPER);
-                final PackageManager pm = context.getPackageManager();
-                final List<ResolveInfo> rList = pm.queryIntentActivities(intent,
-                        PackageManager.MATCH_DEFAULT_ONLY);
-
-                // Add indexable data for package that is in config_wallpaper_picker_package
-                final String wallpaperPickerPackage =
-                        context.getString(R.string.config_wallpaper_picker_package);
-                for (ResolveInfo info : rList) {
-                    if (!wallpaperPickerPackage.equals(info.activityInfo.packageName)) {
-                        continue;
-                    }
-                    CharSequence label = info.loadLabel(pm);
-                    if (label == null) {
-                        label = info.activityInfo.packageName;
-                    }
-                    final SearchIndexableRaw data = new SearchIndexableRaw(context);
-                    data.title = label.toString();
-                    data.key = "wallpaper_type_settings";
-                    data.screenTitle = context.getResources().getString(
-                            R.string.wallpaper_settings_fragment_title);
-                    data.intentAction = Intent.ACTION_SET_WALLPAPER;
-                    data.intentTargetPackage = info.activityInfo.packageName;
-                    data.intentTargetClass = info.activityInfo.name;
-                    data.keywords = context.getString(R.string.keywords_wallpaper);
-                    result.add(data);
-                }
-
-                return result;
-            }
-        };
 }
diff --git a/src/com/android/settings/wifi/NetworkRequestDialogFragment.java b/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
index e9057e6..2a7ac17 100644
--- a/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
+++ b/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
@@ -138,9 +138,9 @@
                 .setOnItemClickListener(
                         (parent, view, position, id) -> this.onClick(dialog, position));
 
-        // Don't dismiss dialog when touching outside. User report it is easy to touch outside.
-        // This causes dialog to close. Which is concerned as a bad UX (b/128877712).
-        dialog.setCanceledOnTouchOutside(false);
+        // Don't dismiss dialog when touching outside. User reports it is easy to touch outside.
+        // This causes dialog to close.
+        setCancelable(false);
 
         dialog.setOnShowListener((dialogInterface) -> {
             // Replace NeutralButton onClickListener to avoid closing dialog
diff --git a/src/com/android/settings/wifi/WifiConfigController.java b/src/com/android/settings/wifi/WifiConfigController.java
index 0887fc5..ac11510 100644
--- a/src/com/android/settings/wifi/WifiConfigController.java
+++ b/src/com/android/settings/wifi/WifiConfigController.java
@@ -55,6 +55,7 @@
 import android.widget.CompoundButton;
 import android.widget.CompoundButton.OnCheckedChangeListener;
 import android.widget.EditText;
+import android.widget.ImageButton;
 import android.widget.ScrollView;
 import android.widget.Spinner;
 import android.widget.TextView;
@@ -64,6 +65,7 @@
 import com.android.settings.ProxySelector;
 import com.android.settings.R;
 import com.android.settings.wifi.details.WifiPrivacyPreferenceController;
+import com.android.settings.wifi.dpp.WifiDppUtils;
 import com.android.settingslib.Utils;
 import com.android.settingslib.utils.ThreadUtils;
 import com.android.settingslib.wifi.AccessPoint;
@@ -129,6 +131,8 @@
     @VisibleForTesting
     int mAccessPointSecurity;
     private TextView mPasswordView;
+    private ImageButton mSsidScanButton;
+    private ImageButton mPasswordScanButton;
 
     private String mUnspecifiedCertString;
     private String mMultipleCertSetString;
@@ -239,6 +243,8 @@
         mDoNotValidateEapServerString =
             mContext.getString(R.string.wifi_do_not_validate_eap_server);
 
+        mSsidScanButton = (ImageButton) mView.findViewById(R.id.ssid_scanner_button);
+        mPasswordScanButton = (ImageButton) mView.findViewById(R.id.password_scanner_button);
         mDialogContainer = mView.findViewById(R.id.dialog_scrollview);
         mIpSettingsSpinner = (Spinner) mView.findViewById(R.id.ip_settings);
         mIpSettingsSpinner.setOnItemSelectedListener(this);
@@ -264,6 +270,7 @@
         if (mAccessPoint == null) { // new network
             configureSecuritySpinner();
             mConfigUi.setSubmitButton(res.getString(R.string.wifi_save));
+            mPasswordScanButton.setVisibility(View.GONE);
         } else {
             mConfigUi.setTitle(mAccessPoint.getTitle());
 
@@ -408,6 +415,11 @@
                     mConfigUi.setForgetButton(res.getString(R.string.wifi_forget));
                 }
             }
+
+            if (!WifiDppUtils.isSupportEnrolleeQrCodeScanner(mContext, mAccessPointSecurity)) {
+                mPasswordScanButton.setVisibility(View.GONE);
+            }
+            mSsidScanButton.setVisibility(View.GONE);
         }
 
         if (!isSplitSystemUser()) {
@@ -1444,6 +1456,12 @@
             // Convert menu position to actual Wi-Fi security type
             mAccessPointSecurity = mSecurityInPosition[position];
             showSecurityFields();
+
+            if (WifiDppUtils.isSupportEnrolleeQrCodeScanner(mContext, mAccessPointSecurity)) {
+                mSsidScanButton.setVisibility(View.VISIBLE);
+            } else {
+                mSsidScanButton.setVisibility(View.GONE);
+            }
         } else if (parent == mEapMethodSpinner || parent == mEapCaCertSpinner) {
             showSecurityFields();
         } else if (parent == mPhase2Spinner
diff --git a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
index 955525d..92132e8 100644
--- a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
+++ b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
@@ -115,6 +115,8 @@
     @VisibleForTesting
     static final String KEY_SECURITY_PREF = "security";
     @VisibleForTesting
+    static final String KEY_SSID_PREF = "ssid";
+    @VisibleForTesting
     static final String KEY_MAC_ADDRESS_PREF = "mac_address";
     @VisibleForTesting
     static final String KEY_IP_ADDRESS_PREF = "ip_address";
@@ -158,6 +160,7 @@
     private final WifiTracker mWifiTracker;
     private final MetricsFeatureProvider mMetricsFeatureProvider;
     private boolean mIsOutOfRange;
+    private boolean mIsEphemeral;
     private boolean mConnected;
     private int mConnectingState;
     private WifiManager.ActionListener mConnectListener;
@@ -170,6 +173,7 @@
     private Preference mRxLinkSpeedPref;
     private Preference mFrequencyPref;
     private Preference mSecurityPref;
+    private Preference mSsidPref;
     private Preference mMacAddressPref;
     private Preference mIpAddressPref;
     private Preference mGatewayPref;
@@ -248,12 +252,14 @@
 
         @Override
         public void onLost(Network network) {
-            // If support detail page for saved network, should update as disconnect but not exit.
-            if (SavedAccessPointsWifiSettings.usingDetailsFragment(mContext)) {
-                return;
-            }
+            final boolean lostCurrentNetwork = network.equals(mNetwork);
+            if (lostCurrentNetwork) {
+                // If support detail page for saved network, should update as disconnect but not
+                // exit. Except for ephemeral network which should not show on saved network list.
+                if (SavedAccessPointsWifiSettings.usingDetailsFragment(mContext) && !mIsEphemeral) {
+                    return;
+                }
 
-            if (network.equals(mNetwork)) {
                 exitActivity();
             }
         }
@@ -347,6 +353,9 @@
             mWifiTracker = null;
         }
         mConnected = mAccessPoint.isActive();
+        // When lost the network connection, WifiInfo/NetworkInfo will be clear. So causes we
+        // could not check if the AccessPoint is ephemeral. Need to cache it in first.
+        mIsEphemeral = mAccessPoint.isEphemeral();
         mConnectingState = STATE_NONE;
         mConnectListener = new WifiManager.ActionListener() {
             @Override
@@ -399,6 +408,7 @@
         mFrequencyPref = screen.findPreference(KEY_FREQUENCY_PREF);
         mSecurityPref = screen.findPreference(KEY_SECURITY_PREF);
 
+        mSsidPref = screen.findPreference(KEY_SSID_PREF);
         mMacAddressPref = screen.findPreference(KEY_MAC_ADDRESS_PREF);
         mIpAddressPref = screen.findPreference(KEY_IP_ADDRESS_PREF);
         mGatewayPref = screen.findPreference(KEY_GATEWAY_PREF);
@@ -497,6 +507,8 @@
         refreshRxSpeed();
         // IP related information
         refreshIpLayerInfo();
+        // SSID Pref
+        refreshSsid();
         // MAC Address Pref
         refreshMacAddress();
     }
@@ -645,6 +657,15 @@
                 R.string.rx_link_speed, mWifiInfo.getRxLinkSpeedMbps()));
     }
 
+    private void refreshSsid() {
+        if (mAccessPoint.isPasspoint() || mAccessPoint.isOsuProvider()) {
+            mSsidPref.setVisible(true);
+            mSsidPref.setSummary(mAccessPoint.getSsidStr());
+        } else {
+            mSsidPref.setVisible(false);
+        }
+    }
+
     private void refreshMacAddress() {
         String macAddress = getMacAddress();
         if (macAddress == null) {
@@ -663,7 +684,8 @@
         }
 
         // return randomized MAC address
-        if (mWifiConfig.macRandomizationSetting == WifiConfiguration.RANDOMIZATION_PERSISTENT) {
+        if (mWifiConfig != null &&
+                mWifiConfig.macRandomizationSetting == WifiConfiguration.RANDOMIZATION_PERSISTENT) {
             return mWifiConfig.getRandomizedMacAddress().toString();
         }
 
@@ -687,6 +709,10 @@
     }
 
     private void refreshButtons() {
+        // Ephemeral network won't be removed permanently, but be putted in blacklist.
+        mButtonsPref.setButton1Text(
+                mIsEphemeral ? R.string.wifi_disconnect_button_text : R.string.forget);
+
         mButtonsPref.setButton1Visible(canForgetNetwork());
         mButtonsPref.setButton2Visible(canSignIntoNetwork());
         mButtonsPref.setButton3Visible(canConnectNetwork());
diff --git a/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java b/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
index ee4cc29..10d1d48 100644
--- a/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
+++ b/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
@@ -140,6 +140,8 @@
                 context);
         privacyController.setWifiConfiguration(mAccessPoint.getConfig());
         privacyController.setIsEphemeral(mAccessPoint.isEphemeral());
+        privacyController.setIsPasspoint(
+                mAccessPoint.isPasspoint() || mAccessPoint.isPasspointConfig());
         controllers.add(privacyController);
 
         return controllers;
diff --git a/src/com/android/settings/wifi/details/WifiPrivacyPreferenceController.java b/src/com/android/settings/wifi/details/WifiPrivacyPreferenceController.java
index a549e21..7bec411 100644
--- a/src/com/android/settings/wifi/details/WifiPrivacyPreferenceController.java
+++ b/src/com/android/settings/wifi/details/WifiPrivacyPreferenceController.java
@@ -41,6 +41,7 @@
     private WifiConfiguration mWifiConfiguration;
     private WifiManager mWifiManager;
     private boolean mIsEphemeral = false;
+    private boolean mIsPasspoint = false;
 
     public WifiPrivacyPreferenceController(Context context) {
         super(context, KEY_WIFI_PRIVACY);
@@ -56,6 +57,10 @@
         mIsEphemeral = isEphemeral;
     }
 
+    public void setIsPasspoint(boolean isPasspoint) {
+        mIsPasspoint = isPasspoint;
+    }
+
     @Override
     public int getAvailabilityStatus() {
         return mContext.getResources().getBoolean(
@@ -71,7 +76,7 @@
         updateSummary(dropDownPreference, randomizationLevel);
 
         // Makes preference not selectable, when this is a ephemeral network.
-        if (mIsEphemeral) {
+        if (mIsEphemeral || mIsPasspoint) {
             preference.setSelectable(false);
             dropDownPreference.setSummary(R.string.wifi_privacy_settings_ephemeral_summary);
         }
diff --git a/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java b/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java
index 905d3a0..0fb56fa 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java
@@ -134,6 +134,7 @@
 
                     if (msg.arg1 == ARG_RESTART_CAMERA) {
                         mProgressBar.setVisibility(View.INVISIBLE);
+                        mDecorateView.setFocused(false);
                         restartCamera();
                     }
                     break;
diff --git a/src/com/android/settings/wifi/dpp/WifiDppUtils.java b/src/com/android/settings/wifi/dpp/WifiDppUtils.java
index 6c6444c..42e88a5 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppUtils.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppUtils.java
@@ -323,31 +323,36 @@
         }
     }
 
+    /**
+     * Checks if QR code scanner supports to config other devices with the Wi-Fi network
+     *
+     * @param context The context to use for {@link WifiManager#isEasyConnectSupported()}
+     * @param accessPoint The {@link AccessPoint} of the Wi-Fi network
+     */
     public static boolean isSupportConfiguratorQrCodeScanner(Context context,
             AccessPoint accessPoint) {
-        if (!isWifiDppEnabled(context)) {
-            return false;
-        }
-
-        // DPP 1.0 only supports SAE and PSK.
-        final int security = accessPoint.getSecurity();
-        if (security == AccessPoint.SECURITY_SAE || security == AccessPoint.SECURITY_PSK) {
-            return true;
-        }
-
-        return false;
+        return isSupportWifiDpp(context, accessPoint.getSecurity());
     }
 
+    /**
+     * Checks if QR code generator supports to config other devices with the Wi-Fi network
+     *
+     * @param accessPoint The {@link AccessPoint} of the Wi-Fi network
+     */
     public static boolean isSupportConfiguratorQrCodeGenerator(AccessPoint accessPoint) {
-        // QR code generator produces QR code with ZXing's Wi-Fi network config format,
-        // it supports PSK and WEP and non security
-        final int security = accessPoint.getSecurity();
-        if (security == AccessPoint.SECURITY_PSK || security == AccessPoint.SECURITY_WEP ||
-                security == AccessPoint.SECURITY_NONE) {
-            return true;
-        }
+        return isSupportZxing(accessPoint.getSecurity());
+    }
 
-        return false;
+    /**
+     * Checks if this device supports to be configured by the Wi-Fi network of the security
+     *
+     * @param context The context to use for {@link WifiManager#isEasyConnectSupported()}
+     * @param accesspointSecurity The security constants defined in {@link AccessPoint}
+     */
+    public static boolean isSupportEnrolleeQrCodeScanner(Context context,
+            int accesspointSecurity) {
+        return isSupportWifiDpp(context, accesspointSecurity) ||
+                isSupportZxing(accesspointSecurity);
     }
 
     private static boolean isSupportHotspotConfiguratorQrCodeGenerator(
@@ -358,4 +363,27 @@
         return wifiConfiguration.allowedKeyManagement.get(KeyMgmt.WPA2_PSK) ||
                 wifiConfiguration.allowedKeyManagement.get(KeyMgmt.NONE);
     }
+
+    private static boolean isSupportWifiDpp(Context context, int accesspointSecurity) {
+        if (!isWifiDppEnabled(context)) {
+            return false;
+        }
+
+        // DPP 1.0 only supports SAE and PSK.
+        if (accesspointSecurity == AccessPoint.SECURITY_SAE ||
+                accesspointSecurity == AccessPoint.SECURITY_PSK) {
+            return true;
+        }
+        return false;
+    }
+
+    // TODO (b/124131581 b/129396816): TO support WPA3 securities (SAE & OWE), change here at first
+    private static boolean isSupportZxing(int accesspointSecurity) {
+        if (accesspointSecurity == AccessPoint.SECURITY_PSK ||
+                accesspointSecurity == AccessPoint.SECURITY_WEP ||
+                accesspointSecurity == AccessPoint.SECURITY_NONE) {
+            return true;
+        }
+        return false;
+    }
 }
diff --git a/src/com/android/settings/wifi/qrcode/QrPreviewLayout.java b/src/com/android/settings/wifi/qrcode/QrPreviewLayout.java
deleted file mode 100644
index ad17146..0000000
--- a/src/com/android/settings/wifi/qrcode/QrPreviewLayout.java
+++ /dev/null
@@ -1,49 +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.qrcode;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.widget.FrameLayout;
-
-/**
- * A customize square {@link FrameLayout}.
- * This is used for camera preview. Choose the smaller size of both dimensions as length and width.
- */
-public class QrPreviewLayout extends FrameLayout {
-    public QrPreviewLayout(Context context) {
-        super(context);
-    }
-
-    public QrPreviewLayout(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    public QrPreviewLayout(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-    }
-
-    @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        // Choose the smaller size of the two dimensions.
-        if (MeasureSpec.getSize(widthMeasureSpec) > MeasureSpec.getSize(heightMeasureSpec)) {
-            super.onMeasure(heightMeasureSpec, heightMeasureSpec);
-        } else {
-            super.onMeasure(widthMeasureSpec, widthMeasureSpec);
-        }
-    }
-}
diff --git a/tests/robotests/assets/grandfather_not_implementing_index_provider b/tests/robotests/assets/grandfather_not_implementing_index_provider
index 8ca65ff..d7e5585 100644
--- a/tests/robotests/assets/grandfather_not_implementing_index_provider
+++ b/tests/robotests/assets/grandfather_not_implementing_index_provider
@@ -75,6 +75,7 @@
 com.android.settings.users.UserDetailsSettings
 com.android.settings.vpn2.AppManagementFragment
 com.android.settings.vpn2.VpnSettings
+com.android.settings.wallpaper.WallpaperTypeSettings
 com.android.settings.wifi.calling.WifiCallingSettingsForSub
 com.android.settings.wifi.ChangeWifiStateDetails
 com.android.settings.wifi.details.WifiNetworkDetailsFragment
diff --git a/tests/robotests/res/values/themes.xml b/tests/robotests/res/values/themes.xml
index 41ace18..92edb17 100644
--- a/tests/robotests/res/values/themes.xml
+++ b/tests/robotests/res/values/themes.xml
@@ -23,7 +23,7 @@
         <item name="android:textColorPrimary">@android:color/white</item>
         <item name="switchBarMarginStart">@dimen/switchbar_subsettings_margin_start</item>
         <item name="switchBarMarginEnd">@dimen/switchbar_subsettings_margin_end</item>
-        <item name="switchBarBackgroundColor">@color/switch_bar_background</item>
+        <item name="switchBarBackgroundColor">?android:attr/textColorSecondary</item>
         <item name="switchBarBackgroundActivatedColor">?android:attr/colorAccent</item>
         <item name="switchBarRestrictionIcon">@drawable/ic_help</item>
     </style>
diff --git a/tests/robotests/src/com/android/settings/SetupWizardUtilsTest.java b/tests/robotests/src/com/android/settings/SetupWizardUtilsTest.java
index f718a67..b965d78 100644
--- a/tests/robotests/src/com/android/settings/SetupWizardUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/SetupWizardUtilsTest.java
@@ -31,24 +31,27 @@
 @RunWith(RobolectricTestRunner.class)
 public class SetupWizardUtilsTest {
 
+    private static final String EXTRA_IS_SETUP_FLOW = "isSetupFlow";
+    private static final String EXTRA_IS_FIRST_RUN = "firstRun";
+
     @Test
     public void testCopySetupExtras() {
         Intent fromIntent = new Intent();
         final String theme = "TEST_THEME";
         fromIntent.putExtra(WizardManagerHelper.EXTRA_THEME, theme);
-        fromIntent.putExtra(WizardManagerHelper.EXTRA_USE_IMMERSIVE_MODE, true);
+        fromIntent.putExtra(WizardManagerHelper.EXTRA_IS_SETUP_FLOW, true);
         Intent toIntent = new Intent();
         SetupWizardUtils.copySetupExtras(fromIntent, toIntent);
 
         assertThat(theme).isEqualTo(toIntent.getStringExtra(WizardManagerHelper.EXTRA_THEME));
-        assertThat(toIntent.getBooleanExtra(WizardManagerHelper.EXTRA_USE_IMMERSIVE_MODE, false))
+        assertThat(toIntent.getBooleanExtra(WizardManagerHelper.EXTRA_IS_SETUP_FLOW, false))
                 .isTrue();
     }
 
     @Test
     public void testGetTheme_withIntentExtra_shouldReturnExtraTheme() {
         SetupWizardProperties.theme(ThemeHelper.THEME_GLIF);
-        Intent intent = new Intent();
+        Intent intent = createSetupWizardIntent();
         intent.putExtra(WizardManagerHelper.EXTRA_THEME, ThemeHelper.THEME_GLIF_V2);
 
         assertThat(SetupWizardUtils.getTheme(intent)).isEqualTo(R.style.GlifV2Theme);
@@ -57,7 +60,7 @@
     @Test
     public void testGetTheme_withEmptyIntent_shouldReturnSystemProperty() {
         SetupWizardProperties.theme(ThemeHelper.THEME_GLIF_V2_LIGHT);
-        Intent intent = new Intent();
+        Intent intent = createSetupWizardIntent();
 
         assertThat(SetupWizardUtils.getTheme(intent)).isEqualTo(R.style.GlifV2Theme_Light);
     }
@@ -65,10 +68,26 @@
     @Test
     public void testGetTheme_glifV3Light_shouldReturnThemeResource() {
         SetupWizardProperties.theme(ThemeHelper.THEME_GLIF_V3_LIGHT);
-        Intent intent = new Intent();
+        Intent intent = createSetupWizardIntent();
 
         assertThat(SetupWizardUtils.getTheme(intent)).isEqualTo(R.style.GlifV3Theme_Light);
         assertThat(SetupWizardUtils.getTransparentTheme(intent))
                 .isEqualTo(R.style.GlifV3Theme_Light_Transparent);
     }
+
+    @Test
+    public void testGetTheme_nonSuw_shouldReturnDayNightTheme() {
+        SetupWizardProperties.theme(ThemeHelper.THEME_GLIF_V3_LIGHT);
+        Intent intent = new Intent();
+
+        assertThat(SetupWizardUtils.getTheme(intent)).isEqualTo(R.style.GlifV3Theme);
+        assertThat(SetupWizardUtils.getTransparentTheme(intent))
+                .isEqualTo(R.style.GlifV3Theme_Transparent);
+    }
+
+    private Intent createSetupWizardIntent() {
+        return new Intent()
+                .putExtra(EXTRA_IS_SETUP_FLOW, true)
+                .putExtra(EXTRA_IS_FIRST_RUN, true);
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java
index 8c53019..0cc9dc4 100644
--- a/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java
@@ -156,7 +156,7 @@
 
     @Test
     public void testDarkUIModePreferenceSummary_shouldUpdateSummary() {
-        final ListPreference darkUIModePreference = new ListPreference(mContext);
+        final Preference darkUIModePreference = new Preference(mContext);
         final DarkUIPreferenceController mController;
         doReturn(darkUIModePreference).when(mSettings).findPreference(
             DARK_UI_MODE_PREFERENCE);
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/AppButtonsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/AppButtonsPreferenceControllerTest.java
index 59aea3d..6d9430c 100644
--- a/tests/robotests/src/com/android/settings/applications/appinfo/AppButtonsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/AppButtonsPreferenceControllerTest.java
@@ -119,7 +119,6 @@
 
         mController = spy(new AppButtonsPreferenceController(mSettingsActivity, mFragment,
                 mLifecycle, PACKAGE_NAME, mState, REQUEST_UNINSTALL, REQUEST_REMOVE_DEVICE_ADMIN));
-        doReturn(false).when(mController).isFallbackPackage(anyString());
 
         mAppEntry.info = mAppInfo;
         mAppInfo.packageName = PACKAGE_NAME;
diff --git a/tests/robotests/src/com/android/settings/enterprise/ActionDisabledByAdminDialogHelperTest.java b/tests/robotests/src/com/android/settings/enterprise/ActionDisabledByAdminDialogHelperTest.java
index c01ef3f..ff3a36f 100644
--- a/tests/robotests/src/com/android/settings/enterprise/ActionDisabledByAdminDialogHelperTest.java
+++ b/tests/robotests/src/com/android/settings/enterprise/ActionDisabledByAdminDialogHelperTest.java
@@ -20,6 +20,11 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
 
 import android.app.Activity;
 import android.app.admin.DevicePolicyManager;
@@ -33,6 +38,8 @@
 import android.widget.FrameLayout;
 import android.widget.TextView;
 
+import androidx.appcompat.app.AlertDialog;
+
 import com.android.settings.R;
 import com.android.settings.Settings;
 import com.android.settings.applications.specialaccess.deviceadmin.DeviceAdminAdd;
@@ -179,5 +186,28 @@
         mHelper.setAdminSupportDetails(mActivity, null, admin);
         assertNull(admin.component);
     }
-}
 
+    @Test
+    public void testMaybeSetLearnMoreButton() {
+        final UserManager userManager = RuntimeEnvironment.application.getSystemService(
+                UserManager.class);
+        final ShadowUserManager userManagerShadow = Shadow.extract(userManager);
+        final ComponentName component = new ComponentName("some.package.name",
+                "some.package.name.SomeClass");
+        mHelper.mEnforcedAdmin = new EnforcedAdmin(component, UserHandle.of(123));
+
+        // Set up for shadow call.
+        userManagerShadow.getSameProfileGroupIds().put(123, 0);
+
+        // Test that the button is shown when user IDs are in the same profile group
+        AlertDialog.Builder builder = mock(AlertDialog.Builder.class);
+        mHelper.maybeSetLearnMoreButton(builder);
+        verify(builder).setNeutralButton(anyInt(), any());
+
+        // Test that the button is not shown when user IDs are not in the same profile group
+        userManagerShadow.getSameProfileGroupIds().clear();
+        builder = mock(AlertDialog.Builder.class);
+        mHelper.maybeSetLearnMoreButton(builder);
+        verify(builder, never()).setNeutralButton(anyInt(), any());
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleRadioButtonsControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleRadioButtonsControllerTest.java
index 6012dbb..8654a4e 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleRadioButtonsControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleRadioButtonsControllerTest.java
@@ -7,6 +7,7 @@
 import android.os.PowerManager;
 import android.provider.Settings;
 import android.provider.Settings.Global;
+import android.provider.Settings.Secure;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -54,4 +55,13 @@
         assertThat(mController.getDefaultKey())
                 .isEqualTo(BatterySaverScheduleRadioButtonsController.KEY_NO_SCHEDULE);
     }
+
+    @Test
+    public void setDefaultKey_any_defaultsToNoScheduleIfWarningNotSeen() {
+        Secure.putString(
+            mContext.getContentResolver(), Secure.LOW_POWER_WARNING_ACKNOWLEDGED, "null");
+        mController.setDefaultKey(BatterySaverScheduleRadioButtonsController.KEY_ROUTINE);
+        assertThat(mController.getDefaultKey())
+                .isEqualTo(BatterySaverScheduleRadioButtonsController.KEY_NO_SCHEDULE);
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/NotificationChannelSliceTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/NotificationChannelSliceTest.java
index a744e68..12513f6 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/NotificationChannelSliceTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/NotificationChannelSliceTest.java
@@ -16,6 +16,7 @@
 
 package com.android.settings.homepage.contextualcards.slices;
 
+import static android.app.NotificationManager.IMPORTANCE_LOW;
 import static android.app.NotificationManager.IMPORTANCE_NONE;
 import static android.app.slice.Slice.HINT_LIST_ITEM;
 import static android.app.slice.SliceItem.FORMAT_SLICE;
@@ -116,7 +117,8 @@
     public void getSlice_hasSuggestedApp_shouldHaveNotificationChannelTitle() {
         addMockPackageToPackageManager(true /* isRecentlyInstalled */,
                 ApplicationInfo.FLAG_INSTALLED);
-        mockNotificationBackend(CHANNEL_COUNT, NOTIFICATION_COUNT, false /* banned */);
+        mockNotificationBackend(CHANNEL_COUNT, NOTIFICATION_COUNT, false /* banned */,
+                false /* isChannelBlocked */);
 
         final Slice slice = mNotificationChannelSlice.getSlice();
 
@@ -130,7 +132,8 @@
     public void getSlice_hasSuggestedApp_shouldSortByNotificationSentCount() {
         addMockPackageToPackageManager(true /* isRecentlyInstalled */,
                 ApplicationInfo.FLAG_INSTALLED);
-        mockNotificationBackend(CHANNEL_COUNT, NOTIFICATION_COUNT, false /* banned */);
+        mockNotificationBackend(CHANNEL_COUNT, NOTIFICATION_COUNT, false /* banned */,
+                false /* isChannelBlocked */);
 
         final Slice slice = mNotificationChannelSlice.getSlice();
 
@@ -157,7 +160,8 @@
     public void getSlice_noRecentlyInstalledApp_shouldHaveNoSuggestedAppTitle() {
         addMockPackageToPackageManager(false /* isRecentlyInstalled */,
                 ApplicationInfo.FLAG_INSTALLED);
-        mockNotificationBackend(CHANNEL_COUNT, NOTIFICATION_COUNT, false /* banned */);
+        mockNotificationBackend(CHANNEL_COUNT, NOTIFICATION_COUNT, false /* banned */,
+                false /* isChannelBlocked */);
 
         final Slice slice = mNotificationChannelSlice.getSlice();
 
@@ -169,7 +173,8 @@
     public void getSlice_noMultiChannelApp_shouldHaveNoSuggestedAppTitle() {
         addMockPackageToPackageManager(true /* isRecentlyInstalled */,
                 ApplicationInfo.FLAG_INSTALLED);
-        mockNotificationBackend(1 /* channelCount */, NOTIFICATION_COUNT, false /* banned */);
+        mockNotificationBackend(1 /* channelCount */, NOTIFICATION_COUNT, false /* banned */,
+                false /* isChannelBlocked */);
 
         final Slice slice = mNotificationChannelSlice.getSlice();
 
@@ -178,10 +183,12 @@
     }
 
     @Test
+    @Config(shadows = ShadowRestrictedLockUtilsInternal.class)
     public void getSlice_insufficientNotificationSentCount_shouldHaveNoSuggestedAppTitle() {
         addMockPackageToPackageManager(true /* isRecentlyInstalled */,
                 ApplicationInfo.FLAG_INSTALLED);
-        mockNotificationBackend(CHANNEL_COUNT, 1 /* notificationCount */, false /* banned */);
+        mockNotificationBackend(CHANNEL_COUNT, 1 /* notificationCount */, false /* banned */,
+                false /* isChannelBlocked */);
 
         final Slice slice = mNotificationChannelSlice.getSlice();
 
@@ -192,7 +199,8 @@
     @Test
     public void getSlice_isSystemApp_shouldHaveNoSuggestedAppTitle() {
         addMockPackageToPackageManager(true /* isRecentlyInstalled */, ApplicationInfo.FLAG_SYSTEM);
-        mockNotificationBackend(CHANNEL_COUNT, NOTIFICATION_COUNT, false /* banned */);
+        mockNotificationBackend(CHANNEL_COUNT, NOTIFICATION_COUNT, false /* banned */,
+                false /* isChannelBlocked */);
 
         final Slice slice = mNotificationChannelSlice.getSlice();
 
@@ -204,7 +212,8 @@
     public void getSlice_isNotificationBanned_shouldHaveNoSuggestedAppTitle() {
         addMockPackageToPackageManager(true /* isRecentlyInstalled */,
                 ApplicationInfo.FLAG_INSTALLED);
-        mockNotificationBackend(CHANNEL_COUNT, NOTIFICATION_COUNT, true /* banned */);
+        mockNotificationBackend(CHANNEL_COUNT, NOTIFICATION_COUNT, true /* banned */,
+                false /* isChannelBlocked */);
 
         final Slice slice = mNotificationChannelSlice.getSlice();
 
@@ -218,7 +227,7 @@
         addMockPackageToPackageManager(true /* isRecentlyInstalled */,
                 ApplicationInfo.FLAG_INSTALLED);
         mockNotificationBackend(NotificationChannelSlice.DEFAULT_EXPANDED_ROW_COUNT * 2,
-                NOTIFICATION_COUNT, false /* banned */);
+                NOTIFICATION_COUNT, false /* banned */, false /* isChannelBlocked */);
 
         final Slice slice = mNotificationChannelSlice.getSlice();
 
@@ -234,7 +243,8 @@
     public void getSlice_channelCountIsLessThanDefaultRows_subTitleShouldNotHaveTapToManagerAll() {
         addMockPackageToPackageManager(true /* isRecentlyInstalled */,
                 ApplicationInfo.FLAG_INSTALLED);
-        mockNotificationBackend(CHANNEL_COUNT - 1, NOTIFICATION_COUNT, false /* banned */);
+        mockNotificationBackend(CHANNEL_COUNT - 1, NOTIFICATION_COUNT, false /* banned */,
+                false /* isChannelBlocked */);
 
         final Slice slice = mNotificationChannelSlice.getSlice();
 
@@ -249,7 +259,8 @@
     public void getSlice_channelCountIsEqualToDefaultRows_subTitleShouldNotHaveTapToManagerAll() {
         addMockPackageToPackageManager(true /* isRecentlyInstalled */,
                 ApplicationInfo.FLAG_INSTALLED);
-        mockNotificationBackend(CHANNEL_COUNT, NOTIFICATION_COUNT, false /* banned */);
+        mockNotificationBackend(CHANNEL_COUNT, NOTIFICATION_COUNT, false /* banned */,
+                false /* isChannelBlocked */);
 
         final Slice slice = mNotificationChannelSlice.getSlice();
 
@@ -263,7 +274,8 @@
     public void getSlice_channelCountIsMoreThanDefaultRows_subTitleShouldHaveTapToManagerAll() {
         addMockPackageToPackageManager(true /* isRecentlyInstalled */,
                 ApplicationInfo.FLAG_INSTALLED);
-        mockNotificationBackend(CHANNEL_COUNT + 1, NOTIFICATION_COUNT, false /* banned */);
+        mockNotificationBackend(CHANNEL_COUNT + 1, NOTIFICATION_COUNT, false /* banned */,
+                false /* isChannelBlocked */);
 
         final Slice slice = mNotificationChannelSlice.getSlice();
 
@@ -273,6 +285,20 @@
                         CHANNEL_COUNT + 1));
     }
 
+    @Test
+    @Config(shadows = ShadowRestrictedLockUtilsInternal.class)
+    public void getSlice_isAllDisplayableChannelBlocked_shouldHaveNoSuggestedAppTitle() {
+        addMockPackageToPackageManager(true /* isRecentlyInstalled */,
+                ApplicationInfo.FLAG_INSTALLED);
+        mockNotificationBackend(CHANNEL_COUNT, NOTIFICATION_COUNT, false /* banned */,
+                true /* isChannelBlocked */);
+
+        final Slice slice = mNotificationChannelSlice.getSlice();
+
+        final SliceMetadata metadata = SliceMetadata.from(mContext, slice);
+        assertThat(metadata.getTitle()).isEqualTo(mContext.getString(R.string.no_suggested_app));
+    }
+
     private void addMockPackageToPackageManager(boolean isRecentlyInstalled, int flags) {
         final ApplicationInfo applicationInfo = new ApplicationInfo();
         applicationInfo.name = APP_LABEL;
@@ -294,8 +320,10 @@
         return System.currentTimeMillis();
     }
 
-    private void mockNotificationBackend(int channelCount, int notificationCount, boolean banned) {
-        final List<NotificationChannel> channels = buildNotificationChannel(channelCount);
+    private void mockNotificationBackend(int channelCount, int notificationCount, boolean banned,
+            boolean isChannelBlocked) {
+        final List<NotificationChannel> channels = buildNotificationChannel(channelCount,
+                isChannelBlocked);
         final AppRow appRow = buildAppRow(channelCount, notificationCount, banned);
 
         doReturn(buildNotificationChannelGroups(channels)).when(mNotificationBackend).getGroups(
@@ -308,6 +336,8 @@
 
     private AppRow buildAppRow(int channelCount, int sentCount, boolean banned) {
         final AppRow appRow = new AppRow();
+        appRow.pkg = PACKAGE_NAME;
+        appRow.uid = UID;
         appRow.banned = banned;
         appRow.channelCount = channelCount;
         appRow.sentByApp = new NotificationsSentState();
@@ -317,11 +347,12 @@
         return appRow;
     }
 
-    private List<NotificationChannel> buildNotificationChannel(int channelCount) {
+    private List<NotificationChannel> buildNotificationChannel(int channelCount,
+            boolean isChannelBlock) {
         final List<NotificationChannel> channels = new ArrayList<>();
         for (int i = 0; i < channelCount; i++) {
             channels.add(new NotificationChannel(CHANNEL_NAME_PREFIX + i, CHANNEL_NAME_PREFIX + i,
-                    IMPORTANCE_NONE));
+                    isChannelBlock ? IMPORTANCE_NONE : IMPORTANCE_LOW));
         }
 
         return channels;
@@ -369,4 +400,4 @@
         // Index 0: title; Index 1: summary.
         return rowSliceItems.get(1).getText();
     }
-}
\ No newline at end of file
+}
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRendererTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRendererTest.java
index e08d845..706f238 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRendererTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRendererTest.java
@@ -16,13 +16,11 @@
 
 package com.android.settings.homepage.contextualcards.slices;
 
-import static com.android.settings.homepage.contextualcards.slices.SliceContextualCardRenderer.VIEW_TYPE_DEFERRED_SETUP;
 import static com.android.settings.homepage.contextualcards.slices.SliceContextualCardRenderer.VIEW_TYPE_FULL_WIDTH;
 
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 
 import android.app.Activity;
@@ -118,34 +116,25 @@
     }
 
     @Test
-    public void longClick_shouldFlipCard() {
+    public void bindView_isPendingDismiss_shouldFlipToDismissalView() {
         final RecyclerView.ViewHolder viewHolder = getSliceViewHolder();
-        final View card = viewHolder.itemView.findViewById(R.id.slice_view);
         final ViewFlipper viewFlipper = viewHolder.itemView.findViewById(R.id.view_flipper);
         final View dismissalView = viewHolder.itemView.findViewById(R.id.dismissal_view);
-        mRenderer.bindView(viewHolder, buildContextualCard(TEST_SLICE_URI));
+        final ContextualCard card = buildContextualCard(
+                TEST_SLICE_URI).mutate().setIsPendingDismiss(true).build();
 
-        card.performLongClick();
+        mRenderer.bindView(viewHolder, card);
 
         assertThat(viewFlipper.getCurrentView()).isEqualTo(dismissalView);
     }
 
     @Test
-    public void longClick_deferredSetupCard_shouldNotBeClickable() {
-        final RecyclerView.ViewHolder viewHolder = getDeferredSetupViewHolder();
-        final View contentView = viewHolder.itemView.findViewById(R.id.content);
-        mRenderer.bindView(viewHolder, buildContextualCard(TEST_SLICE_URI));
-
-        assertThat(contentView.isLongClickable()).isFalse();
-    }
-
-    @Test
-    public void longClick_shouldAddViewHolderToSet() {
+    public void bindView_isPendingDismiss_shouldAddViewHolderToSet() {
         final RecyclerView.ViewHolder viewHolder = getSliceViewHolder();
-        final View card = viewHolder.itemView.findViewById(R.id.slice_view);
-        mRenderer.bindView(viewHolder, buildContextualCard(TEST_SLICE_URI));
+        final ContextualCard card = buildContextualCard(
+                TEST_SLICE_URI).mutate().setIsPendingDismiss(true).build();
 
-        card.performLongClick();
+        mRenderer.bindView(viewHolder, card);
 
         assertThat(mRenderer.mFlippedCardSet).contains(viewHolder);
     }
@@ -153,12 +142,11 @@
     @Test
     public void viewClick_keepCard_shouldFlipBackToSlice() {
         final RecyclerView.ViewHolder viewHolder = getSliceViewHolder();
-        final View card = viewHolder.itemView.findViewById(R.id.slice_view);
         final Button btnKeep = viewHolder.itemView.findViewById(R.id.keep);
         final ViewFlipper viewFlipper = viewHolder.itemView.findViewById(R.id.view_flipper);
         mRenderer.bindView(viewHolder, buildContextualCard(TEST_SLICE_URI));
+        viewFlipper.setDisplayedChild(1);
 
-        card.performLongClick();
         btnKeep.performClick();
 
         assertThat(viewFlipper.getCurrentView()).isInstanceOf(SliceView.class);
@@ -167,11 +155,10 @@
     @Test
     public void viewClick_keepCard_shouldRemoveViewHolderFromSet() {
         final RecyclerView.ViewHolder viewHolder = getSliceViewHolder();
-        final View card = viewHolder.itemView.findViewById(R.id.slice_view);
         final Button btnKeep = viewHolder.itemView.findViewById(R.id.keep);
         mRenderer.bindView(viewHolder, buildContextualCard(TEST_SLICE_URI));
+        mRenderer.mFlippedCardSet.add(viewHolder);
 
-        card.performLongClick();
         btnKeep.performClick();
 
         assertThat(mRenderer.mFlippedCardSet).doesNotContain(viewHolder);
@@ -180,14 +167,13 @@
     @Test
     public void viewClick_removeCard_shouldRemoveViewHolderFromSet() {
         final RecyclerView.ViewHolder viewHolder = getSliceViewHolder();
-        final View card = viewHolder.itemView.findViewById(R.id.slice_view);
         final Button btnRemove = viewHolder.itemView.findViewById(R.id.remove);
         final ContextualCard contextualCard = buildContextualCard(TEST_SLICE_URI);
         mRenderer.bindView(viewHolder, contextualCard);
         doReturn(mController).when(mControllerRendererPool).getController(mActivity,
                 ContextualCard.CardType.SLICE);
+        mRenderer.mFlippedCardSet.add(viewHolder);
 
-        card.performLongClick();
         btnRemove.performClick();
 
         assertThat(mRenderer.mFlippedCardSet).doesNotContain(viewHolder);
@@ -196,7 +182,6 @@
     @Test
     public void viewClick_removeCard_sliceLiveDataShouldRemoveObservers() {
         final RecyclerView.ViewHolder viewHolder = getSliceViewHolder();
-        final View card = viewHolder.itemView.findViewById(R.id.slice_view);
         final Button btnRemove = viewHolder.itemView.findViewById(R.id.remove);
         final ContextualCard contextualCard = buildContextualCard(TEST_SLICE_URI);
         mRenderer.mSliceLiveDataMap.put(TEST_SLICE_URI, mSliceLiveData);
@@ -204,7 +189,6 @@
         doReturn(mController).when(mControllerRendererPool).getController(mActivity,
                 ContextualCard.CardType.SLICE);
 
-        card.performLongClick();
         btnRemove.performClick();
 
         assertThat(mRenderer.mSliceLiveDataMap.get(TEST_SLICE_URI).hasObservers()).isFalse();
@@ -213,11 +197,11 @@
     @Test
     public void onStop_cardIsFlipped_shouldFlipBack() {
         final RecyclerView.ViewHolder viewHolder = getSliceViewHolder();
-        final View card = viewHolder.itemView.findViewById(R.id.slice_view);
         final ViewFlipper viewFlipper = viewHolder.itemView.findViewById(R.id.view_flipper);
         mRenderer.bindView(viewHolder, buildContextualCard(TEST_SLICE_URI));
+        viewFlipper.setDisplayedChild(1);
+        mRenderer.mFlippedCardSet.add(viewHolder);
 
-        card.performLongClick();
         mRenderer.onStop();
 
         assertThat(viewFlipper.getCurrentView()).isInstanceOf(SliceView.class);
@@ -232,18 +216,6 @@
         return mRenderer.createViewHolder(view, VIEW_TYPE_FULL_WIDTH);
     }
 
-    private RecyclerView.ViewHolder getDeferredSetupViewHolder() {
-        final RecyclerView recyclerView = new RecyclerView(mActivity);
-        recyclerView.setLayoutManager(new LinearLayoutManager(mActivity));
-        final View view = LayoutInflater.from(mActivity).inflate(VIEW_TYPE_DEFERRED_SETUP,
-                recyclerView, false);
-        final RecyclerView.ViewHolder viewHolder = spy(
-                mRenderer.createViewHolder(view, VIEW_TYPE_DEFERRED_SETUP));
-        doReturn(VIEW_TYPE_DEFERRED_SETUP).when(viewHolder).getItemViewType();
-
-        return viewHolder;
-    }
-
     private ContextualCard buildContextualCard(Uri sliceUri) {
         return new ContextualCard.Builder()
                 .setName("test_name")
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SwipeDismissalDelegateTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SwipeDismissalDelegateTest.java
new file mode 100644
index 0000000..00b7815
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SwipeDismissalDelegateTest.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2019 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.homepage.contextualcards.slices;
+
+import static com.android.settings.homepage.contextualcards.slices.SliceContextualCardRenderer.VIEW_TYPE_DEFERRED_SETUP;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.app.Activity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.ViewFlipper;
+
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.settings.R;
+import com.android.settings.homepage.contextualcards.conditional.ConditionContextualCardRenderer;
+import com.android.settings.homepage.contextualcards.conditional.ConditionContextualCardRenderer.ConditionalCardHolder;
+import com.android.settings.homepage.contextualcards.slices.SliceDeferredSetupCardRendererHelper.DeferredSetupCardViewHolder;
+import com.android.settings.homepage.contextualcards.slices.SliceFullCardRendererHelper.SliceViewHolder;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.Robolectric;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.android.controller.ActivityController;
+
+@RunWith(RobolectricTestRunner.class)
+public class SwipeDismissalDelegateTest {
+
+    @Mock
+    private SwipeDismissalDelegate.Listener mDismissalDelegateListener;
+
+    private Activity mActivity;
+    private RecyclerView mRecyclerView;
+    private SwipeDismissalDelegate mDismissalDelegate;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        final ActivityController<Activity> activityController = Robolectric.buildActivity(
+                Activity.class);
+        mActivity = activityController.get();
+        mActivity.setTheme(R.style.Theme_Settings_Home);
+        activityController.create();
+        mRecyclerView = new RecyclerView(mActivity);
+        mRecyclerView.setLayoutManager(new LinearLayoutManager(mActivity));
+        mDismissalDelegate = new SwipeDismissalDelegate(mActivity, mDismissalDelegateListener);
+    }
+
+    @Test
+    public void getMovementFlags_conditionalViewHolder_shouldDisableSwipe() {
+        assertThat(mDismissalDelegate.getMovementFlags(mRecyclerView, getConditionalViewHolder()))
+                .isEqualTo(0);
+    }
+
+    @Test
+    public void getMovementFlags_deferredSetupViewHolder_shouldDisableSwipe() {
+        assertThat(mDismissalDelegate.getMovementFlags(mRecyclerView, getDeferredSetupViewHolder()))
+                .isEqualTo(0);
+    }
+
+    @Test
+    public void getMovementFlags_dismissalView_shouldDisableSwipe() {
+        final RecyclerView.ViewHolder holder = getSliceViewHolder();
+        final ViewFlipper viewFlipper = holder.itemView.findViewById(R.id.view_flipper);
+        viewFlipper.showNext();
+        final View dismissalView = holder.itemView.findViewById(R.id.dismissal_view);
+
+        assertThat(viewFlipper.getCurrentView()).isEqualTo(dismissalView);
+        assertThat(mDismissalDelegate.getMovementFlags(mRecyclerView, holder)).isEqualTo(0);
+    }
+
+    @Test
+    public void getMovementFlags_SliceViewHolder_shouldEnableSwipe() {
+        final RecyclerView.ViewHolder holder = getSliceViewHolder();
+        final ViewFlipper viewFlipper = holder.itemView.findViewById(R.id.view_flipper);
+        viewFlipper.setDisplayedChild(0);
+        final View sliceView = holder.itemView.findViewById(R.id.slice_view);
+
+        assertThat(viewFlipper.getCurrentView()).isEqualTo(sliceView);
+        assertThat(mDismissalDelegate.getMovementFlags(mRecyclerView, getSliceViewHolder()))
+                .isNotEqualTo(0);
+    }
+
+    @Test
+    public void onSwipe_shouldNotifyListener() {
+        mDismissalDelegate.onSwiped(getSliceViewHolder(), 1);
+
+        verify(mDismissalDelegateListener).onSwiped(anyInt());
+    }
+
+    private RecyclerView.ViewHolder getSliceViewHolder() {
+        final View view = LayoutInflater.from(mActivity)
+                .inflate(SliceContextualCardRenderer.VIEW_TYPE_FULL_WIDTH, mRecyclerView, false);
+        final RecyclerView.ViewHolder viewHolder = spy(new SliceViewHolder(view));
+        doReturn(SliceContextualCardRenderer.VIEW_TYPE_FULL_WIDTH).when(
+                viewHolder).getItemViewType();
+
+        return viewHolder;
+    }
+
+    private RecyclerView.ViewHolder getConditionalViewHolder() {
+        final View view = LayoutInflater.from(mActivity)
+                .inflate(ConditionContextualCardRenderer.VIEW_TYPE_FULL_WIDTH, mRecyclerView,
+                        false);
+        final RecyclerView.ViewHolder viewHolder = spy(new ConditionalCardHolder(view));
+        doReturn(ConditionContextualCardRenderer.VIEW_TYPE_FULL_WIDTH).when(
+                viewHolder).getItemViewType();
+
+        return viewHolder;
+    }
+
+    private RecyclerView.ViewHolder getDeferredSetupViewHolder() {
+        final View view = LayoutInflater.from(mActivity)
+                .inflate(VIEW_TYPE_DEFERRED_SETUP, mRecyclerView, false);
+        final RecyclerView.ViewHolder viewHolder = spy(new DeferredSetupCardViewHolder(view));
+        doReturn(VIEW_TYPE_DEFERRED_SETUP).when(viewHolder).getItemViewType();
+
+        return viewHolder;
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/media/MediaOutputSliceTest.java b/tests/robotests/src/com/android/settings/media/MediaOutputSliceTest.java
index d26a458..205f295 100644
--- a/tests/robotests/src/com/android/settings/media/MediaOutputSliceTest.java
+++ b/tests/robotests/src/com/android/settings/media/MediaOutputSliceTest.java
@@ -30,6 +30,7 @@
 import android.bluetooth.BluetoothAdapter;
 import android.content.Context;
 import android.content.Intent;
+import android.graphics.drawable.Drawable;
 
 import androidx.slice.Slice;
 import androidx.slice.SliceMetadata;
@@ -66,6 +67,8 @@
 
     @Mock
     private LocalMediaManager mLocalMediaManager;
+    @Mock
+    private Drawable mTestDrawable;
 
     private final List<MediaDevice> mDevices = new ArrayList<>();
 
@@ -105,7 +108,7 @@
         mDevices.clear();
         final MediaDevice device = mock(MediaDevice.class);
         when(device.getName()).thenReturn(TEST_DEVICE_1_NAME);
-        when(device.getIcon()).thenReturn(TEST_DEVICE_1_ICON);
+        when(device.getIcon()).thenReturn(mTestDrawable);
         when(mLocalMediaManager.getCurrentConnectedDevice()).thenReturn(device);
 
         final Slice mediaSlice = mMediaOutputSlice.getSlice();
diff --git a/tests/robotests/src/com/android/settings/notification/BubblePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/BubblePreferenceControllerTest.java
index 99787d8..6d13798 100644
--- a/tests/robotests/src/com/android/settings/notification/BubblePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/BubblePreferenceControllerTest.java
@@ -23,6 +23,7 @@
 import static android.provider.Settings.Secure.NOTIFICATION_BUBBLES;
 
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
@@ -223,6 +224,7 @@
     @Test
     public void testUpdateState_app() {
         NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+        appRow.label = "App!";
         appRow.allowBubbles = true;
         mController.onResume(appRow, null, null, null);
 
@@ -235,6 +237,9 @@
 
         mController.updateState(pref);
         assertFalse(pref.isChecked());
+
+        assertNotNull(pref.getSummary());
+        assertTrue(pref.getSummary().toString().contains(appRow.label));
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/notification/BubbleSummaryNotificationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/BubbleSummaryNotificationPreferenceControllerTest.java
new file mode 100644
index 0000000..4bdb2cc
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/BubbleSummaryNotificationPreferenceControllerTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2019 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 static android.provider.Settings.Secure.NOTIFICATION_BUBBLES;
+
+import static com.android.settings.notification.BadgingNotificationPreferenceController.OFF;
+import static com.android.settings.notification.BadgingNotificationPreferenceController.ON;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.provider.Settings;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+import androidx.preference.Preference;
+
+@RunWith(RobolectricTestRunner.class)
+public class BubbleSummaryNotificationPreferenceControllerTest {
+
+    private Context mContext;
+
+    private BubbleSummaryNotificationPreferenceController mController;
+    private Preference mPreference;
+
+    private static final String KEY_NOTIFICATION_BUBBLES = "notification_bubbles";
+
+    @Before
+    public void setUp() {
+        mContext = RuntimeEnvironment.application;
+        mController = new BubbleSummaryNotificationPreferenceController(mContext,
+                KEY_NOTIFICATION_BUBBLES);
+        mPreference = new Preference(RuntimeEnvironment.application);
+    }
+
+    @Test
+    public void display_shouldDisplay() {
+        assertThat(mPreference.isVisible()).isTrue();
+    }
+
+    @Test
+    public void getSummary() {
+        Settings.Secure.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, OFF);
+
+        assertThat(mController.getSummary()).isEqualTo("Off");
+
+        Settings.Secure.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, ON);
+
+        assertThat(mController.getSummary()).isEqualTo("On");
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/BubbleSummaryPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/BubbleSummaryPreferenceControllerTest.java
new file mode 100644
index 0000000..5158e82
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/BubbleSummaryPreferenceControllerTest.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2019 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 static android.app.NotificationChannel.DEFAULT_CHANNEL_ID;
+import static android.app.NotificationManager.IMPORTANCE_HIGH;
+import static android.app.NotificationManager.IMPORTANCE_LOW;
+import static android.app.NotificationManager.IMPORTANCE_NONE;
+import static android.provider.Settings.Secure.NOTIFICATION_BUBBLES;
+
+import static junit.framework.TestCase.assertEquals;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.os.UserManager;
+import android.provider.Settings;
+
+import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedSwitchPreference;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadows.ShadowApplication;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+@RunWith(RobolectricTestRunner.class)
+public class BubbleSummaryPreferenceControllerTest {
+
+    private Context mContext;
+    @Mock
+    private NotificationBackend mBackend;
+
+    private BubbleSummaryPreferenceController mController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        ShadowApplication shadowApplication = ShadowApplication.getInstance();
+        mContext = RuntimeEnvironment.application;
+        mController = spy(new BubbleSummaryPreferenceController(mContext, mBackend));
+    }
+
+    @Test
+    public void testNoCrashIfNoOnResume() {
+        mController.isAvailable();
+        mController.updateState(mock(Preference.class));
+    }
+
+    @Test
+    public void testIsAvailable_notIfAppBlocked() {
+        NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+        appRow.banned = true;
+        mController.onResume(appRow, mock(NotificationChannel.class), null, null);
+        assertFalse(mController.isAvailable());
+    }
+
+    @Test
+    public void testIsAvailable_notIfOffGlobally() {
+        NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+        NotificationChannel channel = mock(NotificationChannel.class);
+        when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
+        mController.onResume(appRow, channel, null, null);
+        Settings.Secure.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, 0);
+
+        assertFalse(mController.isAvailable());
+    }
+
+    @Test
+    public void testIsAvailable_app() {
+        NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+        mController.onResume(appRow, null, null, null);
+        Settings.Secure.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, 1);
+
+        assertTrue(mController.isAvailable());
+    }
+
+    @Test
+    public void testIsAvailable_defaultChannel() {
+        NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+        appRow.allowBubbles = true;
+        NotificationChannel channel = mock(NotificationChannel.class);
+        when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
+        when(channel.getId()).thenReturn(DEFAULT_CHANNEL_ID);
+        mController.onResume(appRow, channel, null, null);
+        Settings.Secure.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, 1);
+
+        assertTrue(mController.isAvailable());
+    }
+
+    @Test
+    public void testUpdateState() {
+        NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+        appRow.allowBubbles = true;
+        mController.onResume(appRow, null, null, null);
+
+        Preference pref = new Preference(mContext);
+        mController.updateState(pref);
+        assertNotNull(pref.getIntent());
+    }
+
+    @Test
+    public void testGetSummary() {
+        NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+        appRow.allowBubbles = true;
+        mController.onResume(appRow, null, null, null);
+
+        assertEquals("On", mController.getSummary());
+
+        appRow.allowBubbles = false;
+        mController.onResume(appRow, null, null, null);
+
+        assertEquals("Off", mController.getSummary());
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/NotificationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/NotificationPreferenceControllerTest.java
index 2368af5..9c53a7b 100644
--- a/tests/robotests/src/com/android/settings/notification/NotificationPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/NotificationPreferenceControllerTest.java
@@ -318,6 +318,30 @@
     }
 
     @Test
+    public void testIsChannelBlockable_oemLocked() {
+        NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+        appRow.systemApp = false;
+        NotificationChannel channel = mock(NotificationChannel.class);
+        when(channel.isImportanceLockedByOEM()).thenReturn(true);
+        when(channel.getImportance()).thenReturn(IMPORTANCE_DEFAULT);
+
+        mController.onResume(appRow, channel, null, null);
+        assertFalse(mController.isChannelBlockable());
+    }
+
+    @Test
+    public void testIsChannelBlockable_criticalDeviceFunction() {
+        NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+        appRow.systemApp = false;
+        NotificationChannel channel = mock(NotificationChannel.class);
+        when(channel.isImportanceLockedByCriticalDeviceFunction()).thenReturn(true);
+        when(channel.getImportance()).thenReturn(IMPORTANCE_DEFAULT);
+
+        mController.onResume(appRow, channel, null, null);
+        assertFalse(mController.isChannelBlockable());
+    }
+
+    @Test
     public void testIsChannelGroupBlockable_SystemNotBlockable() {
         NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
         appRow.systemApp = true;
diff --git a/tests/robotests/src/com/android/settings/notification/SoundPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/SoundPreferenceControllerTest.java
index 1b4ede5..866f866 100644
--- a/tests/robotests/src/com/android/settings/notification/SoundPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/SoundPreferenceControllerTest.java
@@ -39,6 +39,8 @@
 import android.app.NotificationManager;
 import android.content.Context;
 import android.content.Intent;
+import android.media.AudioAttributes;
+import android.media.RingtoneManager;
 import android.net.Uri;
 import android.os.UserManager;
 import android.provider.Settings;
@@ -54,6 +56,7 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Answers;
+import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.Robolectric;
@@ -231,6 +234,69 @@
     }
 
     @Test
+    public void testOnPreferenceTreeClick_alarmSound() {
+        NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+        NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
+        channel.setSound(null, new AudioAttributes.Builder().setUsage(
+                AudioAttributes.USAGE_ALARM).build());
+        mController.onResume(appRow, channel, null, null);
+
+        AttributeSet attributeSet = Robolectric.buildAttributeSet().build();
+        NotificationSoundPreference pref =
+                spy(new NotificationSoundPreference(mContext, attributeSet));
+        pref.setKey(mController.getPreferenceKey());
+        mController.handlePreferenceTreeClick(pref);
+
+        ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class);
+        verify(pref, times(1)).onPrepareRingtonePickerIntent(intentArgumentCaptor.capture());
+        assertEquals(RingtoneManager.TYPE_ALARM,
+                intentArgumentCaptor.getValue().getIntExtra(
+                        RingtoneManager.EXTRA_RINGTONE_TYPE, 0));
+    }
+
+    @Test
+    public void testOnPreferenceTreeClick_ringtoneSound() {
+        NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+        NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
+        channel.setSound(null, new AudioAttributes.Builder().setUsage(
+                AudioAttributes.USAGE_NOTIFICATION_RINGTONE).build());
+        mController.onResume(appRow, channel, null, null);
+
+        AttributeSet attributeSet = Robolectric.buildAttributeSet().build();
+        NotificationSoundPreference pref =
+                spy(new NotificationSoundPreference(mContext, attributeSet));
+        pref.setKey(mController.getPreferenceKey());
+        mController.handlePreferenceTreeClick(pref);
+
+        ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class);
+        verify(pref, times(1)).onPrepareRingtonePickerIntent(intentArgumentCaptor.capture());
+        assertEquals(RingtoneManager.TYPE_RINGTONE,
+                intentArgumentCaptor.getValue().getIntExtra(
+                        RingtoneManager.EXTRA_RINGTONE_TYPE, 0));
+    }
+
+    @Test
+    public void testOnPreferenceTreeClick_otherSound() {
+        NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+        NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
+        channel.setSound(null, new AudioAttributes.Builder().setUsage(
+                AudioAttributes.USAGE_UNKNOWN).build());
+        mController.onResume(appRow, channel, null, null);
+
+        AttributeSet attributeSet = Robolectric.buildAttributeSet().build();
+        NotificationSoundPreference pref =
+                spy(new NotificationSoundPreference(mContext, attributeSet));
+        pref.setKey(mController.getPreferenceKey());
+        mController.handlePreferenceTreeClick(pref);
+
+        ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class);
+        verify(pref, times(1)).onPrepareRingtonePickerIntent(intentArgumentCaptor.capture());
+        assertEquals(RingtoneManager.TYPE_NOTIFICATION,
+                intentArgumentCaptor.getValue().getIntExtra(
+                        RingtoneManager.EXTRA_RINGTONE_TYPE, 0));
+    }
+
+    @Test
     public void testOnActivityResult() {
         NotificationSoundPreference pref = mock(NotificationSoundPreference.class);
         when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(pref);
diff --git a/tests/robotests/src/com/android/settings/privacy/PermissionBarChartPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/privacy/PermissionBarChartPreferenceControllerTest.java
index 332156e..9888168 100644
--- a/tests/robotests/src/com/android/settings/privacy/PermissionBarChartPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/privacy/PermissionBarChartPreferenceControllerTest.java
@@ -16,6 +16,14 @@
 
 package com.android.settings.privacy;
 
+import static android.Manifest.permission_group.CALENDAR;
+import static android.Manifest.permission_group.CAMERA;
+import static android.Manifest.permission_group.CONTACTS;
+import static android.Manifest.permission_group.LOCATION;
+import static android.Manifest.permission_group.MICROPHONE;
+import static android.Manifest.permission_group.PHONE;
+import static android.Manifest.permission_group.SMS;
+
 import static com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE;
 import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
 
@@ -221,4 +229,27 @@
         verify(mFragment).setLoadingEnabled(false /* enabled */);
         verify(mPreference).updateLoadingState(false /* isLoading */);
     }
+
+    @Test
+    public void onPermissionUsageResult_shouldBeSorted() {
+        final List<RuntimePermissionUsageInfo> infos = new ArrayList<>();
+        infos.add(new RuntimePermissionUsageInfo(PHONE, 10));
+        infos.add(new RuntimePermissionUsageInfo(LOCATION, 10));
+        infos.add(new RuntimePermissionUsageInfo(CAMERA, 10));
+        infos.add(new RuntimePermissionUsageInfo(SMS, 1));
+        infos.add(new RuntimePermissionUsageInfo(MICROPHONE, 10));
+        infos.add(new RuntimePermissionUsageInfo(CONTACTS, 42));
+        infos.add(new RuntimePermissionUsageInfo(CALENDAR, 10));
+        mController.displayPreference(mScreen);
+
+        mController.onPermissionUsageResult(infos);
+
+        assertThat(infos.get(0).getName()).isEqualTo(CONTACTS);
+        assertThat(infos.get(1).getName()).isEqualTo(LOCATION);
+        assertThat(infos.get(2).getName()).isEqualTo(MICROPHONE);
+        assertThat(infos.get(3).getName()).isEqualTo(CAMERA);
+        assertThat(infos.get(4).getName()).isEqualTo(CALENDAR);
+        assertThat(infos.get(5).getName()).isEqualTo(PHONE);
+        assertThat(infos.get(6).getName()).isEqualTo(SMS);
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/system/SystemDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/system/SystemDashboardFragmentTest.java
index 75cd552..7bdc368 100644
--- a/tests/robotests/src/com/android/settings/system/SystemDashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/system/SystemDashboardFragmentTest.java
@@ -18,8 +18,17 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import android.content.Context;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
+import android.content.Context;
+import android.os.Bundle;
+
+import com.android.settings.aware.AwareFeatureProvider;
+import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settings.testutils.XmlTestUtils;
 import com.android.settings.testutils.shadow.SettingsShadowResources;
 import com.android.settings.testutils.shadow.ShadowUserManager;
@@ -38,11 +47,17 @@
 @Config(shadows = {SettingsShadowResources.class, ShadowUserManager.class})
 public class SystemDashboardFragmentTest {
 
+    private Context mContext;
+    private SystemDashboardFragment mFragment;
+
     @Before
     public void setup() {
         SettingsShadowResources.overrideResource(
                 com.android.internal.R.bool.config_supportSystemNavigationKeys, true);
         ShadowUserManager.getShadow().setIsAdminUser(true);
+        mContext = RuntimeEnvironment.application;
+        mFragment = spy(new SystemDashboardFragment());
+        when(mFragment.getContext()).thenReturn(mContext);
     }
 
     @After
@@ -52,13 +67,35 @@
 
     @Test
     public void testNonIndexableKeys_existInXmlLayout() {
-        final Context context = RuntimeEnvironment.application;
         final List<String> niks = SystemDashboardFragment.SEARCH_INDEX_DATA_PROVIDER
-                .getNonIndexableKeys(context);
+                .getNonIndexableKeys(mContext);
         final int xmlId = (new SystemDashboardFragment()).getPreferenceScreenResId();
 
-        final List<String> keys = XmlTestUtils.getKeysFromPreferenceXml(context, xmlId);
+        final List<String> keys = XmlTestUtils.getKeysFromPreferenceXml(mContext, xmlId);
 
         assertThat(keys).containsAllIn(niks);
     }
+
+    @Test
+    public void showRestrictionDialog_hasValidExtra_shouldShowDialog() {
+        final AwareFeatureProvider mProvider =
+                FakeFeatureFactory.setupForTest().mAwareFeatureProvider;
+        final Bundle bundle = new Bundle();
+        bundle.putBoolean(SystemDashboardFragment.EXTRA_SHOW_AWARE_DISABLED, true);
+        when(mFragment.getArguments()).thenReturn(bundle);
+
+        mFragment.showRestrictionDialog();
+
+        verify(mProvider).showRestrictionDialog(any());
+    }
+
+    @Test
+    public void showRestrictionDialog_hasInvalidExtra_shouldNotShowDialog() {
+        final AwareFeatureProvider mProvider =
+                FakeFeatureFactory.setupForTest().mAwareFeatureProvider;
+
+        mFragment.showRestrictionDialog();
+
+        verify(mProvider, never()).showRestrictionDialog(any());
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java
index bceba3c..a85fe10 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java
@@ -22,6 +22,8 @@
 import android.os.UserManager;
 import android.os.UserManager.EnforcingUser;
 
+import com.google.android.collect.Maps;
+
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Implementation;
 import org.robolectric.annotation.Implements;
@@ -48,6 +50,7 @@
     private boolean mIsQuietModeEnabled = false;
     private int[] profileIdsForUser = new int[0];
     private boolean mUserSwitchEnabled;
+    private final Map<Integer, Integer> mSameProfileGroupIds = Maps.newHashMap();
 
     public void addProfile(UserInfo userInfo) {
         mUserProfileInfos.add(userInfo);
@@ -138,6 +141,18 @@
         return sIsSupportsMultipleUsers;
     }
 
+    @Implementation
+    protected boolean isSameProfileGroup(@UserIdInt int userId, int otherUserId) {
+        return mSameProfileGroupIds.containsKey(userId)
+                && mSameProfileGroupIds.get(userId) == otherUserId
+                || mSameProfileGroupIds.containsKey(otherUserId)
+                && mSameProfileGroupIds.get(otherUserId) == userId;
+    }
+
+    public Map<Integer, Integer> getSameProfileGroupIds() {
+        return mSameProfileGroupIds;
+    }
+
     public void setSupportsMultipleUsers(boolean supports) {
         sIsSupportsMultipleUsers = supports;
     }
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 0a565cd..f177b5e 100644
--- a/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
@@ -105,6 +105,7 @@
     private static final int RSSI = -55;
     private static final int TX_LINK_SPEED = 123;
     private static final int RX_LINK_SPEED = 54;
+    private static final String SSID = "ssid";
     private static final String MAC_ADDRESS = WifiInfo.DEFAULT_MAC_ADDRESS;
     private static final String SECURITY = "None";
 
@@ -154,6 +155,8 @@
     @Mock
     private Preference mockSecurityPref;
     @Mock
+    private Preference mockSsidPref;
+    @Mock
     private Preference mockMacAddressPref;
     @Mock
     private Preference mockIpAddressPref;
@@ -245,6 +248,7 @@
         when(mockAccessPoint.getConfig()).thenReturn(mockWifiConfig);
         when(mockAccessPoint.getLevel()).thenReturn(LEVEL);
         when(mockAccessPoint.getSecurityString(false)).thenReturn(SECURITY);
+        when(mockAccessPoint.getSsidStr()).thenReturn(SSID);
         when(mockConnectivityManager.getNetworkInfo(any(Network.class)))
                 .thenReturn(mockNetworkInfo);
         doNothing().when(mockConnectivityManager).registerNetworkCallback(
@@ -314,6 +318,8 @@
                 .thenReturn(mockFrequencyPref);
         when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_SECURITY_PREF))
                 .thenReturn(mockSecurityPref);
+        when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_SSID_PREF))
+                .thenReturn(mockSsidPref);
         when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_MAC_ADDRESS_PREF))
                 .thenReturn(mockMacAddressPref);
         when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_IP_ADDRESS_PREF))
@@ -463,6 +469,50 @@
     }
 
     @Test
+    public void ssidPref_shouldHaveDetailTextSet() {
+        when(mockAccessPoint.isPasspoint()).thenReturn(true);
+        when(mockAccessPoint.isOsuProvider()).thenReturn(false);
+
+        displayAndResume();
+
+        verify(mockSsidPref, times(1)).setSummary(SSID);
+
+        when(mockAccessPoint.isPasspoint()).thenReturn(false);
+        when(mockAccessPoint.isOsuProvider()).thenReturn(true);
+
+        displayAndResume();
+
+        verify(mockSsidPref, times(2)).setSummary(SSID);
+    }
+
+    @Test
+    public void ssidPref_shouldShowIfPasspointOrOsu() {
+        when(mockAccessPoint.isPasspoint()).thenReturn(true);
+        when(mockAccessPoint.isOsuProvider()).thenReturn(false);
+
+        displayAndResume();
+
+        verify(mockSsidPref, times(1)).setVisible(true);
+
+        when(mockAccessPoint.isPasspoint()).thenReturn(false);
+        when(mockAccessPoint.isOsuProvider()).thenReturn(true);
+
+        displayAndResume();
+
+        verify(mockSsidPref, times(2)).setVisible(true);
+    }
+
+    @Test
+    public void ssidPref_shouldNotShowIfNotPasspoint() {
+        when(mockAccessPoint.isPasspoint()).thenReturn(false);
+        when(mockAccessPoint.isOsuProvider()).thenReturn(false);
+
+        displayAndResume();
+
+        verify(mockSsidPref).setVisible(false);
+    }
+
+    @Test
     public void macAddressPref_shouldHaveDetailTextSet() {
         displayAndResume();
 
diff --git a/tests/robotests/src/com/android/settings/wifi/details/WifiPrivacyPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/details/WifiPrivacyPreferenceControllerTest.java
index a1af8bf..2e588b5 100644
--- a/tests/robotests/src/com/android/settings/wifi/details/WifiPrivacyPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/details/WifiPrivacyPreferenceControllerTest.java
@@ -109,4 +109,20 @@
 
         assertThat(mDropDownPreference.isSelectable()).isFalse();
     }
+
+    @Test
+    public void testUpdateState_isNotPasspointNetwork_shouldBeSelectable() {
+        mPreferenceController.setIsPasspoint(false);
+        mPreferenceController.updateState(mDropDownPreference);
+
+        assertThat(mDropDownPreference.isSelectable()).isTrue();
+    }
+
+    @Test
+    public void testUpdateState_isPasspointNetwork_shouldNotSelectable() {
+        mPreferenceController.setIsPasspoint(true);
+        mPreferenceController.updateState(mDropDownPreference);
+
+        assertThat(mDropDownPreference.isSelectable()).isFalse();
+    }
 }