Merge "[Network Connection] Implement new UI changing"
diff --git a/Android.mk b/Android.mk
index e385b34..283575d 100644
--- a/Android.mk
+++ b/Android.mk
@@ -49,6 +49,7 @@
     settings-contextual-card-protos-lite \
     contextualcards \
     settings-logtags \
+    statsdprotolite \
     zxing-core-1.7
 
 LOCAL_PROGUARD_FLAG_FILES := proguard.flags
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 7625e78..5b78681 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -2390,6 +2390,19 @@
         </activity>
 
         <activity
+            android:name="Settings$ZenAccessDetailSettingsActivity"
+            android:label="@string/manage_zen_access_title"
+            android:excludeFromRecents="true">
+            <intent-filter>
+                <action android:name="android.settings.NOTIFICATION_POLICY_ACCESS_DETAIL_SETTINGS" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <data android:scheme="package" />
+            </intent-filter>
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                       android:value="com.android.settings.applications.specialaccess.zenaccess.ZenAccessDetails" />
+        </activity>
+
+        <activity
             android:name="Settings$ZenAccessSettingsActivity"
             android:label="@string/manage_zen_access_title"
             android:parentActivityName="Settings">
@@ -3124,6 +3137,18 @@
 
         <activity android:name=".homepage.contextualcards.ContextualCardFeedbackDialog"
                   android:theme="@android:style/Theme.DeviceDefault.Light.Dialog.Alert" />
+
+        <activity
+            android:name="Settings$WifiCallingDisclaimerActivity"
+            android:label="@string/wifi_calling_settings_title"
+            android:taskAffinity="com.android.settings">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                android:value="com.android.settings.wifi.calling.WifiCallingDisclaimerFragment" />
+        </activity>
         <!-- This is the longest AndroidManifest.xml ever. -->
     </application>
 </manifest>
diff --git a/color-check-baseline.xml b/color-check-baseline.xml
index e9f8d58..7074481 100644
--- a/color-check-baseline.xml
+++ b/color-check-baseline.xml
@@ -37,54 +37,6 @@
         priority="4"
         summary="Using hardcoded color"
         explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
-        errorLine1="            android:textColor=&quot;@color/bluetooth_dialog_text_color&quot;  />"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="res/layout/bluetooth_pin_confirm.xml"
-            line="44"
-            column="13"/>
-    </issue>
-
-    <issue
-        id="HardCodedColor"
-        severity="Error"
-        message="Avoid using hardcoded color"
-        category="Correctness"
-        priority="4"
-        summary="Using hardcoded color"
-        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
-        errorLine1="            android:textColor=&quot;@color/bluetooth_dialog_text_color&quot;"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="res/layout/bluetooth_pin_confirm.xml"
-            line="67"
-            column="13"/>
-    </issue>
-
-    <issue
-        id="HardCodedColor"
-        severity="Error"
-        message="Avoid using hardcoded color"
-        category="Correctness"
-        priority="4"
-        summary="Using hardcoded color"
-        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
-        errorLine1="            android:textColor=&quot;@color/bluetooth_dialog_text_color&quot;  />"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="res/layout/bluetooth_pin_confirm.xml"
-            line="77"
-            column="13"/>
-    </issue>
-
-    <issue
-        id="HardCodedColor"
-        severity="Error"
-        message="Avoid using hardcoded color"
-        category="Correctness"
-        priority="4"
-        summary="Using hardcoded color"
-        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
         errorLine1="                android:background=&quot;@color/lock_pattern_background&quot; />"
         errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
@@ -101,22 +53,6 @@
         priority="4"
         summary="Using hardcoded color"
         explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
-        errorLine1="    &lt;color name=&quot;black&quot;>#000&lt;/color>"
-        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="res/values/colors.xml"
-            line="18"
-            column="5"/>
-    </issue>
-
-    <issue
-        id="HardCodedColor"
-        severity="Error"
-        message="Avoid using hardcoded color"
-        category="Correctness"
-        priority="4"
-        summary="Using hardcoded color"
-        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
         errorLine1="  &lt;color name=&quot;switch_bar_background&quot;>#dadce0&lt;/color>"
         errorLine2="  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
@@ -133,8 +69,8 @@
         priority="4"
         summary="Using hardcoded color"
         explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
-        errorLine1="    &lt;color name=&quot;red&quot;>#F00&lt;/color>"
-        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        errorLine1="    &lt;color name=&quot;crypt_keeper_clock_background&quot;>#ff9a9a9a&lt;/color>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
             line="19"
@@ -165,8 +101,8 @@
         priority="4"
         summary="Using hardcoded color"
         explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
-        errorLine1="    &lt;color name=&quot;blue&quot;>#00F&lt;/color>"
-        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        errorLine1="    &lt;color name=&quot;crypt_keeper_clock_foreground&quot;>#ff666666&lt;/color>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
             line="20"
@@ -181,6 +117,22 @@
         priority="4"
         summary="Using hardcoded color"
         explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
+        errorLine1="    &lt;color name=&quot;crypt_keeper_clock_am_pm&quot;>#ff9a9a9a&lt;/color>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="res/values/colors.xml"
+            line="21"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="HardCodedColor"
+        severity="Error"
+        message="Avoid using hardcoded color"
+        category="Correctness"
+        priority="4"
+        summary="Using hardcoded color"
+        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
         errorLine1="  &lt;color name=&quot;homepage_accessibility_background&quot;>#783BE5&lt;/color>"
         errorLine2="  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
@@ -197,8 +149,8 @@
         priority="4"
         summary="Using hardcoded color"
         explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
-        errorLine1="    &lt;color name=&quot;bluetooth_dialog_text_color&quot;>#8a000000&lt;/color>"
-        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        errorLine1="    &lt;color name=&quot;crypt_keeper_password_background&quot;>#70606060&lt;/color>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
             line="22"
@@ -229,8 +181,8 @@
         priority="4"
         summary="Using hardcoded color"
         explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
-        errorLine1="    &lt;color name=&quot;crypt_keeper_clock_background&quot;>#ff9a9a9a&lt;/color>"
-        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        errorLine1="    &lt;color name=&quot;divider_color&quot;>#20ffffff&lt;/color>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
             line="24"
@@ -261,75 +213,11 @@
         priority="4"
         summary="Using hardcoded color"
         explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
-        errorLine1="    &lt;color name=&quot;crypt_keeper_clock_foreground&quot;>#ff666666&lt;/color>"
-        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="res/values/colors.xml"
-            line="25"
-            column="5"/>
-    </issue>
-
-    <issue
-        id="HardCodedColor"
-        severity="Error"
-        message="Avoid using hardcoded color"
-        category="Correctness"
-        priority="4"
-        summary="Using hardcoded color"
-        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
-        errorLine1="    &lt;color name=&quot;crypt_keeper_clock_am_pm&quot;>#ff9a9a9a&lt;/color>"
-        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="res/values/colors.xml"
-            line="26"
-            column="5"/>
-    </issue>
-
-    <issue
-        id="HardCodedColor"
-        severity="Error"
-        message="Avoid using hardcoded color"
-        category="Correctness"
-        priority="4"
-        summary="Using hardcoded color"
-        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
-        errorLine1="    &lt;color name=&quot;crypt_keeper_password_background&quot;>#70606060&lt;/color>"
-        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="res/values/colors.xml"
-            line="27"
-            column="5"/>
-    </issue>
-
-    <issue
-        id="HardCodedColor"
-        severity="Error"
-        message="Avoid using hardcoded color"
-        category="Correctness"
-        priority="4"
-        summary="Using hardcoded color"
-        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
-        errorLine1="    &lt;color name=&quot;divider_color&quot;>#20ffffff&lt;/color>"
-        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="res/values/colors.xml"
-            line="29"
-            column="5"/>
-    </issue>
-
-    <issue
-        id="HardCodedColor"
-        severity="Error"
-        message="Avoid using hardcoded color"
-        category="Correctness"
-        priority="4"
-        summary="Using hardcoded color"
-        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
         errorLine1="    &lt;color name=&quot;setup_lock_pattern_view_success_color_dark&quot;>#ff84ffff&lt;/color>"
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="32"
+            line="27"
             column="5"/>
     </issue>
 
@@ -345,7 +233,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="34"
+            line="29"
             column="5"/>
     </issue>
 
@@ -361,7 +249,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="35"
+            line="30"
             column="5"/>
     </issue>
 
@@ -377,7 +265,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="36"
+            line="31"
             column="5"/>
     </issue>
 
@@ -393,7 +281,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="38"
+            line="33"
             column="5"/>
     </issue>
 
@@ -409,7 +297,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="39"
+            line="34"
             column="5"/>
     </issue>
 
@@ -425,7 +313,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="41"
+            line="36"
             column="5"/>
     </issue>
 
@@ -441,7 +329,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="46"
+            line="41"
             column="5"/>
     </issue>
 
@@ -457,7 +345,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="47"
+            line="42"
             column="5"/>
     </issue>
 
@@ -473,7 +361,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="49"
+            line="44"
             column="5"/>
     </issue>
 
@@ -489,7 +377,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="50"
+            line="45"
             column="5"/>
     </issue>
 
@@ -505,7 +393,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="54"
+            line="49"
             column="5"/>
     </issue>
 
@@ -521,7 +409,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="57"
+            line="52"
             column="5"/>
     </issue>
 
@@ -537,7 +425,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="60"
+            line="55"
             column="5"/>
     </issue>
 
@@ -553,7 +441,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="61"
+            line="56"
             column="5"/>
     </issue>
 
@@ -569,7 +457,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="62"
+            line="57"
             column="5"/>
     </issue>
 
@@ -585,7 +473,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="63"
+            line="58"
             column="5"/>
     </issue>
 
@@ -597,11 +485,11 @@
         priority="4"
         summary="Using hardcoded color"
         explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
-        errorLine1="    &lt;color name=&quot;switch_bar_background&quot;>#ff80868B&lt;/color>"
-        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        errorLine1="    &lt;color name=&quot;switch_bar_background&quot;>#757575&lt;/color>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="64"
+            line="59"
             column="5"/>
     </issue>
 
@@ -617,7 +505,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="66"
+            line="61"
             column="5"/>
     </issue>
 
@@ -633,7 +521,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="67"
+            line="62"
             column="5"/>
     </issue>
 
@@ -649,7 +537,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="68"
+            line="63"
             column="5"/>
     </issue>
 
@@ -665,7 +553,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="69"
+            line="64"
             column="5"/>
     </issue>
 
@@ -681,7 +569,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="70"
+            line="65"
             column="5"/>
     </issue>
 
@@ -697,7 +585,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="71"
+            line="66"
             column="5"/>
     </issue>
 
@@ -713,7 +601,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="72"
+            line="67"
             column="5"/>
     </issue>
 
@@ -729,7 +617,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="73"
+            line="68"
             column="5"/>
     </issue>
 
@@ -745,7 +633,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="74"
+            line="69"
             column="5"/>
     </issue>
 
@@ -761,7 +649,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="75"
+            line="70"
             column="5"/>
     </issue>
 
@@ -777,7 +665,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="76"
+            line="71"
             column="5"/>
     </issue>
 
@@ -793,7 +681,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="78"
+            line="73"
             column="5"/>
     </issue>
 
@@ -809,7 +697,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="81"
+            line="76"
             column="5"/>
     </issue>
 
@@ -825,7 +713,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="84"
+            line="79"
             column="5"/>
     </issue>
 
@@ -841,7 +729,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="87"
+            line="82"
             column="5"/>
     </issue>
 
@@ -857,7 +745,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="90"
+            line="85"
             column="5"/>
     </issue>
 
@@ -873,7 +761,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="91"
+            line="86"
             column="5"/>
     </issue>
 
@@ -889,7 +777,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="92"
+            line="87"
             column="5"/>
     </issue>
 
@@ -905,7 +793,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="93"
+            line="88"
             column="5"/>
     </issue>
 
@@ -921,7 +809,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="94"
+            line="89"
             column="5"/>
     </issue>
 
@@ -937,7 +825,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="95"
+            line="90"
             column="5"/>
     </issue>
 
@@ -953,7 +841,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="96"
+            line="91"
             column="5"/>
     </issue>
 
@@ -969,7 +857,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="97"
+            line="92"
             column="5"/>
     </issue>
 
@@ -985,7 +873,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="98"
+            line="93"
             column="5"/>
     </issue>
 
@@ -1001,7 +889,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="99"
+            line="94"
             column="5"/>
     </issue>
 
@@ -1017,7 +905,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="100"
+            line="95"
             column="5"/>
     </issue>
 
@@ -1033,7 +921,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="101"
+            line="96"
             column="5"/>
     </issue>
 
@@ -1049,7 +937,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="102"
+            line="97"
             column="5"/>
     </issue>
 
@@ -1065,7 +953,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="103"
+            line="98"
             column="5"/>
     </issue>
 
@@ -1081,7 +969,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="104"
+            line="99"
             column="5"/>
     </issue>
 
@@ -1097,7 +985,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="105"
+            line="100"
             column="5"/>
     </issue>
 
@@ -1113,7 +1001,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="106"
+            line="102"
             column="5"/>
     </issue>
 
@@ -1129,7 +1017,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="110"
+            line="108"
             column="5"/>
     </issue>
 
@@ -1145,7 +1033,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="115"
+            line="113"
             column="5"/>
     </issue>
 
@@ -1161,7 +1049,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="116"
+            line="114"
             column="5"/>
     </issue>
 
@@ -1177,7 +1065,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="117"
+            line="115"
             column="5"/>
     </issue>
 
@@ -1193,7 +1081,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="118"
+            line="116"
             column="5"/>
     </issue>
 
@@ -1209,7 +1097,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="119"
+            line="117"
             column="5"/>
     </issue>
 
@@ -1225,7 +1113,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="120"
+            line="118"
             column="5"/>
     </issue>
 
@@ -1241,7 +1129,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="123"
+            line="121"
             column="5"/>
     </issue>
 
@@ -1257,7 +1145,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="124"
+            line="122"
             column="5"/>
     </issue>
 
@@ -1273,7 +1161,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="125"
+            line="123"
             column="5"/>
     </issue>
 
@@ -1289,7 +1177,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="126"
+            line="124"
             column="5"/>
     </issue>
 
@@ -1305,7 +1193,55 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="127"
+            line="125"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="HardCodedColor"
+        severity="Error"
+        message="Avoid using hardcoded color"
+        category="Correctness"
+        priority="4"
+        summary="Using hardcoded color"
+        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
+        errorLine1="    &lt;color name=&quot;notification_block_color&quot;>#ffff0000&lt;/color>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="res/values/colors.xml"
+            line="128"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="HardCodedColor"
+        severity="Error"
+        message="Avoid using hardcoded color"
+        category="Correctness"
+        priority="4"
+        summary="Using hardcoded color"
+        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
+        errorLine1="    &lt;color name=&quot;notification_silence_color&quot;>#fbbc04&lt;/color>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="res/values/colors.xml"
+            line="129"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="HardCodedColor"
+        severity="Error"
+        message="Avoid using hardcoded color"
+        category="Correctness"
+        priority="4"
+        summary="Using hardcoded color"
+        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
+        errorLine1="    &lt;color name=&quot;notification_alert_color&quot;>#30a751&lt;/color>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="res/values/colors.xml"
+            line="130"
             column="5"/>
     </issue>
 
@@ -1321,7 +1257,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="133"
+            line="136"
             column="5"/>
     </issue>
 
@@ -1337,7 +1273,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="136"
+            line="139"
             column="5"/>
     </issue>
 
@@ -1353,7 +1289,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="137"
+            line="140"
             column="5"/>
     </issue>
 
@@ -1369,7 +1305,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="138"
+            line="141"
             column="5"/>
     </issue>
 
@@ -1653,12 +1589,12 @@
         priority="4"
         summary="Using hardcoded color"
         explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
-        errorLine1="                android:color=&quot;@color/homepage_about_background&quot; />"
-        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        errorLine1="            android:color=&quot;@color/homepage_about_background&quot; />"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/drawable/ic_homepage_about.xml"
-            line="23"
-            column="17"/>
+            line="24"
+            column="13"/>
     </issue>
 
     <issue
@@ -1669,12 +1605,12 @@
         priority="4"
         summary="Using hardcoded color"
         explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
-        errorLine1="                android:color=&quot;@color/homepage_accessibility_background&quot; />"
-        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        errorLine1="            android:color=&quot;@color/homepage_accessibility_background&quot; />"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/drawable/ic_homepage_accessibility.xml"
-            line="23"
-            column="17"/>
+            line="24"
+            column="13"/>
     </issue>
 
     <issue
@@ -1685,12 +1621,12 @@
         priority="4"
         summary="Using hardcoded color"
         explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
-        errorLine1="                android:color=&quot;@color/homepage_accessibility_background&quot; />"
-        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        errorLine1="            android:color=&quot;@color/homepage_accessibility_background&quot; />"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/drawable/ic_homepage_accessibility.xml"
-            line="23"
-            column="17"/>
+            line="24"
+            column="13"/>
     </issue>
 
     <issue
@@ -1701,12 +1637,12 @@
         priority="4"
         summary="Using hardcoded color"
         explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
-        errorLine1="                android:color=&quot;@color/homepage_accounts_background&quot; />"
-        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        errorLine1="            android:color=&quot;@color/homepage_accounts_background&quot; />"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/drawable/ic_homepage_accounts.xml"
-            line="23"
-            column="17"/>
+            line="24"
+            column="13"/>
     </issue>
 
     <issue
@@ -1717,12 +1653,12 @@
         priority="4"
         summary="Using hardcoded color"
         explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
-        errorLine1="                android:color=&quot;@color/homepage_app_and_notification_background&quot; />"
-        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        errorLine1="            android:color=&quot;@color/homepage_app_and_notification_background&quot; />"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/drawable/ic_homepage_apps.xml"
-            line="23"
-            column="17"/>
+            line="24"
+            column="13"/>
     </issue>
 
     <issue
@@ -1733,12 +1669,12 @@
         priority="4"
         summary="Using hardcoded color"
         explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
-        errorLine1="                android:color=&quot;@color/homepage_battery_background&quot; />"
-        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        errorLine1="            android:color=&quot;@color/homepage_battery_background&quot; />"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/drawable/ic_homepage_battery.xml"
-            line="23"
-            column="17"/>
+            line="24"
+            column="13"/>
     </issue>
 
     <issue
@@ -1749,12 +1685,12 @@
         priority="4"
         summary="Using hardcoded color"
         explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
-        errorLine1="                android:color=&quot;@color/homepage_connected_device_background&quot; />"
-        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        errorLine1="            android:color=&quot;@color/homepage_connected_device_background&quot; />"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/drawable/ic_homepage_connected_device.xml"
-            line="23"
-            column="17"/>
+            line="24"
+            column="13"/>
     </issue>
 
     <issue
@@ -1765,12 +1701,12 @@
         priority="4"
         summary="Using hardcoded color"
         explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
-        errorLine1="                android:color=&quot;@color/homepage_display_background&quot; />"
-        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        errorLine1="            android:color=&quot;@color/homepage_display_background&quot; />"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/drawable/ic_homepage_display.xml"
-            line="23"
-            column="17"/>
+            line="24"
+            column="13"/>
     </issue>
 
     <issue
@@ -1781,28 +1717,12 @@
         priority="4"
         summary="Using hardcoded color"
         explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
-        errorLine1="        android:color=&quot;@color/homepage_generic_icon_background&quot; />"
-        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="res/drawable/ic_homepage_generic_background.xml"
-            line="20"
-            column="9"/>
-    </issue>
-
-    <issue
-        id="HardCodedColor"
-        severity="Error"
-        message="Avoid using hardcoded color"
-        category="Correctness"
-        priority="4"
-        summary="Using hardcoded color"
-        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
-        errorLine1="                android:color=&quot;@color/homepage_location_background&quot;/>"
-        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        errorLine1="            android:color=&quot;@color/homepage_location_background&quot; />"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/drawable/ic_homepage_location.xml"
-            line="23"
-            column="17"/>
+            line="24"
+            column="13"/>
     </issue>
 
     <issue
@@ -1813,12 +1733,12 @@
         priority="4"
         summary="Using hardcoded color"
         explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
-        errorLine1="                android:color=&quot;@color/homepage_network_background&quot; />"
-        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        errorLine1="            android:color=&quot;@color/homepage_network_background&quot; />"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/drawable/ic_homepage_network.xml"
-            line="23"
-            column="17"/>
+            line="24"
+            column="13"/>
     </issue>
 
     <issue
@@ -1829,12 +1749,12 @@
         priority="4"
         summary="Using hardcoded color"
         explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
-        errorLine1="                android:color=&quot;@color/homepage_privacy_background&quot;/>"
-        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        errorLine1="            android:color=&quot;@color/homepage_privacy_background&quot; />"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/drawable/ic_homepage_privacy.xml"
-            line="23"
-            column="17"/>
+            line="24"
+            column="13"/>
     </issue>
 
     <issue
@@ -1845,12 +1765,12 @@
         priority="4"
         summary="Using hardcoded color"
         explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
-        errorLine1="                android:color=&quot;@color/homepage_security_background&quot; />"
-        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        errorLine1="            android:color=&quot;@color/homepage_security_background&quot; />"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/drawable/ic_homepage_security.xml"
-            line="23"
-            column="17"/>
+            line="24"
+            column="13"/>
     </issue>
 
     <issue
@@ -1861,12 +1781,12 @@
         priority="4"
         summary="Using hardcoded color"
         explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
-        errorLine1="                android:color=&quot;@color/homepage_sound_background&quot; />"
-        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        errorLine1="            android:color=&quot;@color/homepage_sound_background&quot; />"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/drawable/ic_homepage_sound.xml"
-            line="23"
-            column="17"/>
+            line="24"
+            column="13"/>
     </issue>
 
     <issue
@@ -1877,12 +1797,12 @@
         priority="4"
         summary="Using hardcoded color"
         explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
-        errorLine1="                android:color=&quot;@color/homepage_storage_background&quot; />"
-        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        errorLine1="            android:color=&quot;@color/homepage_storage_background&quot; />"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/drawable/ic_homepage_storage.xml"
-            line="23"
-            column="17"/>
+            line="24"
+            column="13"/>
     </issue>
 
     <issue
@@ -1893,12 +1813,12 @@
         priority="4"
         summary="Using hardcoded color"
         explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
-        errorLine1="                android:color=&quot;@color/homepage_support_background&quot; />"
-        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        errorLine1="            android:color=&quot;@color/homepage_support_background&quot; />"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/drawable/ic_homepage_support.xml"
-            line="23"
-            column="17"/>
+            line="24"
+            column="13"/>
     </issue>
 
     <issue
@@ -1909,12 +1829,12 @@
         priority="4"
         summary="Using hardcoded color"
         explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
-        errorLine1="                android:color=&quot;@color/homepage_support_background&quot; />"
-        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        errorLine1="            android:color=&quot;@color/homepage_support_background&quot; />"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/drawable/ic_homepage_support.xml"
-            line="23"
-            column="17"/>
+            line="24"
+            column="13"/>
     </issue>
 
     <issue
@@ -1925,11 +1845,107 @@
         priority="4"
         summary="Using hardcoded color"
         explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
-        errorLine1="                android:color=&quot;@color/homepage_system_background&quot; />"
-        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        errorLine1="            android:color=&quot;@color/homepage_system_background&quot; />"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/drawable/ic_homepage_system_dashboard.xml"
-            line="23"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="HardCodedColor"
+        severity="Error"
+        message="Avoid using hardcoded color"
+        category="Correctness"
+        priority="4"
+        summary="Using hardcoded color"
+        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
+        errorLine1="                    android:color=&quot;@color/notification_alert_color&quot;/>"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="res/drawable/ic_notification_alert.xml"
+            line="27"
+            column="21"/>
+    </issue>
+
+    <issue
+        id="HardCodedColor"
+        severity="Error"
+        message="Avoid using hardcoded color"
+        category="Correctness"
+        priority="4"
+        summary="Using hardcoded color"
+        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
+        errorLine1="                android:fillColor=&quot;@color/notification_alert_color&quot;"
+        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="res/drawable/ic_notification_alert.xml"
+            line="39"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="HardCodedColor"
+        severity="Error"
+        message="Avoid using hardcoded color"
+        category="Correctness"
+        priority="4"
+        summary="Using hardcoded color"
+        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
+        errorLine1="                    android:color=&quot;@color/notification_block_color&quot;/>"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="res/drawable/ic_notification_block.xml"
+            line="27"
+            column="21"/>
+    </issue>
+
+    <issue
+        id="HardCodedColor"
+        severity="Error"
+        message="Avoid using hardcoded color"
+        category="Correctness"
+        priority="4"
+        summary="Using hardcoded color"
+        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
+        errorLine1="                android:fillColor=&quot;@color/notification_block_color&quot;"
+        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="res/drawable/ic_notification_block.xml"
+            line="39"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="HardCodedColor"
+        severity="Error"
+        message="Avoid using hardcoded color"
+        category="Correctness"
+        priority="4"
+        summary="Using hardcoded color"
+        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
+        errorLine1="                    android:color=&quot;@color/notification_silence_color&quot;/>"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="res/drawable/ic_notification_silence.xml"
+            line="27"
+            column="21"/>
+    </issue>
+
+    <issue
+        id="HardCodedColor"
+        severity="Error"
+        message="Avoid using hardcoded color"
+        category="Correctness"
+        priority="4"
+        summary="Using hardcoded color"
+        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
+        errorLine1="                android:fillColor=&quot;@color/notification_silence_color&quot;"
+        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="res/drawable/ic_notification_silence.xml"
+            line="39"
             column="17"/>
     </issue>
 
@@ -2437,12 +2453,12 @@
         priority="4"
         summary="Using hardcoded color"
         explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
-        errorLine1="    &lt;string name=&quot;sync_plug&quot; msgid=&quot;3905078969081888738&quot;>&quot;‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‏‏‎‎‎‏‏‎‎‎‏‏‎‏‎‎‎‎‎‏‎‏‎‎‎‎‏‏‏‏‎‎‎‏‏‏‏‏‏‏‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‎‏‎‎‏‏‎&quot;&lt;font fgcolor=&quot;#ffffffff&quot;>&quot;‎‏‎‎‏‏‏‎Welcome to Google sync!‎‏‎‎‏‏‎&quot;&lt;/font>&quot;‎‏‎‎‏‏‏‎ ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎A Google approach to syncing data to allow access to your contacts, appointments, and more from wherever you are.‎‏‎‎‏‎&quot;&lt;/string>"
-        errorLine2="                                                                                                                                                                       ~~~~~~~~~~~~~~~~~~~">
+        errorLine1="    &lt;string name=&quot;sync_plug&quot; msgid=&quot;3905078969081888738&quot;>&quot;‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‏‏‎‎‎‏‏‎‎‎‏‏‎‏‎‎‎‎‎‏‎‏‎‎‎‎‏‏‏‏‎‎‎‏‏‏‏‏‏‏‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‎‏‎‎‏‏‎&quot;&lt;font fgcolor=&quot;#ffffffff&quot;>&quot;‎‏‎‎‏‏‏‎Welcome to Google sync!‎‏‎‎‏‏‎&quot;&lt;/font>&quot;‎‏‎‎‏‏‏‎ ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎A Google approach to syncing data to allow access to your contacts, appointments, and more from wherever you are.‎‏‎‎‏‎&quot;&lt;/string>"
+        errorLine2="                                                                                                                                                                        ~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values-en-rXC/strings.xml"
-            line="2533"
-            column="168"/>
+            line="2580"
+            column="169"/>
     </issue>
 
     <issue
@@ -2457,7 +2473,7 @@
         errorLine2="                                                               ~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values-en-rAU/strings.xml"
-            line="2534"
+            line="2581"
             column="64"/>
     </issue>
 
@@ -2473,7 +2489,7 @@
         errorLine2="                                                               ~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values-en-rCA/strings.xml"
-            line="2534"
+            line="2581"
             column="64"/>
     </issue>
 
@@ -2489,7 +2505,7 @@
         errorLine2="                                                               ~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values-en-rGB/strings.xml"
-            line="2534"
+            line="2581"
             column="64"/>
     </issue>
 
@@ -2505,7 +2521,7 @@
         errorLine2="                                                               ~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values-en-rIN/strings.xml"
-            line="2534"
+            line="2581"
             column="64"/>
     </issue>
 
@@ -2521,7 +2537,7 @@
         errorLine2="                                   ~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/strings.xml"
-            line="5885"
+            line="6026"
             column="36"/>
     </issue>
 
@@ -2537,7 +2553,7 @@
         errorLine2="                                        ^">
         <location
             file="res/values/styles.xml"
-            line="174"
+            line="163"
             column="41"/>
     </issue>
 
@@ -2553,7 +2569,7 @@
         errorLine2="                                           ^">
         <location
             file="res/values/styles.xml"
-            line="388"
+            line="380"
             column="44"/>
     </issue>
 
@@ -2569,7 +2585,7 @@
         errorLine2="                                           ^">
         <location
             file="res/values/styles.xml"
-            line="394"
+            line="386"
             column="44"/>
     </issue>
 
@@ -2585,7 +2601,7 @@
         errorLine2="                                           ^">
         <location
             file="res/values/styles.xml"
-            line="395"
+            line="387"
             column="44"/>
     </issue>
 
@@ -2601,7 +2617,7 @@
         errorLine2="                                 ^">
         <location
             file="res/values/styles.xml"
-            line="430"
+            line="423"
             column="34"/>
     </issue>
 
@@ -2729,7 +2745,7 @@
         errorLine2="                                            ^">
         <location
             file="res/values/themes.xml"
-            line="166"
+            line="169"
             column="45"/>
     </issue>
 
@@ -2745,7 +2761,7 @@
         errorLine2="                                                ^">
         <location
             file="res/values/themes.xml"
-            line="167"
+            line="170"
             column="49"/>
     </issue>
 
@@ -2761,7 +2777,7 @@
         errorLine2="                                            ^">
         <location
             file="res/values/themes.xml"
-            line="175"
+            line="178"
             column="45"/>
     </issue>
 
@@ -2777,7 +2793,7 @@
         errorLine2="                                                ^">
         <location
             file="res/values/themes.xml"
-            line="176"
+            line="179"
             column="49"/>
     </issue>
 
@@ -2793,7 +2809,7 @@
         errorLine2="                                      ^">
         <location
             file="res/values/themes.xml"
-            line="192"
+            line="195"
             column="39"/>
     </issue>
 
@@ -2809,7 +2825,7 @@
         errorLine2="                                       ^">
         <location
             file="res/values/themes.xml"
-            line="193"
+            line="196"
             column="40"/>
     </issue>
 
@@ -2825,7 +2841,7 @@
         errorLine2="                                     ^">
         <location
             file="res/values/themes.xml"
-            line="194"
+            line="197"
             column="38"/>
     </issue>
 
diff --git a/res/color/circle_outline_color.xml b/res/color/circle_outline_color.xml
new file mode 100644
index 0000000..eb4e83c
--- /dev/null
+++ b/res/color/circle_outline_color.xml
@@ -0,0 +1,20 @@
+<?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.
+  -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:alpha="0.14"
+          android:color="?android:attr/colorForeground"/>
+</selector>
\ No newline at end of file
diff --git a/res/drawable/circle_outline.xml b/res/drawable/circle_outline.xml
new file mode 100644
index 0000000..1b2631d
--- /dev/null
+++ b/res/drawable/circle_outline.xml
@@ -0,0 +1,22 @@
+<?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.
+  -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+       android:shape="oval">
+    <stroke
+        android:width="1dp"
+        android:color="@color/circle_outline_color"/>
+</shape>
diff --git a/res/drawable/ic_face_header.xml b/res/drawable/ic_face_header.xml
index 0bf2c07..15ea7ae 100644
--- a/res/drawable/ic_face_header.xml
+++ b/res/drawable/ic_face_header.xml
@@ -1,4 +1,4 @@
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
   ~ Copyright (C) 2018 The Android Open Source Project
   ~
   ~ Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,10 +15,17 @@
   -->
 
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:height="32dp"
     android:width="32dp"
+    android:height="32dp"
     android:tint="?android:attr/colorPrimary"
-    android:viewportWidth="24"
-    android:viewportHeight="24">
-    <path android:fillColor="#000" android:pathData="M9,11.75A1.25,1.25 0 0,0 7.75,13A1.25,1.25 0 0,0 9,14.25A1.25,1.25 0 0,0 10.25,13A1.25,1.25 0 0,0 9,11.75M15,11.75A1.25,1.25 0 0,0 13.75,13A1.25,1.25 0 0,0 15,14.25A1.25,1.25 0 0,0 16.25,13A1.25,1.25 0 0,0 15,11.75M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M12,20C7.59,20 4,16.41 4,12C4,11.71 4,11.42 4.05,11.14C6.41,10.09 8.28,8.16 9.26,5.77C11.07,8.33 14.05,10 17.42,10C18.2,10 18.95,9.91 19.67,9.74C19.88,10.45 20,11.21 20,12C20,16.41 16.41,20 12,20Z" />
+    android:viewportHeight="24"
+    android:viewportWidth="24">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M 12 13 C 13.1045694997 13 14 13.8954305003 14 15 C 14 16.1045694997 13.1045694997 17 12 17 C 10.8954305003 17 10 16.1045694997 10 15 C 10 13.8954305003 10.8954305003 13 12 13 Z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M18.5,1C16.01,1,14,3.01,14,5.5V8H6c-1.1,0-2,0.9-2,2v10c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V10c0-1.1-0.9-2-2-2h-2V5.5 C16,4.12,17.12,3,18.5,3C19.88,3,21,4.12,21,5.5V6h2V5.5C23,3.01,20.99,1,18.5,1z M18,10v10H6V10H18z" />
+    <path android:pathData="M0,0h24v24H0V0z" />
 </vector>
\ No newline at end of file
diff --git a/res/drawable/ic_gray_scale_24dp.xml b/res/drawable/ic_gray_scale_24dp.xml
new file mode 100644
index 0000000..3fda134
--- /dev/null
+++ b/res/drawable/ic_gray_scale_24dp.xml
@@ -0,0 +1,25 @@
+<!--
+  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.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24"
+        android:viewportHeight="24">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10s10,-4.48 10,-10S17.52,2 12,2zM11,19.93C7.06,19.44 4,16.08 4,12s3.05,-7.44 7,-7.93V19.93zM13,4.07C14.03,4.2 15,4.52 15.87,5H13V4.07zM13,7h5.24c0.25,0.31 0.48,0.65 0.68,1H13V7zM13,10h6.74c0.08,0.33 0.15,0.66 0.19,1H13V10zM13,19.93V19h2.87C15,19.48 14.03,19.8 13,19.93zM18.24,17H13v-1h5.92C18.72,16.35 18.49,16.69 18.24,17zM19.74,14H13v-1h6.93C19.89,13.34 19.82,13.67 19.74,14z"/>
+</vector>
+
diff --git a/res/drawable/ic_notification_alert.xml b/res/drawable/ic_notification_alert.xml
new file mode 100644
index 0000000..07e7b48
--- /dev/null
+++ b/res/drawable/ic_notification_alert.xml
@@ -0,0 +1,43 @@
+<?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.
+-->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:id="@+id/back">
+        <shape android:shape="oval">
+            <solid
+                android:color="@android:color/transparent" />
+            <size
+                android:height="48dp"
+                android:width="48dp"/>
+            <stroke android:width="1dp"
+                    android:color="@color/notification_alert_color"/>
+        </shape>
+    </item>
+    <item
+        android:id="@+id/fore"
+        android:gravity="center">
+        <vector
+            android:height="24dp"
+            android:width="24dp"
+            android:viewportHeight="24"
+            android:viewportWidth="24">
+            <path
+                android:fillColor="@color/notification_alert_color"
+                android:pathData="M7.58 4.08L6.15 2.65C3.75 4.48 2.17 7.3 2.03 10.5h2c.15-2.65 1.51-4.97 3.55-6.42zm12.39 6.42h2c-.15-3.2-1.73-6.02-4.12-7.85l-1.42 1.43c2.02 1.45 3.39 3.77 3.54 6.42zM18 11c0-3.07-1.64-5.64-4.5-6.32V4c0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5v.68C7.63 5.36 6 7.92 6 11v5l-2 2v1h16v-1l-2-2v-5zm-6 11c.14 0 .27-.01.4-.04.65-.14 1.18-.58 1.44-1.18.1-.24.15-.5.15-.78h-4c.01 1.1.9 2 2.01 2z"/>
+        </vector>
+    </item>
+</layer-list>
\ No newline at end of file
diff --git a/res/drawable/ic_notification_block.xml b/res/drawable/ic_notification_block.xml
new file mode 100644
index 0000000..d4f0a2a
--- /dev/null
+++ b/res/drawable/ic_notification_block.xml
@@ -0,0 +1,43 @@
+<?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.
+-->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:id="@+id/back">
+        <shape android:shape="oval">
+            <solid
+                android:color="@android:color/transparent" />
+            <size
+                android:height="48dp"
+                android:width="48dp"/>
+            <stroke android:width="1dp"
+                    android:color="@color/notification_block_color"/>
+        </shape>
+    </item>
+    <item
+        android:id="@+id/fore"
+        android:gravity="center">
+        <vector
+            android:height="24dp"
+            android:width="24dp"
+            android:viewportHeight="24"
+            android:viewportWidth="24">
+            <path
+                android:fillColor="@color/notification_block_color"
+                android:pathData="M12.0,2.0C6.48,2.0 2.0,6.48 2.0,12.0s4.48,10.0 10.0,10.0 10.0,-4.48 10.0,-10.0S17.52,2.0 12.0,2.0zM4.0,12.0c0.0,-4.42 3.58,-8.0 8.0,-8.0 1.85,0.0 3.5,0.63 4.9,1.69L5.69,16.9C4.63,15.55 4.0,13.85 4.0,12.0zm8.0,8.0c-1.85,0.0 -3.55,-0.63 -4.9,-1.69L18.31,7.1C19.37,8.45 20.0,10.15 20.0,12.0c0.0,4.42 -3.58,8.0 -8.0,8.0z"/>
+        </vector>
+    </item>
+</layer-list>
\ No newline at end of file
diff --git a/res/drawable/ic_notification_silence.xml b/res/drawable/ic_notification_silence.xml
new file mode 100644
index 0000000..673340f
--- /dev/null
+++ b/res/drawable/ic_notification_silence.xml
@@ -0,0 +1,43 @@
+<?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.
+-->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:id="@+id/back">
+        <shape android:shape="oval">
+            <solid
+                android:color="@android:color/transparent" />
+            <size
+                android:height="48dp"
+                android:width="48dp"/>
+            <stroke android:width="1dp"
+                    android:color="@color/notification_silence_color"/>
+        </shape>
+    </item>
+    <item
+        android:id="@+id/fore"
+        android:gravity="center">
+        <vector
+            android:height="24dp"
+            android:width="24dp"
+            android:viewportHeight="24"
+            android:viewportWidth="24">
+            <path
+                android:fillColor="@color/notification_silence_color"
+                android:pathData="M20 18.69L7.84 6.14 5.27 3.49 4 4.76l2.8 2.8v.01c-.52.99-.8 2.16-.8 3.42v5l-2 2v1h13.73l2 2L21 19.72l-1-1.03zM12 22c1.11 0 2-.89 2-2h-4c0 1.11.89 2 2 2zm6-7.32V11c0-3.08-1.64-5.64-4.5-6.32V4c0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5v.68c-.15.03-.29.08-.42.12-.1.03-.2.07-.3.11h-.01c-.01 0-.01 0-.02.01-.23.09-.46.2-.68.31 0 0-.01 0-.01.01L18 14.68z" />
+        </vector>
+    </item>
+</layer-list>
\ No newline at end of file
diff --git a/res/drawable/ic_qrcode_24dp.xml b/res/drawable/ic_qrcode_24dp.xml
index ff7806f..6928cb9 100644
--- a/res/drawable/ic_qrcode_24dp.xml
+++ b/res/drawable/ic_qrcode_24dp.xml
@@ -2,7 +2,8 @@
     android:width="24dp"
     android:height="24dp"
     android:viewportWidth="24"
-    android:viewportHeight="24">
+    android:viewportHeight="24"
+    android:tint="?android:attr/colorAccent">
   <path
       android:fillColor="#FF000000"
       android:pathData="M7,4v3H4V4H7M9,2H2v7h7V2L9,2z"/>
diff --git a/res/drawable/ic_scan_24dp.xml b/res/drawable/ic_scan_24dp.xml
index bcef8e3..c7b82d1 100644
--- a/res/drawable/ic_scan_24dp.xml
+++ b/res/drawable/ic_scan_24dp.xml
@@ -2,7 +2,8 @@
     android:width="24dp"
     android:height="24dp"
     android:viewportWidth="24"
-    android:viewportHeight="24">
+    android:viewportHeight="24"
+    android:tint="?android:attr/colorAccent">
   <path
       android:fillColor="#FF000000"
       android:pathData="M9,2l-7,0l0,2l7,0l0,-2z"/>
diff --git a/res/layout/advanced_bt_entity_sub.xml b/res/layout/advanced_bt_entity_sub.xml
index 07ea814..0f30583 100644
--- a/res/layout/advanced_bt_entity_sub.xml
+++ b/res/layout/advanced_bt_entity_sub.xml
@@ -26,9 +26,11 @@
         android:id="@+id/header_icon"
         android:layout_width="72dp"
         android:layout_height="72dp"
-        android:scaleType="fitCenter"
         android:layout_gravity="center_horizontal"
-        android:antialias="true"/>
+        android:antialias="true"
+        android:background="@drawable/circle_outline"
+        android:padding="8dp"
+        android:scaleType="fitCenter"/>
 
     <TextView
         android:id="@+id/header_title"
diff --git a/res/layout/homepage_condition_footer.xml b/res/layout/homepage_condition_footer.xml
index cc84f52..56687fe 100644
--- a/res/layout/homepage_condition_footer.xml
+++ b/res/layout/homepage_condition_footer.xml
@@ -29,7 +29,6 @@
         android:id="@+id/collapse_button"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:src="@drawable/ic_expand_less"
-        android:tint="?android:attr/colorAccent"/>
+        android:src="@drawable/ic_expand_less"/>
 
 </LinearLayout>
\ No newline at end of file
diff --git a/res/layout/homepage_condition_header.xml b/res/layout/homepage_condition_header.xml
index 5c1b181..5460be9 100644
--- a/res/layout/homepage_condition_header.xml
+++ b/res/layout/homepage_condition_header.xml
@@ -45,8 +45,8 @@
             android:paddingTop="@dimen/homepage_condition_header_indicator_padding_top"
             android:paddingStart="@dimen/homepage_condition_header_indicator_padding_start"
             android:paddingEnd="@dimen/homepage_condition_header_indicator_padding_end"
-            android:src="@*android:drawable/ic_expand_more"
-            android:tint="?android:attr/colorAccent"/>
+            android:src="@drawable/ic_expand_more_inverse"
+            android:tint="?android:attr/colorControlNormal"/>
 
     </LinearLayout>
 
diff --git a/res/layout/homepage_slice_tile.xml b/res/layout/homepage_slice_tile.xml
index e95129e..b2badf5 100644
--- a/res/layout/homepage_slice_tile.xml
+++ b/res/layout/homepage_slice_tile.xml
@@ -32,6 +32,7 @@
             android:layout_height="wrap_content"
             android:layout_gravity="center_vertical"
             android:animateLayoutChanges="true"
+            android:importantForAccessibility="no"
             style="@style/SliceViewStyle"/>
 
         <!--dismissal view-->
diff --git a/res/layout/master_clear.xml b/res/layout/master_clear.xml
index 9c1dd80..6368588 100644
--- a/res/layout/master_clear.xml
+++ b/res/layout/master_clear.xml
@@ -127,12 +127,9 @@
                         android:text="@string/erase_external_storage_description"/>
                 </LinearLayout>
             </LinearLayout>
-            <include
-                layout="@layout/reset_esim_checkbox"
-                android:layout_marginTop="40dp"
-                android:id="@+id/erase_esim_container"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"/>
+
+            <include layout="@layout/reset_esim_checkbox"/>
+
         </LinearLayout>
     </ScrollView>
 </com.google.android.setupdesign.GlifLayout>
diff --git a/res/layout/notif_importance_preference.xml b/res/layout/notif_importance_preference.xml
new file mode 100644
index 0000000..5d79ff3
--- /dev/null
+++ b/res/layout/notif_importance_preference.xml
@@ -0,0 +1,104 @@
+<?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.
+  -->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/app_entities_header"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:gravity="center"
+    android:orientation="horizontal">
+
+    <LinearLayout
+        android:id="@+id/block"
+        android:layout_width="0dp"
+        android:layout_weight="33.33"
+        android:layout_height="wrap_content"
+        android:layout_marginBottom="16dp"
+        android:layout_marginTop="16dp"
+        android:orientation="vertical"
+        android:gravity="center">
+
+        <ImageButton
+            android:id="@+id/block_icon"
+            android:layout_width="@dimen/notification_importance_toggle_size"
+            android:layout_height="@dimen/notification_importance_toggle_size"
+            android:background="?android:attr/selectableItemBackgroundBorderless"
+            android:src="@drawable/ic_notification_block"
+            android:contentDescription="@string/notification_block_title" />
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/notification_block_title"
+            android:layout_marginTop="@dimen/notification_importance_toggle_marginTop"
+            android:layout_marginBottom="@dimen/notification_importance_toggle_marginBottom"
+            android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Subhead" />
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/silence"
+        android:layout_width="0dp"
+        android:layout_weight="33.33"
+        android:layout_height="wrap_content"
+        android:layout_marginBottom="16dp"
+        android:layout_marginTop="16dp"
+        android:orientation="vertical"
+        android:gravity="center">
+
+        <ImageButton
+            android:id="@+id/silence_icon"
+            android:layout_width="@dimen/notification_importance_toggle_size"
+            android:layout_height="@dimen/notification_importance_toggle_size"
+            android:background="?android:attr/selectableItemBackgroundBorderless"
+            android:src="@drawable/ic_notification_silence"
+            android:contentDescription="@string/notification_silence_title" />
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/notification_silence_title"
+            android:layout_marginTop="@dimen/notification_importance_toggle_marginTop"
+            android:layout_marginBottom="@dimen/notification_importance_toggle_marginBottom"
+            android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Subhead" />
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/alert"
+        android:layout_width="0dp"
+        android:layout_weight="33.33"
+        android:layout_height="wrap_content"
+        android:layout_marginBottom="16dp"
+        android:layout_marginTop="16dp"
+        android:orientation="vertical"
+        android:gravity="center">
+
+        <ImageButton
+            android:id="@+id/alert_icon"
+            android:layout_width="@dimen/notification_importance_toggle_size"
+            android:layout_height="@dimen/notification_importance_toggle_size"
+            android:background="?android:attr/selectableItemBackgroundBorderless"
+            android:src="@drawable/ic_notification_alert"
+            android:contentDescription="@string/notification_alert_title" />
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/notification_alert_title"
+            android:layout_marginTop="@dimen/notification_importance_toggle_marginTop"
+            android:layout_marginBottom="@dimen/notification_importance_toggle_marginBottom"
+            android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Subhead" />
+    </LinearLayout>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/preference_single_target.xml b/res/layout/preference_single_target.xml
new file mode 100644
index 0000000..b4a9de0
--- /dev/null
+++ b/res/layout/preference_single_target.xml
@@ -0,0 +1,96 @@
+<?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.
+  -->
+
+<!-- Based off preference_two_target.xml with Material ripple moved to parent for full ripple. -->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:settings="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:minHeight="?android:attr/listPreferredItemHeightSmall"
+    android:gravity="center_vertical"
+    android:background="?android:attr/selectableItemBackground"
+    android:clipToPadding="false">
+
+    <LinearLayout
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:gravity="start|center_vertical"
+        android:clipToPadding="false"
+        android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+        android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
+
+        <LinearLayout
+            android:id="@+id/icon_frame"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:gravity="start|center_vertical"
+            android:minWidth="56dp"
+            android:orientation="horizontal"
+            android:clipToPadding="false"
+            android:paddingTop="4dp"
+            android:paddingBottom="4dp">
+            <androidx.preference.internal.PreferenceImageView
+                android:id="@android:id/icon"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                settings:maxWidth="48dp"
+                settings:maxHeight="48dp" />
+        </LinearLayout>
+
+        <RelativeLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:paddingTop="16dp"
+            android:paddingBottom="16dp">
+
+            <TextView
+                android:id="@android:id/title"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:singleLine="true"
+                android:textAppearance="?android:attr/textAppearanceListItem"
+                android:ellipsize="marquee" />
+
+            <TextView
+                android:id="@android:id/summary"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_below="@android:id/title"
+                android:layout_alignStart="@android:id/title"
+                android:textAppearance="?android:attr/textAppearanceListItemSecondary"
+                android:textColor="?android:attr/textColorSecondary"
+                android:maxLines="10" />
+
+        </RelativeLayout>
+
+    </LinearLayout>
+
+    <include layout="@layout/preference_two_target_divider" />
+
+    <!-- Preference should place its actual preference widget here. -->
+    <LinearLayout
+        android:id="@android:id/widget_frame"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:minWidth="64dp"
+        android:gravity="center"
+        android:orientation="vertical" />
+
+</LinearLayout>
diff --git a/res/layout/reset_esim_checkbox.xml b/res/layout/reset_esim_checkbox.xml
index 2195435..77b90a1 100644
--- a/res/layout/reset_esim_checkbox.xml
+++ b/res/layout/reset_esim_checkbox.xml
@@ -15,7 +15,9 @@
 -->
 <LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/erase_esim_container"
     style="@style/SudDescription"
+    android:layout_marginTop="40dp"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:orientation="horizontal"
@@ -41,10 +43,10 @@
         android:orientation="vertical">
 
         <TextView
-            android:id="@+id/erase_esim_title"
             style="@style/TextAppearance.SudGlifItemTitle"
             android:layout_width="wrap_content"
-            android:layout_height="wrap_content"/>
+            android:layout_height="wrap_content"
+            android:text="@string/reset_esim_title"/>
 
         <TextView
             style="@style/TextAppearance.SudGlifItemSummary"
diff --git a/res/layout/reset_network.xml b/res/layout/reset_network.xml
index 7eb5d2a..2c31d1a 100644
--- a/res/layout/reset_network.xml
+++ b/res/layout/reset_network.xml
@@ -40,10 +40,7 @@
                 android:textDirection="locale"
                 android:text="@string/reset_network_desc" />
 
-            <include layout="@layout/reset_esim_checkbox"
-                android:id="@+id/erase_esim_container"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content" />
+            <include layout="@layout/reset_esim_checkbox"/>
 
         </LinearLayout>
 
diff --git a/res/layout/settings_homepage_container.xml b/res/layout/settings_homepage_container.xml
index 78a0278..9332463 100644
--- a/res/layout/settings_homepage_container.xml
+++ b/res/layout/settings_homepage_container.xml
@@ -25,6 +25,7 @@
         android:id="@+id/main_content_scrollable_container"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
+        android:importantForAccessibility="no"
         app:layout_behavior="com.android.settings.widget.FloatingAppBarScrollingViewBehavior">
 
         <LinearLayout
diff --git a/res/layout/time_zone_search_header.xml b/res/layout/time_zone_search_header.xml
new file mode 100644
index 0000000..5c4e0ee
--- /dev/null
+++ b/res/layout/time_zone_search_header.xml
@@ -0,0 +1,28 @@
+<?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.
+  -->
+<!-- similar to preference_material.xml but textview for emoji country flag
+instead of an ImageView -->
+
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+          android:id="@+android:id/title"
+          android:layout_width="match_parent"
+          android:layout_height="wrap_content"
+          android:layout_marginBottom="16dp"
+          android:layout_marginTop="16dp"
+          android:textAppearance="@style/TextAppearance.CategoryTitle"
+          android:textColor="?android:attr/colorAccent"
+          android:paddingStart="@dimen/preference_no_icon_padding_start"/>
diff --git a/res/layout/wfc_disclaimer_fragment.xml b/res/layout/wfc_disclaimer_fragment.xml
new file mode 100644
index 0000000..00baae5
--- /dev/null
+++ b/res/layout/wfc_disclaimer_fragment.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="16dp"
+        android:layout_marginStart="16dp"
+        android:layout_marginBottom="20dp"
+        android:textAppearance="?android:attr/textAppearanceLarge"
+        android:text="@string/wfc_disclaimer_title_text" />
+
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="1dp"
+        android:background="?android:attr/listDivider" />
+
+    <androidx.recyclerview.widget.RecyclerView
+        android:id="@+id/disclaimer_item_list"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1" />
+
+    <LinearLayout
+        android:orientation="horizontal"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" >
+
+        <Button
+            android:id="@+id/disagree_button"
+            style="@style/DisclaimerNegativeButton"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center_vertical"
+            android:text="@string/wfc_disclaimer_disagree_text" />
+
+        <Space
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1" />
+
+        <Button
+            android:id="@+id/agree_button"
+            style="@style/DisclaimerPositiveButton"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center_vertical"
+            android:text="@string/wfc_disclaimer_agree_button_text" />
+    </LinearLayout>
+</LinearLayout>
diff --git a/res/layout/wfc_simple_disclaimer_item.xml b/res/layout/wfc_simple_disclaimer_item.xml
new file mode 100644
index 0000000..ee43182
--- /dev/null
+++ b/res/layout/wfc_simple_disclaimer_item.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:paddingTop="16dp"
+    android:paddingBottom="20dp"
+    android:paddingStart="16dp"
+    android:paddingEnd="16dp"
+    android:gravity="center_vertical">
+    <TextView
+        android:id="@+id/disclaimer_title"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textAppearance="@android:style/TextAppearance.Material.Subhead" />
+    <TextView
+        android:id="@+id/disclaimer_desc"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textAppearance="@android:style/TextAppearance.Material.Body1"
+        android:textColor="?android:attr/textColorSecondary"
+        android:layout_below="@id/disclaimer_title" />
+</RelativeLayout>
\ No newline at end of file
diff --git a/res/layout/wifi_button_preference_widget.xml b/res/layout/wifi_button_preference_widget.xml
index 0999d20..4b004e3 100644
--- a/res/layout/wifi_button_preference_widget.xml
+++ b/res/layout/wifi_button_preference_widget.xml
@@ -22,5 +22,4 @@
            android:minWidth="@dimen/min_tap_target_size"
            android:minHeight="@dimen/min_tap_target_size"
            android:layout_gravity="center"
-           android:background="@null"
-           android:visibility="gone"/>
+           android:background="?android:attr/selectableItemBackground"/>
diff --git a/res/layout/wifi_dialog.xml b/res/layout/wifi_dialog.xml
index 333296c..d5dbb17 100644
--- a/res/layout/wifi_dialog.xml
+++ b/res/layout/wifi_dialog.xml
@@ -50,29 +50,31 @@
                         android:text="@string/wifi_ssid"
                         android:textDirection="locale" />
 
-                <RelativeLayout
+                <androidx.constraintlayout.widget.ConstraintLayout
+                        xmlns:app="http://schemas.android.com/apk/res-auto"
                         android:layout_width="match_parent"
-                        android:layout_height="wrap_content" >
+                        android:layout_height="wrap_content">
                     <EditText android:id="@+id/ssid"
-                            android:layout_width="match_parent"
+                            android:layout_width="0dp"
                             android:layout_height="wrap_content"
-                            android:layout_alignParentStart="true"
+                            app:layout_constraintStart_toStartOf="parent"
+                            app:layout_constraintEnd_toStartOf="@+id/ssid_scanner_button"
                             style="@style/wifi_item_edit_content"
                             android:hint="@string/wifi_ssid_hint"
                             android:singleLine="true"
-                            android:inputType="textNoSuggestions" />
+                            android:inputType="textNoSuggestions"/>
+
                     <ImageButton
                         android:id="@+id/ssid_scanner_button"
                         android:layout_width="wrap_content"
                         android:layout_height="wrap_content"
                         android:minWidth="@dimen/min_tap_target_size"
                         android:minHeight="@dimen/min_tap_target_size"
-                        android:layout_alignParentEnd="true"
-                        android:layout_centerVertical="true"
-                        android:background="@null"
+                        app:layout_constraintEnd_toEndOf="parent"
+                        android:background="?android:attr/selectableItemBackground"
                         android:src="@drawable/ic_scan_24dp"
                         android:contentDescription="@string/wifi_dpp_scan_qr_code"/>
-                </RelativeLayout>
+                </androidx.constraintlayout.widget.ConstraintLayout>
 
                 <LinearLayout android:id="@+id/ssid_too_long_warning"
                               android:layout_width="match_parent"
@@ -286,16 +288,18 @@
                         style="@style/wifi_item_label"
                         android:text="@string/wifi_password" />
 
-                <RelativeLayout
+                <androidx.constraintlayout.widget.ConstraintLayout
+                    xmlns:app="http://schemas.android.com/apk/res-auto"
                     android:layout_width="match_parent"
-                    android:layout_height="wrap_content" >
+                    android:layout_height="wrap_content">
                     <EditText android:id="@+id/password"
-                              android:layout_width="match_parent"
+                              android:layout_width="0dp"
                               android:layout_height="wrap_content"
-                              android:layout_alignParentStart="true"
+                              app:layout_constraintStart_toStartOf="parent"
+                              app:layout_constraintEnd_toStartOf="@+id/password_scanner_button"
                               style="@style/wifi_item_edit_content"
                               android:singleLine="true"
-                              android:password="true" />
+                              android:password="true"/>
 
                     <ImageButton
                         android:id="@+id/password_scanner_button"
@@ -303,12 +307,11 @@
                         android:layout_height="wrap_content"
                         android:minWidth="@dimen/min_tap_target_size"
                         android:minHeight="@dimen/min_tap_target_size"
-                        android:layout_alignParentEnd="true"
-                        android:layout_centerVertical="true"
-                        android:background="@null"
+                        app:layout_constraintEnd_toEndOf="parent"
+                        android:background="?android:attr/selectableItemBackground"
                         android:src="@drawable/ic_scan_24dp"
                         android:contentDescription="@string/wifi_dpp_scan_qr_code"/>
-                </RelativeLayout>
+                </androidx.constraintlayout.widget.ConstraintLayout>
             </LinearLayout>
 
             <LinearLayout android:id="@+id/show_password_layout"
diff --git a/res/layout/wifi_dpp_choose_saved_wifi_network_fragment.xml b/res/layout/wifi_dpp_choose_saved_wifi_network_fragment.xml
index ed288f0..3606ccd 100644
--- a/res/layout/wifi_dpp_choose_saved_wifi_network_fragment.xml
+++ b/res/layout/wifi_dpp_choose_saved_wifi_network_fragment.xml
@@ -22,28 +22,24 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent">
 
-    <ScrollView
+    <LinearLayout
         android:layout_width="match_parent"
-        android:layout_height="match_parent">
+        android:layout_height="0dp"
+        android:gravity="center_horizontal"
+        android:orientation="vertical"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintBottom_toTopOf="@+id/footer">
 
-        <LinearLayout
+        <include layout="@layout/wifi_dpp_fragment_header"/>
+
+        <LinearLayout android:id="@+id/wifi_network_list_container"
             android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:gravity="center_horizontal"
-            android:orientation="vertical">
+            android:layout_height="wrap_content"/>
 
-            <include layout="@layout/wifi_dpp_fragment_header"/>
-
-            <LinearLayout android:id="@+id/wifi_network_list_container"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                app:layout_constraintTop_toBottomOf="@+id/header"/>
-
-        </LinearLayout>
-
-    </ScrollView>
+    </LinearLayout>
 
     <include
+        android:id="@+id/footer"
         layout="@layout/wifi_dpp_fragment_footer"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 7b55a2b..0afd288 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -56,7 +56,7 @@
     <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">#ff80868B</color>
+    <color name="switch_bar_background">#757575</color>
 
     <color name="message_text_incoming">#ffffffff</color>
     <color name="message_text_outgoing">#ff323232</color>
@@ -124,6 +124,11 @@
     <color name="face_anim_particle_color_4">#fffdd835</color> <!-- Material Yellow 600 -->
     <color name="face_anim_particle_error">#ff9e9e9e</color> <!-- Material Gray 500 -->
 
+    <!-- notification settings -->
+    <color name="notification_block_color">#ffff0000</color>
+    <color name="notification_silence_color">#fbbc04</color>
+    <color name="notification_alert_color">#30a751</color>
+
     <!-- launcher icon color -->
     <color name="icon_launcher_setting_color">@*android:color/accent_device_default_light</color>
 
diff --git a/res/values/config.xml b/res/values/config.xml
index e6ada66..805469a 100755
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -356,4 +356,7 @@
 
     <!-- Slice Uri to query nearby devices. -->
     <string name="config_nearby_devices_slice_uri" translatable="false">content://com.google.android.gms.nearby.fastpair/device_status_list_item</string>
+
+    <!-- Grayscale settings intent -->
+    <string name="config_grayscale_settings_intent" translate="false"></string>
 </resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index a36d8ab..ef6fc4f 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -68,6 +68,9 @@
     <dimen name="notification_app_icon_size">64dp</dimen>
     <dimen name="notification_app_icon_badge_size">20dp</dimen>
     <dimen name="notification_app_icon_badge_margin">4dp</dimen>
+    <dimen name="notification_importance_toggle_size">48dp</dimen>
+    <dimen name="notification_importance_toggle_marginTop">8dp</dimen>
+    <dimen name="notification_importance_toggle_marginBottom">16dp</dimen>
     <dimen name="zen_schedule_rule_checkbox_padding">7dp</dimen>
     <dimen name="zen_schedule_day_margin">17dp</dimen>
 
@@ -389,7 +392,7 @@
     <dimen name="homepage_condition_header_indicator_padding_top">4dp</dimen>
     <dimen name="homepage_condition_header_indicator_padding_start">16dp</dimen>
     <dimen name="homepage_condition_header_indicator_padding_end">16dp</dimen>
-    <dimen name="homepage_condition_footer_height">44dp</dimen>
+    <dimen name="homepage_condition_footer_height">48dp</dimen>
     <dimen name="homepage_condition_footer_padding_top">10dp</dimen>
     <dimen name="homepage_condition_footer_padding_end">10dp</dimen>
     <dimen name="homepage_condition_header_icon_width_height">24dp</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 165ee0b..631d912 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -3022,14 +3022,14 @@
     <string name="status_prl_version">PRL version</string>
     <!-- About phone screen, title for MEID for multi-sim devices -->
     <string name="meid_multi_sim">MEID (sim slot %1$d)</string>
-    <!-- The status text when both Wi-Fi scanning and Bluetooth scanning are on. [CHAR LIMIT=120] -->
-    <string name="scanning_status_text_wifi_on_ble_on">Both Wi\u2011Fi and Bluetooth are allowed to determine location</string>
-    <!-- The status text when Wi-Fi scanning is on and Bluetooth scanning are off. [CHAR LIMIT=120] -->
-    <string name="scanning_status_text_wifi_on_ble_off">Only Wi\u2011Fi is allowed to determine location</string>
-    <!-- The status text when Wi-Fi scanning is off and Bluetooth scanning are on. [CHAR LIMIT=120] -->
-    <string name="scanning_status_text_wifi_off_ble_on">Only Bluetooth is allowed to determine location</string>
-    <!-- The status text when both Wi-Fi scanning and Bluetooth scanning are off. [CHAR LIMIT=120] -->
-    <string name="scanning_status_text_wifi_off_ble_off">Neither Wi\u2011Fi nor Bluetooth is allowed to determine location</string>
+    <!-- The status text when both Wi-Fi scanning and Bluetooth scanning are on. [CHAR LIMIT=100] -->
+    <string name="scanning_status_text_wifi_on_ble_on">Both Wi\u2011Fi and Bluetooth scanning are on</string>
+    <!-- The status text when Wi-Fi scanning is on and Bluetooth scanning are off. [CHAR LIMIT=100] -->
+    <string name="scanning_status_text_wifi_on_ble_off">Wi\u2011Fi scanning is on, Bluetooth scanning is off</string>
+    <!-- The status text when Wi-Fi scanning is off and Bluetooth scanning are on. [CHAR LIMIT=100] -->
+    <string name="scanning_status_text_wifi_off_ble_on">Bluetooth scanning is on, Wi\u2011Fi scanning is off</string>
+    <!-- The status text when both Wi-Fi scanning and Bluetooth scanning are off. [CHAR LIMIT=100] -->
+    <string name="scanning_status_text_wifi_off_ble_off">Both Wi\u2011Fi and Bluetooth scanning are off</string>
     <!-- About phone, status item title.  The phone MEID number of the current LTE/CDMA device. [CHAR LIMIT=30] -->
     <string name="status_meid_number">MEID</string>
     <!-- About phone, status item title.  The ICCID of the current LTE device. [CHAR LIMIT=30] -->
@@ -3581,10 +3581,10 @@
     <string name="reset_network_title">Reset Wi-Fi, mobile &amp; Bluetooth</string>
     <!-- SD card & phone storage settings screen, message on screen after user selects Reset network settings [CHAR LIMIT=NONE] -->
     <string name="reset_network_desc">This will reset all network settings, including:\n\n<li>Wi\u2011Fi</li>\n<li>Mobile data</li>\n<li>Bluetooth</li>"</string>
-    <!-- SD card & phone storage settings screen, title for the checkbox to let user decide whether erase eSIM data together [CHAR LIMIT=NONE] -->
-    <string name="reset_esim_title">Also reset eSIM</string>
+    <!-- SD card & phone storage settings screen, title for the checkbox to let user decide whether erase eSIM data together [CHAR LIMIT=30] -->
+    <string name="reset_esim_title">Erase eSIMs</string>
     <!-- SD card & phone storage settings screen, message for the checkbox to let user decide whether erase eSIM data together [CHAR LIMIT=NONE] -->
-    <string name="reset_esim_desc">Erase all eSIMs on the phone. You\u2019ll have to contact your carrier to redownload your eSIMs. This will not cancel your mobile service plan.</string>
+    <string name="reset_esim_desc">You\u2019ll have to contact your carrier to download replacement eSIMs. This won\u2019t cancel any mobile service plans.</string>
     <!-- SD card & phone storage settings screen, button on screen after user selects Reset network settings -->
     <string name="reset_network_button_text">Reset settings</string>
     <!-- SD card & phone storage settings screen, message on screen after user selects Reset settings button -->
@@ -3633,12 +3633,6 @@
     <string name="erase_external_storage_description" product="nosdcard">Erase all the data on the internal USB storage, such as music or photos</string>
     <!-- SD card & phone storage settings screen, description for check box to erase USB storage [CHAR LIMIT=NONE] -->
     <string name="erase_external_storage_description" product="default">Erase all the data on the SD card, such as music or photos</string>
-    <!-- SD card & phone storage settings screen, label for check box to erase all the carriers information on the embedded SIM card [CHAR LIMIT=30] -->
-    <string name="erase_esim_storage">Erase eSIM</string>
-    <!-- SD card & phone storage settings screen, description for check box to erase eSIMs for default devices [CHAR LIMIT=NONE] -->
-    <string name="erase_esim_storage_description" product="default">Erase all eSIMs on the phone. This will not cancel your mobile service plan.</string>
-    <!-- SD card & phone storage settings screen, description for check box to erase eSIMs for tablets [CHAR LIMIT=NONE] -->
-    <string name="erase_esim_storage_description" product="tablet">Erase all eSIMs on the tablet. This will not cancel your mobile service plan.</string>
     <!-- SD card & phone storage settings screen, button on screen after user selects Factory data reset -->
     <string name="master_clear_button_text" product="tablet">Erase all data</string>
     <!-- SD card & phone storage settings screen, button on screen after user selects Factory data reset -->
@@ -3754,13 +3748,25 @@
     <string name="location_app_level_permissions">App permission</string>
     <!-- Summary for app permission on Location settings page when location is off [CHAR LIMIT=NONE] -->
     <string name="location_app_permission_summary_location_off">Location is off</string>
-    <!-- Summary for Location settings when location is on, explaining how many apps have location permission [CHAR LIMIT=NONE]-->
+    <!--
+    Summary for Location settings when location is on, explaining how many apps have unlimited
+    location permission.
+
+    "Unlimited access" means the app can access the device location even when it's not being used
+    (on background), while "limited" means the app can only access the device location when the user
+    is using it (foreground only).
+
+    Please note that the distinction between singular and plural of this sentence only depends on
+    the quantity of "background_location_app_count" ("has" vs "have"). The quantity of
+    "total_location_app_count" is almost always greater than 1, so "apps" is always in plural form.
+
+    [CHAR LIMIT=NONE]-->
     <plurals name="location_app_permission_summary_location_on">
         <item quantity="one">
             <xliff:g id="background_location_app_count">%1$d</xliff:g>
             of
             <xliff:g id="total_location_app_count">%2$d</xliff:g>
-            app has unlimited access</item>
+            apps has unlimited access</item>
         <item quantity="other">
             <xliff:g id="background_location_app_count">%1$d</xliff:g>
             of
@@ -3771,8 +3777,12 @@
     <string name="location_category_recent_location_access">Recent location access</string>
     <!-- [CHAR LIMIT=30] Location settings screen, button to bring the user to view the details of recent location access -->
     <string name="location_recent_location_access_view_details">View details</string>
-    <!-- Location settings screen, displayed when there's no recent app accessing location -->
+    <!-- Location settings screen, displayed when there's no recent app accessing location
+      (for TV) [CHAR LIMIT=100] -->
     <string name="location_no_recent_apps">No apps have requested location recently</string>
+    <!-- Location settings screen, displayed when there's no recent app accessing location
+      (for phones and tablets) [CHAR LIMIT=100] -->
+    <string name="location_no_recent_accesses">No apps recently accessed location</string>
     <!-- [CHAR LIMIT=30] Location settings screen, recent location requests high battery use-->
     <string name="location_high_battery_use">High battery use</string>
     <!-- [CHAR LIMIT=30] Location settings screen, recent location requests low battery use-->
@@ -4515,8 +4525,8 @@
     <string name="keyboard_shortcuts_helper">Keyboard shortcuts helper</string>
     <!-- Summary text for the 'keyboard shortcuts helper' dialog. [CHAR LIMIT=100] -->
     <string name="keyboard_shortcuts_helper_summary">Display available shortcuts</string>
-    <!-- Title for the 'Work profile input & assistance' preference category inside Languages and inputs'. [CHAR LIMIT=50] -->
-    <string name="language_and_input_for_work_category_title">Work profile input &amp; assistance</string>
+    <!-- Title for the 'Work profile keyboards & tools' preference category inside Languages and inputs'. [CHAR LIMIT=50] -->
+    <string name="language_and_input_for_work_category_title">Work profile keyboards &amp; tools</string>
     <!-- Title for the 'Virtual keyboards for work' preference. [CHAR LIMIT=45] -->
     <string name="virtual_keyboards_for_work_title">Virtual keyboard for work</string>
 
@@ -7771,7 +7781,7 @@
      summary on the channel page-->
 
     <!-- [CHAR LIMIT=100] Notification Importance title: min importance level title -->
-    <string name="notification_importance_min_title">Low</string>
+    <string name="notification_importance_min_title">Minimize</string>
 
     <!-- [CHAR LIMIT=100] Notification Importance title: low importance level title -->
     <string name="notification_importance_low_title">Medium</string>
@@ -7780,7 +7790,16 @@
     <string name="notification_importance_default_title">High</string>
 
     <!-- [CHAR LIMIT=100] Notification Importance title: high importance level title -->
-    <string name="notification_importance_high_title">Urgent</string>
+    <string name="notification_importance_high_title">Pop on screen</string>
+
+    <!-- [CHAR LIMIT=100] Notification Importance title -->
+    <string name="notification_block_title">Block</string>
+
+    <!-- [CHAR LIMIT=100] Notification Importance title -->
+    <string name="notification_silence_title">Show silently</string>
+
+    <!-- [CHAR LIMIT=100] Notification Importance title -->
+    <string name="notification_alert_title">Alert</string>
 
     <!-- [CHAR LIMIT=40] Notification importance title. This setting controls how notifications in older apps may alert the user (eg, sound, visual, vibrate). -->
     <string name="allow_interruption">Allow interruptions</string>
@@ -7920,6 +7939,9 @@
     <!-- Sound & notification > Advanced section: Title for managing Do Not Disturb access option. [CHAR LIMIT=40] -->
     <string name="manage_zen_access_title">Do Not Disturb access</string>
 
+    <!-- Button title that grants 'Do Not Disturb' permission to an app [CHAR_LIMIT=60]-->
+    <string name="zen_access_detail_switch">Allow Do Not Disturb</string>
+
     <!-- Sound & notification > Do Not Disturb access > Text to display when the list is empty. [CHAR LIMIT=NONE] -->
     <string name="zen_access_empty_text">No installed apps have requested Do Not Disturb access</string>
 
@@ -9306,6 +9328,12 @@
     <!-- Summary of condition that night display is on (renamed "Night Light" with title caps). [CHAR LIMIT=NONE] -->
     <string name="condition_night_display_summary">Screen tinted amber</string>
 
+    <!-- Title of condition that gray scale is on [CHAR LIMIT=NONE] -->
+    <string name="condition_grayscale_title">Greyscale</string>
+
+    <!-- Summary of condition that gray scale is on [CHAR LIMIT=NONE] -->
+    <string name="condition_grayscale_summary">Display only in grey color</string>
+
     <!-- Summary for the condition section on the dashboard, representing number of conditions. [CHAR LIMIT=10] -->
     <string name="condition_summary" translatable="false"><xliff:g name="count" example="3">%1$d</xliff:g></string>
 
@@ -9867,8 +9895,6 @@
 
     <!-- Preference and settings suggestion title text for display wake-up gesture [CHAR LIMIT=60]-->
     <string name="ambient_display_wake_screen_title">Wake up display</string>
-    <!-- Summary text for ambient display wake-up gesture [CHAR LIMIT=NONE]-->
-    <string name="ambient_display_wake_screen_summary"></string>
 
     <!-- Summary text for ambient display (phone) [CHAR LIMIT=NONE]-->
     <string name="ambient_display_pickup_summary" product="default">To check time, notifications, and other info, pick up your phone.</string>
@@ -10684,6 +10710,9 @@
     <!-- Title for the Volume dialog (settings panel) with all volume streams[CHAR LIMIT=50] -->
     <string name="volume_connectivity_panel_title">Volume</string>
 
+    <!-- Subtitle explaining that mobile data cannot be used while airplane mode is on [CHAR LIMIT=50] -->
+    <string name="mobile_data_ap_mode_disabled">Unavailable during airplane mode</string>
+
     <!-- UI debug setting: force desktop mode [CHAR LIMIT=50] -->
     <string name="force_desktop_mode">Force desktop mode</string>
     <!-- UI debug setting: force desktop mode summary [CHAR LIMIT=NONE] -->
@@ -10734,12 +10763,12 @@
 
     <!-- Summary for the accessibility usage preference in the Privacy page.  [CHAR LIMIT=NONE] -->
     <plurals name="accessibility_usage_summary">
-        <item quantity="one">1 service has full access to your device</item>
-        <item quantity="other"><xliff:g id="service_count">%1$d</xliff:g> services have full access to your device</item>
+        <item quantity="one">1 app has full access to your device</item>
+        <item quantity="other"><xliff:g id="service_count">%1$d</xliff:g> apps have full access to your device</item>
     </plurals>
 
     <!-- Title for notification channel slice. [CHAR LIMIT=NONE] -->
-    <string name="manage_app_notification">Manage <xliff:g id="app_name" example="Settings">%1$s</xliff:g> Notifications</string>
+    <string name="manage_app_notification">Manage <xliff:g id="app_name" example="Settings">%1$s</xliff:g> notifications</string>
     <!-- Title for no suggested app in notification channel slice. [CHAR LIMIT=NONE] -->
     <string name="no_suggested_app">No suggested application</string>
     <!-- Summary for the channels count is equal or less than 3 in notification channel slice. [CHAR LIMIT=NONE] -->
@@ -10749,12 +10778,23 @@
     </plurals>
     <!-- Summary for the channels count is more than 3 in notification channel slice. [CHAR LIMIT=NONE] -->
     <string name="notification_many_channel_count_summary"><xliff:g id="notification_channel_count" example="4">%1$d</xliff:g> notification channels. Tap to manage all.</string>
+    <!-- Summary for recently installed app in contextual notification channel slice. [CHAR LIMIT=NONE] -->
+    <string name="recently_installed_app">You recently installed this app.</string>
 
     <!-- Title for the Switch output dialog (settings panel) with media related devices [CHAR LIMIT=50] -->
     <string name="media_output_panel_title">Switch output</string>
     <!-- Summary for represent which device is playing media [CHAR LIMIT=NONE] -->
     <string name="media_output_panel_summary_of_playing_device">Currently playing on <xliff:g id="device_name" example="Bose headphone">%1$s</xliff:g></string>
 
+    <!-- Label for the title on wfc disclaimer fragment. [CHAR LIMIT=40] -->
+    <string name="wfc_disclaimer_title_text">Important information</string>
+
+    <!-- Label for the agree button on wfc disclaimer fragment. [CHAR LIMIT=30] -->
+    <string name="wfc_disclaimer_agree_button_text">CONTINUE</string>
+
+    <!-- Label for the disagree button on wfc disclaimer fragment. [CHAR LIMIT=30] -->
+    <string name="wfc_disclaimer_disagree_text">NO THANKS</string>
+
     <!-- 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>
 
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 92a4098..8fde9a0 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -520,4 +520,17 @@
         <!-- Padding between content and the start icon is 8dp. -->
         <item name="contentStartPadding">8dp</item>
     </style>
+
+    <style name="DisclaimerPositiveButton" parent="@style/SudGlifButton.Primary">
+        <item name="android:layout_margin">16dp</item>
+        <item name="android:paddingStart">8dp</item>
+        <item name="android:paddingEnd">8dp</item>
+    </style>
+
+    <style name="DisclaimerNegativeButton" parent="@style/SudGlifButton.Secondary">
+        <item name="android:layout_margin">16dp</item>
+        <item name="android:paddingStart">8dp</item>
+        <item name="android:paddingEnd">8dp</item>
+    </style>
+
 </resources>
diff --git a/res/xml/app_notification_settings.xml b/res/xml/app_notification_settings.xml
index 54d6fe7..faad649 100644
--- a/res/xml/app_notification_settings.xml
+++ b/res/xml/app_notification_settings.xml
@@ -61,7 +61,7 @@
             android:order="1001"
             settings:restrictedSwitchSummary="@string/enabled_by_admin" />
         <com.android.settingslib.RestrictedSwitchPreference
-            android:key="bubble"
+            android:key="bubble_pref"
             android:title="@string/notification_bubbles_title"
             android:order="1002"
             settings:restrictedSwitchSummary="@string/enabled_by_admin" />
diff --git a/res/xml/channel_notification_settings.xml b/res/xml/channel_notification_settings.xml
index 94a2cdb..3158819 100644
--- a/res/xml/channel_notification_settings.xml
+++ b/res/xml/channel_notification_settings.xml
@@ -25,11 +25,6 @@
         android:order="1"
         android:layout="@layout/settings_entity_header" />
 
-    <com.android.settingslib.widget.LayoutPreference
-        android:key="block"
-        android:order="2"
-        android:layout="@layout/styled_switch_bar" />
-
     <!-- Importance toggle -->
     <com.android.settingslib.RestrictedSwitchPreference
         android:key="allow_sound"
@@ -38,10 +33,23 @@
         android:summary="@string/allow_interruption_summary" />
 
     <!-- Importance -->
-    <com.android.settings.RestrictedListPreference
+    <com.android.settings.notification.ImportancePreference
         android:key="importance"
-        android:order="10"
-        android:title="@string/notification_importance_title" />
+        android:order="4"
+        android:title="@string/notification_importance_title"
+        settings:allowDividerBelow="true"/>
+
+    <com.android.settingslib.RestrictedSwitchPreference
+        android:key="min_importance"
+        android:order="5"
+        settings:allowDividerAbove="true"
+        android:title="@string/notification_importance_min_title"/>
+
+    <com.android.settingslib.RestrictedSwitchPreference
+        android:key="high_importance"
+        android:order="6"
+        settings:allowDividerAbove="true"
+        android:title="@string/notification_importance_high_title"/>
 
     <PreferenceCategory
         android:key="channel_advanced"
@@ -87,7 +95,7 @@
             settings:restrictedSwitchSummary="@string/enabled_by_admin"/>
 
         <com.android.settingslib.RestrictedSwitchPreference
-            android:key="bubble"
+            android:key="bubble_pref"
             android:title="@string/notification_bubbles_title"
             android:order="16"
             settings:restrictedSwitchSummary="@string/enabled_by_admin" />
@@ -113,6 +121,7 @@
 
     <com.android.settings.notification.NotificationFooterPreference
         android:key="block_desc"
-        android:order="110"/>
+        android:order="110"
+        settings:allowDividerAbove="false"/>
 
 </PreferenceScreen>
diff --git a/res/xml/gestures.xml b/res/xml/gestures.xml
index f705630..8515bd7 100644
--- a/res/xml/gestures.xml
+++ b/res/xml/gestures.xml
@@ -28,12 +28,6 @@
         settings:controller="com.android.settings.gestures.AssistGestureSettingsPreferenceController" />
 
     <Preference
-        android:key="gesture_wake_screen_input_summary"
-        android:title="@string/ambient_display_wake_screen_title"
-        android:fragment="com.android.settings.gestures.WakeScreenGestureSettings"
-        settings:controller="com.android.settings.gestures.WakeScreenGesturePreferenceController" />
-
-    <Preference
         android:key="gesture_swipe_down_fingerprint_input_summary"
         android:title="@string/fingerprint_swipe_for_notifications_title"
         android:fragment="com.android.settings.gestures.SwipeToNotificationSettings"
diff --git a/res/xml/mobile_network_list.xml b/res/xml/mobile_network_list.xml
index b72540f..c2baf46 100644
--- a/res/xml/mobile_network_list.xml
+++ b/res/xml/mobile_network_list.xml
@@ -16,11 +16,13 @@
 
 <PreferenceScreen
     xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:settings="http://schemas.android.com/apk/res-auto"
     android:key="mobile_network_list_screen"
     android:title="@string/network_settings_title">
 
     <Preference
         android:key="add_more"
+        settings:isPreferenceVisible="false"
         android:title="@string/mobile_network_list_add_more"
         android:icon="@drawable/ic_menu_add"
         android:order="100" >
diff --git a/res/xml/my_device_info.xml b/res/xml/my_device_info.xml
index 83bf5c4..bc498d2 100644
--- a/res/xml/my_device_info.xml
+++ b/res/xml/my_device_info.xml
@@ -115,6 +115,7 @@
         android:title="@string/status_imei"
         settings:keywords="@string/keywords_imei_info"
         android:summary="@string/summary_placeholder"
+        settings:allowDynamicSummaryInSlice="true"
         settings:controller="com.android.settings.deviceinfo.imei.ImeiInfoPreferenceController"/>
 
     <!-- Android version -->
diff --git a/res/xml/security_lockscreen_settings.xml b/res/xml/security_lockscreen_settings.xml
index 6833922..611d33f 100644
--- a/res/xml/security_lockscreen_settings.xml
+++ b/res/xml/security_lockscreen_settings.xml
@@ -60,12 +60,6 @@
             settings:controller="com.android.settings.display.AmbientDisplayAlwaysOnPreferenceController" />
 
         <Preference
-            android:key="ambient_display_wake_screen"
-            android:title="@string/ambient_display_wake_screen_title"
-            android:fragment="com.android.settings.gestures.WakeScreenGestureSettings"
-            settings:controller="com.android.settings.gestures.WakeScreenGesturePreferenceController" />
-
-        <Preference
             android:key="ambient_display_tap"
             android:title="@string/ambient_display_tap_screen_title"
             android:fragment="com.android.settings.gestures.TapScreenGestureSettings"
diff --git a/res/xml/special_access.xml b/res/xml/special_access.xml
index 05f4a81..9be01f9 100644
--- a/res/xml/special_access.xml
+++ b/res/xml/special_access.xml
@@ -53,7 +53,7 @@
         android:key="zen_access"
         android:title="@string/manage_zen_access_title"
         android:fragment="com.android.settings.notification.ZenAccessSettings"
-        settings:controller="com.android.settings.applications.specialaccess.ZenAccessController" />
+        settings:controller="com.android.settings.applications.specialaccess.zenaccess.ZenAccessController" />
 
     <Preference
         android:key="write_settings_apps"
diff --git a/res/xml/wake_screen_gesture_settings.xml b/res/xml/wake_screen_gesture_settings.xml
deleted file mode 100644
index 7bcb2e9..0000000
--- a/res/xml/wake_screen_gesture_settings.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright (C) 2018 The Android Open Source Project
-
-  Licensed under the Apache License, Version 2.0 (the "License");
-  you may not use this file except in compliance with the License.
-  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
-  -->
-
-<PreferenceScreen
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:key="gesture_wake_screen_screen"
-    android:title="@string/ambient_display_wake_screen_title">
-
-    <com.android.settings.widget.VideoPreference
-        android:key="gesture_wake_screen_video"
-        app:animation="@raw/gesture_ambient_wake_screen"
-        app:preview="@drawable/gesture_ambient_wake_screen" />
-
-    <SwitchPreference
-        android:key="gesture_wake_screen"
-        android:title="@string/ambient_display_wake_screen_title"
-        android:summary="@string/ambient_display_wake_screen_summary"
-        app:keywords="@string/keywords_gesture"
-        app:controller="com.android.settings.gestures.WakeScreenGesturePreferenceController"
-        app:allowDividerAbove="true" />
-
-</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/zen_access_permission_details.xml b/res/xml/zen_access_permission_details.xml
new file mode 100644
index 0000000..afa8d80
--- /dev/null
+++ b/res/xml/zen_access_permission_details.xml
@@ -0,0 +1,27 @@
+<?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"
+    android:key="zen_access_permission_detail_settings"
+    android:title="@string/manage_zen_access_title">
+
+    <SwitchPreference
+        android:key="zen_access_switch"
+        android:title="@string/zen_access_detail_switch"/>
+
+</PreferenceScreen>
\ No newline at end of file
diff --git a/src/com/android/settings/MasterClear.java b/src/com/android/settings/MasterClear.java
index 58bc58c..c78115d 100644
--- a/src/com/android/settings/MasterClear.java
+++ b/src/com/android/settings/MasterClear.java
@@ -326,8 +326,6 @@
 
         if (showWipeEuicc()) {
             if (showWipeEuiccCheckbox()) {
-                TextView title = mContentView.findViewById(R.id.erase_esim_title);
-                title.setText(R.string.erase_esim_storage);
                 mEsimStorageContainer.setVisibility(View.VISIBLE);
                 mEsimStorageContainer.setOnClickListener(new View.OnClickListener() {
                     @Override
diff --git a/src/com/android/settings/RadioInfo.java b/src/com/android/settings/RadioInfo.java
index 0af12fd..495d35c 100644
--- a/src/com/android/settings/RadioInfo.java
+++ b/src/com/android/settings/RadioInfo.java
@@ -457,6 +457,13 @@
         imsWfcProvisionedSwitch = (Switch) findViewById(R.id.wfc_provisioned_switch);
         eabProvisionedSwitch = (Switch) findViewById(R.id.eab_provisioned_switch);
 
+        if (!ImsManager.isImsSupportedOnDevice(phone.getContext())) {
+            imsVolteProvisionedSwitch.setVisibility(View.GONE);
+            imsVtProvisionedSwitch.setVisibility(View.GONE);
+            imsWfcProvisionedSwitch.setVisibility(View.GONE);
+            eabProvisionedSwitch.setVisibility(View.GONE);
+        }
+
         cbrsDataSwitch = (Switch) findViewById(R.id.cbrs_data_switch);
         cbrsDataSwitch.setVisibility(isCbrsSupported() ? View.VISIBLE : View.GONE);
 
@@ -631,8 +638,10 @@
                 R.string.radioInfo_menu_viewFDN).setOnMenuItemClickListener(mViewFDNCallback);
         menu.add(1, MENU_ITEM_VIEW_SDN, 0,
                 R.string.radioInfo_menu_viewSDN).setOnMenuItemClickListener(mViewSDNCallback);
-        menu.add(1, MENU_ITEM_GET_IMS_STATUS,
-                0, R.string.radioInfo_menu_getIMS).setOnMenuItemClickListener(mGetImsStatus);
+        if (ImsManager.isImsSupportedOnDevice(phone.getContext())) {
+            menu.add(1, MENU_ITEM_GET_IMS_STATUS,
+                    0, R.string.radioInfo_menu_getIMS).setOnMenuItemClickListener(mGetImsStatus);
+        }
         menu.add(1, MENU_ITEM_TOGGLE_DATA,
                 0, R.string.radio_info_data_connection_disable).setOnMenuItemClickListener(mToggleData);
         return true;
@@ -1384,6 +1393,9 @@
     }
 
     private void updateImsProvisionedState() {
+        if (!ImsManager.isImsSupportedOnDevice(phone.getContext())) {
+            return;
+        }
         log("updateImsProvisionedState isImsVolteProvisioned()=" + isImsVolteProvisioned());
         //delightful hack to prevent on-checked-changed calls from
         //actually forcing the ims provisioning to its transient/current value.
diff --git a/src/com/android/settings/ResetNetwork.java b/src/com/android/settings/ResetNetwork.java
index bd45f9b..5d7dd99 100644
--- a/src/com/android/settings/ResetNetwork.java
+++ b/src/com/android/settings/ResetNetwork.java
@@ -213,8 +213,6 @@
         mInitiateButton.setOnClickListener(mInitiateListener);
         if (showEuiccSettings(getContext())) {
             mEsimContainer.setVisibility(View.VISIBLE);
-            TextView title = mContentView.findViewById(R.id.erase_esim_title);
-            title.setText(R.string.reset_esim_title);
             mEsimContainer.setOnClickListener(new OnClickListener() {
                 @Override
                 public void onClick(View v) {
diff --git a/src/com/android/settings/ResetNetworkConfirm.java b/src/com/android/settings/ResetNetworkConfirm.java
index 7c21b55..72e1919 100644
--- a/src/com/android/settings/ResetNetworkConfirm.java
+++ b/src/com/android/settings/ResetNetworkConfirm.java
@@ -157,20 +157,9 @@
                      SubscriptionManager.getPhoneId(mSubId)).factoryReset();
             restoreDefaultApn(context);
             esimFactoryReset(context, context.getPackageName());
-            // There has been issues when Sms raw table somehow stores orphan
-            // fragments. They lead to garbled message when new fragments come
-            // in and combied with those stale ones. In case this happens again,
-            // user can reset all network settings which will clean up this table.
-            cleanUpSmsRawTable(context);
         }
     };
 
-    private void cleanUpSmsRawTable(Context context) {
-        ContentResolver resolver = context.getContentResolver();
-        Uri uri = Uri.withAppendedPath(Telephony.Sms.CONTENT_URI, "raw/permanentDelete");
-        resolver.delete(uri, null, null);
-    }
-
     @VisibleForTesting
     void esimFactoryReset(Context context, String packageName) {
         if (mEraseEsim) {
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index fac4253..ead0d6a 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -96,6 +96,7 @@
     public static class PictureInPictureSettingsActivity extends SettingsActivity { /* empty */ }
     public static class AppPictureInPictureSettingsActivity extends SettingsActivity { /* empty */ }
     public static class ZenAccessSettingsActivity extends SettingsActivity { /* empty */ }
+    public static class ZenAccessDetailSettingsActivity extends SettingsActivity {}
     public static class ConditionProviderSettingsActivity extends SettingsActivity { /* empty */ }
     public static class UsbSettingsActivity extends SettingsActivity { /* empty */ }
     public static class UsbDetailsActivity extends SettingsActivity { /* empty */ }
@@ -159,6 +160,7 @@
     public static class WebViewAppPickerActivity extends SettingsActivity { /* empty */ }
     public static class AdvancedConnectedDeviceActivity extends SettingsActivity { /* empty */ }
     public static class BluetoothDeviceDetailActivity extends SettingsActivity { /* empty */ }
+    public static class WifiCallingDisclaimerActivity extends SettingsActivity { /* empty */ }
 
     // Top level categories for new IA
     public static class NetworkDashboardActivity extends SettingsActivity {}
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index 541ca3a..001e65b 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -50,6 +50,8 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.settings.Settings.WifiSettingsActivity;
 import com.android.settings.applications.manageapplications.ManageApplications;
+import com.android.settings.backup.BackupSettingsHelper;
+import com.android.settings.backup.UserBackupSettingsActivity;
 import com.android.settings.core.OnActivityResultListener;
 import com.android.settings.core.SettingsBaseActivity;
 import com.android.settings.core.SubSettingLauncher;
@@ -630,6 +632,12 @@
                 showDev, isAdmin)
                 || somethingChanged;
 
+        // Enable/disable backup settings depending on whether backup is activated for the user.
+        boolean isBackupActive = new BackupSettingsHelper(this).isBackupServiceActive();
+        somethingChanged = setTileEnabled(changedList, new ComponentName(packageName,
+                UserBackupSettingsActivity.class.getName()), isBackupActive, isAdmin)
+                || somethingChanged;
+
         somethingChanged = setTileEnabled(changedList, new ComponentName(packageName,
                         Settings.WifiDisplaySettingsActivity.class.getName()),
                 WifiDisplaySettings.isAvailable(this), isAdmin)
diff --git a/src/com/android/settings/UserCredentialsSettings.java b/src/com/android/settings/UserCredentialsSettings.java
index c30e51d..d322819 100644
--- a/src/com/android/settings/UserCredentialsSettings.java
+++ b/src/com/android/settings/UserCredentialsSettings.java
@@ -154,11 +154,15 @@
                         dialog.dismiss();
                     }
                 };
-                if (item.isSystem()) {
-                    // TODO: a safe means of clearing wifi certificates. Configs refer to aliases
-                    //       directly so deleting certs will break dependent access points.
-                    builder.setNegativeButton(R.string.trusted_credentials_remove_label, listener);
-                }
+                // TODO: b/127865361
+                //       a safe means of clearing wifi certificates. Configs refer to aliases
+                //       directly so deleting certs will break dependent access points.
+                //       However, Wi-Fi used to remove this certificate from storage if the network
+                //       was removed, regardless if it is used in more than one network.
+                //       It has been decided to allow removing certificates from this menu, as we
+                //       assume that the user who manually adds certificates must have a way to
+                //       manually remove them.
+                builder.setNegativeButton(R.string.trusted_credentials_remove_label, listener);
             }
             return builder.create();
         }
@@ -172,7 +176,8 @@
          * Deletes all certificates and keys under a given alias.
          *
          * If the {@link Credential} is for a system alias, all active grants to the alias will be
-         * removed using {@link KeyChain}.
+         * removed using {@link KeyChain}. If the {@link Credential} is for Wi-Fi alias, all
+         * credentials and keys will be removed using {@link KeyStore}.
          */
         private class RemoveCredentialsTask extends AsyncTask<Credential, Void, Credential[]> {
             private Context context;
@@ -188,14 +193,32 @@
                 for (final Credential credential : credentials) {
                     if (credential.isSystem()) {
                         removeGrantsAndDelete(credential);
-                        continue;
+                    } else {
+                        deleteWifiCredential(credential);
                     }
-                    throw new UnsupportedOperationException(
-                            "Not implemented for wifi certificates. This should not be reachable.");
                 }
                 return credentials;
             }
 
+            private void deleteWifiCredential(final Credential credential) {
+                final KeyStore keyStore = KeyStore.getInstance();
+                final EnumSet<Credential.Type> storedTypes = credential.getStoredTypes();
+
+                // Remove all Wi-Fi credentials
+                if (storedTypes.contains(Credential.Type.USER_KEY)) {
+                    keyStore.delete(Credentials.USER_PRIVATE_KEY + credential.getAlias(),
+                            Process.WIFI_UID);
+                }
+                if (storedTypes.contains(Credential.Type.USER_CERTIFICATE)) {
+                    keyStore.delete(Credentials.USER_CERTIFICATE + credential.getAlias(),
+                            Process.WIFI_UID);
+                }
+                if (storedTypes.contains(Credential.Type.CA_CERTIFICATE)) {
+                    keyStore.delete(Credentials.CA_CERTIFICATE + credential.getAlias(),
+                            Process.WIFI_UID);
+                }
+            }
+
             private void removeGrantsAndDelete(final Credential credential) {
                 final KeyChainConnection conn;
                 try {
@@ -488,5 +511,11 @@
         public boolean isSystem() {
             return UserHandle.getAppId(uid) == Process.SYSTEM_UID;
         }
+
+        public String getAlias() { return alias; }
+
+        public EnumSet<Type> getStoredTypes() {
+            return storedTypes;
+        }
     }
 }
diff --git a/src/com/android/settings/accounts/AvatarViewMixin.java b/src/com/android/settings/accounts/AvatarViewMixin.java
index 3ce8c0a..9e762c7 100644
--- a/src/com/android/settings/accounts/AvatarViewMixin.java
+++ b/src/com/android/settings/accounts/AvatarViewMixin.java
@@ -17,6 +17,7 @@
 package com.android.settings.accounts;
 
 import android.accounts.Account;
+import android.app.ActivityManager;
 import android.app.settings.SettingsEnums;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -64,11 +65,13 @@
     private final Context mContext;
     private final ImageView mAvatarView;
     private final MutableLiveData<Bitmap> mAvatarImage;
+    private final ActivityManager mActivityManager;
 
     private String mAccountName;
 
     public AvatarViewMixin(SettingsHomepageActivity activity, ImageView avatarView) {
         mContext = activity.getApplicationContext();
+        mActivityManager = mContext.getSystemService(ActivityManager.class);
         mAvatarView = avatarView;
         mAvatarView.setOnClickListener(v -> {
             Intent intent;
@@ -114,7 +117,11 @@
     @OnLifecycleEvent(Lifecycle.Event.ON_START)
     public void onStart() {
         if (!mContext.getResources().getBoolean(R.bool.config_show_avatar_in_homepage)) {
-            Log.d(TAG, "Feature disabled. Skipping");
+            Log.d(TAG, "Feature disabled by config. Skipping");
+            return;
+        }
+        if (mActivityManager.isLowRamDevice()) {
+            Log.d(TAG, "Feature disabled on low ram device. Skipping");
             return;
         }
         if (hasAccount()) {
diff --git a/src/com/android/settings/applications/RecentAppsPreferenceController.java b/src/com/android/settings/applications/RecentAppsPreferenceController.java
index c0d18c6..be86dd5 100644
--- a/src/com/android/settings/applications/RecentAppsPreferenceController.java
+++ b/src/com/android/settings/applications/RecentAppsPreferenceController.java
@@ -25,6 +25,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
+import android.icu.text.RelativeDateTimeFormatter;
 import android.os.PowerManager;
 import android.os.UserHandle;
 import android.util.ArrayMap;
@@ -224,7 +225,8 @@
                 .setIcon(mIconDrawableFactory.getBadgedIcon(appEntry.info))
                 .setTitle(appEntry.label)
                 .setSummary(StringUtil.formatRelativeTime(mContext,
-                        System.currentTimeMillis() - stat.getLastTimeUsed(), false))
+                        System.currentTimeMillis() - stat.getLastTimeUsed(), false,
+                        RelativeDateTimeFormatter.Style.SHORT))
                 .setOnClickListener(v ->
                         AppInfoBase.startAppInfoFragment(AppInfoDashboardFragment.class,
                                 R.string.application_info_label, pkgName, appEntry.info.uid,
diff --git a/src/com/android/settings/applications/appinfo/DrawOverlayDetails.java b/src/com/android/settings/applications/appinfo/DrawOverlayDetails.java
index d0b26a5..0f90c69 100644
--- a/src/com/android/settings/applications/appinfo/DrawOverlayDetails.java
+++ b/src/com/android/settings/applications/appinfo/DrawOverlayDetails.java
@@ -15,22 +15,13 @@
  */
 package com.android.settings.applications.appinfo;
 
-import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
-
-import android.app.ActivityManager;
 import android.app.AppOpsManager;
 import android.app.settings.SettingsEnums;
 import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
 import android.os.Bundle;
-import android.provider.Settings;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.Window;
-import android.view.WindowManager;
 
 import androidx.annotation.VisibleForTesting;
 import androidx.appcompat.app.AlertDialog;
@@ -55,16 +46,11 @@
     private static final String KEY_APP_OPS_SETTINGS_SWITCH = "app_ops_settings_switch";
     private static final String LOG_TAG = "DrawOverlayDetails";
 
-    private static final int[] APP_OPS_OP_CODE = {
-            AppOpsManager.OP_SYSTEM_ALERT_WINDOW
-    };
-
     // Use a bridge to get the overlay details but don't initialize it to connect with all state.
     // TODO: Break out this functionality into its own class.
     private AppStateOverlayBridge mOverlayBridge;
     private AppOpsManager mAppOpsManager;
     private SwitchPreference mSwitchPref;
-    private Intent mSettingsIntent;
     private OverlayState mOverlayState;
 
     @Override
@@ -82,18 +68,15 @@
 
         // find preferences
         addPreferencesFromResource(R.xml.draw_overlay_permissions_details);
-        mSwitchPref = (SwitchPreference) findPreference(KEY_APP_OPS_SETTINGS_SWITCH);
+        mSwitchPref = findPreference(KEY_APP_OPS_SETTINGS_SWITCH);
 
         // install event listeners
         mSwitchPref.setOnPreferenceChangeListener(this);
-
-        mSettingsIntent = new Intent(Intent.ACTION_MAIN)
-                .setAction(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
     }
 
     // Override here so we don't have an empty screen
     @Override
-    public View onCreateView (LayoutInflater inflater,
+    public View onCreateView(LayoutInflater inflater,
             ViewGroup container,
             Bundle savedInstanceState) {
         // if we don't have a package info, show a page saying this is unsupported
@@ -104,21 +87,6 @@
     }
 
     @Override
-    public void onResume() {
-        super.onResume();
-        getActivity().getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
-    }
-
-    @Override
-    public void onPause() {
-        super.onPause();
-        Window window = getActivity().getWindow();
-        WindowManager.LayoutParams attrs = window.getAttributes();
-        attrs.privateFlags &= ~SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
-        window.setAttributes(attrs);
-    }
-
-    @Override
     public void onDestroy() {
         super.onDestroy();
         mOverlayBridge.release();
@@ -164,7 +132,9 @@
 
     @Override
     protected boolean refreshUi() {
-        if (mPackageInfo == null) return true;
+        if (mPackageInfo == null) {
+            return true;
+        }
 
         mOverlayState = mOverlayBridge.getOverlayInfo(mPackageName,
                 mPackageInfo.applicationInfo.uid);
@@ -174,9 +144,6 @@
         // you cannot ask a user to grant you a permission you did not have!
         mSwitchPref.setEnabled(mOverlayState.permissionDeclared && mOverlayState.controlEnabled);
 
-        ResolveInfo resolveInfo = mPm.resolveActivityAsUser(mSettingsIntent,
-                PackageManager.GET_META_DATA, mUserId);
-
         return true;
     }
 
diff --git a/src/com/android/settings/applications/specialaccess/ZenAccessController.java b/src/com/android/settings/applications/specialaccess/ZenAccessController.java
deleted file mode 100644
index 5ae2bd3..0000000
--- a/src/com/android/settings/applications/specialaccess/ZenAccessController.java
+++ /dev/null
@@ -1,39 +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.applications.specialaccess;
-
-import android.app.ActivityManager;
-import android.content.Context;
-
-import com.android.settings.core.BasePreferenceController;
-
-public class ZenAccessController extends BasePreferenceController {
-
-    private final ActivityManager mActivityManager;
-
-    public ZenAccessController(Context context, String preferenceKey) {
-        super(context, preferenceKey);
-        mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
-    }
-
-    @Override
-    public int getAvailabilityStatus() {
-        return !mActivityManager.isLowRamDevice()
-                ? AVAILABLE_UNSEARCHABLE
-                : UNSUPPORTED_ON_DEVICE;
-    }
-}
diff --git a/src/com/android/settings/applications/specialaccess/zenaccess/FriendlyWarningDialogFragment.java b/src/com/android/settings/applications/specialaccess/zenaccess/FriendlyWarningDialogFragment.java
new file mode 100644
index 0000000..fc85f7d
--- /dev/null
+++ b/src/com/android/settings/applications/specialaccess/zenaccess/FriendlyWarningDialogFragment.java
@@ -0,0 +1,76 @@
+/*
+ * 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.applications.specialaccess.zenaccess;
+
+import android.app.Dialog;
+import android.app.settings.SettingsEnums;
+import android.os.Bundle;
+import android.text.TextUtils;
+
+import androidx.appcompat.app.AlertDialog;
+
+import com.android.settings.R;
+import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+
+/**
+ * Warning dialog when revoking zen access warning that zen rule instances will be deleted.
+ */
+public class FriendlyWarningDialogFragment extends InstrumentedDialogFragment {
+    static final String KEY_PKG = "p";
+    static final String KEY_LABEL = "l";
+
+
+    @Override
+    public int getMetricsCategory() {
+        return SettingsEnums.DIALOG_ZEN_ACCESS_REVOKE;
+    }
+
+    public FriendlyWarningDialogFragment setPkgInfo(String pkg, CharSequence label) {
+        Bundle args = new Bundle();
+        args.putString(KEY_PKG, pkg);
+        args.putString(KEY_LABEL, TextUtils.isEmpty(label) ? pkg : label.toString());
+        setArguments(args);
+        return this;
+    }
+
+    @Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        final Bundle args = getArguments();
+        final String pkg = args.getString(KEY_PKG);
+        final String label = args.getString(KEY_LABEL);
+
+        final String title = getResources().getString(
+                R.string.zen_access_revoke_warning_dialog_title, label);
+        final String summary = getResources()
+                .getString(R.string.zen_access_revoke_warning_dialog_summary);
+        return new AlertDialog.Builder(getContext())
+                .setMessage(summary)
+                .setTitle(title)
+                .setCancelable(true)
+                .setPositiveButton(R.string.okay,
+                        (dialog, id) -> {
+                            ZenAccessController.deleteRules(getContext(), pkg);
+                            ZenAccessController.setAccess(getContext(), pkg, false);
+                        })
+                .setNegativeButton(R.string.cancel,
+                        (dialog, id) -> {
+                            // pass
+                        })
+                .create();
+    }
+}
diff --git a/src/com/android/settings/applications/specialaccess/zenaccess/OWNERS b/src/com/android/settings/applications/specialaccess/zenaccess/OWNERS
new file mode 100644
index 0000000..9b5f41e
--- /dev/null
+++ b/src/com/android/settings/applications/specialaccess/zenaccess/OWNERS
@@ -0,0 +1,2 @@
+beverlyt@google.com
+juliacr@google.com
\ No newline at end of file
diff --git a/src/com/android/settings/applications/specialaccess/zenaccess/ScaryWarningDialogFragment.java b/src/com/android/settings/applications/specialaccess/zenaccess/ScaryWarningDialogFragment.java
new file mode 100644
index 0000000..69318f8
--- /dev/null
+++ b/src/com/android/settings/applications/specialaccess/zenaccess/ScaryWarningDialogFragment.java
@@ -0,0 +1,73 @@
+/*
+ * 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.applications.specialaccess.zenaccess;
+
+import android.app.Dialog;
+import android.app.settings.SettingsEnums;
+import android.os.Bundle;
+import android.text.TextUtils;
+
+import androidx.appcompat.app.AlertDialog;
+
+import com.android.settings.R;
+import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+import com.android.settings.notification.ZenAccessSettings;
+
+/**
+ * Warning dialog when allowing zen access warning about the privileges being granted.
+ */
+public class ScaryWarningDialogFragment extends InstrumentedDialogFragment {
+    static final String KEY_PKG = "p";
+    static final String KEY_LABEL = "l";
+
+    @Override
+    public int getMetricsCategory() {
+        return SettingsEnums.DIALOG_ZEN_ACCESS_GRANT;
+    }
+
+    public ScaryWarningDialogFragment setPkgInfo(String pkg, CharSequence label) {
+        Bundle args = new Bundle();
+        args.putString(KEY_PKG, pkg);
+        args.putString(KEY_LABEL, TextUtils.isEmpty(label) ? pkg : label.toString());
+        setArguments(args);
+        return this;
+    }
+
+    @Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        final Bundle args = getArguments();
+        final String pkg = args.getString(KEY_PKG);
+        final String label = args.getString(KEY_LABEL);
+
+        final String title = getResources().getString(R.string.zen_access_warning_dialog_title,
+                label);
+        final String summary = getResources()
+                .getString(R.string.zen_access_warning_dialog_summary);
+        return new AlertDialog.Builder(getContext())
+                .setMessage(summary)
+                .setTitle(title)
+                .setCancelable(true)
+                .setPositiveButton(R.string.allow,
+                        (dialog, id) -> ZenAccessController.setAccess(getContext(), pkg, true))
+                .setNegativeButton(R.string.deny,
+                        (dialog, id) -> {
+                            // pass
+                        })
+                .create();
+    }
+}
diff --git a/src/com/android/settings/applications/specialaccess/zenaccess/ZenAccessController.java b/src/com/android/settings/applications/specialaccess/zenaccess/ZenAccessController.java
new file mode 100644
index 0000000..946599b
--- /dev/null
+++ b/src/com/android/settings/applications/specialaccess/zenaccess/ZenAccessController.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.applications.specialaccess.zenaccess;
+
+import android.app.ActivityManager;
+import android.app.AppGlobals;
+import android.app.NotificationManager;
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.ParceledListSlice;
+import android.os.AsyncTask;
+import android.os.RemoteException;
+import android.util.ArraySet;
+import android.util.Log;
+
+import androidx.annotation.VisibleForTesting;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.overlay.FeatureFactory;
+
+import java.util.List;
+import java.util.Set;
+
+public class ZenAccessController extends BasePreferenceController {
+
+    private static final String TAG = "ZenAccessController";
+
+    private final ActivityManager mActivityManager;
+
+    public ZenAccessController(Context context, String preferenceKey) {
+        super(context, preferenceKey);
+        mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return isSupported(mActivityManager)
+                ? AVAILABLE_UNSEARCHABLE
+                : UNSUPPORTED_ON_DEVICE;
+    }
+
+    public static boolean isSupported(ActivityManager activityManager) {
+        return !activityManager.isLowRamDevice();
+    }
+
+    public static Set<String> getPackagesRequestingNotificationPolicyAccess() {
+        final ArraySet<String> requestingPackages = new ArraySet<>();
+        try {
+            final String[] PERM = {
+                    android.Manifest.permission.ACCESS_NOTIFICATION_POLICY
+            };
+            final ParceledListSlice list = AppGlobals.getPackageManager()
+                    .getPackagesHoldingPermissions(PERM, 0 /*flags*/,
+                            ActivityManager.getCurrentUser());
+            final List<PackageInfo> pkgs = list.getList();
+            if (pkgs != null) {
+                for (PackageInfo info : pkgs) {
+                    requestingPackages.add(info.packageName);
+                }
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "Cannot reach packagemanager", e);
+        }
+        return requestingPackages;
+    }
+
+    public static Set<String> getAutoApprovedPackages(Context context) {
+        final Set<String> autoApproved = new ArraySet<>();
+        autoApproved.addAll(context.getSystemService(NotificationManager.class)
+                .getEnabledNotificationListenerPackages());
+        return autoApproved;
+    }
+
+    public static boolean hasAccess(Context context, String pkg) {
+        return context.getSystemService(
+                NotificationManager.class).isNotificationPolicyAccessGrantedForPackage(pkg);
+    }
+
+    public static void setAccess(final Context context, final String pkg, final boolean access) {
+        logSpecialPermissionChange(access, pkg, context);
+        AsyncTask.execute(() -> {
+            final NotificationManager mgr = context.getSystemService(NotificationManager.class);
+            mgr.setNotificationPolicyAccessGranted(pkg, access);
+        });
+    }
+
+    public static void deleteRules(final Context context, final String pkg) {
+        AsyncTask.execute(() -> {
+            final NotificationManager mgr = context.getSystemService(NotificationManager.class);
+            mgr.removeAutomaticZenRules(pkg);
+        });
+    }
+
+    @VisibleForTesting
+    static void logSpecialPermissionChange(boolean enable, String packageName, Context context) {
+        int logCategory = enable ? SettingsEnums.APP_SPECIAL_PERMISSION_DND_ALLOW
+                : SettingsEnums.APP_SPECIAL_PERMISSION_DND_DENY;
+        FeatureFactory.getFactory(context).getMetricsFeatureProvider().action(context,
+                logCategory, packageName);
+    }
+}
diff --git a/src/com/android/settings/applications/specialaccess/zenaccess/ZenAccessDetails.java b/src/com/android/settings/applications/specialaccess/zenaccess/ZenAccessDetails.java
new file mode 100644
index 0000000..a18e7d6
--- /dev/null
+++ b/src/com/android/settings/applications/specialaccess/zenaccess/ZenAccessDetails.java
@@ -0,0 +1,100 @@
+/*
+ * 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.applications.specialaccess.zenaccess;
+
+import android.app.ActivityManager;
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.os.Bundle;
+
+import androidx.appcompat.app.AlertDialog;
+import androidx.preference.SwitchPreference;
+
+import com.android.settings.R;
+import com.android.settings.applications.AppInfoWithHeader;
+
+import java.util.Set;
+
+public class ZenAccessDetails extends AppInfoWithHeader implements
+        ZenAccessSettingObserverMixin.Listener {
+
+    private static final String SWITCH_PREF_KEY = "zen_access_switch";
+
+    @Override
+    public int getMetricsCategory() {
+        return SettingsEnums.ZEN_ACCESS_DETAIL;
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        addPreferencesFromResource(R.xml.zen_access_permission_details);
+        getSettingsLifecycle().addObserver(
+                new ZenAccessSettingObserverMixin(getContext(), this /* listener */));
+    }
+
+    @Override
+    protected boolean refreshUi() {
+        final Context context = getContext();
+        if (!ZenAccessController.isSupported(context.getSystemService(ActivityManager.class))) {
+            return false;
+        }
+        // If this app didn't declare this permission in their manifest, don't bother showing UI.
+        final Set<String> needAccessApps =
+                ZenAccessController.getPackagesRequestingNotificationPolicyAccess();
+        if (!needAccessApps.contains(mPackageName)) {
+            return false;
+        }
+        updatePreference(context, findPreference(SWITCH_PREF_KEY));
+        return true;
+    }
+
+    @Override
+    protected AlertDialog createDialog(int id, int errorCode) {
+        return null;
+    }
+
+    public void updatePreference(Context context, SwitchPreference preference) {
+        final CharSequence label = mPackageInfo.applicationInfo.loadLabel(mPm);
+        final Set<String> autoApproved = ZenAccessController.getAutoApprovedPackages(context);
+        if (autoApproved.contains(mPackageName)) {
+            //Auto approved, user cannot do anything. Hard code summary and disable preference.
+            preference.setEnabled(false);
+            preference.setSummary(getString(R.string.zen_access_disabled_package_warning));
+            return;
+        }
+        preference.setChecked(ZenAccessController.hasAccess(context, mPackageName));
+        preference.setOnPreferenceChangeListener((p, newValue) -> {
+            final boolean access = (Boolean) newValue;
+            if (access) {
+                new ScaryWarningDialogFragment()
+                        .setPkgInfo(mPackageName, label)
+                        .show(getFragmentManager(), "dialog");
+            } else {
+                new FriendlyWarningDialogFragment()
+                        .setPkgInfo(mPackageName, label)
+                        .show(getFragmentManager(), "dialog");
+            }
+            return false;
+        });
+    }
+
+    @Override
+    public void onZenAccessPolicyChanged() {
+        refreshUi();
+    }
+}
diff --git a/src/com/android/settings/applications/specialaccess/zenaccess/ZenAccessSettingObserverMixin.java b/src/com/android/settings/applications/specialaccess/zenaccess/ZenAccessSettingObserverMixin.java
new file mode 100644
index 0000000..30507ef
--- /dev/null
+++ b/src/com/android/settings/applications/specialaccess/zenaccess/ZenAccessSettingObserverMixin.java
@@ -0,0 +1,77 @@
+/*
+ * 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.applications.specialaccess.zenaccess;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
+import android.provider.Settings;
+
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnStart;
+import com.android.settingslib.core.lifecycle.events.OnStop;
+
+public class ZenAccessSettingObserverMixin extends ContentObserver implements LifecycleObserver,
+        OnStart, OnStop {
+
+    public interface Listener {
+        void onZenAccessPolicyChanged();
+    }
+
+    private final Context mContext;
+    private final Listener mListener;
+
+    public ZenAccessSettingObserverMixin(Context context, Listener listener) {
+        super(new Handler(Looper.getMainLooper()));
+        mContext = context;
+        mListener = listener;
+    }
+
+    @Override
+    public void onChange(boolean selfChange, Uri uri) {
+        if (mListener != null) {
+            mListener.onZenAccessPolicyChanged();
+        }
+    }
+
+    @Override
+    public void onStart() {
+        if (!ZenAccessController.isSupported(mContext.getSystemService(ActivityManager.class))) {
+            return;
+        }
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Secure.getUriFor(
+                        Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES),
+                false /* notifyForDescendants */,
+                this /* observer */);
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Secure.getUriFor(Settings.Secure.ENABLED_NOTIFICATION_LISTENERS),
+                false /* notifyForDescendants */,
+                this /* observer */);
+    }
+
+    @Override
+    public void onStop() {
+        if (!ZenAccessController.isSupported(mContext.getSystemService(ActivityManager.class))) {
+            return;
+        }
+        mContext.getContentResolver().unregisterContentObserver(this /* observer */);
+    }
+}
diff --git a/src/com/android/settings/backup/BackupSettingsHelper.java b/src/com/android/settings/backup/BackupSettingsHelper.java
index fa77154..b836e55 100644
--- a/src/com/android/settings/backup/BackupSettingsHelper.java
+++ b/src/com/android/settings/backup/BackupSettingsHelper.java
@@ -209,7 +209,7 @@
     }
 
     /** Checks if backup service is enabled for this user. */
-    private boolean isBackupServiceActive() {
+    public boolean isBackupServiceActive() {
         boolean backupOkay;
         try {
             backupOkay = mBackupManager.isBackupServiceActive(UserHandle.myUserId());
diff --git a/src/com/android/settings/backup/OWNERS b/src/com/android/settings/backup/OWNERS
index c026a35..a7b55fd 100644
--- a/src/com/android/settings/backup/OWNERS
+++ b/src/com/android/settings/backup/OWNERS
@@ -1,6 +1,13 @@
-# Default reviewers for this and subdirectories.
+# Use this reviewer by default.
+br-framework-team+reviews@google.com
+
+# People who can approve changes for submission.
+anniemeng@google.com
+nathch@google.com
+rthakohov@google.com
+
+# Others (in case above are not available).
 bryanmawhinney@google.com
-cprins@google.com
 jorlow@google.com
 philippov@google.com
 stefanot@google.com
\ No newline at end of file
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollAccessibilityToggle.java b/src/com/android/settings/biometrics/face/FaceEnrollAccessibilityToggle.java
index 49f4f7f..2db654b 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollAccessibilityToggle.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollAccessibilityToggle.java
@@ -58,9 +58,14 @@
             a.recycle();
         }
         mSwitch = findViewById(R.id.toggle);
+        mSwitch.setChecked(false);
     }
 
     public boolean isChecked() {
         return mSwitch.isChecked();
     }
+
+    public void setChecked(boolean checked) {
+        mSwitch.setChecked(checked);
+    }
 }
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
index 5f2b675..c7966f2 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
@@ -53,6 +53,7 @@
         final LinearLayout accessibilityLayout = findViewById(R.id.accessibility_layout);
         final Button accessibilityButton = findViewById(R.id.accessibility_button);
         accessibilityButton.setOnClickListener(view -> {
+            mSwitchDiversity.setChecked(true);
             accessibilityButton.setVisibility(View.INVISIBLE);
             accessibilityLayout.setVisibility(View.VISIBLE);
         });
@@ -177,7 +178,7 @@
         } else {
             intent.setClass(this, FaceEnrollEnrolling.class);
         }
-        intent.putExtra(EXTRA_KEY_REQUIRE_DIVERSITY, mSwitchDiversity.isChecked());
+        intent.putExtra(EXTRA_KEY_REQUIRE_DIVERSITY, !mSwitchDiversity.isChecked());
         WizardManagerHelper.copyWizardManagerExtras(getIntent(), intent);
         return intent;
     }
diff --git a/src/com/android/settings/core/HideNonSystemOverlayMixin.java b/src/com/android/settings/core/HideNonSystemOverlayMixin.java
new file mode 100644
index 0000000..59cef3b
--- /dev/null
+++ b/src/com/android/settings/core/HideNonSystemOverlayMixin.java
@@ -0,0 +1,64 @@
+/*
+ * 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.core;
+
+import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+
+import static androidx.lifecycle.Lifecycle.Event.ON_START;
+import static androidx.lifecycle.Lifecycle.Event.ON_STOP;
+
+import android.app.Activity;
+import android.view.Window;
+import android.view.WindowManager;
+
+import androidx.lifecycle.LifecycleObserver;
+import androidx.lifecycle.OnLifecycleEvent;
+
+
+/**
+ * A mixin that adds window flag to prevent non-system overlays showing on top of Settings
+ * activities.
+ */
+public class HideNonSystemOverlayMixin implements LifecycleObserver {
+
+    private final Activity mActivity;
+
+    public HideNonSystemOverlayMixin(Activity activity) {
+        mActivity = activity;
+    }
+
+    @OnLifecycleEvent(ON_START)
+    public void onStart() {
+        if (mActivity == null) {
+            return;
+        }
+        mActivity.getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
+        android.util.EventLog.writeEvent(0x534e4554, "120484087", -1, "");
+    }
+
+
+    @OnLifecycleEvent(ON_STOP)
+    public void onStop() {
+        if (mActivity == null) {
+            return;
+        }
+        final Window window = mActivity.getWindow();
+        final WindowManager.LayoutParams attrs = window.getAttributes();
+        attrs.privateFlags &= ~SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+        window.setAttributes(attrs);
+    }
+}
diff --git a/src/com/android/settings/core/SettingsBaseActivity.java b/src/com/android/settings/core/SettingsBaseActivity.java
index 294e754..cd13654 100644
--- a/src/com/android/settings/core/SettingsBaseActivity.java
+++ b/src/com/android/settings/core/SettingsBaseActivity.java
@@ -32,7 +32,6 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.Window;
-import android.view.WindowManager.LayoutParams;
 import android.widget.Toolbar;
 
 import androidx.fragment.app.FragmentActivity;
@@ -59,8 +58,8 @@
     @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-
         final long startTime = System.currentTimeMillis();
+        getLifecycle().addObserver(new HideNonSystemOverlayMixin(this));
 
         final TypedArray theme = getTheme().obtainStyledAttributes(android.R.styleable.Theme);
         if (!theme.getBoolean(android.R.styleable.Theme_windowNoTitle, false)) {
diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java
index 147d0be..d522918 100644
--- a/src/com/android/settings/core/gateway/SettingsGateway.java
+++ b/src/com/android/settings/core/gateway/SettingsGateway.java
@@ -50,6 +50,7 @@
 import com.android.settings.applications.specialaccess.pictureinpicture.PictureInPictureDetails;
 import com.android.settings.applications.specialaccess.pictureinpicture.PictureInPictureSettings;
 import com.android.settings.applications.specialaccess.vrlistener.VrListenerSettings;
+import com.android.settings.applications.specialaccess.zenaccess.ZenAccessDetails;
 import com.android.settings.backup.PrivacySettings;
 import com.android.settings.backup.ToggleBackupSettingFragment;
 import com.android.settings.backup.UserBackupSettingsActivity;
@@ -135,6 +136,7 @@
 import com.android.settings.wifi.WifiAPITest;
 import com.android.settings.wifi.WifiInfo;
 import com.android.settings.wifi.WifiSettings;
+import com.android.settings.wifi.calling.WifiCallingDisclaimerFragment;
 import com.android.settings.wifi.calling.WifiCallingSettings;
 import com.android.settings.wifi.p2p.WifiP2pSettings;
 import com.android.settings.wifi.savedaccesspoints.SavedAccessPointsWifiSettings;
@@ -208,6 +210,7 @@
             UserSettings.class.getName(),
             NotificationAccessSettings.class.getName(),
             ZenAccessSettings.class.getName(),
+            ZenAccessDetails.class.getName(),
             ZenModeAutomationSettings.class.getName(),
             PrintSettingsFragment.class.getName(),
             PrintJobSettingsFragment.class.getName(),
@@ -260,6 +263,7 @@
             ConnectedDeviceDashboardFragment.class.getName(),
             UsbDetailsFragment.class.getName(),
             AppAndNotificationDashboardFragment.class.getName(),
+            WifiCallingDisclaimerFragment.class.getName(),
             AccountDashboardFragment.class.getName(),
             EnterprisePrivacySettings.class.getName(),
             WebViewAppPicker.class.getName(),
diff --git a/src/com/android/settings/datetime/timezone/BaseTimeZoneAdapter.java b/src/com/android/settings/datetime/timezone/BaseTimeZoneAdapter.java
index ff980b2..66735c8 100644
--- a/src/com/android/settings/datetime/timezone/BaseTimeZoneAdapter.java
+++ b/src/com/android/settings/datetime/timezone/BaseTimeZoneAdapter.java
@@ -77,9 +77,10 @@
     @Override
     public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
         LayoutInflater inflater = LayoutInflater.from(parent.getContext());
-        switch(viewType) {
+        switch (viewType) {
             case TYPE_HEADER: {
-                final View view = inflater.inflate(R.layout.preference_category_material,
+                final View view = inflater.inflate(
+                        R.layout.time_zone_search_header,
                         parent, false);
                 return new HeaderViewHolder(view);
             }
@@ -136,7 +137,8 @@
         return mShowHeader && position == 0;
     }
 
-    public @NonNull ArrayFilter getFilter() {
+    @NonNull
+    public ArrayFilter getFilter() {
         if (mFilter == null) {
             mFilter = new ArrayFilter();
         }
@@ -153,14 +155,18 @@
 
     public interface AdapterItem {
         CharSequence getTitle();
+
         CharSequence getSummary();
+
         String getIconText();
+
         String getCurrentTime();
 
         /**
          * @return unique non-negative number
          */
         long getItemId();
+
         String[] getSearchKeys();
     }
 
diff --git a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverStickyPreferenceController.java b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverStickyPreferenceController.java
index b14fec9..7a1f7f5 100644
--- a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverStickyPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverStickyPreferenceController.java
@@ -19,7 +19,7 @@
 
     @Override
     public void updateState(Preference preference) {
-        int setting = Settings.System.getInt(mContext.getContentResolver(),
+        int setting = Settings.Global.getInt(mContext.getContentResolver(),
                 LOW_POWER_STICKY_AUTO_DISABLE_ENABLED, 1);
 
         ((SwitchPreference) preference).setChecked(setting == 0);
@@ -28,7 +28,7 @@
     @Override
     public boolean onPreferenceChange(Preference preference, Object newValue) {
         boolean keepActive = (Boolean) newValue;
-        Settings.System.putInt(mContext.getContentResolver(),
+        Settings.Global.putInt(mContext.getContentResolver(),
                 LOW_POWER_STICKY_AUTO_DISABLE_ENABLED,
                 keepActive ? 0 : 1);
         return true;
diff --git a/src/com/android/settings/gestures/SystemNavigationPreferenceController.java b/src/com/android/settings/gestures/SystemNavigationPreferenceController.java
index a11754e..e1be9d4 100644
--- a/src/com/android/settings/gestures/SystemNavigationPreferenceController.java
+++ b/src/com/android/settings/gestures/SystemNavigationPreferenceController.java
@@ -51,13 +51,15 @@
     private static final String ENABLE_ASSISTANT_GESTURE = "ENABLE_ASSISTANT_GESTURE";
     private static final String PROTOTYPE_ENABLED = "prototype_enabled";
 
-    private static final int EDGE_SENSITIVITY_WIDTH = 32;
+    private static final int EDGE_SENSITIVITY_WIDTH = 48;
     private static final String EDGE_SENSITIVITY_KEY = "quickstepcontroller_edge_width_sensitivity";
 
     private static final String GESTURES_MATCH_MAP_OFF = "000000";
     private static final String GESTURES_MATCH_MAP_ON = "071133";
     private static final String GESTURES_MATCH_MAP_KEY = "quickstepcontroller_gesture_match_map";
 
+    private static final String OVERLAY_NAVBAR_KEY =
+            "com.android.internal.experiment.navbar.default";
     private static final String OVERLAY_NAVBAR_TYPE_INSET =
             "com.android.internal.experiment.navbar.type.inset";
     private static final String OVERLAY_NAVBAR_TYPE_FLOATING =
@@ -174,6 +176,7 @@
                 .asInterface(ServiceManager.getService(Context.OVERLAY_SERVICE));
         if (overlayManager != null) {
             try {
+                overlayManager.setEnabled(OVERLAY_NAVBAR_KEY, true, USER_SYSTEM);
                 overlayManager.setEnabled(OVERLAY_NAVBAR_TYPE_FLOATING, false, USER_SYSTEM);
                 overlayManager.setEnabled(OVERLAY_NAVBAR_TYPE_INSET, enable, USER_SYSTEM);
             } catch (RemoteException e) {
diff --git a/src/com/android/settings/gestures/WakeScreenGestureSettings.java b/src/com/android/settings/gestures/WakeScreenGestureSettings.java
deleted file mode 100644
index b8a782a..0000000
--- a/src/com/android/settings/gestures/WakeScreenGestureSettings.java
+++ /dev/null
@@ -1,65 +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.gestures;
-
-import android.app.settings.SettingsEnums;
-import android.content.Context;
-import android.provider.SearchIndexableResource;
-
-import com.android.settings.R;
-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 WakeScreenGestureSettings extends DashboardFragment {
-
-    private static final String TAG = "WakeScreenGestureSettings";
-
-    public static final String PREF_KEY_SUGGESTION_COMPLETE =
-            "pref_wake_screen_gesture_suggestion_complete";
-
-    @Override
-    public int getMetricsCategory() {
-        return SettingsEnums.SETTINGS_GESTURE_WAKE_SCREEN;
-    }
-
-    @Override
-    protected String getLogTag() {
-        return TAG;
-    }
-
-    @Override
-    protected int getPreferenceScreenResId() {
-        return R.xml.wake_screen_gesture_settings;
-    }
-
-    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.wake_screen_gesture_settings;
-                    return Arrays.asList(sir);
-                }
-            };
-
-}
diff --git a/src/com/android/settings/homepage/SettingsHomepageActivity.java b/src/com/android/settings/homepage/SettingsHomepageActivity.java
index 9e869a9..9b83f88 100644
--- a/src/com/android/settings/homepage/SettingsHomepageActivity.java
+++ b/src/com/android/settings/homepage/SettingsHomepageActivity.java
@@ -17,6 +17,7 @@
 package com.android.settings.homepage;
 
 import android.animation.LayoutTransition;
+import android.app.ActivityManager;
 import android.app.settings.SettingsEnums;
 import android.os.Bundle;
 import android.view.View;
@@ -53,7 +54,10 @@
         final AvatarViewMixin avatarViewMixin = new AvatarViewMixin(this, avatarView);
         getLifecycle().addObserver(avatarViewMixin);
 
-        showFragment(new ContextualCardsFragment(), R.id.contextual_cards_content);
+        if (!getSystemService(ActivityManager.class).isLowRamDevice()) {
+            // Only allow contextual feature on high ram devices.
+            showFragment(new ContextualCardsFragment(), R.id.contextual_cards_content);
+        }
         showFragment(new TopLevelSettings(), R.id.main_content);
         ((FrameLayout) findViewById(R.id.main_content))
                 .getLayoutTransition().enableTransitionType(LayoutTransition.CHANGING);
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImpl.java b/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImpl.java
index 43e90e8..ce7777a 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImpl.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImpl.java
@@ -139,7 +139,7 @@
         final String action = mContext.getString(R.string.config_settingsintelligence_log_action);
         if (!TextUtils.isEmpty(action)) {
             intent.setAction(action);
-            mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+            mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
         }
     }
 
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
index 13564b5..1f5f7dd 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
@@ -67,7 +67,8 @@
 
     @VisibleForTesting
     Uri mNotifyUri;
-    private Context mContext;
+
+    private final Context mContext;
 
     ContextualCardLoader(Context context) {
         super(context);
@@ -186,7 +187,6 @@
         // Collect future and eligible cards
         for (Future<ContextualCard> cardFuture : eligibleCards) {
             try {
-                //TODO(b/124492762): Log latency and timeout occurrence.
                 final ContextualCard card = cardFuture.get(ELIGIBILITY_CHECKER_TIMEOUT_MS,
                         TimeUnit.MILLISECONDS);
                 if (card != null) {
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java b/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
index c829015..7df322d 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
@@ -22,6 +22,7 @@
 
 import static java.util.stream.Collectors.groupingBy;
 
+import android.app.settings.SettingsEnums;
 import android.content.Context;
 import android.os.Bundle;
 import android.provider.Settings;
@@ -38,6 +39,7 @@
 
 import com.android.settings.homepage.contextualcards.slices.SliceContextualCardRenderer;
 import com.android.settings.overlay.FeatureFactory;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
 import com.android.settingslib.core.lifecycle.events.OnSaveInstanceState;
@@ -109,13 +111,13 @@
         }
     }
 
-    void loadContextualCards(ContextualCardsFragment fragment) {
+    void loadContextualCards(LoaderManager loaderManager) {
         mStartTime = System.currentTimeMillis();
         final CardContentLoaderCallbacks cardContentLoaderCallbacks =
                 new CardContentLoaderCallbacks(mContext);
         cardContentLoaderCallbacks.setListener(this);
         // Use the cached data when navigating back to the first page and upon screen rotation.
-        LoaderManager.getInstance(fragment).initLoader(CARD_CONTENT_LOADER_ID, null /* bundle */,
+        loaderManager.initLoader(CARD_CONTENT_LOADER_ID, null /* bundle */,
                 cardContentLoaderCallbacks);
     }
 
@@ -195,8 +197,8 @@
     @Override
     public void onFinishCardLoading(List<ContextualCard> cards) {
         final long loadTime = System.currentTimeMillis() - mStartTime;
-        //TODO(b/123668403): remove the log here once we do the change with FutureTask
         Log.d(TAG, "Total loading time = " + loadTime);
+
         final List<ContextualCard> cardsToKeep = getCardsToKeep(cards);
 
         //navigate back to the homepage, screen rotate or after card dismissal
@@ -206,15 +208,25 @@
             return;
         }
 
-        //only log homepage display upon a fresh launch
+        final MetricsFeatureProvider metricsFeatureProvider =
+                FeatureFactory.getFactory(mContext).getMetricsFeatureProvider();
         final long timeoutLimit = getCardLoaderTimeout(mContext);
         if (loadTime <= timeoutLimit) {
             onContextualCardUpdated(cards.stream()
                     .collect(groupingBy(ContextualCard::getCardType)));
+        } else {
+            // log timeout occurrence
+            metricsFeatureProvider.action(SettingsEnums.PAGE_UNKNOWN,
+                    SettingsEnums.ACTION_CONTEXTUAL_CARD_LOAD_TIMEOUT,
+                    SettingsEnums.SETTINGS_HOMEPAGE,
+                    null /* key */, (int) loadTime /* value */);
         }
+        //only log homepage display upon a fresh launch
         final long totalTime = System.currentTimeMillis() - mStartTime;
         FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider(mContext)
                 .logHomepageDisplay(totalTime);
+        metricsFeatureProvider.action(mContext,
+                SettingsEnums.ACTION_CONTEXTUAL_HOME_SHOW, (int) totalTime);
 
         mIsFirstLaunch = false;
     }
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardsFragment.java b/src/com/android/settings/homepage/contextualcards/ContextualCardsFragment.java
index e598e4c..72ddb50 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardsFragment.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardsFragment.java
@@ -19,16 +19,19 @@
 import static com.android.settings.homepage.contextualcards.ContextualCardsAdapter.SPAN_COUNT;
 
 import android.app.settings.SettingsEnums;
+import android.content.Context;
 import android.os.Bundle;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 
+import androidx.loader.app.LoaderManager;
 import androidx.recyclerview.widget.GridLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
 
 import com.android.settings.R;
 import com.android.settings.core.InstrumentedFragment;
+import com.android.settings.overlay.FeatureFactory;
 
 public class ContextualCardsFragment extends InstrumentedFragment {
 
@@ -42,14 +45,19 @@
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        mContextualCardManager = new ContextualCardManager(getContext(), getSettingsLifecycle(),
+        final Context context = getContext();
+        if (savedInstanceState == null) {
+            FeatureFactory.getFactory(context).getSlicesFeatureProvider().newUiSession();
+        }
+        mContextualCardManager = new ContextualCardManager(context, getSettingsLifecycle(),
                 savedInstanceState);
+
     }
 
     @Override
     public void onStart() {
         super.onStart();
-        mContextualCardManager.loadContextualCards(this);
+        mContextualCardManager.loadContextualCards(LoaderManager.getInstance(this));
     }
 
     @Override
diff --git a/src/com/android/settings/homepage/contextualcards/EligibleCardChecker.java b/src/com/android/settings/homepage/contextualcards/EligibleCardChecker.java
index fe68d02..811aaa2 100644
--- a/src/com/android/settings/homepage/contextualcards/EligibleCardChecker.java
+++ b/src/com/android/settings/homepage/contextualcards/EligibleCardChecker.java
@@ -18,6 +18,7 @@
 
 import static android.app.slice.Slice.HINT_ERROR;
 
+import android.app.settings.SettingsEnums;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.net.Uri;
@@ -27,6 +28,9 @@
 import androidx.slice.Slice;
 import androidx.slice.SliceViewManager;
 
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
+
 import java.util.concurrent.Callable;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -46,7 +50,32 @@
 
     @Override
     public ContextualCard call() throws Exception {
-        return isCardEligibleToDisplay(mCard) ? mCard : null;
+        final long startTime = System.currentTimeMillis();
+        final MetricsFeatureProvider metricsFeatureProvider =
+                FeatureFactory.getFactory(mContext).getMetricsFeatureProvider();
+        ContextualCard result;
+
+        if (isCardEligibleToDisplay(mCard)) {
+            metricsFeatureProvider.action(SettingsEnums.PAGE_UNKNOWN,
+                    SettingsEnums.ACTION_CONTEXTUAL_CARD_ELIGIBILITY,
+                    SettingsEnums.SETTINGS_HOMEPAGE,
+                    mCard.getTextSliceUri() /* key */, 1 /* true */);
+            result = mCard;
+        } else {
+            metricsFeatureProvider.action(SettingsEnums.PAGE_UNKNOWN,
+                    SettingsEnums.ACTION_CONTEXTUAL_CARD_ELIGIBILITY,
+                    SettingsEnums.SETTINGS_HOMEPAGE,
+                    mCard.getTextSliceUri() /* key */, 0 /* false */);
+            result = null;
+        }
+        // Log individual card loading time
+        metricsFeatureProvider.action(SettingsEnums.PAGE_UNKNOWN,
+                SettingsEnums.ACTION_CONTEXTUAL_CARD_LOAD,
+                SettingsEnums.SETTINGS_HOMEPAGE,
+                mCard.getTextSliceUri() /* key */,
+                (int) (System.currentTimeMillis() - startTime) /* value */);
+
+        return result;
     }
 
     @VisibleForTesting
diff --git a/src/com/android/settings/homepage/contextualcards/conditional/ConditionManager.java b/src/com/android/settings/homepage/contextualcards/conditional/ConditionManager.java
index c741b98..66f6c81 100644
--- a/src/com/android/settings/homepage/contextualcards/conditional/ConditionManager.java
+++ b/src/com/android/settings/homepage/contextualcards/conditional/ConditionManager.java
@@ -162,6 +162,7 @@
         mCardControllers.add(new RingerVibrateConditionController(mAppContext, this /* manager */));
         mCardControllers.add(new RingerMutedConditionController(mAppContext, this /* manager */));
         mCardControllers.add(new WorkModeConditionController(mAppContext, this /* manager */));
+        mCardControllers.add(new GrayscaleConditionController(mAppContext, this /* manager */));
     }
 
     /**
diff --git a/src/com/android/settings/homepage/contextualcards/conditional/GrayscaleConditionController.java b/src/com/android/settings/homepage/contextualcards/conditional/GrayscaleConditionController.java
new file mode 100644
index 0000000..664707d
--- /dev/null
+++ b/src/com/android/settings/homepage/contextualcards/conditional/GrayscaleConditionController.java
@@ -0,0 +1,103 @@
+/*
+ * 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.conditional;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.content.Intent;
+import android.hardware.display.ColorDisplayManager;
+import android.util.Log;
+
+import com.android.settings.R;
+import com.android.settings.homepage.contextualcards.ContextualCard;
+
+import java.net.URISyntaxException;
+import java.util.Objects;
+
+public class GrayscaleConditionController implements ConditionalCardController {
+    static final int ID = Objects.hash("GrayscaleConditionController");
+
+    private static final String TAG = "GrayscaleCondition";
+
+    private final Context mAppContext;
+    private final ConditionManager mConditionManager;
+    private final ColorDisplayManager mColorDisplayManager;
+
+    private Intent mIntent;
+
+    public GrayscaleConditionController(Context appContext, ConditionManager conditionManager) {
+        mAppContext = appContext;
+        mConditionManager = conditionManager;
+        mColorDisplayManager = mAppContext.getSystemService(ColorDisplayManager.class);
+    }
+
+    @Override
+    public long getId() {
+        return ID;
+    }
+
+    @Override
+    public boolean isDisplayable() {
+        try {
+            mIntent = Intent.parseUri(
+                    mAppContext.getString(R.string.config_grayscale_settings_intent),
+                    Intent.URI_INTENT_SCHEME);
+        } catch (URISyntaxException e) {
+            Log.w(TAG, "Failure parsing grayscale settings intent, skipping", e);
+            return false;
+        }
+        return mColorDisplayManager.isSaturationActivated();
+    }
+
+    @Override
+    public void onPrimaryClick(Context context) {
+        mAppContext.startActivity(mIntent);
+    }
+
+    @Override
+    public void onActionClick() {
+        // Turn off grayscale
+        mColorDisplayManager.setSaturationLevel(100 /* staturationLevel */);
+        mConditionManager.onConditionChanged();
+    }
+
+    @Override
+    public ContextualCard buildContextualCard() {
+        return new ConditionalContextualCard.Builder()
+                .setConditionId(ID)
+                .setMetricsConstant(SettingsEnums.SETTINGS_CONDITION_GRAYSCALE_MODE)
+                .setActionText(mAppContext.getText(R.string.condition_turn_off))
+                .setName(mAppContext.getPackageName() + "/" + mAppContext.getText(
+                        R.string.condition_grayscale_title))
+                .setTitleText(mAppContext.getText(R.string.condition_grayscale_title).toString())
+                .setSummaryText(
+                        mAppContext.getText(R.string.condition_grayscale_summary).toString())
+                .setIconDrawable(mAppContext.getDrawable(R.drawable.ic_gray_scale_24dp))
+                .setViewType(ConditionContextualCardRenderer.VIEW_TYPE_HALF_WIDTH)
+                .build();
+    }
+
+    @Override
+    public void startMonitoringStateChange() {
+
+    }
+
+    @Override
+    public void stopMonitoringStateChange() {
+
+    }
+}
diff --git a/src/com/android/settings/homepage/contextualcards/deviceinfo/BatteryInfoSlice.java b/src/com/android/settings/homepage/contextualcards/deviceinfo/BatteryInfoSlice.java
deleted file mode 100644
index 6c7f930..0000000
--- a/src/com/android/settings/homepage/contextualcards/deviceinfo/BatteryInfoSlice.java
+++ /dev/null
@@ -1,139 +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.homepage.contextualcards.deviceinfo;
-
-import android.app.PendingIntent;
-import android.app.settings.SettingsEnums;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.net.Uri;
-import android.os.PowerManager;
-
-import androidx.annotation.VisibleForTesting;
-import androidx.core.graphics.drawable.IconCompat;
-import androidx.slice.Slice;
-import androidx.slice.builders.ListBuilder;
-import androidx.slice.builders.SliceAction;
-
-import com.android.settings.R;
-import com.android.settings.SubSettings;
-import com.android.settings.Utils;
-import com.android.settings.fuelgauge.BatteryInfo;
-import com.android.settings.fuelgauge.PowerUsageSummary;
-import com.android.settings.slices.CustomSliceRegistry;
-import com.android.settings.slices.CustomSliceable;
-import com.android.settings.slices.SliceBuilderUtils;
-
-/**
- * Utility class to build a Battery Slice, and handle all associated actions.
- */
-public class BatteryInfoSlice implements CustomSliceable {
-    private static final String TAG = "BatteryInfoSlice";
-
-    private final Context mContext;
-
-    private BatteryInfo mBatteryInfo;
-    private boolean mIsBatteryInfoLoading;
-
-    public BatteryInfoSlice(Context context) {
-        mContext = context;
-    }
-
-    @Override
-    public Slice getSlice() {
-        if (mBatteryInfo == null) {
-            mIsBatteryInfoLoading = true;
-            loadBatteryInfo();
-        }
-        final IconCompat icon = IconCompat.createWithResource(mContext,
-                R.drawable.ic_settings_battery);
-        final CharSequence title = mContext.getText(R.string.power_usage_summary_title);
-        final SliceAction primarySliceAction = SliceAction.createDeeplink(getPrimaryAction(), icon,
-                ListBuilder.ICON_IMAGE, title);
-        final Slice slice = new ListBuilder(mContext, CustomSliceRegistry.BATTERY_INFO_SLICE_URI,
-                ListBuilder.INFINITY)
-                .setAccentColor(Utils.getColorAccentDefaultColor(mContext))
-                .setHeader(new ListBuilder.HeaderBuilder().setTitle(title))
-                .addRow(new ListBuilder.RowBuilder()
-                        .setTitle(getBatteryPercentString(), mIsBatteryInfoLoading)
-                        .setSubtitle(getSummary(), mIsBatteryInfoLoading)
-                        .setPrimaryAction(primarySliceAction))
-                .build();
-        mBatteryInfo = null;
-        mIsBatteryInfoLoading = false;
-        return slice;
-    }
-
-    @Override
-    public Uri getUri() {
-        return CustomSliceRegistry.BATTERY_INFO_SLICE_URI;
-    }
-
-    @Override
-    public void onNotifyChange(Intent intent) {
-
-    }
-
-    @Override
-    public Intent getIntent() {
-        final String screenTitle = mContext.getText(R.string.power_usage_summary_title).toString();
-        return SliceBuilderUtils.buildSearchResultPageIntent(mContext,
-                PowerUsageSummary.class.getName(), "" /* key */, screenTitle,
-                SettingsEnums.SLICE)
-                .setClassName(mContext.getPackageName(), SubSettings.class.getName())
-                .setData(CustomSliceRegistry.BATTERY_INFO_SLICE_URI);
-    }
-
-    @Override
-    public IntentFilter getIntentFilter() {
-        final IntentFilter intentFilter = new IntentFilter();
-        intentFilter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
-        intentFilter.addAction(Intent.ACTION_POWER_CONNECTED);
-        intentFilter.addAction(Intent.ACTION_POWER_DISCONNECTED);
-        intentFilter.addAction(Intent.ACTION_BATTERY_LEVEL_CHANGED);
-        return intentFilter;
-    }
-
-    @VisibleForTesting
-    void loadBatteryInfo() {
-        BatteryInfo.getBatteryInfo(mContext, info -> {
-            mBatteryInfo = info;
-            mContext.getContentResolver().notifyChange(getUri(), null);
-        }, true);
-    }
-
-    @VisibleForTesting
-    CharSequence getBatteryPercentString() {
-        return mBatteryInfo == null ? null : mBatteryInfo.batteryPercentString;
-    }
-
-    @VisibleForTesting
-    CharSequence getSummary() {
-        if (mBatteryInfo == null) {
-            return null;
-        }
-        return mBatteryInfo.remainingLabel == null ? mBatteryInfo.statusLabel
-                : mBatteryInfo.remainingLabel;
-    }
-
-    private PendingIntent getPrimaryAction() {
-        final Intent intent = getIntent();
-        return PendingIntent.getActivity(mContext, 0 /* requestCode */,
-                intent, 0 /* flags */);
-    }
-}
\ No newline at end of file
diff --git a/src/com/android/settings/location/RecentLocationAccessPreferenceController.java b/src/com/android/settings/location/RecentLocationAccessPreferenceController.java
index 44d600e..a76d381 100644
--- a/src/com/android/settings/location/RecentLocationAccessPreferenceController.java
+++ b/src/com/android/settings/location/RecentLocationAccessPreferenceController.java
@@ -74,6 +74,7 @@
         mController = AppEntitiesHeaderController.newInstance(mContext, view)
                 .setHeaderTitleRes(R.string.location_category_recent_location_access)
                 .setHeaderDetailsRes(R.string.location_recent_location_access_view_details)
+                .setHeaderEmptyRes(R.string.location_no_recent_accesses)
                 .setHeaderDetailsClickListener((View v) -> {
                     final Intent intent = new Intent(Intent.ACTION_REVIEW_PERMISSION_USAGE);
                     intent.putExtra(Intent.EXTRA_PERMISSION_NAME,
@@ -100,14 +101,20 @@
                         .setIcon(access.icon)
                         .setTitle(access.label)
                         .setSummary(access.contentDescription)
+                        .setOnClickListener((v) -> {
+                            final Intent intent = new Intent(Intent.ACTION_MANAGE_APP_PERMISSION);
+                            intent.putExtra(Intent.EXTRA_PERMISSION_NAME,
+                                    Manifest.permission_group.LOCATION);
+                            intent.putExtra(Intent.EXTRA_PACKAGE_NAME, access.packageName);
+                            intent.putExtra(Intent.EXTRA_USER, access.userHandle);
+                            mContext.startActivity(intent);
+                        })
                         .build();
                 mController.setAppEntity(i, appEntityInfo);
             }
             for (; i < MAXIMUM_APP_COUNT; i++) {
                 mController.removeAppEntity(i);
             }
-        } else {
-            // If there's no item to display, add a "No recent apps" item.
         }
         mController.apply();
     }
diff --git a/src/com/android/settings/media/MediaOutputIndicatorSlice.java b/src/com/android/settings/media/MediaOutputIndicatorSlice.java
new file mode 100644
index 0000000..eb0c81f
--- /dev/null
+++ b/src/com/android/settings/media/MediaOutputIndicatorSlice.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.media;
+
+import static com.android.settings.slices.CustomSliceRegistry.MEDIA_OUTPUT_INDICATOR_SLICE_URI;
+
+import android.annotation.ColorInt;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.core.graphics.drawable.IconCompat;
+import androidx.slice.Slice;
+import androidx.slice.builders.ListBuilder;
+import androidx.slice.builders.SliceAction;
+
+import com.android.settings.R;
+import com.android.settings.Utils;
+import com.android.settings.slices.CustomSliceable;
+import com.android.settings.slices.SliceBackgroundWorker;
+import com.android.settingslib.media.MediaOutputSliceConstants;
+
+public class MediaOutputIndicatorSlice implements CustomSliceable {
+
+    private Context mContext;
+    @VisibleForTesting
+    MediaOutputIndicatorWorker mWorker;
+
+    public MediaOutputIndicatorSlice(Context context) {
+        mContext = context;
+    }
+
+    @Override
+    public Slice getSlice() {
+        if (!getWorker().isVisible()) {
+            return null;
+        }
+        final IconCompat icon = IconCompat.createWithResource(mContext,
+                com.android.internal.R.drawable.ic_settings_bluetooth);
+        final CharSequence title = mContext.getText(R.string.media_output_title);
+        final PendingIntent primaryActionIntent = PendingIntent.getActivity(mContext,
+                0 /* requestCode */, getMediaOutputSliceIntent(), 0 /* flags */);
+        final SliceAction primarySliceAction = SliceAction.createDeeplink(
+                primaryActionIntent, icon, ListBuilder.ICON_IMAGE, title);
+        @ColorInt final int color = Utils.getColorAccentDefaultColor(mContext);
+
+        final ListBuilder listBuilder = new ListBuilder(mContext,
+                MEDIA_OUTPUT_INDICATOR_SLICE_URI,
+                ListBuilder.INFINITY)
+                .setAccentColor(color)
+                .addRow(new ListBuilder.RowBuilder()
+                        .setTitle(title)
+                        .setSubtitle(getWorker().findActiveDeviceName())
+                        .setPrimaryAction(primarySliceAction));
+        return listBuilder.build();
+    }
+
+    private MediaOutputIndicatorWorker getWorker() {
+        if (mWorker == null) {
+            mWorker = (MediaOutputIndicatorWorker) SliceBackgroundWorker.getInstance(getUri());
+        }
+        return mWorker;
+    }
+
+    private Intent getMediaOutputSliceIntent() {
+        final Intent intent = new Intent()
+                .setAction(MediaOutputSliceConstants.ACTION_MEDIA_OUTPUT)
+                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+        return intent;
+    }
+
+    @Override
+    public Uri getUri() {
+        return MEDIA_OUTPUT_INDICATOR_SLICE_URI;
+    }
+
+    @Override
+    public Intent getIntent() {
+        // This Slice reflects active media device information and launch MediaOutputSlice. It does
+        // not contain its owned Slice data
+        return null;
+    }
+
+    @Override
+    public Class getBackgroundWorkerClass() {
+        return MediaOutputIndicatorWorker.class;
+    }
+}
diff --git a/src/com/android/settings/media/MediaOutputIndicatorWorker.java b/src/com/android/settings/media/MediaOutputIndicatorWorker.java
new file mode 100644
index 0000000..adee055
--- /dev/null
+++ b/src/com/android/settings/media/MediaOutputIndicatorWorker.java
@@ -0,0 +1,161 @@
+/*
+ * 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.media;
+
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+import android.net.Uri;
+import android.util.Log;
+
+import com.android.internal.util.CollectionUtils;
+import com.android.settings.R;
+import com.android.settings.bluetooth.Utils;
+import com.android.settings.slices.SliceBackgroundWorker;
+import com.android.settingslib.bluetooth.A2dpProfile;
+import com.android.settingslib.bluetooth.BluetoothCallback;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.bluetooth.HearingAidProfile;
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Listener for background change from {@code BluetoothCallback} to update media output indicator.
+ */
+public class MediaOutputIndicatorWorker extends SliceBackgroundWorker implements BluetoothCallback {
+
+    private static final String TAG = "MediaOutputIndicatorWorker";
+
+    private LocalBluetoothManager mLocalBluetoothManager;
+    private LocalBluetoothProfileManager mProfileManager;
+
+    public MediaOutputIndicatorWorker(Context context, Uri uri) {
+        super(context, uri);
+    }
+
+    @Override
+    protected void onSlicePinned() {
+        LocalBluetoothManager mLocalBluetoothManager = Utils.getLocalBtManager(getContext());
+        if (mLocalBluetoothManager == null) {
+            Log.e(TAG, "Bluetooth is not supported on this device");
+            return;
+        }
+        mProfileManager = mLocalBluetoothManager.getProfileManager();
+        mLocalBluetoothManager.getEventManager().registerCallback(this);
+    }
+
+    @Override
+    protected void onSliceUnpinned() {
+        if (mLocalBluetoothManager == null) {
+            Log.e(TAG, "Bluetooth is not supported on this device");
+            return;
+        }
+        mLocalBluetoothManager.getEventManager().unregisterCallback(this);
+    }
+
+    @Override
+    public void close() throws IOException {
+        mLocalBluetoothManager = null;
+        mProfileManager = null;
+    }
+
+    @Override
+    public void onBluetoothStateChanged(int bluetoothState) {
+        // To handle the case that Bluetooth on and no connected devices
+        notifySliceChange();
+    }
+
+    @Override
+    public void onActiveDeviceChanged(CachedBluetoothDevice activeDevice, int bluetoothProfile) {
+        if (bluetoothProfile == BluetoothProfile.A2DP) {
+            notifySliceChange();
+        }
+    }
+
+    /**
+     * To decide Slice's visibility.
+     *
+     * @return true if device is connected or previously connected, false for other cases.
+     */
+    public boolean isVisible() {
+        return !CollectionUtils.isEmpty(getConnectableA2dpDevices())
+                || !CollectionUtils.isEmpty(getConnectableHearingAidDevices());
+    }
+
+    private List<BluetoothDevice> getConnectableA2dpDevices() {
+        // get A2dp devices on all states
+        // (STATE_DISCONNECTED, STATE_CONNECTING, STATE_CONNECTED,  STATE_DISCONNECTING)
+        final A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile();
+        if (a2dpProfile == null) {
+            return new ArrayList<>();
+        }
+        return a2dpProfile.getConnectableDevices();
+    }
+
+    private List<BluetoothDevice> getConnectableHearingAidDevices() {
+        // get hearing aid profile devices on all states
+        // (STATE_DISCONNECTED, STATE_CONNECTING, STATE_CONNECTED,  STATE_DISCONNECTING)
+        final HearingAidProfile hapProfile = mProfileManager.getHearingAidProfile();
+        if (hapProfile == null) {
+            return new ArrayList<>();
+        }
+
+        return hapProfile.getConnectableDevices();
+    }
+
+    /**
+     * Get active devices name.
+     *
+     * @return active Bluetooth device alias, or default summary if no active device.
+     */
+    public CharSequence findActiveDeviceName() {
+        // Return Hearing Aid device name if it is active
+        BluetoothDevice activeDevice = findActiveHearingAidDevice();
+        if (activeDevice != null) {
+            return activeDevice.getAliasName();
+        }
+        // Return A2DP device name if it is active
+        final A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile();
+        if (a2dpProfile != null) {
+            activeDevice = a2dpProfile.getActiveDevice();
+            if (activeDevice != null) {
+                return activeDevice.getAliasName();
+            }
+        }
+        // No active device, return default summary
+        return getContext().getText(R.string.media_output_default_summary);
+    }
+
+    private BluetoothDevice findActiveHearingAidDevice() {
+        final HearingAidProfile hearingAidProfile = mProfileManager.getHearingAidProfile();
+        if (hearingAidProfile == null) {
+            return null;
+        }
+
+        final List<BluetoothDevice> activeDevices = hearingAidProfile.getActiveDevices();
+        for (BluetoothDevice btDevice : activeDevices) {
+            if (btDevice != null) {
+                return btDevice;
+            }
+        }
+        return null;
+    }
+}
diff --git a/src/com/android/settings/media/MediaOutputSlice.java b/src/com/android/settings/media/MediaOutputSlice.java
index 232986c..e76bc88 100644
--- a/src/com/android/settings/media/MediaOutputSlice.java
+++ b/src/com/android/settings/media/MediaOutputSlice.java
@@ -76,6 +76,11 @@
             return null;
         }
 
+        if (getWorker() == null) {
+            Log.d(TAG, "getSlice() Can not get worker through uri!");
+            return null;
+        }
+
         final List<MediaDevice> devices = getMediaDevices();
         @ColorInt final int color = Utils.getColorAccentDefaultColor(mContext);
 
@@ -115,13 +120,15 @@
     private MediaDeviceUpdateWorker getWorker() {
         if (mWorker == null) {
             mWorker = (MediaDeviceUpdateWorker) SliceBackgroundWorker.getInstance(getUri());
-            mWorker.setPackageName(mPackageName);
+            if (mWorker != null) {
+                mWorker.setPackageName(mPackageName);
+            }
         }
         return mWorker;
     }
 
     private List<MediaDevice> getMediaDevices() {
-        List<MediaDevice> devices = getWorker().getMediaDevices();
+        final List<MediaDevice> devices = getWorker().getMediaDevices();
         return devices;
     }
 
diff --git a/src/com/android/settings/network/MobileNetworkListController.java b/src/com/android/settings/network/MobileNetworkListController.java
index 7de6cdd..79715e3 100644
--- a/src/com/android/settings/network/MobileNetworkListController.java
+++ b/src/com/android/settings/network/MobileNetworkListController.java
@@ -24,14 +24,10 @@
 import android.provider.Settings;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
+import android.telephony.euicc.EuiccManager;
 import android.util.ArrayMap;
 
-import androidx.lifecycle.Lifecycle;
-import androidx.lifecycle.LifecycleObserver;
-import androidx.lifecycle.OnLifecycleEvent;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
-
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.settings.R;
 import com.android.settings.network.telephony.MobileNetworkActivity;
 import com.android.settingslib.core.AbstractPreferenceController;
@@ -39,6 +35,12 @@
 import java.util.List;
 import java.util.Map;
 
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.LifecycleObserver;
+import androidx.lifecycle.OnLifecycleEvent;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
 /**
  * This populates the entries on a page which lists all available mobile subscriptions. Each entry
  * has the name of the subscription with some subtext giving additional detail, and clicking on the
@@ -48,6 +50,9 @@
         LifecycleObserver, SubscriptionsChangeListener.SubscriptionsChangeListenerClient {
     private static final String TAG = "MobileNetworkListCtlr";
 
+    @VisibleForTesting
+    static final String KEY_ADD_MORE = "add_more";
+
     private SubscriptionManager mSubscriptionManager;
     private SubscriptionsChangeListener mChangeListener;
     private PreferenceScreen mPreferenceScreen;
@@ -76,6 +81,8 @@
     public void displayPreference(PreferenceScreen screen) {
         super.displayPreference(screen);
         mPreferenceScreen = screen;
+        final EuiccManager euiccManager = mContext.getSystemService(EuiccManager.class);
+        mPreferenceScreen.findPreference(KEY_ADD_MORE).setVisible(euiccManager.isEnabled());
         update();
     }
 
@@ -93,7 +100,7 @@
         final List<SubscriptionInfo> subscriptions = SubscriptionUtil.getAvailableSubscriptions(
                 mSubscriptionManager);
         for (SubscriptionInfo info : subscriptions) {
-            int subId = info.getSubscriptionId();
+            final int subId = info.getSubscriptionId();
             Preference pref = existingPreferences.remove(subId);
             if (pref == null) {
                 pref = new Preference(mPreferenceScreen.getContext());
diff --git a/src/com/android/settings/network/MobileNetworkSummaryController.java b/src/com/android/settings/network/MobileNetworkSummaryController.java
index a1fef4c..56735ab 100644
--- a/src/com/android/settings/network/MobileNetworkSummaryController.java
+++ b/src/com/android/settings/network/MobileNetworkSummaryController.java
@@ -16,8 +16,6 @@
 
 package com.android.settings.network;
 
-import static android.telephony.TelephonyManager.MultiSimVariants.UNKNOWN;
-
 import static androidx.lifecycle.Lifecycle.Event.ON_PAUSE;
 import static androidx.lifecycle.Lifecycle.Event.ON_RESUME;
 
@@ -25,7 +23,6 @@
 import android.content.Intent;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyManager;
 import android.telephony.euicc.EuiccManager;
 
 import com.android.settings.R;
@@ -52,7 +49,6 @@
 
     private SubscriptionManager mSubscriptionManager;
     private SubscriptionsChangeListener mChangeListener;
-    private TelephonyManager mTelephonyMgr;
     private EuiccManager mEuiccManager;
     private AddPreference mPreference;
 
@@ -74,7 +70,6 @@
     public MobileNetworkSummaryController(Context context, Lifecycle lifecycle) {
         super(context);
         mSubscriptionManager = context.getSystemService(SubscriptionManager.class);
-        mTelephonyMgr = mContext.getSystemService(TelephonyManager.class);
         mEuiccManager = mContext.getSystemService(EuiccManager.class);
         if (lifecycle != null) {
           mChangeListener = new SubscriptionsChangeListener(context, this);
@@ -124,48 +119,43 @@
         mContext.startActivity(intent);
     }
 
-    private boolean shouldShowAddButton() {
-        // The add button should only show up if the device is in multi-sim mode and the eSIM
-        // manager is enabled.
-        return mTelephonyMgr.getMultiSimConfiguration() != UNKNOWN && mEuiccManager.isEnabled();
-    }
-
     private void update() {
         if (mPreference == null) {
             return;
         }
-        final boolean showAddButton = shouldShowAddButton();
         refreshSummary(mPreference);
-        if (!showAddButton) {
-            mPreference.setOnAddClickListener(null);
-        } else {
-            mPreference.setAddWidgetEnabled(!mChangeListener.isAirplaneModeOn());
-            mPreference.setOnAddClickListener(p -> {
-                startAddSimFlow();
-            });
-        }
-        final List<SubscriptionInfo> subs = SubscriptionUtil.getAvailableSubscriptions(
-                mSubscriptionManager);
         mPreference.setOnPreferenceClickListener(null);
+        mPreference.setOnAddClickListener(null);
         mPreference.setFragment(null);
         mPreference.setEnabled(!mChangeListener.isAirplaneModeOn());
+
+        final List<SubscriptionInfo> subs = SubscriptionUtil.getAvailableSubscriptions(
+                mSubscriptionManager);
+
         if (subs.isEmpty()) {
-            if (showAddButton) {
-                mPreference.setEnabled(false);
-            } else if (mEuiccManager.isEnabled()) {
+            if (mEuiccManager.isEnabled()) {
                 mPreference.setOnPreferenceClickListener((Preference pref) -> {
                     startAddSimFlow();
                     return true;
                 });
             }
-        } else if (subs.size() == 1) {
-            mPreference.setOnPreferenceClickListener((Preference pref) -> {
-                final Intent intent = new Intent(mContext, MobileNetworkActivity.class);
-                mContext.startActivity(intent);
-                return true;
-            });
         } else {
-            mPreference.setFragment(MobileNetworkListFragment.class.getCanonicalName());
+            // We have one or more existing subscriptions, so we want the plus button if eSIM is
+            // supported.
+            if (mEuiccManager.isEnabled()) {
+                mPreference.setAddWidgetEnabled(!mChangeListener.isAirplaneModeOn());
+                mPreference.setOnAddClickListener(p -> startAddSimFlow());
+            }
+
+            if (subs.size() == 1) {
+                mPreference.setOnPreferenceClickListener((Preference pref) -> {
+                    final Intent intent = new Intent(mContext, MobileNetworkActivity.class);
+                    mContext.startActivity(intent);
+                    return true;
+                });
+            } else {
+                mPreference.setFragment(MobileNetworkListFragment.class.getCanonicalName());
+            }
         }
     }
 
diff --git a/src/com/android/settings/network/telephony/MobileDataSlice.java b/src/com/android/settings/network/telephony/MobileDataSlice.java
index 6efd8c3..5a5d6a2 100644
--- a/src/com/android/settings/network/telephony/MobileDataSlice.java
+++ b/src/com/android/settings/network/telephony/MobileDataSlice.java
@@ -74,8 +74,27 @@
         final IconCompat icon = IconCompat.createWithResource(mContext,
                 R.drawable.ic_network_cell);
         final String title = mContext.getText(R.string.mobile_data_settings_title).toString();
-        final CharSequence summary = getSummary();
         @ColorInt final int color = Utils.getColorAccentDefaultColor(mContext);
+
+        // Return a Slice without the mobile data toggle when airplane mode is on.
+        if (isAirplaneModeEnabled()) {
+            final CharSequence summary = mContext.getText(R.string.mobile_data_ap_mode_disabled);
+            // Intent does nothing, but we have to pass an intent to the Row.
+            final PendingIntent intent = PendingIntent.getActivity(mContext, 0 /* requestCode */,
+                    new Intent(), 0 /* flags */);
+            final SliceAction deadAction =
+                    SliceAction.create(intent, icon, ListBuilder.ICON_IMAGE, title);
+            final ListBuilder listBuilder = new ListBuilder(mContext, getUri(),
+                    ListBuilder.INFINITY)
+                    .setAccentColor(color)
+                    .addRow(new ListBuilder.RowBuilder()
+                            .setTitle(title)
+                            .setSubtitle(summary)
+                            .setPrimaryAction(deadAction));
+            return listBuilder.build();
+        }
+
+        final CharSequence summary = getSummary();
         final PendingIntent toggleAction = getBroadcastIntent(mContext);
         final PendingIntent primaryAction = getPrimaryAction();
         final SliceAction primarySliceAction = SliceAction.createDeeplink(primaryAction, icon,
@@ -101,11 +120,6 @@
 
     @Override
     public void onNotifyChange(Intent intent) {
-        // Don't make a change if we are in Airplane Mode.
-        if (isAirplaneModeEnabled()) {
-            return;
-        }
-
         final boolean newState = intent.getBooleanExtra(EXTRA_TOGGLE_STATE,
                     isMobileDataEnabled());
 
diff --git a/src/com/android/settings/network/telephony/NetworkSelectSettings.java b/src/com/android/settings/network/telephony/NetworkSelectSettings.java
index 088bfbf..47db875 100644
--- a/src/com/android/settings/network/telephony/NetworkSelectSettings.java
+++ b/src/com/android/settings/network/telephony/NetworkSelectSettings.java
@@ -27,7 +27,7 @@
 import android.telephony.CarrierConfigManager;
 import android.telephony.CellIdentity;
 import android.telephony.CellInfo;
-import android.telephony.NetworkRegistrationState;
+import android.telephony.NetworkRegistrationInfo;
 import android.telephony.ServiceState;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
@@ -304,7 +304,7 @@
      * Config the connected network operator preference when the page was created. When user get
      * into this page, the device might or might not have data connection.
      * - If the device has data:
-     * 1. use {@code ServiceState#getNetworkRegistrationStates()} to get the currently
+     * 1. use {@code ServiceState#getNetworkRegistrationInfoList()} to get the currently
      * registered cellIdentity, wrap it into a CellInfo;
      * 2. set the signal strength level as strong;
      * 3. use {@link TelephonyManager#getNetworkOperatorName()} to get the title of the
@@ -317,8 +317,9 @@
         if (mTelephonyManager.getDataState() == mTelephonyManager.DATA_CONNECTED) {
             // Try to get the network registration states
             ServiceState ss = mTelephonyManager.getServiceState();
-            List<NetworkRegistrationState> networkList =
-                    ss.getNetworkRegistrationStates(AccessNetworkConstants.TransportType.WWAN);
+            List<NetworkRegistrationInfo> networkList =
+                    ss.getNetworkRegistrationInfoListForTransportType(
+                            AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
             if (networkList == null || networkList.size() == 0) {
                 // Remove the connected network operators category
                 mConnectedPreferenceCategory.setVisible(false);
diff --git a/src/com/android/settings/notification/AppNotificationSettings.java b/src/com/android/settings/notification/AppNotificationSettings.java
index 9f5ece2..3ccca00 100644
--- a/src/com/android/settings/notification/AppNotificationSettings.java
+++ b/src/com/android/settings/notification/AppNotificationSettings.java
@@ -16,8 +16,6 @@
 
 package com.android.settings.notification;
 
-import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
-
 import android.app.NotificationChannel;
 import android.app.NotificationChannelGroup;
 import android.app.settings.SettingsEnums;
@@ -26,8 +24,6 @@
 import android.os.Bundle;
 import android.text.TextUtils;
 import android.util.Log;
-import android.view.Window;
-import android.view.WindowManager;
 
 import androidx.preference.Preference;
 import androidx.preference.PreferenceCategory;
@@ -88,8 +84,6 @@
     public void onResume() {
         super.onResume();
 
-        getActivity().getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
-
         if (mUid < 0 || TextUtils.isEmpty(mPkg) || mPkgInfo == null) {
             Log.w(TAG, "Missing package or uid or packageinfo");
             finish();
@@ -124,15 +118,6 @@
     }
 
     @Override
-    public void onPause() {
-        super.onPause();
-        final Window window = getActivity().getWindow();
-        final WindowManager.LayoutParams attrs = window.getAttributes();
-        attrs.privateFlags &= ~SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
-        window.setAttributes(attrs);
-    }
-
-    @Override
     protected String getLogTag() {
         return TAG;
     }
@@ -152,6 +137,10 @@
                 context, mImportanceListener, mBackend));
         mControllers.add(new ImportancePreferenceController(
                 context, mImportanceListener, mBackend));
+        mControllers.add(new MinImportancePreferenceController(
+                context, mImportanceListener, mBackend));
+        mControllers.add(new HighImportancePreferenceController(
+                context, mImportanceListener, mBackend));
         mControllers.add(new SoundPreferenceController(context, this,
                 mImportanceListener, mBackend));
         mControllers.add(new LightsPreferenceController(context, mBackend));
diff --git a/src/com/android/settings/notification/BubblePreferenceController.java b/src/com/android/settings/notification/BubblePreferenceController.java
index e61de4b..5b3be44 100644
--- a/src/com/android/settings/notification/BubblePreferenceController.java
+++ b/src/com/android/settings/notification/BubblePreferenceController.java
@@ -30,7 +30,7 @@
         implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener {
 
     private static final String TAG = "BubblePrefContr";
-    private static final String KEY = "bubble";
+    private static final String KEY = "bubble_pref";
     private static final int SYSTEM_WIDE_ON = 1;
     private static final int SYSTEM_WIDE_OFF = 0;
 
diff --git a/src/com/android/settings/notification/ChannelNotificationSettings.java b/src/com/android/settings/notification/ChannelNotificationSettings.java
index f92e529..850fde2 100644
--- a/src/com/android/settings/notification/ChannelNotificationSettings.java
+++ b/src/com/android/settings/notification/ChannelNotificationSettings.java
@@ -94,9 +94,12 @@
     protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
         mControllers = new ArrayList<>();
         mControllers.add(new HeaderPreferenceController(context, this));
-        mControllers.add(new BlockPreferenceController(context, mImportanceListener, mBackend));
         mControllers.add(new ImportancePreferenceController(
                 context, mImportanceListener, mBackend));
+        mControllers.add(new MinImportancePreferenceController(
+                context, mImportanceListener, mBackend));
+        mControllers.add(new HighImportancePreferenceController(
+                context, mImportanceListener, mBackend));
         mControllers.add(new AllowSoundPreferenceController(
                 context, mImportanceListener, mBackend));
         mControllers.add(new SoundPreferenceController(context, this,
diff --git a/src/com/android/settings/notification/HighImportancePreferenceController.java b/src/com/android/settings/notification/HighImportancePreferenceController.java
new file mode 100644
index 0000000..fe843fd
--- /dev/null
+++ b/src/com/android/settings/notification/HighImportancePreferenceController.java
@@ -0,0 +1,84 @@
+/*
+ * 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.NotificationManager.IMPORTANCE_DEFAULT;
+import static android.app.NotificationManager.IMPORTANCE_HIGH;
+
+import android.app.NotificationChannel;
+import android.content.Context;
+
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.RestrictedSwitchPreference;
+
+import androidx.preference.Preference;
+
+public class HighImportancePreferenceController extends NotificationPreferenceController
+        implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener  {
+
+    private static final String KEY_IMPORTANCE = "high_importance";
+    private NotificationSettingsBase.ImportanceListener mImportanceListener;
+
+    public HighImportancePreferenceController(Context context,
+            NotificationSettingsBase.ImportanceListener importanceListener,
+            NotificationBackend backend) {
+        super(context, backend);
+        mImportanceListener = importanceListener;
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return KEY_IMPORTANCE;
+    }
+
+    @Override
+    public boolean isAvailable() {
+        if (!super.isAvailable()) {
+            return false;
+        }
+        if (mChannel == null) {
+            return false;
+        }
+        if (isDefaultChannel()) {
+           return false;
+        }
+        return mChannel.getImportance() >= IMPORTANCE_DEFAULT;
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        if (mAppRow!= null && mChannel != null) {
+            preference.setEnabled(mAdmin == null && isChannelConfigurable());
+
+            RestrictedSwitchPreference pref = (RestrictedSwitchPreference) preference;
+            pref.setChecked(mChannel.getImportance() >= IMPORTANCE_HIGH);
+        }
+    }
+
+    @Override
+    public boolean onPreferenceChange(Preference preference, Object newValue) {
+        if (mChannel != null) {
+            final boolean checked = (boolean) newValue;
+
+            mChannel.setImportance(checked ? IMPORTANCE_HIGH : IMPORTANCE_DEFAULT);
+            mChannel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
+            saveChannel();
+            mImportanceListener.onImportanceChanged();
+        }
+        return true;
+    }
+}
diff --git a/src/com/android/settings/notification/ImportancePreference.java b/src/com/android/settings/notification/ImportancePreference.java
new file mode 100644
index 0000000..b8f3e45
--- /dev/null
+++ b/src/com/android/settings/notification/ImportancePreference.java
@@ -0,0 +1,172 @@
+/*
+ * 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.NotificationManager.IMPORTANCE_DEFAULT;
+import static android.app.NotificationManager.IMPORTANCE_HIGH;
+import static android.app.NotificationManager.IMPORTANCE_LOW;
+import static android.app.NotificationManager.IMPORTANCE_MIN;
+import static android.app.NotificationManager.IMPORTANCE_NONE;
+
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.GradientDrawable;
+import android.graphics.drawable.LayerDrawable;
+import android.util.ArrayMap;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.ImageButton;
+
+import com.android.settingslib.R;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceViewHolder;
+
+public class ImportancePreference extends Preference {
+
+    boolean mIsBlockable = true;
+    boolean mIsConfigurable = true;
+    int mImportance;
+    ImageButton blockButton;
+    ImageButton silenceButton;
+    ImageButton alertButton;
+    ArrayMap<ImageButton, Integer> mImageButtons = new ArrayMap<>();
+    Context mContext;
+
+    public ImportancePreference(Context context, AttributeSet attrs,
+            int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+        init(context);
+    }
+
+    public ImportancePreference(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        init(context);
+    }
+
+    public ImportancePreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init(context);
+    }
+
+    public ImportancePreference(Context context) {
+        super(context);
+        init(context);
+    }
+
+    private void init(Context context) {
+        mContext = context;
+        setLayoutResource(R.layout.notif_importance_preference);
+    }
+
+    public void setImportance(int importance) {
+        mImportance = importance;
+    }
+
+    public void setBlockable(boolean blockable) {
+        mIsBlockable = blockable;
+    }
+
+    public void setConfigurable(boolean configurable) {
+        mIsConfigurable = configurable;
+    }
+
+    @Override
+    public void onBindViewHolder(PreferenceViewHolder holder) {
+        super.onBindViewHolder(holder);
+
+        View blockView = holder.itemView.findViewById(R.id.block);
+        View alertView = holder.itemView.findViewById(R.id.alert);
+        View silenceView = holder.itemView.findViewById(R.id.silence);
+        if (!mIsBlockable) {
+            blockView.setVisibility(View.GONE);
+            if (mImportance == IMPORTANCE_NONE) {
+                mImportance = IMPORTANCE_LOW;
+                callChangeListener(IMPORTANCE_LOW);
+            }
+
+        }
+        blockButton = blockView.findViewById(R.id.block_icon);
+        silenceButton = silenceView.findViewById(R.id.silence_icon);
+        alertButton = alertView.findViewById(R.id.alert_icon);
+        mImageButtons.put(blockButton, mContext.getColor(R.color.notification_block_color));
+        mImageButtons.put(silenceButton, mContext.getColor(R.color.notification_silence_color));
+        mImageButtons.put(alertButton, mContext.getColor(R.color.notification_alert_color));
+
+        switch (mImportance) {
+            case IMPORTANCE_NONE:
+                colorizeImageButton(blockButton.getId());
+                if (!mIsConfigurable) {
+                    alertView.setVisibility(View.GONE);
+                    silenceView.setVisibility(View.GONE);
+                }
+                break;
+            case IMPORTANCE_MIN:
+            case IMPORTANCE_LOW:
+                colorizeImageButton(silenceButton.getId());
+                if (!mIsConfigurable) {
+                    alertView.setVisibility(View.GONE);
+                    blockView.setVisibility(View.GONE);
+                }
+                break;
+            case IMPORTANCE_HIGH:
+            default:
+                colorizeImageButton(alertButton.getId());
+                if (!mIsConfigurable) {
+                    blockView.setVisibility(View.GONE);
+                    silenceView.setVisibility(View.GONE);
+                }
+                break;
+        }
+
+        blockButton.setOnClickListener(v -> {
+            callChangeListener(IMPORTANCE_NONE);
+            colorizeImageButton(blockButton.getId());
+        });
+        silenceButton.setOnClickListener(v -> {
+            callChangeListener(IMPORTANCE_LOW);
+            colorizeImageButton(silenceButton.getId());
+        });
+        alertButton.setOnClickListener(v -> {
+            callChangeListener(IMPORTANCE_DEFAULT);
+            colorizeImageButton(alertButton.getId());
+        });
+    }
+
+    private void colorizeImageButton(int buttonId) {
+        if (mImageButtons != null) {
+            for (int i = 0; i < mImageButtons.size(); i++) {
+                final ImageButton imageButton = mImageButtons.keyAt(i);
+                final int color = mImageButtons.valueAt(i);
+                if (imageButton != null) {
+                    LayerDrawable drawable = (LayerDrawable) imageButton.getDrawable();
+                    Drawable foreground = drawable.findDrawableByLayerId(R.id.fore);
+                    GradientDrawable background =
+                            (GradientDrawable) drawable.findDrawableByLayerId(R.id.back);
+                    if (buttonId == imageButton.getId()) {
+                        foreground.setTint(Color.WHITE);
+                        background.setColor(color);
+                    } else {
+                        foreground.setTint(color);
+                        background.setColor(Color.TRANSPARENT);
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/src/com/android/settings/notification/ImportancePreferenceController.java b/src/com/android/settings/notification/ImportancePreferenceController.java
index 4c20a46..0955571 100644
--- a/src/com/android/settings/notification/ImportancePreferenceController.java
+++ b/src/com/android/settings/notification/ImportancePreferenceController.java
@@ -18,21 +18,15 @@
 
 import static android.app.NotificationChannel.USER_LOCKED_SOUND;
 import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
-import static android.app.NotificationManager.IMPORTANCE_HIGH;
-import static android.app.NotificationManager.IMPORTANCE_MIN;
-import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
 
 import android.app.NotificationChannel;
-import android.app.NotificationManager;
 import android.content.Context;
 import android.media.RingtoneManager;
 
-import androidx.preference.Preference;
-
-import com.android.settings.R;
-import com.android.settings.RestrictedListPreference;
 import com.android.settings.core.PreferenceControllerMixin;
 
+import androidx.preference.Preference;
+
 public class ImportancePreferenceController extends NotificationPreferenceController
         implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener  {
 
@@ -53,44 +47,33 @@
 
     @Override
     public boolean isAvailable() {
-        if (!super.isAvailable()) {
+        if (mAppRow == null) {
             return false;
         }
         if (mChannel == null) {
             return false;
         }
-        return !isDefaultChannel();
+        if (isDefaultChannel()) {
+            return false;
+        }
+        return true;
     }
 
     @Override
     public void updateState(Preference preference) {
         if (mAppRow!= null && mChannel != null) {
             preference.setEnabled(mAdmin == null && isChannelConfigurable());
-            preference.setSummary(getImportanceSummary(mChannel));
-
-            int importances = IMPORTANCE_HIGH - IMPORTANCE_MIN + 1;
-            CharSequence[] entries = new CharSequence[importances];
-            CharSequence[] values = new CharSequence[importances];
-
-            int index = 0;
-            for (int i = IMPORTANCE_HIGH; i >= IMPORTANCE_MIN; i--) {
-                NotificationChannel channel = new NotificationChannel("", "", i);
-                entries[index] = getImportanceSummary(channel);
-                values[index] = String.valueOf(i);
-                index++;
-            }
-
-            RestrictedListPreference pref = (RestrictedListPreference) preference;
-            pref.setEntries(entries);
-            pref.setEntryValues(values);
-            pref.setValue(String.valueOf(mChannel.getImportance()));
+            ImportancePreference pref = (ImportancePreference) preference;
+            pref.setBlockable(isChannelBlockable());
+            pref.setConfigurable(isChannelConfigurable());
+            pref.setImportance(mChannel.getImportance());
         }
     }
 
     @Override
     public boolean onPreferenceChange(Preference preference, Object newValue) {
         if (mChannel != null) {
-            final int importance = Integer.parseInt((String) newValue);
+            final int importance = (Integer) newValue;
 
             // If you are moving from an importance level without sound to one with sound,
             // but the sound you had selected was "Silence",
@@ -111,39 +94,4 @@
         }
         return true;
     }
-
-    protected String getImportanceSummary(NotificationChannel channel) {
-        String summary = "";
-        int importance = channel.getImportance();
-        switch (importance) {
-            case IMPORTANCE_UNSPECIFIED:
-                summary = mContext.getString(R.string.notification_importance_unspecified);
-                break;
-            case NotificationManager.IMPORTANCE_MIN:
-                summary = mContext.getString(R.string.notification_importance_min);
-                break;
-            case NotificationManager.IMPORTANCE_LOW:
-                summary = mContext.getString(R.string.notification_importance_low);
-                break;
-            case NotificationManager.IMPORTANCE_DEFAULT:
-                if (SoundPreferenceController.hasValidSound(channel)) {
-                    summary = mContext.getString(R.string.notification_importance_default);
-                } else {
-                    summary = mContext.getString(R.string.notification_importance_low);
-                }
-                break;
-            case NotificationManager.IMPORTANCE_HIGH:
-            case NotificationManager.IMPORTANCE_MAX:
-                if (SoundPreferenceController.hasValidSound(channel)) {
-                    summary = mContext.getString(R.string.notification_importance_high);
-                } else {
-                    summary = mContext.getString(R.string.notification_importance_high_silent);
-                }
-                break;
-            default:
-                return "";
-        }
-
-        return summary;
-    }
 }
diff --git a/src/com/android/settings/notification/MinImportancePreferenceController.java b/src/com/android/settings/notification/MinImportancePreferenceController.java
new file mode 100644
index 0000000..771ac60
--- /dev/null
+++ b/src/com/android/settings/notification/MinImportancePreferenceController.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import static android.app.NotificationManager.IMPORTANCE_LOW;
+import static android.app.NotificationManager.IMPORTANCE_MIN;
+
+import android.app.NotificationChannel;
+import android.content.Context;
+
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.RestrictedSwitchPreference;
+
+import androidx.preference.Preference;
+
+public class MinImportancePreferenceController extends NotificationPreferenceController
+        implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener  {
+
+    private static final String KEY_IMPORTANCE = "min_importance";
+    private NotificationSettingsBase.ImportanceListener mImportanceListener;
+
+    public MinImportancePreferenceController(Context context,
+            NotificationSettingsBase.ImportanceListener importanceListener,
+            NotificationBackend backend) {
+        super(context, backend);
+        mImportanceListener = importanceListener;
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return KEY_IMPORTANCE;
+    }
+
+    @Override
+    public boolean isAvailable() {
+        if (!super.isAvailable()) {
+            return false;
+        }
+        if (mChannel == null) {
+            return false;
+        }
+        if (isDefaultChannel()) {
+            return false;
+        }
+        return mChannel.getImportance() <= IMPORTANCE_LOW;
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        if (mAppRow!= null && mChannel != null) {
+            preference.setEnabled(mAdmin == null && isChannelConfigurable());
+
+            RestrictedSwitchPreference pref = (RestrictedSwitchPreference) preference;
+            pref.setChecked(mChannel.getImportance() == IMPORTANCE_MIN);
+        }
+    }
+
+    @Override
+    public boolean onPreferenceChange(Preference preference, Object newValue) {
+        if (mChannel != null) {
+            final boolean checked = (boolean) newValue;
+
+            mChannel.setImportance(checked ? IMPORTANCE_MIN : IMPORTANCE_LOW);
+            mChannel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
+            saveChannel();
+            mImportanceListener.onImportanceChanged();
+        }
+        return true;
+    }
+}
diff --git a/src/com/android/settings/notification/NotificationPreferenceController.java b/src/com/android/settings/notification/NotificationPreferenceController.java
index 22f07be..3f535fb 100644
--- a/src/com/android/settings/notification/NotificationPreferenceController.java
+++ b/src/com/android/settings/notification/NotificationPreferenceController.java
@@ -111,6 +111,9 @@
     }
 
     protected boolean isChannelConfigurable() {
+        if (mAppRow != null && mAppRow.lockedImportance) {
+            return false;
+        }
         if (mChannel != null && mAppRow != null) {
             return !Objects.equals(mChannel.getId(), mAppRow.lockedChannelId);
         }
diff --git a/src/com/android/settings/notification/RemoteVolumePreferenceController.java b/src/com/android/settings/notification/RemoteVolumePreferenceController.java
index 0ad307e..37a493e 100644
--- a/src/com/android/settings/notification/RemoteVolumePreferenceController.java
+++ b/src/com/android/settings/notification/RemoteVolumePreferenceController.java
@@ -35,6 +35,7 @@
 
 import java.io.IOException;
 import java.util.List;
+import java.util.Objects;
 
 public class RemoteVolumePreferenceController extends
     VolumeSeekBarPreferenceController {
@@ -58,14 +59,14 @@
             if (mActiveToken == null) {
                 updateToken(token);
             }
-            if (mActiveToken == token) {
+            if (Objects.equals(mActiveToken, token)) {
                 updatePreference(mPreference, mActiveToken, pi);
             }
         }
 
         @Override
         public void onRemoteRemoved(MediaSession.Token t) {
-            if (mActiveToken == t) {
+            if (Objects.equals(mActiveToken, t)) {
                 updateToken(null);
                 if (mPreference != null) {
                     mPreference.setVisible(false);
@@ -75,7 +76,7 @@
 
         @Override
         public void onRemoteVolumeChanged(MediaSession.Token token, int flags) {
-            if (mActiveToken == token) {
+            if (Objects.equals(mActiveToken, token)) {
                 final MediaController.PlaybackInfo pi = mMediaController.getPlaybackInfo();
                 if (pi != null) {
                     setSliderPosition(pi.getCurrentVolume());
@@ -116,13 +117,13 @@
     @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
     public void onResume() {
         super.onResume();
-        //TODO(b/126199571): register callback once b/126890783 is fixed
+        mMediaSessions.init();
     }
 
     @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
     public void onPause() {
         super.onPause();
-        //TODO(b/126199571): unregister callback once b/126890783 is fixed
+        mMediaSessions.destroy();
     }
 
     @Override
@@ -189,8 +190,7 @@
 
     @Override
     public Class<? extends SliceBackgroundWorker> getBackgroundWorkerClass() {
-        //TODO(b/126199571): return RemoteVolumeSliceWorker once b/126890783 is fixed
-        return null;
+        return RemoteVolumeSliceWorker.class;
     }
 
     private void updatePreference(VolumeSeekBarPreference seekBarPreference,
diff --git a/src/com/android/settings/notification/ZenAccessSettings.java b/src/com/android/settings/notification/ZenAccessSettings.java
index d057c75..fca8255 100644
--- a/src/com/android/settings/notification/ZenAccessSettings.java
+++ b/src/com/android/settings/notification/ZenAccessSettings.java
@@ -18,56 +18,40 @@
 
 import android.annotation.Nullable;
 import android.app.ActivityManager;
-import android.app.AppGlobals;
-import android.app.Dialog;
 import android.app.NotificationManager;
 import android.app.settings.SettingsEnums;
 import android.content.Context;
-import android.content.DialogInterface;
 import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageInfo;
 import android.content.pm.PackageItemInfo;
 import android.content.pm.PackageManager;
-import android.content.pm.ParceledListSlice;
-import android.database.ContentObserver;
-import android.net.Uri;
-import android.os.AsyncTask;
 import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.RemoteException;
 import android.provider.SearchIndexableResource;
-import android.provider.Settings.Secure;
-import android.text.TextUtils;
 import android.util.ArraySet;
-import android.util.Log;
 import android.view.View;
 
-import androidx.annotation.VisibleForTesting;
-import androidx.appcompat.app.AlertDialog;
-import androidx.preference.Preference;
-import androidx.preference.Preference.OnPreferenceChangeListener;
 import androidx.preference.PreferenceScreen;
-import androidx.preference.SwitchPreference;
 
 import com.android.settings.R;
-import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
-import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.applications.AppInfoBase;
+import com.android.settings.applications.specialaccess.zenaccess.ZenAccessController;
+import com.android.settings.applications.specialaccess.zenaccess.ZenAccessDetails;
+import com.android.settings.applications.specialaccess.zenaccess.ZenAccessSettingObserverMixin;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.search.Indexable;
-import com.android.settings.widget.AppSwitchPreference;
 import com.android.settings.widget.EmptyTextSettings;
 import com.android.settingslib.search.SearchIndexable;
+import com.android.settingslib.widget.apppreference.AppPreference;
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.Set;
 
 @SearchIndexable
-public class ZenAccessSettings extends EmptyTextSettings {
+public class ZenAccessSettings extends EmptyTextSettings implements
+        ZenAccessSettingObserverMixin.Listener {
     private final String TAG = "ZenAccessSettings";
 
-    private final SettingObserver mObserver = new SettingObserver();
     private Context mContext;
     private PackageManager mPkgMan;
     private NotificationManager mNoMan;
@@ -84,6 +68,8 @@
         mContext = getActivity();
         mPkgMan = mContext.getPackageManager();
         mNoMan = mContext.getSystemService(NotificationManager.class);
+        getSettingsLifecycle().addObserver(
+                new ZenAccessSettingObserverMixin(getContext(), this /* listener */));
     }
 
     @Override
@@ -102,30 +88,22 @@
         super.onResume();
         if (!ActivityManager.isLowRamDeviceStatic()) {
             reloadList();
-            getContentResolver().registerContentObserver(
-                    Secure.getUriFor(Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES), false,
-                    mObserver);
-            getContentResolver().registerContentObserver(
-                    Secure.getUriFor(Secure.ENABLED_NOTIFICATION_LISTENERS), false,
-                    mObserver);
         } else {
             setEmptyText(R.string.disabled_low_ram_device);
         }
     }
 
     @Override
-    public void onPause() {
-        super.onPause();
-        if (!ActivityManager.isLowRamDeviceStatic()) {
-            getContentResolver().unregisterContentObserver(mObserver);
-        }
+    public void onZenAccessPolicyChanged() {
+        reloadList();
     }
 
     private void reloadList() {
         final PreferenceScreen screen = getPreferenceScreen();
         screen.removeAll();
         final ArrayList<ApplicationInfo> apps = new ArrayList<>();
-        final ArraySet<String> requesting = getPackagesRequestingNotificationPolicyAccess();
+        final Set<String> requesting =
+                ZenAccessController.getPackagesRequestingNotificationPolicyAccess();
         if (!requesting.isEmpty()) {
             final List<ApplicationInfo> installed = mPkgMan.getInstalledApplications(0);
             if (installed != null) {
@@ -143,204 +121,42 @@
         for (ApplicationInfo app : apps) {
             final String pkg = app.packageName;
             final CharSequence label = app.loadLabel(mPkgMan);
-            final SwitchPreference pref = new AppSwitchPreference(getPrefContext());
+            final AppPreference pref = new AppPreference(getPrefContext());
             pref.setKey(pkg);
-            pref.setPersistent(false);
             pref.setIcon(app.loadIcon(mPkgMan));
             pref.setTitle(label);
-            pref.setChecked(hasAccess(pkg));
             if (autoApproved.contains(pkg)) {
+                //Auto approved, user cannot do anything. Hard code summary and disable preference.
                 pref.setEnabled(false);
                 pref.setSummary(getString(R.string.zen_access_disabled_package_warning));
+            } else {
+                // Not auto approved, update summary according to notification backend.
+                pref.setSummary(getPreferenceSummary(pkg));
             }
-            pref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
-                @Override
-                public boolean onPreferenceChange(Preference preference, Object newValue) {
-                    final boolean access = (Boolean) newValue;
-                    if (access) {
-                        new ScaryWarningDialogFragment()
-                                .setPkgInfo(pkg, label)
-                                .show(getFragmentManager(), "dialog");
-                    } else {
-                        new FriendlyWarningDialogFragment()
-                                .setPkgInfo(pkg, label)
-                                .show(getFragmentManager(), "dialog");
-                    }
-                    return false;
-                }
+            pref.setOnPreferenceClickListener(preference -> {
+                AppInfoBase.startAppInfoFragment(
+                        ZenAccessDetails.class  /* fragment */,
+                        R.string.manage_zen_access_title /* titleRes */,
+                        pkg,
+                        app.uid,
+                        this /* source */,
+                        -1 /* requestCode */,
+                        getMetricsCategory() /* sourceMetricsCategory */);
+                return true;
             });
+
             screen.addPreference(pref);
         }
     }
 
-    private ArraySet<String> getPackagesRequestingNotificationPolicyAccess() {
-        ArraySet<String> requestingPackages = new ArraySet<>();
-        try {
-            final String[] PERM = {
-                    android.Manifest.permission.ACCESS_NOTIFICATION_POLICY
-            };
-            final ParceledListSlice list = AppGlobals.getPackageManager()
-                    .getPackagesHoldingPermissions(PERM, 0 /*flags*/,
-                            ActivityManager.getCurrentUser());
-            final List<PackageInfo> pkgs = list.getList();
-            if (pkgs != null) {
-                for (PackageInfo info : pkgs) {
-                    requestingPackages.add(info.packageName);
-                }
-            }
-        } catch(RemoteException e) {
-            Log.e(TAG, "Cannot reach packagemanager", e);
-        }
-        return requestingPackages;
-    }
-
-    private boolean hasAccess(String pkg) {
-        return mNoMan.isNotificationPolicyAccessGrantedForPackage(pkg);
-    }
-
-    private static void setAccess(final Context context, final String pkg, final boolean access) {
-        logSpecialPermissionChange(access, pkg, context);
-        AsyncTask.execute(new Runnable() {
-            @Override
-            public void run() {
-                final NotificationManager mgr = context.getSystemService(NotificationManager.class);
-                mgr.setNotificationPolicyAccessGranted(pkg, access);
-            }
-        });
-    }
-
-    @VisibleForTesting
-    static void logSpecialPermissionChange(boolean enable, String packageName, Context context) {
-        int logCategory = enable ? SettingsEnums.APP_SPECIAL_PERMISSION_DND_ALLOW
-                : SettingsEnums.APP_SPECIAL_PERMISSION_DND_DENY;
-        FeatureFactory.getFactory(context).getMetricsFeatureProvider().action(context,
-                logCategory, packageName);
-    }
-
-
-    private static void deleteRules(final Context context, final String pkg) {
-        AsyncTask.execute(new Runnable() {
-            @Override
-            public void run() {
-                final NotificationManager mgr = context.getSystemService(NotificationManager.class);
-                mgr.removeAutomaticZenRules(pkg);
-            }
-        });
-    }
-
-    private final class SettingObserver extends ContentObserver {
-        public SettingObserver() {
-            super(new Handler(Looper.getMainLooper()));
-        }
-
-        @Override
-        public void onChange(boolean selfChange, Uri uri) {
-            reloadList();
-        }
-    }
-
     /**
-     * Warning dialog when allowing zen access warning about the privileges being granted.
+     * @return the summary for the current state of whether the app associated with the given
+     * {@param packageName} is allowed to enter picture-in-picture.
      */
-    public static class ScaryWarningDialogFragment extends InstrumentedDialogFragment {
-        static final String KEY_PKG = "p";
-        static final String KEY_LABEL = "l";
-
-        @Override
-        public int getMetricsCategory() {
-            return SettingsEnums.DIALOG_ZEN_ACCESS_GRANT;
-        }
-
-        public ScaryWarningDialogFragment setPkgInfo(String pkg, CharSequence label) {
-            Bundle args = new Bundle();
-            args.putString(KEY_PKG, pkg);
-            args.putString(KEY_LABEL, TextUtils.isEmpty(label) ? pkg : label.toString());
-            setArguments(args);
-            return this;
-        }
-
-        @Override
-        public Dialog onCreateDialog(Bundle savedInstanceState) {
-            super.onCreate(savedInstanceState);
-            final Bundle args = getArguments();
-            final String pkg = args.getString(KEY_PKG);
-            final String label = args.getString(KEY_LABEL);
-
-            final String title = getResources().getString(R.string.zen_access_warning_dialog_title,
-                    label);
-            final String summary = getResources()
-                    .getString(R.string.zen_access_warning_dialog_summary);
-            return new AlertDialog.Builder(getContext())
-                    .setMessage(summary)
-                    .setTitle(title)
-                    .setCancelable(true)
-                    .setPositiveButton(R.string.allow,
-                            new DialogInterface.OnClickListener() {
-                                public void onClick(DialogInterface dialog, int id) {
-                                    setAccess(getContext(), pkg, true);
-                                }
-                            })
-                    .setNegativeButton(R.string.deny,
-                            new DialogInterface.OnClickListener() {
-                                public void onClick(DialogInterface dialog, int id) {
-                                    // pass
-                                }
-                            })
-                    .create();
-        }
-    }
-
-    /**
-     * Warning dialog when revoking zen access warning that zen rule instances will be deleted.
-     */
-    public static class FriendlyWarningDialogFragment extends InstrumentedDialogFragment {
-        static final String KEY_PKG = "p";
-        static final String KEY_LABEL = "l";
-
-
-        @Override
-        public int getMetricsCategory() {
-            return SettingsEnums.DIALOG_ZEN_ACCESS_REVOKE;
-        }
-
-        public FriendlyWarningDialogFragment setPkgInfo(String pkg, CharSequence label) {
-            Bundle args = new Bundle();
-            args.putString(KEY_PKG, pkg);
-            args.putString(KEY_LABEL, TextUtils.isEmpty(label) ? pkg : label.toString());
-            setArguments(args);
-            return this;
-        }
-
-        @Override
-        public Dialog onCreateDialog(Bundle savedInstanceState) {
-            super.onCreate(savedInstanceState);
-            final Bundle args = getArguments();
-            final String pkg = args.getString(KEY_PKG);
-            final String label = args.getString(KEY_LABEL);
-
-            final String title = getResources().getString(
-                    R.string.zen_access_revoke_warning_dialog_title, label);
-            final String summary = getResources()
-                    .getString(R.string.zen_access_revoke_warning_dialog_summary);
-            return new AlertDialog.Builder(getContext())
-                    .setMessage(summary)
-                    .setTitle(title)
-                    .setCancelable(true)
-                    .setPositiveButton(R.string.okay,
-                            new DialogInterface.OnClickListener() {
-                                public void onClick(DialogInterface dialog, int id) {
-                                    deleteRules(getContext(), pkg);
-                                    setAccess(getContext(), pkg, false);
-                                }
-                            })
-                    .setNegativeButton(R.string.cancel,
-                            new DialogInterface.OnClickListener() {
-                                public void onClick(DialogInterface dialog, int id) {
-                                    // pass
-                                }
-                            })
-                    .create();
-        }
+    private int getPreferenceSummary(String packageName) {
+        final boolean enabled = ZenAccessController.hasAccess(getContext(), packageName);
+        return enabled ? R.string.app_permission_summary_allowed
+                : R.string.app_permission_summary_not_allowed;
     }
 
     public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
diff --git a/src/com/android/settings/notification/ZenRulePreference.java b/src/com/android/settings/notification/ZenRulePreference.java
index 613eb1d..8bc602a 100644
--- a/src/com/android/settings/notification/ZenRulePreference.java
+++ b/src/com/android/settings/notification/ZenRulePreference.java
@@ -171,6 +171,9 @@
                 getSettingsActivity(rule, si);
         mIntent = AbstractZenModeAutomaticRulePreferenceController.getRuleIntent(action,
                 settingsActivity, mId);
+        if (mIntent.resolveActivity(mPm) == null) {
+            mIntent = null;
+        }
         setKey(mId);
     }
 
diff --git a/src/com/android/settings/overlay/FeatureFactory.java b/src/com/android/settings/overlay/FeatureFactory.java
index 23136a4..d9af345 100644
--- a/src/com/android/settings/overlay/FeatureFactory.java
+++ b/src/com/android/settings/overlay/FeatureFactory.java
@@ -20,6 +20,8 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import androidx.annotation.Nullable;
+
 import com.android.settings.R;
 import com.android.settings.accounts.AccountFeatureProvider;
 import com.android.settings.applications.ApplicationFeatureProvider;
@@ -50,6 +52,7 @@
     private static final boolean DEBUG = false;
 
     protected static FeatureFactory sFactory;
+    protected static Context sAppContext;
 
     /**
      * Returns a factory for creating feature controllers. Creates the factory if it does not
@@ -60,6 +63,9 @@
         if (sFactory != null) {
             return sFactory;
         }
+        if (sAppContext == null) {
+            sAppContext = context.getApplicationContext();
+        }
 
         if (DEBUG) Log.d(LOG_TAG, "getFactory");
         final String clsName = context.getString(R.string.config_featureFactory);
@@ -76,6 +82,16 @@
         return sFactory;
     }
 
+    /**
+     * Returns an application {@link Context} used to create this {@link FeatureFactory}. If the
+     * factory has not been properly created yet (aka {@link #getFactory} has not been called), this
+     * will return null.
+     */
+    @Nullable
+    public static Context getAppContext() {
+        return sAppContext;
+    }
+
     public abstract AssistGestureFeatureProvider getAssistGestureFeatureProvider();
 
     public abstract SuggestionFeatureProvider getSuggestionFeatureProvider(Context context);
diff --git a/src/com/android/settings/panel/PanelSlicesAdapter.java b/src/com/android/settings/panel/PanelSlicesAdapter.java
index c1cb049..47ff631 100644
--- a/src/com/android/settings/panel/PanelSlicesAdapter.java
+++ b/src/com/android/settings/panel/PanelSlicesAdapter.java
@@ -94,6 +94,7 @@
             super(view);
             sliceView = view.findViewById(R.id.slice_view);
             sliceView.setMode(SliceView.MODE_LARGE);
+            sliceView.showTitleItems(true);
             mPanelContent = panelContent;
         }
 
diff --git a/src/com/android/settings/panel/VolumePanel.java b/src/com/android/settings/panel/VolumePanel.java
index 62eca53..4ea7fe7 100644
--- a/src/com/android/settings/panel/VolumePanel.java
+++ b/src/com/android/settings/panel/VolumePanel.java
@@ -16,6 +16,7 @@
 
 package com.android.settings.panel;
 
+import static com.android.settings.slices.CustomSliceRegistry.MEDIA_OUTPUT_INDICATOR_SLICE_URI;
 import static com.android.settings.slices.CustomSliceRegistry.VOLUME_ALARM_URI;
 import static com.android.settings.slices.CustomSliceRegistry.VOLUME_CALL_URI;
 import static com.android.settings.slices.CustomSliceRegistry.VOLUME_MEDIA_URI;
@@ -55,6 +56,7 @@
         final List<Uri> uris = new ArrayList<>();
         uris.add(VOLUME_REMOTE_MEDIA_URI);
         uris.add(VOLUME_MEDIA_URI);
+        uris.add(MEDIA_OUTPUT_INDICATOR_SLICE_URI);
         uris.add(VOLUME_CALL_URI);
         uris.add(VOLUME_RINGER_URI);
         uris.add(VOLUME_ALARM_URI);
diff --git a/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java b/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
index ec1e835..d3d5c49 100644
--- a/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
+++ b/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
@@ -198,7 +198,7 @@
         } else if (isManagedProfile && isInternalActivity()
                 && !lockPatternUtils.isSeparateProfileChallengeEnabled(mUserId)) {
             mCredentialMode = CREDENTIAL_MANAGED;
-            if (isBiometricAllowed(effectiveUserId)) {
+            if (isBiometricAllowed(effectiveUserId, mUserId)) {
                 showBiometricPrompt(bpBundle);
                 launchedBiometric = true;
             } else {
@@ -207,7 +207,7 @@
             }
         } else {
             mCredentialMode = CREDENTIAL_NORMAL;
-            if (isBiometricAllowed(effectiveUserId)) {
+            if (isBiometricAllowed(effectiveUserId, mUserId)) {
                 // Don't need to check if biometrics / pin/pattern/pass are enrolled. It will go to
                 // onAuthenticationError and do the right thing automatically.
                 showBiometricPrompt(bpBundle);
@@ -273,9 +273,10 @@
         return (disabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_BIOMETRICS) != 0;
     }
 
-    private boolean isBiometricAllowed(int effectiveUserId) {
+    private boolean isBiometricAllowed(int effectiveUserId, int realUserId) {
         return !isStrongAuthRequired(effectiveUserId)
-                && !isBiometricDisabledByAdmin(effectiveUserId);
+                && !isBiometricDisabledByAdmin(effectiveUserId)
+                && !mLockPatternUtils.hasPendingEscrowToken(realUserId);
     }
 
     private void showBiometricPrompt(Bundle bundle) {
@@ -304,9 +305,18 @@
     private void showConfirmCredentials() {
         mCCLaunched = true;
         boolean launched = false;
+        // The only difference between CREDENTIAL_MANAGED and CREDENTIAL_NORMAL is that for
+        // CREDENTIAL_MANAGED, we launch the real confirm credential activity with an explicit
+        // but dummy challenge value (0L). This will result in ConfirmLockPassword calling
+        // verifyTiedProfileChallenge() (if it's a profile with unified challenge), due to the
+        // difference between ConfirmLockPassword.startVerifyPassword() and
+        // ConfirmLockPassword.startCheckPassword(). Calling verifyTiedProfileChallenge() here is
+        // necessary when this is part of the turning on work profile flow, because it forces
+        // unlocking the work profile even before the profile is running.
+        // TODO: Remove the duplication of checkPassword and verifyPassword in ConfirmLockPassword,
+        // LockPatternChecker and LockPatternUtils. verifyPassword should be the only API to use,
+        // which optionally accepts a challenge.
         if (mCredentialMode == CREDENTIAL_MANAGED) {
-            // We set the challenge as 0L, so it will force to unlock managed profile when it
-            // unlocks primary profile screen lock, by calling verifyTiedProfileChallenge()
             launched = mChooseLockSettingsHelper
                     .launchConfirmationActivityWithExternalAndChallenge(
                             0 /* request code */, null /* title */, mTitle, mDetails,
diff --git a/src/com/android/settings/search/SearchFeatureProvider.java b/src/com/android/settings/search/SearchFeatureProvider.java
index dcb4acc..896f6e5 100644
--- a/src/com/android/settings/search/SearchFeatureProvider.java
+++ b/src/com/android/settings/search/SearchFeatureProvider.java
@@ -39,7 +39,7 @@
  */
 public interface SearchFeatureProvider {
 
-    int REQUEST_CODE = 0;
+    int REQUEST_CODE = 501;
 
     /**
      * Ensures the caller has necessary privilege to launch search result page.
diff --git a/src/com/android/settings/search/actionbar/SearchMenuController.java b/src/com/android/settings/search/actionbar/SearchMenuController.java
index af7141e..25d0d30 100644
--- a/src/com/android/settings/search/actionbar/SearchMenuController.java
+++ b/src/com/android/settings/search/actionbar/SearchMenuController.java
@@ -33,6 +33,7 @@
 import com.android.settings.core.InstrumentedFragment;
 import com.android.settings.core.InstrumentedPreferenceFragment;
 import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.search.SearchFeatureProvider;
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
 import com.android.settingslib.core.lifecycle.events.OnCreateOptionsMenu;
 
@@ -93,7 +94,7 @@
 
             FeatureFactory.getFactory(context).getMetricsFeatureProvider()
                     .action(context, SettingsEnums.ACTION_SEARCH_RESULTS);
-            mHost.startActivityForResult(intent, 0 /* requestCode */);
+            mHost.startActivityForResult(intent, SearchFeatureProvider.REQUEST_CODE);
             return true;
         });
     }
diff --git a/src/com/android/settings/slices/CustomSliceManager.java b/src/com/android/settings/slices/CustomSliceManager.java
deleted file mode 100644
index c9e473a..0000000
--- a/src/com/android/settings/slices/CustomSliceManager.java
+++ /dev/null
@@ -1,133 +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.slices;
-
-import android.content.Context;
-import android.net.Uri;
-import android.util.ArrayMap;
-
-import androidx.annotation.VisibleForTesting;
-
-import com.android.settings.flashlight.FlashlightSlice;
-import com.android.settings.homepage.contextualcards.deviceinfo.BatteryInfoSlice;
-import com.android.settings.homepage.contextualcards.deviceinfo.DataUsageSlice;
-import com.android.settings.homepage.contextualcards.deviceinfo.DeviceInfoSlice;
-import com.android.settings.homepage.contextualcards.deviceinfo.EmergencyInfoSlice;
-import com.android.settings.homepage.contextualcards.deviceinfo.StorageSlice;
-import com.android.settings.homepage.contextualcards.slices.BatteryFixSlice;
-import com.android.settings.homepage.contextualcards.slices.BluetoothDevicesSlice;
-import com.android.settings.homepage.contextualcards.slices.LowStorageSlice;
-import com.android.settings.homepage.contextualcards.slices.NotificationChannelSlice;
-import com.android.settings.location.LocationSlice;
-import com.android.settings.media.MediaOutputSlice;
-import com.android.settings.network.telephony.MobileDataSlice;
-import com.android.settings.wifi.slice.ContextualWifiSlice;
-import com.android.settings.wifi.slice.WifiSlice;
-
-import java.util.Map;
-import java.util.WeakHashMap;
-
-/**
- * Manages custom {@link androidx.slice.Slice Slices}, which are all Slices not backed by
- * preferences.
- */
-public class CustomSliceManager {
-
-    @VisibleForTesting
-    final Map<Uri, Class<? extends CustomSliceable>> mUriMap;
-
-    private final Context mContext;
-    private final Map<Uri, CustomSliceable> mSliceableCache;
-
-    public CustomSliceManager(Context context) {
-        mContext = context.getApplicationContext();
-        mUriMap = new ArrayMap<>();
-        mSliceableCache = new WeakHashMap<>();
-        addSlices();
-    }
-
-    /**
-     * Return a {@link CustomSliceable} associated to the Uri.
-     * <p>
-     * Do not change this method signature to accommodate for a special-case slicable - a context is
-     * the only thing that should be needed to create the object.
-     */
-    public CustomSliceable getSliceableFromUri(Uri uri) {
-        final Uri newUri = removeParameterFromUri(uri);
-        if (mSliceableCache.containsKey(newUri)) {
-            return mSliceableCache.get(newUri);
-        }
-
-        final Class clazz = mUriMap.get(newUri);
-        if (clazz == null) {
-            throw new IllegalArgumentException("No Slice found for uri: " + uri);
-        }
-
-        final CustomSliceable sliceable = CustomSliceable.createInstance(mContext, clazz);
-        mSliceableCache.put(newUri, sliceable);
-        return sliceable;
-    }
-
-    private Uri removeParameterFromUri(Uri uri) {
-        return uri != null ? uri.buildUpon().clearQuery().build() : null;
-    }
-
-    /**
-     * Return a {@link CustomSliceable} associated to the Action.
-     * <p>
-     * Do not change this method signature to accommodate for a special-case sliceable - a context
-     * is the only thing that should be needed to create the object.
-     */
-    public CustomSliceable getSliceableFromIntentAction(String action) {
-        return getSliceableFromUri(Uri.parse(action));
-    }
-
-    /**
-     * Returns {@code true} if {@param uri} is a valid Slice Uri handled by
-     * {@link CustomSliceManager}.
-     */
-    public boolean isValidUri(Uri uri) {
-        return mUriMap.containsKey(removeParameterFromUri(uri));
-    }
-
-    /**
-     * Returns {@code true} if {@param action} is a valid intent action handled by
-     * {@link CustomSliceManager}.
-     */
-    public boolean isValidAction(String action) {
-        return isValidUri(Uri.parse(action));
-    }
-
-    private void addSlices() {
-        mUriMap.put(CustomSliceRegistry.BATTERY_FIX_SLICE_URI, BatteryFixSlice.class);
-        mUriMap.put(CustomSliceRegistry.BATTERY_INFO_SLICE_URI, BatteryInfoSlice.class);
-        mUriMap.put(CustomSliceRegistry.BLUETOOTH_DEVICES_SLICE_URI, BluetoothDevicesSlice.class);
-        mUriMap.put(CustomSliceRegistry.CONTEXTUAL_WIFI_SLICE_URI, ContextualWifiSlice.class);
-        mUriMap.put(CustomSliceRegistry.DATA_USAGE_SLICE_URI, DataUsageSlice.class);
-        mUriMap.put(CustomSliceRegistry.DEVICE_INFO_SLICE_URI, DeviceInfoSlice.class);
-        mUriMap.put(CustomSliceRegistry.EMERGENCY_INFO_SLICE_URI, EmergencyInfoSlice.class);
-        mUriMap.put(CustomSliceRegistry.FLASHLIGHT_SLICE_URI, FlashlightSlice.class);
-        mUriMap.put(CustomSliceRegistry.LOCATION_SLICE_URI, LocationSlice.class);
-        mUriMap.put(CustomSliceRegistry.LOW_STORAGE_SLICE_URI, LowStorageSlice.class);
-        mUriMap.put(CustomSliceRegistry.MOBILE_DATA_SLICE_URI, MobileDataSlice.class);
-        mUriMap.put(CustomSliceRegistry.NOTIFICATION_CHANNEL_SLICE_URI,
-                NotificationChannelSlice.class);
-        mUriMap.put(CustomSliceRegistry.STORAGE_SLICE_URI, StorageSlice.class);
-        mUriMap.put(CustomSliceRegistry.WIFI_SLICE_URI, WifiSlice.class);
-        mUriMap.put(CustomSliceRegistry.MEDIA_OUTPUT_SLICE_URI, MediaOutputSlice.class);
-    }
-}
diff --git a/src/com/android/settings/slices/CustomSliceRegistry.java b/src/com/android/settings/slices/CustomSliceRegistry.java
index 3a1db69..6b1ead7 100644
--- a/src/com/android/settings/slices/CustomSliceRegistry.java
+++ b/src/com/android/settings/slices/CustomSliceRegistry.java
@@ -24,11 +24,31 @@
 import android.content.ContentResolver;
 import android.net.Uri;
 import android.provider.SettingsSlicesContract;
+import android.util.ArrayMap;
 
+import androidx.annotation.VisibleForTesting;
+
+import com.android.settings.flashlight.FlashlightSlice;
 import com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController;
+import com.android.settings.homepage.contextualcards.deviceinfo.DataUsageSlice;
+import com.android.settings.homepage.contextualcards.deviceinfo.DeviceInfoSlice;
+import com.android.settings.homepage.contextualcards.deviceinfo.EmergencyInfoSlice;
+import com.android.settings.homepage.contextualcards.deviceinfo.StorageSlice;
+import com.android.settings.homepage.contextualcards.slices.BatteryFixSlice;
+import com.android.settings.homepage.contextualcards.slices.BluetoothDevicesSlice;
+import com.android.settings.homepage.contextualcards.slices.LowStorageSlice;
+import com.android.settings.homepage.contextualcards.slices.NotificationChannelSlice;
+import com.android.settings.location.LocationSlice;
+import com.android.settings.media.MediaOutputIndicatorSlice;
+import com.android.settings.media.MediaOutputSlice;
+import com.android.settings.network.telephony.MobileDataSlice;
 import com.android.settings.wifi.calling.WifiCallingSliceHelper;
+import com.android.settings.wifi.slice.ContextualWifiSlice;
+import com.android.settings.wifi.slice.WifiSlice;
 import com.android.settingslib.media.MediaOutputSliceConstants;
 
+import java.util.Map;
+
 /**
  * A registry of custom slice Uris.
  */
@@ -53,15 +73,7 @@
             .appendEncodedPath(SettingsSlicesContract.PATH_SETTING_INTENT)
             .appendPath(BatteryTipPreferenceController.PREF_NAME)
             .build();
-    /**
-     * Backing Uri for the Battery info Slice.
-     */
-    public static final Uri BATTERY_INFO_SLICE_URI = new Uri.Builder()
-            .scheme(ContentResolver.SCHEME_CONTENT)
-            .authority(SettingsSliceProvider.SLICE_AUTHORITY)
-            .appendEncodedPath(SettingsSlicesContract.PATH_SETTING_INTENT)
-            .appendPath("battery_card")
-            .build();
+
     /**
      * Backing Uri for the Bluetooth Slice.
      */
@@ -287,4 +299,61 @@
             .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
             .appendPath(MediaOutputSliceConstants.KEY_MEDIA_OUTPUT)
             .build();
+
+    /**
+     * Backing Uri for the Media output indicator Slice.
+     */
+    public static Uri MEDIA_OUTPUT_INDICATOR_SLICE_URI = new Uri.Builder()
+            .scheme(ContentResolver.SCHEME_CONTENT)
+            .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+            .appendPath(SettingsSlicesContract.PATH_SETTING_INTENT)
+            .appendPath("media_output_indicator")
+            .build();
+
+    @VisibleForTesting
+    static final Map<Uri, Class<? extends CustomSliceable>> sUriToSlice;
+
+    static {
+        sUriToSlice = new ArrayMap<>();
+
+        sUriToSlice.put(BATTERY_FIX_SLICE_URI, BatteryFixSlice.class);
+        sUriToSlice.put(BLUETOOTH_DEVICES_SLICE_URI, BluetoothDevicesSlice.class);
+        sUriToSlice.put(CONTEXTUAL_WIFI_SLICE_URI, ContextualWifiSlice.class);
+        sUriToSlice.put(DATA_USAGE_SLICE_URI, DataUsageSlice.class);
+        sUriToSlice.put(DEVICE_INFO_SLICE_URI, DeviceInfoSlice.class);
+        sUriToSlice.put(EMERGENCY_INFO_SLICE_URI, EmergencyInfoSlice.class);
+        sUriToSlice.put(FLASHLIGHT_SLICE_URI, FlashlightSlice.class);
+        sUriToSlice.put(LOCATION_SLICE_URI, LocationSlice.class);
+        sUriToSlice.put(LOW_STORAGE_SLICE_URI, LowStorageSlice.class);
+        sUriToSlice.put(MOBILE_DATA_SLICE_URI, MobileDataSlice.class);
+        sUriToSlice.put(NOTIFICATION_CHANNEL_SLICE_URI, NotificationChannelSlice.class);
+        sUriToSlice.put(STORAGE_SLICE_URI, StorageSlice.class);
+        sUriToSlice.put(WIFI_SLICE_URI, WifiSlice.class);
+        sUriToSlice.put(MEDIA_OUTPUT_SLICE_URI, MediaOutputSlice.class);
+        sUriToSlice.put(MEDIA_OUTPUT_INDICATOR_SLICE_URI, MediaOutputIndicatorSlice.class);
+    }
+
+    public static Class<? extends CustomSliceable> getSliceClassByUri(Uri uri) {
+        return sUriToSlice.get(removeParameterFromUri(uri));
+    }
+
+    public static Uri removeParameterFromUri(Uri uri) {
+        return uri != null ? uri.buildUpon().clearQuery().build() : null;
+    }
+
+    /**
+     * Returns {@code true} if {@param uri} is a valid Slice Uri handled by
+     * {@link CustomSliceRegistry}.
+     */
+    public static boolean isValidUri(Uri uri) {
+        return sUriToSlice.containsKey(removeParameterFromUri(uri));
+    }
+
+    /**
+     * Returns {@code true} if {@param action} is a valid intent action handled by
+     * {@link CustomSliceRegistry}.
+     */
+    public static boolean isValidAction(String action) {
+        return isValidUri(Uri.parse(action));
+    }
 }
diff --git a/src/com/android/settings/slices/CustomSliceable.java b/src/com/android/settings/slices/CustomSliceable.java
index 0b97bed..93d08a2 100644
--- a/src/com/android/settings/slices/CustomSliceable.java
+++ b/src/com/android/settings/slices/CustomSliceable.java
@@ -19,7 +19,6 @@
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
-import android.content.IntentFilter;
 import android.net.Uri;
 
 import androidx.slice.Slice;
@@ -106,16 +105,17 @@
     /**
      * Build an instance of a {@link CustomSliceable} which has a {@link Context}-only constructor.
      */
-    static CustomSliceable createInstance(Context context, Class<CustomSliceable> sliceableClass) {
+    static CustomSliceable createInstance(Context context,
+            Class<? extends CustomSliceable> sliceable) {
         try {
-            final Constructor<CustomSliceable> sliceable =
-                    sliceableClass.getConstructor(Context.class);
-            final Object[] params = new Object[]{context};
-            return sliceable.newInstance(params);
+            final Constructor<? extends CustomSliceable> constructor =
+                    sliceable.getConstructor(Context.class);
+            final Object[] params = new Object[]{context.getApplicationContext()};
+            return constructor.newInstance(params);
         } catch (NoSuchMethodException | InstantiationException |
                 IllegalArgumentException | InvocationTargetException | IllegalAccessException e) {
             throw new IllegalStateException(
-                    "Invalid sliceable class: " + sliceableClass, e);
+                    "Invalid sliceable class: " + sliceable, e);
         }
     }
 }
\ No newline at end of file
diff --git a/src/com/android/settings/slices/SettingsSliceProvider.java b/src/com/android/settings/slices/SettingsSliceProvider.java
index 397b2fc..3187d10 100644
--- a/src/com/android/settings/slices/SettingsSliceProvider.java
+++ b/src/com/android/settings/slices/SettingsSliceProvider.java
@@ -118,9 +118,6 @@
     private static final KeyValueListParser KEY_VALUE_LIST_PARSER = new KeyValueListParser(',');
 
     @VisibleForTesting
-    CustomSliceManager mCustomSliceManager;
-
-    @VisibleForTesting
     SlicesDatabaseAccessor mSlicesDatabaseAccessor;
 
     @VisibleForTesting
@@ -140,15 +137,15 @@
         mSlicesDatabaseAccessor = new SlicesDatabaseAccessor(getContext());
         mSliceDataCache = new ConcurrentHashMap<>();
         mSliceWeakDataCache = new WeakHashMap<>();
-        mCustomSliceManager = FeatureFactory.getFactory(
-                getContext()).getSlicesFeatureProvider().getCustomSliceManager(getContext());
         return true;
     }
 
     @Override
     public void onSlicePinned(Uri sliceUri) {
-        if (mCustomSliceManager.isValidUri(sliceUri)) {
-            final CustomSliceable sliceable = mCustomSliceManager.getSliceableFromUri(sliceUri);
+        if (CustomSliceRegistry.isValidUri(sliceUri)) {
+            final Context context = getContext();
+            final CustomSliceable sliceable = FeatureFactory.getFactory(context)
+                    .getSlicesFeatureProvider().getSliceableFromUri(context, sliceUri);
             final IntentFilter filter = sliceable.getIntentFilter();
             if (filter != null) {
                 registerIntentToUri(filter, sliceUri);
@@ -194,10 +191,11 @@
 
             // Before adding a slice to {@link CustomSliceManager}, please get approval
             // from the Settings team.
-            if (mCustomSliceManager.isValidUri(sliceUri)) {
-                final CustomSliceable sliceable = mCustomSliceManager.getSliceableFromUri(
-                        sliceUri);
-                return sliceable.getSlice();
+            if (CustomSliceRegistry.isValidUri(sliceUri)) {
+                final Context context = getContext();
+                return FeatureFactory.getFactory(context)
+                        .getSlicesFeatureProvider().getSliceableFromUri(context, sliceUri)
+                        .getSlice();
             }
 
             if (CustomSliceRegistry.WIFI_CALLING_URI.equals(sliceUri)) {
diff --git a/src/com/android/settings/slices/SliceBackgroundWorker.java b/src/com/android/settings/slices/SliceBackgroundWorker.java
index 559aa71..f19b1df 100644
--- a/src/com/android/settings/slices/SliceBackgroundWorker.java
+++ b/src/com/android/settings/slices/SliceBackgroundWorker.java
@@ -146,7 +146,7 @@
                 needNotify = true;
             }
         } else {
-            needNotify = !results.equals(mCachedResults);
+            needNotify = !areListsTheSame(results, mCachedResults);
         }
 
         if (needNotify) {
@@ -155,6 +155,10 @@
         }
     }
 
+    protected boolean areListsTheSame(List<E> a, List<E> b) {
+        return a.equals(b);
+    }
+
     /**
      * Notify that data was updated and attempt to sync changes to the Slice.
      */
diff --git a/src/com/android/settings/slices/SliceBroadcastReceiver.java b/src/com/android/settings/slices/SliceBroadcastReceiver.java
index b2ea583..9926a52 100644
--- a/src/com/android/settings/slices/SliceBroadcastReceiver.java
+++ b/src/com/android/settings/slices/SliceBroadcastReceiver.java
@@ -61,11 +61,10 @@
         final boolean isPlatformSlice = intent.getBooleanExtra(EXTRA_SLICE_PLATFORM_DEFINED,
                 false /* default */);
 
-        final CustomSliceManager mCustomSliceManager = FeatureFactory.getFactory(
-                context).getSlicesFeatureProvider().getCustomSliceManager(context);
-        if (mCustomSliceManager.isValidAction(action)) {
+        if (CustomSliceRegistry.isValidAction(action)) {
             final CustomSliceable sliceable =
-                    mCustomSliceManager.getSliceableFromIntentAction(action);
+                    CustomSliceable.createInstance(context,
+                            CustomSliceRegistry.getSliceClassByUri(Uri.parse(action)));
             sliceable.onNotifyChange(intent);
             return;
         }
diff --git a/src/com/android/settings/slices/SliceDeepLinkSpringBoard.java b/src/com/android/settings/slices/SliceDeepLinkSpringBoard.java
index f4afa16..2ff071e 100644
--- a/src/com/android/settings/slices/SliceDeepLinkSpringBoard.java
+++ b/src/com/android/settings/slices/SliceDeepLinkSpringBoard.java
@@ -23,7 +23,6 @@
 
 import com.android.settings.bluetooth.BluetoothSliceBuilder;
 import com.android.settings.notification.ZenModeSliceBuilder;
-import com.android.settings.overlay.FeatureFactory;
 
 public class SliceDeepLinkSpringBoard extends Activity {
 
@@ -45,11 +44,10 @@
             Intent launchIntent;
 
             // TODO (b/80263568) Avoid duplicating this list of Slice Uris.
-            final CustomSliceManager customSliceManager = FeatureFactory.getFactory(this)
-                    .getSlicesFeatureProvider().getCustomSliceManager(this);
-            if (customSliceManager.isValidUri(sliceUri)) {
+            if (CustomSliceRegistry.isValidUri(sliceUri)) {
                 final CustomSliceable sliceable =
-                        customSliceManager.getSliceableFromUri(sliceUri);
+                        CustomSliceable.createInstance(getApplicationContext(),
+                                CustomSliceRegistry.getSliceClassByUri(sliceUri));
                 launchIntent = sliceable.getIntent();
             } else if (CustomSliceRegistry.ZEN_MODE_SLICE_URI.equals(sliceUri)) {
                 launchIntent = ZenModeSliceBuilder.getIntent(this /* context */);
diff --git a/src/com/android/settings/slices/SlicesFeatureProvider.java b/src/com/android/settings/slices/SlicesFeatureProvider.java
index 1a9fd98..ae94f29 100644
--- a/src/com/android/settings/slices/SlicesFeatureProvider.java
+++ b/src/com/android/settings/slices/SlicesFeatureProvider.java
@@ -1,6 +1,7 @@
 package com.android.settings.slices;
 
 import android.content.Context;
+import android.net.Uri;
 
 import com.android.settings.network.telephony.Enhanced4gLteSliceHelper;
 import com.android.settings.wifi.calling.WifiCallingSliceHelper;
@@ -12,11 +13,23 @@
 
     boolean DEBUG = false;
 
-    SlicesIndexer getSliceIndexer(Context context);
-
     SliceDataConverter getSliceDataConverter(Context context);
 
     /**
+     * Starts a new UI session for the purpose of using Slices.
+     *
+     * A UI session is defined as an duration of time when user stays in a UI screen. Screen
+     * rotation does not break the continuation of session, going to a sub-page and coming out does
+     * not break the continuation either. Leaving the page and coming back breaks it.
+     */
+    void newUiSession();
+
+    /**
+     * Returns the token created in {@link #newUiSession}.
+     */
+    long getUiSessionToken();
+
+    /**
      * Asynchronous call to index the data used to build Slices.
      * If the data is already indexed, the data will not change.
      */
@@ -28,7 +41,14 @@
      */
     void indexSliceData(Context context);
 
-    CustomSliceManager getCustomSliceManager(Context context);
+
+    /**
+     * Return a {@link CustomSliceable} associated to the Uri.
+     * <p>
+     * Do not change this method signature to accommodate for a special-case sliceable - a context
+     * is the only thing that should be needed to create the object.
+     */
+    CustomSliceable getSliceableFromUri(Context context, Uri uri);
 
     /**
      * Gets new WifiCallingSliceHelper object
diff --git a/src/com/android/settings/slices/SlicesFeatureProviderImpl.java b/src/com/android/settings/slices/SlicesFeatureProviderImpl.java
index 508eb1c..297f2c1 100644
--- a/src/com/android/settings/slices/SlicesFeatureProviderImpl.java
+++ b/src/com/android/settings/slices/SlicesFeatureProviderImpl.java
@@ -17,27 +17,23 @@
 package com.android.settings.slices;
 
 import android.content.Context;
+import android.net.Uri;
+import android.os.SystemClock;
 
 import com.android.settings.network.telephony.Enhanced4gLteSliceHelper;
 import com.android.settings.wifi.calling.WifiCallingSliceHelper;
 import com.android.settingslib.utils.ThreadUtils;
 
+import java.util.Random;
+
 /**
  * Manages Slices in Settings.
  */
 public class SlicesFeatureProviderImpl implements SlicesFeatureProvider {
 
+    private long mUiSessionToken;
     private SlicesIndexer mSlicesIndexer;
     private SliceDataConverter mSliceDataConverter;
-    private CustomSliceManager mCustomSliceManager;
-
-    @Override
-    public SlicesIndexer getSliceIndexer(Context context) {
-        if (mSlicesIndexer == null) {
-            mSlicesIndexer = new SlicesIndexer(context.getApplicationContext());
-        }
-        return mSlicesIndexer;
-    }
 
     @Override
     public SliceDataConverter getSliceDataConverter(Context context) {
@@ -48,11 +44,13 @@
     }
 
     @Override
-    public CustomSliceManager getCustomSliceManager(Context context) {
-        if (mCustomSliceManager == null) {
-            mCustomSliceManager = new CustomSliceManager(context.getApplicationContext());
-        }
-        return mCustomSliceManager;
+    public void newUiSession() {
+        mUiSessionToken = SystemClock.elapsedRealtime();
+    }
+
+    @Override
+    public long getUiSessionToken() {
+        return mUiSessionToken;
     }
 
     @Override
@@ -76,4 +74,23 @@
     public Enhanced4gLteSliceHelper getNewEnhanced4gLteSliceHelper(Context context) {
         return new Enhanced4gLteSliceHelper(context);
     }
+
+    @Override
+    public CustomSliceable getSliceableFromUri(Context context, Uri uri) {
+        final Uri newUri = CustomSliceRegistry.removeParameterFromUri(uri);
+        final Class clazz = CustomSliceRegistry.getSliceClassByUri(newUri);
+        if (clazz == null) {
+            throw new IllegalArgumentException("No Slice found for uri: " + uri);
+        }
+
+        final CustomSliceable sliceable = CustomSliceable.createInstance(context, clazz);
+        return sliceable;
+    }
+
+    private SlicesIndexer getSliceIndexer(Context context) {
+        if (mSlicesIndexer == null) {
+            mSlicesIndexer = new SlicesIndexer(context.getApplicationContext());
+        }
+        return mSlicesIndexer;
+    }
 }
diff --git a/src/com/android/settings/slices/SlicesIndexer.java b/src/com/android/settings/slices/SlicesIndexer.java
index 1b3a25e..5f80047 100644
--- a/src/com/android/settings/slices/SlicesIndexer.java
+++ b/src/com/android/settings/slices/SlicesIndexer.java
@@ -84,7 +84,6 @@
         } finally {
             database.endTransaction();
         }
-        database.close();
     }
 
     @VisibleForTesting
diff --git a/src/com/android/settings/widget/SingleTargetGearPreference.java b/src/com/android/settings/widget/SingleTargetGearPreference.java
index 48876fa..f6496ed 100644
--- a/src/com/android/settings/widget/SingleTargetGearPreference.java
+++ b/src/com/android/settings/widget/SingleTargetGearPreference.java
@@ -18,9 +18,10 @@
 
 import android.content.Context;
 import android.util.AttributeSet;
+import android.view.View;
 
-import androidx.core.content.res.TypedArrayUtils;
 import androidx.preference.Preference;
+import androidx.preference.PreferenceViewHolder;
 
 import com.android.settings.R;
 
@@ -28,23 +29,38 @@
  * A preference with single target and a gear icon on the side.
  */
 public class SingleTargetGearPreference extends Preference {
-
-    public SingleTargetGearPreference(Context context, AttributeSet attrs,
-            int defStyleAttr, int defStyleRes) {
+    public SingleTargetGearPreference(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
-        setWidgetLayoutResource(R.layout.preference_widget_gear_no_bg);
+        init();
     }
 
     public SingleTargetGearPreference(Context context, AttributeSet attrs, int defStyleAttr) {
-        this(context, attrs, defStyleAttr, 0 /* defStyleRes */);
+        super(context, attrs, defStyleAttr);
+        init();
     }
 
     public SingleTargetGearPreference(Context context, AttributeSet attrs) {
-        this(context, attrs, TypedArrayUtils.getAttr(context, R.attr.preferenceStyle,
-                android.R.attr.preferenceStyle));
+        super(context, attrs);
+        init();
     }
 
     public SingleTargetGearPreference(Context context) {
-        this(context, null /* attrs */);
+        super(context);
+        init();
     }
-}
\ No newline at end of file
+
+    private void init() {
+        setLayoutResource(R.layout.preference_single_target);
+        setWidgetLayoutResource(R.layout.preference_widget_gear_optional_background);
+    }
+
+    @Override
+    public void onBindViewHolder(PreferenceViewHolder holder) {
+        super.onBindViewHolder(holder);
+        final View divider = holder.findViewById(com.android.settingslib.R.id.two_target_divider);
+        if (divider != null) {
+            divider.setVisibility(View.INVISIBLE);
+        }
+    }
+}
diff --git a/src/com/android/settings/wifi/AddWifiNetworkPreference.java b/src/com/android/settings/wifi/AddWifiNetworkPreference.java
new file mode 100644
index 0000000..cd2e4a8
--- /dev/null
+++ b/src/com/android/settings/wifi/AddWifiNetworkPreference.java
@@ -0,0 +1,83 @@
+/*
+ * 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.wifi;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.util.Log;
+import android.view.View;
+import android.widget.ImageButton;
+
+import androidx.annotation.DrawableRes;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceViewHolder;
+
+import com.android.settings.R;
+import com.android.settings.wifi.dpp.WifiDppUtils;
+
+/**
+ * The Preference for users to add Wi-Fi networks in WifiSettings
+ */
+public class AddWifiNetworkPreference extends Preference {
+
+    private static final String TAG = "AddWifiNetworkPreference";
+
+    private boolean mInitialized;
+
+    public AddWifiNetworkPreference(Context context) {
+        super(context);
+
+        setLayoutResource(com.android.settingslib.R.layout.preference_access_point);
+        setWidgetLayoutResource(R.layout.wifi_button_preference_widget);
+        setIcon(R.drawable.ic_menu_add);
+        setTitle(R.string.wifi_add_network);
+    }
+
+    @Override
+    public void onBindViewHolder(PreferenceViewHolder holder) {
+        super.onBindViewHolder(holder);
+
+        if (!mInitialized) {
+            mInitialized = true;
+
+            final ImageButton imageButton = (ImageButton) holder.findViewById(R.id.button_icon);
+            imageButton.setImageDrawable(getDrawable(R.drawable.ic_scan_24dp));
+            imageButton.setContentDescription(
+                    getContext().getString(R.string.wifi_dpp_scan_qr_code));
+            imageButton.setOnClickListener(view -> {
+                getContext().startActivity(
+                    WifiDppUtils.getEnrolleeQrCodeScannerIntent(/* ssid */ null));
+            });
+
+            final View divider = (View) holder.findViewById(
+                    com.android.settingslib.R.id.two_target_divider);
+            divider.setVisibility(View.INVISIBLE);
+        }
+    }
+
+    private Drawable getDrawable(@DrawableRes int iconResId) {
+        Drawable buttonIcon = null;
+
+        try {
+            buttonIcon = getContext().getDrawable(iconResId);
+        } catch (Resources.NotFoundException exception) {
+            Log.e(TAG, "Resource does not exist: " + iconResId);
+        }
+        return buttonIcon;
+    }
+}
diff --git a/src/com/android/settings/wifi/ButtonPreference.java b/src/com/android/settings/wifi/ButtonPreference.java
deleted file mode 100644
index 5169d7a..0000000
--- a/src/com/android/settings/wifi/ButtonPreference.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.settings.wifi;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.drawable.Drawable;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.View;
-import android.widget.ImageButton;
-
-import androidx.annotation.DrawableRes;
-import androidx.annotation.VisibleForTesting;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceViewHolder;
-
-import com.android.settings.R;
-
-/**
- * This preference provides one button layout with Settings style.
- * It looks like below
- *
- * --------------------------------------------------------------
- * | icon | title                                    |  button  |
- * --------------------------------------------------------------
- *
- * User can set icon / click listener for button.
- * By default, the button is invisible.
- */
-public class ButtonPreference extends Preference {
-
-    private static final String TAG = "ButtonPreference";
-
-    private ImageButton mImageButton;
-    private Drawable mButtonIcon;
-    private View.OnClickListener mClickListener;
-    private String mContentDescription;
-
-    // Used for dummy pref.
-    public ButtonPreference(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        setWidgetLayoutResource(R.layout.wifi_button_preference_widget);
-        mImageButton = null;
-        mButtonIcon = null;
-        mClickListener = null;
-        mContentDescription = null;
-    }
-
-    public ButtonPreference(Context context) {
-        this(context, /* attrs */ null);
-    }
-
-    @Override
-    public void onBindViewHolder(final PreferenceViewHolder view) {
-        super.onBindViewHolder(view);
-        initButton(view);
-    }
-
-    @Override
-    public void setOrder(int order) {
-        super.setOrder(order);
-        setButtonVisibility();
-    }
-
-    @VisibleForTesting
-    protected void initButton(final PreferenceViewHolder view) {
-        if (mImageButton == null) {
-            mImageButton = (ImageButton) view.findViewById(R.id.button_icon);
-        }
-        if (mImageButton != null) {
-            mImageButton.setImageDrawable(mButtonIcon);
-            mImageButton.setOnClickListener(mClickListener);
-            mImageButton.setContentDescription(mContentDescription);
-        }
-        setButtonVisibility();
-    }
-
-    private void setButtonVisibility() {
-        if(mImageButton != null) {
-            mImageButton.setVisibility(mButtonIcon == null ? View.GONE : View.VISIBLE);
-        }
-    }
-
-    /**
-     * Sets the drawable to be displayed in button.
-     */
-    public void setButtonIcon(@DrawableRes int iconResId) {
-        if (iconResId == 0) {
-            return;
-        }
-
-        try {
-            mButtonIcon = getContext().getDrawable(iconResId);
-            notifyChanged();
-        } catch (Resources.NotFoundException exception) {
-            Log.e(TAG, "Resource does not exist: " + iconResId);
-        }
-    }
-
-    /**
-     * Register a callback to be invoked when button is clicked.
-     */
-    public void setButtonOnClickListener(View.OnClickListener listener) {
-        if (listener != mClickListener) {
-            mClickListener = listener;
-            notifyChanged();
-        }
-    }
-
-    /**
-     * A content description briefly describes the button and is primarily used for accessibility
-     * support to determine how a button should be presented to the user.
-     */
-    public void setButtonContentDescription(String contentDescription) {
-        if (contentDescription != mContentDescription) {
-            mContentDescription = contentDescription;
-            notifyChanged();
-        }
-    }
-}
diff --git a/src/com/android/settings/wifi/WifiConfigController.java b/src/com/android/settings/wifi/WifiConfigController.java
index 665e253..0adbd8d 100644
--- a/src/com/android/settings/wifi/WifiConfigController.java
+++ b/src/com/android/settings/wifi/WifiConfigController.java
@@ -249,7 +249,7 @@
         mHiddenSettingsSpinner = mView.findViewById(R.id.hidden_settings);
         mPrivacySettingsSpinner = mView.findViewById(R.id.privacy_settings);
         if (mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_wifi_p2p_mac_randomization_supported)) {
+                com.android.internal.R.bool.config_wifi_connected_mac_randomization_supported)) {
             View privacySettingsLayout = mView.findViewById(R.id.privacy_settings_fields);
             privacySettingsLayout.setVisibility(View.VISIBLE);
         }
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index a8fc34d..585cf71 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -179,7 +179,8 @@
 
     private PreferenceCategory mConnectedAccessPointPreferenceCategory;
     private PreferenceCategory mAccessPointsPreferenceCategory;
-    private ButtonPreference mAddPreference;
+    @VisibleForTesting
+    AddWifiNetworkPreference mAddWifiNetworkPreference;
     @VisibleForTesting
     Preference mConfigureWifiSettingsPreference;
     @VisibleForTesting
@@ -237,20 +238,8 @@
                 (PreferenceCategory) findPreference(PREF_KEY_ACCESS_POINTS);
         mConfigureWifiSettingsPreference = findPreference(PREF_KEY_CONFIGURE_WIFI_SETTINGS);
         mSavedNetworksPreference = findPreference(PREF_KEY_SAVED_NETWORKS);
-
-        Context prefContext = getPrefContext();
-        mAddPreference = new ButtonPreference(prefContext);
-        mAddPreference.setIcon(R.drawable.ic_menu_add);
-        mAddPreference.setTitle(R.string.wifi_add_network);
-        mAddPreference.setButtonIcon(R.drawable.ic_scan_24dp);
-        mAddPreference.setButtonOnClickListener((View v) -> {
-            // Launch QR code scanner to join a network.
-            getContext().startActivity(
-                    WifiDppUtils.getEnrolleeQrCodeScannerIntent(/* ssid */ null));
-        });
-        mAddPreference.setButtonContentDescription(getString(R.string.wifi_dpp_scan_qr_code));
+        mAddWifiNetworkPreference = new AddWifiNetworkPreference(getPrefContext());
         mStatusMessagePreference = (LinkablePreference) findPreference(PREF_KEY_STATUS_MESSAGE);
-
         mUserBadgeCache = new AccessPointPreference.UserBadgeCache(getPackageManager());
     }
 
@@ -590,7 +579,7 @@
                     showDialog(mSelectedAccessPoint, WifiConfigUiBase.MODE_CONNECT);
                     break;
             }
-        } else if (preference == mAddPreference) {
+        } else if (preference == mAddWifiNetworkPreference) {
             onAddNetworkPressed();
         } else {
             return super.onPreferenceTreeClick(preference);
@@ -809,8 +798,8 @@
             }
         }
         removeCachedPrefs(mAccessPointsPreferenceCategory);
-        mAddPreference.setOrder(index);
-        mAccessPointsPreferenceCategory.addPreference(mAddPreference);
+        mAddWifiNetworkPreference.setOrder(index);
+        mAccessPointsPreferenceCategory.addPreference(mAddWifiNetworkPreference);
         setAdditionalSettingsSummaries();
 
         if (!hasAvailableAccessPoints) {
diff --git a/src/com/android/settings/wifi/calling/DisclaimerItem.java b/src/com/android/settings/wifi/calling/DisclaimerItem.java
new file mode 100644
index 0000000..6fd8b70
--- /dev/null
+++ b/src/com/android/settings/wifi/calling/DisclaimerItem.java
@@ -0,0 +1,137 @@
+/*
+ * 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.calling;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.PersistableBundle;
+import android.telephony.CarrierConfigManager;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * Interface to control disclaimer item from {@link WifiCallingDisclaimerFragment}.
+ */
+@VisibleForTesting
+public abstract class DisclaimerItem {
+    private static final String SHARED_PREFERENCES_NAME = "wfc_disclaimer_prefs";
+
+    protected final Context mContext;
+    protected final int mSubId;
+    private final CarrierConfigManager mCarrierConfigManager;
+
+    DisclaimerItem(Context context, int subId) {
+        mContext = context;
+        mSubId = subId;
+        mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class);
+    }
+
+    /**
+     * Called by the {@link WifiCallingDisclaimerFragment} when a user has clicked the agree button.
+     */
+    void onAgreed() {
+        setBooleanSharedPrefs(getPrefKey(), true);
+    }
+
+    /**
+     * Checks whether the disclaimer item need to be displayed or not.
+     *
+     * @return Returns {@code true} if disclaimer item need to be displayed,
+     * {@code false} if not displayed.
+     */
+    boolean shouldShow() {
+        if (getBooleanSharedPrefs(getPrefKey(), false)) {
+            logd("shouldShow: false due to a user has already agreed.");
+            return false;
+        }
+        logd("shouldShow: true");
+        return true;
+    }
+
+    /**
+     * Gets the configuration values for a particular sub id.
+     *
+     * @return The {@link PersistableBundle} instance containing the config value for a
+     * particular phone id, or default values.
+     */
+    protected PersistableBundle getCarrierConfig() {
+        PersistableBundle config = mCarrierConfigManager.getConfigForSubId(mSubId);
+        if (config != null) {
+            return config;
+        }
+        // Return static default defined in CarrierConfigManager.
+        return CarrierConfigManager.getDefaultConfig();
+    }
+
+    protected void logd(String msg) {
+        Log.d(getName(), "[" + mSubId +  "] " + msg);
+    }
+
+    /**
+     * Gets a title id for disclaimer item.
+     *
+     * @return Title id for disclaimer item.
+     */
+    protected abstract int getTitleId();
+
+    /**
+     * Gets a message id for disclaimer item.
+     *
+     * @return Message id for disclaimer item.
+     */
+    protected abstract int getMessageId();
+
+    /**
+     * Gets a name of disclaimer item.
+     *
+     * @return Name of disclaimer item.
+     */
+    protected abstract String getName();
+
+    /**
+     * Gets a preference key to keep user's consent.
+     *
+     * @return Preference key to keep user's consent.
+     */
+    protected abstract String getPrefKey();
+
+    /**
+     * Gets the boolean value from shared preferences.
+     *
+     * @param key The key for the preference item.
+     * @param defValue Value to return if this preference does not exist.
+     * @return The boolean value of corresponding key, or defValue.
+     */
+    private boolean getBooleanSharedPrefs(String key, boolean defValue) {
+        SharedPreferences prefs = mContext.getSharedPreferences(SHARED_PREFERENCES_NAME,
+                Context.MODE_PRIVATE);
+        return prefs.getBoolean(key + mSubId, defValue);
+    }
+
+    /**
+     * Sets the boolean value to shared preferences.
+     *
+     * @param key The key for the preference item.
+     * @param value The value to be set for shared preferences.
+     */
+    private void setBooleanSharedPrefs(String key, boolean value) {
+        SharedPreferences prefs = mContext.getSharedPreferences(SHARED_PREFERENCES_NAME,
+                Context.MODE_PRIVATE);
+        prefs.edit().putBoolean(key + mSubId, value).apply();
+    }
+}
diff --git a/src/com/android/settings/wifi/calling/DisclaimerItemFactory.java b/src/com/android/settings/wifi/calling/DisclaimerItemFactory.java
new file mode 100644
index 0000000..6d8dc8f
--- /dev/null
+++ b/src/com/android/settings/wifi/calling/DisclaimerItemFactory.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.wifi.calling;
+
+import android.content.Context;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Factory class to create disclaimer items list.
+ */
+@VisibleForTesting
+public final class DisclaimerItemFactory {
+
+    /**
+     * Creates disclaimer items list.
+     *
+     * @param context The application context
+     * @param subId The subscription id.
+     * @return The {@link DisclaimerItem} list instance, if there are no items, return empty list.
+     */
+    public static List<DisclaimerItem> create(Context context, int subId) {
+        List<DisclaimerItem> itemList = getDisclaimerItemList(context, subId);
+        Iterator itr = itemList.iterator();
+        while (itr.hasNext()) {
+            DisclaimerItem item = (DisclaimerItem) itr.next();
+            if (!item.shouldShow()) {
+                itr.remove();
+            }
+        }
+        return itemList;
+    }
+
+    private static List<DisclaimerItem> getDisclaimerItemList(Context context, int subId) {
+        List<DisclaimerItem> itemList = new ArrayList<DisclaimerItem>();
+
+        return itemList;
+    }
+}
diff --git a/src/com/android/settings/wifi/calling/DisclaimerItemListAdapter.java b/src/com/android/settings/wifi/calling/DisclaimerItemListAdapter.java
new file mode 100644
index 0000000..4b5d19c
--- /dev/null
+++ b/src/com/android/settings/wifi/calling/DisclaimerItemListAdapter.java
@@ -0,0 +1,78 @@
+/*
+ * 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.calling;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.settings.R;
+
+import java.util.List;
+
+/**
+ * Adapter for disclaimer items list.
+ */
+public class DisclaimerItemListAdapter extends
+        RecyclerView.Adapter<DisclaimerItemListAdapter.DisclaimerItemViewHolder> {
+
+    private List<DisclaimerItem> mDisclaimerItemList;
+
+    public DisclaimerItemListAdapter(List<DisclaimerItem> list) {
+        mDisclaimerItemList = list;
+    }
+
+    @Override
+    public DisclaimerItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+        LayoutInflater inflater = (LayoutInflater) parent.getContext().getSystemService(
+                Context.LAYOUT_INFLATER_SERVICE);
+        View view = inflater.inflate(R.layout.wfc_simple_disclaimer_item, null, false);
+        return new DisclaimerItemViewHolder(view);
+    }
+
+    @Override
+    public void onBindViewHolder(DisclaimerItemViewHolder holder, int position) {
+        holder.titleView.setText(mDisclaimerItemList.get(position).getTitleId());
+        holder.descriptionView.setText(mDisclaimerItemList.get(position).getMessageId());
+    }
+
+    @Override
+    public int getItemCount() {
+        return mDisclaimerItemList.size();
+    }
+
+    public static class DisclaimerItemViewHolder extends RecyclerView.ViewHolder {
+        @VisibleForTesting
+        static final int ID_DISCLAIMER_ITEM_TITLE = R.id.disclaimer_title;
+        @VisibleForTesting
+        static final int ID_DISCLAIMER_ITEM_DESCRIPTION = R.id.disclaimer_desc;
+
+        public final TextView titleView;
+        public final TextView descriptionView;
+
+        public DisclaimerItemViewHolder(View itemView) {
+            super(itemView);
+            titleView = itemView.findViewById(ID_DISCLAIMER_ITEM_TITLE);
+            descriptionView = itemView.findViewById(ID_DISCLAIMER_ITEM_DESCRIPTION);
+        }
+    }
+}
diff --git a/src/com/android/settings/wifi/calling/WifiCallingDisclaimerFragment.java b/src/com/android/settings/wifi/calling/WifiCallingDisclaimerFragment.java
new file mode 100644
index 0000000..7763226
--- /dev/null
+++ b/src/com/android/settings/wifi/calling/WifiCallingDisclaimerFragment.java
@@ -0,0 +1,148 @@
+/*
+ * 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.calling;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.telephony.SubscriptionManager;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+
+import androidx.recyclerview.widget.DividerItemDecoration;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.recyclerview.widget.RecyclerView.OnScrollListener;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settings.R;
+import com.android.settings.core.InstrumentedFragment;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Fragment for displaying disclaimers for WFC.
+ */
+public class WifiCallingDisclaimerFragment extends InstrumentedFragment
+        implements View.OnClickListener {
+    private static final String TAG = "WifiCallingDisclaimerFragment";
+
+    private static final String STATE_IS_SCROLL_TO_BOTTOM = "state_is_scroll_to_bottom";
+
+    private List<DisclaimerItem> mDisclaimerItemList = new ArrayList<DisclaimerItem>();
+    private Button mAgreeButton;
+    private Button mDisagreeButton;
+    private boolean mScrollToBottom;
+
+    @Override
+    public int getMetricsCategory() {
+        return MetricsEvent.WIFI_CALLING;
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        final Bundle args = getArguments();
+        final int subId = (args != null) ? args.getInt(WifiCallingSettingsForSub.EXTRA_SUB_ID)
+                : SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
+
+        mDisclaimerItemList = DisclaimerItemFactory.create(getActivity(), subId);
+        if (mDisclaimerItemList.isEmpty()) {
+            finish(Activity.RESULT_OK);
+            return;
+        }
+
+        if (savedInstanceState != null) {
+            mScrollToBottom = savedInstanceState.getBoolean(
+                    STATE_IS_SCROLL_TO_BOTTOM, mScrollToBottom);
+        }
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+
+        final View view = inflater.inflate(R.layout.wfc_disclaimer_fragment, container, false);
+
+        mAgreeButton = view.findViewById(R.id.agree_button);
+        mAgreeButton.setOnClickListener(this);
+        mDisagreeButton = view.findViewById(R.id.disagree_button);
+        mDisagreeButton.setOnClickListener(this);
+
+        final RecyclerView recyclerView = (RecyclerView) view.findViewById(
+                R.id.disclaimer_item_list);
+        recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
+        recyclerView.setAdapter(new DisclaimerItemListAdapter(mDisclaimerItemList));
+
+        RecyclerView.ItemDecoration itemDecoration =
+                new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL);
+        recyclerView.addItemDecoration(itemDecoration);
+
+        recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
+            @Override
+            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
+                super.onScrolled(recyclerView, dx, dy);
+                if (!recyclerView.canScrollVertically(1 /* scrolling down */)) {
+                    mScrollToBottom = true;
+                    updateButtonState();
+                    recyclerView.removeOnScrollListener(this);
+                }
+            }
+        });
+
+        return view;
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        updateButtonState();
+    }
+
+    @Override
+    public void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+        outState.putBoolean(STATE_IS_SCROLL_TO_BOTTOM, mScrollToBottom);
+    }
+
+    private void updateButtonState() {
+        mAgreeButton.setEnabled(mScrollToBottom);
+    }
+
+    @Override
+    public void onClick(View v) {
+        if (v == mAgreeButton) {
+            for (DisclaimerItem item : mDisclaimerItemList) {
+                item.onAgreed();
+            }
+            finish(Activity.RESULT_OK);
+        } else if (v == mDisagreeButton) {
+            finish(Activity.RESULT_CANCELED);
+        }
+    }
+
+    @VisibleForTesting
+    void finish(int result) {
+        Activity activity = getActivity();
+        activity.setResult(result, null);
+        activity.finish();
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/wifi/calling/WifiCallingSettingsForSub.java b/src/com/android/settings/wifi/calling/WifiCallingSettingsForSub.java
index 4255f3c..525b59b 100644
--- a/src/com/android/settings/wifi/calling/WifiCallingSettingsForSub.java
+++ b/src/com/android/settings/wifi/calling/WifiCallingSettingsForSub.java
@@ -40,7 +40,6 @@
 import android.widget.TextView;
 
 import androidx.appcompat.app.AlertDialog;
-import androidx.preference.ListPreference;
 import androidx.preference.Preference;
 import androidx.preference.Preference.OnPreferenceClickListener;
 import androidx.preference.PreferenceScreen;
@@ -54,6 +53,7 @@
 import com.android.settings.SettingsActivity;
 import com.android.settings.SettingsPreferenceFragment;
 import com.android.settings.Utils;
+import com.android.settings.core.SubSettingLauncher;
 import com.android.settings.widget.SwitchBar;
 
 /**
@@ -70,9 +70,13 @@
     private static final String BUTTON_WFC_ROAMING_MODE = "wifi_calling_roaming_mode";
     private static final String PREFERENCE_EMERGENCY_ADDRESS = "emergency_address_key";
 
-    private static final int REQUEST_CHECK_WFC_EMERGENCY_ADDRESS = 1;
+    @VisibleForTesting
+    static final int REQUEST_CHECK_WFC_EMERGENCY_ADDRESS = 1;
+    @VisibleForTesting
+    static final int REQUEST_CHECK_WFC_DISCLAIMER = 2;
 
     public static final String EXTRA_LAUNCH_CARRIER_APP = "EXTRA_LAUNCH_CARRIER_APP";
+    public static final String EXTRA_SUB_ID = "EXTRA_SUB_ID";
 
     protected static final String FRAGMENT_BUNDLE_SUBID = "subId";
 
@@ -141,20 +145,17 @@
         }
     };
 
+    /*
+     * Launch carrier emergency address managemnent activity
+     */
     private final OnPreferenceClickListener mUpdateAddressListener =
-            new OnPreferenceClickListener() {
-                /*
-                 * Launch carrier emergency address managemnent activity
-                 */
-                @Override
-                public boolean onPreferenceClick(Preference preference) {
-                    Intent carrierAppIntent = getCarrierActivityIntent();
-                    if (carrierAppIntent != null) {
-                        carrierAppIntent.putExtra(EXTRA_LAUNCH_CARRIER_APP, LAUCH_APP_UPDATE);
-                        startActivity(carrierAppIntent);
-                    }
-                    return true;
+            preference -> {
+                Intent carrierAppIntent = getCarrierActivityIntent();
+                if (carrierAppIntent != null) {
+                    carrierAppIntent.putExtra(EXTRA_LAUNCH_CARRIER_APP, LAUCH_APP_UPDATE);
+                    startActivity(carrierAppIntent);
                 }
+                return true;
             };
 
     private final ProvisioningManager.Callback mProvisioningCallback =
@@ -174,11 +175,9 @@
     public void onActivityCreated(Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
 
-        final SettingsActivity activity = (SettingsActivity) getActivity();
-
         mEmptyView = getView().findViewById(android.R.id.empty);
         setEmptyView(mEmptyView);
-        final Resources res = SubscriptionManager.getResourcesForSubId(getContext(), mSubId);
+        final Resources res = getResourcesForSubId();
         String emptyViewText = res.getString(R.string.wifi_calling_off_explanation,
                 res.getString(R.string.wifi_calling_off_explanation_2));
         mEmptyView.setText(emptyViewText);
@@ -265,14 +264,13 @@
         mTelephonyManager = ((TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE))
                 .createForSubscriptionId(mSubId);
 
-        mButtonWfcMode = (ListWithEntrySummaryPreference) findPreference(BUTTON_WFC_MODE);
+        mButtonWfcMode = findPreference(BUTTON_WFC_MODE);
         mButtonWfcMode.setOnPreferenceChangeListener(this);
 
-        mButtonWfcRoamingMode = (ListWithEntrySummaryPreference) findPreference(
-                BUTTON_WFC_ROAMING_MODE);
+        mButtonWfcRoamingMode =  findPreference(BUTTON_WFC_ROAMING_MODE);
         mButtonWfcRoamingMode.setOnPreferenceChangeListener(this);
 
-        mUpdateAddress = (Preference) findPreference(PREFERENCE_EMERGENCY_ADDRESS);
+        mUpdateAddress = findPreference(PREFERENCE_EMERGENCY_ADDRESS);
         mUpdateAddress.setOnPreferenceClickListener(mUpdateAddressListener);
 
         mIntentFilter = new IntentFilter();
@@ -423,14 +421,17 @@
             return;
         }
 
-        // Call address management activity before turning on WFC
-        Intent carrierAppIntent = getCarrierActivityIntent();
-        if (carrierAppIntent != null) {
-            carrierAppIntent.putExtra(EXTRA_LAUNCH_CARRIER_APP, LAUCH_APP_ACTIVATE);
-            startActivityForResult(carrierAppIntent, REQUEST_CHECK_WFC_EMERGENCY_ADDRESS);
-        } else {
-            updateWfcMode(true);
-        }
+        // Launch disclaimer fragment before turning on WFC
+        final Context context = getActivity();
+        final Bundle args = new Bundle();
+        args.putInt(EXTRA_SUB_ID, mSubId);
+        new SubSettingLauncher(context)
+                .setDestination(WifiCallingDisclaimerFragment.class.getName())
+                .setArguments(args)
+                .setTitleRes(R.string.wifi_calling_settings_title)
+                .setSourceMetricsCategory(getMetricsCategory())
+                .setResultListener(this, REQUEST_CHECK_WFC_DISCLAIMER)
+                .launch();
     }
 
     /*
@@ -483,12 +484,30 @@
 
         final Context context = getActivity();
 
-        if (requestCode == REQUEST_CHECK_WFC_EMERGENCY_ADDRESS) {
-            Log.d(TAG, "WFC emergency address activity result = " + resultCode);
+        Log.d(TAG, "WFC activity request = " + requestCode + " result = " + resultCode);
 
-            if (resultCode == Activity.RESULT_OK) {
-                updateWfcMode(true);
-            }
+        switch (requestCode) {
+            case REQUEST_CHECK_WFC_EMERGENCY_ADDRESS:
+                if (resultCode == Activity.RESULT_OK) {
+                    updateWfcMode(true);
+                }
+                break;
+            case REQUEST_CHECK_WFC_DISCLAIMER:
+                if (resultCode == Activity.RESULT_OK) {
+                    // Call address management activity before turning on WFC
+                    Intent carrierAppIntent = getCarrierActivityIntent();
+                    if (carrierAppIntent != null) {
+                        carrierAppIntent.putExtra(EXTRA_LAUNCH_CARRIER_APP, LAUCH_APP_ACTIVATE);
+                        startActivityForResult(carrierAppIntent,
+                                REQUEST_CHECK_WFC_EMERGENCY_ADDRESS);
+                    } else {
+                        updateWfcMode(true);
+                    }
+                }
+                break;
+            default:
+                Log.e(TAG, "Unexpected request: " + requestCode);
+                break;
         }
     }
 
@@ -575,4 +594,9 @@
         }
         return resId;
     }
+
+    @VisibleForTesting
+    Resources getResourcesForSubId() {
+        return SubscriptionManager.getResourcesForSubId(getContext(), mSubId, false);
+    }
 }
diff --git a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
index 89565df..5588977 100644
--- a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
+++ b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
@@ -66,6 +66,7 @@
 import com.android.settings.wifi.WifiDialog.WifiDialogListener;
 import com.android.settings.wifi.WifiUtils;
 import com.android.settings.wifi.dpp.WifiDppUtils;
+import com.android.settings.wifi.savedaccesspoints.SavedAccessPointsWifiSettings;
 import com.android.settingslib.core.AbstractPreferenceController;
 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
 import com.android.settingslib.core.lifecycle.Lifecycle;
@@ -75,6 +76,8 @@
 import com.android.settingslib.widget.ActionButtonsPreference;
 import com.android.settingslib.widget.LayoutPreference;
 import com.android.settingslib.wifi.AccessPoint;
+import com.android.settingslib.wifi.WifiTracker;
+import com.android.settingslib.wifi.WifiTrackerFactory;
 
 import java.net.Inet4Address;
 import java.net.Inet6Address;
@@ -136,7 +139,9 @@
     private WifiConfiguration mWifiConfig;
     private WifiInfo mWifiInfo;
     private final WifiManager mWifiManager;
+    private final WifiTracker mWifiTracker;
     private final MetricsFeatureProvider mMetricsFeatureProvider;
+    private boolean mIsOutOfRange;
 
     // UI elements - in order of appearance
     private ActionButtonsPreference mButtonsPref;
@@ -176,7 +181,7 @@
                     // fall through
                 case WifiManager.NETWORK_STATE_CHANGED_ACTION:
                 case WifiManager.RSSI_CHANGED_ACTION:
-                    updateLiveNetworkInfo();
+                    updateNetworkInfo();
                     break;
             }
         }
@@ -206,14 +211,16 @@
         @Override
         public void onCapabilitiesChanged(Network network, NetworkCapabilities nc) {
             // If the network just validated or lost Internet access, refresh network state.
-            // Don't do this on every NetworkCapabilities change because refreshNetworkState
-            // sends IPCs to the system server from the UI thread, which can cause jank.
+            // Don't do this on every NetworkCapabilities change because update accesspoint notify
+            // changed for accesspoint changed on the main thread, which can cause jank.
             if (network.equals(mNetwork) && !nc.equals(mNetworkCapabilities)) {
                 if (hasCapabilityChanged(nc, NET_CAPABILITY_VALIDATED) ||
                         hasCapabilityChanged(nc, NET_CAPABILITY_CAPTIVE_PORTAL)) {
-                    refreshNetworkState();
+                    mAccessPoint.update(mWifiConfig, mWifiInfo, mNetworkInfo);
+                    refreshEntityHeader();
                 }
                 mNetworkCapabilities = nc;
+                refreshButtons();
                 updateIpLayerInfo();
             }
         }
@@ -226,6 +233,29 @@
         }
     };
 
+    private final WifiTracker.WifiListener mWifiListener = new WifiTracker.WifiListener() {
+        /** Called when the state of Wifi has changed. */
+        public void onWifiStateChanged(int state) {
+            Log.d(TAG, "onWifiStateChanged(" + state + ")");
+            // Do nothing.
+        }
+
+        /** Called when the connection state of wifi has changed. */
+        public void onConnectedChanged() {
+            Log.d(TAG, "onConnectedChanged");
+            // Do nothing.
+        }
+
+        /**
+         * Called to indicate the list of AccessPoints has been updated and
+         * {@link WifiTracker#getAccessPoints()} should be called to get the updated list.
+         */
+        public void onAccessPointsChanged() {
+            Log.d(TAG, "onAccessPointsChanged");
+            updateNetworkInfo();
+        }
+    };
+
     public static WifiDetailPreferenceController newInstance(
             AccessPoint accessPoint,
             ConnectivityManager connectivityManager,
@@ -270,6 +300,17 @@
 
         mLifecycle = lifecycle;
         lifecycle.addObserver(this);
+
+        if (SavedAccessPointsWifiSettings.usingDetailsFragment(mContext)) {
+            mWifiTracker = WifiTrackerFactory.create(
+                    mFragment.getActivity(),
+                    mWifiListener,
+                    mLifecycle,
+                    true /*includeSaved*/,
+                    true /*includeScans*/);
+        } else {
+            mWifiTracker = null;
+        }
     }
 
     @Override
@@ -360,7 +401,7 @@
         mNetwork = mWifiManager.getCurrentNetwork();
         mLinkProperties = mConnectivityManager.getLinkProperties(mNetwork);
         mNetworkCapabilities = mConnectivityManager.getNetworkCapabilities(mNetwork);
-        updateLiveNetworkInfo();
+        updateNetworkInfo();
         mContext.registerReceiver(mReceiver, mFilter);
         mConnectivityManager.registerNetworkCallback(mNetworkRequest, mNetworkCallback,
                 mHandler);
@@ -377,72 +418,73 @@
         mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
     }
 
-    // TODO(b/124707751): Refactoring the code later, keeping it currently for stability.
-    protected void updateSavedNetworkInfo() {
-        mSignalStrengthPref.setVisible(false);
-        mFrequencyPref.setVisible(false);
-        mTxLinkSpeedPref.setVisible(false);
-        mRxLinkSpeedPref.setVisible(false);
-
-        // MAC Address Pref
-        mMacAddressPref.setSummary(mWifiConfig.getRandomizedMacAddress().toString());
-
-        refreshEntityHeader();
-
-        updateIpLayerInfo();
-
-        // Update whether the forget button should be displayed.
-        mButtonsPref.setButton1Visible(canForgetNetwork());
-    }
-
-    private void updateLiveNetworkInfo() {
-        // No need to fetch LinkProperties and NetworkCapabilities, they are updated by the
-        // callbacks. mNetwork doesn't change except in onResume.
-        mNetworkInfo = mConnectivityManager.getNetworkInfo(mNetwork);
-        mWifiInfo = mWifiManager.getConnectionInfo();
-        if (mNetwork == null || mNetworkInfo == null || mWifiInfo == null) {
-            exitActivity();
+    private void updateNetworkInfo() {
+        if(!updateAccessPoint()) {
             return;
         }
 
-        // Update whether the forget button should be displayed.
-        mButtonsPref.setButton1Visible(canForgetNetwork());
+        // refresh header
+        refreshEntityHeader();
 
-        refreshNetworkState();
+        // refresh Buttons
+        refreshButtons();
 
         // Update Connection Header icon and Signal Strength Preference
         refreshRssiViews();
-
-        // MAC Address Pref
-        mMacAddressPref.setSummary(mWifiInfo.getMacAddress());
-
-        // Transmit Link Speed Pref
-        int txLinkSpeedMbps = mWifiInfo.getTxLinkSpeedMbps();
-        mTxLinkSpeedPref.setVisible(txLinkSpeedMbps >= 0);
-        mTxLinkSpeedPref.setSummary(mContext.getString(
-                R.string.tx_link_speed, mWifiInfo.getTxLinkSpeedMbps()));
-
-        // Receive Link Speed Pref
-        int rxLinkSpeedMbps = mWifiInfo.getRxLinkSpeedMbps();
-        mRxLinkSpeedPref.setVisible(rxLinkSpeedMbps >= 0);
-        mRxLinkSpeedPref.setSummary(mContext.getString(
-                R.string.rx_link_speed, mWifiInfo.getRxLinkSpeedMbps()));
-
         // Frequency Pref
-        final int frequency = mWifiInfo.getFrequency();
-        String band = null;
-        if (frequency >= AccessPoint.LOWER_FREQ_24GHZ
-                && frequency < AccessPoint.HIGHER_FREQ_24GHZ) {
-            band = mContext.getResources().getString(R.string.wifi_band_24ghz);
-        } else if (frequency >= AccessPoint.LOWER_FREQ_5GHZ
-                && frequency < AccessPoint.HIGHER_FREQ_5GHZ) {
-            band = mContext.getResources().getString(R.string.wifi_band_5ghz);
-        } else {
-            Log.e(TAG, "Unexpected frequency " + frequency);
-        }
-        mFrequencyPref.setSummary(band);
-
+        refreshFrequency();
+        // Transmit Link Speed Pref
+        refreshTxSpeed();
+        // Receive Link Speed Pref
+        refreshRxSpeed();
+        // IP related information
         updateIpLayerInfo();
+        // MAC Address Pref
+        refreshMacAddress();
+
+    }
+
+    private boolean updateAccessPoint() {
+        boolean changed = false;
+        if (mWifiTracker != null) {
+            updateAccessPointFromScannedList();
+            // refresh UI if signal level changed for disconnect network.
+            changed = mRssiSignalLevel != mAccessPoint.getLevel();
+        }
+
+        if (mAccessPoint.isActive()) {
+            // No need to fetch LinkProperties and NetworkCapabilities, they are updated by the
+            // callbacks. mNetwork doesn't change except in onResume.
+            mNetworkInfo = mConnectivityManager.getNetworkInfo(mNetwork);
+            mWifiInfo = mWifiManager.getConnectionInfo();
+            if (mNetwork == null || mNetworkInfo == null || mWifiInfo == null) {
+                exitActivity();
+                return false;
+            }
+
+            changed |= mAccessPoint.update(mWifiConfig, mWifiInfo, mNetworkInfo);
+            // If feature for saved network not enabled, always return true.
+            return mWifiTracker == null || changed;
+        }
+
+        return changed;
+    }
+
+    private void updateAccessPointFromScannedList() {
+        mIsOutOfRange = true;
+
+        if (mAccessPoint.getConfig() == null) {
+            return;
+        }
+
+        for (AccessPoint ap : mWifiTracker.getAccessPoints()) {
+            if (ap.getConfig() != null
+                    && mAccessPoint.matches(ap.getConfig())) {
+                mAccessPoint = ap;
+                mIsOutOfRange = false;
+                return;
+            }
+        }
     }
 
     private void exitActivity() {
@@ -452,14 +494,16 @@
         mFragment.getActivity().finish();
     }
 
-    private void refreshNetworkState() {
-        mAccessPoint.update(mWifiConfig, mWifiInfo, mNetworkInfo);
-        refreshEntityHeader();
-    }
-
     private void refreshRssiViews() {
         int signalLevel = mAccessPoint.getLevel();
 
+        // Disappears signal view if not in range. e.g. for saved networks.
+        if (mIsOutOfRange) {
+            mSignalStrengthPref.setVisible(false);
+            mRssiSignalLevel = -1;
+            return;
+        }
+
         if (mRssiSignalLevel == signalLevel) {
             return;
         }
@@ -477,6 +521,84 @@
         mSignalStrengthPref.setIcon(wifiIconDark);
 
         mSignalStrengthPref.setSummary(mSignalStr[mRssiSignalLevel]);
+        mSignalStrengthPref.setVisible(true);
+    }
+
+    private void refreshFrequency() {
+        if (mWifiInfo == null) {
+            mFrequencyPref.setVisible(false);
+            return;
+        }
+
+        final int frequency = mWifiInfo.getFrequency();
+        String band = null;
+        if (frequency >= AccessPoint.LOWER_FREQ_24GHZ
+                && frequency < AccessPoint.HIGHER_FREQ_24GHZ) {
+            band = mContext.getResources().getString(R.string.wifi_band_24ghz);
+        } else if (frequency >= AccessPoint.LOWER_FREQ_5GHZ
+                && frequency < AccessPoint.HIGHER_FREQ_5GHZ) {
+            band = mContext.getResources().getString(R.string.wifi_band_5ghz);
+        } else {
+            Log.e(TAG, "Unexpected frequency " + frequency);
+        }
+        mFrequencyPref.setSummary(band);
+        mFrequencyPref.setVisible(true);
+    }
+
+    private void refreshTxSpeed() {
+        if (mWifiInfo == null) {
+            mTxLinkSpeedPref.setVisible(false);
+            return;
+        }
+
+        int txLinkSpeedMbps = mWifiInfo.getTxLinkSpeedMbps();
+        mTxLinkSpeedPref.setVisible(txLinkSpeedMbps >= 0);
+        mTxLinkSpeedPref.setSummary(mContext.getString(
+                R.string.tx_link_speed, mWifiInfo.getTxLinkSpeedMbps()));
+    }
+
+    private void refreshRxSpeed() {
+        if (mWifiInfo == null) {
+            mRxLinkSpeedPref.setVisible(false);
+            return;
+        }
+
+        int rxLinkSpeedMbps = mWifiInfo.getRxLinkSpeedMbps();
+        mRxLinkSpeedPref.setVisible(rxLinkSpeedMbps >= 0);
+        mRxLinkSpeedPref.setSummary(mContext.getString(
+                R.string.rx_link_speed, mWifiInfo.getRxLinkSpeedMbps()));
+    }
+
+    private void refreshMacAddress() {
+        String macAddress = getMacAddress();
+        if (macAddress == null) {
+            mMacAddressPref.setVisible(false);
+            return;
+        }
+
+        mMacAddressPref.setVisible(true);
+        mMacAddressPref.setSummary(macAddress);
+    }
+
+    private String getMacAddress() {
+        if (mWifiInfo != null) {
+            // get MAC address from connected network information
+            return mWifiInfo.getMacAddress();
+        }
+
+        // return randomized MAC address
+        if (mWifiConfig.macRandomizationSetting == WifiConfiguration.RANDOMIZATION_PERSISTENT) {
+            return mWifiConfig.getRandomizedMacAddress().toString();
+        }
+
+        // return device MAC address
+        final String[] macAddresses = mWifiManager.getFactoryMacAddresses();
+        if (macAddresses != null && macAddresses.length > 0) {
+            return macAddresses[0];
+        }
+
+        Log.e(TAG, "Can't get device MAC address!");
+        return null;
     }
 
     private void updatePreference(Preference pref, String detailText) {
@@ -488,13 +610,17 @@
         }
     }
 
-    private void updateIpLayerInfo() {
+    private void refreshButtons() {
+        mButtonsPref.setButton1Visible(canForgetNetwork());
         mButtonsPref.setButton2Visible(canSignIntoNetwork());
         mButtonsPref.setButton3Visible(canShareNetwork());
         mButtonsPref.setVisible(
                 canSignIntoNetwork() || canForgetNetwork() || canShareNetwork());
+    }
 
-        if (mNetwork == null || mLinkProperties == null) {
+    private void updateIpLayerInfo() {
+        // Hide IP layer info if not a connected network.
+        if (!mAccessPoint.isActive() || mNetwork == null || mLinkProperties == null) {
             mIpAddressPref.setVisible(false);
             mSubnetPref.setVisible(false);
             mGatewayPref.setVisible(false);
diff --git a/src/com/android/settings/wifi/details/WifiDetailSavedNetworkPreferenceController.java b/src/com/android/settings/wifi/details/WifiDetailSavedNetworkPreferenceController.java
deleted file mode 100644
index 3407890..0000000
--- a/src/com/android/settings/wifi/details/WifiDetailSavedNetworkPreferenceController.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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.wifi.details;
-
-import android.content.Context;
-import android.net.ConnectivityManager;
-import android.net.wifi.WifiManager;
-import android.os.Handler;
-
-import androidx.fragment.app.Fragment;
-
-import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
-import com.android.settingslib.core.lifecycle.Lifecycle;
-import com.android.settingslib.wifi.AccessPoint;
-
-public class WifiDetailSavedNetworkPreferenceController extends WifiDetailPreferenceController {
-
-    WifiDetailSavedNetworkPreferenceController(AccessPoint accessPoint,
-            ConnectivityManager connectivityManager, Context context,
-            Fragment fragment, Handler handler,
-            Lifecycle lifecycle,
-            WifiManager wifiManager,
-            MetricsFeatureProvider metricsFeatureProvider,
-            IconInjector injector) {
-        super(accessPoint, connectivityManager, context, fragment, handler, lifecycle, wifiManager,
-                metricsFeatureProvider, injector);
-    }
-
-    public static WifiDetailSavedNetworkPreferenceController newInstance(
-            AccessPoint accessPoint,
-            ConnectivityManager connectivityManager,
-            Context context,
-            Fragment fragment,
-            Handler handler,
-            Lifecycle lifecycle,
-            WifiManager wifiManager,
-            MetricsFeatureProvider metricsFeatureProvider) {
-        return new WifiDetailSavedNetworkPreferenceController(
-                accessPoint, connectivityManager, context, fragment, handler, lifecycle,
-                wifiManager, metricsFeatureProvider, new IconInjector(context));
-    }
-
-    @Override
-    public void onPause() {
-        // Do nothing
-    }
-
-    @Override
-    public void onResume() {
-        updateSavedNetworkInfo();
-    }
-}
diff --git a/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java b/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
index 7edd227..66587ed 100644
--- a/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
+++ b/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
@@ -51,9 +51,6 @@
 
     private static final String TAG = "WifiNetworkDetailsFrg";
 
-    // Extra for if current fragment shows saved network status or not.
-    public static final String EXTRA_IS_SAVED_NETWORK = "SavedNetwork";
-
     private AccessPoint mAccessPoint;
     private WifiDetailPreferenceController mWifiDetailPreferenceController;
 
@@ -126,30 +123,15 @@
         final List<AbstractPreferenceController> controllers = new ArrayList<>();
         final ConnectivityManager cm = context.getSystemService(ConnectivityManager.class);
 
-        final boolean isDisplaySavedNetworkDetails =
-                getArguments().getBoolean(EXTRA_IS_SAVED_NETWORK, false /* defaultValue */);
-        if (isDisplaySavedNetworkDetails) {
-            mWifiDetailPreferenceController =
-                    WifiDetailSavedNetworkPreferenceController.newInstance(
-                            mAccessPoint,
-                            cm,
-                            context,
-                            this,
-                            new Handler(Looper.getMainLooper()),  // UI thread.
-                            getSettingsLifecycle(),
-                            context.getSystemService(WifiManager.class),
-                            mMetricsFeatureProvider);
-        } else {
-            mWifiDetailPreferenceController = WifiDetailPreferenceController.newInstance(
-                    mAccessPoint,
-                    cm,
-                    context,
-                    this,
-                    new Handler(Looper.getMainLooper()),  // UI thread.
-                    getSettingsLifecycle(),
-                    context.getSystemService(WifiManager.class),
-                    mMetricsFeatureProvider);
-        }
+        mWifiDetailPreferenceController = WifiDetailPreferenceController.newInstance(
+                mAccessPoint,
+                cm,
+                context,
+                this,
+                new Handler(Looper.getMainLooper()),  // UI thread.
+                getSettingsLifecycle(),
+                context.getSystemService(WifiManager.class),
+                mMetricsFeatureProvider);
 
         controllers.add(mWifiDetailPreferenceController);
         controllers.add(new WifiMeteredPreferenceController(context, mAccessPoint.getConfig()));
diff --git a/src/com/android/settings/wifi/details/WifiPrivacyPreferenceController.java b/src/com/android/settings/wifi/details/WifiPrivacyPreferenceController.java
index 97ddc53..a549e21 100644
--- a/src/com/android/settings/wifi/details/WifiPrivacyPreferenceController.java
+++ b/src/com/android/settings/wifi/details/WifiPrivacyPreferenceController.java
@@ -59,7 +59,7 @@
     @Override
     public int getAvailabilityStatus() {
         return mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_wifi_p2p_mac_randomization_supported) ?
+                com.android.internal.R.bool.config_wifi_connected_mac_randomization_supported) ?
                 AVAILABLE : CONDITIONALLY_UNAVAILABLE;
     }
 
diff --git a/src/com/android/settings/wifi/dpp/WifiNetworkListFragment.java b/src/com/android/settings/wifi/dpp/WifiNetworkListFragment.java
index 4688d76..84f1c36 100644
--- a/src/com/android/settings/wifi/dpp/WifiNetworkListFragment.java
+++ b/src/com/android/settings/wifi/dpp/WifiNetworkListFragment.java
@@ -34,11 +34,14 @@
 import com.android.settings.SettingsPreferenceFragment;
 import com.android.settings.core.SubSettingLauncher;
 import com.android.settings.wifi.AddNetworkFragment;
+import com.android.settings.wifi.savedaccesspoints.SavedNetworkComparator;
 import com.android.settingslib.wifi.AccessPoint;
 import com.android.settingslib.wifi.AccessPointPreference;
+import com.android.settingslib.wifi.WifiSavedConfigUtils;
 import com.android.settingslib.wifi.WifiTracker;
 import com.android.settingslib.wifi.WifiTrackerFactory;
 
+import java.util.Collections;
 import java.util.List;
 
 public class WifiNetworkListFragment extends SettingsPreferenceFragment implements
@@ -256,17 +259,6 @@
             return false;
         }
 
-        // Can only use saved network for DPP configuration. For ephemeral connections networkId
-        // is invalid.
-        if (!accessPoint.isSaved()) {
-            return false;
-        }
-
-        // Ignore access points that are out of range.
-        if (!accessPoint.isReachable()) {
-            return false;
-        }
-
         return true;
     }
 
@@ -290,44 +282,47 @@
             return;
         }
 
-        // AccessPoints are sorted by the WifiTracker
-        final List<AccessPoint> accessPoints = mWifiTracker.getAccessPoints();
-
-        mAccessPointsPreferenceCategory.setVisible(true);
-
-        cacheRemoveAllPrefs(mAccessPointsPreferenceCategory);
+        // TODO(b/128942314): Lists reachable AccessPoints on top of the list
+        final List<AccessPoint> savedAccessPoints =
+                WifiSavedConfigUtils.getAllConfigs(getContext(), mWifiManager);
+        Collections.sort(savedAccessPoints, SavedNetworkComparator.INSTANCE);
 
         int index = 0;
-        for (; index < accessPoints.size(); index++) {
-            AccessPoint accessPoint = accessPoints.get(index);
-            // Check if this access point is valid for DPP.
-            if (isValidForDppConfiguration(accessPoint)) {
-                final String key = accessPoint.getKey();
+        mAccessPointsPreferenceCategory.removeAll();
+        for (AccessPoint savedAccessPoint : savedAccessPoints) {
+            if (isValidForDppConfiguration(savedAccessPoint)) {
+                // Replaces with an AccessPoint from scanned result for signal information
+                savedAccessPoint = getScannedAccessPointIfAvailable(savedAccessPoint);
+                final AccessPointPreference preference =
+                        createAccessPointPreference(savedAccessPoint);
 
-                final AccessPointPreference pref = (AccessPointPreference) getCachedPreference(key);
-                if (pref != null) {
-                    pref.setOrder(index);
-                    continue;
-                }
-                final AccessPointPreference preference = createAccessPointPreference(accessPoint);
-                preference.setKey(key);
-                preference.setOrder(index);
+                preference.setOrder(index++);
+                preference.setEnabled(savedAccessPoint.isReachable());
+                savedAccessPoint.setListener(this);
 
-                mAccessPointsPreferenceCategory.addPreference(preference);
-                accessPoint.setListener(this);
                 preference.refresh();
+                mAccessPointsPreferenceCategory.addPreference(preference);
             }
         }
-        removeCachedPrefs(mAccessPointsPreferenceCategory);
         mAddPreference.setOrder(index);
         mAccessPointsPreferenceCategory.addPreference(mAddPreference);
 
         if (mIsTest) {
-            mFakeNetworkPreference.setOrder(index + 1);
             mAccessPointsPreferenceCategory.addPreference(mFakeNetworkPreference);
         }
     }
 
+    private AccessPoint getScannedAccessPointIfAvailable(AccessPoint savedAccessPoint) {
+        final List<AccessPoint> scannedAccessPoints = mWifiTracker.getAccessPoints();
+        final WifiConfiguration savedWifiConfiguration = savedAccessPoint.getConfig();
+        for (AccessPoint scannedAccessPoint : scannedAccessPoints) {
+            if (scannedAccessPoint.matches(savedWifiConfiguration)) {
+                return scannedAccessPoint;
+            }
+        }
+        return savedAccessPoint;
+    }
+
     private AccessPointPreference createAccessPointPreference(AccessPoint accessPoint) {
         return new AccessPointPreference(accessPoint, getPrefContext(), mUserBadgeCache,
                 R.drawable.ic_wifi_signal_0, /* forSavedNetworks */ false);
diff --git a/src/com/android/settings/wifi/savedaccesspoints/SavedAccessPointsWifiSettings.java b/src/com/android/settings/wifi/savedaccesspoints/SavedAccessPointsWifiSettings.java
index ea858f3..3f600e6 100644
--- a/src/com/android/settings/wifi/savedaccesspoints/SavedAccessPointsWifiSettings.java
+++ b/src/com/android/settings/wifi/savedaccesspoints/SavedAccessPointsWifiSettings.java
@@ -108,7 +108,6 @@
             }
             final Bundle savedState = new Bundle();
             mSelectedAccessPoint.saveWifiState(savedState);
-            savedState.putBoolean(WifiNetworkDetailsFragment.EXTRA_IS_SAVED_NETWORK, true);
 
             new SubSettingLauncher(getContext())
                     .setTitleText(mSelectedAccessPoint.getTitle())
diff --git a/src/com/android/settings/wifi/slice/ContextualWifiSlice.java b/src/com/android/settings/wifi/slice/ContextualWifiSlice.java
index fa8c267..4a799d1 100644
--- a/src/com/android/settings/wifi/slice/ContextualWifiSlice.java
+++ b/src/com/android/settings/wifi/slice/ContextualWifiSlice.java
@@ -25,6 +25,7 @@
 import androidx.annotation.VisibleForTesting;
 import androidx.slice.Slice;
 
+import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.slices.CustomSliceRegistry;
 import com.android.settings.slices.CustomSliceable;
 
@@ -35,7 +36,9 @@
 
     private static final String TAG = "ContextualWifiSlice";
     @VisibleForTesting
-    boolean mPreviouslyDisplayed;
+    static long sActiveUiSession = -1000;
+    @VisibleForTesting
+    static boolean sPreviouslyDisplayed;
 
     public ContextualWifiSlice(Context context) {
         super(context);
@@ -48,13 +51,19 @@
 
     @Override
     public Slice getSlice() {
-        if (!mPreviouslyDisplayed && !TextUtils.equals(getActiveSSID(), WifiSsid.NONE)) {
+        final long currentUiSession = FeatureFactory.getFactory(mContext)
+                .getSlicesFeatureProvider().getUiSessionToken();
+        if (currentUiSession != sActiveUiSession) {
+            sActiveUiSession = currentUiSession;
+            sPreviouslyDisplayed = false;
+        }
+        if (!sPreviouslyDisplayed && !TextUtils.equals(getActiveSSID(), WifiSsid.NONE)) {
             Log.d(TAG, "Wifi is connected, no point showing any suggestion.");
             return null;
         }
-        // Set mPreviouslyDisplayed to true - we will show *something* on the screen. So we should
+        // Set sPreviouslyDisplayed to true - we will show *something* on the screen. So we should
         // keep showing this card to keep UI stable, even if wifi connects to a network later.
-        mPreviouslyDisplayed = true;
+        sPreviouslyDisplayed = true;
 
         return super.getSlice();
     }
diff --git a/src/com/android/settings/wifi/slice/WifiSlice.java b/src/com/android/settings/wifi/slice/WifiSlice.java
index a2debb8..1c44204 100644
--- a/src/com/android/settings/wifi/slice/WifiSlice.java
+++ b/src/com/android/settings/wifi/slice/WifiSlice.java
@@ -32,6 +32,7 @@
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.net.NetworkInfo;
+import android.net.NetworkInfo.State;
 import android.net.Uri;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
@@ -355,7 +356,6 @@
 
         @Override
         public void onConnectedChanged() {
-            notifySliceChange();
         }
 
         @Override
@@ -370,10 +370,43 @@
             final List<AccessPoint> resultList = new ArrayList<>();
             for (AccessPoint ap : accessPoints) {
                 if (ap.isReachable()) {
-                    resultList.add(ap);
+                    resultList.add(clone(ap));
+                    if (resultList.size() >= DEFAULT_EXPANDED_ROW_COUNT) {
+                        break;
+                    }
                 }
             }
             updateResults(resultList);
         }
+
+        private AccessPoint clone(AccessPoint accessPoint) {
+            final Bundle savedState = new Bundle();
+            accessPoint.saveWifiState(savedState);
+            return new AccessPoint(mContext, savedState);
+        }
+
+        @Override
+        protected boolean areListsTheSame(List<AccessPoint> a, List<AccessPoint> b) {
+            if (!a.equals(b)) {
+                return false;
+            }
+
+            // compare access point states one by one
+            final int listSize = a.size();
+            for (int i = 0; i < listSize; i++) {
+                if (getState(a.get(i)) != getState(b.get(i))) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        private State getState(AccessPoint accessPoint) {
+            final NetworkInfo networkInfo = accessPoint.getNetworkInfo();
+            if (networkInfo != null) {
+                return networkInfo.getState();
+            }
+            return null;
+        }
     }
 }
diff --git a/tests/robotests/res/values-mcc999/config.xml b/tests/robotests/res/values-mcc999/config.xml
index 776a4d0..1fe4bbe 100644
--- a/tests/robotests/res/values-mcc999/config.xml
+++ b/tests/robotests/res/values-mcc999/config.xml
@@ -91,4 +91,7 @@
 
     <!-- Email address for the homepage contextual cards feedback -->
     <string name="config_contextual_card_feedback_email" translatable="false">test@test.test</string>
+
+    <!-- Grayscale settings intent -->
+    <string name="config_grayscale_settings_intent" translate="false">intent:#Intent;action=test.test;end</string>
 </resources>
diff --git a/tests/robotests/src/com/android/settings/accounts/AvatarViewMixinTest.java b/tests/robotests/src/com/android/settings/accounts/AvatarViewMixinTest.java
index 6a2348c..8c75e33 100644
--- a/tests/robotests/src/com/android/settings/accounts/AvatarViewMixinTest.java
+++ b/tests/robotests/src/com/android/settings/accounts/AvatarViewMixinTest.java
@@ -27,6 +27,7 @@
 import static org.mockito.Mockito.verify;
 
 import android.accounts.Account;
+import android.app.ActivityManager;
 import android.content.ContentProvider;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -55,6 +56,7 @@
 import org.robolectric.annotation.Implementation;
 import org.robolectric.annotation.Implements;
 import org.robolectric.shadow.api.Shadow;
+import org.robolectric.shadows.ShadowActivityManager;
 import org.robolectric.shadows.ShadowContentResolver;
 import org.robolectric.shadows.ShadowPackageManager;
 
@@ -101,6 +103,19 @@
     }
 
     @Test
+    public void onStart_lowRamDevice_doNothing() {
+        final AvatarViewMixin mixin = spy(new AvatarViewMixin(mActivity, mImageView));
+
+        final ShadowActivityManager activityManager =
+                Shadow.extract(mContext.getSystemService(ActivityManager.class));
+        activityManager.setIsLowRamDevice(true);
+
+        mixin.onStart();
+
+        verify(mixin, never()).hasAccount();
+    }
+
+    @Test
     @Config(qualifiers = "mcc999",
             shadows = {
                     BatteryFixSliceTest.ShadowBatteryStatsHelperLoader.class,
diff --git a/tests/robotests/src/com/android/settings/applications/specialaccess/ZenAccessControllerTest.java b/tests/robotests/src/com/android/settings/applications/specialaccess/ZenAccessControllerTest.java
deleted file mode 100644
index 5bce86c..0000000
--- a/tests/robotests/src/com/android/settings/applications/specialaccess/ZenAccessControllerTest.java
+++ /dev/null
@@ -1,55 +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.applications.specialaccess;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.Context;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.shadow.api.Shadow;
-import org.robolectric.shadows.ShadowActivityManager;
-
-@RunWith(RobolectricTestRunner.class)
-public class ZenAccessControllerTest {
-
-    private Context mContext;
-    private ZenAccessController mController;
-    private ShadowActivityManager mActivityManager;
-
-    @Before
-    public void setUp() {
-        mContext = RuntimeEnvironment.application;
-        mController = new ZenAccessController(mContext, "key");
-        mActivityManager = Shadow.extract(mContext.getSystemService(Context.ACTIVITY_SERVICE));
-    }
-
-    @Test
-    public void isAvailable_byDefault_true() {
-        assertThat(mController.isAvailable()).isTrue();
-    }
-
-    @Test
-    public void isAvailable_lowMemory_false() {
-        mActivityManager.setIsLowRamDevice(true);
-        assertThat(mController.isAvailable()).isFalse();
-    }
-}
diff --git a/tests/robotests/src/com/android/settings/applications/specialaccess/zenaccess/ZenAccessControllerTest.java b/tests/robotests/src/com/android/settings/applications/specialaccess/zenaccess/ZenAccessControllerTest.java
new file mode 100644
index 0000000..6041e9d
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/applications/specialaccess/zenaccess/ZenAccessControllerTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.applications.specialaccess.zenaccess;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+
+import android.app.NotificationManager;
+import android.content.Context;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.shadow.ShadowNotificationManager;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadow.api.Shadow;
+import org.robolectric.shadows.ShadowActivityManager;
+
+@RunWith(RobolectricTestRunner.class)
+public class ZenAccessControllerTest {
+
+    private static final String TEST_PKG = "com.test.package";
+
+    private FakeFeatureFactory mFeatureFactory;
+    private Context mContext;
+    private ZenAccessController mController;
+    private ShadowActivityManager mActivityManager;
+
+
+    @Before
+    public void setUp() {
+        mContext = RuntimeEnvironment.application;
+        mFeatureFactory = FakeFeatureFactory.setupForTest();
+        mController = new ZenAccessController(mContext, "key");
+        mActivityManager = Shadow.extract(mContext.getSystemService(Context.ACTIVITY_SERVICE));
+    }
+
+    @Test
+    public void isAvailable_byDefault_true() {
+        assertThat(mController.isAvailable()).isTrue();
+    }
+
+    @Test
+    public void isAvailable_lowMemory_false() {
+        mActivityManager.setIsLowRamDevice(true);
+        assertThat(mController.isAvailable()).isFalse();
+    }
+
+    @Test
+    public void logSpecialPermissionChange() {
+        ZenAccessController.logSpecialPermissionChange(true, "app", mContext);
+        verify(mFeatureFactory.metricsFeatureProvider).action(any(Context.class),
+                eq(MetricsProto.MetricsEvent.APP_SPECIAL_PERMISSION_DND_ALLOW),
+                eq("app"));
+
+        ZenAccessController.logSpecialPermissionChange(false, "app", mContext);
+        verify(mFeatureFactory.metricsFeatureProvider).action(any(Context.class),
+                eq(MetricsProto.MetricsEvent.APP_SPECIAL_PERMISSION_DND_DENY),
+                eq("app"));
+    }
+
+    @Test
+    @Config(shadows = ShadowNotificationManager.class)
+    public void hasAccess_granted_yes() {
+        final ShadowNotificationManager snm = Shadow.extract(mContext.getSystemService(
+                NotificationManager.class));
+        snm.setNotificationPolicyAccessGrantedForPackage(TEST_PKG);
+        assertThat(ZenAccessController.hasAccess(mContext, TEST_PKG)).isTrue();
+    }
+
+    @Test
+    @Config(shadows = ShadowNotificationManager.class)
+    public void hasAccess_notGranted_no() {
+        assertThat(ZenAccessController.hasAccess(mContext, TEST_PKG)).isFalse();
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/applications/specialaccess/zenaccess/ZenAccessSettingObserverMixinTest.java b/tests/robotests/src/com/android/settings/applications/specialaccess/zenaccess/ZenAccessSettingObserverMixinTest.java
new file mode 100644
index 0000000..cba1a51
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/applications/specialaccess/zenaccess/ZenAccessSettingObserverMixinTest.java
@@ -0,0 +1,109 @@
+/*
+ * 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.applications.specialaccess.zenaccess;
+
+import static androidx.lifecycle.Lifecycle.Event.ON_START;
+import static androidx.lifecycle.Lifecycle.Event.ON_STOP;
+
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.provider.Settings;
+
+import androidx.lifecycle.LifecycleOwner;
+
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadow.api.Shadow;
+import org.robolectric.shadows.ShadowActivityManager;
+
+@RunWith(RobolectricTestRunner.class)
+public class ZenAccessSettingObserverMixinTest {
+
+    @Mock
+    private ZenAccessSettingObserverMixin.Listener mListener;
+
+    private Context mContext;
+    private LifecycleOwner mLifecycleOwner;
+    private Lifecycle mLifecycle;
+    private ZenAccessSettingObserverMixin mMixin;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = spy(RuntimeEnvironment.application);
+        mLifecycleOwner = () -> mLifecycle;
+        mLifecycle = new Lifecycle(mLifecycleOwner);
+
+        mMixin = new ZenAccessSettingObserverMixin(mContext, mListener);
+
+        mLifecycle.addObserver(mMixin);
+    }
+
+    @Test
+    public void onStart_lowMemory_shouldNotRegisterListener() {
+        final ShadowActivityManager sam = Shadow.extract(
+                mContext.getSystemService(ActivityManager.class));
+        sam.setIsLowRamDevice(true);
+
+        mLifecycle.handleLifecycleEvent(ON_START);
+
+        mContext.getContentResolver().notifyChange(Settings.Secure.getUriFor(
+                Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES), null);
+
+        verify(mListener, never()).onZenAccessPolicyChanged();
+    }
+
+    @Test
+    public void onStart_highMemory_shouldRegisterListener() {
+        final ShadowActivityManager sam = Shadow.extract(
+                mContext.getSystemService(ActivityManager.class));
+        sam.setIsLowRamDevice(false);
+
+        mLifecycle.handleLifecycleEvent(ON_START);
+
+        mContext.getContentResolver().notifyChange(Settings.Secure.getUriFor(
+                Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES), null);
+
+        verify(mListener).onZenAccessPolicyChanged();
+    }
+
+    @Test
+    public void onStop_shouldUnregisterListener() {
+        final ShadowActivityManager sam = Shadow.extract(
+                mContext.getSystemService(ActivityManager.class));
+        sam.setIsLowRamDevice(false);
+
+        mLifecycle.handleLifecycleEvent(ON_START);
+        mLifecycle.handleLifecycleEvent(ON_STOP);
+
+        mContext.getContentResolver().notifyChange(Settings.Secure.getUriFor(
+                Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES), null);
+
+        verify(mListener, never()).onZenAccessPolicyChanged();
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/core/HideNonSystemOverlayMixinTest.java b/tests/robotests/src/com/android/settings/core/HideNonSystemOverlayMixinTest.java
new file mode 100644
index 0000000..579cba0
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/core/HideNonSystemOverlayMixinTest.java
@@ -0,0 +1,78 @@
+/*
+ * 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.core;
+
+import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.os.Bundle;
+import android.view.WindowManager;
+
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.android.settings.R;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.Robolectric;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.android.controller.ActivityController;
+
+@RunWith(RobolectricTestRunner.class)
+public class HideNonSystemOverlayMixinTest {
+
+    private ActivityController<TestActivity> mActivityController;
+
+    @Before
+    public void setUp() {
+        RuntimeEnvironment.application.setTheme(R.style.Theme_AppCompat);
+        mActivityController = Robolectric.buildActivity(TestActivity.class);
+    }
+
+    @Test
+    public void startActivity_shouldHideNonSystemOverlay() {
+        mActivityController.setup();
+        TestActivity activity = mActivityController.get();
+
+        // Activity start: HIDE_NON_SYSTEM_OVERLAY should be set.
+        final WindowManager.LayoutParams attrs = activity.getWindow().getAttributes();
+        assertThat(attrs.privateFlags & SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS)
+                .isNotEqualTo(0);
+    }
+
+    @Test
+    public void stopActivity_shouldUnhideNonSystemOverlay() {
+        mActivityController.setup().stop();
+        TestActivity activity = mActivityController.get();
+
+        final WindowManager.LayoutParams attrs = activity.getWindow().getAttributes();
+        assertThat(attrs.privateFlags & SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS)
+                .isEqualTo(0);
+    }
+
+    public static class TestActivity extends AppCompatActivity {
+        @Override
+        protected void onCreate(@Nullable Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+            getLifecycle().addObserver(new HideNonSystemOverlayMixin(this));
+        }
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverButtonPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverButtonPreferenceControllerTest.java
index 7999dc8..3509330 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverButtonPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverButtonPreferenceControllerTest.java
@@ -94,13 +94,13 @@
     public void setChecked_on_setPowerSaveMode() {
         mController.setChecked(true);
 
-        verify(mPowerManager).setPowerSaveMode(true);
+        verify(mPowerManager).setPowerSaveModeEnabled(true);
     }
 
     @Test
     public void setChecked_off_unsetPowerSaveMode() {
         mController.setChecked(false);
 
-        verify(mPowerManager).setPowerSaveMode(false);
+        verify(mPowerManager).setPowerSaveModeEnabled(false);
     }
 }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverStickyPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverStickyPreferenceControllerTest.java
index a441864..0ee9cfc 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverStickyPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverStickyPreferenceControllerTest.java
@@ -42,7 +42,7 @@
     }
 
     private int getAutoDisableSetting() {
-        return Settings.System.getInt(mContext.getContentResolver(),
+        return Settings.Global.getInt(mContext.getContentResolver(),
                 LOW_POWER_STICKY_AUTO_DISABLE_ENABLED,
                 1);
     }
diff --git a/tests/robotests/src/com/android/settings/gestures/WakeScreenGestureSettingsTest.java b/tests/robotests/src/com/android/settings/gestures/WakeScreenGestureSettingsTest.java
deleted file mode 100644
index f1d2fcc..0000000
--- a/tests/robotests/src/com/android/settings/gestures/WakeScreenGestureSettingsTest.java
+++ /dev/null
@@ -1,50 +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.gestures;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.provider.SearchIndexableResource;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-import java.util.List;
-
-@RunWith(RobolectricTestRunner.class)
-public class WakeScreenGestureSettingsTest {
-
-    private WakeScreenGestureSettings mSettings;
-
-    @Before
-    public void setUp() {
-        mSettings = new WakeScreenGestureSettings();
-    }
-
-    @Test
-    public void testSearchIndexProvider_shouldIndexResource() {
-        final List<SearchIndexableResource> indexRes =
-                WakeScreenGestureSettings.SEARCH_INDEX_DATA_PROVIDER.getXmlResourcesToIndex(
-                        RuntimeEnvironment.application, true /* enabled */);
-
-        assertThat(indexRes).isNotNull();
-        assertThat(indexRes.get(0).xmlResId).isEqualTo(mSettings.getPreferenceScreenResId());
-    }
-}
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImplTest.java
index 2db7f3f..0683bd8 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImplTest.java
@@ -57,7 +57,7 @@
         final Intent intent = new Intent();
         mImpl.sendBroadcast(intent);
 
-        verify(mContext, never()).sendBroadcastAsUser(intent, UserHandle.ALL);
+        verify(mContext, never()).sendBroadcastAsUser(intent, UserHandle.CURRENT);
     }
 
     @Test
@@ -66,7 +66,7 @@
         final Intent intent = new Intent();
         mImpl.sendBroadcast(intent);
 
-        verify(mContext).sendBroadcastAsUser(intent, UserHandle.ALL);
+        verify(mContext).sendBroadcastAsUser(intent, UserHandle.CURRENT);
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java
index e66774e..40e6939 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java
@@ -229,11 +229,6 @@
                 .setSliceUri(Uri.parse(
                         "content://com.android.settings.test.slices/action/gesture_pick_up"))
                 .build());
-        cards.add(new ContextualCard.Builder()
-                .setName("test_battery")
-                .setCardType(ContextualCard.CardType.SLICE)
-                .setSliceUri(CustomSliceRegistry.BATTERY_INFO_SLICE_URI)
-                .build());
         return cards;
     }
 
@@ -262,11 +257,6 @@
                 .setSliceUri(Uri.parse(
                         "content://com.android.settings.test.slices/action/gesture_pick_up"))
                 .build());
-        cards.add(new ContextualCard.Builder()
-                .setName("test_battery")
-                .setCardType(ContextualCard.CardType.SLICE)
-                .setSliceUri(CustomSliceRegistry.BATTERY_INFO_SLICE_URI)
-                .build());
         return cards;
     }
 }
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardManagerTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardManagerTest.java
index eb9a461..8087716 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardManagerTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardManagerTest.java
@@ -460,7 +460,7 @@
         cards.add(new ContextualCard.Builder()
                 .setName("test_battery")
                 .setCardType(ContextualCard.CardType.SLICE)
-                .setSliceUri(CustomSliceRegistry.BATTERY_INFO_SLICE_URI)
+                .setSliceUri(CustomSliceRegistry.BATTERY_FIX_SLICE_URI)
                 .setViewType(VIEW_TYPE_FULL_WIDTH)
                 .build());
         return cards;
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/GrayscaleConditionControllerTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/GrayscaleConditionControllerTest.java
new file mode 100644
index 0000000..8c24735
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/GrayscaleConditionControllerTest.java
@@ -0,0 +1,83 @@
+/*
+ * 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.conditional;
+
+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.content.Context;
+import android.hardware.display.ColorDisplayManager;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(RobolectricTestRunner.class)
+public class GrayscaleConditionControllerTest {
+
+    @Mock
+    private ConditionManager mConditionManager;
+
+    private ColorDisplayManager mColorDisplayManager;
+    private Context mContext;
+    private GrayscaleConditionController mController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = spy(RuntimeEnvironment.application);
+        mColorDisplayManager = spy(mContext.getSystemService(ColorDisplayManager.class));
+        doReturn(mColorDisplayManager).when(mContext).getSystemService(ColorDisplayManager.class);
+        mController = new GrayscaleConditionController(mContext, mConditionManager);
+    }
+
+    @Test
+    public void isDisplayable_noIntent_shouldReturnFalse() {
+        assertThat(mController.isDisplayable()).isFalse();
+    }
+
+    @Test
+    @Config(qualifiers = "mcc999")
+    public void isDisplayable_validIntentAndGrayscaleOn_shouldReturnTrue() {
+        doReturn(true).when(mColorDisplayManager).isSaturationActivated();
+
+        assertThat(mController.isDisplayable()).isTrue();
+    }
+
+    @Test
+    @Config(qualifiers = "mcc999")
+    public void isDisplayable_validIntentAndGrayscaleOff_shouldReturnFalse() {
+        doReturn(false).when(mColorDisplayManager).isSaturationActivated();
+
+        assertThat(mController.isDisplayable()).isFalse();
+    }
+
+    @Test
+    public void onActionClick_shouldRefreshCondition() {
+        mController.onActionClick();
+
+        verify(mConditionManager).onConditionChanged();
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/deviceinfo/BatteryInfoSliceTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/deviceinfo/BatteryInfoSliceTest.java
deleted file mode 100644
index ff276d6..0000000
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/deviceinfo/BatteryInfoSliceTest.java
+++ /dev/null
@@ -1,75 +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.homepage.contextualcards.deviceinfo;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.spy;
-
-import android.content.Context;
-
-import androidx.core.graphics.drawable.IconCompat;
-import androidx.slice.Slice;
-import androidx.slice.SliceMetadata;
-import androidx.slice.SliceProvider;
-import androidx.slice.core.SliceAction;
-import androidx.slice.widget.SliceLiveData;
-
-import com.android.settings.R;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-@RunWith(RobolectricTestRunner.class)
-public class BatteryInfoSliceTest {
-
-    private Context mContext;
-    private BatteryInfoSlice mBatteryInfoSlice;
-
-    @Before
-    public void setUp() {
-        mContext = RuntimeEnvironment.application;
-
-        // Set-up specs for SliceMetadata.
-        SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
-
-        mBatteryInfoSlice = spy(new BatteryInfoSlice(mContext));
-    }
-
-    @Test
-    public void getSlice_shouldBeCorrectSliceContent() {
-        doNothing().when(mBatteryInfoSlice).loadBatteryInfo();
-        doReturn("10%").when(mBatteryInfoSlice).getBatteryPercentString();
-        doReturn("test").when(mBatteryInfoSlice).getSummary();
-
-        final Slice slice = mBatteryInfoSlice.getSlice();
-
-        final SliceMetadata metadata = SliceMetadata.from(mContext, slice);
-        assertThat(metadata.getTitle()).isEqualTo(
-                mContext.getString(R.string.power_usage_summary_title));
-
-        final SliceAction primaryAction = metadata.getPrimaryAction();
-        final IconCompat expectedIcon = IconCompat.createWithResource(mContext,
-                R.drawable.ic_settings_battery);
-        assertThat(primaryAction.getIcon().toString()).isEqualTo(expectedIcon.toString());
-    }
-}
diff --git a/tests/robotests/src/com/android/settings/media/MediaOutputIndicatorSliceTest.java b/tests/robotests/src/com/android/settings/media/MediaOutputIndicatorSliceTest.java
new file mode 100644
index 0000000..ab3f4de
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/media/MediaOutputIndicatorSliceTest.java
@@ -0,0 +1,109 @@
+/*
+ * 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.media;
+
+import static com.android.settings.slices.CustomSliceRegistry.MEDIA_OUTPUT_INDICATOR_SLICE_URI;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.bluetooth.BluetoothAdapter;
+import android.content.Context;
+import android.content.Intent;
+
+import androidx.slice.Slice;
+import androidx.slice.SliceItem;
+import androidx.slice.SliceMetadata;
+import androidx.slice.SliceProvider;
+import androidx.slice.core.SliceAction;
+import androidx.slice.widget.SliceLiveData;
+
+import com.android.settings.R;
+import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
+import com.android.settingslib.media.LocalMediaManager;
+import com.android.settingslib.media.MediaDevice;
+import com.android.settingslib.media.MediaOutputSliceConstants;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadow.api.Shadow;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowBluetoothAdapter.class})
+public class MediaOutputIndicatorSliceTest {
+
+    private static final String TEST_DEVICE_NAME = "test_device_name";
+    private static final int TEST_DEVICE_1_ICON =
+            com.android.internal.R.drawable.ic_bt_headphones_a2dp;
+
+    @Mock
+    private LocalMediaManager mLocalMediaManager;
+
+    private final List<MediaDevice> mDevices = new ArrayList<>();
+
+    private Context mContext;
+    private MediaOutputIndicatorSlice mMediaOutputIndicatorSlice;
+    private MediaOutputIndicatorWorker mMediaOutputIndicatorWorker;
+    private ShadowBluetoothAdapter mShadowBluetoothAdapter;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        mContext = spy(RuntimeEnvironment.application);
+
+        // Set-up specs for SliceMetadata.
+        SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
+
+        mMediaOutputIndicatorSlice = new MediaOutputIndicatorSlice(mContext);
+        mMediaOutputIndicatorWorker = spy(new MediaOutputIndicatorWorker(
+                mContext, MEDIA_OUTPUT_INDICATOR_SLICE_URI));
+        mMediaOutputIndicatorSlice.mWorker = mMediaOutputIndicatorWorker;
+    }
+
+    @Test
+    public void getSlice_invisible_returnNull() {
+        when(mMediaOutputIndicatorWorker.isVisible()).thenReturn(false);
+
+        assertThat(mMediaOutputIndicatorSlice.getSlice()).isNull();
+    }
+
+    @Test
+    public void getSlice_withActiveDevice_checkContent() {
+        when(mMediaOutputIndicatorWorker.isVisible()).thenReturn(true);
+        when(mMediaOutputIndicatorWorker.findActiveDeviceName()).thenReturn(TEST_DEVICE_NAME);
+        final Slice mediaSlice = mMediaOutputIndicatorSlice.getSlice();
+        final SliceMetadata metadata = SliceMetadata.from(mContext, mediaSlice);
+        // Verify slice title and subtitle
+        assertThat(metadata.getTitle()).isEqualTo(mContext.getText(R.string.media_output_title));
+        assertThat(metadata.getSubtitle()).isEqualTo(TEST_DEVICE_NAME);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/media/MediaOutputIndicatorWorkerTest.java b/tests/robotests/src/com/android/settings/media/MediaOutputIndicatorWorkerTest.java
new file mode 100644
index 0000000..4a5662e
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/media/MediaOutputIndicatorWorkerTest.java
@@ -0,0 +1,161 @@
+/*
+ * 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.media;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothManager;
+import android.content.Context;
+import android.net.Uri;
+
+import com.android.settings.R;
+import com.android.settings.bluetooth.Utils;
+import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
+import com.android.settingslib.bluetooth.A2dpProfile;
+import com.android.settingslib.bluetooth.BluetoothEventManager;
+import com.android.settingslib.bluetooth.HearingAidProfile;
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowBluetoothDevice;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowBluetoothUtils.class,
+        ShadowBluetoothDevice.class})
+public class MediaOutputIndicatorWorkerTest {
+
+    private static final String TEST_A2DP_DEVICE_NAME = "Test_A2DP_BT_Device_NAME";
+    private static final String TEST_HAP_DEVICE_NAME = "Test_HAP_BT_Device_NAME";
+    private static final String TEST_A2DP_DEVICE_ADDRESS = "00:A1:A1:A1:A1:A1";
+    private static final String TEST_HAP_DEVICE_ADDRESS = "00:B2:B2:B2:B2:B2";
+    private static final Uri URI = Uri.parse("content://com.android.settings.slices/test");
+
+    @Mock
+    private A2dpProfile mA2dpProfile;
+    @Mock
+    private HearingAidProfile mHearingAidProfile;
+    @Mock
+    private LocalBluetoothManager mLocalManager;
+    @Mock
+    private BluetoothEventManager mBluetoothEventManager;
+    @Mock
+    private LocalBluetoothProfileManager mLocalBluetoothProfileManager;
+
+    private BluetoothAdapter mBluetoothAdapter;
+    private BluetoothDevice mA2dpDevice;
+    private BluetoothDevice mHapDevice;
+    private BluetoothManager mBluetoothManager;
+    private Context mContext;
+    private List<BluetoothDevice> mDevicesList;
+    private LocalBluetoothManager mLocalBluetoothManager;
+    private MediaOutputIndicatorWorker mMediaDeviceUpdateWorker;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = spy(RuntimeEnvironment.application);
+        ShadowBluetoothUtils.sLocalBluetoothManager = mLocalManager;
+        mLocalBluetoothManager = Utils.getLocalBtManager(mContext);
+        when(mLocalBluetoothManager.getEventManager()).thenReturn(mBluetoothEventManager);
+        when(mLocalBluetoothManager.getProfileManager()).thenReturn(mLocalBluetoothProfileManager);
+        when(mLocalBluetoothProfileManager.getA2dpProfile()).thenReturn(mA2dpProfile);
+        when(mLocalBluetoothProfileManager.getHearingAidProfile()).thenReturn(mHearingAidProfile);
+        mBluetoothManager = new BluetoothManager(mContext);
+        mBluetoothAdapter = mBluetoothManager.getAdapter();
+
+        // Setup A2dp device
+        mA2dpDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_A2DP_DEVICE_ADDRESS));
+        when(mA2dpDevice.getName()).thenReturn(TEST_A2DP_DEVICE_NAME);
+        when(mA2dpDevice.isConnected()).thenReturn(true);
+        // Setup HearingAid device
+        mHapDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_HAP_DEVICE_ADDRESS));
+        when(mHapDevice.getName()).thenReturn(TEST_HAP_DEVICE_NAME);
+        when(mHapDevice.isConnected()).thenReturn(true);
+
+        mMediaDeviceUpdateWorker = new MediaOutputIndicatorWorker(mContext, URI);
+        mDevicesList = new ArrayList<>();
+    }
+
+    @Test
+    public void isVisible_noConnectableDevice_returnFalse() {
+        mDevicesList.clear();
+        when(mA2dpProfile.getConnectableDevices()).thenReturn(mDevicesList);
+
+        assertThat(mMediaDeviceUpdateWorker.isVisible()).isFalse();
+    }
+
+    @Test
+    public void isVisible_withConnectableA2dpDevice_returnTrue() {
+        mDevicesList.clear();
+        mDevicesList.add(mA2dpDevice);
+        when(mHearingAidProfile.getConnectableDevices()).thenReturn(mDevicesList);
+
+        assertThat(mMediaDeviceUpdateWorker.isVisible()).isTrue();
+    }
+
+    @Test
+    public void isVisible_withConnectableHADevice_returnTrue() {
+        mDevicesList.clear();
+        mDevicesList.add(mHapDevice);
+        when(mA2dpProfile.getConnectableDevices()).thenReturn(mDevicesList);
+
+        assertThat(mMediaDeviceUpdateWorker.isVisible()).isTrue();
+    }
+
+    @Test
+    public void findActiveDeviceName_A2dpDeviceActive_verifyName() {
+        when(mA2dpProfile.getActiveDevice()).thenReturn(mA2dpDevice);
+
+        assertThat(mMediaDeviceUpdateWorker.findActiveDeviceName())
+                .isEqualTo(mA2dpDevice.getAliasName());
+    }
+
+    @Test
+    public void findActiveDeviceName_HADeviceActive_verifyName() {
+        mDevicesList.add(mHapDevice);
+        when(mHearingAidProfile.getActiveDevices()).thenReturn(mDevicesList);
+
+        assertThat(mMediaDeviceUpdateWorker.findActiveDeviceName())
+                .isEqualTo(mHapDevice.getAliasName());
+    }
+
+    @Test
+    public void findActiveDeviceName_noActiveDevice_verifyDefaultName() {
+        when(mA2dpProfile.getActiveDevice()).thenReturn(null);
+        mDevicesList.clear();
+        when(mHearingAidProfile.getActiveDevices()).thenReturn(mDevicesList);
+
+        assertThat(mMediaDeviceUpdateWorker.findActiveDeviceName())
+                .isEqualTo(mContext.getText(R.string.media_output_default_summary));
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/media/MediaOutputSliceTest.java b/tests/robotests/src/com/android/settings/media/MediaOutputSliceTest.java
index da0d85b..d26a458 100644
--- a/tests/robotests/src/com/android/settings/media/MediaOutputSliceTest.java
+++ b/tests/robotests/src/com/android/settings/media/MediaOutputSliceTest.java
@@ -94,6 +94,13 @@
     }
 
     @Test
+    public void getSlice_workerIsNull_shouldNotCrash() {
+        mMediaOutputSlice.init(TEST_PACKAGE_NAME, null);
+
+        mMediaOutputSlice.getSlice();
+    }
+
+    @Test
     public void getSlice_shouldHaveActiveDeviceName() {
         mDevices.clear();
         final MediaDevice device = mock(MediaDevice.class);
diff --git a/tests/robotests/src/com/android/settings/network/MobileNetworkListControllerTest.java b/tests/robotests/src/com/android/settings/network/MobileNetworkListControllerTest.java
index 1325650..10264ab 100644
--- a/tests/robotests/src/com/android/settings/network/MobileNetworkListControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/MobileNetworkListControllerTest.java
@@ -21,6 +21,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
@@ -31,6 +32,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.telephony.SubscriptionInfo;
+import android.telephony.euicc.EuiccManager;
 
 import org.junit.After;
 import org.junit.Before;
@@ -51,6 +53,9 @@
 @RunWith(RobolectricTestRunner.class)
 public class MobileNetworkListControllerTest {
     @Mock
+    EuiccManager mEuiccManager;
+
+    @Mock
     private Lifecycle mLifecycle;
 
     @Mock
@@ -58,12 +63,17 @@
 
     private Context mContext;
     private MobileNetworkListController mController;
+    private Preference mAddMorePreference;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mContext = spy(Robolectric.setupActivity(Activity.class));
+        when(mContext.getSystemService(EuiccManager.class)).thenReturn(mEuiccManager);
         when(mPreferenceScreen.getContext()).thenReturn(mContext);
+        mAddMorePreference = new Preference(mContext);
+        when(mPreferenceScreen.findPreference(MobileNetworkListController.KEY_ADD_MORE)).thenReturn(
+                mAddMorePreference);
         mController = new MobileNetworkListController(mContext, mLifecycle);
     }
 
@@ -79,6 +89,22 @@
     }
 
     @Test
+    public void displayPreference_eSimNotSupported_addMoreLinkNotVisible() {
+        when(mEuiccManager.isEnabled()).thenReturn(false);
+        mController.displayPreference(mPreferenceScreen);
+        mController.onResume();
+        assertThat(mAddMorePreference.isVisible()).isFalse();
+    }
+
+    @Test
+    public void displayPreference_eSimSupported_addMoreLinkIsVisible() {
+        when(mEuiccManager.isEnabled()).thenReturn(true);
+        mController.displayPreference(mPreferenceScreen);
+        mController.onResume();
+        assertThat(mAddMorePreference.isVisible()).isTrue();
+    }
+
+    @Test
     public void displayPreference_twoSubscriptions_correctlySetup() {
         final SubscriptionInfo sub1 = createMockSubscription(1, "sub1");
         final SubscriptionInfo sub2 = createMockSubscription(2, "sub2");
diff --git a/tests/robotests/src/com/android/settings/network/MobileNetworkSummaryControllerTest.java b/tests/robotests/src/com/android/settings/network/MobileNetworkSummaryControllerTest.java
index ba152b9..3404ca2 100644
--- a/tests/robotests/src/com/android/settings/network/MobileNetworkSummaryControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/MobileNetworkSummaryControllerTest.java
@@ -16,13 +16,9 @@
 
 package com.android.settings.network;
 
-import static android.telephony.TelephonyManager.MultiSimVariants.DSDS;
-import static android.telephony.TelephonyManager.MultiSimVariants.UNKNOWN;
-
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.ArgumentMatchers.isNull;
 import static org.mockito.ArgumentMatchers.notNull;
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.mock;
@@ -37,7 +33,6 @@
 import android.net.ConnectivityManager;
 import android.provider.Settings;
 import android.telephony.SubscriptionInfo;
-import android.telephony.TelephonyManager;
 import android.telephony.euicc.EuiccManager;
 import android.text.TextUtils;
 
@@ -64,8 +59,6 @@
     @Mock
     private Lifecycle mLifecycle;
     @Mock
-    private TelephonyManager mTelephonyManager;
-    @Mock
     private EuiccManager mEuiccManager;
     @Mock
     private PreferenceScreen mPreferenceScreen;
@@ -78,9 +71,7 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mContext = spy(Robolectric.setupActivity(Activity.class));
-        when(mContext.getSystemService(eq(TelephonyManager.class))).thenReturn(mTelephonyManager);
         when(mContext.getSystemService(EuiccManager.class)).thenReturn(mEuiccManager);
-        when(mTelephonyManager.getMultiSimConfiguration()).thenReturn(UNKNOWN);
         when(mEuiccManager.isEnabled()).thenReturn(true);
 
         mController = new MobileNetworkSummaryController(mContext, mLifecycle);
@@ -97,7 +88,7 @@
 
     @Test
     public void isAvailable_wifiOnlyMode_notAvailable() {
-        ConnectivityManager cm = mock(ConnectivityManager.class);
+        final ConnectivityManager cm = mock(ConnectivityManager.class);
         when(cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)).thenReturn(false);
         when(mContext.getSystemService(ConnectivityManager.class)).thenReturn(cm);
         assertThat(mController.isAvailable()).isFalse();
@@ -212,24 +203,7 @@
     }
 
     @Test
-    public void addButton_noSubscriptionsSingleSimMode_noAddClickListener() {
-        mController.displayPreference(mPreferenceScreen);
-        mController.onResume();
-        verify(mPreference, never()).setOnAddClickListener(notNull());
-    }
-
-    @Test
-    public void addButton_oneSubscriptionSingleSimMode_noAddClickListener() {
-        final SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
-        SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1));
-        mController.displayPreference(mPreferenceScreen);
-        mController.onResume();
-        verify(mPreference, never()).setOnAddClickListener(notNull());
-    }
-
-    @Test
-    public void addButton_noSubscriptionsMultiSimModeNoEuiccMgr_noAddClickListener() {
-        when(mTelephonyManager.getMultiSimConfiguration()).thenReturn(DSDS);
+    public void addButton_noSubscriptionsNoEuiccMgr_noAddClickListener() {
         when(mEuiccManager.isEnabled()).thenReturn(false);
         mController.displayPreference(mPreferenceScreen);
         mController.onResume();
@@ -237,41 +211,43 @@
     }
 
     @Test
-    public void addButton_noSubscriptionsMultiSimMode_hasAddClickListenerAndPrefDisabled() {
-        when(mTelephonyManager.getMultiSimConfiguration()).thenReturn(DSDS);
-        mController.displayPreference(mPreferenceScreen);
-        mController.onResume();
-        assertThat(mPreference.isEnabled()).isFalse();
-        verify(mPreference, never()).setOnAddClickListener(isNull());
-        verify(mPreference).setOnAddClickListener(notNull());
-    }
-
-    @Test
-    public void addButton_oneSubscriptionMultiSimMode_hasAddClickListener() {
-        when(mTelephonyManager.getMultiSimConfiguration()).thenReturn(DSDS);
+    public void addButton_oneSubscriptionNoEuiccMgr_noAddClickListener() {
+        when(mEuiccManager.isEnabled()).thenReturn(false);
         final SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
         SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1));
         mController.displayPreference(mPreferenceScreen);
         mController.onResume();
-        verify(mPreference, never()).setOnAddClickListener(isNull());
+        verify(mPreference, never()).setOnAddClickListener(notNull());
+    }
+
+    @Test
+    public void addButton_noSubscriptions_noAddClickListener() {
+        mController.displayPreference(mPreferenceScreen);
+        mController.onResume();
+        verify(mPreference, never()).setOnAddClickListener(notNull());
+    }
+
+    @Test
+    public void addButton_oneSubscription_hasAddClickListener() {
+        final SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
+        SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1));
+        mController.displayPreference(mPreferenceScreen);
+        mController.onResume();
         verify(mPreference).setOnAddClickListener(notNull());
     }
 
     @Test
-    public void addButton_twoSubscriptionsMultiSimMode_hasAddClickListener() {
-        when(mTelephonyManager.getMultiSimConfiguration()).thenReturn(DSDS);
+    public void addButton_twoSubscriptions_hasAddClickListener() {
         final SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
         final SubscriptionInfo sub2 = mock(SubscriptionInfo.class);
         SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub2));
         mController.displayPreference(mPreferenceScreen);
         mController.onResume();
-        verify(mPreference, never()).setOnAddClickListener(isNull());
         verify(mPreference).setOnAddClickListener(notNull());
     }
 
     @Test
     public void addButton_oneSubscriptionAirplaneModeTurnedOn_addButtonGetsDisabled() {
-        when(mTelephonyManager.getMultiSimConfiguration()).thenReturn(DSDS);
         final SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
         SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1));
         mController.displayPreference(mPreferenceScreen);
@@ -280,14 +256,13 @@
         Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1);
         mController.onAirplaneModeChanged(true);
 
-        ArgumentCaptor<Boolean> captor = ArgumentCaptor.forClass(Boolean.class);
+        final ArgumentCaptor<Boolean> captor = ArgumentCaptor.forClass(Boolean.class);
         verify(mPreference, atLeastOnce()).setAddWidgetEnabled(captor.capture());
         assertThat(captor.getValue()).isFalse();
     }
 
     @Test
     public void onResume_oneSubscriptionAirplaneMode_isDisabled() {
-        when(mTelephonyManager.getMultiSimConfiguration()).thenReturn(DSDS);
         Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1);
         final SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
         SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1));
@@ -296,7 +271,7 @@
 
         assertThat(mPreference.isEnabled()).isFalse();
 
-        ArgumentCaptor<Boolean> captor = ArgumentCaptor.forClass(Boolean.class);
+        final ArgumentCaptor<Boolean> captor = ArgumentCaptor.forClass(Boolean.class);
         verify(mPreference, atLeastOnce()).setAddWidgetEnabled(captor.capture());
         assertThat(captor.getValue()).isFalse();
     }
@@ -318,7 +293,6 @@
 
     @Test
     public void onAirplaneModeChanged_oneSubscriptionAirplaneModeGetsTurnedOff_isEnabled() {
-        when(mTelephonyManager.getMultiSimConfiguration()).thenReturn(DSDS);
         Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1);
         final SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
         SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1));
@@ -332,7 +306,7 @@
 
         assertThat(mPreference.isEnabled()).isTrue();
 
-        ArgumentCaptor<Boolean> captor = ArgumentCaptor.forClass(Boolean.class);
+        final ArgumentCaptor<Boolean> captor = ArgumentCaptor.forClass(Boolean.class);
         verify(mPreference, atLeastOnce()).setAddWidgetEnabled(eq(false));
         verify(mPreference, atLeastOnce()).setAddWidgetEnabled(captor.capture());
         assertThat(captor.getValue()).isTrue();
diff --git a/tests/robotests/src/com/android/settings/network/telephony/Enhanced4gLteSliceHelperTest.java b/tests/robotests/src/com/android/settings/network/telephony/Enhanced4gLteSliceHelperTest.java
index 072c835..a9882d9 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/Enhanced4gLteSliceHelperTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/Enhanced4gLteSliceHelperTest.java
@@ -22,7 +22,6 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
@@ -43,7 +42,6 @@
 
 import com.android.ims.ImsManager;
 import com.android.settings.R;
-import com.android.settings.slices.CustomSliceManager;
 import com.android.settings.slices.CustomSliceRegistry;
 import com.android.settings.slices.SettingsSliceProvider;
 import com.android.settings.slices.SliceBroadcastReceiver;
@@ -85,10 +83,6 @@
         mFeatureFactory = FakeFeatureFactory.setupForTest();
         mSlicesFeatureProvider = mFeatureFactory.getSlicesFeatureProvider();
 
-        CustomSliceManager manager = new CustomSliceManager(mContext);
-        when(mSlicesFeatureProvider.getCustomSliceManager(any(Context.class)))
-                .thenReturn(manager);
-
         //setup for SettingsSliceProvider tests
         mProvider = spy(new SettingsSliceProvider());
         doReturn(mContext).when(mProvider).getContext();
diff --git a/tests/robotests/src/com/android/settings/network/telephony/MobileDataSliceTest.java b/tests/robotests/src/com/android/settings/network/telephony/MobileDataSliceTest.java
index c497cf8..e488d0c 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/MobileDataSliceTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/MobileDataSliceTest.java
@@ -24,6 +24,7 @@
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
+import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
 import android.provider.Settings;
@@ -162,4 +163,27 @@
 
         assertThat(isMobileDataEnabled).isEqualTo(seed);
     }
+
+    @Test
+    public void airplaneModeEnabled_slicePrimaryActionIsEmpty() {
+        doReturn(true).when(mMobileDataSlice).isAirplaneModeEnabled();
+        doReturn(mSubscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(SUB_ID);
+        final Slice mobileData = mMobileDataSlice.getSlice();
+
+        final SliceMetadata metadata = SliceMetadata.from(mContext, mobileData);
+        assertThat(metadata.getTitle())
+                .isEqualTo(mContext.getString(R.string.mobile_data_settings_title));
+
+        assertThat(metadata.getSubtitle())
+                .isEqualTo(mContext.getString(R.string.mobile_data_ap_mode_disabled));
+
+        final List<SliceAction> toggles = metadata.getToggles();
+        assertThat(toggles).hasSize(0);
+
+        final SliceAction primaryAction = metadata.getPrimaryAction();
+        final PendingIntent pendingIntent = primaryAction.getAction();
+        final Intent actionIntent = pendingIntent.getIntent();
+
+        assertThat(actionIntent).isNull();
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/notification/BlockPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/BlockPreferenceControllerTest.java
index 4f6944a..bdbf40a 100644
--- a/tests/robotests/src/com/android/settings/notification/BlockPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/BlockPreferenceControllerTest.java
@@ -111,6 +111,26 @@
     }
 
     @Test
+    public void testIsAvailable_notIfChannelNonDefault() {
+        NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+        appRow.systemApp = true;
+        NotificationChannel channel = mock(NotificationChannel.class);
+        when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
+        mController.onResume(appRow, channel, null, null);
+        assertFalse(mController.isAvailable());
+    }
+
+    @Test
+    public void testIsAvailable_ifChannelDefault() {
+        NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+        NotificationChannel channel = mock(NotificationChannel.class);
+        when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
+        when(channel.getId()).thenReturn(DEFAULT_CHANNEL_ID);
+        mController.onResume(appRow, channel, null, null);
+        assertTrue(mController.isAvailable());
+    }
+
+    @Test
     public void testIsAvailable_notIfGroupNotBlockable() {
         NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
         appRow.systemApp = true;
diff --git a/tests/robotests/src/com/android/settings/notification/HighImportancePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/HighImportancePreferenceControllerTest.java
new file mode 100644
index 0000000..6e6dad4
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/HighImportancePreferenceControllerTest.java
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import static android.app.NotificationChannel.DEFAULT_CHANNEL_ID;
+import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
+import static android.app.NotificationManager.IMPORTANCE_HIGH;
+import static android.app.NotificationManager.IMPORTANCE_NONE;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+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 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 HighImportancePreferenceControllerTest {
+
+    private Context mContext;
+    @Mock
+    private NotificationManager mNm;
+    @Mock
+    private NotificationBackend mBackend;
+    @Mock
+    private NotificationSettingsBase.ImportanceListener mImportanceListener;
+    @Mock
+    private UserManager mUm;
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private PreferenceScreen mScreen;
+
+    private HighImportancePreferenceController mController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        ShadowApplication shadowApplication = ShadowApplication.getInstance();
+        shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNm);
+        shadowApplication.setSystemService(Context.USER_SERVICE, mUm);
+        mContext = RuntimeEnvironment.application;
+        mController = spy(new HighImportancePreferenceController(
+                mContext, mImportanceListener, mBackend));
+    }
+
+    @Test
+    public void testNoCrashIfNoOnResume() {
+        mController.isAvailable();
+        mController.updateState(mock(Preference.class));
+    }
+
+    @Test
+    public void testIsAvailable_notIfNull() {
+        mController.onResume(null, null, null, null);
+        assertFalse(mController.isAvailable());
+    }
+
+    @Test
+    public void testIsAvailable_ifAppBlocked() {
+        NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+        appRow.banned = true;
+        mController.onResume(appRow, mock(NotificationChannel.class), null, null);
+        assertFalse(mController.isAvailable());
+    }
+
+    @Test
+    public void testIsAvailable_notIfChannelBlocked() {
+        NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+        NotificationChannel channel = mock(NotificationChannel.class);
+        when(channel.getImportance()).thenReturn(IMPORTANCE_NONE);
+        mController.onResume(appRow, channel, null, null);
+        assertFalse(mController.isAvailable());
+    }
+
+    @Test
+    public void testIsAvailable_notForDefaultChannel() {
+        NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+        NotificationChannel channel = mock(NotificationChannel.class);
+        when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
+        when(channel.getId()).thenReturn(DEFAULT_CHANNEL_ID);
+        mController.onResume(appRow, channel, null, null);
+        assertFalse(mController.isAvailable());
+    }
+
+    @Test
+    public void testIsAvailable() {
+        NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+        NotificationChannel channel = mock(NotificationChannel.class);
+        when(channel.getImportance()).thenReturn(IMPORTANCE_DEFAULT);
+        mController.onResume(appRow, channel, null, null);
+        assertTrue(mController.isAvailable());
+    }
+
+    @Test
+    public void testUpdateState_disabledByAdmin() {
+        NotificationChannel channel = mock(NotificationChannel.class);
+        when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
+        mController.onResume(new NotificationBackend.AppRow(), channel, null, mock(
+                RestrictedLockUtils.EnforcedAdmin.class));
+
+        Preference pref = new RestrictedSwitchPreference(mContext, null);
+        mController.updateState(pref);
+
+        assertFalse(pref.isEnabled());
+    }
+
+    @Test
+    public void testUpdateState_notConfigurable() {
+        String lockedId = "locked";
+        NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+        appRow.lockedChannelId = lockedId;
+        NotificationChannel channel = mock(NotificationChannel.class);
+        when(channel.getId()).thenReturn(lockedId);
+        when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
+        mController.onResume(appRow, channel, null, null);
+
+        Preference pref = new RestrictedSwitchPreference(mContext, null);
+        mController.updateState(pref);
+
+        assertFalse(pref.isEnabled());
+    }
+
+    @Test
+    public void testUpdateState_high() {
+        NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+        NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
+        mController.onResume(appRow, channel, null, null);
+
+        RestrictedSwitchPreference pref = new RestrictedSwitchPreference(mContext);
+        mController.updateState(pref);
+
+        assertTrue(pref.isChecked());
+    }
+
+    @Test
+    public void testUpdateState_default() {
+        NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+        NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_DEFAULT);
+        mController.onResume(appRow, channel, null, null);
+
+        RestrictedSwitchPreference pref = new RestrictedSwitchPreference(mContext);
+        mController.updateState(pref);
+
+        assertFalse(pref.isChecked());
+    }
+    
+    @Test
+    public void onPreferenceChange() {
+        NotificationChannel channel =
+                new NotificationChannel(DEFAULT_CHANNEL_ID, "a", IMPORTANCE_HIGH);
+        mController.onResume(new NotificationBackend.AppRow(), channel, null, null);
+
+        RestrictedSwitchPreference pref = new RestrictedSwitchPreference(mContext, null);
+        when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(pref);
+        mController.displayPreference(mScreen);
+        mController.updateState(pref);
+
+        mController.onPreferenceChange(pref, false);
+
+        assertEquals(IMPORTANCE_DEFAULT, channel.getImportance());
+        verify(mImportanceListener, times(1)).onImportanceChanged();
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/ImportancePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ImportancePreferenceControllerTest.java
index 99d3376..c180ace 100644
--- a/tests/robotests/src/com/android/settings/notification/ImportancePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/ImportancePreferenceControllerTest.java
@@ -27,8 +27,11 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
+import static org.mockito.ArgumentMatchers.anyBoolean;
 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.Notification;
@@ -36,12 +39,10 @@
 import android.app.NotificationManager;
 import android.content.Context;
 import android.os.UserManager;
-import android.text.TextUtils;
 
 import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
 
-import com.android.settings.RestrictedListPreference;
 import com.android.settingslib.RestrictedLockUtils;
 
 import org.junit.Before;
@@ -95,20 +96,20 @@
     }
 
     @Test
-    public void testIsAvailable_notIfAppBlocked() {
+    public void testIsAvailable_ifAppBlocked() {
         NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
         appRow.banned = true;
         mController.onResume(appRow, mock(NotificationChannel.class), null, null);
-        assertFalse(mController.isAvailable());
+        assertTrue(mController.isAvailable());
     }
 
     @Test
-    public void testIsAvailable_notIfChannelBlocked() {
+    public void testIsAvailable_evenIfChannelBlocked() {
         NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
         NotificationChannel channel = mock(NotificationChannel.class);
         when(channel.getImportance()).thenReturn(IMPORTANCE_NONE);
         mController.onResume(appRow, channel, null, null);
-        assertFalse(mController.isAvailable());
+        assertTrue(mController.isAvailable());
     }
 
     @Test
@@ -137,11 +138,10 @@
         mController.onResume(new NotificationBackend.AppRow(), channel, null, mock(
                 RestrictedLockUtils.EnforcedAdmin.class));
 
-        Preference pref = new RestrictedListPreference(mContext, null);
+        Preference pref = new ImportancePreference(mContext, null);
         mController.updateState(pref);
 
         assertFalse(pref.isEnabled());
-        assertFalse(TextUtils.isEmpty(pref.getSummary()));
     }
 
     @Test
@@ -154,11 +154,10 @@
         when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
         mController.onResume(appRow, channel, null, null);
 
-        Preference pref = new RestrictedListPreference(mContext, null);
+        Preference pref = new ImportancePreference(mContext, null);
         mController.updateState(pref);
 
         assertFalse(pref.isEnabled());
-        assertFalse(TextUtils.isEmpty(pref.getSummary()));
     }
 
     @Test
@@ -167,11 +166,12 @@
         NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
         mController.onResume(appRow, channel, null, null);
 
-        Preference pref = new RestrictedListPreference(mContext, null);
+        ImportancePreference pref = mock(ImportancePreference.class);
         mController.updateState(pref);
 
-        assertTrue(pref.isEnabled());
-        assertFalse(TextUtils.isEmpty(pref.getSummary()));
+        verify(pref, times(1)).setConfigurable(anyBoolean());
+        verify(pref, times(1)).setBlockable(anyBoolean());
+        verify(pref, times(1)).setImportance(IMPORTANCE_HIGH);
     }
     
     @Test
@@ -181,13 +181,12 @@
         channel.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT);
         mController.onResume(new NotificationBackend.AppRow(), channel, null, null);
 
-        RestrictedListPreference pref = new RestrictedListPreference(mContext, null);
+        ImportancePreference pref = new ImportancePreference(mContext, null);
         when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(pref);
         mController.displayPreference(mScreen);
         mController.updateState(pref);
 
-        pref.setValue(String.valueOf(IMPORTANCE_HIGH));
-        mController.onPreferenceChange(pref, pref.getValue());
+        mController.onPreferenceChange(pref, IMPORTANCE_HIGH);
 
         assertEquals(IMPORTANCE_HIGH, channel.getImportance());
         assertNotNull(channel.getSound());
@@ -200,13 +199,12 @@
         channel.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT);
         mController.onResume(new NotificationBackend.AppRow(), channel, null, null);
 
-        RestrictedListPreference pref = new RestrictedListPreference(mContext, null);
+        ImportancePreference pref = new ImportancePreference(mContext, null);
         when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(pref);
         mController.displayPreference(mScreen);
         mController.updateState(pref);
 
-        pref.setValue(String.valueOf(IMPORTANCE_LOW));
-        mController.onPreferenceChange(pref, pref.getValue());
+        mController.onPreferenceChange(pref, IMPORTANCE_LOW);
 
         assertEquals(IMPORTANCE_LOW, channel.getImportance());
         assertNull(channel.getSound());
diff --git a/tests/robotests/src/com/android/settings/notification/ImportancePreferenceTest.java b/tests/robotests/src/com/android/settings/notification/ImportancePreferenceTest.java
new file mode 100644
index 0000000..eebfbd1
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/ImportancePreferenceTest.java
@@ -0,0 +1,192 @@
+/*
+ * 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.NotificationManager.IMPORTANCE_DEFAULT;
+import static android.app.NotificationManager.IMPORTANCE_LOW;
+
+import static com.google.common.truth.Truth.assertThat;
+
+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 android.content.Context;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.GradientDrawable;
+import android.graphics.drawable.LayerDrawable;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.ImageButton;
+import android.widget.LinearLayout;
+import android.widget.Switch;
+
+import com.android.settings.R;
+import com.android.settingslib.RestrictedLockUtils;
+
+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;
+import androidx.preference.PreferenceViewHolder;
+
+@RunWith(RobolectricTestRunner.class)
+public class ImportancePreferenceTest {
+
+    private Context mContext;
+
+    @Before
+    public void setUp() {
+        mContext = RuntimeEnvironment.application;
+    }
+
+    private GradientDrawable getBackground(ImageButton button) {
+        return (GradientDrawable) ((LayerDrawable) button.getDrawable())
+                .findDrawableByLayerId(R.id.back);
+    }
+
+    @Test
+    public void createNewPreference_shouldSetLayout() {
+        final ImportancePreference preference = new ImportancePreference(mContext);
+        assertThat(preference.getLayoutResource()).isEqualTo(
+                R.layout.notif_importance_preference);
+    }
+
+    @Test
+    public void onBindViewHolder_hideBlockNonBlockable() {
+        final ImportancePreference preference = new ImportancePreference(mContext);
+        final LayoutInflater inflater = LayoutInflater.from(mContext);
+        final PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(
+                inflater.inflate(R.layout.notif_importance_preference, null));
+
+        preference.setBlockable(false);
+        preference.setConfigurable(true);
+        preference.setImportance(IMPORTANCE_DEFAULT);
+        preference.onBindViewHolder(holder);
+
+        assertThat(holder.itemView.findViewById(R.id.block).getVisibility()).isEqualTo(View.GONE);
+    }
+
+    @Test
+    public void onBindViewHolder_hideNonSelectedNonConfigurable() {
+        final ImportancePreference preference = new ImportancePreference(mContext);
+        final LayoutInflater inflater = LayoutInflater.from(mContext);
+        PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(
+                inflater.inflate(R.layout.notif_importance_preference, null));
+
+        preference.setBlockable(true);
+        preference.setConfigurable(false);
+        preference.setImportance(IMPORTANCE_DEFAULT);
+        preference.onBindViewHolder(holder);
+
+        assertThat(holder.itemView.findViewById(R.id.block).getVisibility()).isEqualTo(View.GONE);
+        assertThat(holder.itemView.findViewById(R.id.silence).getVisibility()).isEqualTo(View.GONE);
+        assertThat(holder.itemView.findViewById(R.id.alert).getVisibility())
+                .isEqualTo(View.VISIBLE);
+
+        // other button
+        preference.setImportance(IMPORTANCE_LOW);
+        holder = PreferenceViewHolder.createInstanceForTests(
+                inflater.inflate(R.layout.notif_importance_preference, null));
+        preference.onBindViewHolder(holder);
+
+        assertThat(holder.itemView.findViewById(R.id.block).getVisibility()).isEqualTo(View.GONE);
+        assertThat(holder.itemView.findViewById(R.id.silence).getVisibility())
+                .isEqualTo(View.VISIBLE);
+        assertThat(holder.itemView.findViewById(R.id.alert).getVisibility())
+                .isEqualTo(View.GONE);
+    }
+
+    @Test
+    public void onBindViewHolder_selectButton() {
+        final ImportancePreference preference = new ImportancePreference(mContext);
+        final LayoutInflater inflater = LayoutInflater.from(mContext);
+        final PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(
+                inflater.inflate(R.layout.notif_importance_preference, null));
+
+        preference.setBlockable(true);
+        preference.setConfigurable(true);
+        preference.setImportance(IMPORTANCE_DEFAULT);
+
+        ImageButton blockButton = (ImageButton) holder.findViewById(R.id.block_icon);
+        ImageButton silenceButton = (ImageButton) holder.findViewById(R.id.silence_icon);
+        ImageButton alertButton = (ImageButton) holder.findViewById(R.id.alert_icon);
+
+        preference.onBindViewHolder(holder);
+
+        // selected has full color background. others are transparent
+        assertThat(getBackground(alertButton).getColor().getColors()[0]).isNotEqualTo(
+                Color.TRANSPARENT);
+        assertThat(getBackground(silenceButton).getColor().getColors()[0]).isEqualTo(
+                Color.TRANSPARENT);
+        assertThat(getBackground(blockButton).getColor().getColors()[0]).isEqualTo(
+                Color.TRANSPARENT);
+    }
+
+    @Test
+    public void onClick_changesUICallsListener() {
+        final ImportancePreference preference = spy(new ImportancePreference(mContext));
+        final LayoutInflater inflater = LayoutInflater.from(mContext);
+        final PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(
+                inflater.inflate(R.layout.notif_importance_preference, null));
+
+        preference.setBlockable(true);
+        preference.setConfigurable(true);
+        preference.setImportance(IMPORTANCE_DEFAULT);
+        preference.onBindViewHolder(holder);
+
+        ImageButton blockButton = (ImageButton) holder.findViewById(R.id.block_icon);
+        ImageButton silenceButton = (ImageButton) holder.findViewById(R.id.silence_icon);
+        ImageButton alertButton = (ImageButton) holder.findViewById(R.id.alert_icon);
+
+        silenceButton.callOnClick();
+
+        // selected has full color background. others are transparent
+        assertThat(getBackground(silenceButton).getColor().getColors()[0]).isNotEqualTo(
+                Color.TRANSPARENT);
+        assertThat(getBackground(alertButton).getColor().getColors()[0]).isEqualTo(
+                Color.TRANSPARENT);
+        assertThat(getBackground(blockButton).getColor().getColors()[0]).isEqualTo(
+                Color.TRANSPARENT);
+
+        verify(preference, times(1)).callChangeListener(IMPORTANCE_LOW);
+    }
+
+    @Test
+    public void onBindViewHolder_allButtonsVisible() {
+        final ImportancePreference preference = new ImportancePreference(mContext);
+        final LayoutInflater inflater = LayoutInflater.from(mContext);
+        final PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(
+                inflater.inflate(R.layout.notif_importance_preference, null));
+
+        preference.setBlockable(true);
+        preference.setConfigurable(true);
+        preference.onBindViewHolder(holder);
+
+        assertThat(holder.itemView.findViewById(R.id.block).getVisibility())
+                .isEqualTo(View.VISIBLE);
+        assertThat(holder.itemView.findViewById(R.id.silence).getVisibility())
+                .isEqualTo(View.VISIBLE);
+        assertThat(holder.itemView.findViewById(R.id.alert).getVisibility())
+                .isEqualTo(View.VISIBLE);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/MinImportancePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/MinImportancePreferenceControllerTest.java
new file mode 100644
index 0000000..28058a4
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/MinImportancePreferenceControllerTest.java
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import static android.app.NotificationChannel.DEFAULT_CHANNEL_ID;
+import static android.app.NotificationManager.IMPORTANCE_LOW;
+import static android.app.NotificationManager.IMPORTANCE_MIN;
+import static android.app.NotificationManager.IMPORTANCE_NONE;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+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 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 MinImportancePreferenceControllerTest {
+
+    private Context mContext;
+    @Mock
+    private NotificationManager mNm;
+    @Mock
+    private NotificationBackend mBackend;
+    @Mock
+    private NotificationSettingsBase.ImportanceListener mImportanceListener;
+    @Mock
+    private UserManager mUm;
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private PreferenceScreen mScreen;
+
+    private MinImportancePreferenceController mController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        ShadowApplication shadowApplication = ShadowApplication.getInstance();
+        shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNm);
+        shadowApplication.setSystemService(Context.USER_SERVICE, mUm);
+        mContext = RuntimeEnvironment.application;
+        mController = spy(new MinImportancePreferenceController(
+                mContext, mImportanceListener, mBackend));
+    }
+
+    @Test
+    public void testNoCrashIfNoOnResume() {
+        mController.isAvailable();
+        mController.updateState(mock(Preference.class));
+    }
+
+    @Test
+    public void testIsAvailable_notIfNull() {
+        mController.onResume(null, null, null, null);
+        assertFalse(mController.isAvailable());
+    }
+
+    @Test
+    public void testIsAvailable_ifAppBlocked() {
+        NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+        appRow.banned = true;
+        mController.onResume(appRow, mock(NotificationChannel.class), null, null);
+        assertFalse(mController.isAvailable());
+    }
+
+    @Test
+    public void testIsAvailable_notIfChannelBlocked() {
+        NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+        NotificationChannel channel = mock(NotificationChannel.class);
+        when(channel.getImportance()).thenReturn(IMPORTANCE_NONE);
+        mController.onResume(appRow, channel, null, null);
+        assertFalse(mController.isAvailable());
+    }
+
+    @Test
+    public void testIsAvailable_notForDefaultChannel() {
+        NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+        NotificationChannel channel = mock(NotificationChannel.class);
+        when(channel.getImportance()).thenReturn(IMPORTANCE_LOW);
+        when(channel.getId()).thenReturn(DEFAULT_CHANNEL_ID);
+        mController.onResume(appRow, channel, null, null);
+        assertFalse(mController.isAvailable());
+    }
+
+    @Test
+    public void testIsAvailable() {
+        NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+        NotificationChannel channel = mock(NotificationChannel.class);
+        when(channel.getImportance()).thenReturn(IMPORTANCE_LOW);
+        mController.onResume(appRow, channel, null, null);
+        assertTrue(mController.isAvailable());
+    }
+
+    @Test
+    public void testUpdateState_disabledByAdmin() {
+        NotificationChannel channel = mock(NotificationChannel.class);
+        when(channel.getImportance()).thenReturn(IMPORTANCE_LOW);
+        mController.onResume(new NotificationBackend.AppRow(), channel, null, mock(
+                RestrictedLockUtils.EnforcedAdmin.class));
+
+        Preference pref = new RestrictedSwitchPreference(mContext, null);
+        mController.updateState(pref);
+
+        assertFalse(pref.isEnabled());
+    }
+
+    @Test
+    public void testUpdateState_notConfigurable() {
+        String lockedId = "locked";
+        NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+        appRow.lockedChannelId = lockedId;
+        NotificationChannel channel = mock(NotificationChannel.class);
+        when(channel.getId()).thenReturn(lockedId);
+        when(channel.getImportance()).thenReturn(IMPORTANCE_LOW);
+        mController.onResume(appRow, channel, null, null);
+
+        Preference pref = new RestrictedSwitchPreference(mContext, null);
+        mController.updateState(pref);
+
+        assertFalse(pref.isEnabled());
+    }
+
+    @Test
+    public void testUpdateState_min() {
+        NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+        NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_MIN);
+        mController.onResume(appRow, channel, null, null);
+
+        RestrictedSwitchPreference pref = new RestrictedSwitchPreference(mContext);
+        mController.updateState(pref);
+
+        assertTrue(pref.isChecked());
+    }
+
+    @Test
+    public void testUpdateState_low() {
+        NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+        NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_LOW);
+        mController.onResume(appRow, channel, null, null);
+
+        RestrictedSwitchPreference pref = new RestrictedSwitchPreference(mContext);
+        mController.updateState(pref);
+
+        assertFalse(pref.isChecked());
+    }
+    
+    @Test
+    public void onPreferenceChange() {
+        NotificationChannel channel =
+                new NotificationChannel(DEFAULT_CHANNEL_ID, "a", IMPORTANCE_LOW);
+        mController.onResume(new NotificationBackend.AppRow(), channel, null, null);
+
+        RestrictedSwitchPreference pref = new RestrictedSwitchPreference(mContext, null);
+        when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(pref);
+        mController.displayPreference(mScreen);
+        mController.updateState(pref);
+
+        mController.onPreferenceChange(pref, true);
+
+        assertEquals(IMPORTANCE_MIN, channel.getImportance());
+        verify(mImportanceListener, times(1)).onImportanceChanged();
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/NotificationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/NotificationPreferenceControllerTest.java
index 1ad9378..2368af5 100644
--- a/tests/robotests/src/com/android/settings/notification/NotificationPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/NotificationPreferenceControllerTest.java
@@ -219,6 +219,20 @@
     }
 
     @Test
+    public void testIsConfigurable_appLevel() {
+        NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+        appRow.lockedChannelId = "something";
+        appRow.lockedImportance = true;
+
+        mController.onResume(appRow, mock(NotificationChannel.class), null, null);
+        assertFalse(mController.isChannelConfigurable());
+
+        appRow.lockedImportance = false;
+        mController.onResume(appRow, mock(NotificationChannel.class), null, null);
+        assertTrue(mController.isChannelConfigurable());
+    }
+
+    @Test
     public void testIsChannelBlockable_nonSystemAppsBlockable() {
         NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
         appRow.systemApp = false;
diff --git a/tests/robotests/src/com/android/settings/notification/RemoteVolumePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/RemoteVolumePreferenceControllerTest.java
index 1bf2fd8..1e68de5 100644
--- a/tests/robotests/src/com/android/settings/notification/RemoteVolumePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/RemoteVolumePreferenceControllerTest.java
@@ -23,7 +23,7 @@
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
-import android.media.session.ControllerLink;
+import android.media.session.ISessionController;
 import android.media.session.MediaController;
 import android.media.session.MediaSession;
 import android.media.session.MediaSessionManager;
@@ -51,9 +51,9 @@
     @Mock
     private MediaController mMediaController;
     @Mock
-    private ControllerLink.ControllerStub mStub;
+    private ISessionController mStub;
     @Mock
-    private ControllerLink.ControllerStub mStub2;
+    private ISessionController mStub2;
     private MediaSession.Token mToken;
     private MediaSession.Token mToken2;
     private RemoteVolumePreferenceController mController;
@@ -71,8 +71,8 @@
         mActiveSessions.add(mMediaController);
         when(mMediaSessionManager.getActiveSessions(null)).thenReturn(
                 mActiveSessions);
-        mToken = new MediaSession.Token(new ControllerLink(mStub));
-        mToken2 = new MediaSession.Token(new ControllerLink(mStub2));
+        mToken = new MediaSession.Token(mStub);
+        mToken2 = new MediaSession.Token(mStub2);
 
         mController = new RemoteVolumePreferenceController(mContext);
         mPlaybackInfo = new MediaController.PlaybackInfo(
diff --git a/tests/robotests/src/com/android/settings/notification/ZenAccessSettingsTest.java b/tests/robotests/src/com/android/settings/notification/ZenAccessSettingsTest.java
deleted file mode 100644
index c2a6f4f..0000000
--- a/tests/robotests/src/com/android/settings/notification/ZenAccessSettingsTest.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.settings.notification;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.verify;
-
-import android.content.Context;
-
-import com.android.internal.logging.nano.MetricsProto;
-import com.android.settings.testutils.FakeFeatureFactory;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Answers;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-
-@RunWith(RobolectricTestRunner.class)
-public class ZenAccessSettingsTest {
-
-    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
-    private Context mContext;
-
-    private FakeFeatureFactory mFeatureFactory;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-
-        mFeatureFactory = FakeFeatureFactory.setupForTest();
-    }
-
-    @Test
-    public void logSpecialPermissionChange() {
-        ZenAccessSettings.logSpecialPermissionChange(true, "app", mContext);
-        verify(mFeatureFactory.metricsFeatureProvider).action(any(Context.class),
-                eq(MetricsProto.MetricsEvent.APP_SPECIAL_PERMISSION_DND_ALLOW),
-                eq("app"));
-
-        ZenAccessSettings.logSpecialPermissionChange(false, "app", mContext);
-        verify(mFeatureFactory.metricsFeatureProvider).action(any(Context.class),
-                eq(MetricsProto.MetricsEvent.APP_SPECIAL_PERMISSION_DND_DENY),
-                eq("app"));
-    }
-}
diff --git a/tests/robotests/src/com/android/settings/panel/VolumePanelTest.java b/tests/robotests/src/com/android/settings/panel/VolumePanelTest.java
index 4665dc9..11de7b3 100644
--- a/tests/robotests/src/com/android/settings/panel/VolumePanelTest.java
+++ b/tests/robotests/src/com/android/settings/panel/VolumePanelTest.java
@@ -48,6 +48,7 @@
                 CustomSliceRegistry.VOLUME_REMOTE_MEDIA_URI,
                 CustomSliceRegistry.VOLUME_CALL_URI,
                 CustomSliceRegistry.VOLUME_MEDIA_URI,
+                CustomSliceRegistry.MEDIA_OUTPUT_INDICATOR_SLICE_URI,
                 CustomSliceRegistry.VOLUME_RINGER_URI,
                 CustomSliceRegistry.VOLUME_ALARM_URI);
     }
diff --git a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
index a693f34..23025b2 100644
--- a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
@@ -135,7 +135,6 @@
         mProvider.mSliceWeakDataCache = new HashMap<>();
         mProvider.mSliceDataCache = new HashMap<>();
         mProvider.mSlicesDatabaseAccessor = new SlicesDatabaseAccessor(mContext);
-        mProvider.mCustomSliceManager = new CustomSliceManager(mContext);
         when(mProvider.getContext()).thenReturn(mContext);
 
         SlicesDatabaseHelper.getInstance(mContext).setIndexedState();
diff --git a/tests/robotests/src/com/android/settings/slices/SliceBroadcastReceiverTest.java b/tests/robotests/src/com/android/settings/slices/SliceBroadcastReceiverTest.java
index 74f4ac2..1ea324d 100644
--- a/tests/robotests/src/com/android/settings/slices/SliceBroadcastReceiverTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SliceBroadcastReceiverTest.java
@@ -19,14 +19,12 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
 
 import android.app.settings.SettingsEnums;
 import android.app.slice.Slice;
@@ -82,9 +80,6 @@
         mSearchFeatureProvider = new SearchFeatureProviderImpl();
         mFakeFeatureFactory = FakeFeatureFactory.setupForTest();
         mFakeFeatureFactory.searchFeatureProvider = mSearchFeatureProvider;
-        CustomSliceManager manager = new CustomSliceManager(mContext);
-        when(mFakeFeatureFactory.slicesFeatureProvider.getCustomSliceManager(any()))
-                .thenReturn(manager);
     }
 
     @After
diff --git a/tests/robotests/src/com/android/settings/slices/SlicesDatabaseHelperTest.java b/tests/robotests/src/com/android/settings/slices/SlicesDatabaseHelperTest.java
index 0e92c05..96bca07 100644
--- a/tests/robotests/src/com/android/settings/slices/SlicesDatabaseHelperTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SlicesDatabaseHelperTest.java
@@ -55,6 +55,7 @@
     @After
     public void cleanUp() {
         DatabaseTestUtils.clearDb(mContext);
+        mDatabase.close();
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/slices/SpecialCaseSliceManagerTest.java b/tests/robotests/src/com/android/settings/slices/SpecialCaseSliceManagerTest.java
index 82726df..d483f9e 100644
--- a/tests/robotests/src/com/android/settings/slices/SpecialCaseSliceManagerTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SpecialCaseSliceManagerTest.java
@@ -19,8 +19,6 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.Mockito.spy;
-
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
@@ -39,44 +37,50 @@
 @RunWith(RobolectricTestRunner.class)
 public class SpecialCaseSliceManagerTest {
 
-    private Context mContext;
+    private final String FAKE_PARAMETER_KEY = "fake_parameter_key";
+    private final String FAKE_PARAMETER_VALUE = "fake_value";
 
-    private CustomSliceManager mCustomSliceManager;
+    private Context mContext;
 
     @Before
     public void setUp() {
         mContext = RuntimeEnvironment.application;
-        mCustomSliceManager = spy(new CustomSliceManager(mContext));
-        mCustomSliceManager.mUriMap.clear();
-        mCustomSliceManager.mUriMap.put(FakeSliceable.URI, FakeSliceable.class);
+        CustomSliceRegistry.sUriToSlice.clear();
+        CustomSliceRegistry.sUriToSlice.put(FakeSliceable.URI, FakeSliceable.class);
     }
 
     @Test
     public void getSliceableFromUri_returnsCorrectObject() {
-        final CustomSliceable sliceable = mCustomSliceManager.getSliceableFromUri(
-                FakeSliceable.URI);
+        final CustomSliceable sliceable = CustomSliceable.createInstance(
+                mContext, CustomSliceRegistry.getSliceClassByUri(FakeSliceable.URI));
 
         assertThat(sliceable).isInstanceOf(FakeSliceable.class);
     }
 
     @Test
-    public void getSliceableFromIntentAction_returnsCorrectObject() {
-        final CustomSliceable sliceable =
-                mCustomSliceManager.getSliceableFromIntentAction(FakeSliceable.URI.toString());
+    public void getSliceableFromUriWithParameter_returnsCorrectObject() {
+        final Uri parameterUri = FakeSliceable.URI
+                .buildUpon()
+                .clearQuery()
+                .appendQueryParameter(FAKE_PARAMETER_KEY, FAKE_PARAMETER_VALUE)
+                .build();
+
+        final CustomSliceable sliceable = CustomSliceable.createInstance(
+                mContext, CustomSliceRegistry.getSliceClassByUri(parameterUri));
 
         assertThat(sliceable).isInstanceOf(FakeSliceable.class);
     }
 
     @Test
     public void isValidUri_validUri_returnsTrue() {
-        final boolean isValidUri = mCustomSliceManager.isValidUri(FakeSliceable.URI);
+        final boolean isValidUri = CustomSliceRegistry.isValidUri(FakeSliceable.URI);
 
         assertThat(isValidUri).isTrue();
     }
 
     @Test
     public void isValidUri_invalidUri_returnsFalse() {
-        final boolean isValidUri = mCustomSliceManager.isValidUri(null);
+        final boolean isValidUri = CustomSliceRegistry.isValidUri(null);
 
         assertThat(isValidUri).isFalse();
     }
@@ -84,14 +88,14 @@
     @Test
     public void isValidAction_validActions_returnsTrue() {
         final boolean isValidAction =
-                mCustomSliceManager.isValidAction(FakeSliceable.URI.toString());
+                CustomSliceRegistry.isValidAction(FakeSliceable.URI.toString());
 
         assertThat(isValidAction).isTrue();
     }
 
     @Test
     public void isValidAction_invalidAction_returnsFalse() {
-        final boolean isValidAction = mCustomSliceManager.isValidAction("action");
+        final boolean isValidAction = CustomSliceRegistry.isValidAction("action");
 
         assertThat(isValidAction).isFalse();
     }
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDisclaimerItemFactory.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDisclaimerItemFactory.java
new file mode 100644
index 0000000..c50d4f1
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDisclaimerItemFactory.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.testutils.shadow;
+
+import android.content.Context;
+
+import com.android.settings.wifi.calling.DisclaimerItemFactory;
+import com.android.settings.wifi.calling.DisclaimerItem;
+
+import java.util.List;
+
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+@Implements(DisclaimerItemFactory.class)
+public final class ShadowDisclaimerItemFactory {
+    private static List<DisclaimerItem> sMockDisclaimerItemList;
+
+    public static void setDisclaimerItemList(List<DisclaimerItem> list) {
+        sMockDisclaimerItemList = list;
+    }
+
+    @Implementation
+    public static List<DisclaimerItem> create(Context context, int subId) {
+        return sMockDisclaimerItemList;
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowNotificationManager.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowNotificationManager.java
index 8325777..78fb23f 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowNotificationManager.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowNotificationManager.java
@@ -19,15 +19,19 @@
 import android.app.NotificationManager;
 import android.net.Uri;
 import android.service.notification.ZenModeConfig;
+import android.util.ArraySet;
 
 import org.robolectric.annotation.Implementation;
 import org.robolectric.annotation.Implements;
 
+import java.util.Set;
+
 @Implements(NotificationManager.class)
 public class ShadowNotificationManager {
 
     private int mZenMode;
     private ZenModeConfig mZenModeConfig;
+    private Set<String> mNotificationPolicyGrantedPackages = new ArraySet<>();
 
     @Implementation
     protected void setZenMode(int mode, Uri conditionId, String reason) {
@@ -40,6 +44,11 @@
     }
 
     @Implementation
+    protected boolean isNotificationPolicyAccessGrantedForPackage(String pkg) {
+        return mNotificationPolicyGrantedPackages.contains(pkg);
+    }
+
+    @Implementation
     public ZenModeConfig getZenModeConfig() {
         return mZenModeConfig;
     }
@@ -47,4 +56,8 @@
     public void setZenModeConfig(ZenModeConfig config) {
         mZenModeConfig = config;
     }
+
+    public void setNotificationPolicyAccessGrantedForPackage(String pkg) {
+        mNotificationPolicyGrantedPackages.add(pkg);
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/wifi/ButtonPreferenceTest.java b/tests/robotests/src/com/android/settings/wifi/ButtonPreferenceTest.java
deleted file mode 100644
index 7f0598d..0000000
--- a/tests/robotests/src/com/android/settings/wifi/ButtonPreferenceTest.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.wifi;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.Context;
-import android.view.View;
-import android.widget.ImageButton;
-
-import androidx.preference.PreferenceViewHolder;
-
-import com.android.settings.R;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-@RunWith(RobolectricTestRunner.class)
-public class ButtonPreferenceTest {
-
-    private Context mContext;
-    private View mRootView;
-    private ButtonPreference mPref;
-    private PreferenceViewHolder mHolder;
-    private boolean mClicked;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-
-        mContext = RuntimeEnvironment.application;
-        mPref = new ButtonPreference(mContext);
-        mRootView = View.inflate(mContext, R.layout.wifi_button_preference_widget, /* parent */
-                null);
-        mHolder = PreferenceViewHolder.createInstanceForTests(mRootView);
-    }
-
-    @Test
-    public void initButton_noIcon_shouldInvisible() {
-        mPref.initButton(mHolder);
-        assertThat(mRootView.findViewById(R.id.button_icon).getVisibility()).isEqualTo(View.GONE);
-    }
-
-    @Test
-    public void initButton_withIcon_shouldVisible() {
-        mPref.setButtonIcon(R.drawable.ic_qrcode_24dp);
-        mPref.initButton(mHolder);
-        assertThat(mRootView.findViewById(R.id.button_icon).getVisibility()).isEqualTo(
-                View.VISIBLE);
-    }
-
-    @Test
-    public void initButton_whenClick_shouldCallback() {
-        mClicked = false;
-        mPref.setButtonIcon(R.drawable.ic_qrcode_24dp);
-        mPref.setButtonOnClickListener((View v) -> {
-            mClicked = true;
-        });
-        mPref.initButton(mHolder);
-        ImageButton button = (ImageButton) mRootView.findViewById(R.id.button_icon);
-        button.performClick();
-        assertThat(mClicked).isTrue();
-    }
-}
diff --git a/tests/robotests/src/com/android/settings/wifi/WifiSettingsTest.java b/tests/robotests/src/com/android/settings/wifi/WifiSettingsTest.java
index 22ccd3c..c811b0c 100644
--- a/tests/robotests/src/com/android/settings/wifi/WifiSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/WifiSettingsTest.java
@@ -69,6 +69,7 @@
         mWifiSettings = spy(new WifiSettings());
         doReturn(mContext).when(mWifiSettings).getContext();
         doReturn(mPowerManager).when(mContext).getSystemService(PowerManager.class);
+        mWifiSettings.mAddWifiNetworkPreference = new AddWifiNetworkPreference(mContext);
         mWifiSettings.mSavedNetworksPreference = new Preference(mContext);
         mWifiSettings.mConfigureWifiSettingsPreference = new Preference(mContext);
         mWifiSettings.mWifiTracker = mWifiTracker;
@@ -151,4 +152,11 @@
         assertThat(mWifiSettings.mConfigureWifiSettingsPreference.getSummary()).isEqualTo(
                 mContext.getString(R.string.wifi_configure_settings_preference_summary_wakeup_off));
     }
-}
\ No newline at end of file
+
+    @Test
+    public void checkAddWifiNetworkPrefernce_preferenceVisible() {
+        assertThat(mWifiSettings.mAddWifiNetworkPreference.isVisible()).isTrue();
+        assertThat(mWifiSettings.mAddWifiNetworkPreference.getTitle()).isEqualTo(
+                mContext.getString(R.string.wifi_add_network));
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/wifi/calling/DisclaimerItemListAdapterTest.java b/tests/robotests/src/com/android/settings/wifi/calling/DisclaimerItemListAdapterTest.java
new file mode 100644
index 0000000..4cfc9ba
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/wifi/calling/DisclaimerItemListAdapterTest.java
@@ -0,0 +1,126 @@
+/*
+ * 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.calling;
+
+import static com.android.settings.wifi.calling.DisclaimerItemListAdapter
+        .DisclaimerItemViewHolder.ID_DISCLAIMER_ITEM_TITLE;
+import static com.android.settings.wifi.calling.DisclaimerItemListAdapter
+        .DisclaimerItemViewHolder.ID_DISCLAIMER_ITEM_DESCRIPTION;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyObject;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import com.android.settings.R;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+
+@RunWith(RobolectricTestRunner.class)
+public class DisclaimerItemListAdapterTest {
+
+    private static final int ITEM_POSITION = 0;
+    private static final int DISCLAIMER_TITLE_STRING_ID = 0;
+    private static final int DISCLAIMER_MESSAGE_STRING_ID = 1;
+
+    @Mock
+    private LayoutInflater mLayoutInflater;
+    @Mock
+    private TextView mTestView;
+    @Mock
+    private TextView mDescView;
+    @Mock
+    private View mView;
+    @Mock
+    private ViewGroup mViewGroup;
+    @Mock
+    private Context mContext;
+
+    private MockDisclaimerItem mDisclaimerItem;
+    private DisclaimerItemListAdapter mDisclaimerItemListAdapter;
+    private List<DisclaimerItem> mDisclaimerItemList = new ArrayList<>();
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mDisclaimerItem = spy(new MockDisclaimerItem(mContext, 0 /* subId */));
+        mDisclaimerItemList.add(mDisclaimerItem);
+
+        when(mLayoutInflater.inflate(anyInt(), anyObject(), anyBoolean())).thenReturn(mView);
+        when(mViewGroup.getContext()).thenReturn(mContext);
+        when(mViewGroup.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE)).thenReturn(
+                mLayoutInflater);
+        when(mView.findViewById(ID_DISCLAIMER_ITEM_TITLE)).thenReturn(mTestView);
+        when(mView.findViewById(ID_DISCLAIMER_ITEM_DESCRIPTION)).thenReturn(mDescView);
+    }
+
+    @Test
+    public void onBindViewHolder_haveItem_shouldSetText() {
+        final DisclaimerItemListAdapter.DisclaimerItemViewHolder viewHolder =
+                new DisclaimerItemListAdapter.DisclaimerItemViewHolder(mView);
+
+        mDisclaimerItemListAdapter = new DisclaimerItemListAdapter(mDisclaimerItemList);
+        mDisclaimerItemListAdapter.onCreateViewHolder(mViewGroup, 0 /* viewType */);
+        mDisclaimerItemListAdapter.onBindViewHolder(viewHolder, ITEM_POSITION);
+
+        // Check the text is set when the DisclaimerItem exists.
+        verify(viewHolder.titleView).setText(DISCLAIMER_TITLE_STRING_ID);
+        verify(viewHolder.descriptionView).setText(DISCLAIMER_MESSAGE_STRING_ID);
+    }
+
+    private class MockDisclaimerItem extends DisclaimerItem {
+        MockDisclaimerItem(Context context, int subId) {
+            super(context, subId);
+        }
+
+        @Override
+        protected int getTitleId() {
+            return DISCLAIMER_TITLE_STRING_ID;
+        }
+
+        @Override
+        protected int getMessageId() {
+            return DISCLAIMER_MESSAGE_STRING_ID;
+        }
+
+        @Override
+        protected String getName() {
+            return "MockDisclaimerItem";
+        }
+
+        @Override
+        protected String getPrefKey() {
+            return "mock_pref_key";
+        }
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/wifi/calling/ListWithEntrySummaryPreferenceTest.java b/tests/robotests/src/com/android/settings/wifi/calling/ListWithEntrySummaryPreferenceTest.java
index cc2622f..307c0ac 100644
--- a/tests/robotests/src/com/android/settings/wifi/calling/ListWithEntrySummaryPreferenceTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/calling/ListWithEntrySummaryPreferenceTest.java
@@ -33,8 +33,6 @@
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 
-import java.io.IOException;
-
 @RunWith(RobolectricTestRunner.class)
 public class ListWithEntrySummaryPreferenceTest {
 
@@ -54,6 +52,7 @@
     @Before
     public void setUp() {
         mContext = RuntimeEnvironment.application;
+        mContext.setTheme(R.style.Theme_Settings_Home);
         mPreference = new ListWithEntrySummaryPreference(mContext, null);
         mPreference.setEntries(mDefaultEntries);
         mPreference.setEntryValues(mDefaultEntryValues);
diff --git a/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingDisclaimerFragmentTest.java b/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingDisclaimerFragmentTest.java
new file mode 100644
index 0000000..6c221e7
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingDisclaimerFragmentTest.java
@@ -0,0 +1,180 @@
+/*
+ * 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.calling;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyObject;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.Activity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.Button;
+
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.recyclerview.widget.RecyclerView.OnScrollListener;
+
+import com.android.settings.R;
+import com.android.settings.testutils.shadow.ShadowDisclaimerItemFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+import org.robolectric.Robolectric;
+import org.robolectric.RobolectricTestRunner;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = ShadowDisclaimerItemFactory.class)
+public class WifiCallingDisclaimerFragmentTest {
+
+    @Mock
+    private Activity mActivity;
+    @Mock
+    private DisclaimerItem mDisclaimerItem;
+    @Mock
+    private LayoutInflater mLayoutInflater;
+    @Mock
+    private View mView;
+    @Mock
+    private ViewGroup mViewGroup;
+    @Mock
+    private Button mAgreeButton;
+    @Mock
+    private Button mDisagreeButton;
+    @Mock
+    private RecyclerView mRecyclerView;
+
+    @Captor
+    ArgumentCaptor<OnClickListener> mOnClickListenerCaptor;
+    @Captor
+    ArgumentCaptor<OnScrollListener> mOnScrollListenerCaptor;
+
+    private WifiCallingDisclaimerFragment mFragment;
+    private List<DisclaimerItem> mDisclaimerItemList = new ArrayList<>();
+    private List<DisclaimerItem> mEmptyDisclaimerItemList = new ArrayList<>();
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mActivity = Robolectric.setupActivity(Activity.class);
+        mFragment = spy(new WifiCallingDisclaimerFragment());
+
+        doReturn(mActivity).when(mFragment).getActivity();
+
+        when(mLayoutInflater.inflate(anyInt(), anyObject(), anyBoolean())).thenReturn(mView);
+        when(mView.findViewById(R.id.agree_button)).thenReturn(mAgreeButton);
+        when(mView.findViewById(R.id.disagree_button)).thenReturn(mDisagreeButton);
+        when(mView.findViewById(R.id.disclaimer_item_list)).thenReturn(mRecyclerView);
+        when(mView.getId()).thenReturn(R.id.agree_button);
+
+        mOnScrollListenerCaptor = ArgumentCaptor.forClass(OnScrollListener.class);
+        doNothing().when(mRecyclerView).addOnScrollListener(mOnScrollListenerCaptor.capture());
+        mOnClickListenerCaptor = ArgumentCaptor.forClass(OnClickListener.class);
+        doNothing().when(mAgreeButton).setOnClickListener(mOnClickListenerCaptor.capture());
+
+        mDisclaimerItemList.add(mDisclaimerItem);
+    }
+
+    @Test
+    public void onCreate_notHaveItem_shouldFinishFragment() {
+        ShadowDisclaimerItemFactory.setDisclaimerItemList(mEmptyDisclaimerItemList);
+
+        mFragment.onCreate(null /* savedInstanceState */);
+
+        // Check the fragment is finished when the DisclaimerItemList is empty.
+        verify(mFragment).finish(Activity.RESULT_OK);
+    }
+
+    @Test
+    public void onCreate_haveItem_shouldNotFinishFragment() {
+        ShadowDisclaimerItemFactory.setDisclaimerItemList(mDisclaimerItemList);
+
+        mFragment.onCreate(null /* savedInstanceState */);
+
+        // Check the fragment is not finished when the DisclaimerItemList is not empty.
+        verify(mFragment, never()).finish(Activity.RESULT_OK);
+    }
+
+    @Test
+    public void onScrolled_canNotScroll_shouldEnableAgreeButton() {
+        ShadowDisclaimerItemFactory.setDisclaimerItemList(mDisclaimerItemList);
+
+        when(mRecyclerView.canScrollVertically(1)).thenReturn(false);
+
+        mFragment.onCreate(null /* savedInstanceState */);
+        mFragment.onCreateView(mLayoutInflater, mViewGroup, null /* savedInstanceState */);
+
+        mOnScrollListenerCaptor.getValue().onScrolled(mRecyclerView, 0, 0);
+
+        // Check the agreeButton is enabled when the view is scrolled to the bottom end.
+        verify(mAgreeButton).setEnabled(true);
+        // Check the OnScrollListener is removed when the view is scrolled to the bottom end.
+        verify(mRecyclerView).removeOnScrollListener(any());
+    }
+
+    @Test
+    public void onScrolled_canScroll_shouldNotEnableAgreeButton() {
+        ShadowDisclaimerItemFactory.setDisclaimerItemList(mDisclaimerItemList);
+
+        when(mRecyclerView.canScrollVertically(1)).thenReturn(true);
+
+        mFragment.onCreate(null /* savedInstanceState */);
+        mFragment.onCreateView(mLayoutInflater, mViewGroup, null /* savedInstanceState */);
+
+        mOnScrollListenerCaptor.getValue().onScrolled(mRecyclerView, 0, 0);
+
+        // Check the agreeButton is not enabled when the view is not scrolled to the bottom end.
+        verify(mAgreeButton, never()).setEnabled(anyBoolean());
+        // Check the OnScrollListener is not removed when the view is not scrolled to
+        // the bottom end.
+        verify(mRecyclerView, never()).removeOnScrollListener(any());
+    }
+
+    @Test
+    public void onClick_agreeButton_shouldFinishFragment() {
+        ShadowDisclaimerItemFactory.setDisclaimerItemList(mDisclaimerItemList);
+
+        mFragment.onCreate(null /* savedInstanceState */);
+        mFragment.onCreateView(mLayoutInflater, mViewGroup, null /* savedInstanceState */);
+
+        mOnClickListenerCaptor.getValue().onClick(mAgreeButton);
+
+        // Check the onAgreed callback is called when "CONTINUE" button is clicked.
+        verify(mDisclaimerItem).onAgreed();
+        // Check the WFC disclaimer fragment is finished when "CONTINUE" button is clicked.
+        verify(mFragment).finish(Activity.RESULT_OK);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSettingsForSubTest.java b/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSettingsForSubTest.java
index 39de254..ae88231 100644
--- a/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSettingsForSubTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSettingsForSubTest.java
@@ -16,11 +16,14 @@
 
 package com.android.settings.wifi.calling;
 
+import static com.android.settings.SettingsActivity.EXTRA_SHOW_FRAGMENT;
 import static com.google.common.truth.Truth.assertThat;
 
+import static junit.framework.Assert.assertEquals;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyBoolean;
 import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.eq;
@@ -31,6 +34,8 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.app.Activity;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
@@ -41,20 +46,22 @@
 import android.view.View;
 import android.widget.TextView;
 
-import androidx.preference.ListPreference;
+import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
 
 import com.android.ims.ImsConfig;
-import com.android.ims.ImsException;
 import com.android.ims.ImsManager;
 import com.android.settings.R;
 import com.android.settings.SettingsActivity;
+import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.shadow.SettingsShadowResources;
 import com.android.settings.widget.SwitchBar;
 import com.android.settings.widget.ToggleSwitch;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
@@ -65,6 +72,8 @@
 public class WifiCallingSettingsForSubTest {
     private static final String BUTTON_WFC_MODE = "wifi_calling_mode";
     private static final String BUTTON_WFC_ROAMING_MODE = "wifi_calling_roaming_mode";
+    private static final String TEST_EMERGENCY_ADDRESS_CARRIER_APP =
+            "com.android.settings/.wifi.calling.TestEmergencyAddressCarrierApp";
 
     private TestFragment mFragment;
     private Context mContext;
@@ -72,6 +81,7 @@
     private final PersistableBundle mBundle = new PersistableBundle();
 
     @Mock private static CarrierConfigManager sCarrierConfigManager;
+    @Mock private CarrierConfigManager mMockConfigManager;
     @Mock private ImsManager mImsManager;
     @Mock private TelephonyManager mTelephonyManager;
     @Mock private PreferenceScreen mPreferenceScreen;
@@ -80,11 +90,12 @@
     @Mock private ToggleSwitch mToggleSwitch;
     @Mock private View mView;
     @Mock private ImsConfig mImsConfig;
-    @Mock private ListPreference mButtonWfcMode;
-    @Mock private ListPreference mButtonWfcRoamingMode;
+    @Mock private ListWithEntrySummaryPreference mButtonWfcMode;
+    @Mock private ListWithEntrySummaryPreference mButtonWfcRoamingMode;
+    @Mock private Preference mUpdateAddress;
 
     @Before
-    public void setUp() throws NoSuchFieldException, ImsException {
+    public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
 
         mContext = RuntimeEnvironment.application;
@@ -100,7 +111,7 @@
         final Bundle bundle = new Bundle();
         when(mFragment.getArguments()).thenReturn(bundle);
         doNothing().when(mFragment).addPreferencesFromResource(anyInt());
-        doReturn(mock(ListPreference.class)).when(mFragment).findPreference(any());
+        doReturn(mock(ListWithEntrySummaryPreference.class)).when(mFragment).findPreference(any());
         doReturn(mButtonWfcMode).when(mFragment).findPreference(BUTTON_WFC_MODE);
         doReturn(mButtonWfcRoamingMode).when(mFragment).findPreference(BUTTON_WFC_ROAMING_MODE);
         doNothing().when(mFragment).finish();
@@ -123,6 +134,11 @@
         doReturn(mBundle).when(sCarrierConfigManager).getConfigForSubId(anyInt());
         setDefaultCarrierConfigValues();
 
+        doReturn(sCarrierConfigManager).when(mActivity).getSystemService(
+                CarrierConfigManager.class);
+        doReturn(mContext.getResources()).when(mFragment).getResourcesForSubId();
+        doNothing().when(mFragment).startActivityForResult(any(Intent.class), anyInt());
+
         mFragment.onAttach(mContext);
         mFragment.onCreate(null);
         mFragment.onActivityCreated(null);
@@ -133,6 +149,9 @@
                 CarrierConfigManager.KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL, false);
         mBundle.putBoolean(CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL, true);
         mBundle.putBoolean(CarrierConfigManager.KEY_EDITABLE_WFC_ROAMING_MODE_BOOL, true);
+        mBundle.putString(
+                CarrierConfigManager.KEY_WFC_EMERGENCY_ADDRESS_CARRIER_APP_STRING,
+                TEST_EMERGENCY_ADDRESS_CARRIER_APP);
     }
 
     @Test
@@ -141,7 +160,7 @@
     }
 
     @Test
-    public void onResume_provisioningAllowed_shouldNotFinish() throws ImsException {
+    public void onResume_provisioningAllowed_shouldNotFinish() {
         // Call onResume while provisioning is allowed.
         mFragment.onResume();
 
@@ -160,7 +179,7 @@
     }
 
     @Test
-    public void onResumeOnPause_provisioningCallbackRegistration() throws ImsException {
+    public void onResumeOnPause_provisioningCallbackRegistration() throws Exception {
         // Verify that provisioning callback is registered after call to onResume().
         mFragment.onResume();
         verify(mImsConfig).addConfigCallback(any(ProvisioningManager.Callback.class));
@@ -261,6 +280,61 @@
                 eq(true));
     }
 
+    @Test
+    public void onSwitchChanged_enableSetting_shouldLaunchWfcDisclaimerFragment() {
+        ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+
+        mFragment.onSwitchChanged(null, true);
+
+        // Check the WFC disclaimer fragment is launched.
+        verify(mFragment).startActivityForResult(intentCaptor.capture(),
+                eq(WifiCallingSettingsForSub.REQUEST_CHECK_WFC_DISCLAIMER));
+        Intent intent = intentCaptor.getValue();
+        assertThat(intent.getStringExtra(EXTRA_SHOW_FRAGMENT))
+                .isEqualTo(WifiCallingDisclaimerFragment.class.getName());
+    }
+
+    @Test
+    public void onActivityResult_finishWfcDisclaimerFragment_shouldLaunchCarrierActivity() {
+        ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+
+        // Emulate the WfcDisclaimerActivity finish.
+        mFragment.onActivityResult(WifiCallingSettingsForSub.REQUEST_CHECK_WFC_DISCLAIMER,
+                Activity.RESULT_OK, null);
+
+        // Check the WFC emergency address activity is launched.
+        verify(mFragment).startActivityForResult(intentCaptor.capture(),
+                eq(WifiCallingSettingsForSub.REQUEST_CHECK_WFC_EMERGENCY_ADDRESS));
+        Intent intent = intentCaptor.getValue();
+        assertEquals(intent.getComponent(), ComponentName.unflattenFromString(
+                TEST_EMERGENCY_ADDRESS_CARRIER_APP));
+    }
+
+    @Test
+    public void onActivityResult_finishCarrierActivity_shouldShowWfcPreference() {
+        ReflectionHelpers.setField(mFragment, "mButtonWfcMode", mButtonWfcMode);
+        ReflectionHelpers.setField(mFragment, "mButtonWfcRoamingMode", mButtonWfcRoamingMode);
+        ReflectionHelpers.setField(mFragment, "mUpdateAddress", mUpdateAddress);
+
+        mFragment.onActivityResult(WifiCallingSettingsForSub.REQUEST_CHECK_WFC_EMERGENCY_ADDRESS,
+                Activity.RESULT_OK, null);
+
+        // Check the WFC preferences is added.
+        verify(mPreferenceScreen).addPreference(mButtonWfcMode);
+        verify(mPreferenceScreen).addPreference(mButtonWfcRoamingMode);
+        verify(mPreferenceScreen).addPreference(mUpdateAddress);
+        // Check the WFC enable request.
+        verify(mImsManager).setWfcSetting(true);
+    }
+
+    @Test
+    public void onSwitchChanged_disableSetting_shouldNotLaunchWfcDisclaimerFragment() {
+        mFragment.onSwitchChanged(null, false);
+
+        // Check the WFC disclaimer fragment is not launched.
+        verify(mFragment, never()).startActivityForResult(any(Intent.class), anyInt());
+    }
+
     protected class TestFragment extends WifiCallingSettingsForSub {
         @Override
         protected Object getSystemService(final String name) {
diff --git a/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSliceHelperTest.java b/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSliceHelperTest.java
index f9109ce..644e5e8 100644
--- a/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSliceHelperTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSliceHelperTest.java
@@ -22,7 +22,6 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
@@ -48,7 +47,6 @@
 import com.android.ims.ImsConfig;
 import com.android.ims.ImsManager;
 import com.android.settings.R;
-import com.android.settings.slices.CustomSliceManager;
 import com.android.settings.slices.CustomSliceRegistry;
 import com.android.settings.slices.SettingsSliceProvider;
 import com.android.settings.slices.SliceBroadcastReceiver;
@@ -99,9 +97,6 @@
 
         mFeatureFactory = FakeFeatureFactory.setupForTest();
         mSlicesFeatureProvider = mFeatureFactory.getSlicesFeatureProvider();
-        CustomSliceManager manager = new CustomSliceManager(mContext);
-        when(mSlicesFeatureProvider.getCustomSliceManager(any(Context.class)))
-                .thenReturn(manager);
 
         mWfcSliceHelper = new FakeWifiCallingSliceHelper(mContext);
 
diff --git a/tests/robotests/src/com/android/settings/wifi/slice/ContextualWifiSliceTest.java b/tests/robotests/src/com/android/settings/wifi/slice/ContextualWifiSliceTest.java
index d681afe..520d988 100644
--- a/tests/robotests/src/com/android/settings/wifi/slice/ContextualWifiSliceTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/slice/ContextualWifiSliceTest.java
@@ -36,6 +36,8 @@
 
 import com.android.settings.R;
 import com.android.settings.slices.CustomSliceRegistry;
+import com.android.settings.slices.SlicesFeatureProviderImpl;
+import com.android.settings.testutils.FakeFeatureFactory;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -52,11 +54,15 @@
     private ContentResolver mResolver;
     private WifiManager mWifiManager;
     private ContextualWifiSlice mWifiSlice;
+    private FakeFeatureFactory mFeatureFactory;
 
     @Before
     public void setUp() {
         mContext = spy(RuntimeEnvironment.application);
         mResolver = mock(ContentResolver.class);
+        mFeatureFactory = FakeFeatureFactory.setupForTest();
+        mFeatureFactory.slicesFeatureProvider = new SlicesFeatureProviderImpl();
+        mFeatureFactory.slicesFeatureProvider.newUiSession();
         doReturn(mResolver).when(mContext).getContentResolver();
         mWifiManager = mContext.getSystemService(WifiManager.class);
 
@@ -65,10 +71,28 @@
         mWifiManager.setWifiEnabled(true);
 
         mWifiSlice = new ContextualWifiSlice(mContext);
+        mWifiSlice.sPreviouslyDisplayed = false;
     }
 
     @Test
     public void getWifiSlice_hasActiveConnection_shouldReturnNull() {
+        mWifiSlice.sPreviouslyDisplayed = false;
+        final WifiConfiguration config = new WifiConfiguration();
+        config.SSID = "123";
+        mWifiManager.connect(config, null /* listener */);
+
+        final Slice wifiSlice = mWifiSlice.getSlice();
+
+        assertThat(wifiSlice).isNull();
+    }
+
+    @Test
+    public void getWifiSlice_newSession_hasActiveConnection_shouldReturnNull() {
+        // Session: use a non-active value
+        // previous displayed: yes
+        mWifiSlice.sPreviouslyDisplayed = true;
+        mWifiSlice.sActiveUiSession = ~mFeatureFactory.slicesFeatureProvider.getUiSessionToken();
+
         final WifiConfiguration config = new WifiConfiguration();
         config.SSID = "123";
         mWifiManager.connect(config, null /* listener */);
@@ -80,7 +104,8 @@
 
     @Test
     public void getWifiSlice_previousDisplayed_hasActiveConnection_shouldHaveTitleAndToggle() {
-        mWifiSlice.mPreviouslyDisplayed = true;
+        mWifiSlice.sActiveUiSession = mFeatureFactory.slicesFeatureProvider.getUiSessionToken();
+        mWifiSlice.sPreviouslyDisplayed = true;
         final WifiConfiguration config = new WifiConfiguration();
         config.SSID = "123";
         mWifiManager.connect(config, null /* listener */);
@@ -101,7 +126,8 @@
 
     @Test
     public void getWifiSlice_contextualWifiSlice_shouldReturnContextualWifiSliceUri() {
-        mWifiSlice.mPreviouslyDisplayed = true;
+        mWifiSlice.sActiveUiSession = mFeatureFactory.slicesFeatureProvider.getUiSessionToken();
+        mWifiSlice.sPreviouslyDisplayed = true;
 
         final Slice wifiSlice = mWifiSlice.getSlice();
 
diff --git a/tests/robotests/src/com/android/settings/wifi/slice/WifiSliceTest.java b/tests/robotests/src/com/android/settings/wifi/slice/WifiSliceTest.java
index 01feb8e..75a9e11 100644
--- a/tests/robotests/src/com/android/settings/wifi/slice/WifiSliceTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/slice/WifiSliceTest.java
@@ -34,8 +34,10 @@
 import android.content.Context;
 import android.content.Intent;
 import android.net.NetworkInfo;
+import android.net.NetworkInfo.State;
 import android.net.Uri;
 import android.net.wifi.WifiManager;
+import android.os.Bundle;
 
 import androidx.core.graphics.drawable.IconCompat;
 import androidx.slice.Slice;
@@ -61,6 +63,7 @@
 import org.robolectric.annotation.Implements;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 @RunWith(RobolectricTestRunner.class)
@@ -253,11 +256,42 @@
         verify(mResolver).notifyChange(WIFI_SLICE_URI, null);
     }
 
-    @Test
-    public void onConnectedChanged_shouldNotifyChange() {
-        mWifiScanWorker.onConnectedChanged();
+    private AccessPoint createAccessPoint(String name, State state) {
+        final NetworkInfo info = mock(NetworkInfo.class);
+        doReturn(state).when(info).getState();
 
-        verify(mResolver).notifyChange(WIFI_SLICE_URI, null);
+        final Bundle savedState = new Bundle();
+        savedState.putString("key_ssid", name);
+        savedState.putParcelable("key_networkinfo", info);
+        return new AccessPoint(mContext, savedState);
+    }
+
+    @Test
+    public void SliceAccessPoint_sameState_shouldBeTheSame() {
+        final AccessPoint ap1 = createAccessPoint(AP1_NAME, State.CONNECTED);
+        final AccessPoint ap2 = createAccessPoint(AP1_NAME, State.CONNECTED);
+
+        assertThat(mWifiScanWorker.areListsTheSame(Arrays.asList(ap1), Arrays.asList(ap2)))
+                .isTrue();
+    }
+
+    @Test
+    public void SliceAccessPoint_differentState_shouldBeDifferent() {
+        final AccessPoint ap1 = createAccessPoint(AP1_NAME, State.CONNECTING);
+        final AccessPoint ap2 = createAccessPoint(AP1_NAME, State.CONNECTED);
+
+        assertThat(mWifiScanWorker.areListsTheSame(Arrays.asList(ap1), Arrays.asList(ap2)))
+                .isFalse();
+    }
+    @Test
+    public void SliceAccessPoint_differentLength_shouldBeDifferent() {
+        final AccessPoint ap1 = createAccessPoint(AP1_NAME, State.CONNECTED);
+        final AccessPoint ap2 = createAccessPoint(AP1_NAME, State.CONNECTED);
+        final List<AccessPoint> list = new ArrayList<>();
+        list.add(ap1);
+        list.add(ap2);
+
+        assertThat(mWifiScanWorker.areListsTheSame(list, Arrays.asList(ap1))).isFalse();
     }
 
     @Implements(SliceBackgroundWorker.class)