Merge "Add summary with accessibility timeout item"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 1b4304b..c5e512e 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -114,11 +114,12 @@
         <uses-library android:name="org.apache.http.legacy" />
         <!-- Settings -->
 
+        <!-- TODO(b/118444000): Remove this. -->
         <activity android:name="SettingsActivity"
-                android:label="@string/settings_label_launcher"
-                android:launchMode="singleTask">
+                  android:label="@string/settings_label_launcher"
+                  android:launchMode="singleTask">
             <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
-                android:value="true" />
+                       android:value="true" />
         </activity>
 
         <activity android:name=".homepage.SettingsHomepageActivity"
@@ -3043,7 +3044,17 @@
         </provider>
 
         <activity
-            android:name=".wifi.dpp.WifiDppConfiguratorActivity"/>
+            android:name=".wifi.dpp.WifiDppConfiguratorActivity">
+            <intent-filter>
+                <action android:name="android.settings.WIFI_DPP_CONFIGURATOR_QR_CODE_SCANNER"/>
+                <action android:name="android.settings.WIFI_DPP_CONFIGURATOR_QR_CODE_GENERATOR"/>
+                <action android:name="android.settings.WIFI_DPP_CONFIGURATOR_CHOOSE_SAVED_WIFI_NETWORK"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".homepage.contextualcards.ContextualCardFeedbackDialog"
+                  android:theme="@android:style/Theme.DeviceDefault.Light.Dialog.Alert" />
         <!-- This is the longest AndroidManifest.xml ever. -->
     </application>
 </manifest>
diff --git a/color-check-baseline.xml b/color-check-baseline.xml
index eb2e730..787c559 100644
--- a/color-check-baseline.xml
+++ b/color-check-baseline.xml
@@ -2,6 +2,18 @@
 <issues format="4">
 
     <issue
+        id="LintError"
+        severity="Error"
+        message="No `.class` files were found in project &quot;.&quot;, so none of the classfile based checks could be run. Does the project need to be built first?"
+        category="Lint"
+        priority="10"
+        summary="Lint Failure"
+        explanation="This issue type represents a problem running lint itself. Examples include failure to find bytecode for source files (which means certain detectors could not be run), parsing errors in lint configuration files, etc.&#xA;These errors are not errors in your own code, but they are shown to make it clear that some checks were not completed.">
+        <location
+            file="."/>
+    </issue>
+
+    <issue
         id="HardCodedColor"
         severity="Error"
         message="Avoid using hardcoded color"
@@ -169,12 +181,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;color name=&quot;material_empty_color_light&quot;>#FFCED7DB&lt;/color>"
-        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        errorLine1="  &lt;color name=&quot;homepage_accessibility_background&quot;>#783BE5&lt;/color>"
+        errorLine2="  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
-            file="res/values/colors.xml"
+            file="res/values-night/colors.xml"
             line="22"
-            column="5"/>
+            column="3"/>
     </issue>
 
     <issue
@@ -189,7 +201,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="24"
+            line="22"
             column="5"/>
     </issue>
 
@@ -201,11 +213,27 @@
         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_support_background&quot;>#3F5FBD&lt;/color>"
+        errorLine2="  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="res/values-night/colors.xml"
+            line="23"
+            column="3"/>
+    </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_background&quot;>#ff9a9a9a&lt;/color>"
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="26"
+            line="24"
             column="5"/>
     </issue>
 
@@ -221,7 +249,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="27"
+            line="25"
             column="5"/>
     </issue>
 
@@ -237,7 +265,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="28"
+            line="26"
             column="5"/>
     </issue>
 
@@ -253,7 +281,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="29"
+            line="27"
             column="5"/>
     </issue>
 
@@ -269,23 +297,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="31"
-            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_regular_color_dark&quot;>#ffbdbdbd&lt;/color>"
-        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="res/values/colors.xml"
-            line="33"
+            line="29"
             column="5"/>
     </issue>
 
@@ -301,7 +313,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="35"
+            line="32"
             column="5"/>
     </issue>
 
@@ -317,7 +329,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="37"
+            line="34"
             column="5"/>
     </issue>
 
@@ -333,7 +345,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="38"
+            line="35"
             column="5"/>
     </issue>
 
@@ -349,7 +361,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="39"
+            line="36"
             column="5"/>
     </issue>
 
@@ -365,7 +377,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="41"
+            line="38"
             column="5"/>
     </issue>
 
@@ -381,7 +393,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="42"
+            line="39"
             column="5"/>
     </issue>
 
@@ -397,7 +409,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="44"
+            line="41"
             column="5"/>
     </issue>
 
@@ -413,7 +425,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="49"
+            line="46"
             column="5"/>
     </issue>
 
@@ -429,7 +441,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="50"
+            line="47"
             column="5"/>
     </issue>
 
@@ -445,7 +457,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="52"
+            line="49"
             column="5"/>
     </issue>
 
@@ -461,23 +473,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="53"
-            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;wifi_divider&quot;>#ffe0e0e0&lt;/color>"
-        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="res/values/colors.xml"
-            line="55"
+            line="50"
             column="5"/>
     </issue>
 
@@ -493,103 +489,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="58"
-            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;voice_interaction_highlight&quot;>#33b5e5&lt;/color>"
-        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="res/values/colors.xml"
-            line="59"
-            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;memory_normal&quot;>#ff009587&lt;/color>"
-        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="res/values/colors.xml"
-            line="61"
-            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;memory_moderate&quot;>#ffF3B300&lt;/color>"
-        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="res/values/colors.xml"
-            line="62"
-            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;memory_low&quot;>#ffff9700&lt;/color>"
-        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="res/values/colors.xml"
-            line="63"
-            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;memory_critical&quot;>#ffff5621&lt;/color>"
-        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="res/values/colors.xml"
-            line="64"
-            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;memory_avg_use&quot;>#ff384248&lt;/color>"
-        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="res/values/colors.xml"
-            line="66"
+            line="54"
             column="5"/>
     </issue>
 
@@ -605,39 +505,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="69"
-            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;importance_icon_tint&quot;>#8a000000&lt;/color>"
-        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="res/values/colors.xml"
-            line="71"
-            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;importance_disabled_tint&quot;>#4d000000&lt;/color>"
-        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="res/values/colors.xml"
-            line="72"
+            line="57"
             column="5"/>
     </issue>
 
@@ -653,7 +521,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="75"
+            line="60"
             column="5"/>
     </issue>
 
@@ -669,7 +537,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="76"
+            line="61"
             column="5"/>
     </issue>
 
@@ -685,7 +553,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="77"
+            line="62"
             column="5"/>
     </issue>
 
@@ -701,7 +569,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="78"
+            line="63"
             column="5"/>
     </issue>
 
@@ -717,7 +585,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="79"
+            line="64"
             column="5"/>
     </issue>
 
@@ -733,7 +601,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="82"
+            line="66"
             column="5"/>
     </issue>
 
@@ -749,7 +617,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="83"
+            line="67"
             column="5"/>
     </issue>
 
@@ -765,7 +633,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="84"
+            line="68"
             column="5"/>
     </issue>
 
@@ -781,7 +649,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="85"
+            line="69"
             column="5"/>
     </issue>
 
@@ -797,7 +665,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="86"
+            line="70"
             column="5"/>
     </issue>
 
@@ -813,7 +681,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="87"
+            line="71"
             column="5"/>
     </issue>
 
@@ -829,7 +697,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="88"
+            line="72"
             column="5"/>
     </issue>
 
@@ -845,7 +713,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="89"
+            line="73"
             column="5"/>
     </issue>
 
@@ -861,7 +729,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="90"
+            line="74"
             column="5"/>
     </issue>
 
@@ -877,7 +745,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="91"
+            line="75"
             column="5"/>
     </issue>
 
@@ -893,7 +761,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="92"
+            line="76"
             column="5"/>
     </issue>
 
@@ -909,7 +777,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="94"
+            line="78"
             column="5"/>
     </issue>
 
@@ -925,7 +793,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="97"
+            line="81"
             column="5"/>
     </issue>
 
@@ -941,7 +809,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="100"
+            line="84"
             column="5"/>
     </issue>
 
@@ -953,43 +821,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;wifi_details_icon_color&quot;>#8A000000&lt;/color>"
-        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        errorLine1="    &lt;color name=&quot;fallback_tintColor&quot;>#89000000&lt;/color>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="103"
-            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;suggestion_condition_background&quot;>#f2f2f2&lt;/color>"
-        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="res/values/colors.xml"
-            line="106"
-            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;condition_card_background&quot;>#f8f8f8&lt;/color>"
-        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="res/values/colors.xml"
-            line="107"
+            line="87"
             column="5"/>
     </issue>
 
@@ -1005,7 +841,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="110"
+            line="90"
             column="5"/>
     </issue>
 
@@ -1021,7 +857,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="111"
+            line="91"
             column="5"/>
     </issue>
 
@@ -1037,7 +873,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="112"
+            line="92"
             column="5"/>
     </issue>
 
@@ -1053,7 +889,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="113"
+            line="93"
             column="5"/>
     </issue>
 
@@ -1069,7 +905,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="114"
+            line="94"
             column="5"/>
     </issue>
 
@@ -1085,7 +921,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="115"
+            line="95"
             column="5"/>
     </issue>
 
@@ -1101,7 +937,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="116"
+            line="96"
             column="5"/>
     </issue>
 
@@ -1117,7 +953,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="117"
+            line="97"
             column="5"/>
     </issue>
 
@@ -1133,7 +969,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="118"
+            line="98"
             column="5"/>
     </issue>
 
@@ -1145,11 +981,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;homepage_accessibility_background&quot;>#783BE5&lt;/color>"
+        errorLine1="    &lt;color name=&quot;homepage_accessibility_background&quot;>#5011C1&lt;/color>"
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="119"
+            line="99"
             column="5"/>
     </issue>
 
@@ -1165,7 +1001,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="120"
+            line="100"
             column="5"/>
     </issue>
 
@@ -1177,11 +1013,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;homepage_support_background&quot;>#3F5FBD&lt;/color>"
+        errorLine1="    &lt;color name=&quot;homepage_support_background&quot;>#26459C&lt;/color>"
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="121"
+            line="101"
             column="5"/>
     </issue>
 
@@ -1197,7 +1033,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="122"
+            line="102"
             column="5"/>
     </issue>
 
@@ -1213,7 +1049,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="123"
+            line="103"
             column="5"/>
     </issue>
 
@@ -1229,7 +1065,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="124"
+            line="104"
             column="5"/>
     </issue>
 
@@ -1245,7 +1081,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="125"
+            line="105"
             column="5"/>
     </issue>
 
@@ -1261,7 +1097,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="126"
+            line="106"
             column="5"/>
     </issue>
 
@@ -1277,7 +1113,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="130"
+            line="110"
             column="5"/>
     </issue>
 
@@ -1293,7 +1129,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="135"
+            line="115"
             column="5"/>
     </issue>
 
@@ -1309,7 +1145,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="136"
+            line="116"
             column="5"/>
     </issue>
 
@@ -1325,7 +1161,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="137"
+            line="117"
             column="5"/>
     </issue>
 
@@ -1341,7 +1177,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="138"
+            line="118"
             column="5"/>
     </issue>
 
@@ -1357,7 +1193,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="139"
+            line="119"
             column="5"/>
     </issue>
 
@@ -1373,7 +1209,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="140"
+            line="120"
             column="5"/>
     </issue>
 
@@ -1389,7 +1225,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="143"
+            line="123"
             column="5"/>
     </issue>
 
@@ -1405,7 +1241,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="144"
+            line="124"
             column="5"/>
     </issue>
 
@@ -1421,7 +1257,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="145"
+            line="125"
             column="5"/>
     </issue>
 
@@ -1437,7 +1273,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="146"
+            line="126"
             column="5"/>
     </issue>
 
@@ -1453,7 +1289,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="147"
+            line="127"
             column="5"/>
     </issue>
 
@@ -1737,12 +1573,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:tint=&quot;@color/wifi_details_icon_color&quot;>"
-        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        errorLine1="                android:color=&quot;@color/homepage_about_background&quot; />"
+        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
-            file="res/drawable/ic_frequency_antenna.xml"
-            line="22"
-            column="9"/>
+            file="res/drawable/ic_homepage_about.xml"
+            line="23"
+            column="17"/>
     </issue>
 
     <issue
@@ -1753,10 +1589,10 @@
         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_accessibility_background&quot; />"
+        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
-            file="res/drawable/ic_homepage_about.xml"
+            file="res/drawable/ic_homepage_accessibility.xml"
             line="23"
             column="17"/>
     </issue>
@@ -1993,6 +1829,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="                android:color=&quot;@color/homepage_support_background&quot; />"
+        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="res/drawable/ic_homepage_support.xml"
+            line="23"
+            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/homepage_system_background&quot; />"
         errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
@@ -2041,22 +1893,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:tint=&quot;@color/wifi_details_icon_color&quot;>"
-        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="res/drawable/ic_security_lock_24dp.xml"
-            line="22"
-            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="    &lt;background android:drawable=&quot;@color/shortcut_background&quot;/>"
         errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
@@ -2605,7 +2441,7 @@
         errorLine2="                                   ~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/strings.xml"
-            line="5806"
+            line="5805"
             column="36"/>
     </issue>
 
@@ -2637,7 +2473,7 @@
         errorLine2="                                           ^">
         <location
             file="res/values/styles.xml"
-            line="419"
+            line="425"
             column="44"/>
     </issue>
 
@@ -2653,7 +2489,7 @@
         errorLine2="                                           ^">
         <location
             file="res/values/styles.xml"
-            line="425"
+            line="431"
             column="44"/>
     </issue>
 
@@ -2669,7 +2505,7 @@
         errorLine2="                                           ^">
         <location
             file="res/values/styles.xml"
-            line="426"
+            line="432"
             column="44"/>
     </issue>
 
@@ -2685,7 +2521,23 @@
         errorLine2="                                 ^">
         <location
             file="res/values/styles.xml"
-            line="461"
+            line="467"
+            column="34"/>
+    </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;item name=&quot;strokeColor&quot;>@color/homepage_card_stroke_color&lt;/item>"
+        errorLine2="                                 ^">
+        <location
+            file="res/values/styles.xml"
+            line="474"
             column="34"/>
     </issue>
 
diff --git a/res/drawable/ic_frequency_antenna.xml b/res/drawable/ic_frequency_antenna.xml
index 581b83e..716a98a 100644
--- a/res/drawable/ic_frequency_antenna.xml
+++ b/res/drawable/ic_frequency_antenna.xml
@@ -19,7 +19,7 @@
         android:viewportHeight="24"
         android:width="24dp"
         android:height="24dp"
-        android:tint="@color/wifi_details_icon_color">
+        android:tint="?android:attr/colorControlNormal">
     <path
         android:pathData="M12,5c-3.9,0-7,3.1-7,7h2c0-2.8,2.2-5,5-5s5,2.2,5,5h2C19,8.1,15.9,5,12,5z M13,14.3c0.9-0.4,1.5-1.3,1.5-2.3
                 c0-1.4-1.1-2.5-2.5-2.5S9.5,10.6,9.5,12c0,1,0.6,1.9,1.5,2.3v3.3L7.6,21L9,22.4l3-3l3,3l1.4-1.4L13,17.6V14.3z M12,1
diff --git a/res/drawable/ic_security_lock_24dp.xml b/res/drawable/ic_security_lock_24dp.xml
index fd49b23..40b5109 100644
--- a/res/drawable/ic_security_lock_24dp.xml
+++ b/res/drawable/ic_security_lock_24dp.xml
@@ -19,7 +19,7 @@
         android:viewportHeight="24"
         android:width="24dp"
         android:height="24dp"
-        android:tint="@color/wifi_details_icon_color">
+        android:tint="?android:attr/colorControlNormal">
     <path
         android:pathData="M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zm-6 9c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zm3.1-9H8.9V6c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39 3.1 3.1v2z"
         android:fillColor="#FFFFFFFF" />
diff --git a/res/drawable/ic_wifi_privacy_24dp.xml b/res/drawable/ic_wifi_privacy_24dp.xml
new file mode 100644
index 0000000..c23fbc1
--- /dev/null
+++ b/res/drawable/ic_wifi_privacy_24dp.xml
@@ -0,0 +1,32 @@
+<?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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:viewportWidth="24"
+        android:viewportHeight="24"
+        android:width="24dp"
+        android:height="24dp"
+        android:tint="?android:attr/colorControlNormal">
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M21.25,16.5v-0.66c0,-1.13 -1.03,-2.09 -2.25,-2.09s-2.25,0.96 -2.25,2.09v0.66H16V22h6v-5.5H21.25zM19.75,16.5h-1.5v-0.66c0,-0.29 0.38,-0.59 0.75,-0.59s0.75,0.3 0.75,0.59V16.5z"/>
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M12,17c-3.79,0 -7.17,-2.13 -8.82,-5.5C4.83,8.13 8.21,6 12,6s7.17,2.13 8.82,5.5H23C21.27,7.11 17,4 12,4S2.73,7.11 1,11.5C2.73,15.89 7,19 12,19c0.68,0 1.35,-0.06 2,-0.17v-2.05C13.35,16.91 12.69,17 12,17z"/>
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M16.43,12.23c0.04,-0.24 0.07,-0.48 0.07,-0.73C16.5,9.02 14.48,7 12,7s-4.5,2.02 -4.5,4.5S9.52,16 12,16c0.77,0 1.48,-0.21 2.12,-0.55C14.41,14.08 15.27,12.93 16.43,12.23zM12,14.2c-1.49,0 -2.7,-1.21 -2.7,-2.7s1.21,-2.7 2.7,-2.7s2.7,1.21 2.7,2.7S13.49,14.2 12,14.2z"/>
+</vector>
diff --git a/res/layout-land/panel_layout.xml b/res/layout-land/panel_layout.xml
new file mode 100644
index 0000000..3975bfe
--- /dev/null
+++ b/res/layout-land/panel_layout.xml
@@ -0,0 +1,42 @@
+<?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:layout_width="match_parent"
+              android:layout_height="match_parent"
+              android:orientation="vertical">
+
+    <TextView
+        android:id="@+id/title"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:gravity="center"
+        android:paddingBottom="24dp"
+        android:paddingTop="18dp"
+        android:textColor="?android:attr/colorPrimary"
+        android:textSize="20sp"/>
+
+    <include layout="@layout/horizontal_divider"/>
+
+    <androidx.recyclerview.widget.RecyclerView
+        android:id="@+id/panel_parent_layout"
+        android:scrollbars="vertical"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1"/>
+
+    <include layout="@layout/panel_buttons"/>
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout-land/wifi_dpp_qrcode_scanner_fragment.xml b/res/layout-land/wifi_dpp_qrcode_scanner_fragment.xml
new file mode 100644
index 0000000..0c938f8
--- /dev/null
+++ b/res/layout-land/wifi_dpp_qrcode_scanner_fragment.xml
@@ -0,0 +1,51 @@
+<?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:id="@+id/root"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+    <include layout="@layout/wifi_dpp_fragment_header"/>
+
+    <FrameLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content">
+        <SurfaceView
+            android:id="@+id/preview_view"
+            android:layout_width="426dp"
+            android:layout_height="320dp"
+            android:layout_gravity="center"/>
+        <com.android.settings.wifi.qrcode.QrDecorateView
+            android:id="@+id/decorate_view"
+            android:layout_width="426dp"
+            android:layout_height="320dp"
+            android:layout_gravity="center"/>
+    </FrameLayout>
+
+    <TextView android:id="@+id/error_message"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"/>
+
+    <include layout="@layout/wifi_dpp_fragment_footer"
+        android:gravity="center|bottom"/>
+
+</LinearLayout>
+
diff --git a/res/layout/panel_buttons.xml b/res/layout/panel_buttons.xml
new file mode 100644
index 0000000..1bb3898
--- /dev/null
+++ b/res/layout/panel_buttons.xml
@@ -0,0 +1,45 @@
+<?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:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:paddingTop="14dp"
+    android:paddingBottom="14dp"
+    android:orientation="horizontal">
+
+    <Button
+        android:id="@+id/see_more"
+        style="@android:style/Widget.DeviceDefault.Button.Borderless.Colored"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="20dp"
+        android:text="@string/see_more"/>
+
+    <Space
+        android:layout_weight="1"
+        android:layout_width="0dp"
+        android:layout_height="match_parent" />
+
+    <Button
+        android:id="@+id/done"
+        style="@android:style/Widget.DeviceDefault.Button.Borderless.Colored"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginEnd="20dp"
+        android:text="@string/done"/>
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/panel_layout.xml b/res/layout/panel_layout.xml
index cbdd53f..a6f62a4 100644
--- a/res/layout/panel_layout.xml
+++ b/res/layout/panel_layout.xml
@@ -14,13 +14,30 @@
     See the License for the specific language governing permissions and
     limitations under the License
   -->
+
+<!-- Note: There is a landscape version of this layout. -->
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:id="@+id/panel_parent_layout"
+              android:layout_width="match_parent"
+              android:layout_height="wrap_content"
+              android:orientation="vertical">
+
+    <TextView
+        android:id="@+id/title"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:paddingLeft="24dp"
-        android:paddingRight="24dp"
-        android:paddingBottom="8dp"
-        android:layout_margin="4dp"
-        android:orientation="vertical">
+        android:gravity="center"
+        android:paddingBottom="24dp"
+        android:paddingTop="18dp"
+        android:textColor="?android:attr/colorPrimary"
+        android:textSize="20sp"/>
+
+    <include layout="@layout/horizontal_divider"/>
+
+    <androidx.recyclerview.widget.RecyclerView
+        android:id="@+id/panel_parent_layout"
+        android:scrollbars="vertical"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"/>
+
+    <include layout="@layout/panel_buttons"/>
 </LinearLayout>
\ No newline at end of file
diff --git a/res/layout/panel_slice_row.xml b/res/layout/panel_slice_row.xml
new file mode 100644
index 0000000..4ce3494
--- /dev/null
+++ b/res/layout/panel_slice_row.xml
@@ -0,0 +1,31 @@
+<?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:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
+
+    <androidx.slice.widget.SliceView
+        android:id="@+id/slice_view"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingStart="20dp"
+        android:paddingEnd="20dp" />
+
+    <include layout="@layout/horizontal_divider"/>
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/search_bar.xml b/res/layout/search_bar.xml
index 9135ebf..be8aa3b 100644
--- a/res/layout/search_bar.xml
+++ b/res/layout/search_bar.xml
@@ -15,42 +15,33 @@
      limitations under the License.
 -->
 
-<FrameLayout
+<com.google.android.material.card.MaterialCardView
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:id="@+id/search_bar_container"
+    android:id="@+id/search_bar"
+    style="@style/SearchBarStyle"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:background="?android:attr/colorBackground"
-    android:theme="@style/ThemeOverlay.Settings.SearchBar"
     app:layout_scrollFlags="scroll|enterAlways">
-    <androidx.cardview.widget.CardView
-        android:id="@+id/search_bar"
+    <Toolbar
+        android:id="@+id/search_action_bar"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_margin="@dimen/search_bar_margin"
-        app:cardCornerRadius="@dimen/search_bar_corner_radius"
-        app:cardElevation="@dimen/search_bar_card_elevation">
-        <Toolbar
-            android:id="@+id/search_action_bar"
-            android:layout_width="match_parent"
-            android:layout_height="@dimen/search_bar_height"
-            android:background="?android:attr/selectableItemBackground"
-            android:contentInsetStartWithNavigation="@dimen/search_bar_content_inset"
-            android:navigationIcon="@drawable/ic_search_24dp">
-            <TextView
-                android:id="@+id/search_action_bar_title"
-                style="@style/TextAppearance.SearchBar"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:text="@string/search_menu"/>
-        </Toolbar>
-        <ImageView
-            android:id="@+id/account_avatar"
-            android:layout_marginStart="@dimen/search_bar_avatar_start_margin"
-            android:layout_marginEnd="@dimen/search_bar_avatar_end_margin"
-            android:layout_width="@dimen/search_bar_avatar_size"
-            android:layout_height="@dimen/search_bar_avatar_size"
-            android:layout_gravity="end|center_vertical"/>
-    </androidx.cardview.widget.CardView>
-</FrameLayout>
\ No newline at end of file
+        android:layout_height="@dimen/search_bar_height"
+        android:background="?android:attr/selectableItemBackground"
+        android:contentInsetStartWithNavigation="@dimen/search_bar_content_inset"
+        android:navigationIcon="@drawable/ic_search_24dp">
+        <TextView
+            android:id="@+id/search_action_bar_title"
+            style="@style/TextAppearance.SearchBar"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/search_menu"/>
+    </Toolbar>
+    <ImageView
+        android:id="@+id/account_avatar"
+        android:layout_marginStart="@dimen/search_bar_avatar_start_margin"
+        android:layout_marginEnd="@dimen/search_bar_avatar_end_margin"
+        android:layout_width="@dimen/search_bar_avatar_size"
+        android:layout_height="@dimen/search_bar_avatar_size"
+        android:layout_gravity="end|center_vertical"/>
+</com.google.android.material.card.MaterialCardView>
diff --git a/res/layout/settings_action_buttons.xml b/res/layout/settings_action_buttons.xml
deleted file mode 100644
index 56e1a36..0000000
--- a/res/layout/settings_action_buttons.xml
+++ /dev/null
@@ -1,52 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright (C) 2017 The Android Open Source Project
-
-  Licensed under the Apache License, Version 2.0 (the "License");
-  you may not use this file except in compliance with the License.
-  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
-  -->
-
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:paddingStart="8dp"
-    android:orientation="horizontal">
-
-    <Button
-        android:id="@+id/button1"
-        style="@style/SettingsActionButton"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_weight="1"/>
-
-    <Button
-        android:id="@+id/button2"
-        style="@style/SettingsActionButton"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_weight="1"/>
-
-    <Button
-        android:id="@+id/button3"
-        style="@style/SettingsActionButton"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_weight="1"/>
-
-    <Button
-        android:id="@+id/button4"
-        style="@style/SettingsActionButton"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_weight="1"/>
-</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/settings_homepage_container.xml b/res/layout/settings_homepage_container.xml
index 0223573..8d81e82 100644
--- a/res/layout/settings_homepage_container.xml
+++ b/res/layout/settings_homepage_container.xml
@@ -23,11 +23,12 @@
 
     <com.google.android.material.appbar.AppBarLayout
         android:layout_width="match_parent"
-        android:layout_height="wrap_content">
+        android:layout_height="wrap_content"
+        android:background="@android:color/transparent"
+        app:elevation="0dp">
         <include layout="@layout/search_bar"/>
     </com.google.android.material.appbar.AppBarLayout>
 
-
     <androidx.core.widget.NestedScrollView
         android:id="@+id/main_content_scrollable_container"
         android:layout_width="match_parent"
diff --git a/res/layout/settings_main_dashboard.xml b/res/layout/settings_main_dashboard.xml
index 3994092..ee84576 100644
--- a/res/layout/settings_main_dashboard.xml
+++ b/res/layout/settings_main_dashboard.xml
@@ -1,25 +1,23 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-/*
-** Copyright 2014, 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.
-*/
+     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.
 -->
 
+<!-- TODO(118444000): Remove this -->
 <LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="vertical">
@@ -30,4 +28,4 @@
         android:id="@+id/main_content"
         android:layout_height="match_parent"
         android:layout_width="match_parent" />
-</LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/wifi_dpp_add_device_fragment.xml b/res/layout/wifi_dpp_add_device_fragment.xml
new file mode 100644
index 0000000..03add62
--- /dev/null
+++ b/res/layout/wifi_dpp_add_device_fragment.xml
@@ -0,0 +1,48 @@
+<?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:id="@+id/root"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+    <include layout="@layout/wifi_dpp_fragment_header"/>
+
+    <ProgressBar
+      android:id="@+id/progress_bar"
+      android:layout_width="match_parent"
+      android:layout_height="wrap_content"
+      android:indeterminate="true"/>
+
+    <ImageView
+        android:id="@+id/wifi_ap_picture_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_gravity="center"/>
+
+    <TextView android:id="@+id/choose_different_network"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"/>
+
+    <include layout="@layout/wifi_dpp_fragment_footer"
+        android:gravity="center|bottom"/>
+
+</LinearLayout>
+
diff --git a/res/layout/wifi_dpp_choose_saved_wifi_network_fragment.xml b/res/layout/wifi_dpp_choose_saved_wifi_network_fragment.xml
new file mode 100644
index 0000000..a65cf3e
--- /dev/null
+++ b/res/layout/wifi_dpp_choose_saved_wifi_network_fragment.xml
@@ -0,0 +1,35 @@
+<?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:id="@+id/root"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+    <include layout="@layout/wifi_dpp_fragment_header"/>
+
+    <ListView android:id="@+id/saved_wifi_network_list"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"/>
+
+    <include layout="@layout/wifi_dpp_fragment_footer"
+        android:gravity="center|bottom"/>
+
+</LinearLayout>
+
diff --git a/res/layout/wifi_dpp_qrcode_generator_fragment.xml b/res/layout/wifi_dpp_qrcode_generator_fragment.xml
new file mode 100644
index 0000000..789b3a3
--- /dev/null
+++ b/res/layout/wifi_dpp_qrcode_generator_fragment.xml
@@ -0,0 +1,34 @@
+<?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:id="@+id/root"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+    <include layout="@layout/wifi_dpp_fragment_header"/>
+
+    <ImageView
+        android:id="@+id/barcode_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_gravity="center"/>
+
+</LinearLayout>
+
diff --git a/res/layout/wifi_dpp_qrcode_scanner_fragment.xml b/res/layout/wifi_dpp_qrcode_scanner_fragment.xml
index 130bb6d..ab38ac1 100644
--- a/res/layout/wifi_dpp_qrcode_scanner_fragment.xml
+++ b/res/layout/wifi_dpp_qrcode_scanner_fragment.xml
@@ -17,7 +17,6 @@
 
 <LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:id="@+id/root"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
@@ -33,7 +32,7 @@
             android:layout_width="320dp"
             android:layout_height="426dp"
             android:layout_gravity="center"/>
-        <ImageView
+        <com.android.settings.wifi.qrcode.QrDecorateView
             android:id="@+id/decorate_view"
             android:layout_width="320dp"
             android:layout_height="426dp"
diff --git a/res/layout/zen_onboarding.xml b/res/layout/zen_onboarding.xml
index 33cdbdd..35b992d 100644
--- a/res/layout/zen_onboarding.xml
+++ b/res/layout/zen_onboarding.xml
@@ -47,7 +47,8 @@
                 android:id="@+id/zen_onboarding_new_setting_button"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:paddingHorizontal="8dp" />
+                android:paddingHorizontal="8dp"
+                android:minHeight="48dp"/>
 
             <LinearLayout
                 android:layout_width="match_parent"
@@ -83,7 +84,8 @@
                 android:id="@+id/zen_onboarding_current_setting_button"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:paddingHorizontal="8dp" />
+                android:paddingHorizontal="8dp"
+                android:minHeight="48dp"/>
 
             <LinearLayout
                 android:layout_width="match_parent"
diff --git a/res/layout/zen_rule_widget.xml b/res/layout/zen_rule_widget.xml
index d502243..c6214e7 100644
--- a/res/layout/zen_rule_widget.xml
+++ b/res/layout/zen_rule_widget.xml
@@ -20,13 +20,13 @@
         android:layout_height="match_parent"
         android:orientation="horizontal">
     <ImageView
-            android:id="@+id/delete_zen_rule"
+            android:id="@+id/zen_automatic_rule_widget"
             android:layout_width="wrap_content"
             android:layout_height="fill_parent"
             android:paddingStart="16dip"
             android:paddingEnd="16dip"
-            android:src="@drawable/ic_delete"
-            android:contentDescription="@string/zen_mode_delete_rule"
+            android:src="@drawable/ic_settings"
+            android:contentDescription="zen_mode_rule_settings"
             android:layout_gravity="center"
             android:background="?android:attr/selectableItemBackground" />
 </LinearLayout>
diff --git a/res/values-night/colors.xml b/res/values-night/colors.xml
index 595f429..bc06f47 100644
--- a/res/values-night/colors.xml
+++ b/res/values-night/colors.xml
@@ -19,5 +19,7 @@
   <color name="switch_bar_background">#dadce0</color>
   <color name="switchbar_switch_track_tint">#82000000</color>
   <color name="switchbar_switch_thumb_tint">@android:color/black</color>
+  <color name="homepage_accessibility_background">#783BE5</color>
+  <color name="homepage_support_background">#3F5FBD</color>
 </resources>
 
diff --git a/res/values/colors.xml b/res/values/colors.xml
index e477277..587184b 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -19,8 +19,6 @@
     <color name="red">#F00</color>
     <color name="blue">#00F</color>
 
-    <color name="material_empty_color_light">#FFCED7DB</color>
-
     <color name="bluetooth_dialog_text_color">#8a000000</color>
 
     <color name="crypt_keeper_clock_background">#ff9a9a9a</color>
@@ -30,7 +28,6 @@
 
     <color name="divider_color">#20ffffff</color>
     <color name="title_color">@android:color/holo_blue_light</color>
-    <color name="setup_lock_pattern_view_regular_color_dark">#ffbdbdbd</color>
     <color name="setup_lock_pattern_view_regular_color_light">@color/lock_pattern_view_regular_color</color>
     <color name="setup_lock_pattern_view_success_color_dark">#ff84ffff</color>
     <color name="setup_lock_pattern_view_success_color_light">@color/suw_color_accent_light</color>
@@ -52,25 +49,13 @@
     <color name="running_processes_system_ram">#ff384248</color>
     <color name="running_processes_free_ram">#ffced7db</color>
 
-    <color name="wifi_divider">#ffe0e0e0</color>
     <color name="sim_noitification">@*android:color/accent_device_default_light</color>
 
     <color name="confirm_device_credential_transparent_black">#60000000</color>
-    <color name="voice_interaction_highlight">#33b5e5</color>
-
-    <color name="memory_normal">#ff009587</color>
-    <color name="memory_moderate">#ffF3B300</color>
-    <color name="memory_low">#ffff9700</color>
-    <color name="memory_critical">#ffff5621</color>
-
-    <color name="memory_avg_use">#ff384248</color>
 
     <!-- Accent color that matches the settings launcher icon -->
     <color name="icon_accent">#ffabffec</color>
 
-    <color name="importance_icon_tint">#8a000000</color>
-    <color name="importance_disabled_tint">#4d000000</color>
-
     <!-- Accessibility SUW colors -->
     <color name="material_blue_500">#4285F4</color>
     <color name="material_blue_700">#3367D6</color>
@@ -78,7 +63,6 @@
     <color name="material_grey_200">#ffffff</color>
     <color name="switch_bar_background">#ff80868B</color>
 
-
     <color name="message_text_incoming">#ffffffff</color>
     <color name="message_text_outgoing">#ff323232</color>
     <color name="timestamp_text_outgoing">#99323232</color>
@@ -99,12 +83,8 @@
     <!-- Color for the background of the shortcut icons.-->
     <color name="shortcut_background">#fff5f5f5</color>
 
-    <!-- Color for preference icons on the Wifi Network Details page -->
-    <color name="wifi_details_icon_color">#8A000000</color>
-
-    <!-- Suggestion/condition colors -->
-    <color name="suggestion_condition_background">#f2f2f2</color>
-    <color name="condition_card_background">#f8f8f8</color>
+    <!-- The fallback color for tinting icons. Only used when colorControlNormal is unavailable -->
+    <color name="fallback_tintColor">#89000000</color>
 
     <!-- Dashboard/homepage icon background colors -->
     <color name="homepage_network_background">#2196F3</color>
@@ -116,9 +96,9 @@
     <color name="homepage_storage_background">#C14CE6</color>
     <color name="homepage_security_background">#0F9D58</color>
     <color name="homepage_accounts_background">#F15B8D</color>
-    <color name="homepage_accessibility_background">#783BE5</color>
+    <color name="homepage_accessibility_background">#5011C1</color>
     <color name="homepage_system_background">#9E9E9E</color>
-    <color name="homepage_support_background">#3F5FBD</color>
+    <color name="homepage_support_background">#26459C</color>
     <color name="homepage_generic_icon_background">#1A73E8</color>
     <color name="homepage_location_background">#2EC7DC</color>
     <color name="homepage_about_background">#9FA8DA</color>
diff --git a/res/values/config.xml b/res/values/config.xml
index 917f14d..edd948f 100755
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -151,6 +151,9 @@
         com.android.settings.intelligence
     </string>
 
+    <!-- Settings intelligence interaction log intent action -->
+    <string name="config_settingsintelligence_log_action" translatable="false"></string>
+
     <!-- Emergency app package name -->
     <string name="config_emergency_package_name" translatable="false">
         com.android.emergency
@@ -160,4 +163,6 @@
         android.settings.EDIT_EMERGENCY_INFO
     </string>
 
+    <!-- Email address for the homepage contextual cards feedback -->
+    <string name="config_contextual_card_feedback_email" translatable="false"></string>
 </resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index f55ef10..83848af 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -95,11 +95,7 @@
     <dimen name="switchbar_subsettings_margin_start">72dp</dimen>
     <dimen name="switchbar_subsettings_margin_end">16dp</dimen>
 
-    <!-- The following two margins need to match, with the caveat that
-         the second should be negative. The second one ensures that the icons and text
-         align despite the additional padding caused by the search bar's card background. -->
     <dimen name="search_bar_margin">16dp</dimen>
-    <dimen name="search_bar_negative_margin">-16dp</dimen>
 
     <dimen name="search_bar_height">48dp</dimen>
     <dimen name="search_bar_corner_radius">2dp</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 876be51..4aa0951 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -3456,9 +3456,9 @@
     <!-- Button title to factory data reset the entire device. The "(factory reset)" part is optional for translation. [CHAR LIMIT=30 BACKUP_MESSAGE_ID=3531267871084279512]-->
     <string name="master_clear_short_title">Erase all data (factory reset)</string>
     <!-- SD card & phone storage settings screen, message on screen after user selects Factory data reset [CHAR LIMIT=NONE] -->
-    <string name="master_clear_desc" product="tablet">"This will erase all data from your tablet\u2019s <b>internal storage</b>, including:\n\n<li>Your Google account</li>\n<li>System and app data and settings</li>\n<li>Downloaded apps</li>"</string>
+    <string name="master_clear_desc" product="tablet">"This will erase all data from your tablet\u2019s <b>internal storage</b>, including:\n\n<li>Your Google Account</li>\n<li>System and app data and settings</li>\n<li>Downloaded apps</li>"</string>
     <!-- SD card & phone storage settings screen, message on screen after user selects Factory data reset [CHAR LIMIT=NONE] -->
-    <string name="master_clear_desc" product="default">"This will erase all data from your phone\u2019s <b>internal storage</b>, including:\n\n<li>Your Google account</li>\n<li>System and app data and settings</li>\n<li>Downloaded apps</li>"</string>
+    <string name="master_clear_desc" product="default">"This will erase all data from your phone\u2019s <b>internal storage</b>, including:\n\n<li>Your Google Account</li>\n<li>System and app data and settings</li>\n<li>Downloaded apps</li>"</string>
     <!-- SD card & phone storage settings screen, instructions and list of current accounts.  The list of accounts follows this text[CHAR LIMIT=NONE] -->
     <string name="master_clear_accounts" product="default">"\n\nYou are currently signed into the following accounts:\n"</string>
     <!-- SD card & phone storage settings screen, notification if other users are present on the device [CHAR LIMIT=NONE] -->
@@ -3488,17 +3488,17 @@
     <!-- 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">Reset tablet</string>
+    <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 -->
-    <string name="master_clear_button_text" product="default">Reset phone</string>
+    <string name="master_clear_button_text" product="default">Erase all data</string>
     <!-- SD card & phone storage settings screen, message on screen after user selects Reset phone button -->
-    <string name="master_clear_final_desc">Erase all your personal information and downloaded apps? You can\u2019t undo this action!</string>
+    <string name="master_clear_final_desc">All of your personal information and downloaded apps will be deleted. You can\u2019t undo this action!</string>
     <!-- SD card & phone storage settings screen, button on screen after user selects Reset phone button -->
     <string name="master_clear_final_button_text">Erase everything</string>
     <!-- Master clear failed message -->
     <string name="master_clear_failed">No reset was performed because the System Clear service isn\u2019t available.</string>
     <!-- Master clear confirmation screen title [CHAR LIMIT=30] -->
-    <string name="master_clear_confirm_title">Reset?</string>
+    <string name="master_clear_confirm_title">Erase all data?</string>
     <!-- Error message for users that aren't allowed to factory reset [CHAR LIMIT=none] -->
     <string name="master_clear_not_available">Factory reset is not available for this user</string>
     <!-- Master clear progress screen title [CHAR LIMIT=30] -->
@@ -7117,6 +7117,12 @@
     <!--  Do not disturb: Title for the zen mode automation option in Settings. [CHAR LIMIT=40] -->
     <string name="zen_mode_automation_settings_title">Schedules</string>
 
+    <!--  Do not disturb: Title for dialog that allows users to delete DND rules/schedules[CHAR LIMIT=40] -->
+    <string name="zen_mode_delete_automatic_rules">Delete schedules</string>
+
+    <!--  Do not disturb: Delete text button presented in a dialog to confirm the user would like to delete the selected DND rules. [CHAR LIMIT=30] -->
+    <string name="zen_mode_schedule_delete">Delete</string>
+
     <!--  Do not disturb: Title for the zen mode automatic rules page in settings. [CHAR LIMIT=30] -->
     <string name="zen_mode_automation_settings_page_title">Do Not Disturb</string>
 
@@ -7253,6 +7259,9 @@
     <!-- [CHAR LIMIT=110] Zen mode settings footer: Footer how DND was triggered by an app -->
     <string name="zen_mode_settings_dnd_automatic_rule_app">Do Not Disturb was automatically turned on by an app (<xliff:g id="app_name" example="Android Services">%s</xliff:g>)</string>
 
+    <!-- [CHAR LIMIT=120] Zen mode settings footer: Footer informing user DND has custom settings. -->
+    <string name="zen_mode_settings_dnd_custom_settings_footer">Do Not Disturb is on for <xliff:g id="rule_names" example="Sleeping and Work">%s</xliff:g> with custom settings.</string>
+
     <!--[CHAR LIMIT=40] Zen Interruption level: Priority.  -->
     <string name="zen_interruption_level_priority">Priority only</string>
 
@@ -7848,6 +7857,15 @@
     <!-- [CHAR LIMIT=NONE] Zen mode settings: Downtime rule setting -->
     <string name="zen_mode_schedule_alarm_summary">Stop at the end time or next alarm, whichever comes first</string>
 
+    <!-- [CHAR LIMIT=80] Zen mode settings: Title for preference to allow custom behavior for the dnd schedule -->
+    <string name="zen_mode_custom_behavior_title">Do Not Disturb behavior</string>
+
+    <!-- [CHAR LIMIT=120] Zen mode settings: Summay text indicating the currenty dnd schedule is using the default dnd settings -->
+    <string name="zen_mode_custom_behavior_summary_default">Use default settings</string>
+
+    <!-- [CHAR LIMIT=120] Zen mode settings: Summay text indicating the currenty dnd schedule is using custom behavior -->
+    <string name="zen_mode_custom_behavior_summary">Create custom settings for this schedule</string>
+
     <!-- [CHAR LIMIT=40] General divider text when concatenating multiple items in a text summary -->
     <string name="summary_divider_text">,\u0020</string>
 
@@ -8931,25 +8949,28 @@
     <string name="condition_expand_hide">Hide</string>
 
     <!-- Title of condition that hotspot is on [CHAR LIMIT=30] -->
-    <string name="condition_hotspot_title">Hotspot is on</string>
+    <string name="condition_hotspot_title">Hotspot</string>
 
     <!-- Summary of condition that hotspot is on [CHAR LIMIT=NONE] -->
-    <string name="condition_hotspot_summary">Portable Wi-Fi hotspot <xliff:g name="ap_name" example="AndroidAP">%1$s</xliff:g> is active, Wi-Fi for this device is turned off.</string>
+    <string name="condition_hotspot_summary"><xliff:g name="ap_name" example="AndroidAP">%1$s</xliff:g> on</string>
 
     <!-- Title of condition that airplane mode is on [CHAR LIMIT=30] -->
     <string name="condition_airplane_title">Airplane mode is on</string>
 
     <!-- Summary of condition that airplane mode is on [CHAR LIMIT=NONE] -->
-    <string name="condition_airplane_summary">When airplane mode is turned on, Wi\u2011Fi, Bluetooth, and mobile network are turned off. Wi\u2011Fi and Bluetooth can be turned back on.</string>
+    <string name="condition_airplane_summary">Networks unavailable</string>
 
     <!-- Title of condition that do not disturb is on [CHAR LIMIT=36] -->
     <string name="condition_zen_title">Do Not Disturb is on</string>
 
+    <!-- Summary of condition that do not disturb is on [CHAR LIMIT=36] -->
+    <string name="condition_zen_summary">Impacts what you hear and see</string>
+
     <!-- Title of condition that battery saver is on [CHAR LIMIT=30] -->
     <string name="condition_battery_title">Battery Saver is on</string>
 
     <!-- Summary of condition that battery saver is on [CHAR LIMIT=NONE] -->
-    <string name="condition_battery_summary">Battery Saver turns off some device features and restricts apps</string>
+    <string name="condition_battery_summary">Features restricted</string>
 
     <!-- Title of condition that cellular data is off [CHAR LIMIT=50] -->
     <string name="condition_cellular_title">Mobile data is off</string>
@@ -8958,10 +8979,10 @@
     <string name="condition_cellular_summary">Internet is available only via Wi-Fi</string>
 
     <!-- Title of condition that background data is off [CHAR LIMIT=30] -->
-    <string name="condition_bg_data_title">Data Saver is on</string>
+    <string name="condition_bg_data_title">Data Saver</string>
 
     <!-- Summary of condition that background data is off [CHAR LIMIT=NONE] -->
-    <string name="condition_bg_data_summary">Background data is only available via Wi-Fi. This may affect some apps or services when Wi-Fi is not available.</string>
+    <string name="condition_bg_data_summary">Features restricted</string>
 
     <!-- Title of condition that work mode is off [CHAR LIMIT=30] -->
     <string name="condition_work_title">Work profile is off</string>
@@ -8976,22 +8997,22 @@
     <string name="condition_device_muted_title" product="tablet">Device is muted</string>
 
     <!-- Title of condition that indicates device is muted [CHAR LIMIT=50] -->
-    <string name="condition_device_muted_title" product="default">Phone is muted</string>
+    <string name="condition_device_muted_title" product="default">Phone muted</string>
 
     <!-- Summary of condition that indicates device is muted -->
-    <string name="condition_device_muted_summary">Calls and notifications will be muted</string>
+    <string name="condition_device_muted_summary">For calls &amp; notifications</string>
 
     <!-- Title of condition that indicates device is set to vibrate [CHAR LIMIT=50] -->
     <string name="condition_device_vibrate_title" product="tablet">Device is set to vibrate</string>
 
     <!-- Title of condition that indicates device is muted [CHAR LIMIT=50] -->
-    <string name="condition_device_vibrate_title" product="default">Phone is set to vibrate</string>
+    <string name="condition_device_vibrate_title" product="default">Vibration only</string>
 
     <!-- Summary of condition that indicates device is set to vibrate -->
     <string name="condition_device_vibrate_summary" product="tablet">Calls and notifications will vibrate device</string>
 
     <!-- Summary of condition that indicates device is set to vibrate -->
-    <string name="condition_device_vibrate_summary" product="default">Calls and notifications will vibrate phone</string>
+    <string name="condition_device_vibrate_summary" product="default">For calls &amp; notifications</string>
 
     <!--  Night display: Title for the night display option Suggestion (renamed "Night Light" with title caps). [CHAR LIMIT=46] -->
     <string name="night_display_suggestion_title">Set Night Light schedule</string>
@@ -9003,7 +9024,7 @@
     <string name="condition_night_display_title">Night Light is on</string>
 
     <!-- Summary of condition that night display is on (renamed "Night Light" with title caps). [CHAR LIMIT=NONE] -->
-    <string name="condition_night_display_summary">Screen is tinted amber. This may help you fall asleep.</string>
+    <string name="condition_night_display_summary">Screen tinted amber</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>
@@ -9889,6 +9910,11 @@
     <!-- UI debug setting: preference summary - describes the behavior of forcing full raw GNSS satellite measurements [CHAR LIMIT=NONE] -->
     <string name="enable_gnss_raw_meas_full_tracking_summary">Track all GNSS constellations and frequencies with no duty cycling</string>
 
+    <!-- UI debug setting: preference title - allow background activity starts [CHAR LIMIT=60] -->
+    <string name="allow_background_activity_starts">Allow background activity starts</string>
+    <!-- UI debug setting: preference summary - describes the behavior of allowing background activity starts [CHAR LIMIT=NONE] -->
+    <string name="allow_background_activity_starts_summary">Allows all background activity starts</string>
+
     <!-- UI debug setting: preference title - show all crash dialogs [CHAR LIMIT=60] -->
     <string name="show_first_crash_dialog">Always show crash dialog</string>
     <!-- UI debug setting: preference summary - describes the behavior of showing a dialog every time an app crashes [CHAR LIMIT=NONE] -->
@@ -10216,6 +10242,8 @@
         <item quantity="one"><xliff:g id="number_device_count">%1$d</xliff:g> device connected</item>
         <item quantity="other"><xliff:g id="number_device_count">%1$d</xliff:g> devices connected</item>
     </plurals>
+    <!-- Title for bluetooth connected devices in connected device slice. [CHAR LIMIT=NONE] -->
+    <string name="bluetooth_connected_devices">Bluetooth Devices</string>
     <!-- Title for no connected devices in connected device slice. [CHAR LIMIT=NONE] -->
     <string name="no_connected_devices">No connected devices</string>
 
@@ -10225,14 +10253,17 @@
     <!-- Title for the Internet Connectivity dialog (settings panel) with Internet related settings [CHAR LIMIT=50] -->
     <string name="internet_connectivity_panel_title">Internet Connectivity</string>
 
+    <!-- Title for the Volume dialog (settings panel) with all volume streams[CHAR LIMIT=50] -->
+    <string name="volume_connectivity_panel_title">Volume</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] -->
     <string name="force_desktop_mode_summary">Force experimental desktop mode on secondary displays</string>
 
-    <!-- UI debug setting: Force enable "smart dark" UI rendering feature [CHAR LIMIT=40] -->
+    <!-- UI debug setting: Force enable "smart dark" UI rendering feature [CHAR LIMIT=60] -->
     <string name="hwui_force_dark_title">Override force-dark</string>
-    <!-- UI debug setting: Force enable "smart dark" UI rendering feature summary [CHAR LIMIT=100] -->
+    <!-- UI debug setting: Force enable "smart dark" UI rendering feature summary [CHAR LIMIT=NONE] -->
     <string name="hwui_force_dark_summary">Overrides the force-dark feature to be always-on</string>
 
     <!-- Title for the top level Privacy Settings [CHAR LIMIT=30]-->
@@ -10249,4 +10280,9 @@
 
     <!-- Summary for low storage slice. [CHAR LIMIT=NONE] -->
     <string name="low_storage_summary">Storage is low. <xliff:g id="percentage" example="54%">%1$s</xliff:g> used - <xliff:g id="free_space" example="32GB">%2$s</xliff:g> free</string>
-</resources>
\ No newline at end of file
+
+    <!-- Label for button in contextual card feedback dialog for users to send feedback [CHAR LIMIT=30] -->
+    <string name="contextual_card_feedback_send">Send feedback</string>
+    <!-- String for contextual card feedback dialog [CHAR LIMIT=NONE] -->
+    <string name="contextual_card_feedback_confirm_message">Would you like to give us feedback on this suggestion?</string>
+</resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 1b311aa..141426e 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -17,7 +17,7 @@
 <resources>
 
     <style name="Widget.ActionBar.Base"
-            parent="@android:style/Widget.DeviceDefault.Light.ActionBar.Solid"/>
+           parent="@android:style/Widget.DeviceDefault.Light.ActionBar.Solid"/>
 
     <style name="Widget.ActionBar"
            parent="Widget.ActionBar.Base">
@@ -259,7 +259,8 @@
 
     <style name="TextAppearance.Medium" parent="@android:style/TextAppearance.Material.Medium"/>
     <style name="TextAppearance.Small" parent="@android:style/TextAppearance.Material.Small"/>
-    <style name="TextAppearance.Switch" parent="@android:style/TextAppearance.DeviceDefault.Widget.ActionBar.Title">
+    <style name="TextAppearance.Switch"
+           parent="@android:style/TextAppearance.DeviceDefault.Widget.ActionBar.Title">
         <item name="android:textSize">16sp</item>
     </style>
 
@@ -400,14 +401,6 @@
 
     <style name="ActionSecondaryButton" parent="android:Widget.DeviceDefault.Button"/>
 
-    <style name="SettingsActionButton" parent="android:Widget.DeviceDefault.Button.Borderless.Colored">
-        <item name="android:drawablePadding">4dp</item>
-        <item name="android:drawableTint">@*android:color/btn_colored_borderless_text_material</item>
-        <item name="android:layout_marginEnd">8dp</item>
-        <item name="android:paddingTop">20dp</item>
-        <item name="android:paddingBottom">20dp</item>
-    </style>
-
     <style name="LockPatternContainerStyle">
         <item name="android:maxHeight">400dp</item>
         <item name="android:maxWidth">420dp</item>
@@ -465,6 +458,13 @@
         <item name="strokeWidth">1dp</item>
     </style>
 
+    <style name="SearchBarStyle">
+        <item name="android:layout_margin">@dimen/search_bar_margin</item>
+        <item name="cardCornerRadius">8dp</item>
+        <item name="strokeColor">@color/homepage_card_stroke_color</item>
+        <item name="strokeWidth">1dp</item>
+    </style>
+
     <style name="ConditionCardBorderlessButton"
            parent="android:Widget.DeviceDefault.Button.Borderless">
         <item name="android:textColor">?android:attr/colorAccent</item>
diff --git a/res/values/themes.xml b/res/values/themes.xml
index 873216d..1e24770 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -54,6 +54,10 @@
         <item name="batteryGoodColor">@color/battery_good_color_light</item>
         <item name="batteryMaybeColor">@color/battery_maybe_color_light</item>
         <item name="batteryBadColor">@color/battery_bad_color_light</item>
+
+        <!-- TODO(118444000): Remove colorPrimary and colorPrimaryVariant -->
+        <item name="colorPrimary">@*android:color/primary_device_default_settings_light</item>
+        <item name="colorPrimaryVariant">@android:color/white</item>
     </style>
 
     <!-- Variant of the settings theme with no action bar. -->
@@ -185,6 +189,8 @@
         <item name="batteryGoodColor">@color/battery_good_color_light</item>
         <item name="batteryMaybeColor">@color/battery_maybe_color_light</item>
         <item name="batteryBadColor">@color/battery_bad_color_light</item>
+        <!-- Define this color for material design -->
+        <item name="colorPrimaryVariant">@android:color/white</item>
     </style>
 
     <style name="Theme.Settings.Home" parent="Theme.Settings.HomeBase">
@@ -195,13 +201,11 @@
         <item name="android:windowLightNavigationBar">true</item>
     </style>
 
-    <style name="ThemeOverlay.Settings.SearchBar" parent="Theme.Settings">
-        <item name="android:colorBackground">?android:attr/colorPrimary</item>
-        <item name="cardBackgroundColor">?android:attr/colorBackground</item>
-    </style>
-
     <style name="Theme.BottomDialog" parent="@*android:style/Theme.DeviceDefault.Settings.Dialog">
         <item name="android:windowBackground">@drawable/settings_panel_background</item>
+        <item name="android:dividerHorizontal">@*android:drawable/list_divider_material</item>
+        <item name="android:windowNoTitle">true</item>
+        <item name="android:fontFamily">@*android:string/config_headlineFontFamilyMedium</item>
     </style>
 
 </resources>
diff --git a/res/xml/app_info_settings.xml b/res/xml/app_info_settings.xml
index 8f99ce1..506686a 100644
--- a/res/xml/app_info_settings.xml
+++ b/res/xml/app_info_settings.xml
@@ -36,7 +36,7 @@
         settings:allowDividerAbove="true"
         settings:allowDividerBelow="true"/>
 
-    <com.android.settings.widget.ActionButtonPreference
+    <com.android.settingslib.widget.ActionButtonsPreference
         android:key="action_buttons"
         android:order="-9998" />
 
@@ -72,12 +72,6 @@
         settings:controller="com.android.settings.applications.appinfo.AppDataUsagePreferenceController" />
 
     <Preference
-        android:key="data_settings_v2"
-        android:title="@string/data_usage_app_summary_title"
-        android:summary="@string/summary_placeholder"
-        settings:controller="com.android.settings.applications.appinfo.AppDataUsagePreferenceControllerV2" />
-
-    <Preference
         android:key="time_spent_in_app"
         android:title="@string/time_spent_in_app_pref_title"
         settings:controller="com.android.settings.applications.appinfo.TimeSpentInAppPreferenceController" />
@@ -185,4 +179,4 @@
         settings:allowDividerAbove="true"
         settings:enableCopying="true"/>
 
-</PreferenceScreen>
\ No newline at end of file
+</PreferenceScreen>
diff --git a/res/xml/app_storage_settings.xml b/res/xml/app_storage_settings.xml
index 7036d27..376f09e 100644
--- a/res/xml/app_storage_settings.xml
+++ b/res/xml/app_storage_settings.xml
@@ -19,7 +19,7 @@
     xmlns:settings="http://schemas.android.com/apk/res-auto"
     android:title="@string/storage_label">
 
-    <com.android.settings.widget.ActionButtonPreference
+    <com.android.settingslib.widget.ActionButtonsPreference
         android:key="header_view" />
 
     <com.android.settings.applications.SpacePreference
diff --git a/res/xml/bluetooth_device_details_fragment.xml b/res/xml/bluetooth_device_details_fragment.xml
index 6449e4b..40ce93d 100644
--- a/res/xml/bluetooth_device_details_fragment.xml
+++ b/res/xml/bluetooth_device_details_fragment.xml
@@ -25,7 +25,7 @@
         android:selectable="false"
         settings:allowDividerBelow="true"/>
 
-    <com.android.settings.widget.ActionButtonPreference
+    <com.android.settingslib.widget.ActionButtonsPreference
         android:key="action_buttons" />
 
     <PreferenceCategory
diff --git a/res/xml/development_settings.xml b/res/xml/development_settings.xml
index cc724b8..a0f019d 100644
--- a/res/xml/development_settings.xml
+++ b/res/xml/development_settings.xml
@@ -485,6 +485,11 @@
             android:title="@string/background_check_pref" />
 
         <SwitchPreference
+            android:key="allow_background_activity_starts"
+            android:title="@string/allow_background_activity_starts"
+            android:summary="@string/allow_background_activity_starts_summary" />
+
+        <SwitchPreference
             android:key="show_first_crash_dialog"
             android:title="@string/show_first_crash_dialog"
             android:summary="@string/show_first_crash_dialog_summary" />
diff --git a/res/xml/display_settings.xml b/res/xml/display_settings.xml
index b0e362c..50a5649 100644
--- a/res/xml/display_settings.xml
+++ b/res/xml/display_settings.xml
@@ -44,7 +44,6 @@
         android:title="@string/auto_brightness_title"
         android:summary="@string/summary_placeholder"
         android:fragment="com.android.settings.display.AutoBrightnessSettings"
-        settings:searchable="false"
         settings:controller="com.android.settings.display.AutoBrightnessPreferenceController" />
 
     <com.android.settingslib.RestrictedPreference
diff --git a/res/xml/enterprise_privacy_settings.xml b/res/xml/enterprise_privacy_settings.xml
index 4fa50e7..e8b26b0 100644
--- a/res/xml/enterprise_privacy_settings.xml
+++ b/res/xml/enterprise_privacy_settings.xml
@@ -21,82 +21,107 @@
 
     <!-- Header -->
     <Preference android:key="enterprise_privacy_header"
+                android:order="100"
                 android:icon="@drawable/ic_info_outline_24dp"
                 android:summary="@string/enterprise_privacy_header"
                 android:selectable="false"/>
 
     <PreferenceCategory android:key="exposure_category"
+                        android:order="200"
                         android:title="@string/enterprise_privacy_exposure_category"
                         android:contentDescription="@string/enterprise_privacy_exposure_category">
         <Preference android:key="enterprise_privacy_enterprise_data"
+                    android:order="210"
                     android:layout_height="wrap_content"
                     android:title="@string/enterprise_privacy_enterprise_data"
                     android:selectable="false"/>
         <Preference android:key="enterprise_privacy_installed_packages"
+                    android:order="220"
                     android:title="@string/enterprise_privacy_installed_packages"
                     android:selectable="false"/>
         <Preference android:key="enterprise_privacy_usage_stats"
+                    android:order="230"
                     android:title="@string/enterprise_privacy_usage_stats"
                     android:selectable="false"/>
         <Preference android:key="network_logs"
+                    android:order="240"
                     android:title="@string/enterprise_privacy_network_logs"
                     android:selectable="false"/>
         <Preference android:key="bug_reports"
+                    android:order="250"
                     android:title="@string/enterprise_privacy_bug_reports"
                     android:selectable="false"/>
         <Preference android:key="security_logs"
+                    android:order="260"
                     android:title="@string/enterprise_privacy_security_logs"
                     android:selectable="false"/>
     </PreferenceCategory>
 
     <PreferenceCategory android:title="@string/enterprise_privacy_exposure_changes_category"
+                        android:order="300"
                         android:key="exposure_changes_category">
         <Preference android:fragment="com.android.settings.enterprise.ApplicationListFragment$EnterpriseInstalledPackages"
+                    android:order="310"
                     android:key="number_enterprise_installed_packages"
                     android:title="@string/enterprise_privacy_enterprise_installed_packages"/>
         <Preference android:fragment="com.android.settings.enterprise.ApplicationListFragment$AdminGrantedPermissionLocation"
+                    android:order="320"
                     android:key="enterprise_privacy_number_location_access_packages"
                     android:title="@string/enterprise_privacy_location_access"/>
         <Preference android:fragment="com.android.settings.enterprise.ApplicationListFragment$AdminGrantedPermissionMicrophone"
+                    android:order="330"
                     android:key="enterprise_privacy_number_microphone_access_packages"
                     android:title="@string/enterprise_privacy_microphone_access"/>
         <Preference android:fragment="com.android.settings.enterprise.ApplicationListFragment$AdminGrantedPermissionCamera"
+                    android:order="340"
                     android:key="enterprise_privacy_number_camera_access_packages"
                     android:title="@string/enterprise_privacy_camera_access"/>
         <Preference android:fragment="com.android.settings.enterprise.EnterpriseSetDefaultAppsListFragment"
+                    android:order="350"
                     android:key="number_enterprise_set_default_apps"
                     android:title="@string/enterprise_privacy_enterprise_set_default_apps"/>
         <Preference android:key="always_on_vpn_primary_user"
+                    android:order="360"
                     android:selectable="false"/>
         <Preference android:key="always_on_vpn_managed_profile"
+                    android:order="370"
                     android:title="@string/enterprise_privacy_always_on_vpn_work"
                     android:selectable="false"/>
         <Preference android:key="input_method"
+                    android:order="380"
                     android:title="@string/enterprise_privacy_input_method"
                     android:selectable="false"/>
         <Preference android:key="global_http_proxy"
+                    android:order="390"
                     android:title="@string/enterprise_privacy_global_http_proxy"
                     android:selectable="false"/>
         <Preference android:key="ca_certs_current_user"
+                    android:order="400"
                     android:title="@string/enterprise_privacy_ca_certs_personal"
                     android:selectable="false"/>
         <Preference android:key="ca_certs_managed_profile"
+                    android:order="410"
                     android:title="@string/enterprise_privacy_ca_certs_work"
                     android:selectable="false"/>
     </PreferenceCategory>
 
     <PreferenceCategory android:key="device_access_category"
+                        android:order="500"
                         android:title="@string/enterprise_privacy_device_access_category">
         <Preference android:key="enterprise_privacy_lock_device"
+                    android:order="510"
                     android:title="@string/enterprise_privacy_lock_device"
                     android:selectable="false"/>
         <Preference android:key="enterprise_privacy_wipe_device"
+                    android:order="520"
                     android:title="@string/enterprise_privacy_wipe_device"
                     android:selectable="false"/>
         <Preference android:key="failed_password_wipe_current_user"
+                    android:order="530"
                     android:title="@string/enterprise_privacy_failed_password_wipe_device"
                     android:selectable="false"/>
         <Preference android:key="failed_password_wipe_managed_profile"
+                    android:order="540"
                     android:title="@string/enterprise_privacy_failed_password_wipe_work"
                     android:selectable="false"/>
     </PreferenceCategory>
diff --git a/res/xml/power_usage_detail.xml b/res/xml/power_usage_detail.xml
index 12c7e21..945ceed 100644
--- a/res/xml/power_usage_detail.xml
+++ b/res/xml/power_usage_detail.xml
@@ -26,7 +26,7 @@
         android:order="-10000"
         settings:allowDividerBelow="true"/>
 
-    <com.android.settings.widget.ActionButtonPreference
+    <com.android.settingslib.widget.ActionButtonsPreference
         android:key="action_buttons"
         android:order="-9999"/>
 
diff --git a/res/xml/sound_settings.xml b/res/xml/sound_settings.xml
index d38a8e4..ee8613d 100644
--- a/res/xml/sound_settings.xml
+++ b/res/xml/sound_settings.xml
@@ -28,6 +28,7 @@
         android:icon="@drawable/ic_media_stream"
         android:title="@string/media_volume_option_title"
         android:order="-180"
+        settings:allowDynamicSummaryInSlice="true"
         settings:controller="com.android.settings.notification.MediaVolumePreferenceController"/>
 
     <!-- Media output switcher -->
@@ -44,6 +45,7 @@
         android:icon="@drawable/ic_local_phone_24_lib"
         android:title="@string/call_volume_option_title"
         android:order="-170"
+        settings:allowDynamicSummaryInSlice="true"
         settings:controller="com.android.settings.notification.CallVolumePreferenceController"/>
 
     <!-- Hands free profile output switcher -->
@@ -60,6 +62,7 @@
         android:icon="@drawable/ic_notifications"
         android:title="@string/ring_volume_option_title"
         android:order="-160"
+        settings:allowDynamicSummaryInSlice="true"
         settings:controller="com.android.settings.notification.RingVolumePreferenceController"/>
 
 
@@ -69,6 +72,7 @@
         android:icon="@*android:drawable/ic_audio_alarm"
         android:title="@string/alarm_volume_option_title"
         android:order="-150"
+        settings:allowDynamicSummaryInSlice="true"
         settings:controller="com.android.settings.notification.AlarmVolumePreferenceController"/>
 
     <!-- Notification volume -->
diff --git a/res/xml/tts_settings.xml b/res/xml/tts_settings.xml
index e76cdb7..92bf5d7 100644
--- a/res/xml/tts_settings.xml
+++ b/res/xml/tts_settings.xml
@@ -50,7 +50,7 @@
             android:defaultValue="100"
             android:max="400"/>
 
-        <com.android.settings.widget.ActionButtonPreference
+        <com.android.settingslib.widget.ActionButtonsPreference
             android:key="action_buttons" />
 
     </PreferenceCategory>
diff --git a/res/xml/wifi_network_details_fragment.xml b/res/xml/wifi_network_details_fragment.xml
index b33cb75..70bd194 100644
--- a/res/xml/wifi_network_details_fragment.xml
+++ b/res/xml/wifi_network_details_fragment.xml
@@ -27,25 +27,25 @@
         settings:allowDividerBelow="true"/>
 
     <!-- Buttons -->
-    <com.android.settings.widget.ActionButtonPreference
+    <com.android.settingslib.widget.ActionButtonsPreference
         android:key="buttons"
         android:selectable="false" />
 
     <!-- General Details Category -->
     <PreferenceCategory
             android:key="general_details_category" >
-        <com.android.settings.wifi.WifiDetailPreference
+        <Preference
                 android:key="signal_strength"
                 android:title="@string/wifi_signal"
                 android:selectable="false"/>
 
-        <com.android.settings.wifi.WifiDetailPreference
+        <Preference
                 android:key="frequency"
                 android:icon="@drawable/ic_frequency_antenna"
                 android:title="@string/wifi_frequency"
                 android:selectable="false"/>
 
-        <com.android.settings.wifi.WifiDetailPreference
+        <Preference
                 android:key="security"
                 android:icon="@drawable/ic_security_lock_24dp"
                 android:title="@string/wifi_security"
@@ -60,6 +60,7 @@
 
         <DropDownPreference
             android:key="privacy"
+            android:icon="@drawable/ic_wifi_privacy_24dp"
             android:title="@string/wifi_privacy_settings"
             android:entries="@array/wifi_privacy_entries"
             android:entryValues="@array/wifi_privacy_values"/>
@@ -69,30 +70,36 @@
     <PreferenceCategory
             android:key="ip_details_category"
             android:title="@string/wifi_setup_detail">
-        <com.android.settings.wifi.WifiDetailPreference
-            android:key="mac_address"
-            android:title="@string/wifi_advanced_mac_address_title"
-            android:selectable="false"/>
-        <com.android.settings.wifi.WifiDetailPreference
+        <Preference
+                android:key="mac_address"
+                android:title="@string/wifi_advanced_mac_address_title"
+                android:selectable="false"
+                settings:enableCopying="true"/>
+        <Preference
                 android:key="ip_address"
                 android:title="@string/wifi_ip_address"
-                android:selectable="false"/>
-        <com.android.settings.wifi.WifiDetailPreference
+                android:selectable="false"
+                settings:enableCopying="true"/>
+        <Preference
                 android:key="gateway"
                 android:title="@string/wifi_gateway"
-                android:selectable="false"/>
-        <com.android.settings.wifi.WifiDetailPreference
+                android:selectable="false"
+                settings:enableCopying="true"/>
+        <Preference
                 android:key="subnet_mask"
                 android:title="@string/wifi_details_subnet_mask"
-                android:selectable="false"/>
-        <com.android.settings.wifi.WifiDetailPreference
+                android:selectable="false"
+                settings:enableCopying="true"/>
+        <Preference
                 android:key="dns"
                 android:title="@string/wifi_details_dns"
-                android:selectable="false"/>
-        <com.android.settings.wifi.WifiDetailPreference
+                android:selectable="false"
+                settings:enableCopying="true"/>
+        <Preference
                 android:key="link_speed"
                 android:title="@string/wifi_speed"
-                android:selectable="false"/>
+                android:selectable="false"
+                settings:enableCopying="true"/>
     </PreferenceCategory>
 
     <!-- IPv6 Details -->
diff --git a/res/xml/zen_mode_schedule_rule_settings.xml b/res/xml/zen_mode_schedule_rule_settings.xml
index d05bbd2..c257d87 100644
--- a/res/xml/zen_mode_schedule_rule_settings.xml
+++ b/res/xml/zen_mode_schedule_rule_settings.xml
@@ -43,4 +43,10 @@
         android:summary="@string/zen_mode_schedule_alarm_summary"
         android:order="99" />
 
+    <!-- Custom Do Not Disturb Setting-->
+    <Preference
+        android:key="zen_schedule_custom_setting"
+        android:title="@string/zen_mode_custom_behavior_title"
+        android:order="100" />
+
 </PreferenceScreen>
diff --git a/src/com/android/settings/CryptKeeper.java b/src/com/android/settings/CryptKeeper.java
index 1f331d7..ca54b07 100644
--- a/src/com/android/settings/CryptKeeper.java
+++ b/src/com/android/settings/CryptKeeper.java
@@ -33,11 +33,11 @@
 import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.storage.IStorageManager;
 import android.os.storage.StorageManager;
 import android.provider.Settings;
+import android.sysprop.VoldProperties;
 import android.telecom.TelecomManager;
 import android.telephony.TelephonyManager;
 import android.text.Editable;
@@ -400,7 +400,7 @@
         super.onCreate(savedInstanceState);
 
         // If we are not encrypted or encrypting, get out quickly.
-        final String state = SystemProperties.get("vold.decrypt");
+        final String state = VoldProperties.decrypt().orElse("");
         if (!isDebugView() && ("".equals(state) || DECRYPT_STATE.equals(state))) {
             disableCryptKeeperComponent(this);
             // Typically CryptKeeper is launched as the home app.  We didn't
@@ -468,7 +468,7 @@
             return;
         }
 
-        final String progress = SystemProperties.get("vold.encrypt_progress");
+        final String progress = VoldProperties.encrypt_progress().orElse("");
         if (!"".equals(progress) || isDebugView(FORCE_VIEW_PROGRESS)) {
             setContentView(R.layout.crypt_keeper_progress);
             encryptionProgressInit();
@@ -636,7 +636,7 @@
     }
 
     private void updateProgress() {
-        final String state = SystemProperties.get("vold.encrypt_progress");
+        final String state = VoldProperties.encrypt_progress().orElse("");
 
         if ("error_partially_encrypted".equals(state)) {
             showFactoryReset(false);
@@ -657,8 +657,7 @@
         // Now try to get status as time remaining and replace as appropriate
         Log.v(TAG, "Encryption progress: " + progress);
         try {
-            final String timeProperty = SystemProperties.get("vold.encrypt_time_remaining");
-            int time = Integer.parseInt(timeProperty);
+            int time = VoldProperties.encrypt_time_remaining().get();
             if (time >= 0) {
                 // Round up to multiple of 10 - this way display is less jerky
                 time = (time + 9) / 10 * 10;
diff --git a/src/com/android/settings/MasterClear.java b/src/com/android/settings/MasterClear.java
index 97942fe..307bbc1 100644
--- a/src/com/android/settings/MasterClear.java
+++ b/src/com/android/settings/MasterClear.java
@@ -39,6 +39,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
+import android.sysprop.VoldProperties;
 import android.telephony.euicc.EuiccManager;
 import android.text.TextUtils;
 import android.util.Log;
@@ -440,7 +441,7 @@
     }
 
     private boolean isExtStorageEncrypted() {
-        String state = SystemProperties.get("vold.decrypt");
+        String state = VoldProperties.decrypt().orElse("");
         return !"".equals(state);
     }
 
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index 07f59e2..9b5fc00 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -35,7 +35,6 @@
 import android.transition.TransitionManager;
 import android.util.Log;
 import android.view.View;
-import android.view.View.OnClickListener;
 import android.view.ViewGroup;
 import android.widget.Button;
 import android.widget.Toolbar;
@@ -169,6 +168,10 @@
 
     private Button mNextButton;
 
+    /**
+     * TODO(b/118444000): Remove this and all related code.
+     */
+    @Deprecated
     private boolean mIsShowingDashboard;
 
     private ViewGroup mContent;
@@ -241,9 +244,6 @@
         // Getting Intent properties can only be done after the super.onCreate(...)
         final String initialFragmentName = intent.getStringExtra(EXTRA_SHOW_FRAGMENT);
 
-        mIsShowingDashboard = TextUtils.equals(
-                SettingsActivity.class.getName(), intent.getComponent().getClassName());
-
         // This is a "Sub Settings" when:
         // - this is a real SubSettings
         // - or :settings:show_fragment_as_subsetting is passed to the Intent
@@ -256,6 +256,9 @@
             setTheme(R.style.Theme_SubSettings);
         }
 
+        mIsShowingDashboard = TextUtils.equals(
+                SettingsActivity.class.getName(), intent.getComponent().getClassName());
+
         setContentView(mIsShowingDashboard ?
                 R.layout.settings_main_dashboard : R.layout.settings_main_prefs);
 
@@ -276,7 +279,7 @@
                 setTitleFromBackStack();
             }
         } else {
-            launchSettingFragment(initialFragmentName, isSubSettings, intent);
+            launchSettingFragment(initialFragmentName, intent);
         }
 
         final boolean deviceProvisioned = Utils.isDeviceProvisioned(this);
@@ -308,26 +311,20 @@
             if (buttonBar != null) {
                 buttonBar.setVisibility(View.VISIBLE);
 
-                Button backButton = (Button) findViewById(R.id.back_button);
-                backButton.setOnClickListener(new OnClickListener() {
-                    public void onClick(View v) {
-                        setResult(RESULT_CANCELED, null);
-                        finish();
-                    }
+                Button backButton = findViewById(R.id.back_button);
+                backButton.setOnClickListener(v -> {
+                    setResult(RESULT_CANCELED, null);
+                    finish();
                 });
-                Button skipButton = (Button) findViewById(R.id.skip_button);
-                skipButton.setOnClickListener(new OnClickListener() {
-                    public void onClick(View v) {
-                        setResult(RESULT_OK, null);
-                        finish();
-                    }
+                Button skipButton = findViewById(R.id.skip_button);
+                skipButton.setOnClickListener(v -> {
+                    setResult(RESULT_OK, null);
+                    finish();
                 });
-                mNextButton = (Button) findViewById(R.id.next_button);
-                mNextButton.setOnClickListener(new OnClickListener() {
-                    public void onClick(View v) {
-                        setResult(RESULT_OK, null);
-                        finish();
-                    }
+                mNextButton = findViewById(R.id.next_button);
+                mNextButton.setOnClickListener(v -> {
+                    setResult(RESULT_OK, null);
+                    finish();
                 });
 
                 // set our various button parameters
@@ -372,8 +369,8 @@
     }
 
     @VisibleForTesting
-    void launchSettingFragment(String initialFragmentName, boolean isSubSettings, Intent intent) {
-        if (!mIsShowingDashboard && initialFragmentName != null) {
+    void launchSettingFragment(String initialFragmentName, Intent intent) {
+        if (initialFragmentName != null) {
             setTitleFromIntent(intent);
 
             Bundle initialArguments = intent.getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS);
diff --git a/src/com/android/settings/applications/AppStorageSettings.java b/src/com/android/settings/applications/AppStorageSettings.java
index 61ce33d..61293c5 100644
--- a/src/com/android/settings/applications/AppStorageSettings.java
+++ b/src/com/android/settings/applications/AppStorageSettings.java
@@ -53,11 +53,11 @@
 import com.android.settings.R;
 import com.android.settings.Utils;
 import com.android.settings.deviceinfo.StorageWizardMoveConfirm;
-import com.android.settings.widget.ActionButtonPreference;
 import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.applications.ApplicationsState.Callbacks;
 import com.android.settingslib.applications.StorageStatsSource;
 import com.android.settingslib.applications.StorageStatsSource.AppStorageStats;
+import com.android.settingslib.widget.ActionButtonsPreference;
 import com.android.settingslib.widget.LayoutPreference;
 
 import java.util.Collections;
@@ -107,7 +107,7 @@
 
     // Views related to cache info
     @VisibleForTesting
-    ActionButtonPreference mButtonsPref;
+    ActionButtonsPreference mButtonsPref;
 
     private Preference mStorageUsed;
     private Button mChangeStorageButton;
@@ -168,7 +168,7 @@
                 .setComputingString(R.string.computing_size)
                 .setErrorString(R.string.invalid_size_value)
                 .build();
-        mButtonsPref = ((ActionButtonPreference) findPreference(KEY_HEADER_BUTTONS));
+        mButtonsPref = ((ActionButtonsPreference) findPreference(KEY_HEADER_BUTTONS));
         mStorageUsed = findPreference(KEY_STORAGE_USED);
         mChangeStorageButton = (Button) ((LayoutPreference) findPreference(KEY_CHANGE_STORAGE))
                 .findViewById(R.id.button);
diff --git a/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java b/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java
index 9740ecb..2e528a7 100644
--- a/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java
+++ b/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java
@@ -54,7 +54,6 @@
 import com.android.settings.core.InstrumentedPreferenceFragment;
 import com.android.settings.core.PreferenceControllerMixin;
 import com.android.settings.overlay.FeatureFactory;
-import com.android.settings.widget.ActionButtonPreference;
 import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.applications.AppUtils;
@@ -64,6 +63,7 @@
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
 import com.android.settingslib.core.lifecycle.events.OnDestroy;
 import com.android.settingslib.core.lifecycle.events.OnResume;
+import com.android.settingslib.widget.ActionButtonsPreference;
 
 import java.util.ArrayList;
 import java.util.HashSet;
@@ -99,8 +99,9 @@
     @VisibleForTesting
     boolean mDisableAfterUninstall = false;
     @VisibleForTesting
-    ActionButtonPreference mButtonsPref;
+    ActionButtonsPreference mButtonsPref;
 
+    private final int mUserId;
     private final int mRequestUninstall;
     private final int mRequestRemoveDeviceAdmin;
     private final DevicePolicyManager mDpm;
@@ -110,8 +111,8 @@
     private final InstrumentedPreferenceFragment mFragment;
     private final MetricsFeatureProvider mMetricsFeatureProvider;
     private final ApplicationFeatureProvider mApplicationFeatureProvider;
-    private final int mUserId;
 
+    private Intent mAppLaunchIntent;
     private ApplicationsState.Session mSession;
     private RestrictedLockUtils.EnforcedAdmin mAppsControlDisallowedAdmin;
 
@@ -144,6 +145,7 @@
         mUserId = UserHandle.myUserId();
         mRequestUninstall = requestUninstall;
         mRequestRemoveDeviceAdmin = requestRemoveDeviceAdmin;
+        mAppLaunchIntent = mPm.getLaunchIntentForPackage(mPackageName);
 
         if (packageName != null) {
             mAppEntry = mState.getEntry(packageName, mUserId);
@@ -158,21 +160,25 @@
     public int getAvailabilityStatus() {
         // TODO(b/37313605): Re-enable once this controller supports instant apps
         return mAppEntry != null && !AppUtils.isInstant(mAppEntry.info)
-            ? AVAILABLE : DISABLED_FOR_USER ;
+                ? AVAILABLE : DISABLED_FOR_USER;
     }
 
     @Override
     public void displayPreference(PreferenceScreen screen) {
         super.displayPreference(screen);
         if (isAvailable()) {
-            mButtonsPref = ((ActionButtonPreference) screen.findPreference(KEY_ACTION_BUTTONS))
-                    .setButton1Text(R.string.uninstall_text)
-                    .setButton1Icon(R.drawable.ic_settings_delete)
-                    .setButton2Text(R.string.force_stop)
-                    .setButton2Icon(R.drawable.ic_settings_force_stop)
-                    .setButton1OnClickListener(new UninstallAndDisableButtonListener())
-                    .setButton2OnClickListener(new ForceStopButtonListener())
-                    .setButton2Enabled(false);
+            mButtonsPref = ((ActionButtonsPreference) screen.findPreference(
+                    KEY_ACTION_BUTTONS))
+                    .setButton1Text(R.string.launch_instant_app)
+                    .setButton1Icon(R.drawable.ic_settings_open)
+                    .setButton1OnClickListener(v -> launchApplication())
+                    .setButton2Text(R.string.uninstall_text)
+                    .setButton2Icon(R.drawable.ic_settings_delete)
+                    .setButton2OnClickListener(new UninstallAndDisableButtonListener())
+                    .setButton3Text(R.string.force_stop)
+                    .setButton3Icon(R.drawable.ic_settings_force_stop)
+                    .setButton3OnClickListener(new ForceStopButtonListener())
+                    .setButton3Enabled(false);
         }
     }
 
@@ -361,6 +367,12 @@
     }
 
     @VisibleForTesting
+    void updateOpenButton() {
+        mAppLaunchIntent = mPm.getLaunchIntentForPackage(mPackageName);
+        mButtonsPref.setButton1Visible(mAppLaunchIntent != null);
+    }
+
+    @VisibleForTesting
     void updateUninstallButton() {
         final boolean isBundled = (mAppEntry.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
         boolean enabled = true;
@@ -430,7 +442,7 @@
             enabled = false;
         }
 
-        mButtonsPref.setButton1Enabled(enabled);
+        mButtonsPref.setButton2Enabled(enabled);
     }
 
     /**
@@ -484,7 +496,7 @@
         } else {
             Intent intent = new Intent(Intent.ACTION_QUERY_PACKAGE_RESTART,
                     Uri.fromParts("package", mAppEntry.info.packageName, null));
-            intent.putExtra(Intent.EXTRA_PACKAGES, new String[] {mAppEntry.info.packageName});
+            intent.putExtra(Intent.EXTRA_PACKAGES, new String[]{mAppEntry.info.packageName});
             intent.putExtra(Intent.EXTRA_UID, mAppEntry.info.uid);
             intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(mAppEntry.info.uid));
             Log.d(TAG, "Sending broadcast to query restart status for "
@@ -497,9 +509,9 @@
     @VisibleForTesting
     void updateForceStopButtonInner(boolean enabled) {
         if (mAppsControlDisallowedBySystem) {
-            mButtonsPref.setButton2Enabled(false);
+            mButtonsPref.setButton3Enabled(false);
         } else {
-            mButtonsPref.setButton2Enabled(enabled);
+            mButtonsPref.setButton3Enabled(enabled);
         }
     }
 
@@ -547,16 +559,16 @@
         if (mHomePackages.contains(mAppEntry.info.packageName)
                 || isSystemPackage(mActivity.getResources(), mPm, mPackageInfo)) {
             // Disable button for core system applications.
-            mButtonsPref.setButton1Text(R.string.uninstall_text)
-                    .setButton1Icon(R.drawable.ic_settings_delete);
+            mButtonsPref.setButton2Text(R.string.uninstall_text)
+                    .setButton2Icon(R.drawable.ic_settings_delete);
         } else if (mAppEntry.info.enabled && !isDisabledUntilUsed()) {
-            mButtonsPref.setButton1Text(R.string.uninstall_text)
-                    .setButton1Icon(R.drawable.ic_settings_delete);
+            mButtonsPref.setButton2Text(R.string.uninstall_text)
+                    .setButton2Icon(R.drawable.ic_settings_delete);
             disableable = !mApplicationFeatureProvider.getKeepEnabledPackages()
                     .contains(mAppEntry.info.packageName);
         } else {
-            mButtonsPref.setButton1Text(R.string.install_text)
-                    .setButton1Icon(R.drawable.ic_settings_install);
+            mButtonsPref.setButton2Text(R.string.install_text)
+                    .setButton2Icon(R.drawable.ic_settings_install);
             disableable = true;
         }
 
@@ -639,6 +651,7 @@
             }
         }
 
+        updateOpenButton();
         updateUninstallButton();
         updateForceStopButton();
 
@@ -663,6 +676,11 @@
         mActivity.unregisterReceiver(mPackageRemovedReceiver);
     }
 
+    private void launchApplication() {
+        if (mAppLaunchIntent != null) {
+            mContext.startActivityAsUser(mAppLaunchIntent, new UserHandle(mUserId));
+        }
+    }
 
     /**
      * Changes the status of disable/enable for a package
diff --git a/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceController.java b/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceController.java
index 9443c93..1bfcd7d 100644
--- a/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceController.java
+++ b/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceController.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * 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.
@@ -17,15 +17,10 @@
 package com.android.settings.applications.appinfo;
 
 import android.content.Context;
-import android.net.INetworkStatsService;
-import android.net.INetworkStatsSession;
 import android.net.NetworkTemplate;
 import android.os.Bundle;
-import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.text.format.DateUtils;
 import android.text.format.Formatter;
-import android.util.FeatureFlagUtils;
 
 import androidx.annotation.VisibleForTesting;
 import androidx.loader.app.LoaderManager;
@@ -36,53 +31,35 @@
 import com.android.settings.R;
 import com.android.settings.SettingsPreferenceFragment;
 import com.android.settings.Utils;
-import com.android.settings.core.FeatureFlags;
 import com.android.settings.datausage.AppDataUsage;
-import com.android.settings.datausage.DataUsageList;
 import com.android.settings.datausage.DataUsageUtils;
 import com.android.settingslib.AppItem;
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
 import com.android.settingslib.core.lifecycle.events.OnPause;
 import com.android.settingslib.core.lifecycle.events.OnResume;
-import com.android.settingslib.net.ChartData;
-import com.android.settingslib.net.ChartDataLoaderCompat;
+import com.android.settingslib.net.NetworkCycleDataForUid;
+import com.android.settingslib.net.NetworkCycleDataForUidLoader;
 
-/**
- * Deprecated in favor of {@link AppDataUsagePreferenceControllerV2}
- *
- * @deprecated
- */
-@Deprecated
+import java.util.List;
+
 public class AppDataUsagePreferenceController extends AppInfoPreferenceControllerBase
-        implements LoaderManager.LoaderCallbacks<ChartData>, LifecycleObserver, OnResume, OnPause {
+        implements LoaderManager.LoaderCallbacks<List<NetworkCycleDataForUid>>, LifecycleObserver,
+        OnResume, OnPause {
 
-    private ChartData mChartData;
-    private INetworkStatsSession mStatsSession;
+    private List<NetworkCycleDataForUid> mAppUsageData;
 
-    public AppDataUsagePreferenceController(Context context,String key) {
+    public AppDataUsagePreferenceController(Context context, String key) {
         super(context, key);
     }
 
     @Override
     public int getAvailabilityStatus() {
-        if (FeatureFlagUtils.isEnabled(mContext, FeatureFlags.DATA_USAGE_V2)) {
-            return UNSUPPORTED_ON_DEVICE;
-        }
         return isBandwidthControlEnabled() ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
     }
 
     @Override
     public void displayPreference(PreferenceScreen screen) {
         super.displayPreference(screen);
-        if (isAvailable()) {
-            final INetworkStatsService statsService = INetworkStatsService.Stub.asInterface(
-                    ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
-            try {
-                mStatsSession = statsService.openSession();
-            } catch (RemoteException e) {
-                throw new RuntimeException(e);
-            }
-        }
     }
 
     @Override
@@ -92,36 +69,42 @@
 
     @Override
     public void onResume() {
-        if (mStatsSession != null) {
+        if (isAvailable()) {
             final int uid = mParent.getAppEntry().info.uid;
             final AppItem app = new AppItem(uid);
             app.addUid(uid);
-            mParent.getLoaderManager().restartLoader(mParent.LOADER_CHART_DATA,
-                    ChartDataLoaderCompat.buildArgs(getTemplate(mContext), app),
+            mParent.getLoaderManager().restartLoader(mParent.LOADER_CHART_DATA, null /* args */,
                     this);
         }
     }
 
     @Override
     public void onPause() {
-        if (mStatsSession != null) {
+        if (isAvailable()) {
             mParent.getLoaderManager().destroyLoader(mParent.LOADER_CHART_DATA);
         }
     }
 
     @Override
-    public Loader<ChartData> onCreateLoader(int id, Bundle args) {
-        return new ChartDataLoaderCompat(mContext, mStatsSession, args);
+    public Loader<List<NetworkCycleDataForUid>> onCreateLoader(int id, Bundle args) {
+        final NetworkTemplate template = getTemplate(mContext);
+        return NetworkCycleDataForUidLoader.builder(mContext)
+            .setUid(mParent.getAppEntry().info.uid)
+            .setRetrieveDetail(false)
+            .setNetworkTemplate(template)
+            .setSubscriberId(template.getSubscriberId())
+            .build();
     }
 
     @Override
-    public void onLoadFinished(Loader<ChartData> loader, ChartData data) {
-        mChartData = data;
+    public void onLoadFinished(Loader<List<NetworkCycleDataForUid>> loader,
+            List<NetworkCycleDataForUid> data) {
+        mAppUsageData = data;
         updateState(mPreference);
     }
 
     @Override
-    public void onLoaderReset(Loader<ChartData> loader) {
+    public void onLoaderReset(Loader<List<NetworkCycleDataForUid>> loader) {
         // Leave last result.
     }
 
@@ -131,14 +114,22 @@
     }
 
     private CharSequence getDataSummary() {
-        if (mChartData != null) {
-            final long totalBytes = mChartData.detail.getTotalBytes();
+        if (mAppUsageData != null) {
+            long totalBytes = 0;
+            long startTime = System.currentTimeMillis();
+            for (NetworkCycleDataForUid data : mAppUsageData) {
+                totalBytes += data.getTotalUsage();
+                final long cycleStart = data.getStartTime();
+                if (cycleStart < startTime) {
+                    startTime = cycleStart;
+                }
+            }
             if (totalBytes == 0) {
                 return mContext.getString(R.string.no_data_usage);
             }
             return mContext.getString(R.string.data_summary_format,
                     Formatter.formatFileSize(mContext, totalBytes),
-                    DateUtils.formatDateTime(mContext, mChartData.detail.getStart(),
+                    DateUtils.formatDateTime(mContext, startTime,
                             DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_ABBREV_MONTH));
         }
         return mContext.getString(R.string.computing_size);
diff --git a/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerV2.java b/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerV2.java
deleted file mode 100644
index 9bbc5c0..0000000
--- a/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerV2.java
+++ /dev/null
@@ -1,158 +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.appinfo;
-
-import android.content.Context;
-import android.net.NetworkTemplate;
-import android.os.Bundle;
-import android.text.format.DateUtils;
-import android.text.format.Formatter;
-import android.util.FeatureFlagUtils;
-
-import androidx.annotation.VisibleForTesting;
-import androidx.loader.app.LoaderManager;
-import androidx.loader.content.Loader;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settings.R;
-import com.android.settings.SettingsPreferenceFragment;
-import com.android.settings.Utils;
-import com.android.settings.core.FeatureFlags;
-import com.android.settings.datausage.AppDataUsageV2;
-import com.android.settings.datausage.DataUsageUtils;
-import com.android.settingslib.AppItem;
-import com.android.settingslib.core.lifecycle.LifecycleObserver;
-import com.android.settingslib.core.lifecycle.events.OnPause;
-import com.android.settingslib.core.lifecycle.events.OnResume;
-import com.android.settingslib.net.NetworkCycleDataForUid;
-import com.android.settingslib.net.NetworkCycleDataForUidLoader;
-
-import java.util.List;
-
-public class AppDataUsagePreferenceControllerV2 extends AppInfoPreferenceControllerBase
-        implements LoaderManager.LoaderCallbacks<List<NetworkCycleDataForUid>>, LifecycleObserver,
-        OnResume, OnPause {
-
-    private List<NetworkCycleDataForUid> mAppUsageData;
-
-    public AppDataUsagePreferenceControllerV2(Context context, String key) {
-        super(context, key);
-    }
-
-    @Override
-    public int getAvailabilityStatus() {
-        if (!FeatureFlagUtils.isEnabled(mContext, FeatureFlags.DATA_USAGE_V2)) {
-            return UNSUPPORTED_ON_DEVICE;
-        }
-        return isBandwidthControlEnabled() ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
-    }
-
-    @Override
-    public void displayPreference(PreferenceScreen screen) {
-        super.displayPreference(screen);
-    }
-
-    @Override
-    public void updateState(Preference preference) {
-        preference.setSummary(getDataSummary());
-    }
-
-    @Override
-    public void onResume() {
-        if (isAvailable()) {
-            final int uid = mParent.getAppEntry().info.uid;
-            final AppItem app = new AppItem(uid);
-            app.addUid(uid);
-            mParent.getLoaderManager().restartLoader(mParent.LOADER_CHART_DATA, null /* args */,
-                    this);
-        }
-    }
-
-    @Override
-    public void onPause() {
-        if (isAvailable()) {
-            mParent.getLoaderManager().destroyLoader(mParent.LOADER_CHART_DATA);
-        }
-    }
-
-    @Override
-    public Loader<List<NetworkCycleDataForUid>> onCreateLoader(int id, Bundle args) {
-        final NetworkTemplate template = getTemplate(mContext);
-        return NetworkCycleDataForUidLoader.builder(mContext)
-            .setUid(mParent.getAppEntry().info.uid)
-            .setRetrieveDetail(false)
-            .setNetworkTemplate(template)
-            .setSubscriberId(template.getSubscriberId())
-            .build();
-    }
-
-    @Override
-    public void onLoadFinished(Loader<List<NetworkCycleDataForUid>> loader,
-            List<NetworkCycleDataForUid> data) {
-        mAppUsageData = data;
-        updateState(mPreference);
-    }
-
-    @Override
-    public void onLoaderReset(Loader<List<NetworkCycleDataForUid>> loader) {
-        // Leave last result.
-    }
-
-    @Override
-    protected Class<? extends SettingsPreferenceFragment> getDetailFragmentClass() {
-        return AppDataUsageV2.class;
-    }
-
-    private CharSequence getDataSummary() {
-        if (mAppUsageData != null) {
-            long totalBytes = 0;
-            long startTime = System.currentTimeMillis();
-            for (NetworkCycleDataForUid data : mAppUsageData) {
-                totalBytes += data.getTotalUsage();
-                final long cycleStart = data.getStartTime();
-                if (cycleStart < startTime) {
-                    startTime = cycleStart;
-                }
-            }
-            if (totalBytes == 0) {
-                return mContext.getString(R.string.no_data_usage);
-            }
-            return mContext.getString(R.string.data_summary_format,
-                    Formatter.formatFileSize(mContext, totalBytes),
-                    DateUtils.formatDateTime(mContext, startTime,
-                            DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_ABBREV_MONTH));
-        }
-        return mContext.getString(R.string.computing_size);
-    }
-
-    private static NetworkTemplate getTemplate(Context context) {
-        if (DataUsageUtils.hasReadyMobileRadio(context)) {
-            return NetworkTemplate.buildTemplateMobileWildcard();
-        }
-        if (DataUsageUtils.hasWifiRadio(context)) {
-            return NetworkTemplate.buildTemplateWifiWildcard();
-        }
-        return NetworkTemplate.buildTemplateEthernet();
-    }
-
-    @VisibleForTesting
-    boolean isBandwidthControlEnabled() {
-        return Utils.isBandwidthControlEnabled();
-    }
-
-}
diff --git a/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java b/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java
index 32880d3..80cc6ae 100755
--- a/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java
+++ b/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java
@@ -34,7 +34,6 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.text.TextUtils;
-import android.util.FeatureFlagUtils;
 import android.util.Log;
 import android.view.Menu;
 import android.view.MenuInflater;
@@ -49,7 +48,6 @@
 import com.android.settings.applications.manageapplications.ManageApplications;
 import com.android.settings.applications.specialaccess.pictureinpicture
         .PictureInPictureDetailPreferenceController;
-import com.android.settings.core.FeatureFlags;
 import com.android.settings.core.SubSettingLauncher;
 import com.android.settings.dashboard.DashboardFragment;
 import com.android.settingslib.RestrictedLockUtilsInternal;
@@ -141,11 +139,7 @@
         final String packageName = getPackageName();
         use(TimeSpentInAppPreferenceController.class).setPackageName(packageName);
 
-        if (FeatureFlagUtils.isEnabled(context, FeatureFlags.DATA_USAGE_V2)) {
-            use(AppDataUsagePreferenceControllerV2.class).setParentFragment(this);
-        } else {
-            use(AppDataUsagePreferenceController.class).setParentFragment(this);
-        }
+        use(AppDataUsagePreferenceController.class).setParentFragment(this);
         final AppInstallerInfoPreferenceController installer =
                 use(AppInstallerInfoPreferenceController.class);
         installer.setPackageName(packageName);
diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsButtonsController.java b/src/com/android/settings/bluetooth/BluetoothDetailsButtonsController.java
index 563a06a..a438f09 100644
--- a/src/com/android/settings/bluetooth/BluetoothDetailsButtonsController.java
+++ b/src/com/android/settings/bluetooth/BluetoothDetailsButtonsController.java
@@ -22,9 +22,9 @@
 import androidx.preference.PreferenceScreen;
 
 import com.android.settings.R;
-import com.android.settings.widget.ActionButtonPreference;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.widget.ActionButtonsPreference;
 
 /**
  * This class adds two buttons: one to connect/disconnect from a device (depending on the current
@@ -35,7 +35,7 @@
     private boolean mIsConnected;
 
     private boolean mConnectButtonInitialized;
-    private ActionButtonPreference mActionButtons;
+    private ActionButtonsPreference mActionButtons;
 
     public BluetoothDetailsButtonsController(Context context, PreferenceFragmentCompat fragment,
             CachedBluetoothDevice device, Lifecycle lifecycle) {
@@ -51,7 +51,8 @@
 
     @Override
     protected void init(PreferenceScreen screen) {
-        mActionButtons = ((ActionButtonPreference) screen.findPreference(getPreferenceKey()))
+        mActionButtons = ((ActionButtonsPreference) screen.findPreference(
+                getPreferenceKey()))
                 .setButton1Text(R.string.forget)
                 .setButton1Icon(R.drawable.ic_settings_delete)
                 .setButton1OnClickListener((view) -> onForgetButtonPressed())
@@ -76,7 +77,7 @@
             if (!mConnectButtonInitialized || previouslyConnected) {
                 mActionButtons
                         .setButton2Text(R.string.bluetooth_device_context_connect)
-                        // TODO (b/119646923) Icon is not ready.
+                        .setButton2Icon(R.drawable.ic_add_24dp)
                         .setButton2OnClickListener(
                                 view -> mCachedDevice.connect(true /* connectAllProfiles */));
                 mConnectButtonInitialized = true;
diff --git a/src/com/android/settings/bluetooth/BluetoothSliceBuilder.java b/src/com/android/settings/bluetooth/BluetoothSliceBuilder.java
index 1462f91..67e8b19 100644
--- a/src/com/android/settings/bluetooth/BluetoothSliceBuilder.java
+++ b/src/com/android/settings/bluetooth/BluetoothSliceBuilder.java
@@ -20,7 +20,6 @@
 import android.annotation.ColorInt;
 import android.app.PendingIntent;
 import android.bluetooth.BluetoothAdapter;
-import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -37,6 +36,7 @@
 import com.android.settings.R;
 import com.android.settings.SubSettings;
 import com.android.settings.connecteddevice.BluetoothDashboardFragment;
+import com.android.settings.slices.CustomSliceRegistry;
 import com.android.settings.slices.SliceBroadcastReceiver;
 import com.android.settings.slices.SliceBuilderUtils;
 
@@ -48,16 +48,6 @@
     private static final String TAG = "BluetoothSliceBuilder";
 
     /**
-     * Backing Uri for the Bluetooth Slice.
-     */
-    public static final Uri BLUETOOTH_URI = new Uri.Builder()
-            .scheme(ContentResolver.SCHEME_CONTENT)
-            .authority(SettingsSlicesContract.AUTHORITY)
-            .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
-            .appendPath(SettingsSlicesContract.KEY_BLUETOOTH)
-            .build();
-
-    /**
      * Action notifying a change on the BluetoothSlice.
      */
     public static final String ACTION_BLUETOOTH_SLICE_CHANGED =
@@ -74,7 +64,7 @@
     }
 
     /**
-     * Return a Bluetooth Slice bound to {@link #BLUETOOTH_URI}.
+     * Return a Bluetooth Slice bound to {@link CustomSliceRegistry#BLUETOOTH_URI}.
      * <p>
      * Note that you should register a listener for {@link #INTENT_FILTER} to get changes for
      * Bluetooth.
@@ -88,11 +78,12 @@
                 context).getDefaultColor();
         final PendingIntent toggleAction = getBroadcastIntent(context);
         final PendingIntent primaryAction = getPrimaryAction(context);
-        final SliceAction primarySliceAction = new SliceAction(primaryAction, icon, title);
-        final SliceAction toggleSliceAction = new SliceAction(toggleAction, null /* actionTitle */,
-                isBluetoothEnabled);
+        final SliceAction primarySliceAction = SliceAction.createDeeplink(primaryAction, icon,
+                ListBuilder.ICON_IMAGE, title);
+        final SliceAction toggleSliceAction = SliceAction.createToggle(toggleAction,
+                null /* actionTitle */, isBluetoothEnabled);
 
-        return new ListBuilder(context, BLUETOOTH_URI, ListBuilder.INFINITY)
+        return new ListBuilder(context, CustomSliceRegistry.BLUETOOTH_URI, ListBuilder.INFINITY)
                 .setAccentColor(color)
                 .addRow(new RowBuilder()
                         .setTitle(title)
diff --git a/src/com/android/settings/core/FeatureFlags.java b/src/com/android/settings/core/FeatureFlags.java
index 0a26b79..daa1e7b 100644
--- a/src/com/android/settings/core/FeatureFlags.java
+++ b/src/com/android/settings/core/FeatureFlags.java
@@ -24,7 +24,6 @@
     public static final String DYNAMIC_HOMEPAGE = "settings_dynamic_homepage";
     public static final String HEARING_AID_SETTINGS = "settings_bluetooth_hearing_aid";
     public static final String MOBILE_NETWORK_V2 = "settings_mobile_network_v2";
-    public static final String DATA_USAGE_V2 = "settings_data_usage_v2";
     public static final String WIFI_MAC_RANDOMIZATION = "settings_wifi_mac_randomization";
     public static final String NETWORK_INTERNET_V2 = "settings_network_and_internet_v2";
 }
diff --git a/src/com/android/settings/dashboard/DashboardFragmentRegistry.java b/src/com/android/settings/dashboard/DashboardFragmentRegistry.java
index 8b5d521..2f447d4 100644
--- a/src/com/android/settings/dashboard/DashboardFragmentRegistry.java
+++ b/src/com/android/settings/dashboard/DashboardFragmentRegistry.java
@@ -28,6 +28,7 @@
 import com.android.settings.development.DevelopmentSettingsDashboardFragment;
 import com.android.settings.deviceinfo.StorageDashboardFragment;
 import com.android.settings.display.NightDisplaySettings;
+import com.android.settings.enterprise.EnterprisePrivacySettings;
 import com.android.settings.fuelgauge.PowerUsageSummary;
 import com.android.settings.gestures.GestureSettings;
 import com.android.settings.homepage.TopLevelSettings;
@@ -107,6 +108,8 @@
                 CategoryKey.CATEGORY_NIGHT_DISPLAY);
         PARENT_TO_CATEGORY_KEY_MAP.put(PrivacyDashboardFragment.class.getName(),
                 CategoryKey.CATEGORY_PRIVACY);
+        PARENT_TO_CATEGORY_KEY_MAP.put(EnterprisePrivacySettings.class.getName(),
+                CategoryKey.CATEGORY_ENTERPRISE_PRIVACY);
 
         CATEGORY_KEY_TO_PARENT_MAP = new ArrayMap<>(PARENT_TO_CATEGORY_KEY_MAP.size());
 
diff --git a/src/com/android/settings/datausage/AppDataUsage.java b/src/com/android/settings/datausage/AppDataUsage.java
index 78aa6c2..b6c95dd 100644
--- a/src/com/android/settings/datausage/AppDataUsage.java
+++ b/src/com/android/settings/datausage/AppDataUsage.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * 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
@@ -22,13 +22,8 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.graphics.drawable.Drawable;
-import android.net.INetworkStatsSession;
-import android.net.NetworkPolicy;
-import android.net.NetworkStatsHistory;
 import android.net.NetworkTemplate;
-import android.net.TrafficStats;
 import android.os.Bundle;
-import android.os.RemoteException;
 import android.os.UserHandle;
 import android.util.ArraySet;
 import android.util.IconDrawableFactory;
@@ -51,11 +46,13 @@
 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
 import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.RestrictedSwitchPreference;
-import com.android.settingslib.net.ChartData;
-import com.android.settingslib.net.ChartDataLoaderCompat;
+import com.android.settingslib.net.NetworkCycleDataForUid;
+import com.android.settingslib.net.NetworkCycleDataForUidLoader;
 import com.android.settingslib.net.UidDetail;
 import com.android.settingslib.net.UidDetailProvider;
 
+import java.util.List;
+
 public class AppDataUsage extends DataUsageBaseFragment implements OnPreferenceChangeListener,
         DataSaverBackend.Listener {
 
@@ -73,7 +70,7 @@
     private static final String KEY_CYCLE = "cycle";
     private static final String KEY_UNRESTRICTED_DATA = "unrestricted_data_saver";
 
-    private static final int LOADER_CHART_DATA = 2;
+    private static final int LOADER_APP_USAGE_DATA = 2;
     private static final int LOADER_APP_PREF = 3;
 
     private PackageManager mPackageManager;
@@ -88,14 +85,10 @@
     private Drawable mIcon;
     private CharSequence mLabel;
     private String mPackageName;
-    private INetworkStatsSession mStatsSession;
     private CycleAdapter mCycleAdapter;
 
-    private long mStart;
-    private long mEnd;
-    private ChartData mChartData;
+    private List<NetworkCycleDataForUid> mUsageData;
     private NetworkTemplate mTemplate;
-    private NetworkPolicy mPolicy;
     private AppItem mAppItem;
     private Intent mAppSettingsIntent;
     private SpinnerPreference mCycle;
@@ -108,12 +101,6 @@
         mPackageManager = getPackageManager();
         final Bundle args = getArguments();
 
-        try {
-            mStatsSession = services.mStatsService.openSession();
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-
         mAppItem = (args != null) ? (AppItem) args.getParcelable(ARG_APP_ITEM) : null;
         mTemplate = (args != null) ? (NetworkTemplate) args.getParcelable(ARG_NETWORK_TEMPLATE)
                 : null;
@@ -210,20 +197,13 @@
     }
 
     @Override
-    public void onDestroy() {
-        TrafficStats.closeQuietly(mStatsSession);
-        super.onDestroy();
-    }
-
-    @Override
     public void onResume() {
         super.onResume();
         if (mDataSaverBackend != null) {
             mDataSaverBackend.addListener(this);
         }
-        mPolicy = services.mPolicyEditor.getPolicy(mTemplate);
-        LoaderManager.getInstance(this).restartLoader(LOADER_CHART_DATA,
-                ChartDataLoaderCompat.buildArgs(mTemplate, mAppItem), mChartDataCallbacks);
+        LoaderManager.getInstance(this).restartLoader(LOADER_APP_USAGE_DATA, null /* args */,
+                mUidDataCallbacks);
         updatePrefs();
     }
 
@@ -301,19 +281,17 @@
         }
     }
 
-    private void bindData() {
+    @VisibleForTesting
+    void bindData(int position) {
         final long backgroundBytes, foregroundBytes;
-        if (mChartData == null || mStart == 0) {
+        if (mUsageData == null || position >= mUsageData.size()) {
             backgroundBytes = foregroundBytes = 0;
             mCycle.setVisible(false);
         } else {
             mCycle.setVisible(true);
-            final long now = System.currentTimeMillis();
-            NetworkStatsHistory.Entry entry = null;
-            entry = mChartData.detailDefault.getValues(mStart, mEnd, now, entry);
-            backgroundBytes = entry.rxBytes + entry.txBytes;
-            entry = mChartData.detailForeground.getValues(mStart, mEnd, now, entry);
-            foregroundBytes = entry.rxBytes + entry.txBytes;
+            final NetworkCycleDataForUid data = mUsageData.get(position);
+            backgroundBytes = data.getBackgroudUsage();
+            foregroundBytes = data.getForegroudUsage();
         }
         final long totalBytes = backgroundBytes + foregroundBytes;
         final Context context = getContext();
@@ -377,11 +355,7 @@
             new AdapterView.OnItemSelectedListener() {
         @Override
         public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
-            final CycleAdapter.CycleItem cycle = (CycleAdapter.CycleItem) mCycle.getSelectedItem();
-
-            mStart = cycle.start;
-            mEnd = cycle.end;
-            bindData();
+            bindData(position);
         }
 
         @Override
@@ -390,24 +364,30 @@
         }
     };
 
-    private final LoaderManager.LoaderCallbacks<ChartData> mChartDataCallbacks =
-            new LoaderManager.LoaderCallbacks<ChartData>() {
-        @Override
-        public Loader<ChartData> onCreateLoader(int id, Bundle args) {
-            return new ChartDataLoaderCompat(getActivity(), mStatsSession, args);
-        }
+    private final LoaderManager.LoaderCallbacks<List<NetworkCycleDataForUid>> mUidDataCallbacks =
+        new LoaderManager.LoaderCallbacks<List<NetworkCycleDataForUid>>() {
+            @Override
+            public Loader<List<NetworkCycleDataForUid>> onCreateLoader(int id, Bundle args) {
+                return NetworkCycleDataForUidLoader.builder(getContext())
+                    .setUid(mAppItem.key)
+                    .setRetrieveDetail(true)
+                    .setNetworkTemplate(mTemplate)
+                    .setSubscriberId(mTemplate.getSubscriberId())
+                    .build();
+            }
 
-        @Override
-        public void onLoadFinished(Loader<ChartData> loader, ChartData data) {
-            mChartData = data;
-            mCycleAdapter.updateCycleList(mPolicy, mChartData);
-            bindData();
-        }
+            @Override
+            public void onLoadFinished(Loader<List<NetworkCycleDataForUid>> loader,
+                    List<NetworkCycleDataForUid> data) {
+                mUsageData = data;
+                mCycleAdapter.updateCycleList(data);
+                bindData(0 /* position */);
+            }
 
-        @Override
-        public void onLoaderReset(Loader<ChartData> loader) {
-        }
-    };
+            @Override
+            public void onLoaderReset(Loader<List<NetworkCycleDataForUid>> loader) {
+            }
+        };
 
     private final LoaderManager.LoaderCallbacks<ArraySet<Preference>> mAppPrefCallbacks =
         new LoaderManager.LoaderCallbacks<ArraySet<Preference>>() {
diff --git a/src/com/android/settings/datausage/AppDataUsageV2.java b/src/com/android/settings/datausage/AppDataUsageV2.java
deleted file mode 100644
index 6a31726..0000000
--- a/src/com/android/settings/datausage/AppDataUsageV2.java
+++ /dev/null
@@ -1,432 +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.datausage;
-
-import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.graphics.drawable.Drawable;
-import android.net.NetworkTemplate;
-import android.os.Bundle;
-import android.os.UserHandle;
-import android.util.ArraySet;
-import android.util.IconDrawableFactory;
-import android.util.Log;
-import android.view.View;
-import android.widget.AdapterView;
-
-import androidx.annotation.VisibleForTesting;
-import androidx.loader.app.LoaderManager;
-import androidx.loader.content.Loader;
-import androidx.preference.Preference;
-import androidx.preference.Preference.OnPreferenceChangeListener;
-import androidx.preference.PreferenceCategory;
-
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.settings.R;
-import com.android.settings.applications.AppInfoBase;
-import com.android.settings.widget.EntityHeaderController;
-import com.android.settingslib.AppItem;
-import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
-import com.android.settingslib.RestrictedLockUtilsInternal;
-import com.android.settingslib.RestrictedSwitchPreference;
-import com.android.settingslib.net.NetworkCycleDataForUid;
-import com.android.settingslib.net.NetworkCycleDataForUidLoader;
-import com.android.settingslib.net.UidDetail;
-import com.android.settingslib.net.UidDetailProvider;
-
-import java.util.List;
-
-public class AppDataUsageV2 extends DataUsageBaseFragment implements OnPreferenceChangeListener,
-        DataSaverBackend.Listener {
-
-    private static final String TAG = "AppDataUsageV2";
-
-    public static final String ARG_APP_ITEM = "app_item";
-    public static final String ARG_NETWORK_TEMPLATE = "network_template";
-
-    private static final String KEY_TOTAL_USAGE = "total_usage";
-    private static final String KEY_FOREGROUND_USAGE = "foreground_usage";
-    private static final String KEY_BACKGROUND_USAGE = "background_usage";
-    private static final String KEY_APP_SETTINGS = "app_settings";
-    private static final String KEY_RESTRICT_BACKGROUND = "restrict_background";
-    private static final String KEY_APP_LIST = "app_list";
-    private static final String KEY_CYCLE = "cycle";
-    private static final String KEY_UNRESTRICTED_DATA = "unrestricted_data_saver";
-
-    private static final int LOADER_APP_USAGE_DATA = 2;
-    private static final int LOADER_APP_PREF = 3;
-
-    private PackageManager mPackageManager;
-    private final ArraySet<String> mPackages = new ArraySet<>();
-    private Preference mTotalUsage;
-    private Preference mForegroundUsage;
-    private Preference mBackgroundUsage;
-    private Preference mAppSettings;
-    private RestrictedSwitchPreference mRestrictBackground;
-    private PreferenceCategory mAppList;
-
-    private Drawable mIcon;
-    private CharSequence mLabel;
-    private String mPackageName;
-    private CycleAdapter mCycleAdapter;
-
-    private List<NetworkCycleDataForUid> mUsageData;
-    private NetworkTemplate mTemplate;
-    private AppItem mAppItem;
-    private Intent mAppSettingsIntent;
-    private SpinnerPreference mCycle;
-    private RestrictedSwitchPreference mUnrestrictedData;
-    private DataSaverBackend mDataSaverBackend;
-
-    @Override
-    public void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
-        mPackageManager = getPackageManager();
-        final Bundle args = getArguments();
-
-        mAppItem = (args != null) ? (AppItem) args.getParcelable(ARG_APP_ITEM) : null;
-        mTemplate = (args != null) ? (NetworkTemplate) args.getParcelable(ARG_NETWORK_TEMPLATE)
-                : null;
-        if (mTemplate == null) {
-            Context context = getContext();
-            mTemplate = DataUsageUtils.getDefaultTemplate(context,
-                    DataUsageUtils.getDefaultSubscriptionId(context));
-        }
-        if (mAppItem == null) {
-            int uid = (args != null) ? args.getInt(AppInfoBase.ARG_PACKAGE_UID, -1)
-                    : getActivity().getIntent().getIntExtra(AppInfoBase.ARG_PACKAGE_UID, -1);
-            if (uid == -1) {
-                // TODO: Log error.
-                getActivity().finish();
-            } else {
-                addUid(uid);
-                mAppItem = new AppItem(uid);
-                mAppItem.addUid(uid);
-            }
-        } else {
-            for (int i = 0; i < mAppItem.uids.size(); i++) {
-                addUid(mAppItem.uids.keyAt(i));
-            }
-        }
-
-        mTotalUsage = findPreference(KEY_TOTAL_USAGE);
-        mForegroundUsage = findPreference(KEY_FOREGROUND_USAGE);
-        mBackgroundUsage = findPreference(KEY_BACKGROUND_USAGE);
-
-        mCycle = (SpinnerPreference) findPreference(KEY_CYCLE);
-        mCycleAdapter = new CycleAdapter(getContext(), mCycle, mCycleListener);
-
-        if (mAppItem.key > 0) {
-            if (mPackages.size() != 0) {
-                try {
-                    ApplicationInfo info = mPackageManager.getApplicationInfoAsUser(
-                            mPackages.valueAt(0), 0, UserHandle.getUserId(mAppItem.key));
-                    mIcon = IconDrawableFactory.newInstance(getActivity()).getBadgedIcon(info);
-                    mLabel = info.loadLabel(mPackageManager);
-                    mPackageName = info.packageName;
-                } catch (PackageManager.NameNotFoundException e) {
-                }
-            }
-            if (!UserHandle.isApp(mAppItem.key)) {
-                removePreference(KEY_UNRESTRICTED_DATA);
-                removePreference(KEY_RESTRICT_BACKGROUND);
-            } else {
-                mRestrictBackground = (RestrictedSwitchPreference) findPreference(
-                        KEY_RESTRICT_BACKGROUND);
-                mRestrictBackground.setOnPreferenceChangeListener(this);
-                mUnrestrictedData = (RestrictedSwitchPreference) findPreference(
-                        KEY_UNRESTRICTED_DATA);
-                mUnrestrictedData.setOnPreferenceChangeListener(this);
-            }
-            mDataSaverBackend = new DataSaverBackend(getContext());
-            mAppSettings = findPreference(KEY_APP_SETTINGS);
-
-            mAppSettingsIntent = new Intent(Intent.ACTION_MANAGE_NETWORK_USAGE);
-            mAppSettingsIntent.addCategory(Intent.CATEGORY_DEFAULT);
-
-            PackageManager pm = getPackageManager();
-            boolean matchFound = false;
-            for (String packageName : mPackages) {
-                mAppSettingsIntent.setPackage(packageName);
-                if (pm.resolveActivity(mAppSettingsIntent, 0) != null) {
-                    matchFound = true;
-                    break;
-                }
-            }
-            if (!matchFound) {
-                removePreference(KEY_APP_SETTINGS);
-                mAppSettings = null;
-            }
-
-            if (mPackages.size() > 1) {
-                mAppList = (PreferenceCategory) findPreference(KEY_APP_LIST);
-                LoaderManager.getInstance(this).restartLoader(LOADER_APP_PREF, Bundle.EMPTY,
-                        mAppPrefCallbacks);
-            } else {
-                removePreference(KEY_APP_LIST);
-            }
-        } else {
-            final Context context = getActivity();
-            UidDetail uidDetail = new UidDetailProvider(context).getUidDetail(mAppItem.key, true);
-            mIcon = uidDetail.icon;
-            mLabel = uidDetail.label;
-            mPackageName = context.getPackageName();
-
-            removePreference(KEY_UNRESTRICTED_DATA);
-            removePreference(KEY_APP_SETTINGS);
-            removePreference(KEY_RESTRICT_BACKGROUND);
-            removePreference(KEY_APP_LIST);
-        }
-    }
-
-    @Override
-    public void onResume() {
-        super.onResume();
-        if (mDataSaverBackend != null) {
-            mDataSaverBackend.addListener(this);
-        }
-        LoaderManager.getInstance(this).restartLoader(LOADER_APP_USAGE_DATA, null /* args */,
-                mUidDataCallbacks);
-        updatePrefs();
-    }
-
-    @Override
-    public void onPause() {
-        super.onPause();
-        if (mDataSaverBackend != null) {
-            mDataSaverBackend.remListener(this);
-        }
-    }
-
-    @Override
-    public boolean onPreferenceChange(Preference preference, Object newValue) {
-        if (preference == mRestrictBackground) {
-            mDataSaverBackend.setIsBlacklisted(mAppItem.key, mPackageName, !(Boolean) newValue);
-            updatePrefs();
-            return true;
-        } else if (preference == mUnrestrictedData) {
-            mDataSaverBackend.setIsWhitelisted(mAppItem.key, mPackageName, (Boolean) newValue);
-            return true;
-        }
-        return false;
-    }
-
-    @Override
-    public boolean onPreferenceTreeClick(Preference preference) {
-        if (preference == mAppSettings) {
-            // TODO: target towards entire UID instead of just first package
-            getActivity().startActivityAsUser(mAppSettingsIntent, new UserHandle(
-                    UserHandle.getUserId(mAppItem.key)));
-            return true;
-        }
-        return super.onPreferenceTreeClick(preference);
-    }
-
-    @Override
-    protected int getPreferenceScreenResId() {
-        return R.xml.app_data_usage;
-    }
-
-    @Override
-    protected String getLogTag() {
-        return TAG;
-    }
-
-    @VisibleForTesting
-    void updatePrefs() {
-        updatePrefs(getAppRestrictBackground(), getUnrestrictData());
-    }
-
-    private void updatePrefs(boolean restrictBackground, boolean unrestrictData) {
-        final EnforcedAdmin admin = RestrictedLockUtilsInternal.checkIfMeteredDataRestricted(
-                getContext(), mPackageName, UserHandle.getUserId(mAppItem.key));
-        if (mRestrictBackground != null) {
-            mRestrictBackground.setChecked(!restrictBackground);
-            mRestrictBackground.setDisabledByAdmin(admin);
-        }
-        if (mUnrestrictedData != null) {
-            if (restrictBackground) {
-                mUnrestrictedData.setVisible(false);
-            } else {
-                mUnrestrictedData.setVisible(true);
-                mUnrestrictedData.setChecked(unrestrictData);
-                mUnrestrictedData.setDisabledByAdmin(admin);
-            }
-        }
-    }
-
-    private void addUid(int uid) {
-        String[] packages = getPackageManager().getPackagesForUid(uid);
-        if (packages != null) {
-            for (int i = 0; i < packages.length; i++) {
-                mPackages.add(packages[i]);
-            }
-        }
-    }
-
-    @VisibleForTesting
-    void bindData(int position) {
-        final long backgroundBytes, foregroundBytes;
-        if (mUsageData == null || position >= mUsageData.size()) {
-            backgroundBytes = foregroundBytes = 0;
-            mCycle.setVisible(false);
-        } else {
-            mCycle.setVisible(true);
-            final NetworkCycleDataForUid data = mUsageData.get(position);
-            backgroundBytes = data.getBackgroudUsage();
-            foregroundBytes = data.getForegroudUsage();
-        }
-        final long totalBytes = backgroundBytes + foregroundBytes;
-        final Context context = getContext();
-
-        mTotalUsage.setSummary(DataUsageUtils.formatDataUsage(context, totalBytes));
-        mForegroundUsage.setSummary(DataUsageUtils.formatDataUsage(context, foregroundBytes));
-        mBackgroundUsage.setSummary(DataUsageUtils.formatDataUsage(context, backgroundBytes));
-    }
-
-    private boolean getAppRestrictBackground() {
-        final int uid = mAppItem.key;
-        final int uidPolicy = services.mPolicyManager.getUidPolicy(uid);
-        return (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0;
-    }
-
-    private boolean getUnrestrictData() {
-        if (mDataSaverBackend != null) {
-            return mDataSaverBackend.isWhitelisted(mAppItem.key);
-        }
-        return false;
-    }
-
-    @Override
-    public void onViewCreated(View view, Bundle savedInstanceState) {
-        super.onViewCreated(view, savedInstanceState);
-
-        String pkg = mPackages.size() != 0 ? mPackages.valueAt(0) : null;
-        int uid = 0;
-        if (pkg != null) {
-            try {
-                uid = mPackageManager.getPackageUidAsUser(pkg,
-                        UserHandle.getUserId(mAppItem.key));
-            } catch (PackageManager.NameNotFoundException e) {
-                Log.w(TAG, "Skipping UID because cannot find package " + pkg);
-            }
-        }
-
-        final boolean showInfoButton = mAppItem.key > 0;
-
-        final Activity activity = getActivity();
-        final Preference pref = EntityHeaderController
-                .newInstance(activity, this, null /* header */)
-                .setRecyclerView(getListView(), getSettingsLifecycle())
-                .setUid(uid)
-                .setHasAppInfoLink(showInfoButton)
-                .setButtonActions(EntityHeaderController.ActionType.ACTION_NONE,
-                        EntityHeaderController.ActionType.ACTION_NONE)
-                .setIcon(mIcon)
-                .setLabel(mLabel)
-                .setPackageName(pkg)
-                .done(activity, getPrefContext());
-        getPreferenceScreen().addPreference(pref);
-    }
-
-    @Override
-    public int getMetricsCategory() {
-        return MetricsEvent.APP_DATA_USAGE;
-    }
-
-    private AdapterView.OnItemSelectedListener mCycleListener =
-            new AdapterView.OnItemSelectedListener() {
-        @Override
-        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
-            bindData(position);
-        }
-
-        @Override
-        public void onNothingSelected(AdapterView<?> parent) {
-            // ignored
-        }
-    };
-
-    private final LoaderManager.LoaderCallbacks<List<NetworkCycleDataForUid>> mUidDataCallbacks =
-        new LoaderManager.LoaderCallbacks<List<NetworkCycleDataForUid>>() {
-            @Override
-            public Loader<List<NetworkCycleDataForUid>> onCreateLoader(int id, Bundle args) {
-                return NetworkCycleDataForUidLoader.builder(getContext())
-                    .setUid(mAppItem.key)
-                    .setRetrieveDetail(true)
-                    .setNetworkTemplate(mTemplate)
-                    .setSubscriberId(mTemplate.getSubscriberId())
-                    .build();
-            }
-
-            @Override
-            public void onLoadFinished(Loader<List<NetworkCycleDataForUid>> loader,
-                    List<NetworkCycleDataForUid> data) {
-                mUsageData = data;
-                mCycleAdapter.updateCycleList(data);
-                bindData(0 /* position */);
-            }
-
-            @Override
-            public void onLoaderReset(Loader<List<NetworkCycleDataForUid>> loader) {
-            }
-        };
-
-    private final LoaderManager.LoaderCallbacks<ArraySet<Preference>> mAppPrefCallbacks =
-        new LoaderManager.LoaderCallbacks<ArraySet<Preference>>() {
-            @Override
-            public Loader<ArraySet<Preference>> onCreateLoader(int i, Bundle bundle) {
-                return new AppPrefLoader(getPrefContext(), mPackages, getPackageManager());
-            }
-
-            @Override
-            public void onLoadFinished(Loader<ArraySet<Preference>> loader,
-                    ArraySet<Preference> preferences) {
-                if (preferences != null && mAppList != null) {
-                    for (Preference preference : preferences) {
-                        mAppList.addPreference(preference);
-                    }
-                }
-            }
-
-            @Override
-            public void onLoaderReset(Loader<ArraySet<Preference>> loader) {
-            }
-        };
-
-    @Override
-    public void onDataSaverChanged(boolean isDataSaving) {
-
-    }
-
-    @Override
-    public void onWhitelistStatusChanged(int uid, boolean isWhitelisted) {
-        if (mAppItem.uids.get(uid, false)) {
-            updatePrefs(getAppRestrictBackground(), isWhitelisted);
-        }
-    }
-
-    @Override
-    public void onBlacklistStatusChanged(int uid, boolean isBlacklisted) {
-        if (mAppItem.uids.get(uid, false)) {
-            updatePrefs(isBlacklisted, getUnrestrictData());
-        }
-    }
-}
diff --git a/src/com/android/settings/datausage/ChartDataUsagePreference.java b/src/com/android/settings/datausage/ChartDataUsagePreference.java
index a0cef3a..1c8eb52 100644
--- a/src/com/android/settings/datausage/ChartDataUsagePreference.java
+++ b/src/com/android/settings/datausage/ChartDataUsagePreference.java
@@ -16,14 +16,12 @@
 
 import android.content.Context;
 import android.net.NetworkPolicy;
-import android.net.NetworkStatsHistory;
 import android.net.TrafficStats;
 import android.text.SpannableStringBuilder;
 import android.text.TextUtils;
 import android.text.format.Formatter;
 import android.text.style.ForegroundColorSpan;
 import android.util.AttributeSet;
-import android.util.FeatureFlagUtils;
 import android.util.SparseIntArray;
 
 import androidx.annotation.VisibleForTesting;
@@ -32,7 +30,6 @@
 
 import com.android.settings.R;
 import com.android.settings.Utils;
-import com.android.settings.core.FeatureFlags;
 import com.android.settings.widget.UsageView;
 import com.android.settingslib.net.NetworkCycleChartData;
 import com.android.settingslib.net.NetworkCycleData;
@@ -51,8 +48,6 @@
     private NetworkPolicy mPolicy;
     private long mStart;
     private long mEnd;
-    @Deprecated
-    private NetworkStatsHistory mNetwork;
     private NetworkCycleChartData mNetworkCycleChartData;
     private int mSecondaryColor;
     private int mSeriesColor;
@@ -69,24 +64,14 @@
     public void onBindViewHolder(PreferenceViewHolder holder) {
         super.onBindViewHolder(holder);
         final UsageView chart = (UsageView) holder.findViewById(R.id.data_usage);
-        if (FeatureFlagUtils.isEnabled(getContext(), FeatureFlags.DATA_USAGE_V2)) {
-            if (mNetworkCycleChartData == null) {
-                return;
-            }
-        } else {
-            if (mNetwork == null) {
-                return;
-            }
+        if (mNetworkCycleChartData == null) {
+            return;
         }
 
         final int top = getTop();
         chart.clearPaths();
         chart.configureGraph(toInt(mEnd - mStart), top);
-        if (FeatureFlagUtils.isEnabled(getContext(), FeatureFlags.DATA_USAGE_V2)) {
-            calcPoints(chart, mNetworkCycleChartData.getUsageBuckets());
-        } else {
-            calcPoints(chart);
-        }
+        calcPoints(chart, mNetworkCycleChartData.getUsageBuckets());
         chart.setBottomLabels(new CharSequence[] {
                 Utils.formatDateRange(getContext(), mStart, mStart),
                 Utils.formatDateRange(getContext(), mEnd, mEnd),
@@ -96,58 +81,12 @@
     }
 
     public int getTop() {
-        long totalData = 0;
-        if (FeatureFlagUtils.isEnabled(getContext(), FeatureFlags.DATA_USAGE_V2)) {
-            totalData = mNetworkCycleChartData.getTotalUsage();
-        } else {
-            NetworkStatsHistory.Entry entry = null;
-            final int start = mNetwork.getIndexBefore(mStart);
-            final int end = mNetwork.getIndexAfter(mEnd);
-
-            for (int i = start; i <= end; i++) {
-                entry = mNetwork.getValues(i, entry);
-
-                // increment by current bucket total
-                totalData += entry.rxBytes + entry.txBytes;
-            }
-        }
-        long policyMax = mPolicy != null ? Math.max(mPolicy.limitBytes, mPolicy.warningBytes) : 0;
+        final long totalData = mNetworkCycleChartData.getTotalUsage();
+        final long policyMax =
+            mPolicy != null ? Math.max(mPolicy.limitBytes, mPolicy.warningBytes) : 0;
         return (int) (Math.max(totalData, policyMax) / RESOLUTION);
     }
 
-    @Deprecated
-    @VisibleForTesting
-    void calcPoints(UsageView chart) {
-        SparseIntArray points = new SparseIntArray();
-        NetworkStatsHistory.Entry entry = null;
-
-        long totalData = 0;
-
-        final int start = mNetwork.getIndexAfter(mStart);
-        final int end = mNetwork.getIndexAfter(mEnd);
-        if (start < 0) return;
-
-        points.put(0, 0);
-        for (int i = start; i <= end; i++) {
-            entry = mNetwork.getValues(i, entry);
-
-            final long startTime = entry.bucketStart;
-            final long endTime = startTime + entry.bucketDuration;
-
-            // increment by current bucket total
-            totalData += entry.rxBytes + entry.txBytes;
-
-            if (i == 0) {
-                points.put(toInt(startTime - mStart) - 1, -1);
-            }
-            points.put(toInt(startTime - mStart + 1), (int) (totalData / RESOLUTION));
-            points.put(toInt(endTime - mStart), (int) (totalData / RESOLUTION));
-        }
-        if (points.size() > 1) {
-            chart.addPath(points);
-        }
-    }
-
     @VisibleForTesting
     void calcPoints(UsageView chart, List<NetworkCycleData> usageSummary) {
         if (usageSummary == null) {
@@ -220,13 +159,6 @@
         notifyChanged();
     }
 
-    @Deprecated
-    public void setVisibleRange(long start, long end) {
-        mStart = start;
-        mEnd = end;
-        notifyChanged();
-    }
-
     public long getInspectStart() {
         return mStart;
     }
@@ -235,12 +167,6 @@
         return mEnd;
     }
 
-    @Deprecated
-    public void setNetworkStats(NetworkStatsHistory network) {
-        mNetwork = network;
-        notifyChanged();
-    }
-
     public void setNetworkCycleData(NetworkCycleChartData data) {
         mNetworkCycleChartData = data;
         mStart = data.getStartTime();
diff --git a/src/com/android/settings/datausage/DataUsageList.java b/src/com/android/settings/datausage/DataUsageList.java
index 8f0026f..326b0d4 100644
--- a/src/com/android/settings/datausage/DataUsageList.java
+++ b/src/com/android/settings/datausage/DataUsageList.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * 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
@@ -15,20 +15,22 @@
 package com.android.settings.datausage;
 
 import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
+import static android.net.NetworkStatsHistory.FIELD_RX_BYTES;
+import static android.net.NetworkStatsHistory.FIELD_TX_BYTES;
 import static android.net.TrafficStats.UID_REMOVED;
 import static android.net.TrafficStats.UID_TETHERING;
 
+import android.app.Activity;
 import android.app.ActivityManager;
+import android.app.usage.NetworkStats;
+import android.app.usage.NetworkStats.Bucket;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.UserInfo;
 import android.graphics.Color;
-import android.net.INetworkStatsSession;
+import android.net.ConnectivityManager;
 import android.net.NetworkPolicy;
-import android.net.NetworkStats;
-import android.net.NetworkStatsHistory;
 import android.net.NetworkTemplate;
-import android.net.TrafficStats;
 import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.RemoteException;
@@ -37,6 +39,7 @@
 import android.provider.Settings;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
 import android.text.format.DateUtils;
 import android.util.Log;
 import android.util.SparseArray;
@@ -58,9 +61,9 @@
 import com.android.settings.datausage.CycleAdapter.SpinnerInterface;
 import com.android.settings.widget.LoadingViewController;
 import com.android.settingslib.AppItem;
-import com.android.settingslib.net.ChartData;
-import com.android.settingslib.net.ChartDataLoaderCompat;
-import com.android.settingslib.net.SummaryForAllUidLoaderCompat;
+import com.android.settingslib.net.NetworkCycleChartDataLoader;
+import com.android.settingslib.net.NetworkCycleChartData;
+import com.android.settingslib.net.NetworkStatsSummaryLoader;
 import com.android.settingslib.net.UidDetailProvider;
 
 import java.util.ArrayList;
@@ -70,16 +73,12 @@
 /**
  * Panel showing data usage history across various networks, including options
  * to inspect based on usage cycle and control through {@link NetworkPolicy}.
-
- * Deprecated in favor of {@link DataUsageListV2}
- *
- * @deprecated
  */
-@Deprecated
 public class DataUsageList extends DataUsageBaseFragment {
 
-    public static final String EXTRA_SUB_ID = "sub_id";
-    public static final String EXTRA_NETWORK_TEMPLATE = "network_template";
+    static final String EXTRA_SUB_ID = "sub_id";
+    static final String EXTRA_NETWORK_TEMPLATE = "network_template";
+    static final String EXTRA_NETWORK_TYPE = "network_type";
 
     private static final String TAG = "DataUsageList";
     private static final boolean LOGD = false;
@@ -87,6 +86,9 @@
     private static final String KEY_USAGE_AMOUNT = "usage_amount";
     private static final String KEY_CHART_DATA = "chart_data";
     private static final String KEY_APPS_GROUP = "apps_group";
+    private static final String KEY_TEMPLATE = "template";
+    private static final String KEY_APP = "app";
+    private static final String KEY_FIELDS = "fields";
 
     private static final int LOADER_CHART_DATA = 2;
     private static final int LOADER_SUMMARY = 3;
@@ -99,14 +101,16 @@
                 }
             };
 
-    private INetworkStatsSession mStatsSession;
     private ChartDataUsagePreference mChart;
+    private TelephonyManager mTelephonyManager;
 
     @VisibleForTesting
     NetworkTemplate mTemplate;
     @VisibleForTesting
     int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
-    private ChartData mChartData;
+    @VisibleForTesting
+    int mNetworkType;
+    private List<NetworkCycleChartData> mCycleData;
 
     private LoadingViewController mLoadingViewController;
     private UidDetailProvider mUidDetailProvider;
@@ -116,7 +120,6 @@
     private PreferenceGroup mApps;
     private View mHeader;
 
-
     @Override
     public int getMetricsCategory() {
         return MetricsEvent.DATA_USAGE_LIST;
@@ -125,21 +128,15 @@
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        final Context context = getActivity();
+        final Activity activity = getActivity();
 
         if (!isBandwidthControlEnabled()) {
             Log.w(TAG, "No bandwidth control; leaving");
-            getActivity().finish();
+            activity.finish();
         }
 
-        try {
-            mStatsSession = services.mStatsService.openSession();
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-
-        mUidDetailProvider = new UidDetailProvider(context);
-
+        mUidDetailProvider = new UidDetailProvider(activity);
+        mTelephonyManager = activity.getSystemService(TelephonyManager.class);
         mUsageAmount = findPreference(KEY_USAGE_AMOUNT);
         mChart = (ChartDataUsagePreference) findPreference(KEY_CHART_DATA);
         mApps = (PreferenceGroup) findPreference(KEY_APPS_GROUP);
@@ -194,28 +191,6 @@
         super.onResume();
         mDataStateListener.setListener(true, mSubId, getContext());
         updateBody();
-
-        // kick off background task to update stats
-        new AsyncTask<Void, Void, Void>() {
-            @Override
-            protected Void doInBackground(Void... params) {
-                try {
-                    // wait a few seconds before kicking off
-                    Thread.sleep(2 * DateUtils.SECOND_IN_MILLIS);
-                    services.mStatsService.forceUpdate();
-                } catch (InterruptedException e) {
-                } catch (RemoteException e) {
-                }
-                return null;
-            }
-
-            @Override
-            protected void onPostExecute(Void result) {
-                if (isAdded()) {
-                    updateBody();
-                }
-            }
-        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
     }
 
     @Override
@@ -229,8 +204,6 @@
         mUidDetailProvider.clearCache();
         mUidDetailProvider = null;
 
-        TrafficStats.closeQuietly(mStatsSession);
-
         super.onDestroy();
     }
 
@@ -249,6 +222,7 @@
         if (args != null) {
             mSubId = args.getInt(EXTRA_SUB_ID, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
             mTemplate = args.getParcelable(EXTRA_NETWORK_TEMPLATE);
+            mNetworkType = args.getInt(EXTRA_NETWORK_TYPE, ConnectivityManager.TYPE_MOBILE);
         }
         if (mTemplate == null && mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
             final Intent intent = getIntent();
@@ -259,8 +233,7 @@
     }
 
     /**
-     * Update body content based on current tab. Loads
-     * {@link NetworkStatsHistory} and {@link NetworkPolicy} from system, and
+     * Update body content based on current tab. Loads network cycle data from system, and
      * binds them to visible controls.
      */
     private void updateBody() {
@@ -272,7 +245,7 @@
         // TODO: consider chaining two loaders together instead of reloading
         // network history when showing app detail.
         getLoaderManager().restartLoader(LOADER_CHART_DATA,
-                ChartDataLoaderCompat.buildArgs(mTemplate, null), mChartDataCallbacks);
+                buildArgs(mTemplate), mNetworkCycleDataCallbacks);
 
         // detail mode can change visible menus, invalidate
         getActivity().invalidateOptionsMenu();
@@ -292,6 +265,14 @@
         mChart.setColors(seriesColor, secondaryColor);
     }
 
+    private Bundle buildArgs(NetworkTemplate template) {
+        final Bundle args = new Bundle();
+        args.putParcelable(KEY_TEMPLATE, template);
+        args.putParcelable(KEY_APP, null);
+        args.putInt(KEY_FIELDS, FIELD_RX_BYTES | FIELD_TX_BYTES);
+        return args;
+    }
+
     /**
      * Update chart sweeps and cycle list to reflect {@link NetworkPolicy} for
      * current {@link #mTemplate}.
@@ -311,7 +292,7 @@
         }
 
         // generate cycle list based on policy and available history
-        if (mCycleAdapter.updateCycleList(policy, mChartData)) {
+        if (mCycleAdapter.updateCycleList(mCycleData)) {
             updateDetailData();
         }
     }
@@ -324,23 +305,13 @@
     private void updateDetailData() {
         if (LOGD) Log.d(TAG, "updateDetailData()");
 
-        final long start = mChart.getInspectStart();
-        final long end = mChart.getInspectEnd();
-        final long now = System.currentTimeMillis();
-
-        final Context context = getActivity();
-
-        NetworkStatsHistory.Entry entry = null;
-        if (mChartData != null) {
-            entry = mChartData.network.getValues(start, end, now, null);
-        }
-
         // kick off loader for detailed stats
-        getLoaderManager().restartLoader(LOADER_SUMMARY,
-                SummaryForAllUidLoaderCompat.buildArgs(mTemplate, start, end), mSummaryCallbacks);
+        getLoaderManager().restartLoader(LOADER_SUMMARY, null /* args */,
+                mNetworkStatsDetailCallbacks);
 
-        final long totalBytes = entry != null ? entry.rxBytes + entry.txBytes : 0;
-        final CharSequence totalPhrase = DataUsageUtils.formatDataUsage(context, totalBytes);
+        final long totalBytes = mCycleData != null
+            ? mCycleData.get(mCycleSpinner.getSelectedItemPosition()).getTotalUsage() : 0;
+        final CharSequence totalPhrase = DataUsageUtils.formatDataUsage(getActivity(), totalBytes);
         mUsageAmount.setTitle(getString(R.string.data_used_template, totalPhrase));
     }
 
@@ -348,22 +319,26 @@
      * Bind the given {@link NetworkStats}, or {@code null} to clear list.
      */
     private void bindStats(NetworkStats stats, int[] restrictedUids) {
-        ArrayList<AppItem> items = new ArrayList<>();
+        mApps.removeAll();
+        if (stats == null) {
+            if (LOGD) {
+                Log.d(TAG, "No network stats data. App list cleared.");
+            }
+            return;
+        }
+
+        final ArrayList<AppItem> items = new ArrayList<>();
         long largest = 0;
 
         final int currentUserId = ActivityManager.getCurrentUser();
-        UserManager userManager = UserManager.get(getContext());
+        final UserManager userManager = UserManager.get(getContext());
         final List<UserHandle> profiles = userManager.getUserProfiles();
         final SparseArray<AppItem> knownItems = new SparseArray<AppItem>();
 
-        NetworkStats.Entry entry = null;
-        final int size = stats != null ? stats.size() : 0;
-        for (int i = 0; i < size; i++) {
-            entry = stats.getValues(i, entry);
-
+        final Bucket bucket = new Bucket();
+        while (stats.hasNextBucket() && stats.getNextBucket(bucket)) {
             // Decide how to collapse items together
-            final int uid = entry.uid;
-
+            final int uid = bucket.getUid();
             final int collapseKey;
             final int category;
             final int userId = UserHandle.getUserId(uid);
@@ -372,8 +347,8 @@
                     if (userId != currentUserId) {
                         // Add to a managed user item.
                         final int managedKey = UidDetailProvider.buildKeyForUser(userId);
-                        largest = accumulate(managedKey, knownItems, entry, AppItem.CATEGORY_USER,
-                                items, largest);
+                        largest = accumulate(managedKey, knownItems, bucket,
+                            AppItem.CATEGORY_USER, items, largest);
                     }
                     // Add to app item.
                     collapseKey = uid;
@@ -397,8 +372,9 @@
                 collapseKey = android.os.Process.SYSTEM_UID;
                 category = AppItem.CATEGORY_APP;
             }
-            largest = accumulate(collapseKey, knownItems, entry, category, items, largest);
+            largest = accumulate(collapseKey, knownItems, bucket, category, items, largest);
         }
+        stats.close();
 
         final int restrictedUidsMax = restrictedUids.length;
         for (int i = 0; i < restrictedUidsMax; ++i) {
@@ -419,7 +395,6 @@
         }
 
         Collections.sort(items);
-        mApps.removeAll();
         for (int i = 0; i < items.size(); i++) {
             final int percentTotal = largest != 0 ? (int) (items.get(i).total * 100 / largest) : 0;
             AppDataUsagePreference preference = new AppDataUsagePreference(getContext(),
@@ -456,12 +431,12 @@
      *
      * @param collapseKey  the collapse key used to map the item.
      * @param knownItems   collection of known (already existing) items.
-     * @param entry        the network stats entry to extract data usage from.
+     * @param bucket       the network stats bucket to extract data usage from.
      * @param itemCategory the item is categorized on the list view by this category. Must be
      */
-    private long accumulate(int collapseKey, final SparseArray<AppItem> knownItems,
-            NetworkStats.Entry entry, int itemCategory, ArrayList<AppItem> items, long largest) {
-        final int uid = entry.uid;
+    private static long accumulate(int collapseKey, final SparseArray<AppItem> knownItems,
+            Bucket bucket, int itemCategory, ArrayList<AppItem> items, long largest) {
+        final int uid = bucket.getUid();
         AppItem item = knownItems.get(collapseKey);
         if (item == null) {
             item = new AppItem(collapseKey);
@@ -470,7 +445,7 @@
             knownItems.put(item.key, item);
         }
         item.addUid(uid);
-        item.total += entry.rxBytes + entry.txBytes;
+        item.total += bucket.getRxBytes() + bucket.getTxBytes();
         return Math.max(largest, item.total);
     }
 
@@ -487,7 +462,7 @@
 
             // update chart to show selected cycle, and update detail data
             // to match updated sweep bounds.
-            mChart.setVisibleRange(cycle.start, cycle.end);
+            mChart.setNetworkCycleData(mCycleData.get(position));
 
             updateDetailData();
         }
@@ -498,35 +473,41 @@
         }
     };
 
-    private final LoaderCallbacks<ChartData> mChartDataCallbacks = new LoaderCallbacks<
-            ChartData>() {
+    private final LoaderCallbacks<List<NetworkCycleChartData>> mNetworkCycleDataCallbacks =
+            new LoaderCallbacks<List<NetworkCycleChartData>>() {
         @Override
-        public Loader<ChartData> onCreateLoader(int id, Bundle args) {
-            return new ChartDataLoaderCompat(getActivity(), mStatsSession, args);
+        public Loader<List<NetworkCycleChartData>> onCreateLoader(int id, Bundle args) {
+            return NetworkCycleChartDataLoader.builder(getContext())
+                    .setNetworkTemplate(mTemplate)
+                    .setSubscriberId(mTelephonyManager.getSubscriberId(mSubId))
+                    .build();
         }
 
         @Override
-        public void onLoadFinished(Loader<ChartData> loader, ChartData data) {
+        public void onLoadFinished(Loader<List<NetworkCycleChartData>> loader,
+                List<NetworkCycleChartData> data) {
             mLoadingViewController.showContent(false /* animate */);
-            mChartData = data;
-            mChart.setNetworkStats(mChartData.network);
-
+            mCycleData = data;
             // calculate policy cycles based on available data
             updatePolicy();
         }
 
         @Override
-        public void onLoaderReset(Loader<ChartData> loader) {
-            mChartData = null;
-            mChart.setNetworkStats(null);
+        public void onLoaderReset(Loader<List<NetworkCycleChartData>> loader) {
+            mCycleData = null;
         }
     };
 
-    private final LoaderCallbacks<NetworkStats> mSummaryCallbacks = new LoaderCallbacks<
-            NetworkStats>() {
+    private final LoaderCallbacks<NetworkStats> mNetworkStatsDetailCallbacks =
+            new LoaderCallbacks<NetworkStats>() {
         @Override
         public Loader<NetworkStats> onCreateLoader(int id, Bundle args) {
-            return new SummaryForAllUidLoaderCompat(getActivity(), mStatsSession, args);
+            return new NetworkStatsSummaryLoader.Builder(getContext())
+                    .setStartTime(mChart.getInspectStart())
+                    .setEndTime(mChart.getInspectEnd())
+                    .setNetworkType(mNetworkType)
+                    .setSubscriberId(mTelephonyManager.getSubscriberId(mSubId))
+                    .build();
         }
 
         @Override
diff --git a/src/com/android/settings/datausage/DataUsageListV2.java b/src/com/android/settings/datausage/DataUsageListV2.java
deleted file mode 100644
index 4432fee..0000000
--- a/src/com/android/settings/datausage/DataUsageListV2.java
+++ /dev/null
@@ -1,549 +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.datausage;
-
-import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
-import static android.net.TrafficStats.UID_REMOVED;
-import static android.net.TrafficStats.UID_TETHERING;
-
-import android.app.Activity;
-import android.app.ActivityManager;
-import android.app.usage.NetworkStats;
-import android.app.usage.NetworkStats.Bucket;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.UserInfo;
-import android.graphics.Color;
-import android.net.ConnectivityManager;
-import android.net.NetworkPolicy;
-import android.net.NetworkTemplate;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.provider.Settings;
-import android.telephony.SubscriptionInfo;
-import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyManager;
-import android.text.format.DateUtils;
-import android.util.Log;
-import android.util.SparseArray;
-import android.view.View;
-import android.widget.AdapterView;
-import android.widget.AdapterView.OnItemSelectedListener;
-import android.widget.ImageView;
-import android.widget.Spinner;
-
-import androidx.annotation.VisibleForTesting;
-import androidx.loader.app.LoaderManager.LoaderCallbacks;
-import androidx.loader.content.Loader;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceGroup;
-
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.settings.R;
-import com.android.settings.core.SubSettingLauncher;
-import com.android.settings.datausage.CycleAdapter.SpinnerInterface;
-import com.android.settings.widget.LoadingViewController;
-import com.android.settingslib.AppItem;
-import com.android.settingslib.net.ChartDataLoaderCompat;
-import com.android.settingslib.net.NetworkCycleChartDataLoader;
-import com.android.settingslib.net.NetworkCycleChartData;
-import com.android.settingslib.net.NetworkStatsSummaryLoader;
-import com.android.settingslib.net.UidDetailProvider;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Panel showing data usage history across various networks, including options
- * to inspect based on usage cycle and control through {@link NetworkPolicy}.
- */
-public class DataUsageListV2 extends DataUsageBaseFragment {
-
-    static final String EXTRA_SUB_ID = "sub_id";
-    static final String EXTRA_NETWORK_TEMPLATE = "network_template";
-    static final String EXTRA_NETWORK_TYPE = "network_type";
-
-    private static final String TAG = "DataUsageListV2";
-    private static final boolean LOGD = false;
-
-    private static final String KEY_USAGE_AMOUNT = "usage_amount";
-    private static final String KEY_CHART_DATA = "chart_data";
-    private static final String KEY_APPS_GROUP = "apps_group";
-
-    private static final int LOADER_CHART_DATA = 2;
-    private static final int LOADER_SUMMARY = 3;
-
-    private final CellDataPreference.DataStateListener mDataStateListener =
-            new CellDataPreference.DataStateListener() {
-                @Override
-                public void onChange(boolean selfChange) {
-                    updatePolicy();
-                }
-            };
-
-    private ChartDataUsagePreference mChart;
-    private TelephonyManager mTelephonyManager;
-
-    @VisibleForTesting
-    NetworkTemplate mTemplate;
-    @VisibleForTesting
-    int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
-    @VisibleForTesting
-    int mNetworkType;
-    private List<NetworkCycleChartData> mCycleData;
-
-    private LoadingViewController mLoadingViewController;
-    private UidDetailProvider mUidDetailProvider;
-    private CycleAdapter mCycleAdapter;
-    private Spinner mCycleSpinner;
-    private Preference mUsageAmount;
-    private PreferenceGroup mApps;
-    private View mHeader;
-
-    @Override
-    public int getMetricsCategory() {
-        return MetricsEvent.DATA_USAGE_LIST;
-    }
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        final Activity activity = getActivity();
-
-        if (!isBandwidthControlEnabled()) {
-            Log.w(TAG, "No bandwidth control; leaving");
-            activity.finish();
-        }
-
-        mUidDetailProvider = new UidDetailProvider(activity);
-        mTelephonyManager = activity.getSystemService(TelephonyManager.class);
-        mUsageAmount = findPreference(KEY_USAGE_AMOUNT);
-        mChart = (ChartDataUsagePreference) findPreference(KEY_CHART_DATA);
-        mApps = (PreferenceGroup) findPreference(KEY_APPS_GROUP);
-        processArgument();
-    }
-
-    @Override
-    public void onViewCreated(View v, Bundle savedInstanceState) {
-        super.onViewCreated(v, savedInstanceState);
-
-        mHeader = setPinnedHeaderView(R.layout.apps_filter_spinner);
-        mHeader.findViewById(R.id.filter_settings).setOnClickListener(btn -> {
-            final Bundle args = new Bundle();
-            args.putParcelable(DataUsageListV2.EXTRA_NETWORK_TEMPLATE, mTemplate);
-            new SubSettingLauncher(getContext())
-                    .setDestination(BillingCycleSettings.class.getName())
-                    .setTitleRes(R.string.billing_cycle)
-                    .setSourceMetricsCategory(getMetricsCategory())
-                    .setArguments(args)
-                    .launch();
-        });
-        mCycleSpinner = mHeader.findViewById(R.id.filter_spinner);
-        mCycleAdapter = new CycleAdapter(mCycleSpinner.getContext(), new SpinnerInterface() {
-            @Override
-            public void setAdapter(CycleAdapter cycleAdapter) {
-                mCycleSpinner.setAdapter(cycleAdapter);
-            }
-
-            @Override
-            public void setOnItemSelectedListener(OnItemSelectedListener listener) {
-                mCycleSpinner.setOnItemSelectedListener(listener);
-            }
-
-            @Override
-            public Object getSelectedItem() {
-                return mCycleSpinner.getSelectedItem();
-            }
-
-            @Override
-            public void setSelection(int position) {
-                mCycleSpinner.setSelection(position);
-            }
-        }, mCycleListener);
-
-        mLoadingViewController = new LoadingViewController(
-                getView().findViewById(R.id.loading_container), getListView());
-        mLoadingViewController.showLoadingViewDelayed();
-    }
-
-    @Override
-    public void onResume() {
-        super.onResume();
-        mDataStateListener.setListener(true, mSubId, getContext());
-        updateBody();
-
-        // kick off background task to update stats
-        new AsyncTask<Void, Void, Void>() {
-            @Override
-            protected Void doInBackground(Void... params) {
-                try {
-                    // wait a few seconds before kicking off
-                    Thread.sleep(2 * DateUtils.SECOND_IN_MILLIS);
-                    services.mStatsService.forceUpdate();
-                } catch (InterruptedException e) {
-                } catch (RemoteException e) {
-                }
-                return null;
-            }
-
-            @Override
-            protected void onPostExecute(Void result) {
-                if (isAdded()) {
-                    updateBody();
-                }
-            }
-        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
-    }
-
-    @Override
-    public void onPause() {
-        super.onPause();
-        mDataStateListener.setListener(false, mSubId, getContext());
-    }
-
-    @Override
-    public void onDestroy() {
-        mUidDetailProvider.clearCache();
-        mUidDetailProvider = null;
-
-        super.onDestroy();
-    }
-
-    @Override
-    protected int getPreferenceScreenResId() {
-        return R.xml.data_usage_list;
-    }
-
-    @Override
-    protected String getLogTag() {
-        return TAG;
-    }
-
-    void processArgument() {
-        final Bundle args = getArguments();
-        if (args != null) {
-            mSubId = args.getInt(EXTRA_SUB_ID, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
-            mTemplate = args.getParcelable(EXTRA_NETWORK_TEMPLATE);
-            mNetworkType = args.getInt(EXTRA_NETWORK_TYPE, ConnectivityManager.TYPE_MOBILE);
-        }
-        if (mTemplate == null && mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
-            final Intent intent = getIntent();
-            mSubId = intent.getIntExtra(Settings.EXTRA_SUB_ID,
-                    SubscriptionManager.INVALID_SUBSCRIPTION_ID);
-            mTemplate = intent.getParcelableExtra(Settings.EXTRA_NETWORK_TEMPLATE);
-        }
-    }
-
-    /**
-     * Update body content based on current tab. Loads network cycle data from system, and
-     * binds them to visible controls.
-     */
-    private void updateBody() {
-        if (!isAdded()) return;
-
-        final Context context = getActivity();
-
-        // kick off loader for network history
-        // TODO: consider chaining two loaders together instead of reloading
-        // network history when showing app detail.
-        getLoaderManager().restartLoader(LOADER_CHART_DATA,
-                ChartDataLoaderCompat.buildArgs(mTemplate, null), mNetworkCycleDataCallbacks);
-
-        // detail mode can change visible menus, invalidate
-        getActivity().invalidateOptionsMenu();
-
-        int seriesColor = context.getColor(R.color.sim_noitification);
-        if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
-            final SubscriptionInfo sir = services.mSubscriptionManager
-                    .getActiveSubscriptionInfo(mSubId);
-
-            if (sir != null) {
-                seriesColor = sir.getIconTint();
-            }
-        }
-
-        final int secondaryColor = Color.argb(127, Color.red(seriesColor), Color.green(seriesColor),
-                Color.blue(seriesColor));
-        mChart.setColors(seriesColor, secondaryColor);
-    }
-
-    /**
-     * Update chart sweeps and cycle list to reflect {@link NetworkPolicy} for
-     * current {@link #mTemplate}.
-     */
-    private void updatePolicy() {
-        final NetworkPolicy policy = services.mPolicyEditor.getPolicy(mTemplate);
-        final View configureButton = mHeader.findViewById(R.id.filter_settings);
-        //SUB SELECT
-        if (isNetworkPolicyModifiable(policy, mSubId) && isMobileDataAvailable(mSubId)) {
-            mChart.setNetworkPolicy(policy);
-            configureButton.setVisibility(View.VISIBLE);
-            ((ImageView) configureButton).setColorFilter(android.R.color.white);
-        } else {
-            // controls are disabled; don't bind warning/limit sweeps
-            mChart.setNetworkPolicy(null);
-            configureButton.setVisibility(View.GONE);
-        }
-
-        // generate cycle list based on policy and available history
-        if (mCycleAdapter.updateCycleList(mCycleData)) {
-            updateDetailData();
-        }
-    }
-
-    /**
-     * Update details based on {@link #mChart} inspection range depending on
-     * current mode. Updates {@link #mAdapter} with sorted list
-     * of applications data usage.
-     */
-    private void updateDetailData() {
-        if (LOGD) Log.d(TAG, "updateDetailData()");
-
-        // kick off loader for detailed stats
-        getLoaderManager().restartLoader(LOADER_SUMMARY, null /* args */,
-                mNetworkStatsDetailCallbacks);
-
-        final long totalBytes = mCycleData != null
-            ? mCycleData.get(mCycleSpinner.getSelectedItemPosition()).getTotalUsage() : 0;
-        final CharSequence totalPhrase = DataUsageUtils.formatDataUsage(getActivity(), totalBytes);
-        mUsageAmount.setTitle(getString(R.string.data_used_template, totalPhrase));
-    }
-
-    /**
-     * Bind the given {@link NetworkStats}, or {@code null} to clear list.
-     */
-    private void bindStats(NetworkStats stats, int[] restrictedUids) {
-        mApps.removeAll();
-        if (stats == null) {
-            if (LOGD) {
-                Log.d(TAG, "No network stats data. App list cleared.");
-            }
-            return;
-        }
-
-        final ArrayList<AppItem> items = new ArrayList<>();
-        long largest = 0;
-
-        final int currentUserId = ActivityManager.getCurrentUser();
-        final UserManager userManager = UserManager.get(getContext());
-        final List<UserHandle> profiles = userManager.getUserProfiles();
-        final SparseArray<AppItem> knownItems = new SparseArray<AppItem>();
-
-        final Bucket bucket = new Bucket();
-        while (stats.hasNextBucket() && stats.getNextBucket(bucket)) {
-            // Decide how to collapse items together
-            final int uid = bucket.getUid();
-            final int collapseKey;
-            final int category;
-            final int userId = UserHandle.getUserId(uid);
-            if (UserHandle.isApp(uid)) {
-                if (profiles.contains(new UserHandle(userId))) {
-                    if (userId != currentUserId) {
-                        // Add to a managed user item.
-                        final int managedKey = UidDetailProvider.buildKeyForUser(userId);
-                        largest = accumulate(managedKey, knownItems, bucket,
-                            AppItem.CATEGORY_USER, items, largest);
-                    }
-                    // Add to app item.
-                    collapseKey = uid;
-                    category = AppItem.CATEGORY_APP;
-                } else {
-                    // If it is a removed user add it to the removed users' key
-                    final UserInfo info = userManager.getUserInfo(userId);
-                    if (info == null) {
-                        collapseKey = UID_REMOVED;
-                        category = AppItem.CATEGORY_APP;
-                    } else {
-                        // Add to other user item.
-                        collapseKey = UidDetailProvider.buildKeyForUser(userId);
-                        category = AppItem.CATEGORY_USER;
-                    }
-                }
-            } else if (uid == UID_REMOVED || uid == UID_TETHERING) {
-                collapseKey = uid;
-                category = AppItem.CATEGORY_APP;
-            } else {
-                collapseKey = android.os.Process.SYSTEM_UID;
-                category = AppItem.CATEGORY_APP;
-            }
-            largest = accumulate(collapseKey, knownItems, bucket, category, items, largest);
-        }
-        stats.close();
-
-        final int restrictedUidsMax = restrictedUids.length;
-        for (int i = 0; i < restrictedUidsMax; ++i) {
-            final int uid = restrictedUids[i];
-            // Only splice in restricted state for current user or managed users
-            if (!profiles.contains(new UserHandle(UserHandle.getUserId(uid)))) {
-                continue;
-            }
-
-            AppItem item = knownItems.get(uid);
-            if (item == null) {
-                item = new AppItem(uid);
-                item.total = -1;
-                items.add(item);
-                knownItems.put(item.key, item);
-            }
-            item.restricted = true;
-        }
-
-        Collections.sort(items);
-        for (int i = 0; i < items.size(); i++) {
-            final int percentTotal = largest != 0 ? (int) (items.get(i).total * 100 / largest) : 0;
-            AppDataUsagePreference preference = new AppDataUsagePreference(getContext(),
-                    items.get(i), percentTotal, mUidDetailProvider);
-            preference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
-                @Override
-                public boolean onPreferenceClick(Preference preference) {
-                    AppDataUsagePreference pref = (AppDataUsagePreference) preference;
-                    AppItem item = pref.getItem();
-                    startAppDataUsage(item);
-                    return true;
-                }
-            });
-            mApps.addPreference(preference);
-        }
-    }
-
-    private void startAppDataUsage(AppItem item) {
-        final Bundle args = new Bundle();
-        args.putParcelable(AppDataUsageV2.ARG_APP_ITEM, item);
-        args.putParcelable(AppDataUsageV2.ARG_NETWORK_TEMPLATE, mTemplate);
-
-        new SubSettingLauncher(getContext())
-                .setDestination(AppDataUsageV2.class.getName())
-                .setTitleRes(R.string.app_data_usage)
-                .setArguments(args)
-                .setSourceMetricsCategory(getMetricsCategory())
-                .launch();
-    }
-
-    /**
-     * Accumulate data usage of a network stats entry for the item mapped by the collapse key.
-     * Creates the item if needed.
-     *
-     * @param collapseKey  the collapse key used to map the item.
-     * @param knownItems   collection of known (already existing) items.
-     * @param bucket       the network stats bucket to extract data usage from.
-     * @param itemCategory the item is categorized on the list view by this category. Must be
-     */
-    private static long accumulate(int collapseKey, final SparseArray<AppItem> knownItems,
-            Bucket bucket, int itemCategory, ArrayList<AppItem> items, long largest) {
-        final int uid = bucket.getUid();
-        AppItem item = knownItems.get(collapseKey);
-        if (item == null) {
-            item = new AppItem(collapseKey);
-            item.category = itemCategory;
-            items.add(item);
-            knownItems.put(item.key, item);
-        }
-        item.addUid(uid);
-        item.total += bucket.getRxBytes() + bucket.getTxBytes();
-        return Math.max(largest, item.total);
-    }
-
-    private OnItemSelectedListener mCycleListener = new OnItemSelectedListener() {
-        @Override
-        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
-            final CycleAdapter.CycleItem cycle = (CycleAdapter.CycleItem)
-                    mCycleSpinner.getSelectedItem();
-
-            if (LOGD) {
-                Log.d(TAG, "showing cycle " + cycle + ", start=" + cycle.start + ", end="
-                        + cycle.end + "]");
-            }
-
-            // update chart to show selected cycle, and update detail data
-            // to match updated sweep bounds.
-            mChart.setNetworkCycleData(mCycleData.get(position));
-
-            updateDetailData();
-        }
-
-        @Override
-        public void onNothingSelected(AdapterView<?> parent) {
-            // ignored
-        }
-    };
-
-    private final LoaderCallbacks<List<NetworkCycleChartData>> mNetworkCycleDataCallbacks =
-            new LoaderCallbacks<List<NetworkCycleChartData>>() {
-        @Override
-        public Loader<List<NetworkCycleChartData>> onCreateLoader(int id, Bundle args) {
-            return NetworkCycleChartDataLoader.builder(getContext())
-                    .setNetworkTemplate(mTemplate)
-                    .setSubscriberId(mTelephonyManager.getSubscriberId(mSubId))
-                    .build();
-        }
-
-        @Override
-        public void onLoadFinished(Loader<List<NetworkCycleChartData>> loader,
-                List<NetworkCycleChartData> data) {
-            mLoadingViewController.showContent(false /* animate */);
-            mCycleData = data;
-            // calculate policy cycles based on available data
-            updatePolicy();
-        }
-
-        @Override
-        public void onLoaderReset(Loader<List<NetworkCycleChartData>> loader) {
-            mCycleData = null;
-        }
-    };
-
-    private final LoaderCallbacks<NetworkStats> mNetworkStatsDetailCallbacks =
-            new LoaderCallbacks<NetworkStats>() {
-        @Override
-        public Loader<NetworkStats> onCreateLoader(int id, Bundle args) {
-            return new NetworkStatsSummaryLoader.Builder(getContext())
-                    .setStartTime(mChart.getInspectStart())
-                    .setEndTime(mChart.getInspectEnd())
-                    .setNetworkType(mNetworkType)
-                    .setSubscriberId(mTelephonyManager.getSubscriberId(mSubId))
-                    .build();
-        }
-
-        @Override
-        public void onLoadFinished(Loader<NetworkStats> loader, NetworkStats data) {
-            final int[] restrictedUids = services.mPolicyManager.getUidsWithPolicy(
-                    POLICY_REJECT_METERED_BACKGROUND);
-            bindStats(data, restrictedUids);
-            updateEmptyVisible();
-        }
-
-        @Override
-        public void onLoaderReset(Loader<NetworkStats> loader) {
-            bindStats(null, new int[0]);
-            updateEmptyVisible();
-        }
-
-        private void updateEmptyVisible() {
-            if ((mApps.getPreferenceCount() != 0) !=
-                    (getPreferenceScreen().getPreferenceCount() != 0)) {
-                if (mApps.getPreferenceCount() != 0) {
-                    getPreferenceScreen().addPreference(mUsageAmount);
-                    getPreferenceScreen().addPreference(mApps);
-                } else {
-                    getPreferenceScreen().removeAll();
-                }
-            }
-        }
-    };
-}
diff --git a/src/com/android/settings/datausage/DataUsagePreference.java b/src/com/android/settings/datausage/DataUsagePreference.java
index aa4e646..21c0503 100644
--- a/src/com/android/settings/datausage/DataUsagePreference.java
+++ b/src/com/android/settings/datausage/DataUsagePreference.java
@@ -21,7 +21,6 @@
 import android.net.NetworkTemplate;
 import android.os.Bundle;
 import android.util.AttributeSet;
-import android.util.FeatureFlagUtils;
 
 import androidx.annotation.VisibleForTesting;
 import androidx.core.content.res.TypedArrayUtils;
@@ -29,7 +28,6 @@
 
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.R;
-import com.android.settings.core.FeatureFlags;
 import com.android.settings.core.SubSettingLauncher;
 import com.android.settingslib.net.DataUsageController;
 
@@ -78,23 +76,14 @@
     public Intent getIntent() {
         final Bundle args = new Bundle();
         final SubSettingLauncher launcher;
-        if (FeatureFlagUtils.isEnabled(getContext(), FeatureFlags.DATA_USAGE_V2)) {
-            args.putParcelable(DataUsageListV2.EXTRA_NETWORK_TEMPLATE, mTemplate);
-            args.putInt(DataUsageListV2.EXTRA_SUB_ID, mSubId);
-            args.putInt(DataUsageListV2.EXTRA_NETWORK_TYPE, mTemplate.isMatchRuleMobile()
-                ? ConnectivityManager.TYPE_MOBILE : ConnectivityManager.TYPE_WIFI);
-            launcher = new SubSettingLauncher(getContext())
-                .setArguments(args)
-                .setDestination(DataUsageListV2.class.getName())
-                .setSourceMetricsCategory(MetricsProto.MetricsEvent.VIEW_UNKNOWN);
-        } else {
-            args.putParcelable(DataUsageList.EXTRA_NETWORK_TEMPLATE, mTemplate);
-            args.putInt(DataUsageList.EXTRA_SUB_ID, mSubId);
-            launcher = new SubSettingLauncher(getContext())
-                .setArguments(args)
-                .setDestination(DataUsageList.class.getName())
-                .setSourceMetricsCategory(MetricsProto.MetricsEvent.VIEW_UNKNOWN);
-        }
+        args.putParcelable(DataUsageList.EXTRA_NETWORK_TEMPLATE, mTemplate);
+        args.putInt(DataUsageList.EXTRA_SUB_ID, mSubId);
+        args.putInt(DataUsageList.EXTRA_NETWORK_TYPE, mTemplate.isMatchRuleMobile()
+            ? ConnectivityManager.TYPE_MOBILE : ConnectivityManager.TYPE_WIFI);
+        launcher = new SubSettingLauncher(getContext())
+            .setArguments(args)
+            .setDestination(DataUsageList.class.getName())
+            .setSourceMetricsCategory(MetricsProto.MetricsEvent.VIEW_UNKNOWN);
         if (mTemplate.isMatchRuleMobile()) {
             launcher.setTitleRes(R.string.app_cellular_data_usage);
         } else {
diff --git a/src/com/android/settings/datausage/DataUsageUtils.java b/src/com/android/settings/datausage/DataUsageUtils.java
index 53565ac..b3d0e61 100644
--- a/src/com/android/settings/datausage/DataUsageUtils.java
+++ b/src/com/android/settings/datausage/DataUsageUtils.java
@@ -22,12 +22,8 @@
 import android.app.usage.NetworkStatsManager;
 import android.content.Context;
 import android.net.ConnectivityManager;
-import android.net.INetworkStatsService;
-import android.net.INetworkStatsSession;
 import android.net.NetworkTemplate;
-import android.net.TrafficStats;
 import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.os.SystemProperties;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
@@ -35,11 +31,8 @@
 import android.text.BidiFormatter;
 import android.text.format.Formatter;
 import android.text.format.Formatter.BytesResult;
-import android.util.FeatureFlagUtils;
 import android.util.Log;
 
-import com.android.settings.core.FeatureFlags;
-
 import java.util.List;
 
 /**
@@ -78,44 +71,21 @@
             return false;
         }
 
-        if (FeatureFlagUtils.isEnabled(context, FeatureFlags.DATA_USAGE_V2)) {
-            final TelephonyManager telephonyManager = TelephonyManager.from(context);;
-            final NetworkStatsManager networkStatsManager =
-                context.getSystemService(NetworkStatsManager.class);
-            boolean hasEthernetUsage = false;
-            try {
-                final Bucket bucket = networkStatsManager.querySummaryForUser(
-                    ConnectivityManager.TYPE_ETHERNET, telephonyManager.getSubscriberId(),
-                    0L /* startTime */, System.currentTimeMillis() /* endTime */);
-                if (bucket != null) {
-                    hasEthernetUsage = bucket.getRxBytes() > 0 || bucket.getTxBytes() > 0;
-                }
-            } catch (RemoteException e) {
-                Log.e(TAG, "Exception querying network detail.", e);
+        final TelephonyManager telephonyManager = TelephonyManager.from(context);;
+        final NetworkStatsManager networkStatsManager =
+            context.getSystemService(NetworkStatsManager.class);
+        boolean hasEthernetUsage = false;
+        try {
+            final Bucket bucket = networkStatsManager.querySummaryForUser(
+                ConnectivityManager.TYPE_ETHERNET, telephonyManager.getSubscriberId(),
+                0L /* startTime */, System.currentTimeMillis() /* endTime */);
+            if (bucket != null) {
+                hasEthernetUsage = bucket.getRxBytes() > 0 || bucket.getTxBytes() > 0;
             }
-            return hasEthernetUsage;
-        } else {
-            final long ethernetBytes;
-            try {
-                INetworkStatsService statsService = INetworkStatsService.Stub.asInterface(
-                    ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
-
-                INetworkStatsSession statsSession = statsService.openSession();
-                if (statsSession != null) {
-                    ethernetBytes = statsSession.getSummaryForNetwork(
-                        NetworkTemplate.buildTemplateEthernet(), Long.MIN_VALUE, Long.MAX_VALUE)
-                        .getTotalBytes();
-                    TrafficStats.closeQuietly(statsSession);
-                } else {
-                    ethernetBytes = 0;
-                }
-            } catch (RemoteException e) {
-                throw new RuntimeException(e);
-            }
-
-            // only show ethernet when both hardware present and traffic has occurred
-            return ethernetBytes > 0;
+        } catch (RemoteException e) {
+            Log.e(TAG, "Exception querying network detail.", e);
         }
+        return hasEthernetUsage;
     }
 
     /**
diff --git a/src/com/android/settings/development/AllowBackgroundActivityStartsPreferenceController.java b/src/com/android/settings/development/AllowBackgroundActivityStartsPreferenceController.java
new file mode 100644
index 0000000..ea47f35
--- /dev/null
+++ b/src/com/android/settings/development/AllowBackgroundActivityStartsPreferenceController.java
@@ -0,0 +1,68 @@
+/*
+ * 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.development;
+
+import android.content.Context;
+import android.provider.Settings;
+
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.development.DeveloperOptionsPreferenceController;
+
+import androidx.preference.Preference;
+import androidx.preference.SwitchPreference;
+
+public class AllowBackgroundActivityStartsPreferenceController
+        extends DeveloperOptionsPreferenceController
+        implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin {
+
+    private static final String BACKGROUND_ACTIVITY_STARTS_ENABLED_KEY
+            = "allow_background_activity_starts";
+
+    public AllowBackgroundActivityStartsPreferenceController(Context context) {
+        super(context);
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return BACKGROUND_ACTIVITY_STARTS_ENABLED_KEY;
+    }
+
+    @Override
+    public boolean onPreferenceChange(Preference preference, Object newValue) {
+        writeSetting((boolean) newValue);
+        return true;
+    }
+
+    private void writeSetting(boolean isEnabled) {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED, isEnabled ? 1 : 0);
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        final int mode = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED, 1);
+        ((SwitchPreference) mPreference).setChecked(mode != 0);
+    }
+
+    @Override
+    protected void onDeveloperOptionsSwitchDisabled() {
+        super.onDeveloperOptionsSwitchDisabled();
+        writeSetting(false);
+        ((SwitchPreference) mPreference).setChecked(false);
+    }
+}
diff --git a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
index 932c0c7..762686a 100644
--- a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
+++ b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
@@ -454,6 +454,7 @@
         controllers.add(new ProfileGpuRenderingPreferenceController(context));
         controllers.add(new KeepActivitiesPreferenceController(context));
         controllers.add(new BackgroundProcessLimitPreferenceController(context));
+        controllers.add(new AllowBackgroundActivityStartsPreferenceController(context));
         controllers.add(new ShowFirstCrashDialogPreferenceController(context));
         controllers.add(new AppsNotRespondingPreferenceController(context));
         controllers.add(new NotificationChannelWarningsPreferenceController(context));
diff --git a/src/com/android/settings/deviceinfo/PrivateVolumeOptionMenuController.java b/src/com/android/settings/deviceinfo/PrivateVolumeOptionMenuController.java
index ce425c6..00a79a0 100644
--- a/src/com/android/settings/deviceinfo/PrivateVolumeOptionMenuController.java
+++ b/src/com/android/settings/deviceinfo/PrivateVolumeOptionMenuController.java
@@ -67,7 +67,8 @@
         if (migrate != null) {
             migrate.setVisible((privateVol != null)
                     && (privateVol.getType() == VolumeInfo.TYPE_PRIVATE)
-                    && !Objects.equals(mVolumeInfo, privateVol));
+                    && !Objects.equals(mVolumeInfo, privateVol)
+                    && privateVol.isMountedWritable());
         }
     }
 
diff --git a/src/com/android/settings/deviceinfo/PrivateVolumeSettings.java b/src/com/android/settings/deviceinfo/PrivateVolumeSettings.java
index 1812974..f516926 100644
--- a/src/com/android/settings/deviceinfo/PrivateVolumeSettings.java
+++ b/src/com/android/settings/deviceinfo/PrivateVolumeSettings.java
@@ -416,7 +416,8 @@
                 .getPrimaryStorageCurrentVolume();
         migrate.setVisible((privateVol != null)
                 && (privateVol.getType() == VolumeInfo.TYPE_PRIVATE)
-                && !Objects.equals(mVolume, privateVol));
+                && !Objects.equals(mVolume, privateVol)
+                && privateVol.isMountedWritable());
     }
 
     @Override
diff --git a/src/com/android/settings/display/AutoBrightnessPreferenceController.java b/src/com/android/settings/display/AutoBrightnessPreferenceController.java
index 3f5f2b0..3b53fa8 100644
--- a/src/com/android/settings/display/AutoBrightnessPreferenceController.java
+++ b/src/com/android/settings/display/AutoBrightnessPreferenceController.java
@@ -52,7 +52,7 @@
     public int getAvailabilityStatus() {
         return mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_automatic_brightness_available)
-                ? AVAILABLE_UNSEARCHABLE
+                ? AVAILABLE
                 : UNSUPPORTED_ON_DEVICE;
     }
 
@@ -67,4 +67,4 @@
                 ? R.string.auto_brightness_summary_on
                 : R.string.auto_brightness_summary_off);
     }
-}
\ No newline at end of file
+}
diff --git a/src/com/android/settings/flashlight/FlashlightSliceBuilder.java b/src/com/android/settings/flashlight/FlashlightSliceBuilder.java
index d21739e..5833229 100644
--- a/src/com/android/settings/flashlight/FlashlightSliceBuilder.java
+++ b/src/com/android/settings/flashlight/FlashlightSliceBuilder.java
@@ -22,17 +22,14 @@
 
 import android.annotation.ColorInt;
 import android.app.PendingIntent;
-import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.hardware.camera2.CameraAccessException;
 import android.hardware.camera2.CameraCharacteristics;
 import android.hardware.camera2.CameraManager;
-import android.net.Uri;
 import android.provider.Settings;
 import android.provider.Settings.Secure;
-import android.provider.SettingsSlicesContract;
 import android.util.Log;
 
 import androidx.core.graphics.drawable.IconCompat;
@@ -43,7 +40,7 @@
 
 import com.android.settings.R;
 import com.android.settings.Utils;
-import com.android.settings.slices.SettingsSliceProvider;
+import com.android.settings.slices.CustomSliceRegistry;
 import com.android.settings.slices.SliceBroadcastReceiver;
 
 
@@ -54,37 +51,23 @@
 
     private static final String TAG = "FlashlightSliceBuilder";
 
-    public static final String KEY_FLASHLIGHT = "flashlight";
-
-    /**
-     * Backing Uri for the Flashlight Slice.
-     */
-    public static final Uri FLASHLIGHT_URI = new Uri.Builder()
-        .scheme(ContentResolver.SCHEME_CONTENT)
-        .authority(SettingsSliceProvider.SLICE_AUTHORITY)
-        .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
-        .appendPath(KEY_FLASHLIGHT)
-        .build();
-
     /**
      * Action notifying a change on the Flashlight Slice.
      */
     public static final String ACTION_FLASHLIGHT_SLICE_CHANGED =
-        "com.android.settings.flashlight.action.FLASHLIGHT_SLICE_CHANGED";
+            "com.android.settings.flashlight.action.FLASHLIGHT_SLICE_CHANGED";
 
     /**
      * Action broadcasting a change on whether flashlight is on or off.
      */
     public static final String ACTION_FLASHLIGHT_CHANGED =
-        "com.android.settings.flashlight.action.FLASHLIGHT_CHANGED";
+            "com.android.settings.flashlight.action.FLASHLIGHT_CHANGED";
 
     public static final IntentFilter INTENT_FILTER = new IntentFilter(ACTION_FLASHLIGHT_CHANGED);
 
-    private FlashlightSliceBuilder() {}
+    private FlashlightSliceBuilder() {
+    }
 
-    /**
-     * Return a Flashlight Slice bound to {@link #FLASHLIGHT_URI}.
-     */
     public static Slice getSlice(Context context) {
         if (!isFlashlightAvailable(context)) {
             return null;
@@ -93,14 +76,15 @@
         @ColorInt final int color = Utils.getColorAccentDefaultColor(context);
         final IconCompat icon =
                 IconCompat.createWithResource(context, R.drawable.ic_signal_flashlight);
-        return new ListBuilder(context, FLASHLIGHT_URI, ListBuilder.INFINITY)
-            .setAccentColor(color)
-            .addRow(new RowBuilder()
-                .setTitle(context.getText(R.string.power_flashlight))
-                .setTitleItem(icon, ICON_IMAGE)
-                .setPrimaryAction(
-                        new SliceAction(toggleAction, null, isFlashlightEnabled(context))))
-            .build();
+        return new ListBuilder(context, CustomSliceRegistry.FLASHLIGHT_SLICE_URI,
+                ListBuilder.INFINITY)
+                .setAccentColor(color)
+                .addRow(new RowBuilder()
+                        .setTitle(context.getText(R.string.power_flashlight))
+                        .setTitleItem(icon, ICON_IMAGE)
+                        .setPrimaryAction(
+                                SliceAction.createToggle(toggleAction, null, isFlashlightEnabled(context))))
+                .build();
     }
 
     /**
@@ -119,7 +103,7 @@
         } catch (CameraAccessException e) {
             Log.e(TAG, "Camera couldn't set torch mode.", e);
         }
-        context.getContentResolver().notifyChange(FLASHLIGHT_URI, null);
+        context.getContentResolver().notifyChange(CustomSliceRegistry.FLASHLIGHT_SLICE_URI, null);
     }
 
     private static String getCameraId(Context context) throws CameraAccessException {
@@ -130,7 +114,7 @@
             Boolean flashAvailable = c.get(CameraCharacteristics.FLASH_INFO_AVAILABLE);
             Integer lensFacing = c.get(CameraCharacteristics.LENS_FACING);
             if (flashAvailable != null && flashAvailable
-                  && lensFacing != null && lensFacing == CameraCharacteristics.LENS_FACING_BACK) {
+                    && lensFacing != null && lensFacing == CameraCharacteristics.LENS_FACING_BACK) {
                 return id;
             }
         }
@@ -141,16 +125,16 @@
         final Intent intent = new Intent(ACTION_FLASHLIGHT_SLICE_CHANGED);
         intent.setClass(context, SliceBroadcastReceiver.class);
         return PendingIntent.getBroadcast(context, 0 /* requestCode */, intent,
-            PendingIntent.FLAG_CANCEL_CURRENT);
+                PendingIntent.FLAG_CANCEL_CURRENT);
     }
 
     private static boolean isFlashlightAvailable(Context context) {
         return Settings.Secure.getInt(
-            context.getContentResolver(), Secure.FLASHLIGHT_AVAILABLE, 0) == 1;
+                context.getContentResolver(), Secure.FLASHLIGHT_AVAILABLE, 0) == 1;
     }
 
     private static boolean isFlashlightEnabled(Context context) {
         return Settings.Secure.getInt(
-            context.getContentResolver(), Secure.FLASHLIGHT_ENABLED, 0) == 1;
+                context.getContentResolver(), Secure.FLASHLIGHT_ENABLED, 0) == 1;
     }
 }
diff --git a/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceController.java b/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceController.java
index eac2bf5..0d9b1c4 100644
--- a/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceController.java
@@ -42,6 +42,9 @@
  * Controller in charge of the battery tip group
  */
 public class BatteryTipPreferenceController extends BasePreferenceController {
+
+    public static final String PREF_NAME = "battery_tip";
+
     private static final String TAG = "BatteryTipPreferenceController";
     private static final int REQUEST_ANOMALY_ACTION = 0;
     private static final String KEY_BATTERY_TIPS = "key_battery_tips";
diff --git a/src/com/android/settings/gestures/GesturesSettingPreferenceController.java b/src/com/android/settings/gestures/GesturesSettingPreferenceController.java
index 2e9b5a5..00b7a0c 100644
--- a/src/com/android/settings/gestures/GesturesSettingPreferenceController.java
+++ b/src/com/android/settings/gestures/GesturesSettingPreferenceController.java
@@ -52,7 +52,7 @@
         for (AbstractPreferenceController controller : mGestureControllers) {
             isAvailable = isAvailable || controller.isAvailable();
         }
-        return isAvailable ? AVAILABLE_UNSEARCHABLE : UNSUPPORTED_ON_DEVICE;
+        return isAvailable ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
     }
 
     /**
@@ -101,4 +101,4 @@
         }
         return mContext.getText(R.string.language_input_gesture_summary_off);
     }
-}
\ No newline at end of file
+}
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProvider.java b/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProvider.java
new file mode 100644
index 0000000..8583f38
--- /dev/null
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProvider.java
@@ -0,0 +1,39 @@
+/*
+ * 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;
+
+import android.content.Context;
+
+import java.util.List;
+
+/** Feature provider for the contextual card feature. */
+public interface ContextualCardFeatureProvider {
+
+    /** Homepage displays. */
+    public void logHomepageDisplay(Context context, Long latency);
+
+    /** When user clicks dismiss in contextual card */
+    public void logContextualCardDismiss(Context context, ContextualCard card);
+
+    /** After ContextualCardManager decides which cards will be displayed/hidden */
+    public void logContextualCardDisplay(Context context, List<ContextualCard> showedCards,
+            List<ContextualCard> hiddenCards);
+
+    /** When user clicks toggle/title area of a contextual card. */
+    public void logContextualCardClick(Context context, ContextualCard card, int row,
+            int tapTarget);
+}
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImpl.java b/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImpl.java
new file mode 100644
index 0000000..e437e2b
--- /dev/null
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImpl.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.settings.homepage.contextualcards;
+
+import android.content.Context;
+import android.content.Intent;
+import android.text.TextUtils;
+import android.util.Log;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.slice.widget.EventInfo;
+
+import com.android.settings.R;
+
+import java.util.List;
+
+public class ContextualCardFeatureProviderImpl implements ContextualCardFeatureProvider {
+    private static final String TAG = "ContextualCardFeature";
+
+    // Contextual card interaction logs
+    // Settings Homepage shows
+    private static final int CONTEXTUAL_HOME_SHOW = 38;
+
+    // Contextual card shows, log card name and rank
+    private static final int CONTEXTUAL_CARD_SHOW = 39;
+
+    // Contextual card is eligible to be shown, but doesn't rank high
+    // enough, log card name and score
+    private static final int CONTEXTUAL_CARD_NOT_SHOW = 40;
+
+    // Contextual card is dismissed, log card name
+    private static final int CONTEXTUAL_CARD_DISMISS = 41;
+
+    // Contextual card is clicked , log card name, score, tap area
+    private static final int CONTEXTUAL_CARD_CLICK = 42;
+
+    // SettingsLogBroadcastReceiver contracts
+    // contextual card name
+    private static final String EXTRA_CONTEXTUALCARD_NAME = "name";
+
+    // contextual card score
+    private static final String EXTRA_CONTEXTUALCARD_SCORE = "score";
+
+    // contextual card clicked row
+    private static final String EXTRA_CONTEXTUALCARD_ROW = "row";
+
+    // contextual card tap target
+    private static final String EXTRA_CONTEXTUALCARD_TAP_TARGET = "target";
+
+    // contextual homepage display latency
+    private static final String EXTRA_LATENCY = "latency";
+
+    // log type
+    private static final String EXTRA_CONTEXTUALCARD_ACTION_TYPE = "type";
+
+
+    // Contextual card tap target
+    private static final int TARGET_DEFAULT = 0;
+
+    // Click title area
+    private static final int TARGET_TITLE = 1;
+
+    // Click toggle
+    private static final int TARGET_TOGGLE = 2;
+
+    // Click slider
+    private static final int TARGET_SLIDER = 3;
+
+    @Override
+    public void logHomepageDisplay(Context context, Long latency) {
+    }
+
+    @Override
+    public void logContextualCardDismiss(Context context, ContextualCard card) {
+        final Intent intent = new Intent();
+        intent.putExtra(EXTRA_CONTEXTUALCARD_ACTION_TYPE, CONTEXTUAL_CARD_DISMISS);
+        intent.putExtra(EXTRA_CONTEXTUALCARD_NAME, card.getName());
+        intent.putExtra(EXTRA_CONTEXTUALCARD_SCORE, card.getRankingScore());
+        sendBroadcast(context, intent);
+    }
+
+    @Override
+    public void logContextualCardDisplay(Context context, List<ContextualCard> showCards,
+            List<ContextualCard> hiddenCards) {
+    }
+
+    @Override
+    public void logContextualCardClick(Context context, ContextualCard card, int row,
+            int actionType) {
+        final Intent intent = new Intent();
+        intent.putExtra(EXTRA_CONTEXTUALCARD_ACTION_TYPE, CONTEXTUAL_CARD_CLICK);
+        intent.putExtra(EXTRA_CONTEXTUALCARD_NAME, card.getName());
+        intent.putExtra(EXTRA_CONTEXTUALCARD_SCORE, card.getRankingScore());
+        intent.putExtra(EXTRA_CONTEXTUALCARD_ROW, row);
+        intent.putExtra(EXTRA_CONTEXTUALCARD_TAP_TARGET, actionTypeToTapTarget(actionType));
+        sendBroadcast(context, intent);
+    }
+
+    @VisibleForTesting
+    void sendBroadcast(final Context context, final Intent intent) {
+        intent.setPackage(context.getString(R.string.config_settingsintelligence_package_name));
+        final String action = context.getString(R.string.config_settingsintelligence_log_action);
+        if (!TextUtils.isEmpty(action)) {
+            intent.setAction(action);
+            context.sendBroadcast(intent);
+        }
+    }
+
+    private int actionTypeToTapTarget(int actionType) {
+        switch (actionType) {
+            case EventInfo.ACTION_TYPE_CONTENT:
+                return TARGET_TITLE;
+            case EventInfo.ACTION_TYPE_TOGGLE:
+                return TARGET_TOGGLE;
+            case EventInfo.ACTION_TYPE_SLIDER:
+                return TARGET_SLIDER;
+            default:
+                Log.w(TAG, "unknown type " + actionType);
+                return TARGET_DEFAULT;
+        }
+    }
+}
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardFeedbackDialog.java b/src/com/android/settings/homepage/contextualcards/ContextualCardFeedbackDialog.java
new file mode 100644
index 0000000..0d5b275
--- /dev/null
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardFeedbackDialog.java
@@ -0,0 +1,66 @@
+/*
+ * 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;
+
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.Log;
+
+import com.android.internal.app.AlertActivity;
+import com.android.internal.app.AlertController;
+import com.android.settings.R;
+
+public class ContextualCardFeedbackDialog extends AlertActivity implements
+        DialogInterface.OnClickListener {
+
+    public static final String EXTRA_CARD_NAME = "card_name";
+    public static final String EXTRA_FEEDBACK_EMAIL = "feedback_email";
+
+    private static final String TAG = "CardFeedbackDialog";
+    private static final String SUBJECT = "Settings Contextual Card Feedback - ";
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        final AlertController.AlertParams alertParams = mAlertParams;
+        alertParams.mMessage = getText(R.string.contextual_card_feedback_confirm_message);
+        alertParams.mPositiveButtonText = getText(R.string.contextual_card_feedback_send);
+        alertParams.mPositiveButtonListener = this;
+        alertParams.mNegativeButtonText = getText(R.string.skip_label);
+
+        setupAlert();
+    }
+
+    @Override
+    public void onClick(DialogInterface dialog, int which) {
+        final String cardName = getIntent().getStringExtra(EXTRA_CARD_NAME);
+        final String email = getIntent().getStringExtra(EXTRA_FEEDBACK_EMAIL);
+        final Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.parse("mailto:" + email));
+        intent.putExtra(Intent.EXTRA_SUBJECT, SUBJECT + cardName);
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+        try {
+            startActivity(intent);
+        } catch (Exception e) {
+            Log.e(TAG, "Send feedback failed.", e);
+        }
+        finish();
+    }
+}
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
index 4c06601..3ef4653 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
@@ -34,8 +34,7 @@
 import androidx.annotation.VisibleForTesting;
 import androidx.slice.Slice;
 
-import com.android.settings.homepage.contextualcards.slices.ConnectedDeviceSlice;
-import com.android.settings.wifi.WifiSlice;
+import com.android.settings.slices.CustomSliceRegistry;
 import com.android.settingslib.utils.AsyncLoaderCompat;
 
 import java.util.ArrayList;
@@ -170,8 +169,8 @@
 
     private int getNumberOfLargeCard(List<ContextualCard> cards) {
         return (int) cards.stream()
-                .filter(card -> card.getSliceUri().equals(WifiSlice.WIFI_URI)
-                        || card.getSliceUri().equals(ConnectedDeviceSlice.CONNECTED_DEVICE_URI))
+                .filter(card -> card.getSliceUri().equals(CustomSliceRegistry.WIFI_SLICE_URI)
+                        || card.getSliceUri().equals(CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI))
                 .count();
     }
 
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java b/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
index 30eae29..5f397d7 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
@@ -40,6 +40,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.TreeSet;
 import java.util.stream.Collectors;
 
 /**
@@ -132,8 +133,13 @@
         // except Conditional cards, all other cards are from the database. So when the map sent
         // here is empty, we only keep Conditional cards.
         if (cardTypes.isEmpty()) {
+            final Set<Integer> conditionalCardTypes = new TreeSet() {{
+                add(ContextualCard.CardType.CONDITIONAL);
+                add(ContextualCard.CardType.CONDITIONAL_HEADER);
+                add(ContextualCard.CardType.CONDITIONAL_FOOTER);
+            }};
             cardsToKeep = mContextualCards.stream()
-                    .filter(card -> card.getCardType() == ContextualCard.CardType.CONDITIONAL)
+                    .filter(card -> conditionalCardTypes.contains(card.getCardType()))
                     .collect(Collectors.toList());
         } else {
             cardsToKeep = mContextualCards.stream()
diff --git a/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java b/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java
index 5ff3e90..376bb83 100644
--- a/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java
+++ b/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java
@@ -16,16 +16,11 @@
 
 package com.android.settings.homepage.contextualcards;
 
-import static android.provider.SettingsSlicesContract.KEY_WIFI;
-
 import android.annotation.Nullable;
 
-import com.android.settings.homepage.contextualcards.slices.BatteryFixSlice;
-import com.android.settings.homepage.contextualcards.slices.ConnectedDeviceSlice;
-import com.android.settings.homepage.contextualcards.slices.LowStorageSlice;
 import com.android.settings.intelligence.ContextualCardProto.ContextualCard;
 import com.android.settings.intelligence.ContextualCardProto.ContextualCardList;
-import com.android.settings.wifi.WifiSlice;
+import com.android.settings.slices.CustomSliceRegistry;
 
 import com.google.android.settings.intelligence.libs.contextualcards.ContextualCardProvider;
 
@@ -39,26 +34,26 @@
     public ContextualCardList getContextualCards() {
         final ContextualCard wifiCard =
                 ContextualCard.newBuilder()
-                        .setSliceUri(WifiSlice.WIFI_URI.toString())
-                        .setCardName(KEY_WIFI)
+                        .setSliceUri(CustomSliceRegistry.WIFI_SLICE_URI.toString())
+                        .setCardName(CustomSliceRegistry.WIFI_SLICE_URI.toString())
                         .setCardCategory(ContextualCard.Category.IMPORTANT)
                         .build();
         final ContextualCard connectedDeviceCard =
                 ContextualCard.newBuilder()
-                        .setSliceUri(ConnectedDeviceSlice.CONNECTED_DEVICE_URI.toString())
-                        .setCardName(ConnectedDeviceSlice.PATH_CONNECTED_DEVICE)
+                        .setSliceUri(CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI.toString())
+                        .setCardName(CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI.toString())
                         .setCardCategory(ContextualCard.Category.IMPORTANT)
                         .build();
         final ContextualCard lowStorageCard =
                 ContextualCard.newBuilder()
-                        .setSliceUri(LowStorageSlice.LOW_STORAGE_URI.toString())
-                        .setCardName(LowStorageSlice.PATH_LOW_STORAGE)
+                        .setSliceUri(CustomSliceRegistry.LOW_STORAGE_SLICE_URI.toString())
+                        .setCardName(CustomSliceRegistry.LOW_STORAGE_SLICE_URI.toString())
                         .setCardCategory(ContextualCard.Category.IMPORTANT)
                         .build();
         final ContextualCard batteryFixCard =
                 ContextualCard.newBuilder()
-                        .setSliceUri(BatteryFixSlice.BATTERY_FIX_URI.toString())
-                        .setCardName(BatteryFixSlice.PATH_BATTERY_FIX)
+                        .setSliceUri(CustomSliceRegistry.BATTERY_FIX_SLICE_URI.toString())
+                        .setCardName(CustomSliceRegistry.BATTERY_FIX_SLICE_URI.toString())
                         .setCardCategory(ContextualCard.Category.IMPORTANT)
                         .build();
         final ContextualCardList cards = ContextualCardList.newBuilder()
diff --git a/src/com/android/settings/homepage/contextualcards/conditional/DndConditionCardController.java b/src/com/android/settings/homepage/contextualcards/conditional/DndConditionCardController.java
index 706b50e..cf91157 100644
--- a/src/com/android/settings/homepage/contextualcards/conditional/DndConditionCardController.java
+++ b/src/com/android/settings/homepage/contextualcards/conditional/DndConditionCardController.java
@@ -98,25 +98,12 @@
                 .setName(mAppContext.getPackageName() + "/"
                         + mAppContext.getText(R.string.condition_zen_title))
                 .setTitleText(mAppContext.getText(R.string.condition_zen_title).toString())
-                .setSummaryText(getSummary().toString())
+                .setSummaryText(mAppContext.getText(R.string.condition_zen_summary).toString())
                 .setIconDrawable(mAppContext.getDrawable(R.drawable.ic_do_not_disturb_on_24dp))
                 .setIsHalfWidth(true)
                 .build();
     }
 
-    public CharSequence getSummary() {
-        final int zen = mNotificationManager.getZenMode();
-        final ZenModeConfig config;
-        boolean zenModeEnabled = zen != Settings.Global.ZEN_MODE_OFF;
-        if (zenModeEnabled) {
-            config = mNotificationManager.getZenModeConfig();
-        } else {
-            config = null;
-        }
-        return ZenModeConfig.getDescription(mAppContext, zen != Settings.Global.ZEN_MODE_OFF,
-                config, true);
-    }
-
     public class Receiver extends BroadcastReceiver {
         @Override
         public void onReceive(Context context, Intent intent) {
diff --git a/src/com/android/settings/homepage/contextualcards/deviceinfo/BatterySlice.java b/src/com/android/settings/homepage/contextualcards/deviceinfo/BatterySlice.java
index 873b942..b0d6963 100644
--- a/src/com/android/settings/homepage/contextualcards/deviceinfo/BatterySlice.java
+++ b/src/com/android/settings/homepage/contextualcards/deviceinfo/BatterySlice.java
@@ -16,8 +16,9 @@
 
 package com.android.settings.homepage.contextualcards.deviceinfo;
 
+import static com.android.settings.slices.CustomSliceRegistry.BATTERY_INFO_SLICE_URI;
+
 import android.app.PendingIntent;
-import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -37,7 +38,6 @@
 import com.android.settings.fuelgauge.BatteryInfo;
 import com.android.settings.fuelgauge.PowerUsageSummary;
 import com.android.settings.slices.CustomSliceable;
-import com.android.settings.slices.SettingsSliceProvider;
 import com.android.settings.slices.SliceBuilderUtils;
 
 /**
@@ -46,20 +46,6 @@
 public class BatterySlice implements CustomSliceable {
     private static final String TAG = "BatterySlice";
 
-    /**
-     * The path denotes the unique name of battery slice.
-     */
-    public static final String PATH_BATTERY_INFO = "battery_card";
-
-    /**
-     * Backing Uri for the Battery Slice.
-     */
-    public static final Uri BATTERY_CARD_URI = new Uri.Builder()
-            .scheme(ContentResolver.SCHEME_CONTENT)
-            .authority(SettingsSliceProvider.SLICE_AUTHORITY)
-            .appendPath(PATH_BATTERY_INFO)
-            .build();
-
     private final Context mContext;
 
     private BatteryInfo mBatteryInfo;
@@ -69,9 +55,6 @@
         mContext = context;
     }
 
-    /**
-     * Return a {@link BatterySlice} bound to {@link #BATTERY_CARD_URI}
-     */
     @Override
     public Slice getSlice() {
         if (mBatteryInfo == null) {
@@ -81,8 +64,9 @@
         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 = new SliceAction(getPrimaryAction(), icon, title);
-        final Slice slice = new ListBuilder(mContext, BATTERY_CARD_URI, ListBuilder.INFINITY)
+        final SliceAction primarySliceAction = SliceAction.createDeeplink(getPrimaryAction(), icon,
+                ListBuilder.ICON_IMAGE, title);
+        final Slice slice = new ListBuilder(mContext, BATTERY_INFO_SLICE_URI, ListBuilder.INFINITY)
                 .setAccentColor(Utils.getColorAccentDefaultColor(mContext))
                 .setHeader(new ListBuilder.HeaderBuilder().setTitle(title))
                 .addRow(new ListBuilder.RowBuilder()
@@ -97,7 +81,7 @@
 
     @Override
     public Uri getUri() {
-        return BATTERY_CARD_URI;
+        return BATTERY_INFO_SLICE_URI;
     }
 
     @Override
@@ -108,12 +92,10 @@
     @Override
     public Intent getIntent() {
         final String screenTitle = mContext.getText(R.string.power_usage_summary_title).toString();
-        final Uri contentUri = new Uri.Builder().appendPath(PATH_BATTERY_INFO).build();
         return SliceBuilderUtils.buildSearchResultPageIntent(mContext,
-                PowerUsageSummary.class.getName(), PATH_BATTERY_INFO, screenTitle,
+                PowerUsageSummary.class.getName(), "" /* key */, screenTitle,
                 MetricsProto.MetricsEvent.SLICE)
-                .setClassName(mContext.getPackageName(), SubSettings.class.getName())
-                .setData(contentUri);
+                .setClassName(mContext.getPackageName(), SubSettings.class.getName());
     }
 
     @Override
diff --git a/src/com/android/settings/homepage/contextualcards/deviceinfo/DataUsageSlice.java b/src/com/android/settings/homepage/contextualcards/deviceinfo/DataUsageSlice.java
index 6296b1e..bb78586 100644
--- a/src/com/android/settings/homepage/contextualcards/deviceinfo/DataUsageSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/deviceinfo/DataUsageSlice.java
@@ -17,7 +17,6 @@
 package com.android.settings.homepage.contextualcards.deviceinfo;
 
 import android.app.PendingIntent;
-import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.net.Uri;
@@ -39,8 +38,8 @@
 import com.android.settings.Utils;
 import com.android.settings.datausage.DataUsageSummary;
 import com.android.settings.datausage.DataUsageUtils;
+import com.android.settings.slices.CustomSliceRegistry;
 import com.android.settings.slices.CustomSliceable;
-import com.android.settings.slices.SettingsSliceProvider;
 import com.android.settings.slices.SliceBuilderUtils;
 import com.android.settingslib.net.DataUsageController;
 
@@ -50,19 +49,6 @@
     private static final String TAG = "DataUsageSlice";
     private static final long MILLIS_IN_A_DAY = TimeUnit.DAYS.toMillis(1);
 
-    /**
-     * The path denotes the unique name of data usage slice.
-     */
-    public static final String PATH_DATA_USAGE = "data_usage_card";
-
-    /**
-     * Backing Uri for the Data usage Slice.
-     */
-    public static final Uri DATA_USAGE_CARD_URI = new Uri.Builder()
-            .scheme(ContentResolver.SCHEME_CONTENT)
-            .authority(SettingsSliceProvider.SLICE_AUTHORITY)
-            .appendPath(PATH_DATA_USAGE)
-            .build();
 
     private final Context mContext;
 
@@ -72,22 +58,21 @@
 
     @Override
     public Uri getUri() {
-        return DATA_USAGE_CARD_URI;
+        return CustomSliceRegistry.DATA_USAGE_SLICE_URI;
     }
 
-    /**
-     * Return a Data usage Slice bound to {@link #DATA_USAGE_CARD_URI}
-     */
     @Override
     public Slice getSlice() {
         final IconCompat icon = IconCompat.createWithResource(mContext,
                 R.drawable.ic_settings_data_usage);
         final String title = mContext.getString(R.string.data_usage_summary_title);
-        final SliceAction primaryAction = new SliceAction(getPrimaryAction(), icon, title);
+        final SliceAction primaryAction = SliceAction.createDeeplink(getPrimaryAction(), icon,
+                ListBuilder.ICON_IMAGE, title);
         final DataUsageController dataUsageController = new DataUsageController(mContext);
         final DataUsageController.DataUsageInfo info = dataUsageController.getDataUsageInfo();
         final ListBuilder listBuilder =
-                new ListBuilder(mContext, DATA_USAGE_CARD_URI, ListBuilder.INFINITY)
+                new ListBuilder(mContext, CustomSliceRegistry.DATA_USAGE_SLICE_URI,
+                        ListBuilder.INFINITY)
                         .setAccentColor(Utils.getColorAccentDefaultColor(mContext))
                         .setHeader(new ListBuilder.HeaderBuilder().setTitle(title));
         if (DataUsageUtils.hasSim(mContext)) {
@@ -106,12 +91,10 @@
     @Override
     public Intent getIntent() {
         final String screenTitle = mContext.getText(R.string.data_usage_wifi_title).toString();
-        final Uri contentUri = new Uri.Builder().appendPath(PATH_DATA_USAGE).build();
         return SliceBuilderUtils.buildSearchResultPageIntent(mContext,
-                DataUsageSummary.class.getName(), PATH_DATA_USAGE, screenTitle,
+                DataUsageSummary.class.getName(), "" /* key */, screenTitle,
                 MetricsProto.MetricsEvent.SLICE)
-                .setClassName(mContext.getPackageName(), SubSettings.class.getName())
-                .setData(contentUri);
+                .setClassName(mContext.getPackageName(), SubSettings.class.getName());
     }
 
     private PendingIntent getPrimaryAction() {
diff --git a/src/com/android/settings/homepage/contextualcards/deviceinfo/DeviceInfoSlice.java b/src/com/android/settings/homepage/contextualcards/deviceinfo/DeviceInfoSlice.java
index b8751f8..694336d 100644
--- a/src/com/android/settings/homepage/contextualcards/deviceinfo/DeviceInfoSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/deviceinfo/DeviceInfoSlice.java
@@ -17,7 +17,6 @@
 package com.android.settings.homepage.contextualcards.deviceinfo;
 
 import android.app.PendingIntent;
-import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.net.Uri;
@@ -39,8 +38,8 @@
 import com.android.settings.Utils;
 import com.android.settings.deviceinfo.DeviceModelPreferenceController;
 import com.android.settings.deviceinfo.aboutphone.MyDeviceInfoFragment;
+import com.android.settings.slices.CustomSliceRegistry;
 import com.android.settings.slices.CustomSliceable;
-import com.android.settings.slices.SettingsSliceProvider;
 import com.android.settings.slices.SliceBuilderUtils;
 import com.android.settingslib.DeviceInfoUtils;
 
@@ -49,20 +48,6 @@
 public class DeviceInfoSlice implements CustomSliceable {
     private static final String TAG = "DeviceInfoSlice";
 
-    /**
-     * The path denotes the unique name of device info slice
-     */
-    public static final String PATH_DEVICE_INFO = "device_info_card";
-
-    /**
-     * Backing Uri for the Device info Slice.
-     */
-    public static final Uri DEVICE_INFO_CARD_URI = new Uri.Builder()
-            .scheme(ContentResolver.SCHEME_CONTENT)
-            .authority(SettingsSliceProvider.SLICE_AUTHORITY)
-            .appendPath(PATH_DEVICE_INFO)
-            .build();
-
     private final Context mContext;
     private final SubscriptionManager mSubscriptionManager;
 
@@ -71,16 +56,15 @@
         mSubscriptionManager = mContext.getSystemService(SubscriptionManager.class);
     }
 
-    /**
-     * Return a device info slice bound to {@Link #DEVICE_INFO_CARD_URI}
-     */
     @Override
     public Slice getSlice() {
         final IconCompat icon = IconCompat.createWithResource(mContext,
                 R.drawable.ic_info_outline_24dp);
         final String title = mContext.getString(R.string.device_info_label);
-        final SliceAction primaryAction = new SliceAction(getPrimaryAction(), icon, title);
-        return new ListBuilder(mContext, DEVICE_INFO_CARD_URI, ListBuilder.INFINITY)
+        final SliceAction primaryAction = SliceAction.createDeeplink(getPrimaryAction(), icon,
+                ListBuilder.ICON_IMAGE, title);
+        return new ListBuilder(mContext, CustomSliceRegistry.DEVICE_INFO_SLICE_URI,
+                ListBuilder.INFINITY)
                 .setAccentColor((Utils.getColorAccentDefaultColor(mContext)))
                 .setHeader(new ListBuilder.HeaderBuilder().setTitle(title))
                 .addRow(new ListBuilder.RowBuilder()
@@ -92,18 +76,16 @@
 
     @Override
     public Uri getUri() {
-        return DEVICE_INFO_CARD_URI;
+        return CustomSliceRegistry.DEVICE_INFO_SLICE_URI;
     }
 
     @Override
     public Intent getIntent() {
         final String screenTitle = mContext.getText(R.string.device_info_label).toString();
-        final Uri contentUri = new Uri.Builder().appendPath(PATH_DEVICE_INFO).build();
         return SliceBuilderUtils.buildSearchResultPageIntent(mContext,
-                MyDeviceInfoFragment.class.getName(), PATH_DEVICE_INFO, screenTitle,
+                MyDeviceInfoFragment.class.getName(), "" /* key */, screenTitle,
                 MetricsProto.MetricsEvent.SLICE)
-                .setClassName(mContext.getPackageName(), SubSettings.class.getName())
-                .setData(contentUri);
+                .setClassName(mContext.getPackageName(), SubSettings.class.getName());
     }
 
     private PendingIntent getPrimaryAction() {
diff --git a/src/com/android/settings/homepage/contextualcards/deviceinfo/EmergencyInfoSlice.java b/src/com/android/settings/homepage/contextualcards/deviceinfo/EmergencyInfoSlice.java
index aff34f4..2484e53 100644
--- a/src/com/android/settings/homepage/contextualcards/deviceinfo/EmergencyInfoSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/deviceinfo/EmergencyInfoSlice.java
@@ -17,10 +17,8 @@
 package com.android.settings.homepage.contextualcards.deviceinfo;
 
 import android.app.PendingIntent;
-import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
-import android.net.Uri;
 
 import androidx.core.graphics.drawable.IconCompat;
 import androidx.slice.Slice;
@@ -28,39 +26,27 @@
 import androidx.slice.builders.SliceAction;
 
 import com.android.settings.R;
-import com.android.settings.slices.SettingsSliceProvider;
+import com.android.settings.slices.CustomSliceRegistry;
 
 // This is a slice helper class for EmergencyInfo
 public class EmergencyInfoSlice {
-    /**
-     * The path denotes the unique name of emergency info slice.
-     */
-    public static final String PATH_EMERGENCY_INFO_CARD = "emergency_info_card";
-
-    /**
-     * Backing Uri for the Emergency Info Slice.
-     */
-    public static final Uri EMERGENCY_INFO_CARD_URI = new Uri.Builder()
-            .scheme(ContentResolver.SCHEME_CONTENT)
-            .authority(SettingsSliceProvider.SLICE_AUTHORITY)
-            .appendPath(PATH_EMERGENCY_INFO_CARD)
-            .build();
 
     private static final String ACTION_EDIT_EMERGENCY_INFO = "android.settings.EDIT_EMERGENCY_INFO";
 
     public static Slice getSlice(Context context) {
-        final ListBuilder listBuilder = new ListBuilder(context, EMERGENCY_INFO_CARD_URI,
+        final ListBuilder listBuilder = new ListBuilder(context,
+                CustomSliceRegistry.EMERGENCY_INFO_SLICE_URI,
                 ListBuilder.INFINITY);
         listBuilder.addRow(
                 new ListBuilder.RowBuilder()
                         .setTitle(context.getText(R.string.emergency_info_title))
                         .setSubtitle(
                                 context.getText(R.string.emergency_info_contextual_card_summary))
-                        .setPrimaryAction(generatePrimaryAction(context)));
+                        .setPrimaryAction(createPrimaryAction(context)));
         return listBuilder.build();
     }
 
-    private static SliceAction generatePrimaryAction(Context context) {
+    private static SliceAction createPrimaryAction(Context context) {
         PendingIntent pendingIntent =
                 PendingIntent.getActivity(
                         context,
@@ -68,10 +54,10 @@
                         new Intent(ACTION_EDIT_EMERGENCY_INFO),
                         PendingIntent.FLAG_UPDATE_CURRENT);
 
-        return SliceAction.create(
+        return SliceAction.createDeeplink(
                 pendingIntent,
                 IconCompat.createWithResource(context, R.drawable.empty_icon),
-                ListBuilder.SMALL_IMAGE,
+                ListBuilder.ICON_IMAGE,
                 context.getText(R.string.emergency_info_title));
     }
 }
diff --git a/src/com/android/settings/homepage/contextualcards/deviceinfo/StorageSlice.java b/src/com/android/settings/homepage/contextualcards/deviceinfo/StorageSlice.java
index c61a8a0..eba831a 100644
--- a/src/com/android/settings/homepage/contextualcards/deviceinfo/StorageSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/deviceinfo/StorageSlice.java
@@ -17,7 +17,6 @@
 package com.android.settings.homepage.contextualcards.deviceinfo;
 
 import android.app.PendingIntent;
-import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.net.Uri;
@@ -36,8 +35,8 @@
 import com.android.settings.Utils;
 import com.android.settings.deviceinfo.StorageDashboardFragment;
 import com.android.settings.deviceinfo.storage.StorageSummaryDonutPreferenceController;
+import com.android.settings.slices.CustomSliceRegistry;
 import com.android.settings.slices.CustomSliceable;
-import com.android.settings.slices.SettingsSliceProvider;
 import com.android.settings.slices.SliceBuilderUtils;
 import com.android.settingslib.deviceinfo.PrivateStorageInfo;
 import com.android.settingslib.deviceinfo.StorageManagerVolumeProvider;
@@ -45,20 +44,6 @@
 public class StorageSlice implements CustomSliceable {
     private static final String TAG = "StorageSlice";
 
-    /**
-     * The path denotes the unique name of storage slicel
-     */
-    public static final String PATH_STORAGE_INFO = "storage_card";
-
-    /**
-     * Backing Uri for the storage slice.
-     */
-    public static final Uri STORAGE_CARD_URI = new Uri.Builder()
-            .scheme(ContentResolver.SCHEME_CONTENT)
-            .authority(SettingsSliceProvider.SLICE_AUTHORITY)
-            .appendPath(PATH_STORAGE_INFO)
-            .build();
-
     private final Context mContext;
 
     public StorageSlice(Context context) {
@@ -67,20 +52,19 @@
 
     @Override
     public Uri getUri() {
-        return STORAGE_CARD_URI;
+        return CustomSliceRegistry.STORAGE_SLICE_URI;
     }
 
-    /**
-     * Return a storage slice bound to {@link #STORAGE_CARD_URI}
-     */
     @Override
     public Slice getSlice() {
         final IconCompat icon = IconCompat.createWithResource(mContext,
                 R.drawable.ic_homepage_storage);
         final String title = mContext.getString(R.string.storage_label);
-        final SliceAction primaryAction = new SliceAction(getPrimaryAction(), icon, title);
+        final SliceAction primaryAction = SliceAction.createDeeplink(getPrimaryAction(), icon,
+                ListBuilder.ICON_IMAGE, title);
         final PrivateStorageInfo info = getPrivateStorageInfo();
-        return new ListBuilder(mContext, STORAGE_CARD_URI, ListBuilder.INFINITY)
+        return new ListBuilder(mContext, CustomSliceRegistry.STORAGE_SLICE_URI,
+                ListBuilder.INFINITY)
                 .setAccentColor(Utils.getColorAccentDefaultColor(mContext))
                 .setHeader(new ListBuilder.HeaderBuilder().setTitle(title))
                 .addRow(new ListBuilder.RowBuilder()
@@ -93,12 +77,10 @@
     @Override
     public Intent getIntent() {
         final String screenTitle = mContext.getText(R.string.storage_label).toString();
-        final Uri contentUri = new Uri.Builder().appendPath(PATH_STORAGE_INFO).build();
         return SliceBuilderUtils.buildSearchResultPageIntent(mContext,
-                StorageDashboardFragment.class.getName(), PATH_STORAGE_INFO, screenTitle,
+                StorageDashboardFragment.class.getName(), "" /* key */, screenTitle,
                 MetricsProto.MetricsEvent.SLICE)
-                .setClassName(mContext.getPackageName(), SubSettings.class.getName())
-                .setData(contentUri);
+                .setClassName(mContext.getPackageName(), SubSettings.class.getName());
     }
 
     private PendingIntent getPrimaryAction() {
diff --git a/src/com/android/settings/homepage/contextualcards/slices/BatteryFixSlice.java b/src/com/android/settings/homepage/contextualcards/slices/BatteryFixSlice.java
index 23ff172..403178c 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/BatteryFixSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/BatteryFixSlice.java
@@ -19,7 +19,6 @@
 import static android.content.Context.MODE_PRIVATE;
 
 import android.app.PendingIntent;
-import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
@@ -34,7 +33,6 @@
 import androidx.slice.builders.SliceAction;
 
 import com.android.internal.logging.nano.MetricsProto;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.os.BatteryStatsHelper;
 import com.android.settings.R;
 import com.android.settings.SubSettings;
@@ -42,9 +40,10 @@
 import com.android.settings.fuelgauge.BatteryStatsHelperLoader;
 import com.android.settings.fuelgauge.PowerUsageSummary;
 import com.android.settings.fuelgauge.batterytip.BatteryTipLoader;
+import com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController;
 import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
+import com.android.settings.slices.CustomSliceRegistry;
 import com.android.settings.slices.CustomSliceable;
-import com.android.settings.slices.SettingsSliceProvider;
 import com.android.settings.slices.SliceBackgroundWorker;
 import com.android.settings.slices.SliceBuilderUtils;
 import com.android.settingslib.utils.ThreadUtils;
@@ -53,20 +52,6 @@
 
 public class BatteryFixSlice implements CustomSliceable {
 
-    /**
-     * Unique name of Battery Fix Slice.
-     */
-    public static final String PATH_BATTERY_FIX = "battery_fix";
-
-    /**
-     * Uri for Battery Fix Slice.
-     */
-    public static final Uri BATTERY_FIX_URI = new Uri.Builder()
-            .scheme(ContentResolver.SCHEME_CONTENT)
-            .authority(SettingsSliceProvider.SLICE_AUTHORITY)
-            .appendPath(PATH_BATTERY_FIX)
-            .build();
-
     @VisibleForTesting
     static final String PREFS = "battery_fix_prefs";
     @VisibleForTesting
@@ -82,12 +67,9 @@
 
     @Override
     public Uri getUri() {
-        return BATTERY_FIX_URI;
+        return CustomSliceRegistry.BATTERY_FIX_SLICE_URI;
     }
 
-    /**
-     * Return a Slice bound to {@link #BATTERY_FIX_URI}.
-     */
     @Override
     public Slice getSlice() {
         IconCompat icon;
@@ -106,10 +88,12 @@
             for (BatteryTip batteryTip : batteryTips) {
                 if (batteryTip.getState() != BatteryTip.StateType.INVISIBLE) {
                     icon = IconCompat.createWithResource(mContext, batteryTip.getIconId());
-                    primaryAction = new SliceAction(getPrimaryAction(),
+                    primaryAction = SliceAction.createDeeplink(getPrimaryAction(),
                             icon,
+                            ListBuilder.ICON_IMAGE,
                             batteryTip.getTitle(mContext));
-                    slice = new ListBuilder(mContext, BATTERY_FIX_URI, ListBuilder.INFINITY)
+                    slice = new ListBuilder(mContext, CustomSliceRegistry.BATTERY_FIX_SLICE_URI,
+                            ListBuilder.INFINITY)
                             .setAccentColor(Utils.getColorAccentDefaultColor(mContext))
                             .addRow(new RowBuilder()
                                     .setTitle(batteryTip.getTitle(mContext))
@@ -124,8 +108,10 @@
             icon = IconCompat.createWithResource(mContext,
                     R.drawable.ic_battery_status_good_24dp);
             final String title = mContext.getString(R.string.power_usage_summary_title);
-            primaryAction = new SliceAction(getPrimaryAction(), icon, title);
-            slice = new ListBuilder(mContext, BATTERY_FIX_URI, ListBuilder.INFINITY)
+            primaryAction = SliceAction.createDeeplink(getPrimaryAction(), icon,
+                    ListBuilder.ICON_IMAGE, title);
+            slice = new ListBuilder(mContext, CustomSliceRegistry.BATTERY_FIX_SLICE_URI,
+                    ListBuilder.INFINITY)
                     .setAccentColor(Utils.getColorAccentDefaultColor(mContext))
                     .addRow(new RowBuilder()
                             .setTitle(title)
@@ -140,10 +126,11 @@
     public Intent getIntent() {
         final String screenTitle = mContext.getText(R.string.power_usage_summary_title)
                 .toString();
-        final Uri contentUri = new Uri.Builder().appendPath(PATH_BATTERY_FIX).build();
+        final Uri contentUri = new Uri.Builder()
+                .appendPath(BatteryTipPreferenceController.PREF_NAME).build();
 
         return SliceBuilderUtils.buildSearchResultPageIntent(mContext,
-                PowerUsageSummary.class.getName(), PATH_BATTERY_FIX,
+                PowerUsageSummary.class.getName(), BatteryTipPreferenceController.PREF_NAME,
                 screenTitle,
                 MetricsProto.MetricsEvent.SLICE)
                 .setClassName(mContext.getPackageName(), SubSettings.class.getName())
diff --git a/src/com/android/settings/homepage/contextualcards/slices/ConnectedDeviceSlice.java b/src/com/android/settings/homepage/contextualcards/slices/ConnectedDeviceSlice.java
index ef7c1bd..0c79b6b 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/ConnectedDeviceSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/ConnectedDeviceSlice.java
@@ -18,7 +18,6 @@
 
 import android.app.PendingIntent;
 import android.bluetooth.BluetoothAdapter;
-import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.Bitmap;
@@ -43,8 +42,8 @@
 import com.android.settings.bluetooth.BluetoothDeviceDetailsFragment;
 import com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment;
 import com.android.settings.core.SubSettingLauncher;
+import com.android.settings.slices.CustomSliceRegistry;
 import com.android.settings.slices.CustomSliceable;
-import com.android.settings.slices.SettingsSliceProvider;
 import com.android.settings.slices.SliceBuilderUtils;
 import com.android.settingslib.bluetooth.BluetoothUtils;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
@@ -68,20 +67,6 @@
 public class ConnectedDeviceSlice implements CustomSliceable {
 
     /**
-     * The path denotes the unique name of Connected device Slice.
-     */
-    public static final String PATH_CONNECTED_DEVICE = "connected_device";
-
-    /**
-     * Backing Uri for Connected device Slice.
-     */
-    public static final Uri CONNECTED_DEVICE_URI = new Uri.Builder()
-            .scheme(ContentResolver.SCHEME_CONTENT)
-            .authority(SettingsSliceProvider.SLICE_AUTHORITY)
-            .appendPath(PATH_CONNECTED_DEVICE)
-            .build();
-
-    /**
      * To sort the Bluetooth devices by {@link CachedBluetoothDevice}.
      * Refer compareTo method from {@link com.android.settings.bluetooth.BluetoothDevicePreference}.
      */
@@ -109,25 +94,23 @@
 
     @Override
     public Uri getUri() {
-        return CONNECTED_DEVICE_URI;
+        return CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI;
     }
 
-    /**
-     * Return a Connected Device Slice bound to {@link #CONNECTED_DEVICE_URI}.
-     */
     @Override
     public Slice getSlice() {
         final IconCompat icon = IconCompat.createWithResource(mContext,
                 R.drawable.ic_homepage_connected_device);
-        final CharSequence title = mContext.getText(R.string.connected_devices_dashboard_title);
+        final CharSequence title = mContext.getText(R.string.bluetooth_connected_devices);
         final CharSequence titleNoConnectedDevices = mContext.getText(
                 R.string.no_connected_devices);
         final PendingIntent primaryActionIntent = PendingIntent.getActivity(mContext, 0,
                 getIntent(), 0);
-        final SliceAction primarySliceAction = new SliceAction(primaryActionIntent, icon,
-                title);
+        final SliceAction primarySliceAction = SliceAction.createDeeplink(primaryActionIntent, icon,
+                ListBuilder.ICON_IMAGE, title);
         final ListBuilder listBuilder =
-                new ListBuilder(mContext, CONNECTED_DEVICE_URI, ListBuilder.INFINITY)
+                new ListBuilder(mContext, CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI,
+                        ListBuilder.INFINITY)
                         .setAccentColor(Utils.getColorAccentDefaultColor(mContext));
 
         // Get row builders by connected devices, e.g. Bluetooth.
@@ -159,14 +142,12 @@
     public Intent getIntent() {
         final String screenTitle = mContext.getText(R.string.connected_devices_dashboard_title)
                 .toString();
-        final Uri contentUri = new Uri.Builder().appendPath(PATH_CONNECTED_DEVICE).build();
 
         return SliceBuilderUtils.buildSearchResultPageIntent(mContext,
-                ConnectedDeviceDashboardFragment.class.getName(), PATH_CONNECTED_DEVICE,
+                ConnectedDeviceDashboardFragment.class.getName(), "" /* key */,
                 screenTitle,
                 MetricsProto.MetricsEvent.SLICE)
-                .setClassName(mContext.getPackageName(), SubSettings.class.getName())
-                .setData(contentUri);
+                .setClassName(mContext.getPackageName(), SubSettings.class.getName());
     }
 
     @Override
@@ -251,9 +232,10 @@
     }
 
     private SliceAction buildBluetoothDetailDeepLinkAction(CachedBluetoothDevice bluetoothDevice) {
-        return new SliceAction(
+        return SliceAction.createDeeplink(
                 getBluetoothDetailIntent(bluetoothDevice),
                 IconCompat.createWithResource(mContext, R.drawable.ic_settings),
+                ListBuilder.ICON_IMAGE,
                 bluetoothDevice.getName());
     }
 
diff --git a/src/com/android/settings/homepage/contextualcards/slices/LowStorageSlice.java b/src/com/android/settings/homepage/contextualcards/slices/LowStorageSlice.java
index 7f6efcc..3cbbb0c 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/LowStorageSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/LowStorageSlice.java
@@ -17,13 +17,11 @@
 package com.android.settings.homepage.contextualcards.slices;
 
 import android.app.PendingIntent;
-import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.net.Uri;
 import android.os.storage.StorageManager;
 import android.text.format.Formatter;
-import android.util.Log;
 
 import androidx.core.graphics.drawable.IconCompat;
 import androidx.slice.Slice;
@@ -36,8 +34,8 @@
 import com.android.settings.SubSettings;
 import com.android.settings.Utils;
 import com.android.settings.deviceinfo.StorageSettings;
+import com.android.settings.slices.CustomSliceRegistry;
 import com.android.settings.slices.CustomSliceable;
-import com.android.settings.slices.SettingsSliceProvider;
 import com.android.settings.slices.SliceBuilderUtils;
 import com.android.settingslib.deviceinfo.PrivateStorageInfo;
 import com.android.settingslib.deviceinfo.StorageManagerVolumeProvider;
@@ -47,23 +45,7 @@
 public class LowStorageSlice implements CustomSliceable {
 
     /**
-     * The path denotes the unique name of Low storage Slice.
-     */
-    public static final String PATH_LOW_STORAGE = "low_storage";
-
-    /**
-     * Backing Uri for Low storage Slice.
-     */
-    public static final Uri LOW_STORAGE_URI = new Uri.Builder()
-            .scheme(ContentResolver.SCHEME_CONTENT)
-            .authority(SettingsSliceProvider.SLICE_AUTHORITY)
-            .appendPath(PATH_LOW_STORAGE)
-            .build();
-
-    private static final String TAG = "LowStorageSlice";
-
-    /**
-     * If user used >= 85% storage.
+     * If used storage >= 85%, it would be low storage.
      */
     private static final double LOW_STORAGE_THRESHOLD = 0.85;
 
@@ -73,54 +55,45 @@
         mContext = context;
     }
 
-    /**
-     * Return a Low storage Slice bound to {@link #LOW_STORAGE_URI}
-     */
     @Override
     public Slice getSlice() {
-        // Get current storage percentage from StorageManager.
+        // Get used storage percentage from StorageManager.
         final PrivateStorageInfo info = PrivateStorageInfo.getPrivateStorageInfo(
                 new StorageManagerVolumeProvider(mContext.getSystemService(StorageManager.class)));
-        final double currentStoragePercentage =
-                (double) (info.totalBytes - info.freeBytes) / info.totalBytes;
+        final double usedPercentage = (double) (info.totalBytes - info.freeBytes) / info.totalBytes;
 
-        // Used storage < 85%. NOT show Low storage Slice.
-        if (currentStoragePercentage < LOW_STORAGE_THRESHOLD) {
-            /**
-             * TODO(b/114808204): Contextual Home Page - "Low Storage"
-             * The behavior is under decision making, will update new behavior or remove TODO later.
-             */
-            Log.i(TAG, "Not show low storage slice, not match condition.");
-            return null;
+        // Generate Low storage Slice.
+        final String percentageString = NumberFormat.getPercentInstance().format(usedPercentage);
+        final String freeSizeString = Formatter.formatFileSize(mContext, info.freeBytes);
+        final ListBuilder listBuilder = new ListBuilder(mContext,
+                CustomSliceRegistry.LOW_STORAGE_SLICE_URI, ListBuilder.INFINITY).setAccentColor(
+                Utils.getColorAccentDefaultColor(mContext));
+        final IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.ic_storage);
+
+        if (usedPercentage < LOW_STORAGE_THRESHOLD) {
+            // For clients that ignore error checking, a generic storage slice will be given.
+            final CharSequence titleStorage = mContext.getText(R.string.storage_settings);
+            final String summaryStorage = mContext.getString(R.string.storage_summary,
+                    percentageString, freeSizeString);
+
+            return listBuilder
+                    .addRow(buildRowBuilder(titleStorage, summaryStorage, icon))
+                    .setIsError(true)
+                    .build();
         }
 
-        // Show Low storage Slice.
-        final IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.ic_storage);
-        final CharSequence title = mContext.getText(R.string.storage_menu_free);
-        final SliceAction primarySliceAction = new SliceAction(
-                PendingIntent.getActivity(mContext, 0, getIntent(), 0), icon, title);
-        final String lowStorageSummary = mContext.getString(R.string.low_storage_summary,
-                NumberFormat.getPercentInstance().format(currentStoragePercentage),
-                Formatter.formatFileSize(mContext, info.freeBytes));
+        final CharSequence titleLowStorage = mContext.getText(R.string.storage_menu_free);
+        final String summaryLowStorage = mContext.getString(R.string.low_storage_summary,
+                percentageString, freeSizeString);
 
-        /**
-         * TODO(b/114808204): Contextual Home Page - "Low Storage"
-         * Slices doesn't support "Icon on the left" in header. Now we intend to start with Icon
-         * right aligned. Will update the icon to left until Slices support it.
-         */
-        return new ListBuilder(mContext, LOW_STORAGE_URI, ListBuilder.INFINITY)
-                .setAccentColor(Utils.getColorAccentDefaultColor(mContext))
-                .addRow(new RowBuilder()
-                        .setTitle(title)
-                        .setSubtitle(lowStorageSummary)
-                        .addEndItem(icon, ListBuilder.ICON_IMAGE)
-                        .setPrimaryAction(primarySliceAction))
+        return listBuilder
+                .addRow(buildRowBuilder(titleLowStorage, summaryLowStorage, icon))
                 .build();
     }
 
     @Override
     public Uri getUri() {
-        return LOW_STORAGE_URI;
+        return CustomSliceRegistry.LOW_STORAGE_SLICE_URI;
     }
 
     @Override
@@ -132,13 +105,28 @@
     public Intent getIntent() {
         final String screenTitle = mContext.getText(R.string.storage_label)
                 .toString();
-        final Uri contentUri = new Uri.Builder().appendPath(PATH_LOW_STORAGE).build();
 
         return SliceBuilderUtils.buildSearchResultPageIntent(mContext,
-                StorageSettings.class.getName(), PATH_LOW_STORAGE,
+                StorageSettings.class.getName(), "" /* key */,
                 screenTitle,
                 MetricsProto.MetricsEvent.SLICE)
-                .setClassName(mContext.getPackageName(), SubSettings.class.getName())
-                .setData(contentUri);
+                .setClassName(mContext.getPackageName(), SubSettings.class.getName());
+    }
+
+    private RowBuilder buildRowBuilder(CharSequence title, String summary, IconCompat icon) {
+        final SliceAction primarySliceAction = SliceAction.createDeeplink(
+                PendingIntent.getActivity(mContext, 0, getIntent(), 0), icon,
+                ListBuilder.ICON_IMAGE, title);
+
+        /**
+         * TODO(b/114808204): Contextual Home Page - "Low Storage"
+         * Slices doesn't support "Icon on the left" in header. Now we intend to start with Icon
+         * right aligned. Will update the icon to left until Slices support it.
+         */
+        return new RowBuilder()
+                .setTitle(title)
+                .setSubtitle(summary)
+                .addEndItem(icon, ListBuilder.ICON_IMAGE)
+                .setPrimaryAction(primarySliceAction);
     }
 }
\ No newline at end of file
diff --git a/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardController.java b/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardController.java
index f1fbc9c..4378be3 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardController.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardController.java
@@ -17,12 +17,19 @@
 package com.android.settings.homepage.contextualcards.slices;
 
 import android.content.Context;
+import android.content.Intent;
+import android.text.TextUtils;
 
-import com.android.settings.homepage.contextualcards.CardContentProvider;
+import androidx.annotation.VisibleForTesting;
+
+import com.android.settings.R;
 import com.android.settings.homepage.contextualcards.CardDatabaseHelper;
 import com.android.settings.homepage.contextualcards.ContextualCard;
 import com.android.settings.homepage.contextualcards.ContextualCardController;
+import com.android.settings.homepage.contextualcards.ContextualCardFeatureProvider;
+import com.android.settings.homepage.contextualcards.ContextualCardFeedbackDialog;
 import com.android.settings.homepage.contextualcards.ContextualCardUpdateListener;
+import com.android.settings.overlay.FeatureFactory;
 import com.android.settingslib.utils.ThreadUtils;
 
 /**
@@ -32,7 +39,8 @@
 
     private static final String TAG = "SliceCardController";
 
-    private Context mContext;
+    private final Context mContext;
+
     private ContextualCardUpdateListener mCardUpdateListener;
 
     public SliceContextualCardController(Context context) {
@@ -51,7 +59,7 @@
 
     @Override
     public void onActionClick(ContextualCard card) {
-        //TODO(b/113783548): Implement feedback mechanism
+
     }
 
     @Override
@@ -60,10 +68,33 @@
             final CardDatabaseHelper dbHelper = CardDatabaseHelper.getInstance(mContext);
             dbHelper.markContextualCardAsDismissed(mContext, card.getName());
         });
+        showFeedbackDialog(card);
+        final ContextualCardFeatureProvider contexualCardFeatureProvider =
+                FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider();
+        contexualCardFeatureProvider.logContextualCardDismiss(mContext, card);
     }
 
     @Override
     public void setCardUpdateListener(ContextualCardUpdateListener listener) {
         mCardUpdateListener = listener;
     }
+
+    @VisibleForTesting
+    void showFeedbackDialog(ContextualCard card) {
+        final String email = mContext.getString(R.string.config_contextual_card_feedback_email);
+        if (TextUtils.isEmpty(email)) {
+            return;
+        }
+        final Intent feedbackIntent = new Intent(mContext, ContextualCardFeedbackDialog.class);
+        feedbackIntent.putExtra(ContextualCardFeedbackDialog.EXTRA_CARD_NAME,
+                getSimpleCardName(card));
+        feedbackIntent.putExtra(ContextualCardFeedbackDialog.EXTRA_FEEDBACK_EMAIL, email);
+        feedbackIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        mContext.startActivity(feedbackIntent);
+    }
+
+    private String getSimpleCardName(ContextualCard card) {
+        final String[] split = card.getName().split("/");
+        return split[split.length - 1];
+    }
 }
diff --git a/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java b/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java
index 74f25eb..a2d6e2b 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.net.Uri;
 import android.util.ArrayMap;
+import android.util.ArraySet;
 import android.util.Log;
 import android.view.View;
 import android.widget.Button;
@@ -38,10 +39,13 @@
 
 import com.android.settings.R;
 import com.android.settings.homepage.contextualcards.ContextualCard;
+import com.android.settings.homepage.contextualcards.ContextualCardFeatureProvider;
 import com.android.settings.homepage.contextualcards.ContextualCardRenderer;
 import com.android.settings.homepage.contextualcards.ControllerRendererPool;
+import com.android.settings.overlay.FeatureFactory;
 
 import java.util.Map;
+import java.util.Set;
 
 /**
  * Card renderer for {@link ContextualCard} built as slices.
@@ -58,6 +62,7 @@
     private final Context mContext;
     private final LifecycleOwner mLifecycleOwner;
     private final ControllerRendererPool mControllerRendererPool;
+    private final Set<ContextualCard> mCardSet;
 
     public SliceContextualCardRenderer(Context context, LifecycleOwner lifecycleOwner,
             ControllerRendererPool controllerRendererPool) {
@@ -65,6 +70,7 @@
         mLifecycleOwner = lifecycleOwner;
         mSliceLiveDataMap = new ArrayMap<>();
         mControllerRendererPool = controllerRendererPool;
+        mCardSet = new ArraySet<>();
     }
 
     @Override
@@ -99,6 +105,7 @@
             sliceLiveData = SliceLiveData.fromUri(mContext, uri);
             mSliceLiveDataMap.put(uri.toString(), sliceLiveData);
         }
+        mCardSet.add(card);
 
         sliceLiveData.removeObservers(mLifecycleOwner);
         sliceLiveData.observe(mLifecycleOwner, slice -> {
@@ -128,14 +135,27 @@
 
         final Button btnRemove = cardHolder.itemView.findViewById(R.id.remove);
         btnRemove.setOnClickListener(v -> {
-            mControllerRendererPool.getController(mContext, card.getCardType()).onDismissed(
-                    card);
+            mControllerRendererPool.getController(mContext, card.getCardType()).onDismissed(card);
         });
     }
 
     @Override
     public void onSliceAction(@NonNull EventInfo eventInfo, @NonNull SliceItem sliceItem) {
         //TODO(b/79698338): Log user interaction
+
+        // sliceItem.getSlice().getUri() is like
+        // content://android.settings.slices/action/wifi/_gen/0/_gen/0
+        // contextualCard.getSliceUri() is prefix of sliceItem.getSlice().getUri()
+        for (ContextualCard card : mCardSet) {
+            if (sliceItem.getSlice().getUri().toString().startsWith(
+                    card.getSliceUri().toString())) {
+                ContextualCardFeatureProvider contexualCardFeatureProvider =
+                        FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider();
+                contexualCardFeatureProvider.logContextualCardClick(mContext, card,
+                        eventInfo.rowIndex, eventInfo.actionType);
+                break;
+            }
+        }
     }
 
     public static class SliceViewHolder extends RecyclerView.ViewHolder {
diff --git a/src/com/android/settings/location/LocationSliceBuilder.java b/src/com/android/settings/location/LocationSliceBuilder.java
index 56cf676..f70d09b 100644
--- a/src/com/android/settings/location/LocationSliceBuilder.java
+++ b/src/com/android/settings/location/LocationSliceBuilder.java
@@ -23,11 +23,9 @@
 
 import android.annotation.ColorInt;
 import android.app.PendingIntent;
-import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.net.Uri;
-import android.provider.SettingsSlicesContract;
 
 import androidx.core.graphics.drawable.IconCompat;
 import androidx.slice.Slice;
@@ -39,6 +37,7 @@
 import com.android.settings.R;
 import com.android.settings.SubSettings;
 import com.android.settings.Utils;
+import com.android.settings.slices.CustomSliceRegistry;
 import com.android.settings.slices.SliceBuilderUtils;
 
 /**
@@ -46,21 +45,11 @@
  */
 public class LocationSliceBuilder {
 
-    /**
-     * Backing Uri for the Location Slice.
-     */
-    public static final Uri LOCATION_URI = new Uri.Builder()
-            .scheme(ContentResolver.SCHEME_CONTENT)
-            .authority(SettingsSlicesContract.AUTHORITY)
-            .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
-            .appendPath(KEY_LOCATION)
-            .build();
-
     private LocationSliceBuilder() {
     }
 
     /**
-     * Return a Location Slice bound to {@link #LOCATION_URI}.
+     * Return a Location Slice bound to {@link CustomSliceRegistry#LOCATION_SLICE_URI}.
      */
     public static Slice getSlice(Context context) {
         final IconCompat icon = IconCompat.createWithResource(context,
@@ -68,9 +57,11 @@
         final String title = context.getString(R.string.location_settings_title);
         @ColorInt final int color = Utils.getColorAccentDefaultColor(context);
         final PendingIntent primaryAction = getPrimaryAction(context);
-        final SliceAction primarySliceAction = new SliceAction(primaryAction, icon, title);
+        final SliceAction primarySliceAction = SliceAction.createDeeplink(primaryAction, icon,
+                ListBuilder.ICON_IMAGE, title);
 
-        return new ListBuilder(context, LOCATION_URI, ListBuilder.INFINITY)
+        return new ListBuilder(context, CustomSliceRegistry.LOCATION_SLICE_URI,
+                ListBuilder.INFINITY)
                 .setAccentColor(color)
                 .addRow(new RowBuilder()
                         .setTitle(title)
diff --git a/src/com/android/settings/network/telephony/Enhanced4gLteSliceHelper.java b/src/com/android/settings/network/telephony/Enhanced4gLteSliceHelper.java
index b198f92..be5d948 100644
--- a/src/com/android/settings/network/telephony/Enhanced4gLteSliceHelper.java
+++ b/src/com/android/settings/network/telephony/Enhanced4gLteSliceHelper.java
@@ -19,7 +19,6 @@
 import static android.app.slice.Slice.EXTRA_TOGGLE_STATE;
 
 import android.app.PendingIntent;
-import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
@@ -40,9 +39,8 @@
 import com.android.ims.ImsManager;
 import com.android.settings.R;
 import com.android.settings.Utils;
-import com.android.settings.slices.SettingsSliceProvider;
+import com.android.settings.slices.CustomSliceRegistry;
 import com.android.settings.slices.SliceBroadcastReceiver;
-import com.android.settings.slices.SliceBuilderUtils;
 
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
@@ -57,12 +55,7 @@
  */
 public class Enhanced4gLteSliceHelper {
 
-    private static final String TAG = "Enhanced4gLteSliceHelper";
-
-    /**
-     * Settings slice path to enhanced 4g LTE setting.
-     */
-    public static final String PATH_ENHANCED_4G_LTE = "enhanced_4g_lte";
+    private static final String TAG = "Enhanced4gLteSlice";
 
     /**
      * Action passed for changes to enhanced 4g LTE slice (toggle).
@@ -71,14 +64,6 @@
             "com.android.settings.mobilenetwork.action.ENHANCED_4G_LTE_CHANGED";
 
     /**
-     * Slice Uri for Enhanced 4G slice
-     */
-    public static final Uri SLICE_URI = new Uri.Builder()
-            .scheme(ContentResolver.SCHEME_CONTENT)
-            .authority(SettingsSliceProvider.SLICE_AUTHORITY)
-            .appendPath(PATH_ENHANCED_4G_LTE)
-            .build();
-    /**
      * Action for mobile network settings activity which
      * allows setting configuration for Enhanced 4G LTE
      * related settings
@@ -107,7 +92,7 @@
      * Enhanced 4g lte mode title variant resource name
      */
     private static final String RESOURCE_ENHANCED_4G_LTE_MODE_TITLE_VARIANT =
-          "enhanced_4g_lte_mode_title_variant";
+            "enhanced_4g_lte_mode_title_variant";
 
     @VisibleForTesting
     public Enhanced4gLteSliceHelper(Context context) {
@@ -187,13 +172,15 @@
                 .addRow(new RowBuilder()
                         .setTitle(getEnhanced4glteModeTitle(subId))
                         .addEndItem(
-                                new SliceAction(
+                                SliceAction.createToggle(
                                         getBroadcastIntent(ACTION_ENHANCED_4G_LTE_CHANGED),
                                         null /* actionTitle */, isEnhanced4gLteEnabled))
-                        .setPrimaryAction(new SliceAction(
-                                getActivityIntent(ACTION_MOBILE_NETWORK_SETTINGS_ACTIVITY),
-                                icon,
-                                getEnhanced4glteModeTitle(subId))))
+                        .setPrimaryAction(
+                                SliceAction.createDeeplink(
+                                        getActivityIntent(ACTION_MOBILE_NETWORK_SETTINGS_ACTIVITY),
+                                        icon,
+                                        ListBuilder.ICON_IMAGE,
+                                        getEnhanced4glteModeTitle(subId))))
                 .build();
     }
 
@@ -225,8 +212,7 @@
         }
         // notify change in slice in any case to get re-queried. This would result in displaying
         // appropriate message with the updated setting.
-        final Uri uri = SliceBuilderUtils.getUri(PATH_ENHANCED_4G_LTE, false /*isPlatformSlice*/);
-        mContext.getContentResolver().notifyChange(uri, null);
+        mContext.getContentResolver().notifyChange(CustomSliceRegistry.ENHANCED_4G_SLICE_URI, null);
     }
 
     private CharSequence getEnhanced4glteModeTitle(int subId) {
diff --git a/src/com/android/settings/notification/AbstractZenModeAutomaticRulePreferenceController.java b/src/com/android/settings/notification/AbstractZenModeAutomaticRulePreferenceController.java
index 5b4c245..d0f1ee6 100644
--- a/src/com/android/settings/notification/AbstractZenModeAutomaticRulePreferenceController.java
+++ b/src/com/android/settings/notification/AbstractZenModeAutomaticRulePreferenceController.java
@@ -25,7 +25,6 @@
 import android.content.pm.ServiceInfo;
 import android.provider.Settings;
 import android.service.notification.ConditionProviderService;
-import android.service.notification.ZenModeConfig;
 
 import androidx.fragment.app.Fragment;
 import androidx.preference.Preference;
@@ -34,20 +33,15 @@
 import com.android.settings.core.PreferenceControllerMixin;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.List;
 import java.util.Map;
-import java.util.Set;
 
 abstract public class AbstractZenModeAutomaticRulePreferenceController extends
         AbstractZenModePreferenceController implements PreferenceControllerMixin {
 
     protected ZenModeBackend mBackend;
     protected Fragment mParent;
-    protected Set<Map.Entry<String, AutomaticZenRule>> mRules;
+    protected Map.Entry<String, AutomaticZenRule>[] mRules;
     protected PackageManager mPm;
-    private static List<String> mDefaultRuleIds;
 
     public AbstractZenModeAutomaticRulePreferenceController(Context context, String key, Fragment
             parent, Lifecycle lifecycle) {
@@ -60,20 +54,14 @@
     @Override
     public void updateState(Preference preference) {
         super.updateState(preference);
-        mRules = getZenModeRules();
+        mRules = mBackend.getAutomaticZenRules();
     }
 
-    private static List<String> getDefaultRuleIds() {
-        if (mDefaultRuleIds == null) {
-            mDefaultRuleIds = ZenModeConfig.DEFAULT_RULE_IDS;
+    protected Map.Entry<String, AutomaticZenRule>[] getRules() {
+        if (mRules == null) {
+            mRules = mBackend.getAutomaticZenRules();
         }
-        return mDefaultRuleIds;
-    }
-
-    private Set<Map.Entry<String, AutomaticZenRule>> getZenModeRules() {
-        Map<String, AutomaticZenRule> ruleMap =
-                NotificationManager.from(mContext).getAutomaticZenRules();
-        return ruleMap.entrySet();
+        return mRules;
     }
 
     protected void showNameRuleDialog(final ZenRuleInfo ri, Fragment parent) {
@@ -81,16 +69,6 @@
                 RuleNameChangeListener(ri));
     }
 
-    protected Map.Entry<String, AutomaticZenRule>[] sortedRules() {
-        if (mRules == null) {
-            mRules = getZenModeRules();
-        }
-        final Map.Entry<String, AutomaticZenRule>[] rt =
-                mRules.toArray(new Map.Entry[mRules.size()]);
-        Arrays.sort(rt, RULE_COMPARATOR);
-        return rt;
-    }
-
     protected static Intent getRuleIntent(String settingsAction,
             ComponentName configurationActivity, String ruleId) {
         final Intent intent = new Intent()
@@ -104,35 +82,6 @@
         return intent;
     }
 
-    private static final Comparator<Map.Entry<String, AutomaticZenRule>> RULE_COMPARATOR =
-            new Comparator<Map.Entry<String, AutomaticZenRule>>() {
-                @Override
-                public int compare(Map.Entry<String, AutomaticZenRule> lhs,
-                        Map.Entry<String, AutomaticZenRule> rhs) {
-                    // if it's a default rule, should be at the top of automatic rules
-                    boolean lhsIsDefaultRule = getDefaultRuleIds().contains(lhs.getKey());
-                    boolean rhsIsDefaultRule = getDefaultRuleIds().contains(rhs.getKey());
-                    if (lhsIsDefaultRule != rhsIsDefaultRule) {
-                        return lhsIsDefaultRule ? -1 : 1;
-                    }
-
-                    int byDate = Long.compare(lhs.getValue().getCreationTime(),
-                            rhs.getValue().getCreationTime());
-                    if (byDate != 0) {
-                        return byDate;
-                    } else {
-                        return key(lhs.getValue()).compareTo(key(rhs.getValue()));
-                    }
-                }
-
-                private String key(AutomaticZenRule rule) {
-                    final int type = ZenModeConfig.isValidScheduleConditionId(rule.getConditionId())
-                            ? 1 : ZenModeConfig.isValidEventConditionId(rule.getConditionId())
-                            ? 2 : 3;
-                    return type + rule.getName().toString();
-                }
-            };
-
     public static ZenRuleInfo getRuleInfo(PackageManager pm, ServiceInfo si) {
         if (si == null || si.metaData == null) {
             return null;
diff --git a/src/com/android/settings/notification/ZenAutomaticRuleHeaderPreferenceController.java b/src/com/android/settings/notification/ZenAutomaticRuleHeaderPreferenceController.java
index 72bb0e3..c2db773 100644
--- a/src/com/android/settings/notification/ZenAutomaticRuleHeaderPreferenceController.java
+++ b/src/com/android/settings/notification/ZenAutomaticRuleHeaderPreferenceController.java
@@ -136,7 +136,7 @@
                     MetricsProto.MetricsEvent.ACTION_ZEN_MODE_RULE_NAME_CHANGE_OK);
             mRule.setName(ruleName);
             mRule.setModified(true);
-            mBackend.setZenRule(mId, mRule);
+            mBackend.updateZenRule(mId, mRule);
         }
     }
 }
diff --git a/src/com/android/settings/notification/ZenAutomaticRuleSwitchPreferenceController.java b/src/com/android/settings/notification/ZenAutomaticRuleSwitchPreferenceController.java
index f38deb3..e5ca754 100644
--- a/src/com/android/settings/notification/ZenAutomaticRuleSwitchPreferenceController.java
+++ b/src/com/android/settings/notification/ZenAutomaticRuleSwitchPreferenceController.java
@@ -88,6 +88,6 @@
         final boolean enabled = isChecked;
         if (enabled == mRule.isEnabled()) return;
         mRule.setEnabled(enabled);
-        mBackend.setZenRule(mId, mRule);
+        mBackend.updateZenRule(mId, mRule);
     }
 }
diff --git a/src/com/android/settings/notification/ZenModeAlarmsPreferenceController.java b/src/com/android/settings/notification/ZenModeAlarmsPreferenceController.java
index 67d9e93..b877668 100644
--- a/src/com/android/settings/notification/ZenModeAlarmsPreferenceController.java
+++ b/src/com/android/settings/notification/ZenModeAlarmsPreferenceController.java
@@ -21,12 +21,12 @@
 import android.provider.Settings;
 import android.util.Log;
 
-import com.android.internal.logging.nano.MetricsProto;
-import com.android.settingslib.core.lifecycle.Lifecycle;
-
 import androidx.preference.Preference;
 import androidx.preference.SwitchPreference;
 
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
 public class ZenModeAlarmsPreferenceController extends
         AbstractZenModePreferenceController implements Preference.OnPreferenceChangeListener {
 
@@ -78,6 +78,7 @@
         mMetricsFeatureProvider.action(mContext, MetricsProto.MetricsEvent.ACTION_ZEN_ALLOW_ALARMS,
                 allowAlarms);
         mBackend.saveSoundPolicy(Policy.PRIORITY_CATEGORY_ALARMS, allowAlarms);
+
         return true;
     }
 }
diff --git a/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceController.java b/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceController.java
index 7679b0b..615b26c 100644
--- a/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceController.java
+++ b/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceController.java
@@ -28,6 +28,7 @@
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
 import java.util.Map;
+import java.util.Objects;
 
 public class ZenModeAutomaticRulesPreferenceController extends
         AbstractZenModeAutomaticRulePreferenceController {
@@ -62,16 +63,40 @@
     @Override
     public void updateState(Preference preference) {
         super.updateState(preference);
+        Map.Entry<String, AutomaticZenRule>[] sortedRules = getRules();
+        final int currNumPreferences = mPreferenceCategory.getPreferenceCount();
+        if (currNumPreferences == sortedRules.length) {
+            for (int i = 0; i < sortedRules.length; i++) {
+                ZenRulePreference pref = (ZenRulePreference) mPreferenceCategory.getPreference(i);
+                // we are either:
+                // 1. updating the enabled state or name of the rule
+                // 2. rule was added or deleted, so reload the entire list
+                if (Objects.equals(pref.mId, sortedRules[i].getKey())) {
+                    AutomaticZenRule rule = sortedRules[i].getValue();
+                    pref.setName(rule.getName());
+                    pref.setChecked(rule.isEnabled());
+                } else {
+                    reloadAllRules(sortedRules);
+                    break;
+                }
+            }
+        } else {
+            reloadAllRules(sortedRules);
+        }
+    }
 
+    @VisibleForTesting
+    void reloadAllRules(Map.Entry<String, AutomaticZenRule>[] rules) {
         mPreferenceCategory.removeAll();
-        Map.Entry<String, AutomaticZenRule>[] sortedRules = sortedRules();
-        for (Map.Entry<String, AutomaticZenRule> sortedRule : sortedRules) {
-            ZenRulePreference pref = new ZenRulePreference(mPreferenceCategory.getContext(),
-                    sortedRule, mParent, mMetricsFeatureProvider);
+        for (Map.Entry<String, AutomaticZenRule> rule : rules) {
+            ZenRulePreference pref = createZenRulePreference(rule);
             mPreferenceCategory.addPreference(pref);
         }
     }
+
+    @VisibleForTesting
+    ZenRulePreference createZenRulePreference(Map.Entry<String, AutomaticZenRule> rule) {
+        return new ZenRulePreference(mPreferenceCategory.getContext(),
+                rule, mParent, mMetricsFeatureProvider);
+    }
 }
-
-
-
diff --git a/src/com/android/settings/notification/ZenModeAutomationSettings.java b/src/com/android/settings/notification/ZenModeAutomationSettings.java
index 44bc5f1..c559a28 100644
--- a/src/com/android/settings/notification/ZenModeAutomationSettings.java
+++ b/src/com/android/settings/notification/ZenModeAutomationSettings.java
@@ -16,9 +16,15 @@
 
 package com.android.settings.notification;
 
+import android.app.AlertDialog;
+import android.app.AutomaticZenRule;
 import android.content.Context;
+import android.content.DialogInterface;
 import android.provider.SearchIndexableResource;
 import android.service.notification.ConditionProviderService;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
 
 import androidx.fragment.app.Fragment;
 
@@ -34,10 +40,14 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 
 @SearchIndexable
 public class ZenModeAutomationSettings extends ZenModeSettingsBase {
     protected final ManagedServiceSettings.Config CONFIG = getConditionProviderConfig();
+    private CharSequence[] mDeleteDialogRuleNames;
+    private String[] mDeleteDialogRuleIds;
+    private boolean[] mDeleteDialogChecked;
 
     @Override
     protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
@@ -74,6 +84,52 @@
                 .setNoun("condition provider")
                 .build();
     }
+    private final int DELETE_RULES = 1;
+
+    @Override
+    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+        menu.add(Menu.NONE, DELETE_RULES, Menu.NONE, R.string.zen_mode_delete_automatic_rules);
+        super.onCreateOptionsMenu(menu, inflater);
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        switch (item.getItemId()) {
+            case DELETE_RULES:
+                Map.Entry<String, AutomaticZenRule>[] rules = mBackend.getAutomaticZenRules();
+                mDeleteDialogRuleNames = new CharSequence[rules.length];
+                mDeleteDialogRuleIds = new String[rules.length];
+                mDeleteDialogChecked = new boolean[rules.length];
+                for (int i = 0; i < rules.length; i++) {
+                    mDeleteDialogRuleNames[i] = rules[i].getValue().getName();
+                    mDeleteDialogRuleIds[i] = rules[i].getKey();
+                }
+                new AlertDialog.Builder(mContext)
+                        .setTitle(R.string.zen_mode_delete_automatic_rules)
+                        .setMultiChoiceItems(mDeleteDialogRuleNames, null,
+                                new DialogInterface.OnMultiChoiceClickListener() {
+                                    @Override
+                                    public void onClick(DialogInterface dialog, int which,
+                                            boolean isChecked) {
+                                        mDeleteDialogChecked[which] = isChecked;
+                                    }
+                                })
+                        .setPositiveButton(R.string.zen_mode_schedule_delete,
+                                new DialogInterface.OnClickListener() {
+                            @Override
+                            public void onClick(DialogInterface dialog, int which) {
+                                for (int i = 0; i < rules.length; i++) {
+                                    if (mDeleteDialogChecked[i]) {
+                                        mBackend.removeZenRule(mDeleteDialogRuleIds[i]);
+                                    }
+                                }
+                            }
+                        }).show();
+                return true;
+            default:
+                return super.onOptionsItemSelected(item);
+        }
+    }
 
     /**
      * For Search.
diff --git a/src/com/android/settings/notification/ZenModeBackend.java b/src/com/android/settings/notification/ZenModeBackend.java
index de30e5d..4824825 100644
--- a/src/com/android/settings/notification/ZenModeBackend.java
+++ b/src/com/android/settings/notification/ZenModeBackend.java
@@ -32,6 +32,11 @@
 
 import com.android.settings.R;
 
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+
 public class ZenModeBackend {
     @VisibleForTesting
     protected static final String ZEN_MODE_FROM_ANYONE = "zen_mode_from_anyone";
@@ -42,6 +47,7 @@
     @VisibleForTesting
     protected static final String ZEN_MODE_FROM_NONE = "zen_mode_from_none";
     protected static final int SOURCE_NONE = -1;
+    private static List<String> mDefaultRuleIds;
 
     private static ZenModeBackend sInstance;
 
@@ -79,7 +85,7 @@
                 Settings.Global.ZEN_MODE, mZenMode);
     }
 
-    protected boolean setZenRule(String id, AutomaticZenRule rule) {
+    protected boolean updateZenRule(String id, AutomaticZenRule rule) {
         return NotificationManager.from(mContext).updateAutomaticZenRule(id, rule);
     }
 
@@ -294,13 +300,65 @@
         return NotificationManager.from(mContext).removeAutomaticZenRule(ruleId);
     }
 
+    public NotificationManager.Policy getConsolidatedPolicy() {
+        return NotificationManager.from(mContext).getConsolidatedNotificationPolicy();
+    }
+
     protected String addZenRule(AutomaticZenRule rule) {
         try {
-            String id = NotificationManager.from(mContext).addAutomaticZenRule(rule);
-            NotificationManager.from(mContext).getAutomaticZenRule(id);
-            return id;
+            return NotificationManager.from(mContext).addAutomaticZenRule(rule);
         } catch (Exception e) {
             return null;
         }
     }
+
+    protected Map.Entry<String, AutomaticZenRule>[] getAutomaticZenRules() {
+        Map<String, AutomaticZenRule> ruleMap =
+                NotificationManager.from(mContext).getAutomaticZenRules();
+        final Map.Entry<String, AutomaticZenRule>[] rt = ruleMap.entrySet().toArray(
+                new Map.Entry[ruleMap.size()]);
+        Arrays.sort(rt, RULE_COMPARATOR);
+        return rt;
+    }
+
+    protected AutomaticZenRule getAutomaticZenRule(String id) {
+        return NotificationManager.from(mContext).getAutomaticZenRule(id);
+    }
+
+    private static List<String> getDefaultRuleIds() {
+        if (mDefaultRuleIds == null) {
+            mDefaultRuleIds = ZenModeConfig.DEFAULT_RULE_IDS;
+        }
+        return mDefaultRuleIds;
+    }
+
+    @VisibleForTesting
+    public static final Comparator<Map.Entry<String, AutomaticZenRule>> RULE_COMPARATOR =
+            new Comparator<Map.Entry<String, AutomaticZenRule>>() {
+                @Override
+                public int compare(Map.Entry<String, AutomaticZenRule> lhs,
+                        Map.Entry<String, AutomaticZenRule> rhs) {
+                    // if it's a default rule, should be at the top of automatic rules
+                    boolean lhsIsDefaultRule = getDefaultRuleIds().contains(lhs.getKey());
+                    boolean rhsIsDefaultRule = getDefaultRuleIds().contains(rhs.getKey());
+                    if (lhsIsDefaultRule != rhsIsDefaultRule) {
+                        return lhsIsDefaultRule ? -1 : 1;
+                    }
+
+                    int byDate = Long.compare(lhs.getValue().getCreationTime(),
+                            rhs.getValue().getCreationTime());
+                    if (byDate != 0) {
+                        return byDate;
+                    } else {
+                        return key(lhs.getValue()).compareTo(key(rhs.getValue()));
+                    }
+                }
+
+                private String key(AutomaticZenRule rule) {
+                    final int type = ZenModeConfig.isValidScheduleConditionId(rule.getConditionId())
+                            ? 1 : ZenModeConfig.isValidEventConditionId(rule.getConditionId())
+                            ? 2 : 3;
+                    return type + rule.getName().toString();
+                }
+            };
 }
diff --git a/src/com/android/settings/notification/ZenModePreferenceController.java b/src/com/android/settings/notification/ZenModePreferenceController.java
index 44ad2ff..22eb0c0 100644
--- a/src/com/android/settings/notification/ZenModePreferenceController.java
+++ b/src/com/android/settings/notification/ZenModePreferenceController.java
@@ -35,6 +35,9 @@
 public class ZenModePreferenceController extends BasePreferenceController
         implements LifecycleObserver, OnResume, OnPause {
 
+
+    public static final String ZEN_MODE_KEY = "zen_mode";
+
     private SettingObserver mSettingObserver;
     private ZenModeSettings.SummaryBuilder mSummaryBuilder;
 
diff --git a/src/com/android/settings/notification/ZenModeRuleSettingsBase.java b/src/com/android/settings/notification/ZenModeRuleSettingsBase.java
index 9e5dbc3..11b8084 100644
--- a/src/com/android/settings/notification/ZenModeRuleSettingsBase.java
+++ b/src/com/android/settings/notification/ZenModeRuleSettingsBase.java
@@ -124,7 +124,7 @@
 
     protected void updateRule(Uri newConditionId) {
         mRule.setConditionId(newConditionId);
-        mBackend.setZenRule(mId, mRule);
+        mBackend.updateZenRule(mId, mRule);
     }
 
     @Override
diff --git a/src/com/android/settings/notification/ZenModeScheduleRuleSettings.java b/src/com/android/settings/notification/ZenModeScheduleRuleSettings.java
index f65a8b0..0b2e1bc 100644
--- a/src/com/android/settings/notification/ZenModeScheduleRuleSettings.java
+++ b/src/com/android/settings/notification/ZenModeScheduleRuleSettings.java
@@ -64,7 +64,6 @@
     private TimePickerPreference mEnd;
     private SwitchPreference mExitAtAlarm;
     private AlertDialog mDayDialog;
-
     private ScheduleInfo mSchedule;
 
     @Override
@@ -186,7 +185,6 @@
         final int summaryFormat = nextDay ? R.string.zen_mode_end_time_next_day_summary_format : 0;
         mEnd.setSummaryFormat(summaryFormat);
     }
-
     @Override
     protected void updateControlsInternal() {
         updateDays();
diff --git a/src/com/android/settings/notification/ZenModeSettingsFooterPreferenceController.java b/src/com/android/settings/notification/ZenModeSettingsFooterPreferenceController.java
index 6d5aac9..f69eac7 100644
--- a/src/com/android/settings/notification/ZenModeSettingsFooterPreferenceController.java
+++ b/src/com/android/settings/notification/ZenModeSettingsFooterPreferenceController.java
@@ -16,16 +16,23 @@
 
 package com.android.settings.notification;
 
+import android.app.NotificationManager;
 import android.content.Context;
+import android.icu.text.ListFormatter;
 import android.net.Uri;
 import android.provider.Settings;
 import android.service.notification.ZenModeConfig;
+import android.util.Log;
 
 import androidx.preference.Preference;
 
 import com.android.settings.R;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
 public class ZenModeSettingsFooterPreferenceController extends AbstractZenModePreferenceController {
 
     protected static final String KEY = "footer_preference";
@@ -65,6 +72,31 @@
 
     protected String getFooterText() {
         ZenModeConfig config = getZenModeConfig();
+
+        NotificationManager.Policy appliedPolicy = mBackend.getConsolidatedPolicy();
+        NotificationManager.Policy defaultPolicy = config.toNotificationPolicy();
+        final boolean usingCustomPolicy = !Objects.equals(appliedPolicy, defaultPolicy);
+
+        if (usingCustomPolicy) {
+            final List<ZenModeConfig.ZenRule> activeRules = getActiveRules(config);
+            final List<String> rulesNames = new ArrayList<>();
+            for (ZenModeConfig.ZenRule rule : activeRules) {
+                if (rule.name != null) {
+                    rulesNames.add(rule.name);
+                }
+            }
+            if (rulesNames.size() > 0) {
+                String rules = ListFormatter.getInstance().format(rulesNames);
+                if (!rules.isEmpty()) {
+                    return mContext.getString(R.string.zen_mode_settings_dnd_custom_settings_footer,
+                            rules);
+                }
+            }
+        }
+        return getFooterUsingDefaultPolicy(config);
+    }
+
+    private String getFooterUsingDefaultPolicy(ZenModeConfig config) {
         String footerText = "";
         long latestEndTime = -1;
 
@@ -116,4 +148,18 @@
         }
         return footerText;
     }
+
+    private List<ZenModeConfig.ZenRule> getActiveRules(ZenModeConfig config) {
+        List<ZenModeConfig.ZenRule> zenRules = new ArrayList<>();
+        if (config.manualRule != null) {
+            zenRules.add(config.manualRule);
+        }
+
+        for (ZenModeConfig.ZenRule automaticRule : config.automaticRules.values()) {
+            if (automaticRule.isAutomaticActive()) {
+                zenRules.add(automaticRule);
+            }
+        }
+        return zenRules;
+    }
 }
diff --git a/src/com/android/settings/notification/ZenModeSliceBuilder.java b/src/com/android/settings/notification/ZenModeSliceBuilder.java
index bd6ad0b..5c88fb6 100644
--- a/src/com/android/settings/notification/ZenModeSliceBuilder.java
+++ b/src/com/android/settings/notification/ZenModeSliceBuilder.java
@@ -18,16 +18,16 @@
 
 import static android.app.slice.Slice.EXTRA_TOGGLE_STATE;
 
+import static com.android.settings.notification.ZenModePreferenceController.ZEN_MODE_KEY;
+
 import android.annotation.ColorInt;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
-import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.net.Uri;
 import android.provider.Settings;
-import android.provider.SettingsSlicesContract;
 
 import androidx.core.graphics.drawable.IconCompat;
 import androidx.slice.Slice;
@@ -39,7 +39,7 @@
 import com.android.settings.R;
 import com.android.settings.SubSettings;
 import com.android.settings.Utils;
-import com.android.settings.slices.SettingsSliceProvider;
+import com.android.settings.slices.CustomSliceRegistry;
 import com.android.settings.slices.SliceBroadcastReceiver;
 import com.android.settings.slices.SliceBuilderUtils;
 
@@ -47,18 +47,6 @@
 
     private static final String TAG = "ZenModeSliceBuilder";
 
-    private static final String ZEN_MODE_KEY = "zen_mode";
-
-    /**
-     * Backing Uri for the Zen Mode Slice.
-     */
-    public static final Uri ZEN_MODE_URI = new Uri.Builder()
-            .scheme(ContentResolver.SCHEME_CONTENT)
-            .authority(SettingsSliceProvider.SLICE_AUTHORITY)
-            .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
-            .appendPath(ZEN_MODE_KEY)
-            .build();
-
     /**
      * Action notifying a change on the Zen Mode Slice.
      */
@@ -77,7 +65,7 @@
     }
 
     /**
-     * Return a ZenMode Slice bound to {@link #ZEN_MODE_URI}.
+     * Return a ZenMode Slice bound to {@link CustomSliceRegistry#ZEN_MODE_URI}.
      * <p>
      * Note that you should register a listener for {@link #INTENT_FILTER} to get changes for
      * ZenMode.
@@ -88,12 +76,13 @@
         @ColorInt final int color = Utils.getColorAccentDefaultColor(context);
         final PendingIntent toggleAction = getBroadcastIntent(context);
         final PendingIntent primaryAction = getPrimaryAction(context);
-        final SliceAction primarySliceAction = new SliceAction(primaryAction,
-                (IconCompat) null /* icon */, title);
-        final SliceAction toggleSliceAction = new SliceAction(toggleAction, null /* actionTitle */,
+        final SliceAction primarySliceAction = SliceAction.createDeeplink(primaryAction,
+                (IconCompat) null /* icon */, ListBuilder.ICON_IMAGE, title);
+        final SliceAction toggleSliceAction = SliceAction.createToggle(toggleAction, null /* actionTitle */,
                 isZenModeEnabled);
 
-        return new ListBuilder(context, ZEN_MODE_URI, ListBuilder.INFINITY)
+        return new ListBuilder(context, CustomSliceRegistry.ZEN_MODE_SLICE_URI,
+                ListBuilder.INFINITY)
                 .setAccentColor(color)
                 .addRow(new RowBuilder()
                         .setTitle(title)
diff --git a/src/com/android/settings/notification/ZenRulePreference.java b/src/com/android/settings/notification/ZenRulePreference.java
index 8058e6c..48a879b 100644
--- a/src/com/android/settings/notification/ZenRulePreference.java
+++ b/src/com/android/settings/notification/ZenRulePreference.java
@@ -19,17 +19,18 @@
 import android.app.AutomaticZenRule;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ServiceInfo;
 import android.service.notification.ZenModeConfig;
 import android.view.View;
+import android.widget.CheckBox;
 
 import androidx.fragment.app.Fragment;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceViewHolder;
 
-import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.R;
 import com.android.settings.utils.ManagedServiceSettings;
 import com.android.settings.utils.ZenServiceListing;
@@ -37,11 +38,11 @@
 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
 
 import java.util.Map;
+import java.util.Objects;
 
 public class ZenRulePreference extends TwoTargetPreference {
     private static final ManagedServiceSettings.Config CONFIG =
             ZenModeAutomationSettings.getConditionProviderConfig();
-    final CharSequence mName;
     final String mId;
     boolean appExists;
     final Fragment mParent;
@@ -51,16 +52,23 @@
     final ZenServiceListing mServiceListing;
     final PackageManager mPm;
     final MetricsFeatureProvider mMetricsFeatureProvider;
+    final AutomaticZenRule mRule;
+    CharSequence mName;
+
+    private boolean mIsSystemRule;
+    private Intent mIntent;
+    private boolean mChecked;
+    private CheckBox mCheckBox;
 
     public ZenRulePreference(Context context,
             final Map.Entry<String, AutomaticZenRule> ruleEntry,
             Fragment parent, MetricsFeatureProvider metricsProvider) {
         super(context);
-
+        setLayoutResource(R.layout.preference_checkable_two_target);
         mBackend = ZenModeBackend.getInstance(context);
         mContext = context;
-        final AutomaticZenRule rule = ruleEntry.getValue();
-        mName = rule.getName();
+        mRule = ruleEntry.getValue();
+        mName = mRule.getName();
         mId = ruleEntry.getKey();
         mParent = parent;
         mPm = mContext.getPackageManager();
@@ -68,65 +76,97 @@
         mServiceListing.reloadApprovedServices();
         mPref = this;
         mMetricsFeatureProvider = metricsProvider;
-
-        setAttributes(rule);
+        mChecked = mRule.isEnabled();
+        setAttributes(mRule);
+        setWidgetLayoutResource(getSecondTargetResId());
     }
 
-    @Override
     protected int getSecondTargetResId() {
-        if (mId != null && ZenModeConfig.DEFAULT_RULE_IDS.contains(mId)) {
-            return 0;
+        if (mIntent != null) {
+            return R.layout.zen_rule_widget;
         }
-
-        return R.layout.zen_rule_widget;
+        return 0;
     }
 
     @Override
     public void onBindViewHolder(PreferenceViewHolder view) {
         super.onBindViewHolder(view);
+        View settingsWidget = view.findViewById(android.R.id.widget_frame);
+        View divider = view.findViewById(R.id.two_target_divider);
+        if (mIntent != null) {
+            divider.setVisibility(View.VISIBLE);
+            settingsWidget.setVisibility(View.VISIBLE);
+            settingsWidget.setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    mContext.startActivity(mIntent);
+                }
+            });
+        } else {
+            divider.setVisibility(View.GONE);
+            settingsWidget.setVisibility(View.GONE);
+            settingsWidget.setOnClickListener(null);
+        }
 
-        View v = view.findViewById(R.id.delete_zen_rule);
-        if (v != null) {
-            v.setOnClickListener(mDeleteListener);
+        View checkboxContainer = view.findViewById(R.id.checkbox_container);
+        if (checkboxContainer != null) {
+            checkboxContainer.setOnClickListener(mOnCheckBoxClickListener);
+        }
+        mCheckBox = (CheckBox) view.findViewById(com.android.internal.R.id.checkbox);
+        if (mCheckBox != null) {
+            mCheckBox.setChecked(mChecked);
         }
     }
 
-    private final View.OnClickListener mDeleteListener = new View.OnClickListener() {
+    public boolean isChecked() {
+        return mChecked;
+    }
+
+    public void setChecked(boolean checked) {
+        mChecked = checked;
+        if (mCheckBox != null) {
+            mCheckBox.setChecked(checked);
+        }
+    }
+
+    public void setName(String name) {
+        if (!Objects.equals(mName, name)) {
+            mName = name;
+            setTitle(mName);
+        }
+    }
+
+    @Override
+    public void onClick() {
+        mOnCheckBoxClickListener.onClick(null);
+    }
+
+    private View.OnClickListener mOnCheckBoxClickListener = new View.OnClickListener() {
         @Override
         public void onClick(View v) {
-            showDeleteRuleDialog(mParent, mId, mName.toString());
+            mRule.setEnabled(!mChecked);
+            mBackend.updateZenRule(mId, mRule);
+            setChecked(mRule.isEnabled());
+            setAttributes(mRule);
         }
     };
 
-    private void showDeleteRuleDialog(final Fragment parent, final String ruleId,
-            final String ruleName) {
-        ZenDeleteRuleDialog.show(parent, ruleName, ruleId,
-                new ZenDeleteRuleDialog.PositiveClickListener() {
-                    @Override
-                    public void onOk(String id) {
-                        mMetricsFeatureProvider.action(mContext,
-                                MetricsProto.MetricsEvent.ACTION_ZEN_DELETE_RULE_OK);
-                        mBackend.removeZenRule(id);
-                    }
-                });
-    }
-
     protected void setAttributes(AutomaticZenRule rule) {
         final boolean isSchedule = ZenModeConfig.isValidScheduleConditionId(
                 rule.getConditionId(), true);
         final boolean isEvent = ZenModeConfig.isValidEventConditionId(rule.getConditionId());
-        final boolean isSystemRule = isSchedule || isEvent;
+        mIsSystemRule = isSchedule || isEvent;
 
         try {
             ApplicationInfo info = mPm.getApplicationInfo(rule.getOwner().getPackageName(), 0);
-            setSummary(computeRuleSummary(rule, isSystemRule, info.loadLabel(mPm)));
+            setSummary(computeRuleSummary(rule, mIsSystemRule, info.loadLabel(mPm)));
         } catch (PackageManager.NameNotFoundException e) {
             appExists = false;
             return;
         }
 
         appExists = true;
-        setTitle(rule.getName());
+        setTitle(mName);
         setPersistent(false);
 
         final String action = isSchedule ? ZenModeScheduleRuleSettings.ACTION
@@ -134,9 +174,8 @@
         ServiceInfo si = mServiceListing.findService(rule.getOwner());
         ComponentName settingsActivity = AbstractZenModeAutomaticRulePreferenceController.
                 getSettingsActivity(si);
-        setIntent(AbstractZenModeAutomaticRulePreferenceController.getRuleIntent(action,
-                settingsActivity, mId));
-        setSelectable(settingsActivity != null || isSystemRule);
+        mIntent = AbstractZenModeAutomaticRulePreferenceController.getRuleIntent(action,
+                settingsActivity, mId);
         setKey(mId);
     }
 
diff --git a/src/com/android/settings/overlay/FeatureFactory.java b/src/com/android/settings/overlay/FeatureFactory.java
index 02468b8..a52619b 100644
--- a/src/com/android/settings/overlay/FeatureFactory.java
+++ b/src/com/android/settings/overlay/FeatureFactory.java
@@ -28,6 +28,7 @@
 import com.android.settings.enterprise.EnterprisePrivacyFeatureProvider;
 import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
 import com.android.settings.gestures.AssistGestureFeatureProvider;
+import com.android.settings.homepage.contextualcards.ContextualCardFeatureProvider;
 import com.android.settings.localepicker.LocaleFeatureProvider;
 import com.android.settings.panel.PanelFeatureProvider;
 import com.android.settings.search.SearchFeatureProvider;
@@ -108,6 +109,8 @@
 
     public abstract PanelFeatureProvider getPanelFeatureProvider();
 
+    public abstract ContextualCardFeatureProvider getContextualCardFeatureProvider();
+
     public static final class FactoryNotFoundException extends RuntimeException {
         public FactoryNotFoundException(Throwable throwable) {
             super("Unable to create factory. Did you misconfigure Proguard?", throwable);
diff --git a/src/com/android/settings/overlay/FeatureFactoryImpl.java b/src/com/android/settings/overlay/FeatureFactoryImpl.java
index 8d6d4b6..3515ac0 100644
--- a/src/com/android/settings/overlay/FeatureFactoryImpl.java
+++ b/src/com/android/settings/overlay/FeatureFactoryImpl.java
@@ -40,6 +40,8 @@
 import com.android.settings.fuelgauge.PowerUsageFeatureProviderImpl;
 import com.android.settings.gestures.AssistGestureFeatureProvider;
 import com.android.settings.gestures.AssistGestureFeatureProviderImpl;
+import com.android.settings.homepage.contextualcards.ContextualCardFeatureProvider;
+import com.android.settings.homepage.contextualcards.ContextualCardFeatureProviderImpl;
 import com.android.settings.localepicker.LocaleFeatureProvider;
 import com.android.settings.localepicker.LocaleFeatureProviderImpl;
 import com.android.settings.panel.PanelFeatureProvider;
@@ -75,6 +77,7 @@
     private SlicesFeatureProvider mSlicesFeatureProvider;
     private AccountFeatureProvider mAccountFeatureProvider;
     private PanelFeatureProvider mPanelFeatureProvider;
+    private ContextualCardFeatureProvider mContextualCardFeatureProvider;
 
     @Override
     public SupportFeatureProvider getSupportFeatureProvider(Context context) {
@@ -220,4 +223,11 @@
         }
         return mPanelFeatureProvider;
     }
+
+    public ContextualCardFeatureProvider getContextualCardFeatureProvider() {
+        if (mContextualCardFeatureProvider == null) {
+            mContextualCardFeatureProvider = new ContextualCardFeatureProviderImpl();
+        }
+        return mContextualCardFeatureProvider;
+    }
 }
diff --git a/src/com/android/settings/panel/InternetConnectivityPanel.java b/src/com/android/settings/panel/InternetConnectivityPanel.java
index b6fe53b..aae42f8 100644
--- a/src/com/android/settings/panel/InternetConnectivityPanel.java
+++ b/src/com/android/settings/panel/InternetConnectivityPanel.java
@@ -16,16 +16,13 @@
 
 package com.android.settings.panel;
 
-import androidx.annotation.VisibleForTesting;
-
-import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.net.Uri;
-import android.provider.SettingsSlicesContract;
+import android.provider.Settings;
 
 import com.android.settings.R;
-import com.android.settings.wifi.WifiSlice;
+import com.android.settings.slices.CustomSliceRegistry;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -34,19 +31,11 @@
  * Represents the Internet Connectivity Panel.
  *
  * <p>
- *     Displays Wifi (full Slice) and Airplane mode.
+ * Displays Wifi (full Slice) and Airplane mode.
  * </p>
  */
 public class InternetConnectivityPanel implements PanelContent {
 
-    @VisibleForTesting
-    static final Uri AIRPLANE_URI = new Uri.Builder()
-            .scheme(ContentResolver.SCHEME_CONTENT)
-            .authority(SettingsSlicesContract.AUTHORITY)
-            .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
-            .appendPath(SettingsSlicesContract.KEY_AIRPLANE_MODE)
-            .build();
-
     private final Context mContext;
 
     public static InternetConnectivityPanel create(Context context) {
@@ -58,20 +47,20 @@
     }
 
     @Override
-    public String getTitle() {
-        return (String) mContext.getText(R.string.internet_connectivity_panel_title);
+    public CharSequence getTitle() {
+        return mContext.getText(R.string.internet_connectivity_panel_title);
     }
 
     @Override
     public List<Uri> getSlices() {
         final List<Uri> uris = new ArrayList<>();
-        uris.add(WifiSlice.WIFI_URI);
-        uris.add(AIRPLANE_URI);
+        uris.add(CustomSliceRegistry.WIFI_SLICE_URI);
+        uris.add(CustomSliceRegistry.AIRPLANE_URI);
         return uris;
     }
 
     @Override
     public Intent getSeeMoreIntent() {
-        return null;
+        return new Intent(Settings.ACTION_WIRELESS_SETTINGS);
     }
 }
diff --git a/src/com/android/settings/panel/PanelFeatureProviderImpl.java b/src/com/android/settings/panel/PanelFeatureProviderImpl.java
index 2e84078..503a5c3 100644
--- a/src/com/android/settings/panel/PanelFeatureProviderImpl.java
+++ b/src/com/android/settings/panel/PanelFeatureProviderImpl.java
@@ -25,6 +25,8 @@
         switch (panelType) {
             case SettingsPanelActivity.PANEL_TYPE_WIFI:
                 return InternetConnectivityPanel.create(context);
+            case SettingsPanelActivity.PANEL_TYPE_VOLUME:
+                return VolumePanel.create(context);
         }
 
         throw new IllegalStateException("No matching panel for: "  + panelType);
diff --git a/src/com/android/settings/panel/PanelFragment.java b/src/com/android/settings/panel/PanelFragment.java
index bbdaec3..e61b8f8 100644
--- a/src/com/android/settings/panel/PanelFragment.java
+++ b/src/com/android/settings/panel/PanelFragment.java
@@ -16,19 +16,20 @@
 
 package com.android.settings.panel;
 
-import android.net.Uri;
+import android.content.Intent;
 import android.os.Bundle;
+import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 
-import android.widget.LinearLayout;
+import android.widget.Button;
+import android.widget.TextView;
 
-import androidx.lifecycle.LiveData;
-import androidx.slice.Slice;
-import androidx.slice.widget.SliceLiveData;
-import androidx.slice.widget.SliceView;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.settings.R;
 
 import androidx.annotation.NonNull;
@@ -38,20 +39,24 @@
 
 import com.android.settings.overlay.FeatureFactory;
 
-import java.util.ArrayList;
-import java.util.List;
-
 public class PanelFragment extends Fragment {
 
     private static final String TAG = "PanelFragment";
 
-    private List<SliceView> mSliceViewList;
-    private List<LiveData<Slice>> mSliceDataList;
-    private LinearLayout mPanelLayout;
+    private TextView mTitleView;
+    private Button mSeeMoreButton;
+    private Button mDoneButton;
+    private RecyclerView mPanelSlices;
+
+    @VisibleForTesting
+    PanelSlicesAdapter mAdapter;
+
+    private View.OnClickListener mDoneButtonListener = (v) -> {
+        Log.d(TAG, "Closing dialog");
+        getActivity().finish();
+    };
 
     public PanelFragment() {
-        mSliceViewList = new ArrayList<>();
-        mSliceDataList = new ArrayList<>();
     }
 
     @Nullable
@@ -61,28 +66,37 @@
         final FragmentActivity activity = getActivity();
         final View view = inflater.inflate(R.layout.panel_layout, container, false);
 
-        mPanelLayout = view.findViewById(R.id.panel_parent_layout);
-        final Bundle arguments = getArguments();
+        mPanelSlices = view.findViewById(R.id.panel_parent_layout);
+        mSeeMoreButton = view.findViewById(R.id.see_more);
+        mDoneButton = view.findViewById(R.id.done);
+        mTitleView = view.findViewById(R.id.title);
 
+        final Bundle arguments = getArguments();
         final String panelType = arguments.getString(SettingsPanelActivity.KEY_PANEL_TYPE_ARGUMENT);
 
         final PanelContent panel = FeatureFactory.getFactory(activity)
                 .getPanelFeatureProvider()
                 .getPanel(activity, panelType);
 
-        activity.setTitle(panel.getTitle());
+        mAdapter = new PanelSlicesAdapter(this, panel.getSlices());
 
+        mPanelSlices.setHasFixedSize(true);
+        mPanelSlices.setLayoutManager(new LinearLayoutManager((activity)));
+        mPanelSlices.setAdapter(mAdapter);
 
-        for (Uri uri : panel.getSlices()) {
-            final SliceView sliceView = new SliceView(activity);
-            mPanelLayout.addView(sliceView);
-            final LiveData<Slice> liveData = SliceLiveData.fromUri(activity, uri);
-            liveData.observe(this /* lifecycleOwner */, sliceView);
+        mTitleView.setText(panel.getTitle());
 
-            mSliceDataList.add(liveData);
-            mSliceViewList.add(sliceView);
-        }
+        mSeeMoreButton.setOnClickListener(getSeeMoreListener(panel.getSeeMoreIntent()));
+        mDoneButton.setOnClickListener(mDoneButtonListener);
 
         return view;
     }
+
+    private View.OnClickListener getSeeMoreListener(final Intent intent) {
+        return (v) -> {
+            final FragmentActivity activity = getActivity();
+            activity.startActivity(intent);
+            activity.finish();
+        };
+    }
 }
diff --git a/src/com/android/settings/panel/PanelSlicesAdapter.java b/src/com/android/settings/panel/PanelSlicesAdapter.java
new file mode 100644
index 0000000..f688512
--- /dev/null
+++ b/src/com/android/settings/panel/PanelSlicesAdapter.java
@@ -0,0 +1,100 @@
+/*
+ * 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.panel;
+
+import android.content.Context;
+import android.net.Uri;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
+import androidx.lifecycle.LiveData;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.slice.Slice;
+import androidx.slice.widget.SliceLiveData;
+import androidx.slice.widget.SliceView;
+
+import com.android.settings.R;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * RecyclerView adapter for Slices in Settings Panels.
+ */
+public class PanelSlicesAdapter
+        extends RecyclerView.Adapter<PanelSlicesAdapter.SliceRowViewHolder> {
+
+    private final List<Uri> mSliceUris;
+    private final PanelFragment mPanelFragment;
+
+    public PanelSlicesAdapter(PanelFragment fragment, List<Uri> sliceUris) {
+        mPanelFragment = fragment;
+        mSliceUris = new ArrayList<>(sliceUris);
+    }
+
+    @NonNull
+    @Override
+    public SliceRowViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
+        final Context context = viewGroup.getContext();
+        final LayoutInflater inflater = LayoutInflater.from(context);
+        final View view = inflater.inflate(R.layout.panel_slice_row, viewGroup, false);
+
+        return new SliceRowViewHolder(view);
+    }
+
+    @Override
+    public void onBindViewHolder(@NonNull SliceRowViewHolder sliceRowViewHolder, int position) {
+        sliceRowViewHolder.onBind(mPanelFragment, mSliceUris.get(position));
+    }
+
+    @Override
+    public int getItemCount() {
+        return mSliceUris.size();
+    }
+
+    @VisibleForTesting
+    List<Uri> getData() {
+        return mSliceUris;
+    }
+
+    /**
+     * ViewHolder for binding Slices to SliceViews.
+     */
+    public static class SliceRowViewHolder extends RecyclerView.ViewHolder {
+
+        @VisibleForTesting
+        LiveData<Slice> sliceLiveData;
+
+        @VisibleForTesting
+        final SliceView sliceView;
+
+        public SliceRowViewHolder(View view) {
+            super(view);
+            sliceView = view.findViewById(R.id.slice_view);
+            sliceView.setMode(SliceView.MODE_LARGE);
+        }
+
+        public void onBind(PanelFragment fragment, Uri sliceUri) {
+            final Context context = sliceView.getContext();
+            sliceLiveData = SliceLiveData.fromUri(context, sliceUri);
+            sliceLiveData.observe(fragment.getViewLifecycleOwner(), sliceView);
+        }
+    }
+}
diff --git a/src/com/android/settings/panel/SettingsPanelActivity.java b/src/com/android/settings/panel/SettingsPanelActivity.java
index db1f60d..09bead4 100644
--- a/src/com/android/settings/panel/SettingsPanelActivity.java
+++ b/src/com/android/settings/panel/SettingsPanelActivity.java
@@ -54,6 +54,9 @@
     // TODO (b/117804442) move to framework
     public static final String PANEL_TYPE_WIFI = "wifi_panel";
 
+    // TODO (b/117804442) move to framework
+    public static final String PANEL_TYPE_VOLUME = "volume_panel";
+
     @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
diff --git a/src/com/android/settings/panel/VolumePanel.java b/src/com/android/settings/panel/VolumePanel.java
new file mode 100644
index 0000000..c0118d7
--- /dev/null
+++ b/src/com/android/settings/panel/VolumePanel.java
@@ -0,0 +1,64 @@
+/*
+ * 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.panel;
+
+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;
+import static com.android.settings.slices.CustomSliceRegistry.VOLUME_RINGER_URI;
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.provider.Settings;
+
+import com.android.settings.R;
+import java.util.ArrayList;
+import java.util.List;
+
+public class VolumePanel implements PanelContent {
+
+    private final Context mContext;
+
+    public static VolumePanel create(Context context) {
+        return new VolumePanel(context);
+    }
+
+    private VolumePanel(Context context) {
+        mContext = context.getApplicationContext();
+    }
+
+    @Override
+    public CharSequence getTitle() {
+        return mContext.getText(R.string.volume_connectivity_panel_title);
+    }
+
+    @Override
+    public List<Uri> getSlices() {
+        final List<Uri> uris = new ArrayList<>();
+        uris.add(VOLUME_MEDIA_URI);
+        uris.add(VOLUME_CALL_URI);
+        uris.add(VOLUME_RINGER_URI);
+        uris.add(VOLUME_ALARM_URI);
+        return uris;
+    }
+
+    @Override
+    public Intent getSeeMoreIntent() {
+        return new Intent(Settings.ACTION_SOUND_SETTINGS);
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/search/SearchFeatureProvider.java b/src/com/android/settings/search/SearchFeatureProvider.java
index 3c1c62b..34f8629 100644
--- a/src/com/android/settings/search/SearchFeatureProvider.java
+++ b/src/com/android/settings/search/SearchFeatureProvider.java
@@ -68,8 +68,10 @@
         if (activity == null || toolbar == null) {
             return;
         }
-        if (!Utils.isPackageEnabled(activity, getSettingsIntelligencePkgName(activity))) {
-            final ViewGroup parent = (ViewGroup)toolbar.getParent();
+
+        if (!Utils.isDeviceProvisioned(activity) ||
+                !Utils.isPackageEnabled(activity, getSettingsIntelligencePkgName(activity))) {
+            final ViewGroup parent = (ViewGroup) toolbar.getParent();
             if (parent != null) {
                 parent.setVisibility(View.GONE);
             }
diff --git a/src/com/android/settings/slices/CustomSliceManager.java b/src/com/android/settings/slices/CustomSliceManager.java
index 99e22a1..bef72b7 100644
--- a/src/com/android/settings/slices/CustomSliceManager.java
+++ b/src/com/android/settings/slices/CustomSliceManager.java
@@ -101,13 +101,13 @@
     }
 
     private void addSlices() {
-        mUriMap.put(WifiSlice.WIFI_URI, WifiSlice.class);
-        mUriMap.put(DataUsageSlice.DATA_USAGE_CARD_URI, DataUsageSlice.class);
-        mUriMap.put(DeviceInfoSlice.DEVICE_INFO_CARD_URI, DeviceInfoSlice.class);
-        mUriMap.put(StorageSlice.STORAGE_CARD_URI, StorageSlice.class);
-        mUriMap.put(BatterySlice.BATTERY_CARD_URI, BatterySlice.class);
-        mUriMap.put(ConnectedDeviceSlice.CONNECTED_DEVICE_URI, ConnectedDeviceSlice.class);
-        mUriMap.put(LowStorageSlice.LOW_STORAGE_URI, LowStorageSlice.class);
-        mUriMap.put(BatteryFixSlice.BATTERY_FIX_URI, BatteryFixSlice.class);
+        mUriMap.put(CustomSliceRegistry.BATTERY_FIX_SLICE_URI, BatteryFixSlice.class);
+        mUriMap.put(CustomSliceRegistry.BATTERY_INFO_SLICE_URI, BatterySlice.class);
+        mUriMap.put(CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI, ConnectedDeviceSlice.class);
+        mUriMap.put(CustomSliceRegistry.DATA_USAGE_SLICE_URI, DataUsageSlice.class);
+        mUriMap.put(CustomSliceRegistry.DEVICE_INFO_SLICE_URI, DeviceInfoSlice.class);
+        mUriMap.put(CustomSliceRegistry.LOW_STORAGE_SLICE_URI, LowStorageSlice.class);
+        mUriMap.put(CustomSliceRegistry.STORAGE_SLICE_URI, StorageSlice.class);
+        mUriMap.put(CustomSliceRegistry.WIFI_SLICE_URI, WifiSlice.class);
     }
 }
diff --git a/src/com/android/settings/slices/CustomSliceRegistry.java b/src/com/android/settings/slices/CustomSliceRegistry.java
new file mode 100644
index 0000000..7ca92a9
--- /dev/null
+++ b/src/com/android/settings/slices/CustomSliceRegistry.java
@@ -0,0 +1,222 @@
+/*
+ * 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 static android.provider.SettingsSlicesContract.KEY_LOCATION;
+import static android.provider.SettingsSlicesContract.KEY_WIFI;
+
+import static com.android.settings.notification.ZenModePreferenceController.ZEN_MODE_KEY;
+
+import android.content.ContentResolver;
+import android.net.Uri;
+import android.provider.SettingsSlicesContract;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController;
+import com.android.settings.wifi.calling.WifiCallingSliceHelper;
+
+/**
+ * A registry of custom slice Uris.
+ */
+public class CustomSliceRegistry {
+
+    /**
+     * Uri for Airplane mode Slice.
+     */
+    public static final Uri AIRPLANE_URI = new Uri.Builder()
+            .scheme(ContentResolver.SCHEME_CONTENT)
+            .authority(SettingsSlicesContract.AUTHORITY)
+            .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+            .appendPath(SettingsSlicesContract.KEY_AIRPLANE_MODE)
+            .build();
+
+    /**
+     * Uri for Battery Fix Slice.
+     */
+    public static final Uri BATTERY_FIX_SLICE_URI = new Uri.Builder()
+            .scheme(ContentResolver.SCHEME_CONTENT)
+            .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+            .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.
+     */
+    public static final Uri BLUETOOTH_URI = new Uri.Builder()
+            .scheme(ContentResolver.SCHEME_CONTENT)
+            .authority(SettingsSlicesContract.AUTHORITY)
+            .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+            .appendPath(SettingsSlicesContract.KEY_BLUETOOTH)
+            .build();
+
+    /**
+     * Backing Uri for Connected device Slice.
+     */
+    public static final Uri CONNECTED_DEVICE_SLICE_URI = new Uri.Builder()
+            .scheme(ContentResolver.SCHEME_CONTENT)
+            .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+            .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+            .appendPath("connected_device")
+            .build();
+    /**
+     * Backing Uri for the Data usage Slice.
+     */
+    public static final Uri DATA_USAGE_SLICE_URI = new Uri.Builder()
+            .scheme(ContentResolver.SCHEME_CONTENT)
+            .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+            .appendPath("data_usage_card")
+            .build();
+    /**
+     * Backing Uri for the Device info Slice.
+     */
+    public static final Uri DEVICE_INFO_SLICE_URI = new Uri.Builder()
+            .scheme(ContentResolver.SCHEME_CONTENT)
+            .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+            .appendPath("device_info_card")
+            .build();
+    /**
+     * Backing Uri for the Emergency Info Slice.
+     */
+    public static final Uri EMERGENCY_INFO_SLICE_URI = new Uri.Builder()
+            .scheme(ContentResolver.SCHEME_CONTENT)
+            .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+            .appendPath("emergency_info_card")
+            .build();
+    /**
+     * Slice Uri for Enhanced 4G slice
+     */
+    public static final Uri ENHANCED_4G_SLICE_URI = new Uri.Builder()
+            .scheme(ContentResolver.SCHEME_CONTENT)
+            .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+            .appendPath("enhanced_4g_lte")
+            .build();
+    /**
+     * Backing Uri for the Flashlight Slice.
+     */
+    public static final Uri FLASHLIGHT_SLICE_URI = new Uri.Builder()
+            .scheme(ContentResolver.SCHEME_CONTENT)
+            .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+            .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+            .appendPath("flashlight")
+            .build();
+    /**
+     * Backing Uri for the Location Slice.
+     */
+    public static final Uri LOCATION_SLICE_URI = new Uri.Builder()
+            .scheme(ContentResolver.SCHEME_CONTENT)
+            .authority(SettingsSlicesContract.AUTHORITY)
+            .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+            .appendPath(KEY_LOCATION)
+            .build();
+    /**
+     * Backing Uri for Low storage Slice.
+     */
+    public static final Uri LOW_STORAGE_SLICE_URI = new Uri.Builder()
+            .scheme(ContentResolver.SCHEME_CONTENT)
+            .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+            .appendEncodedPath(SettingsSlicesContract.PATH_SETTING_INTENT)
+            .appendPath("low_storage")
+            .build();
+    /**
+     * Backing Uri for the storage slice.
+     */
+    public static final Uri STORAGE_SLICE_URI = new Uri.Builder()
+            .scheme(ContentResolver.SCHEME_CONTENT)
+            .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+            .appendPath("storage_card")
+            .build();
+    /**
+     * Full {@link Uri} for the Alarm volume Slice.
+     */
+    public static final Uri VOLUME_ALARM_URI = new Uri.Builder()
+            .scheme(ContentResolver.SCHEME_CONTENT)
+            .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+            .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+            .appendPath("alarm_volume")
+            .build();
+    /**
+     * Full {@link Uri} for the Call Volume Slice.
+     */
+    public static final Uri VOLUME_CALL_URI = new Uri.Builder()
+            .scheme(ContentResolver.SCHEME_CONTENT)
+            .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+            .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+            .appendPath("call_volume")
+            .build();
+    /**
+     * Full {@link Uri} for the Media Volume Slice.
+     */
+    public static final Uri VOLUME_MEDIA_URI = new Uri.Builder()
+            .scheme(ContentResolver.SCHEME_CONTENT)
+            .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+            .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+            .appendPath("media_volume")
+            .build();
+    /**
+     * Full {@link Uri} for the Ringer volume Slice.
+     */
+    public static final Uri VOLUME_RINGER_URI = new Uri.Builder()
+            .scheme(ContentResolver.SCHEME_CONTENT)
+            .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+            .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+            .appendPath("ring_volume")
+            .build();
+
+    /**
+     * Full {@link Uri} for the Wifi Calling Slice.
+     */
+    public static final Uri WIFI_CALLING_URI = new Uri.Builder()
+            .scheme(ContentResolver.SCHEME_CONTENT)
+            .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+            .appendPath(WifiCallingSliceHelper.PATH_WIFI_CALLING)
+            .build();
+    /**
+     * Full {@link Uri} for the Wifi Calling Preference Slice.
+     */
+    public static final Uri WIFI_CALLING_PREFERENCE_URI = new Uri.Builder()
+            .scheme(ContentResolver.SCHEME_CONTENT)
+            .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+            .appendPath(WifiCallingSliceHelper.PATH_WIFI_CALLING_PREFERENCE)
+            .build();
+    /**
+     * Backing Uri for the Wifi Slice.
+     */
+    public static final Uri WIFI_SLICE_URI = new Uri.Builder()
+            .scheme(ContentResolver.SCHEME_CONTENT)
+            .authority(SettingsSlicesContract.AUTHORITY)
+            .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+            .appendPath(KEY_WIFI)
+            .build();
+    /**
+     * Backing Uri for the Zen Mode Slice.
+     */
+    public static final Uri ZEN_MODE_SLICE_URI = new Uri.Builder()
+            .scheme(ContentResolver.SCHEME_CONTENT)
+            .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+            .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+            .appendPath(ZEN_MODE_KEY)
+            .build();
+}
diff --git a/src/com/android/settings/slices/SettingsSliceProvider.java b/src/com/android/settings/slices/SettingsSliceProvider.java
index 952fc8b..109f02e 100644
--- a/src/com/android/settings/slices/SettingsSliceProvider.java
+++ b/src/com/android/settings/slices/SettingsSliceProvider.java
@@ -44,11 +44,8 @@
 import com.android.settings.flashlight.FlashlightSliceBuilder;
 import com.android.settings.homepage.contextualcards.deviceinfo.EmergencyInfoSlice;
 import com.android.settings.location.LocationSliceBuilder;
-import com.android.settings.network.telephony.Enhanced4gLteSliceHelper;
 import com.android.settings.notification.ZenModeSliceBuilder;
 import com.android.settings.overlay.FeatureFactory;
-import com.android.settings.wifi.WifiSlice;
-import com.android.settings.wifi.calling.WifiCallingSliceHelper;
 import com.android.settingslib.SliceBroadcastRelay;
 import com.android.settingslib.utils.ThreadUtils;
 
@@ -175,23 +172,21 @@
             if (filter != null) {
                 registerIntentToUri(filter, sliceUri);
             }
-            ThreadUtils.postOnMainThread(() -> {
-                startBackgroundWorker(sliceable);
-            });
+            ThreadUtils.postOnMainThread(() -> startBackgroundWorker(sliceable));
             return;
         }
 
-        if (ZenModeSliceBuilder.ZEN_MODE_URI.equals(sliceUri)) {
+        if (CustomSliceRegistry.ZEN_MODE_SLICE_URI.equals(sliceUri)) {
             registerIntentToUri(ZenModeSliceBuilder.INTENT_FILTER, sliceUri);
             return;
-        } else if (BluetoothSliceBuilder.BLUETOOTH_URI.equals(sliceUri)) {
+        } else if (CustomSliceRegistry.BLUETOOTH_URI.equals(sliceUri)) {
             registerIntentToUri(BluetoothSliceBuilder.INTENT_FILTER, sliceUri);
             return;
-        } else if (FlashlightSliceBuilder.FLASHLIGHT_URI.equals(sliceUri)) {
+        } else if (CustomSliceRegistry.FLASHLIGHT_SLICE_URI.equals(sliceUri)) {
             registerIntentToUri(FlashlightSliceBuilder.INTENT_FILTER, sliceUri);
             mRegisteredUris.add(sliceUri);
             return;
-        } else if (EmergencyInfoSlice.EMERGENCY_INFO_CARD_URI.equals(sliceUri)) {
+        } else if (CustomSliceRegistry.EMERGENCY_INFO_SLICE_URI.equals(sliceUri)) {
             return;
         }
 
@@ -236,30 +231,30 @@
                 return sliceable.getSlice();
             }
 
-            if (WifiCallingSliceHelper.WIFI_CALLING_URI.equals(sliceUri)) {
+            if (CustomSliceRegistry.WIFI_CALLING_URI.equals(sliceUri)) {
                 return FeatureFactory.getFactory(getContext())
                         .getSlicesFeatureProvider()
                         .getNewWifiCallingSliceHelper(getContext())
                         .createWifiCallingSlice(sliceUri);
-            } else if (ZenModeSliceBuilder.ZEN_MODE_URI.equals(sliceUri)) {
+            } else if (CustomSliceRegistry.ZEN_MODE_SLICE_URI.equals(sliceUri)) {
                 return ZenModeSliceBuilder.getSlice(getContext());
-            } else if (BluetoothSliceBuilder.BLUETOOTH_URI.equals(sliceUri)) {
+            } else if (CustomSliceRegistry.BLUETOOTH_URI.equals(sliceUri)) {
                 return BluetoothSliceBuilder.getSlice(getContext());
-            } else if (LocationSliceBuilder.LOCATION_URI.equals(sliceUri)) {
+            } else if (CustomSliceRegistry.LOCATION_SLICE_URI.equals(sliceUri)) {
                 return LocationSliceBuilder.getSlice(getContext());
-            } else if (Enhanced4gLteSliceHelper.SLICE_URI.equals(sliceUri)) {
+            } else if (CustomSliceRegistry.ENHANCED_4G_SLICE_URI.equals(sliceUri)) {
                 return FeatureFactory.getFactory(getContext())
                         .getSlicesFeatureProvider()
                         .getNewEnhanced4gLteSliceHelper(getContext())
                         .createEnhanced4gLteSlice(sliceUri);
-            } else if (WifiCallingSliceHelper.WIFI_CALLING_PREFERENCE_URI.equals(sliceUri)) {
+            } else if (CustomSliceRegistry.WIFI_CALLING_PREFERENCE_URI.equals(sliceUri)) {
                 return FeatureFactory.getFactory(getContext())
                         .getSlicesFeatureProvider()
                         .getNewWifiCallingSliceHelper(getContext())
                         .createWifiCallingPreferenceSlice(sliceUri);
-            } else if (FlashlightSliceBuilder.FLASHLIGHT_URI.equals(sliceUri)) {
+            } else if (CustomSliceRegistry.FLASHLIGHT_SLICE_URI.equals(sliceUri)) {
                 return FlashlightSliceBuilder.getSlice(getContext());
-            } else if (EmergencyInfoSlice.EMERGENCY_INFO_CARD_URI.equals(sliceUri)) {
+            } else if (CustomSliceRegistry.EMERGENCY_INFO_SLICE_URI.equals(sliceUri)) {
                 return EmergencyInfoSlice.getSlice(getContext());
             }
 
@@ -476,16 +471,16 @@
 
     private List<Uri> getSpecialCasePlatformUris() {
         return Arrays.asList(
-                WifiSlice.WIFI_URI,
-                BluetoothSliceBuilder.BLUETOOTH_URI,
-                LocationSliceBuilder.LOCATION_URI
+                CustomSliceRegistry.WIFI_SLICE_URI,
+                CustomSliceRegistry.BLUETOOTH_URI,
+                CustomSliceRegistry.LOCATION_SLICE_URI
         );
     }
 
     private List<Uri> getSpecialCaseOemUris() {
         return Arrays.asList(
-                ZenModeSliceBuilder.ZEN_MODE_URI,
-                FlashlightSliceBuilder.FLASHLIGHT_URI
+                CustomSliceRegistry.ZEN_MODE_SLICE_URI,
+                CustomSliceRegistry.FLASHLIGHT_SLICE_URI
         );
     }
 
diff --git a/src/com/android/settings/slices/SliceBuilderUtils.java b/src/com/android/settings/slices/SliceBuilderUtils.java
index f18225a..c16a8ba 100644
--- a/src/com/android/settings/slices/SliceBuilderUtils.java
+++ b/src/com/android/settings/slices/SliceBuilderUtils.java
@@ -168,10 +168,11 @@
      * @return {@link PendingIntent} for a non-primary {@link SliceAction}.
      */
     public static PendingIntent getActionIntent(Context context, String action, SliceData data) {
-        final Intent intent = new Intent(action);
-        intent.setClass(context, SliceBroadcastReceiver.class);
-        intent.putExtra(EXTRA_SLICE_KEY, data.getKey());
-        intent.putExtra(EXTRA_SLICE_PLATFORM_DEFINED, data.isPlatformDefined());
+        final Intent intent = new Intent(action)
+                .setData(data.getUri())
+                .setClass(context, SliceBroadcastReceiver.class)
+                .putExtra(EXTRA_SLICE_KEY, data.getKey())
+                .putExtra(EXTRA_SLICE_PLATFORM_DEFINED, data.isPlatformDefined());
         return PendingIntent.getBroadcast(context, 0 /* requestCode */, intent,
                 PendingIntent.FLAG_CANCEL_CURRENT);
     }
@@ -193,8 +194,9 @@
         CharSequence summaryText = controller.getSummary();
 
         // Priority 1 : User prefers showing the dynamic summary in slice view rather than static
-        // summary.
-        if (isDynamicSummaryAllowed && isValidSummary(context, summaryText)) {
+        // summary. Note it doesn't require a valid summary - so we can force some slices to have
+        // empty summaries (ex: volume).
+        if (isDynamicSummaryAllowed) {
             return summaryText;
         }
 
@@ -279,7 +281,8 @@
                         .setTitle(sliceData.getTitle())
                         .setSubtitle(subtitleText)
                         .setPrimaryAction(
-                                new SliceAction(contentIntent, icon, sliceData.getTitle()))
+                                SliceAction.createDeeplink(contentIntent, icon,
+                                        ListBuilder.ICON_IMAGE, sliceData.getTitle()))
                         .addEndItem(sliceAction))
                 .setKeywords(keywords)
                 .build();
@@ -299,7 +302,9 @@
                         .setTitle(sliceData.getTitle())
                         .setSubtitle(subtitleText)
                         .setPrimaryAction(
-                                new SliceAction(contentIntent, icon, sliceData.getTitle())))
+                                SliceAction.createDeeplink(contentIntent, icon,
+                                        ListBuilder.ICON_IMAGE,
+                                        sliceData.getTitle())))
                 .setKeywords(keywords)
                 .build();
     }
@@ -312,8 +317,8 @@
         final IconCompat icon = getSafeIcon(context, sliceData);
         @ColorInt final int color = Utils.getColorAccentDefaultColor(context);
         final CharSequence subtitleText = getSubtitleText(context, controller, sliceData);
-        final SliceAction primaryAction = new SliceAction(contentIntent, icon,
-                sliceData.getTitle());
+        final SliceAction primaryAction = SliceAction.createDeeplink(contentIntent, icon,
+                ListBuilder.ICON_IMAGE, sliceData.getTitle());
         final Set<String> keywords = buildSliceKeywords(sliceData);
 
         return new ListBuilder(context, sliceData.getUri(), ListBuilder.INFINITY)
@@ -334,7 +339,8 @@
         final SliceAction copyableAction = getCopyableAction(context, sliceData);
         final PendingIntent contentIntent = getContentPendingIntent(context, sliceData);
         final IconCompat icon = getSafeIcon(context, sliceData);
-        final SliceAction primaryAction = new SliceAction(contentIntent, icon,
+        final SliceAction primaryAction = SliceAction.createDeeplink(contentIntent, icon,
+                ListBuilder.ICON_IMAGE,
                 sliceData.getTitle());
         final CharSequence subtitleText = getSubtitleText(context, controller, sliceData);
         @ColorInt final int color = Utils.getColorAccentDefaultColor(context);
@@ -366,7 +372,7 @@
             boolean isChecked) {
         PendingIntent actionIntent = getActionIntent(context,
                 SettingsSliceProvider.ACTION_TOGGLE_CHANGED, sliceData);
-        return new SliceAction(actionIntent, null, isChecked);
+        return SliceAction.createToggle(actionIntent, null, isChecked);
     }
 
     private static PendingIntent getSliderAction(Context context, SliceData sliceData) {
@@ -378,7 +384,7 @@
                 SettingsSliceProvider.ACTION_COPY, sliceData);
         final IconCompat icon = IconCompat.createWithResource(context,
                 R.drawable.ic_content_copy_grey600_24dp);
-        return new SliceAction(intent, icon, sliceData.getTitle());
+        return SliceAction.create(intent, icon, ListBuilder.ICON_IMAGE, sliceData.getTitle());
     }
 
     private static boolean isValidSummary(Context context, CharSequence summary) {
@@ -421,14 +427,15 @@
         @ColorInt final int color = Utils.getColorAccentDefaultColor(context);
         final CharSequence summary = context.getText(R.string.disabled_dependent_setting_summary);
         final IconCompat icon = getSafeIcon(context, data);
-        final SliceAction primaryAction = new SliceAction(getContentPendingIntent(context, data),
-                icon, title);
+        final SliceAction primaryAction = SliceAction.createDeeplink(
+                getContentPendingIntent(context, data),
+                icon, ListBuilder.ICON_IMAGE, title);
 
         return new ListBuilder(context, data.getUri(), ListBuilder.INFINITY)
                 .setAccentColor(color)
                 .addRow(new RowBuilder()
                         .setTitle(title)
-                        .setTitleItem(icon, ListBuilder.SMALL_IMAGE)
+                        .setTitleItem(icon, ListBuilder.ICON_IMAGE)
                         .setSubtitle(summary)
                         .setPrimaryAction(primaryAction))
                 .setKeywords(keywords)
diff --git a/src/com/android/settings/slices/SliceDeepLinkSpringBoard.java b/src/com/android/settings/slices/SliceDeepLinkSpringBoard.java
index 7531778..01708af 100644
--- a/src/com/android/settings/slices/SliceDeepLinkSpringBoard.java
+++ b/src/com/android/settings/slices/SliceDeepLinkSpringBoard.java
@@ -62,11 +62,11 @@
                     final CustomSliceable sliceable =
                             customSliceManager.getSliceableFromUri(sliceUri);
                     launchIntent = sliceable.getIntent();
-                } else if (ZenModeSliceBuilder.ZEN_MODE_URI.equals(sliceUri)) {
+                } else if (CustomSliceRegistry.ZEN_MODE_SLICE_URI.equals(sliceUri)) {
                     launchIntent = ZenModeSliceBuilder.getIntent(this /* context */);
-                } else if (BluetoothSliceBuilder.BLUETOOTH_URI.equals(sliceUri)) {
+                } else if (CustomSliceRegistry.BLUETOOTH_URI.equals(sliceUri)) {
                     launchIntent = BluetoothSliceBuilder.getIntent(this /* context */);
-                } else if (LocationSliceBuilder.LOCATION_URI.equals(sliceUri)) {
+                } else if (CustomSliceRegistry.LOCATION_SLICE_URI.equals(sliceUri)) {
                     launchIntent = LocationSliceBuilder.getIntent(this /* context */);
                 } else {
                     final SlicesDatabaseAccessor slicesDatabaseAccessor =
diff --git a/src/com/android/settings/slices/SlicesDatabaseAccessor.java b/src/com/android/settings/slices/SlicesDatabaseAccessor.java
index 35a0a5d..c75f3ef 100644
--- a/src/com/android/settings/slices/SlicesDatabaseAccessor.java
+++ b/src/com/android/settings/slices/SlicesDatabaseAccessor.java
@@ -71,6 +71,9 @@
      */
     public SliceData getSliceDataFromUri(Uri uri) {
         Pair<Boolean, String> pathData = SliceBuilderUtils.getPathData(uri);
+        if (pathData == null) {
+            throw new IllegalStateException("Invalid Slices uri: " + uri);
+        }
         Cursor cursor = getIndexedSliceData(pathData.second /* key */);
         return buildSliceData(cursor, uri, pathData.first /* isIntentOnly */);
     }
diff --git a/src/com/android/settings/tts/TextToSpeechSettings.java b/src/com/android/settings/tts/TextToSpeechSettings.java
index b1a1f8f..bd85ef3 100644
--- a/src/com/android/settings/tts/TextToSpeechSettings.java
+++ b/src/com/android/settings/tts/TextToSpeechSettings.java
@@ -44,15 +44,14 @@
 import com.android.settings.SettingsPreferenceFragment;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.search.Indexable;
-import com.android.settings.widget.ActionButtonPreference;
 import com.android.settings.widget.GearPreference;
 import com.android.settings.widget.SeekBarPreference;
 import com.android.settingslib.search.SearchIndexable;
+import com.android.settingslib.widget.ActionButtonsPreference;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.Comparator;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
@@ -113,7 +112,7 @@
 
     private SeekBarPreference mDefaultPitchPref;
     private SeekBarPreference mDefaultRatePref;
-    private ActionButtonPreference mActionButtons;
+    private ActionButtonsPreference mActionButtons;
 
     private int mDefaultPitch = TextToSpeech.Engine.DEFAULT_PITCH;
     private int mDefaultRate = TextToSpeech.Engine.DEFAULT_RATE;
@@ -169,7 +168,7 @@
         mDefaultPitchPref = (SeekBarPreference) findPreference(KEY_DEFAULT_PITCH);
         mDefaultRatePref = (SeekBarPreference) findPreference(KEY_DEFAULT_RATE);
 
-        mActionButtons = ((ActionButtonPreference) findPreference(KEY_ACTION_BUTTONS))
+        mActionButtons = ((ActionButtonsPreference) findPreference(KEY_ACTION_BUTTONS))
                 .setButton1Text(R.string.tts_play)
                 .setButton1OnClickListener(v -> speakSampleText())
                 .setButton1Enabled(false)
diff --git a/src/com/android/settings/widget/ActionButtonPreference.java b/src/com/android/settings/widget/ActionButtonPreference.java
deleted file mode 100644
index a34d735..0000000
--- a/src/com/android/settings/widget/ActionButtonPreference.java
+++ /dev/null
@@ -1,333 +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.widget;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.drawable.Drawable;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.View;
-import android.widget.Button;
-
-import androidx.annotation.DrawableRes;
-import androidx.annotation.StringRes;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceViewHolder;
-
-import com.android.settings.R;
-
-/**
- * This preference provides a four buttons layout with Settings style.
- * It looks like below
- *
- * --------------------------------------------------
- *  button1     | button2   | button3   | button4   |
- * --------------------------------------------------
- *
- * User can set title / icon / click listener for each button.
- *
- * By default, four buttons are visible.
- * However, there are two cases which button should be invisible(View.GONE).
- *
- * 1. User sets invisible for button. ex: ActionButtonPreference.setButton1Visible(false)
- * 2. User doesn't set any title or icon for button.
- *
- */
-public class ActionButtonPreference extends Preference {
-
-    private final String TAG = "ActionButtonPreference";
-    private final ButtonInfo mButton1Info = new ButtonInfo();
-    private final ButtonInfo mButton2Info = new ButtonInfo();
-    private final ButtonInfo mButton3Info = new ButtonInfo();
-    private final ButtonInfo mButton4Info = new ButtonInfo();
-
-    public ActionButtonPreference(Context context, AttributeSet attrs,
-            int defStyleAttr, int defStyleRes) {
-        super(context, attrs, defStyleAttr, defStyleRes);
-        init();
-    }
-
-    public ActionButtonPreference(Context context, AttributeSet attrs, int defStyleAttr) {
-        super(context, attrs, defStyleAttr);
-        init();
-    }
-
-    public ActionButtonPreference(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        init();
-    }
-
-    public ActionButtonPreference(Context context) {
-        super(context);
-        init();
-    }
-
-    private void init() {
-        setLayoutResource(R.layout.settings_action_buttons);
-        setSelectable(false);
-    }
-
-    @Override
-    public void onBindViewHolder(PreferenceViewHolder holder) {
-        super.onBindViewHolder(holder);
-        holder.setDividerAllowedAbove(true);
-        holder.setDividerAllowedBelow(true);
-
-        mButton1Info.mButton = (Button) holder.findViewById(R.id.button1);
-        mButton2Info.mButton = (Button) holder.findViewById(R.id.button2);
-        mButton3Info.mButton = (Button) holder.findViewById(R.id.button3);
-        mButton4Info.mButton = (Button) holder.findViewById(R.id.button4);
-
-        mButton1Info.setUpButton();
-        mButton2Info.setUpButton();
-        mButton3Info.setUpButton();
-        mButton4Info.setUpButton();
-    }
-
-    public ActionButtonPreference setButton1Visible(boolean isVisible) {
-        if (isVisible != mButton1Info.mIsVisible) {
-            mButton1Info.mIsVisible = isVisible;
-            notifyChanged();
-        }
-        return this;
-    }
-
-    public ActionButtonPreference setButton1Text(@StringRes int textResId) {
-        final String newText = getContext().getString(textResId);
-        if (!TextUtils.equals(newText, mButton1Info.mText)) {
-            mButton1Info.mText = newText;
-            notifyChanged();
-        }
-        return this;
-    }
-
-    public ActionButtonPreference setButton1Icon(@DrawableRes int iconResId) {
-        if (iconResId == 0) {
-            return this;
-        }
-
-        final Drawable icon;
-        try {
-            icon = getContext().getDrawable(iconResId);
-            mButton1Info.mIcon = icon;
-            notifyChanged();
-        } catch (Resources.NotFoundException exception) {
-            Log.e(TAG, "Resource does not exist: " + iconResId);
-        }
-        return this;
-    }
-
-    public ActionButtonPreference setButton1Enabled(boolean isEnabled) {
-        if (isEnabled != mButton1Info.mIsEnabled) {
-            mButton1Info.mIsEnabled = isEnabled;
-            notifyChanged();
-        }
-        return this;
-    }
-
-    public ActionButtonPreference setButton1OnClickListener(View.OnClickListener listener) {
-        if (listener != mButton1Info.mListener) {
-            mButton1Info.mListener = listener;
-            notifyChanged();
-        }
-        return this;
-    }
-
-    public ActionButtonPreference setButton2Visible(boolean isVisible) {
-        if (isVisible != mButton2Info.mIsVisible) {
-            mButton2Info.mIsVisible = isVisible;
-            notifyChanged();
-        }
-        return this;
-    }
-
-    public ActionButtonPreference setButton2Text(@StringRes int textResId) {
-        final String newText = getContext().getString(textResId);
-        if (!TextUtils.equals(newText, mButton2Info.mText)) {
-            mButton2Info.mText = newText;
-            notifyChanged();
-        }
-        return this;
-    }
-
-    public ActionButtonPreference setButton2Icon(@DrawableRes int iconResId) {
-        if (iconResId == 0) {
-            return this;
-        }
-
-        final Drawable icon;
-        try {
-            icon = getContext().getDrawable(iconResId);
-            mButton2Info.mIcon = icon;
-            notifyChanged();
-        } catch (Resources.NotFoundException exception) {
-            Log.e(TAG, "Resource does not exist: " + iconResId);
-        }
-        return this;
-    }
-
-    public ActionButtonPreference setButton2Enabled(boolean isEnabled) {
-        if (isEnabled != mButton2Info.mIsEnabled) {
-            mButton2Info.mIsEnabled = isEnabled;
-            notifyChanged();
-        }
-        return this;
-    }
-
-    public ActionButtonPreference setButton2OnClickListener(View.OnClickListener listener) {
-        if (listener != mButton2Info.mListener) {
-            mButton2Info.mListener = listener;
-            notifyChanged();
-        }
-        return this;
-    }
-
-    public ActionButtonPreference setButton3Visible(boolean isVisible) {
-        if (isVisible != mButton3Info.mIsVisible) {
-            mButton3Info.mIsVisible = isVisible;
-            notifyChanged();
-        }
-        return this;
-    }
-
-    public ActionButtonPreference setButton3Text(@StringRes int textResId) {
-        final String newText = getContext().getString(textResId);
-        if (!TextUtils.equals(newText, mButton3Info.mText)) {
-            mButton3Info.mText = newText;
-            notifyChanged();
-        }
-        return this;
-    }
-
-    public ActionButtonPreference setButton3Icon(@DrawableRes int iconResId) {
-        if (iconResId == 0) {
-            return this;
-        }
-
-        final Drawable icon;
-        try {
-            icon = getContext().getDrawable(iconResId);
-            mButton3Info.mIcon = icon;
-            notifyChanged();
-        } catch (Resources.NotFoundException exception) {
-            Log.e(TAG, "Resource does not exist: " + iconResId);
-        }
-        return this;
-    }
-
-    public ActionButtonPreference setButton3Enabled(boolean isEnabled) {
-        if (isEnabled != mButton3Info.mIsEnabled) {
-            mButton3Info.mIsEnabled = isEnabled;
-            notifyChanged();
-        }
-        return this;
-    }
-
-    public ActionButtonPreference setButton3OnClickListener(View.OnClickListener listener) {
-        if (listener != mButton3Info.mListener) {
-            mButton3Info.mListener = listener;
-            notifyChanged();
-        }
-        return this;
-    }
-
-    public ActionButtonPreference setButton4Visible(boolean isVisible) {
-        if (isVisible != mButton4Info.mIsVisible) {
-            mButton4Info.mIsVisible = isVisible;
-            notifyChanged();
-        }
-        return this;
-    }
-
-    public ActionButtonPreference setButton4Text(@StringRes int textResId) {
-        final String newText = getContext().getString(textResId);
-        if (!TextUtils.equals(newText, mButton4Info.mText)) {
-            mButton4Info.mText = newText;
-            notifyChanged();
-        }
-        return this;
-    }
-
-    public ActionButtonPreference setButton4Icon(@DrawableRes int iconResId) {
-        if (iconResId == 0) {
-            return this;
-        }
-
-        final Drawable icon;
-        try {
-            icon = getContext().getDrawable(iconResId);
-            mButton4Info.mIcon = icon;
-            notifyChanged();
-        } catch (Resources.NotFoundException exception) {
-            Log.e(TAG, "Resource does not exist: " + iconResId);
-        }
-        return this;
-    }
-
-    public ActionButtonPreference setButton4Enabled(boolean isEnabled) {
-        if (isEnabled != mButton4Info.mIsEnabled) {
-            mButton4Info.mIsEnabled = isEnabled;
-            notifyChanged();
-        }
-        return this;
-    }
-
-    public ActionButtonPreference setButton4OnClickListener(View.OnClickListener listener) {
-        if (listener != mButton4Info.mListener) {
-            mButton4Info.mListener = listener;
-            notifyChanged();
-        }
-        return this;
-    }
-
-    static class ButtonInfo {
-        private Button mButton;
-        private CharSequence mText;
-        private Drawable mIcon;
-        private View.OnClickListener mListener;
-        private boolean mIsEnabled = true;
-        private boolean mIsVisible = true;
-
-        void setUpButton() {
-            mButton.setText(mText);
-            mButton.setOnClickListener(mListener);
-            mButton.setEnabled(mIsEnabled);
-            mButton.setCompoundDrawablesWithIntrinsicBounds(
-                    null /* left */, mIcon /* top */, null /* right */, null /* bottom */);
-
-            if (shouldBeVisible()) {
-                mButton.setVisibility(View.VISIBLE);
-            } else {
-                mButton.setVisibility(View.GONE);
-            }
-        }
-
-        /**
-         * By default, four buttons are visible.
-         * However, there are two cases which button should be invisible.
-         *
-         * 1. User set invisible for this button. ex: mIsVisible = false.
-         * 2. User didn't set any title or icon.
-         *
-         */
-        private boolean shouldBeVisible() {
-            return mIsVisible && (!TextUtils.isEmpty(mText) || mIcon != null);
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/com/android/settings/wifi/WifiDetailPreference.java b/src/com/android/settings/wifi/WifiDetailPreference.java
deleted file mode 100644
index 2567a42..0000000
--- a/src/com/android/settings/wifi/WifiDetailPreference.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2009 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.text.TextUtils;
-import android.util.AttributeSet;
-import android.widget.TextView;
-
-import androidx.preference.Preference;
-import androidx.preference.PreferenceViewHolder;
-
-import com.android.settings.R;
-
-/**
- * A Preference to be used with the Wifi Network Detail Fragment that allows a summary text to be
- * set inside the widget resource
- */
-public class WifiDetailPreference extends Preference {
-    private String mDetailText;
-
-    public WifiDetailPreference(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        setWidgetLayoutResource(R.layout.preference_widget_summary);
-    }
-
-    public void setDetailText(String text) {
-        if (TextUtils.equals(mDetailText, text)) return;
-        mDetailText = text;
-        notifyChanged();
-    }
-
-    @Override
-    public void onBindViewHolder(PreferenceViewHolder view) {
-        super.onBindViewHolder(view);
-        TextView textView = ((TextView) view.findViewById(R.id.widget_summary));
-        textView.setText(mDetailText);
-        textView.setPadding(0, 0, 10, 0);
-    }
-}
diff --git a/src/com/android/settings/wifi/WifiSlice.java b/src/com/android/settings/wifi/WifiSlice.java
index d06d830..2382abb 100644
--- a/src/com/android/settings/wifi/WifiSlice.java
+++ b/src/com/android/settings/wifi/WifiSlice.java
@@ -19,9 +19,10 @@
 import static android.app.slice.Slice.EXTRA_TOGGLE_STATE;
 import static android.provider.SettingsSlicesContract.KEY_WIFI;
 
+import static com.android.settings.slices.CustomSliceRegistry.WIFI_SLICE_URI;
+
 import android.annotation.ColorInt;
 import android.app.PendingIntent;
-import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -30,7 +31,6 @@
 import android.net.wifi.WifiManager;
 import android.net.wifi.WifiSsid;
 import android.os.Bundle;
-import android.provider.SettingsSlicesContract;
 import android.text.TextUtils;
 
 import androidx.annotation.VisibleForTesting;
@@ -60,16 +60,6 @@
  */
 public class WifiSlice implements CustomSliceable {
 
-    /**
-     * Backing Uri for the Wifi Slice.
-     */
-    public static final Uri WIFI_URI = new Uri.Builder()
-            .scheme(ContentResolver.SCHEME_CONTENT)
-            .authority(SettingsSlicesContract.AUTHORITY)
-            .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
-            .appendPath(KEY_WIFI)
-            .build();
-
     @VisibleForTesting
     static final int DEFAULT_EXPANDED_ROW_COUNT = 3;
 
@@ -81,7 +71,7 @@
 
     @Override
     public Uri getUri() {
-        return WIFI_URI;
+        return WIFI_SLICE_URI;
     }
 
     @Override
@@ -92,9 +82,6 @@
         return filter;
     }
 
-    /**
-     * Return a Wifi Slice bound to {@link #WIFI_URI}.
-     */
     @Override
     public Slice getSlice() {
         final boolean isWifiEnabled = isWifiEnabled();
@@ -105,11 +92,13 @@
         @ColorInt final int color = Utils.getColorAccentDefaultColor(mContext);
         final PendingIntent toggleAction = getBroadcastIntent(mContext);
         final PendingIntent primaryAction = getPrimaryAction();
-        final SliceAction primarySliceAction = new SliceAction(primaryAction, icon, title);
-        final SliceAction toggleSliceAction = new SliceAction(toggleAction, null /* actionTitle */,
-                isWifiEnabled);
+        final SliceAction primarySliceAction = SliceAction.createDeeplink(primaryAction, icon,
+                ListBuilder.ICON_IMAGE, title);
+        final SliceAction toggleSliceAction = SliceAction.createToggle(toggleAction,
+                null /* actionTitle */, isWifiEnabled);
 
-        final ListBuilder listBuilder = new ListBuilder(mContext, WIFI_URI, ListBuilder.INFINITY)
+        final ListBuilder listBuilder = new ListBuilder(mContext, WIFI_SLICE_URI,
+                ListBuilder.INFINITY)
                 .setAccentColor(color)
                 .addRow(new RowBuilder()
                         .setTitle(title)
@@ -151,8 +140,9 @@
                 .setSubtitle(!TextUtils.isEmpty(apSummary)
                         ? apSummary
                         : mContext.getText(R.string.summary_placeholder))
-                .setPrimaryAction(new SliceAction(
-                        getAccessPointAction(accessPoint), levelIcon, title));
+                .setPrimaryAction(SliceAction.create(
+                        getAccessPointAction(accessPoint), levelIcon, ListBuilder.ICON_IMAGE,
+                        title));
 
         final IconCompat endIcon = getEndIcon(accessPoint);
         if (endIcon != null) {
diff --git a/src/com/android/settings/wifi/calling/WifiCallingSliceHelper.java b/src/com/android/settings/wifi/calling/WifiCallingSliceHelper.java
index 0629ad3..70eef2c 100644
--- a/src/com/android/settings/wifi/calling/WifiCallingSliceHelper.java
+++ b/src/com/android/settings/wifi/calling/WifiCallingSliceHelper.java
@@ -18,9 +18,11 @@
 
 import static android.app.slice.Slice.EXTRA_TOGGLE_STATE;
 
+import static com.android.settings.slices.CustomSliceRegistry.WIFI_CALLING_PREFERENCE_URI;
+import static com.android.settings.slices.CustomSliceRegistry.WIFI_CALLING_URI;
+
 import android.app.PendingIntent;
 import android.content.ComponentName;
-import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.net.Uri;
@@ -42,9 +44,7 @@
 import com.android.ims.ImsManager;
 import com.android.settings.R;
 import com.android.settings.Utils;
-import com.android.settings.slices.SettingsSliceProvider;
 import com.android.settings.slices.SliceBroadcastReceiver;
-import com.android.settings.slices.SliceBuilderUtils;
 
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
@@ -104,24 +104,6 @@
             "android.settings.WIFI_CALLING_SETTINGS";
 
     /**
-     * Full {@link Uri} for the Wifi Calling Slice.
-     */
-    public static final Uri WIFI_CALLING_URI = new Uri.Builder()
-            .scheme(ContentResolver.SCHEME_CONTENT)
-            .authority(SettingsSliceProvider.SLICE_AUTHORITY)
-            .appendPath(PATH_WIFI_CALLING)
-            .build();
-
-    /**
-     * Full {@link Uri} for the Wifi Calling Preference Slice.
-     */
-    public static final Uri WIFI_CALLING_PREFERENCE_URI = new Uri.Builder()
-            .scheme(ContentResolver.SCHEME_CONTENT)
-            .authority(SettingsSliceProvider.SLICE_AUTHORITY)
-            .appendPath(PATH_WIFI_CALLING_PREFERENCE)
-            .build();
-
-    /**
      * Timeout for querying wifi calling setting from ims manager.
      */
     private static final int TIMEOUT_MILLIS = 2000;
@@ -212,12 +194,13 @@
                 .addRow(new RowBuilder()
                         .setTitle(mContext.getText(R.string.wifi_calling_settings_title))
                         .addEndItem(
-                                new SliceAction(
+                                SliceAction.createToggle(
                                         getBroadcastIntent(ACTION_WIFI_CALLING_CHANGED),
                                         null /* actionTitle */, isWifiCallingEnabled))
-                        .setPrimaryAction(new SliceAction(
+                        .setPrimaryAction(SliceAction.createDeeplink(
                                 getActivityIntent(ACTION_WIFI_CALLING_SETTINGS_ACTIVITY),
                                 icon,
+                                ListBuilder.ICON_IMAGE,
                                 mContext.getText(R.string.wifi_calling_settings_title))))
                 .build();
     }
@@ -246,7 +229,7 @@
         }
 
         final boolean isWifiCallingPrefEditable = isCarrierConfigManagerKeyEnabled(
-                CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL, subId,false);
+                CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL, subId, false);
         final boolean isWifiOnlySupported = isCarrierConfigManagerKeyEnabled(
                 CarrierConfigManager.KEY_CARRIER_WFC_SUPPORTS_WIFI_ONLY_BOOL, subId, true);
         final ImsManager imsManager = getImsManager(subId);
@@ -287,8 +270,8 @@
      * Returns actionable wifi calling preference slice.
      *
      * @param isWifiOnlySupported adds row for wifi only if this is true
-     * @param currentWfcPref current Preference {@link ImsConfig}
-     * @param sliceUri sliceUri
+     * @param currentWfcPref      current Preference {@link ImsConfig}
+     * @param sliceUri            sliceUri
      * @return Slice for actionable wifi calling preference settings
      */
     private Slice getWifiCallingPreferenceSlice(boolean isWifiOnlySupported,
@@ -299,12 +282,13 @@
         ListBuilder listBuilder = new ListBuilder(mContext, sliceUri, ListBuilder.INFINITY)
                 .setAccentColor(Utils.getColorAccentDefaultColor(mContext));
         listBuilder.setHeader(new ListBuilder.HeaderBuilder()
-                        .setTitle(mContext.getText(R.string.wifi_calling_mode_title))
-                        .setSubtitle(getWifiCallingPreferenceSummary(currentWfcPref))
-                        .setPrimaryAction(new SliceAction(
-                                getActivityIntent(ACTION_WIFI_CALLING_SETTINGS_ACTIVITY),
-                                icon,
-                                mContext.getText(R.string.wifi_calling_mode_title))));
+                .setTitle(mContext.getText(R.string.wifi_calling_mode_title))
+                .setSubtitle(getWifiCallingPreferenceSummary(currentWfcPref))
+                .setPrimaryAction(SliceAction.createDeeplink(
+                        getActivityIntent(ACTION_WIFI_CALLING_SETTINGS_ACTIVITY),
+                        icon,
+                        ListBuilder.ICON_IMAGE,
+                        mContext.getText(R.string.wifi_calling_mode_title))));
 
         if (isWifiOnlySupported) {
             listBuilder.addRow(wifiPreferenceRowBuilder(listBuilder,
@@ -329,9 +313,9 @@
     /**
      * Returns RowBuilder for a new row containing specific wifi calling preference.
      *
-     * @param listBuilder ListBuilder that will be the parent for this RowBuilder
+     * @param listBuilder          ListBuilder that will be the parent for this RowBuilder
      * @param preferenceTitleResId resource Id for the preference row title
-     * @param action action to be added for the row
+     * @param action               action to be added for the row
      * @return RowBuilder for the row
      */
     private RowBuilder wifiPreferenceRowBuilder(ListBuilder listBuilder,
@@ -340,7 +324,7 @@
                 IconCompat.createWithResource(mContext, R.drawable.radio_button_check);
         return new RowBuilder()
                 .setTitle(mContext.getText(preferenceTitleResId))
-                .setTitleItem(new SliceAction(getBroadcastIntent(action),
+                .setTitleItem(SliceAction.createToggle(getBroadcastIntent(action),
                         icon, mContext.getText(preferenceTitleResId), checked));
     }
 
@@ -414,8 +398,7 @@
         }
         // notify change in slice in any case to get re-queried. This would result in displaying
         // appropriate message with the updated setting.
-        final Uri uri = SliceBuilderUtils.getUri(PATH_WIFI_CALLING, false /*isPlatformSlice*/);
-        mContext.getContentResolver().notifyChange(uri, null);
+        mContext.getContentResolver().notifyChange(WIFI_CALLING_URI, null);
     }
 
     /**
@@ -433,7 +416,7 @@
 
         if (subId > SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
             final boolean isWifiCallingPrefEditable = isCarrierConfigManagerKeyEnabled(
-                    CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL, subId,false);
+                    CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL, subId, false);
             final boolean isWifiOnlySupported = isCarrierConfigManagerKeyEnabled(
                     CarrierConfigManager.KEY_CARRIER_WFC_SUPPORTS_WIFI_ONLY_BOOL, subId, true);
 
@@ -470,15 +453,13 @@
 
         // notify change in slice in any case to get re-queried. This would result in displaying
         // appropriate message.
-        final Uri uri = SliceBuilderUtils.getUri(PATH_WIFI_CALLING_PREFERENCE,
-                false /*isPlatformSlice*/);
-        mContext.getContentResolver().notifyChange(uri, null);
+        mContext.getContentResolver().notifyChange(WIFI_CALLING_PREFERENCE_URI, null);
     }
 
     /**
      * Returns Slice with the title and subtitle provided as arguments with wifi signal Icon.
      *
-     * @param title Title of the slice
+     * @param title    Title of the slice
      * @param subtitle Subtitle of the slice
      * @param sliceUri slice uri
      * @return Slice with title and subtitle
@@ -491,8 +472,8 @@
                 .addRow(new RowBuilder()
                         .setTitle(title)
                         .setSubtitle(subtitle)
-                        .setPrimaryAction(new SliceAction(
-                                primaryActionIntent, icon,
+                        .setPrimaryAction(SliceAction.createDeeplink(
+                                primaryActionIntent, icon, ListBuilder.SMALL_IMAGE,
                                 title)))
                 .build();
     }
diff --git a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
index 9a3398a..a676bfa 100644
--- a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
+++ b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
@@ -55,9 +55,7 @@
 import com.android.settings.R;
 import com.android.settings.Utils;
 import com.android.settings.core.PreferenceControllerMixin;
-import com.android.settings.widget.ActionButtonPreference;
 import com.android.settings.widget.EntityHeaderController;
-import com.android.settings.wifi.WifiDetailPreference;
 import com.android.settings.wifi.WifiDialog;
 import com.android.settings.wifi.WifiDialog.WifiDialogListener;
 import com.android.settings.wifi.WifiUtils;
@@ -67,6 +65,7 @@
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
 import com.android.settingslib.core.lifecycle.events.OnPause;
 import com.android.settingslib.core.lifecycle.events.OnResume;
+import com.android.settingslib.widget.ActionButtonsPreference;
 import com.android.settingslib.widget.LayoutPreference;
 import com.android.settingslib.wifi.AccessPoint;
 
@@ -131,17 +130,17 @@
     private final MetricsFeatureProvider mMetricsFeatureProvider;
 
     // UI elements - in order of appearance
-    private ActionButtonPreference mButtonsPref;
+    private ActionButtonsPreference mButtonsPref;
     private EntityHeaderController mEntityHeaderController;
-    private WifiDetailPreference mSignalStrengthPref;
-    private WifiDetailPreference mLinkSpeedPref;
-    private WifiDetailPreference mFrequencyPref;
-    private WifiDetailPreference mSecurityPref;
-    private WifiDetailPreference mMacAddressPref;
-    private WifiDetailPreference mIpAddressPref;
-    private WifiDetailPreference mGatewayPref;
-    private WifiDetailPreference mSubnetPref;
-    private WifiDetailPreference mDnsPref;
+    private Preference mSignalStrengthPref;
+    private Preference mLinkSpeedPref;
+    private Preference mFrequencyPref;
+    private Preference mSecurityPref;
+    private Preference mMacAddressPref;
+    private Preference mIpAddressPref;
+    private Preference mGatewayPref;
+    private Preference mSubnetPref;
+    private Preference mDnsPref;
     private PreferenceCategory mIpv6Category;
     private Preference mIpv6AddressPref;
 
@@ -276,29 +275,28 @@
 
         setupEntityHeader(screen);
 
-        mButtonsPref = ((ActionButtonPreference) screen.findPreference(KEY_BUTTONS_PREF))
+        mButtonsPref = ((ActionButtonsPreference) screen.findPreference(KEY_BUTTONS_PREF))
                 .setButton1Text(R.string.forget)
                 .setButton1Icon(R.drawable.ic_settings_delete)
                 .setButton1OnClickListener(view -> forgetNetwork())
                 .setButton2Text(R.string.wifi_sign_in_button_text)
                 .setButton2OnClickListener(view -> signIntoNetwork());
 
-        mSignalStrengthPref =
-                (WifiDetailPreference) screen.findPreference(KEY_SIGNAL_STRENGTH_PREF);
-        mLinkSpeedPref = (WifiDetailPreference) screen.findPreference(KEY_LINK_SPEED);
-        mFrequencyPref = (WifiDetailPreference) screen.findPreference(KEY_FREQUENCY_PREF);
-        mSecurityPref = (WifiDetailPreference) screen.findPreference(KEY_SECURITY_PREF);
+        mSignalStrengthPref = screen.findPreference(KEY_SIGNAL_STRENGTH_PREF);
+        mLinkSpeedPref = screen.findPreference(KEY_LINK_SPEED);
+        mFrequencyPref = screen.findPreference(KEY_FREQUENCY_PREF);
+        mSecurityPref = screen.findPreference(KEY_SECURITY_PREF);
 
-        mMacAddressPref = (WifiDetailPreference) screen.findPreference(KEY_MAC_ADDRESS_PREF);
-        mIpAddressPref = (WifiDetailPreference) screen.findPreference(KEY_IP_ADDRESS_PREF);
-        mGatewayPref = (WifiDetailPreference) screen.findPreference(KEY_GATEWAY_PREF);
-        mSubnetPref = (WifiDetailPreference) screen.findPreference(KEY_SUBNET_MASK_PREF);
-        mDnsPref = (WifiDetailPreference) screen.findPreference(KEY_DNS_PREF);
+        mMacAddressPref = screen.findPreference(KEY_MAC_ADDRESS_PREF);
+        mIpAddressPref = screen.findPreference(KEY_IP_ADDRESS_PREF);
+        mGatewayPref = screen.findPreference(KEY_GATEWAY_PREF);
+        mSubnetPref = screen.findPreference(KEY_SUBNET_MASK_PREF);
+        mDnsPref = screen.findPreference(KEY_DNS_PREF);
 
         mIpv6Category = (PreferenceCategory) screen.findPreference(KEY_IPV6_CATEGORY);
         mIpv6AddressPref = screen.findPreference(KEY_IPV6_ADDRESSES_PREF);
 
-        mSecurityPref.setDetailText(mAccessPoint.getSecurityString(false /* concise */));
+        mSecurityPref.setSummary(mAccessPoint.getSecurityString(false /* concise */));
     }
 
     private void setupEntityHeader(PreferenceScreen screen) {
@@ -359,12 +357,12 @@
         refreshRssiViews();
 
         // MAC Address Pref
-        mMacAddressPref.setDetailText(mWifiInfo.getMacAddress());
+        mMacAddressPref.setSummary(mWifiInfo.getMacAddress());
 
         // Link Speed Pref
         int linkSpeedMbps = mWifiInfo.getLinkSpeed();
         mLinkSpeedPref.setVisible(linkSpeedMbps >= 0);
-        mLinkSpeedPref.setDetailText(mContext.getString(
+        mLinkSpeedPref.setSummary(mContext.getString(
                 R.string.link_speed, mWifiInfo.getLinkSpeed()));
 
         // Frequency Pref
@@ -379,7 +377,7 @@
         } else {
             Log.e(TAG, "Unexpected frequency " + frequency);
         }
-        mFrequencyPref.setDetailText(band);
+        mFrequencyPref.setSummary(band);
 
         updateIpLayerInfo();
     }
@@ -410,16 +408,15 @@
         mEntityHeaderController.setIcon(wifiIcon).done(mFragment.getActivity(), true /* rebind */);
 
         Drawable wifiIconDark = wifiIcon.getConstantState().newDrawable().mutate();
-        wifiIconDark.setTint(mContext.getResources().getColor(
-                R.color.wifi_details_icon_color, mContext.getTheme()));
+        wifiIconDark.setTintList(Utils.getColorAttr(mContext, android.R.attr.colorControlNormal));
         mSignalStrengthPref.setIcon(wifiIconDark);
 
-        mSignalStrengthPref.setDetailText(mSignalStr[mRssiSignalLevel]);
+        mSignalStrengthPref.setSummary(mSignalStr[mRssiSignalLevel]);
     }
 
-    private void updatePreference(WifiDetailPreference pref, String detailText) {
+    private void updatePreference(Preference pref, String detailText) {
         if (!TextUtils.isEmpty(detailText)) {
-            pref.setDetailText(detailText);
+            pref.setSummary(detailText);
             pref.setVisible(true);
         } else {
             pref.setVisible(false);
diff --git a/src/com/android/settings/wifi/dpp/WifiDppAddDeviceFragment.java b/src/com/android/settings/wifi/dpp/WifiDppAddDeviceFragment.java
new file mode 100644
index 0000000..177e79d
--- /dev/null
+++ b/src/com/android/settings/wifi/dpp/WifiDppAddDeviceFragment.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.wifi.dpp;
+
+import android.os.Bundle;
+
+import com.android.settings.R;
+
+/**
+ * After getting Wi-Fi network information and(or) QR code, this fragment config a device to connect
+ * to the Wi-Fi network.
+ */
+public class WifiDppAddDeviceFragment extends WifiDppQrCodeBaseFragment {
+    @Override
+    protected int getLayout() {
+        return R.layout.wifi_dpp_add_device_fragment;
+    }
+
+    @Override
+    public void onActivityCreated (Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+    }
+}
diff --git a/src/com/android/settings/wifi/dpp/WifiDppChooseSavedWifiNetworkFragment.java b/src/com/android/settings/wifi/dpp/WifiDppChooseSavedWifiNetworkFragment.java
new file mode 100644
index 0000000..7d031c1
--- /dev/null
+++ b/src/com/android/settings/wifi/dpp/WifiDppChooseSavedWifiNetworkFragment.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.wifi.dpp;
+
+import android.os.Bundle;
+
+import com.android.settings.R;
+
+/**
+ * After a camera APP scanned a Wi-Fi DPP QR code, it can trigger
+ * {@code WifiDppConfiguratorActivity} to start with this fragment to choose a saved Wi-Fi network.
+ */
+public class WifiDppChooseSavedWifiNetworkFragment extends WifiDppQrCodeBaseFragment {
+    @Override
+    protected int getLayout() {
+        return R.layout.wifi_dpp_choose_saved_wifi_network_fragment;
+    }
+
+    @Override
+    public void onActivityCreated (Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+    }
+}
diff --git a/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java b/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java
index bccb53a..d81c19b 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java
@@ -18,9 +18,11 @@
 
 import android.app.ActionBar;
 import android.app.Activity;
+import android.content.Intent;
 import android.os.Bundle;
 import android.util.Log;
 
+import androidx.fragment.app.Fragment;
 import androidx.fragment.app.FragmentManager;
 import androidx.fragment.app.FragmentTransaction;
 
@@ -29,32 +31,22 @@
 import com.android.settings.core.InstrumentedActivity;
 import com.android.settings.R;
 
-public class WifiDppConfiguratorActivity extends InstrumentedActivity {
+public class WifiDppConfiguratorActivity extends InstrumentedActivity implements
+        WifiNetworkConfig.Retriever {
     private static final String TAG = "WifiDppConfiguratorActivity";
 
+    public static final String ACTION_CONFIGURATOR_QR_CODE_SCANNER =
+            "android.settings.WIFI_DPP_CONFIGURATOR_QR_CODE_SCANNER";
+    public static final String ACTION_CONFIGURATOR_QR_CODE_GENERATOR =
+            "android.settings.WIFI_DPP_CONFIGURATOR_QR_CODE_GENERATOR";
+    public static final String ACTION_CONFIGURATOR_CHOOSE_SAVED_WIFI_NETWORK =
+            "android.settings.WIFI_DPP_CONFIGURATOR_CHOOSE_SAVED_WIFI_NETWORK";
+
     private FragmentManager mFragmentManager;
     private FragmentTransaction mFragmentTransaction;
 
-    public static final String EXTRA_LAUNCH_MODE =
-            "com.android.settings.wifi.dpp.EXTRA_LAUNCH_MODE";
-    public static final String EXTRA_SSID = "com.android.settings.wifi.dpp.EXTRA_SSID";
-
-    public enum LaunchMode {
-        LAUNCH_MODE_QR_CODE_SCANNER(1),
-        LAUNCH_MODE_QR_CODE_GENERATOR(2),
-        LAUNCH_MODE_CHOOSE_SAVED_WIFI_NETWORK(3),
-        LAUNCH_MODE_NOT_DEFINED(-1);
-
-        private int mMode;
-
-        LaunchMode(int mode) {
-            this.mMode = mode;
-        }
-
-        public int getMode() {
-            return mMode;
-        }
-    }
+    /** The Wi-Fi network which will be configured */
+    private WifiNetworkConfig mWifiNetworkConfig;
 
     @Override
     public int getMetricsCategory() {
@@ -67,25 +59,98 @@
         super.onCreate(savedInstanceState);
         setContentView(R.layout.wifi_dpp_activity);
 
-        // Hide action bar
+        mFragmentManager = getSupportFragmentManager();
+        mFragmentTransaction = getSupportFragmentManager().beginTransaction();
+
+        Intent intent = getIntent();
+        boolean cancelActivity = false;
+        WifiNetworkConfig config;
+        switch (intent.getAction()) {
+            case ACTION_CONFIGURATOR_QR_CODE_SCANNER:
+                config = WifiNetworkConfig.getValidConfigOrNull(intent);
+                if (config == null) {
+                    cancelActivity = true;
+                } else {
+                    mWifiNetworkConfig = config;
+                    addQrCodeScannerFragment(/* addToBackStack= */ false);
+                }
+                break;
+            case ACTION_CONFIGURATOR_QR_CODE_GENERATOR:
+                config = WifiNetworkConfig.getValidConfigOrNull(intent);
+                if (config == null) {
+                    cancelActivity = true;
+                } else {
+                    mWifiNetworkConfig = config;
+                    addQrCodeGeneratorFragment();
+                }
+                break;
+            case ACTION_CONFIGURATOR_CHOOSE_SAVED_WIFI_NETWORK:
+                addChooseSavedWifiNetworkFragment(/* addToBackStack */ false);
+                break;
+            default:
+                cancelActivity = true;
+                Log.e(TAG, "Launch with an invalid action");
+        }
+
+        if (cancelActivity) {
+            setResult(Activity.RESULT_CANCELED);
+            finish();
+        }
+    }
+
+    private void addQrCodeScannerFragment(boolean addToBackStack) {
+        WifiDppQrCodeScannerFragment fragment = new WifiDppQrCodeScannerFragment();
+        mFragmentTransaction.add(R.id.fragment_container, fragment);
+        if (addToBackStack) {
+            mFragmentTransaction.addToBackStack(/* name */ null);
+        }
+        mFragmentTransaction.commit();
+    }
+
+    private void addQrCodeGeneratorFragment() {
+        WifiDppQrCodeGeneratorFragment fragment = new WifiDppQrCodeGeneratorFragment();
+        mFragmentTransaction.add(R.id.fragment_container, fragment);
+        mFragmentTransaction.commit();
+    }
+
+    private void addChooseSavedWifiNetworkFragment(boolean addToBackStack) {
         ActionBar action = getActionBar();
         if (action != null) {
             action.hide();
         }
 
-        mFragmentManager = getSupportFragmentManager();
-        mFragmentTransaction = getSupportFragmentManager().beginTransaction();
+        WifiDppChooseSavedWifiNetworkFragment fragment =
+                new WifiDppChooseSavedWifiNetworkFragment();
+        mFragmentTransaction.add(R.id.fragment_container, fragment);
+        if (addToBackStack) {
+            mFragmentTransaction.addToBackStack(/* name */ null);
+        }
+        mFragmentTransaction.commit();
+    }
 
-        final int launchMode = getIntent().getIntExtra(EXTRA_LAUNCH_MODE,
-            LaunchMode.LAUNCH_MODE_NOT_DEFINED.getMode());
-        if (launchMode == LaunchMode.LAUNCH_MODE_QR_CODE_SCANNER.getMode()) {
-            WifiDppQrCodeScannerFragment scanFragment = new WifiDppQrCodeScannerFragment();
-            mFragmentTransaction.add(R.id.fragment_container, scanFragment);
-            mFragmentTransaction.commit();
+    @Override
+    protected void onStop() {
+        Fragment fragment = mFragmentManager.findFragmentById(R.id.fragment_container);
+        if (fragment != null) {
+            // Remove it to prevent stacking multiple fragments after screen rotated.
+            mFragmentManager.beginTransaction().remove(fragment).commit();
+        }
+
+        super.onStop();
+    }
+
+    @Override
+    public WifiNetworkConfig getWifiNetworkConfig() {
+        return mWifiNetworkConfig;
+    }
+
+    @Override
+    public boolean setWifiNetworkConfig(WifiNetworkConfig config) {
+        if(!WifiNetworkConfig.isValidConfig(config)) {
+            return false;
         } else {
-            Log.e(TAG, "Launch with an invalid mode extra");
-            setResult(Activity.RESULT_CANCELED);
-            finish();
+            mWifiNetworkConfig = new WifiNetworkConfig(config);
+            return true;
         }
     }
 }
diff --git a/src/com/android/settings/wifi/dpp/WifiDppQrCodeBaseFragment.java b/src/com/android/settings/wifi/dpp/WifiDppQrCodeBaseFragment.java
index 004cb18..c86fc98 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppQrCodeBaseFragment.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppQrCodeBaseFragment.java
@@ -22,20 +22,48 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.ProgressBar;
 import android.widget.TextView;
 
 import com.android.internal.logging.nano.MetricsProto;
 
 import com.android.settings.core.InstrumentedFragment;
+import com.android.settings.wifi.qrcode.QrDecorateView;
 import com.android.settings.R;
 
+/**
+ * There are below 4 fragments for Wi-Fi DPP UI flow, to reduce redundant code of UI components,
+ * this parent fragment instantiates all UI components and provides setting APIs for them.
+ *
+ * {@code WifiDppQrCodeScannerFragment}
+ * {@code WifiDppQrCodeGeneratorFragment}
+ * {@code WifiDppChooseSavedWifiNetworkFragment}
+ * {@code WifiDppAddDeviceFragment}
+ */
 public abstract class WifiDppQrCodeBaseFragment extends InstrumentedFragment {
     private TextView mTitle;
     private TextView mDescription;
-    private SurfaceView mPreviewView;
-    private TextView mErrorMessage; //optional, view used to surface connectivity errors to the user
-    private Button mButtonLeft;
-    private Button mButtonRight;
+
+    private SurfaceView mPreviewView;       //optional, for WifiDppQrCodeScannerFragment
+    private QrDecorateView mDecorateViiew;  //optional, for WifiDppQrCodeScannerFragment
+    private TextView mErrorMessage;         //optional, for WifiDppQrCodeScannerFragment
+
+    private ImageView mBarcodeView;         //optional, for WifiDppQrCodeGeneratorFragment
+
+    private ListView mSavedWifiNetworkList; //optional, for WifiDppChooseSavedWifiNetworkFragment
+
+    private ProgressBar mProgressBar;       //optional, for WifiDppAddDeviceFragment
+    private ImageView mWifiApPictureView;   //optional, for WifiDppAddDeviceFragment
+    private TextView mChooseDifferentNetwork;//optional, for WifiDppAddDeviceFragment
+
+    private Button mButtonLeft;             //optional, for WifiDppQrCodeScannerFragment,
+                                            //              WifiDppChooseSavedWifiNetworkFragment,
+                                            //              WifiDppAddDeviceFragment
+    private Button mButtonRight;            //optional, for WifiDppQrCodeScannerFragment,
+                                            //              WifiDppChooseSavedWifiNetworkFragment,
+                                            //              WifiDppAddDeviceFragment
 
     abstract protected int getLayout();
 
@@ -61,8 +89,19 @@
     private void initView(View view) {
         mTitle = view.findViewById(R.id.title);
         mDescription = view.findViewById(R.id.description);
+
         mPreviewView = view.findViewById(R.id.preview_view);
+        mDecorateViiew = view.findViewById(R.id.decorate_view);
         mErrorMessage = view.findViewById(R.id.error_message);
+
+        mBarcodeView = view.findViewById(R.id.barcode_view);
+
+        mSavedWifiNetworkList = view.findViewById(R.id.saved_wifi_network_list);
+
+        mProgressBar = view.findViewById(R.id.progress_bar);
+        mWifiApPictureView = view.findViewById(R.id.wifi_ap_picture_view);
+        mChooseDifferentNetwork = view.findViewById(R.id.choose_different_network);
+
         mButtonLeft = view.findViewById(R.id.button_left);
         mButtonRight = view.findViewById(R.id.button_right);
     }
@@ -75,33 +114,76 @@
         mDescription.setText(description);
     }
 
+    /** optional, for WifiDppQrCodeScannerFragment */
     protected void setErrorMessage(String errorMessage) {
         if (mErrorMessage != null) {
             mErrorMessage.setText(errorMessage);
         }
     }
 
+    /**
+     * optional, for WifiDppQrCodeScannerFragment,
+     *               WifiDppChooseSavedWifiNetworkFragment,
+     *               WifiDppAddDeviceFragment
+     */
     protected void setLeftButtonText(String text) {
-        mButtonLeft.setText(text);
+        if (mButtonLeft != null) {
+            mButtonLeft.setText(text);
+        }
     }
 
+    /**
+     * optional, for WifiDppQrCodeScannerFragment,
+     *               WifiDppChooseSavedWifiNetworkFragment,
+     *               WifiDppAddDeviceFragment
+     */
     protected void setRightButtonText(String text) {
-        mButtonRight.setText(text);
+        if (mButtonRight != null) {
+            mButtonRight.setText(text);
+        }
     }
 
+    /**
+     * optional, for WifiDppQrCodeScannerFragment,
+     *               WifiDppChooseSavedWifiNetworkFragment,
+     *               WifiDppAddDeviceFragment
+     */
     protected void hideLeftButton() {
-        mButtonLeft.setVisibility(View.INVISIBLE);
+        if (mButtonLeft != null) {
+            mButtonLeft.setVisibility(View.INVISIBLE);
+        }
     }
 
+    /**
+     * optional, for WifiDppQrCodeScannerFragment,
+     *               WifiDppChooseSavedWifiNetworkFragment,
+     *               WifiDppAddDeviceFragment
+     */
     protected void hideRightButton() {
-        mButtonRight.setVisibility(View.INVISIBLE);
+        if (mButtonRight != null) {
+            mButtonRight.setVisibility(View.INVISIBLE);
+        }
     }
 
+    /**
+     * optional, for WifiDppQrCodeScannerFragment,
+     *               WifiDppChooseSavedWifiNetworkFragment,
+     *               WifiDppAddDeviceFragment
+     */
     protected void setLeftButtonOnClickListener(View.OnClickListener listener) {
-        mButtonLeft.setOnClickListener(listener);
+        if (mButtonLeft != null) {
+            mButtonLeft.setOnClickListener(listener);
+        }
     }
 
+    /**
+     * optional, for WifiDppQrCodeScannerFragment,
+     *               WifiDppChooseSavedWifiNetworkFragment,
+     *               WifiDppAddDeviceFragment
+     */
     protected void setRightButtonOnClickListener(View.OnClickListener listener) {
-        mButtonRight.setOnClickListener(listener);
+        if (mButtonRight != null) {
+            mButtonRight.setOnClickListener(listener);
+        }
     }
 }
diff --git a/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java b/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java
new file mode 100644
index 0000000..9935bf2
--- /dev/null
+++ b/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.wifi.dpp;
+
+import android.os.Bundle;
+
+import com.android.settings.R;
+
+/**
+ * After sharing a saved Wi-Fi network, {@code WifiDppConfiguratorActivity} start with this fragment
+ * to generate a Wi-Fi DPP QR code for other device to initiate as an enrollee.
+ */
+public class WifiDppQrCodeGeneratorFragment extends WifiDppQrCodeBaseFragment {
+    @Override
+    protected int getLayout() {
+        return R.layout.wifi_dpp_qrcode_generator_fragment;
+    }
+
+    @Override
+    public void onActivityCreated (Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+    }
+}
diff --git a/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java b/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java
index 0ee8434..70dade5 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java
@@ -16,40 +16,117 @@
 
 package com.android.settings.wifi.dpp;
 
+import android.annotation.Nullable;
 import android.app.Activity;
 import android.content.Intent;
+import android.graphics.Rect;
 import android.os.Bundle;
-import android.view.LayoutInflater;
+import android.text.TextUtils;
+import android.util.Size;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
 import android.view.View;
 
-import android.view.ViewGroup;
 import com.android.settings.R;
+import com.android.settings.wifi.qrcode.QrCamera;
+import com.android.settings.wifi.qrcode.QrDecorateView;
 
-public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment {
+public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment implements
+        SurfaceHolder.Callback,
+        QrCamera.ScannerCallback {
+    private QrCamera mCamera;
+    private SurfaceView mSurfaceView;
+    private QrDecorateView mDecorateView;
+
     @Override
     protected int getLayout() {
         return R.layout.wifi_dpp_qrcode_scanner_fragment;
     }
 
     @Override
-    public void onActivityCreated (Bundle savedInstanceState) {
-        super.onActivityCreated (savedInstanceState);
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
 
         setTitle(getString(R.string.wifi_dpp_add_device_to_network));
 
-        String ssid = "";
-        Intent intent = getActivity().getIntent();
-        if (intent != null)
-            ssid = intent.getStringExtra(WifiDppConfiguratorActivity.EXTRA_SSID);
-        String description = getString(R.string.wifi_dpp_center_qr_code, ssid);
-        setDescription(description);
+        WifiNetworkConfig wifiNetworkConfig = ((WifiNetworkConfig.Retriever) getActivity())
+                .getWifiNetworkConfig();
+        if (!WifiNetworkConfig.isValidConfig(wifiNetworkConfig)) {
+            throw new IllegalArgumentException("Invalid Wi-Fi network for configuring");
+        }
+        setDescription(getString(R.string.wifi_dpp_center_qr_code, wifiNetworkConfig.getSsid()));
 
         hideRightButton();
 
         setLeftButtonText(getString(android.R.string.cancel));
 
         setLeftButtonOnClickListener((view) -> {
-                getActivity().setResult(Activity.RESULT_CANCELED);
-                getActivity().finish();});
+            getActivity().setResult(Activity.RESULT_CANCELED);
+            getActivity().finish();
+        });
+    }
+
+    @Override
+    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
+        super.onViewCreated(view, savedInstanceState);
+
+        mSurfaceView = (SurfaceView) view.findViewById(R.id.preview_view);
+        final SurfaceHolder surfaceHolder = mSurfaceView.getHolder();
+        surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
+        surfaceHolder.addCallback(this);
+
+        mDecorateView = (QrDecorateView) view.findViewById(R.id.decorate_view);
+    }
+
+    @Override
+    public void surfaceCreated(final SurfaceHolder holder) {
+        initCamera(holder);
+    }
+
+    @Override
+    public void surfaceDestroyed(SurfaceHolder holder) {
+        destroyCamera();
+    }
+
+    @Override
+    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+        // Do nothing
+    }
+
+    @Override
+    public Size getViewSize() {
+        return new Size(mSurfaceView.getWidth(), mSurfaceView.getHeight());
+    }
+
+    @Override
+    public Rect getFramePosition(Size previewSize, int cameraOrientation) {
+        return new Rect(0, 0, previewSize.getHeight(), previewSize.getHeight());
+    }
+
+    @Override
+    public void handleSuccessfulResult(String qrCode) {
+        destroyCamera();
+        mDecorateView.setFocused(true);
+        // TODO(b/120243131): Add a network by Wi-Fi Network config shared via QR code.
+    }
+
+    @Override
+    public void handleCameraFailure() {
+        destroyCamera();
+    }
+
+    private void initCamera(SurfaceHolder holder) {
+        // Check if the camera has already created.
+        if (mCamera == null) {
+            mCamera = new QrCamera(getContext(), this);
+            mCamera.start(holder);
+        }
+    }
+
+    private void destroyCamera() {
+        if (mCamera != null) {
+            mCamera.stop();
+            mCamera = null;
+        }
     }
 }
diff --git a/src/com/android/settings/wifi/dpp/WifiDppUtils.java b/src/com/android/settings/wifi/dpp/WifiDppUtils.java
new file mode 100644
index 0000000..70ef3a8
--- /dev/null
+++ b/src/com/android/settings/wifi/dpp/WifiDppUtils.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.dpp;
+
+import android.content.Intent;
+
+/**
+ * Here are the items shared by both WifiDppConfiguratorActivity & WifiDppEnrolleeActivity
+ */
+public class WifiDppUtils {
+    /** The data is from {@code com.android.settingslib.wifi.AccessPoint.securityToString} */
+    public static final String EXTRA_WIFI_SECURITY = "security";
+
+    /** The data corresponding to {@code WifiConfiguration} SSID */
+    public static final String EXTRA_WIFI_SSID = "ssid";
+
+    /** The data corresponding to {@code WifiConfiguration} preSharedKey */
+    public static final String EXTRA_WIFI_PRE_SHARED_KEY = "preSharedKey";
+
+    /** The data corresponding to {@code WifiConfiguration} hiddenSSID */
+    public static final String EXTRA_WIFI_HIDDEN_SSID = "hiddenSsid";
+
+    /**
+     * Acceptable QR code string may be a standard W-Fi DPP bootstrapping information or the Wi-Fi
+     * Network config format described in
+     * https://github.com/zxing/zxing/wiki/Barcode-Contents#wi-fi-network-config-android-ios-11
+     *
+     * Wi-Fi Network config format example:
+     *
+     *     WIFI:T:WPA;S:mynetwork;P:mypass;;
+     *
+     * parameter Example    Description
+     * T         WPA        Authentication type; can be WEP or WPA, or 'nopass' for no password. Or,
+     *                      omit for no password.
+     * S         mynetwork  Network SSID. Required. Enclose in double quotes if it is an ASCII name,
+     *                      but could be interpreted as hex (i.e. "ABCD")
+     * P         mypass     Password, ignored if T is "nopass" (in which case it may be omitted).
+     *                      Enclose in double quotes if it is an ASCII name, but could be interpreted as
+     *                      hex (i.e. "ABCD")
+     * H         true       Optional. True if the network SSID is hidden.
+     */
+    public static final String EXTRA_QR_CODE = "qrCode";
+}
diff --git a/src/com/android/settings/wifi/dpp/WifiNetworkConfig.java b/src/com/android/settings/wifi/dpp/WifiNetworkConfig.java
new file mode 100644
index 0000000..439de98
--- /dev/null
+++ b/src/com/android/settings/wifi/dpp/WifiNetworkConfig.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.wifi.dpp;
+
+import android.content.Intent;
+import android.text.TextUtils;
+
+/**
+ * Contains the Wi-Fi Network config parameters described in
+ * https://github.com/zxing/zxing/wiki/Barcode-Contents#wi-fi-network-config-android-ios-11
+ *
+ * Checks below members of {@code WifiDppUtils} for more information.
+ * EXTRA_WIFI_SECURITY / EXTRA_WIFI_SSID / EXTRA_WIFI_PRE_SHARED_KEY / EXTRA_WIFI_HIDDEN_SSID /
+ * EXTRA_QR_CODE
+ */
+public class WifiNetworkConfig {
+    private String mSecurity;
+    private String mSsid;
+    private String mPreSharedKey;
+    private boolean mHiddenSsid;
+
+    private WifiNetworkConfig(String security, String ssid, String preSharedKey,
+            boolean hiddenSsid) {
+        mSecurity = security;
+        mSsid = ssid;
+        mPreSharedKey = preSharedKey;
+        mHiddenSsid = hiddenSsid;
+    }
+
+    public WifiNetworkConfig(WifiNetworkConfig config) {
+        mSecurity = new String(config.mSecurity);
+        mSsid = new String(config.mSsid);
+        mPreSharedKey = new String(config.mPreSharedKey);
+        mHiddenSsid = config.mHiddenSsid;
+    }
+
+    /**
+     * Wi-Fi DPP activities should implement this interface for fragments to retrieve the
+     * WifiNetworkConfig for configuration
+     */
+    public interface Retriever {
+        public WifiNetworkConfig getWifiNetworkConfig();
+        public boolean setWifiNetworkConfig(WifiNetworkConfig config);
+    }
+
+    /**
+     * Retrieve WifiNetworkConfig from below 2 intents
+     *
+     * android.settings.WIFI_DPP_CONFIGURATOR_QR_CODE_GENERATOR
+     * android.settings.WIFI_DPP_CONFIGURATOR_QR_CODE_SCANNER
+     */
+    public static WifiNetworkConfig getValidConfigOrNull(Intent intent) {
+        String security = intent.getStringExtra(WifiDppUtils.EXTRA_WIFI_SECURITY);
+        String ssid = intent.getStringExtra(WifiDppUtils.EXTRA_WIFI_SSID);
+        String preSharedKey = intent.getStringExtra(WifiDppUtils.EXTRA_WIFI_PRE_SHARED_KEY);
+        boolean hiddenSsid = intent.getBooleanExtra(WifiDppUtils.EXTRA_WIFI_HIDDEN_SSID, false);
+
+        if (!isValidConfig(security, ssid, hiddenSsid)) {
+            return null;
+        }
+
+        if (ssid == null) {
+            ssid = "";
+        }
+
+        return new WifiNetworkConfig(security, ssid, preSharedKey, hiddenSsid);
+    }
+
+    public static boolean isValidConfig(WifiNetworkConfig config) {
+        if (config == null) {
+            return false;
+        } else {
+            return isValidConfig(config.mSecurity, config.mSsid, config.mHiddenSsid);
+        }
+    }
+
+    public static boolean isValidConfig(String security, String ssid, boolean hiddenSsid) {
+        if (TextUtils.isEmpty(security)) {
+            return false;
+        }
+
+        if (!hiddenSsid && TextUtils.isEmpty(ssid)) {
+            return false;
+        }
+
+        return true;
+    }
+
+    public String getSecurity() {
+        return new String(mSecurity);
+    }
+
+    public String getSsid() {
+        return new String(mSsid);
+    }
+
+    public String getPreSharedKey() {
+        return new String(mPreSharedKey);
+    }
+
+    public boolean getHiddenSsid() {
+        return mHiddenSsid;
+    }
+}
diff --git a/src/com/android/settings/wifi/qrcode/QrCamera.java b/src/com/android/settings/wifi/qrcode/QrCamera.java
index c29236c..dc650b9 100644
--- a/src/com/android/settings/wifi/qrcode/QrCamera.java
+++ b/src/com/android/settings/wifi/qrcode/QrCamera.java
@@ -43,6 +43,7 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.Executors;
 import java.util.concurrent.Semaphore;
 
 import androidx.annotation.VisibleForTesting;
@@ -85,14 +86,26 @@
         mReader.setHints(HINTS);
     }
 
-    void start(SurfaceHolder surfaceHolder) {
+    /**
+     * The function start camera preview and capture pictures to decode QR code continuously in a
+     * background task.
+     *
+     * @param surfaceHolder the Surface to be used for live preview, must already contain a surface
+     *                      when this method is called.
+     */
+    public void start(SurfaceHolder surfaceHolder) {
         if (mDecodeTask == null) {
             mDecodeTask = new DecodingTask(surfaceHolder);
-            mDecodeTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+            // Execute in the separate thread pool to prevent block other AsyncTask.
+            mDecodeTask.executeOnExecutor(Executors.newSingleThreadExecutor());
         }
     }
 
-    void stop() {
+    /**
+     * The function stop camera preview and background decode task. Caller call this function when
+     * the surface is being destroyed.
+     */
+    public void stop() {
         removeMessages(MSG_AUTO_FOCUS);
         if (mDecodeTask != null) {
             mDecodeTask.cancel(true);
@@ -104,7 +117,7 @@
     }
 
     /** The scanner which includes this QrCamera class should implement this */
-    interface ScannerCallback {
+    public interface ScannerCallback {
 
         /**
          * The function used to handle the decoding result of the QR code.
diff --git a/tests/robotests/assets/grandfather_not_implementing_index_provider b/tests/robotests/assets/grandfather_not_implementing_index_provider
index 479ffee..e105dfc 100644
--- a/tests/robotests/assets/grandfather_not_implementing_index_provider
+++ b/tests/robotests/assets/grandfather_not_implementing_index_provider
@@ -27,9 +27,7 @@
 com.android.settings.bluetooth.BluetoothPairingDetail
 com.android.settings.bluetooth.DevicePickerFragment
 com.android.settings.datausage.AppDataUsage
-com.android.settings.datausage.AppDataUsageV2
 com.android.settings.datausage.DataUsageList
-com.android.settings.datausage.DataUsageListV2
 com.android.settings.datetime.timezone.TimeZoneSettings
 com.android.settings.deviceinfo.PrivateVolumeSettings
 com.android.settings.deviceinfo.PublicVolumeSettings
diff --git a/tests/robotests/res/values-mcc999/config.xml b/tests/robotests/res/values-mcc999/config.xml
index 73d2264..c5c552e 100644
--- a/tests/robotests/res/values-mcc999/config.xml
+++ b/tests/robotests/res/values-mcc999/config.xml
@@ -73,8 +73,16 @@
         <item>fake_package/fake_service</item>
     </string-array>
 
+    <!-- Settings intelligence interaction log intent action -->
+    <string name="config_settingsintelligence_log_action" translatable="false">
+        aaa.bbb.ccc
+    </string>
+
     <!-- List of packages that should be whitelisted for slice uri access. Do not translate -->
     <string-array name="slice_whitelist_package_names" translatable="false">
         <item>com.android.settings.slice_whitelist_package</item>
     </string-array>
+
+    <!-- Email address for the homepage contextual cards feedback -->
+    <string name="config_contextual_card_feedback_email" translatable="false">test@test.test</string>
 </resources>
diff --git a/tests/robotests/res/values/themes.xml b/tests/robotests/res/values/themes.xml
index 7bfbe10..41ace18 100644
--- a/tests/robotests/res/values/themes.xml
+++ b/tests/robotests/res/values/themes.xml
@@ -15,6 +15,8 @@
         <item name="colorAccent">#ffffff</item>
         <item name="preferenceTheme">@style/PreferenceTheme</item>
         <item name="android:windowLightStatusBar">true</item>
+        <!-- Define this color for material design -->
+        <item name="colorPrimaryVariant">@android:color/white</item>
     </style>
 
     <style name="ThemeOverlay.SwitchBar.Settings" parent="@android:style/ThemeOverlay.Material.ActionBar">
diff --git a/tests/robotests/src/com/android/settings/SettingsActivityTest.java b/tests/robotests/src/com/android/settings/SettingsActivityTest.java
index 2c98f70..aa41464 100644
--- a/tests/robotests/src/com/android/settings/SettingsActivityTest.java
+++ b/tests/robotests/src/com/android/settings/SettingsActivityTest.java
@@ -28,9 +28,6 @@
 import android.app.ActivityManager;
 import android.content.Context;
 import android.content.Intent;
-import android.os.Bundle;
-import android.provider.Settings.Global;
-import android.view.View;
 
 import androidx.fragment.app.Fragment;
 import androidx.fragment.app.FragmentManager;
@@ -38,16 +35,13 @@
 
 import com.android.settings.core.OnActivityResultListener;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
-import com.android.settings.testutils.shadow.ShadowUtils;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.Robolectric;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -71,29 +65,6 @@
     }
 
     @Test
-    @Config(shadows = ShadowUtils.class)
-    public void onCreate_deviceNotProvisioned_shouldDisableSearch() {
-        Global.putInt(mContext.getContentResolver(), Global.DEVICE_PROVISIONED, 0);
-        final SettingsActivity activity = Robolectric.buildActivity(SettingsActivity.class)
-                .create(Bundle.EMPTY)
-                .get();
-
-        assertThat(activity.findViewById(R.id.search_bar).getVisibility())
-                .isEqualTo(View.INVISIBLE);
-    }
-
-    @Test
-    @Config(shadows = ShadowUtils.class)
-    public void onCreate_deviceProvisioned_shouldEnableSearch() {
-        Global.putInt(mContext.getContentResolver(), Global.DEVICE_PROVISIONED, 1);
-        final SettingsActivity activity = Robolectric.buildActivity(SettingsActivity.class)
-                .create(Bundle.EMPTY)
-                .get();
-
-        assertThat(activity.findViewById(R.id.search_bar).getVisibility()).isEqualTo(View.VISIBLE);
-    }
-
-    @Test
     public void launchSettingFragment_nullExtraShowFragment_shouldNotCrash() {
         when(mActivity.getSupportFragmentManager()).thenReturn(mFragmentManager);
         doReturn(mContext.getContentResolver()).when(mActivity).getContentResolver();
@@ -101,7 +72,7 @@
 
         doReturn(RuntimeEnvironment.application.getClassLoader()).when(mActivity).getClassLoader();
 
-        mActivity.launchSettingFragment(null, true, mock(Intent.class));
+        mActivity.launchSettingFragment(null, mock(Intent.class));
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/applications/AppStorageSettingsTest.java b/tests/robotests/src/com/android/settings/applications/AppStorageSettingsTest.java
index 87eb6a6..114000c 100644
--- a/tests/robotests/src/com/android/settings/applications/AppStorageSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/applications/AppStorageSettingsTest.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.applications;
 
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.nullable;
 import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.doNothing;
@@ -30,9 +32,8 @@
 import android.widget.Button;
 
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
-import com.android.settings.widget.ActionButtonPreference;
-import com.android.settings.widget.ActionButtonPreferenceTest;
 import com.android.settingslib.applications.StorageStatsSource.AppStorageStats;
+import com.android.settingslib.widget.ActionButtonsPreference;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -46,7 +47,7 @@
 
     @Mock
     private AppStorageSizesController mSizesController;
-    private ActionButtonPreference mButtonsPref;
+    private ActionButtonsPreference mButtonsPref;
     private AppStorageSettings mSettings;
     private Button mLeftButton;
     private Button mRightButton;
@@ -58,7 +59,7 @@
         mRightButton = new Button(RuntimeEnvironment.application);
         mSettings = spy(new AppStorageSettings());
         mSettings.mSizeController = mSizesController;
-        mButtonsPref = ActionButtonPreferenceTest.createMock();
+        mButtonsPref = createMock();
         mSettings.mButtonsPref = mButtonsPref;
 
         when(mButtonsPref.setButton1OnClickListener(any(View.OnClickListener.class)))
@@ -103,5 +104,22 @@
         verify(mSettings).handleClearDataClick();
         verify(mSettings).handleClearCacheClick();
     }
+
+    private ActionButtonsPreference createMock() {
+        final ActionButtonsPreference pref = mock(ActionButtonsPreference.class);
+        when(pref.setButton1Text(anyInt())).thenReturn(pref);
+        when(pref.setButton1Icon(anyInt())).thenReturn(pref);
+        when(pref.setButton1Enabled(anyBoolean())).thenReturn(pref);
+        when(pref.setButton1Visible(anyBoolean())).thenReturn(pref);
+        when(pref.setButton1OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
+
+        when(pref.setButton2Text(anyInt())).thenReturn(pref);
+        when(pref.setButton2Icon(anyInt())).thenReturn(pref);
+        when(pref.setButton2Enabled(anyBoolean())).thenReturn(pref);
+        when(pref.setButton2Visible(anyBoolean())).thenReturn(pref);
+        when(pref.setButton2OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
+
+        return pref;
+    }
 }
 
diff --git a/tests/robotests/src/com/android/settings/applications/RecentAppsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/RecentAppsPreferenceControllerTest.java
index 6ff0dba..3d3a05a 100644
--- a/tests/robotests/src/com/android/settings/applications/RecentAppsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/RecentAppsPreferenceControllerTest.java
@@ -51,7 +51,6 @@
 
 import com.android.settings.R;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
-import com.android.settings.testutils.shadow.ShadowPowerManager;
 import com.android.settingslib.applications.AppUtils;
 import com.android.settingslib.applications.ApplicationsState;
 import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
@@ -93,6 +92,8 @@
     private ApplicationsState.AppEntry mAppEntry;
     @Mock
     private ApplicationInfo mApplicationInfo;
+    @Mock
+    private PowerManager mPowerManager;
 
     private Context mContext;
     private RecentAppsPreferenceController mController;
@@ -104,6 +105,7 @@
         doReturn(mUsageStatsManager).when(mContext).getSystemService(Context.USAGE_STATS_SERVICE);
         doReturn(mUserManager).when(mContext).getSystemService(Context.USER_SERVICE);
         doReturn(mPackageManager).when(mContext).getPackageManager();
+        doReturn(mPowerManager).when(mContext).getSystemService(PowerManager.class);
 
         mController = new RecentAppsPreferenceController(mContext, mAppState, null);
         when(mScreen.findPreference(anyString())).thenReturn(mCategory);
@@ -174,15 +176,15 @@
 
         // stat1, stat2 are valid apps. stat3 is invalid.
         when(mAppState.getEntry(stat1.mPackageName, UserHandle.myUserId()))
-            .thenReturn(mAppEntry);
+                .thenReturn(mAppEntry);
         when(mAppState.getEntry(stat2.mPackageName, UserHandle.myUserId()))
-            .thenReturn(mAppEntry);
+                .thenReturn(mAppEntry);
         when(mAppState.getEntry(stat3.mPackageName, UserHandle.myUserId()))
-            .thenReturn(null);
+                .thenReturn(null);
         when(mPackageManager.resolveActivity(any(Intent.class), anyInt()))
-            .thenReturn(new ResolveInfo());
+                .thenReturn(new ResolveInfo());
         when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
-            .thenReturn(stats);
+                .thenReturn(stats);
         mAppEntry.info = mApplicationInfo;
 
         mController.displayPreference(mScreen);
@@ -199,7 +201,7 @@
 
     @Test
     public void display_powerSaverMode_showNoRecents() {
-        mContext.getSystemService(PowerManager.class).setPowerSaveMode(true);
+        when(mPowerManager.isPowerSaveMode()).thenReturn(true);
 
         final List<UsageStats> stats = new ArrayList<>();
         final UsageStats stat1 = new UsageStats();
@@ -251,7 +253,7 @@
 
         // Only the regular app stat1 should have its intent resolve.
         when(mPackageManager.resolveActivity(argThat(intentMatcher(stat1.mPackageName)), anyInt()))
-            .thenReturn(new ResolveInfo());
+                .thenReturn(new ResolveInfo());
 
         when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
                 .thenReturn(stats);
@@ -311,13 +313,13 @@
 
         // stat1, stat2 are not displayable
         when(mAppState.getEntry(stat1.mPackageName, UserHandle.myUserId()))
-            .thenReturn(mock(ApplicationsState.AppEntry.class));
+                .thenReturn(mock(ApplicationsState.AppEntry.class));
         when(mAppState.getEntry(stat2.mPackageName, UserHandle.myUserId()))
-            .thenReturn(mock(ApplicationsState.AppEntry.class));
+                .thenReturn(mock(ApplicationsState.AppEntry.class));
         when(mPackageManager.resolveActivity(any(Intent.class), anyInt()))
-            .thenReturn(new ResolveInfo());
+                .thenReturn(new ResolveInfo());
         when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
-            .thenReturn(stats);
+                .thenReturn(stats);
 
         mController.displayPreference(mScreen);
 
@@ -336,11 +338,11 @@
         stats.add(stat1);
 
         when(mAppState.getEntry(stat1.mPackageName, UserHandle.myUserId()))
-            .thenReturn(mAppEntry);
+                .thenReturn(mAppEntry);
         when(mPackageManager.resolveActivity(any(Intent.class), anyInt()))
-            .thenReturn(new ResolveInfo());
+                .thenReturn(new ResolveInfo());
         when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
-            .thenReturn(stats);
+                .thenReturn(stats);
         mAppEntry.info = mApplicationInfo;
 
         mController.displayPreference(mScreen);
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/AppButtonsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/AppButtonsPreferenceControllerTest.java
index 815c76b..f8dd11b 100644
--- a/tests/robotests/src/com/android/settings/applications/appinfo/AppButtonsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/AppButtonsPreferenceControllerTest.java
@@ -18,6 +18,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.anyString;
@@ -42,18 +43,18 @@
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.os.UserManager;
+import android.view.View;
 
 import com.android.settings.R;
 import com.android.settings.SettingsActivity;
 import com.android.settings.core.InstrumentedPreferenceFragment;
 import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
-import com.android.settings.widget.ActionButtonPreference;
-import com.android.settings.widget.ActionButtonPreferenceTest;
 import com.android.settingslib.applications.AppUtils;
 import com.android.settingslib.applications.ApplicationsState;
 import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
 import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.widget.ActionButtonsPreference;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -99,9 +100,8 @@
     @Mock
     private PackageInfo mPackageInfo;
 
-    private ActionButtonPreference mButtonPrefs;
-
     private Intent mUninstallIntent;
+    private ActionButtonsPreference mButtonPrefs;
     private AppButtonsPreferenceController mController;
 
     @Before
@@ -127,7 +127,7 @@
         mPackageInfo.packageName = PACKAGE_NAME;
         mPackageInfo.applicationInfo = mAppInfo;
 
-        mButtonPrefs = ActionButtonPreferenceTest.createMock();
+        mButtonPrefs = createMock();
         mController.mButtonsPref = mButtonPrefs;
         mController.mPackageInfo = mPackageInfo;
 
@@ -175,6 +175,22 @@
     }
 
     @Test
+    public void updateOpenButton_noLaunchIntent_buttonShouldBeDisable() {
+        mController.updateOpenButton();
+
+        verify(mButtonPrefs).setButton1Visible(false);
+    }
+
+    @Test
+    public void updateOpenButton_haveLaunchIntent_buttonShouldBeEnable() {
+        doReturn(new Intent()).when(mPackageManger).getLaunchIntentForPackage(anyString());
+
+        mController.updateOpenButton();
+
+        verify(mButtonPrefs).setButton1Visible(true);
+    }
+
+    @Test
     public void updateUninstallButton_isSystemApp_handleAsDisableableButton() {
         doReturn(false).when(mController).handleDisableable();
         mAppInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
@@ -182,7 +198,7 @@
         mController.updateUninstallButton();
 
         verify(mController).handleDisableable();
-        verify(mButtonPrefs).setButton1Enabled(false);
+        verify(mButtonPrefs).setButton2Enabled(false);
     }
 
     @Test
@@ -220,7 +236,7 @@
         mController.updateUninstallButton();
 
         verify(mController).handleDisableable();
-        verify(mButtonPrefs).setButton1Enabled(false);
+        verify(mButtonPrefs).setButton2Enabled(false);
     }
 
     @Test
@@ -229,7 +245,7 @@
 
         mController.updateUninstallButton();
 
-        verify(mButtonPrefs).setButton1Enabled(false);
+        verify(mButtonPrefs).setButton2Enabled(false);
     }
 
     @Test
@@ -239,7 +255,7 @@
 
         mController.updateUninstallButton();
 
-        verify(mButtonPrefs).setButton1Enabled(false);
+        verify(mButtonPrefs).setButton2Enabled(false);
     }
 
     @Test
@@ -248,7 +264,7 @@
 
         mController.updateUninstallButton();
 
-        verify(mButtonPrefs).setButton1Enabled(false);
+        verify(mButtonPrefs).setButton2Enabled(false);
     }
 
     @Test
@@ -258,7 +274,7 @@
 
         mController.updateUninstallButton();
 
-        verify(mButtonPrefs).setButton1Enabled(false);
+        verify(mButtonPrefs).setButton2Enabled(false);
     }
 
     @Test
@@ -308,7 +324,7 @@
 
         final boolean controllable = mController.handleDisableable();
 
-        verify(mButtonPrefs).setButton1Text(R.string.uninstall_text);
+        verify(mButtonPrefs).setButton2Text(R.string.uninstall_text);
         assertThat(controllable).isFalse();
     }
 
@@ -320,7 +336,7 @@
 
         final boolean controllable = mController.handleDisableable();
 
-        verify(mButtonPrefs).setButton1Text(R.string.uninstall_text);
+        verify(mButtonPrefs).setButton2Text(R.string.uninstall_text);
         assertThat(controllable).isTrue();
     }
 
@@ -332,7 +348,7 @@
 
         final boolean controllable = mController.handleDisableable();
 
-        verify(mButtonPrefs).setButton1Text(R.string.install_text);
+        verify(mButtonPrefs).setButton2Text(R.string.install_text);
         assertThat(controllable).isTrue();
     }
 
@@ -390,4 +406,15 @@
             return SettingsEnums.PAGE_UNKNOWN;
         }
     }
+
+    private ActionButtonsPreference createMock() {
+        final ActionButtonsPreference pref = mock(ActionButtonsPreference.class);
+        when(pref.setButton2Text(anyInt())).thenReturn(pref);
+        when(pref.setButton2Icon(anyInt())).thenReturn(pref);
+        when(pref.setButton2Enabled(anyBoolean())).thenReturn(pref);
+        when(pref.setButton2Visible(anyBoolean())).thenReturn(pref);
+        when(pref.setButton2OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
+
+        return pref;
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerTest.java
index 1adc678..fe70c7e 100644
--- a/tests/robotests/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * 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.
@@ -16,13 +16,12 @@
 
 package com.android.settings.applications.appinfo;
 
-import static com.android.settings.core.FeatureFlags.DATA_USAGE_V2;
-
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.nullable;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
@@ -33,12 +32,7 @@
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.net.ConnectivityManager;
-import android.net.INetworkStatsSession;
 import android.os.Bundle;
-import android.util.FeatureFlagUtils;
-
-import androidx.loader.app.LoaderManager;
-import androidx.preference.Preference;
 
 import com.android.settings.core.BasePreferenceController;
 import com.android.settings.datausage.AppDataUsage;
@@ -49,9 +43,12 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
+
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.util.ReflectionHelpers;
+
+import androidx.loader.app.LoaderManager;
+import androidx.preference.Preference;
 
 @RunWith(SettingsRobolectricTestRunner.class)
 public class AppDataUsagePreferenceControllerTest {
@@ -68,7 +65,6 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mContext = spy(RuntimeEnvironment.application.getApplicationContext());
-        FeatureFlagUtils.setEnabled(mContext, DATA_USAGE_V2, false);
         mController = spy(new AppDataUsagePreferenceController(mContext, "test_key"));
         mController.setParentFragment(mFragment);
     }
@@ -90,8 +86,9 @@
     }
 
     @Test
-    public void onResume_noSession_shouldNotRestartDataLoader() {
+    public void onResume_notAvailable_shouldNotRestartDataLoader() {
         doReturn(mLoaderManager).when(mFragment).getLoaderManager();
+        doReturn(BasePreferenceController.CONDITIONALLY_UNAVAILABLE).when(mController).getAvailabilityStatus();
 
         mController.onResume();
 
@@ -100,26 +97,26 @@
     }
 
     @Test
-    public void onResume_hasSession_shouldRestartDataLoader() {
+    public void onResume_isAvailable_shouldRestartDataLoader() {
         final ConnectivityManager connectivityManager = mock(ConnectivityManager.class);
         when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE))
                 .thenReturn(connectivityManager);
         when(connectivityManager.isNetworkSupported(anyInt())).thenReturn(true);
         doReturn(mLoaderManager).when(mFragment).getLoaderManager();
-        ReflectionHelpers.setField(mController, "mStatsSession", mock(INetworkStatsSession.class));
+        doReturn(BasePreferenceController.AVAILABLE).when(mController).getAvailabilityStatus();
         final AppEntry appEntry = mock(AppEntry.class);
         appEntry.info = new ApplicationInfo();
         when(mFragment.getAppEntry()).thenReturn(appEntry);
 
         mController.onResume();
 
-        verify(mLoaderManager).restartLoader(
-                eq(AppInfoDashboardFragment.LOADER_CHART_DATA), any(Bundle.class), eq(mController));
+        verify(mLoaderManager).restartLoader(eq(AppInfoDashboardFragment.LOADER_CHART_DATA),
+                nullable(Bundle.class), eq(mController));
     }
 
     @Test
     public void onPause_shouldDestroyDataLoader() {
-        ReflectionHelpers.setField(mController, "mStatsSession", mock(INetworkStatsSession.class));
+        doReturn(BasePreferenceController.AVAILABLE).when(mController).getAvailabilityStatus();
         doReturn(mLoaderManager).when(mFragment).getLoaderManager();
 
         mController.onPause();
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerV2Test.java b/tests/robotests/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerV2Test.java
deleted file mode 100644
index 708222e..0000000
--- a/tests/robotests/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerV2Test.java
+++ /dev/null
@@ -1,143 +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.appinfo;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.ArgumentMatchers.nullable;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.net.ConnectivityManager;
-import android.os.Bundle;
-
-import com.android.settings.core.BasePreferenceController;
-import com.android.settings.core.FeatureFlags;
-import com.android.settings.datausage.AppDataUsageV2;
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
-import com.android.settingslib.applications.ApplicationsState.AppEntry;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import android.util.FeatureFlagUtils;
-
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RuntimeEnvironment;
-
-import androidx.loader.app.LoaderManager;
-import androidx.preference.Preference;
-
-@RunWith(SettingsRobolectricTestRunner.class)
-public class AppDataUsagePreferenceControllerV2Test {
-
-    @Mock
-    private LoaderManager mLoaderManager;
-    @Mock
-    private AppInfoDashboardFragment mFragment;
-
-    private Context mContext;
-    private AppDataUsagePreferenceControllerV2 mController;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mContext = spy(RuntimeEnvironment.application.getApplicationContext());
-        mController = spy(new AppDataUsagePreferenceControllerV2(mContext, "test_key"));
-        mController.setParentFragment(mFragment);
-        FeatureFlagUtils.setEnabled(mContext, FeatureFlags.DATA_USAGE_V2, true);
-    }
-
-    @Test
-    public void getAvailabilityStatus_bandwidthControlEnabled_shouldReturnAvailable() {
-        doReturn(true).when(mController).isBandwidthControlEnabled();
-
-        assertThat(mController.getAvailabilityStatus())
-            .isEqualTo(BasePreferenceController.AVAILABLE);
-    }
-
-    @Test
-    public void getAvailabilityStatus_bandwidthControlDisabled_shouldReturnDisabled() {
-        doReturn(false).when(mController).isBandwidthControlEnabled();
-
-        assertThat(mController.getAvailabilityStatus())
-            .isEqualTo(BasePreferenceController.CONDITIONALLY_UNAVAILABLE);
-    }
-
-    @Test
-    public void onResume_notAvailable_shouldNotRestartDataLoader() {
-        FeatureFlagUtils.setEnabled(mContext, FeatureFlags.DATA_USAGE_V2, false);
-        doReturn(mLoaderManager).when(mFragment).getLoaderManager();
-
-        mController.onResume();
-
-        verify(mLoaderManager, never()).restartLoader(
-                AppInfoDashboardFragment.LOADER_CHART_DATA, Bundle.EMPTY, mController);
-    }
-
-    @Test
-    public void onResume_isAvailable_shouldRestartDataLoader() {
-        final ConnectivityManager connectivityManager = mock(ConnectivityManager.class);
-        when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE))
-                .thenReturn(connectivityManager);
-        when(connectivityManager.isNetworkSupported(anyInt())).thenReturn(true);
-        doReturn(mLoaderManager).when(mFragment).getLoaderManager();
-        doReturn(BasePreferenceController.AVAILABLE).when(mController).getAvailabilityStatus();
-        final AppEntry appEntry = mock(AppEntry.class);
-        appEntry.info = new ApplicationInfo();
-        when(mFragment.getAppEntry()).thenReturn(appEntry);
-
-        mController.onResume();
-
-        verify(mLoaderManager).restartLoader(eq(AppInfoDashboardFragment.LOADER_CHART_DATA),
-                nullable(Bundle.class), eq(mController));
-    }
-
-    @Test
-    public void onPause_shouldDestroyDataLoader() {
-        doReturn(BasePreferenceController.AVAILABLE).when(mController).getAvailabilityStatus();
-        doReturn(mLoaderManager).when(mFragment).getLoaderManager();
-
-        mController.onPause();
-
-        verify(mLoaderManager).destroyLoader(AppInfoDashboardFragment.LOADER_CHART_DATA);
-    }
-
-    @Test
-    public void getDetailFragmentClass_shouldReturnAppDataUsage() {
-        assertThat(mController.getDetailFragmentClass()).isEqualTo(AppDataUsageV2.class);
-    }
-
-    @Test
-    public void updateState_shouldUpdatePreferenceSummary() {
-        final Preference preference = mock(Preference.class);
-
-        mController.updateState(preference);
-
-        verify(preference).setSummary(any());
-    }
-}
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsButtonsControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsButtonsControllerTest.java
index 094ec80..d8be01f 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsButtonsControllerTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsButtonsControllerTest.java
@@ -18,6 +18,8 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
@@ -34,8 +36,7 @@
 import com.android.settings.R;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.testutils.shadow.SettingsShadowBluetoothDevice;
-import com.android.settings.widget.ActionButtonPreference;
-import com.android.settings.widget.ActionButtonPreferenceTest;
+import com.android.settingslib.widget.ActionButtonsPreference;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -47,7 +48,7 @@
 @Config(shadows = SettingsShadowBluetoothDevice.class)
 public class BluetoothDetailsButtonsControllerTest extends BluetoothDetailsControllerTestBase {
     private BluetoothDetailsButtonsController mController;
-    private ActionButtonPreference mButtonsPref;
+    private ActionButtonsPreference mButtonsPref;
     private Button mConnectButton;
     private Button mForgetButton;
 
@@ -60,8 +61,9 @@
         mConnectButton = buttons.findViewById(R.id.button2);
         mForgetButton = buttons.findViewById(R.id.button1);
         mController =
-            new BluetoothDetailsButtonsController(mContext, mFragment, mCachedDevice, mLifecycle);
-        mButtonsPref = ActionButtonPreferenceTest.createMock();
+                new BluetoothDetailsButtonsController(mContext, mFragment, mCachedDevice,
+                        mLifecycle);
+        mButtonsPref = createMock();
         when(mButtonsPref.getKey()).thenReturn(mController.getPreferenceKey());
         when(mButtonsPref.setButton2OnClickListener(any(View.OnClickListener.class)))
                 .thenAnswer(invocation -> {
@@ -186,4 +188,21 @@
 
         verify(mButtonsPref).setButton2Enabled(false);
     }
+
+    private ActionButtonsPreference createMock() {
+        final ActionButtonsPreference pref = mock(ActionButtonsPreference.class);
+        when(pref.setButton1Text(anyInt())).thenReturn(pref);
+        when(pref.setButton1Icon(anyInt())).thenReturn(pref);
+        when(pref.setButton1Enabled(anyBoolean())).thenReturn(pref);
+        when(pref.setButton1Visible(anyBoolean())).thenReturn(pref);
+        when(pref.setButton1OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
+
+        when(pref.setButton2Text(anyInt())).thenReturn(pref);
+        when(pref.setButton2Icon(anyInt())).thenReturn(pref);
+        when(pref.setButton2Enabled(anyBoolean())).thenReturn(pref);
+        when(pref.setButton2Visible(anyBoolean())).thenReturn(pref);
+        when(pref.setButton2OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
+
+        return pref;
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java b/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java
index 01fa32f..333c706 100644
--- a/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java
+++ b/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java
@@ -19,6 +19,7 @@
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyBoolean;
 import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyLong;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
 import static org.mockito.Mockito.doNothing;
@@ -28,12 +29,14 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.content.Context;
 import android.content.pm.PackageManager;
 import android.net.NetworkPolicyManager;
 import android.os.Bundle;
 import android.util.ArraySet;
 import android.view.View;
 
+import androidx.preference.Preference;
 import androidx.preference.PreferenceManager;
 import androidx.preference.PreferenceScreen;
 
@@ -45,6 +48,7 @@
 import com.android.settingslib.AppItem;
 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
 import com.android.settingslib.RestrictedSwitchPreference;
+import com.android.settingslib.net.NetworkCycleDataForUid;
 
 import org.junit.After;
 import org.junit.Before;
@@ -57,6 +61,9 @@
 import org.robolectric.annotation.Config;
 import org.robolectric.util.ReflectionHelpers;
 
+import java.util.ArrayList;
+import java.util.List;
+
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(shadows = {ShadowEntityHeaderController.class, ShadowRestrictedLockUtilsInternal.class})
 public class AppDataUsageTest {
@@ -172,4 +179,49 @@
         verify(restrictBackgroundPref).setDisabledByAdmin(any(EnforcedAdmin.class));
         verify(unrestrictedDataPref).setDisabledByAdmin(any(EnforcedAdmin.class));
     }
+
+    @Test
+    public void bindData_noAppUsageData_shouldHideCycleSpinner() {
+        mFragment = spy(new AppDataUsage());
+        final SpinnerPreference cycle = mock(SpinnerPreference.class);
+        ReflectionHelpers.setField(mFragment, "mCycle", cycle);
+        final Preference preference = mock(Preference.class);
+        ReflectionHelpers.setField(mFragment, "mBackgroundUsage", preference);
+        ReflectionHelpers.setField(mFragment, "mForegroundUsage", preference);
+        ReflectionHelpers.setField(mFragment, "mTotalUsage", preference);
+        doReturn(RuntimeEnvironment.application).when(mFragment).getContext();
+
+        mFragment.bindData(0 /* position */);
+
+        verify(cycle).setVisible(false);
+    }
+
+    @Test
+    public void bindData_hasAppUsageData_shouldShowCycleSpinnerAndUpdateUsageSummary() {
+        mFragment = spy(new AppDataUsage());
+        final Context context = RuntimeEnvironment.application;
+        doReturn(context).when(mFragment).getContext();
+        final long backgroundBytes = 1234L;
+        final long foregroundBytes = 5678L;
+        final List<NetworkCycleDataForUid> appUsage = new ArrayList<>();
+        appUsage.add(new NetworkCycleDataForUid.Builder()
+            .setBackgroundUsage(backgroundBytes).setForegroundUsage(foregroundBytes).build());
+        ReflectionHelpers.setField(mFragment, "mUsageData", appUsage);
+        final Preference backgroundPref = mock(Preference.class);
+        ReflectionHelpers.setField(mFragment, "mBackgroundUsage", backgroundPref);
+        final Preference foregroundPref = mock(Preference.class);
+        ReflectionHelpers.setField(mFragment, "mForegroundUsage", foregroundPref);
+        final Preference totalPref = mock(Preference.class);
+        ReflectionHelpers.setField(mFragment, "mTotalUsage", totalPref);
+        final SpinnerPreference cycle = mock(SpinnerPreference.class);
+        ReflectionHelpers.setField(mFragment, "mCycle", cycle);
+
+        mFragment.bindData(0 /* position */);
+
+        verify(cycle).setVisible(true);
+        verify(totalPref).setSummary(
+            DataUsageUtils.formatDataUsage(context, backgroundBytes + foregroundBytes));
+        verify(backgroundPref).setSummary(DataUsageUtils.formatDataUsage(context, backgroundBytes));
+        verify(foregroundPref).setSummary(DataUsageUtils.formatDataUsage(context, foregroundBytes));
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/datausage/AppDataUsageV2Test.java b/tests/robotests/src/com/android/settings/datausage/AppDataUsageV2Test.java
deleted file mode 100644
index 8796a39..0000000
--- a/tests/robotests/src/com/android/settings/datausage/AppDataUsageV2Test.java
+++ /dev/null
@@ -1,227 +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.datausage;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.net.NetworkPolicyManager;
-import android.os.Bundle;
-import android.util.ArraySet;
-import android.view.View;
-
-import androidx.preference.Preference;
-import androidx.preference.PreferenceManager;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settings.testutils.FakeFeatureFactory;
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
-import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
-import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal;
-import com.android.settings.widget.EntityHeaderController;
-import com.android.settingslib.AppItem;
-import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
-import com.android.settingslib.RestrictedSwitchPreference;
-import com.android.settingslib.net.NetworkCycleDataForUid;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Answers;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-import org.robolectric.util.ReflectionHelpers;
-
-import java.util.ArrayList;
-import java.util.List;
-
-@RunWith(SettingsRobolectricTestRunner.class)
-@Config(shadows = {ShadowEntityHeaderController.class, ShadowRestrictedLockUtilsInternal.class})
-public class AppDataUsageV2Test {
-
-    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
-    private EntityHeaderController mHeaderController;
-    @Mock
-    private PackageManager mPackageManager;
-
-    private AppDataUsageV2 mFragment;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        FakeFeatureFactory.setupForTest();
-    }
-
-    @After
-    public void tearDown() {
-        ShadowEntityHeaderController.reset();
-    }
-
-    @Test
-    public void bindAppHeader_allWorkApps_shouldNotShowAppInfoLink() {
-        ShadowEntityHeaderController.setUseMock(mHeaderController);
-        when(mHeaderController.setRecyclerView(any(), any())).thenReturn(mHeaderController);
-        when(mHeaderController.setUid(anyInt())).thenReturn(mHeaderController);
-
-        mFragment = spy(new AppDataUsageV2());
-
-        when(mFragment.getPreferenceManager())
-            .thenReturn(mock(PreferenceManager.class, RETURNS_DEEP_STUBS));
-        doReturn(mock(PreferenceScreen.class)).when(mFragment).getPreferenceScreen();
-        ReflectionHelpers.setField(mFragment, "mAppItem", mock(AppItem.class));
-
-        mFragment.onViewCreated(new View(RuntimeEnvironment.application), new Bundle());
-
-        verify(mHeaderController).setHasAppInfoLink(false);
-    }
-
-    @Test
-    public void bindAppHeader_workApp_shouldSetWorkAppUid() throws
-            PackageManager.NameNotFoundException {
-        final int fakeUserId = 100;
-
-        mFragment = spy(new AppDataUsageV2());
-        final ArraySet<String> packages = new ArraySet<>();
-        packages.add("pkg");
-        final AppItem appItem = new AppItem(123456789);
-
-        ReflectionHelpers.setField(mFragment, "mPackageManager", mPackageManager);
-        ReflectionHelpers.setField(mFragment, "mAppItem", appItem);
-        ReflectionHelpers.setField(mFragment, "mPackages", packages);
-
-        when(mPackageManager.getPackageUidAsUser(anyString(), anyInt()))
-                .thenReturn(fakeUserId);
-
-        ShadowEntityHeaderController.setUseMock(mHeaderController);
-        when(mHeaderController.setRecyclerView(any(), any())).thenReturn(mHeaderController);
-        when(mHeaderController.setUid(fakeUserId)).thenReturn(mHeaderController);
-        when(mHeaderController.setHasAppInfoLink(anyBoolean())).thenReturn(mHeaderController);
-
-        when(mFragment.getPreferenceManager())
-            .thenReturn(mock(PreferenceManager.class, RETURNS_DEEP_STUBS));
-        doReturn(mock(PreferenceScreen.class)).when(mFragment).getPreferenceScreen();
-
-        mFragment.onViewCreated(new View(RuntimeEnvironment.application), new Bundle());
-
-        verify(mHeaderController).setHasAppInfoLink(true);
-        verify(mHeaderController).setUid(fakeUserId);
-    }
-
-    @Test
-    public void changePreference_backgroundData_shouldUpdateUI() {
-        mFragment = spy(new AppDataUsageV2());
-        final AppItem appItem = new AppItem(123456789);
-        final RestrictedSwitchPreference pref = mock(RestrictedSwitchPreference.class);
-        final DataSaverBackend dataSaverBackend = mock(DataSaverBackend.class);
-        ReflectionHelpers.setField(mFragment, "mAppItem", appItem);
-        ReflectionHelpers.setField(mFragment, "mRestrictBackground", pref);
-        ReflectionHelpers.setField(mFragment, "mDataSaverBackend", dataSaverBackend);
-
-        doNothing().when(mFragment).updatePrefs();
-
-        mFragment.onPreferenceChange(pref, true /* value */);
-
-        verify(mFragment).updatePrefs();
-    }
-
-    @Test
-    public void updatePrefs_restrictedByAdmin_shouldDisablePreference() {
-        mFragment = spy(new AppDataUsageV2());
-        final int testUid = 123123;
-        final AppItem appItem = new AppItem(testUid);
-        final RestrictedSwitchPreference restrictBackgroundPref
-                = mock(RestrictedSwitchPreference.class);
-        final RestrictedSwitchPreference unrestrictedDataPref
-                = mock(RestrictedSwitchPreference.class);
-        final DataSaverBackend dataSaverBackend = mock(DataSaverBackend.class);
-        final NetworkPolicyManager networkPolicyManager = mock(NetworkPolicyManager.class);
-        ReflectionHelpers.setField(mFragment, "mAppItem", appItem);
-        ReflectionHelpers.setField(mFragment, "mRestrictBackground", restrictBackgroundPref);
-        ReflectionHelpers.setField(mFragment, "mUnrestrictedData", unrestrictedDataPref);
-        ReflectionHelpers.setField(mFragment, "mDataSaverBackend", dataSaverBackend);
-        ReflectionHelpers.setField(mFragment.services, "mPolicyManager", networkPolicyManager);
-
-        ShadowRestrictedLockUtilsInternal.setRestricted(true);
-        doReturn(NetworkPolicyManager.POLICY_NONE).when(networkPolicyManager)
-                .getUidPolicy(testUid);
-
-        mFragment.updatePrefs();
-
-        verify(restrictBackgroundPref).setDisabledByAdmin(any(EnforcedAdmin.class));
-        verify(unrestrictedDataPref).setDisabledByAdmin(any(EnforcedAdmin.class));
-    }
-
-    @Test
-    public void bindData_noAppUsageData_shouldHideCycleSpinner() {
-        mFragment = spy(new AppDataUsageV2());
-        final SpinnerPreference cycle = mock(SpinnerPreference.class);
-        ReflectionHelpers.setField(mFragment, "mCycle", cycle);
-        final Preference preference = mock(Preference.class);
-        ReflectionHelpers.setField(mFragment, "mBackgroundUsage", preference);
-        ReflectionHelpers.setField(mFragment, "mForegroundUsage", preference);
-        ReflectionHelpers.setField(mFragment, "mTotalUsage", preference);
-        doReturn(RuntimeEnvironment.application).when(mFragment).getContext();
-
-        mFragment.bindData(0 /* position */);
-
-        verify(cycle).setVisible(false);
-    }
-
-    @Test
-    public void bindData_hasAppUsageData_shouldShowCycleSpinnerAndUpdateUsageSummary() {
-        mFragment = spy(new AppDataUsageV2());
-        final Context context = RuntimeEnvironment.application;
-        doReturn(context).when(mFragment).getContext();
-        final long backgroundBytes = 1234L;
-        final long foregroundBytes = 5678L;
-        final List<NetworkCycleDataForUid> appUsage = new ArrayList<>();
-        appUsage.add(new NetworkCycleDataForUid.Builder()
-            .setBackgroundUsage(backgroundBytes).setForegroundUsage(foregroundBytes).build());
-        ReflectionHelpers.setField(mFragment, "mUsageData", appUsage);
-        final Preference backgroundPref = mock(Preference.class);
-        ReflectionHelpers.setField(mFragment, "mBackgroundUsage", backgroundPref);
-        final Preference foregroundPref = mock(Preference.class);
-        ReflectionHelpers.setField(mFragment, "mForegroundUsage", foregroundPref);
-        final Preference totalPref = mock(Preference.class);
-        ReflectionHelpers.setField(mFragment, "mTotalUsage", totalPref);
-        final SpinnerPreference cycle = mock(SpinnerPreference.class);
-        ReflectionHelpers.setField(mFragment, "mCycle", cycle);
-
-        mFragment.bindData(0 /* position */);
-
-        verify(cycle).setVisible(true);
-        verify(totalPref).setSummary(
-            DataUsageUtils.formatDataUsage(context, backgroundBytes + foregroundBytes));
-        verify(backgroundPref).setSummary(DataUsageUtils.formatDataUsage(context, backgroundBytes));
-        verify(foregroundPref).setSummary(DataUsageUtils.formatDataUsage(context, foregroundBytes));
-    }
-}
diff --git a/tests/robotests/src/com/android/settings/datausage/ChartDataUsagePreferenceTest.java b/tests/robotests/src/com/android/settings/datausage/ChartDataUsagePreferenceTest.java
index ce58ae2..af56029 100644
--- a/tests/robotests/src/com/android/settings/datausage/ChartDataUsagePreferenceTest.java
+++ b/tests/robotests/src/com/android/settings/datausage/ChartDataUsagePreferenceTest.java
@@ -18,17 +18,15 @@
 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.verify;
-import static org.mockito.Mockito.when;
 
 import android.content.Context;
-import android.net.NetworkStatsHistory;
-import android.net.NetworkStatsHistory.Entry;
 import android.util.SparseIntArray;
 
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.widget.UsageView;
+import com.android.settingslib.net.NetworkCycleChartData;
+import com.android.settingslib.net.NetworkCycleData;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -37,14 +35,17 @@
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RuntimeEnvironment;
 
+import java.util.ArrayList;
+import java.util.List;
+
 @RunWith(SettingsRobolectricTestRunner.class)
 public class ChartDataUsagePreferenceTest {
 
-    private static final long MILLIS_IN_ONE_HOUR = 60 * 60 * 1000;
-    private static final long MILLIS_IN_ONE_DAY = 24 * MILLIS_IN_ONE_HOUR;
-    private static final long TIMESTAMP_NOW = Integer.MAX_VALUE;
+    private static final long TIMESTAMP_START = 1521583200000L;
+    private static final long TIMESTAMP_END = 1521676800000L;
 
-    private NetworkStatsHistory mNetworkStatsHistory;
+    private List<NetworkCycleData> mNetworkCycleData;
+    private NetworkCycleChartData mNetworkCycleChartData;
     private Context mContext;
     private ChartDataUsagePreference mPreference;
 
@@ -54,23 +55,17 @@
 
         mContext = RuntimeEnvironment.application;
         mPreference = new ChartDataUsagePreference(mContext, null);
-        mNetworkStatsHistory = spy(new NetworkStatsHistory(MILLIS_IN_ONE_HOUR, 10));
-        addTestNetworkEntries();
-        mPreference.setNetworkStats(mNetworkStatsHistory);
+        createTestNetworkData();
+        mPreference.setNetworkCycleData(mNetworkCycleChartData);
     }
 
     @Test
-    public void calcPoints_notStartOfData_shouldAddDataPointsOnly() {
-        final long start = TIMESTAMP_NOW - 20 * MILLIS_IN_ONE_DAY;
-        final long end = TIMESTAMP_NOW - 5 * MILLIS_IN_ONE_DAY;
-        mPreference.setVisibleRange(start, end);
-        when(mNetworkStatsHistory.getIndexAfter(start)).thenReturn(2);
-        when(mNetworkStatsHistory.getIndexAfter(end)).thenReturn(7);
+    public void calcPoints_dataAvailableFromCycleStart_shouldAddDataPointsOnly() {
         final UsageView usageView = mock(UsageView.class);
         final ArgumentCaptor<SparseIntArray> pointsCaptor =
                 ArgumentCaptor.forClass(SparseIntArray.class);
 
-        mPreference.calcPoints(usageView);
+        mPreference.calcPoints(usageView, mNetworkCycleData.subList(0, 5));
 
         verify(usageView).addPath(pointsCaptor.capture());
         SparseIntArray points = pointsCaptor.getValue();
@@ -79,17 +74,12 @@
     }
 
     @Test
-    public void calcPoints_startOfData_shouldIndicateStartOfData() {
-        final long start = TIMESTAMP_NOW - 20 * MILLIS_IN_ONE_DAY;
-        final long end = TIMESTAMP_NOW - 5 * MILLIS_IN_ONE_DAY;
-        mPreference.setVisibleRange(start, end);
-        when(mNetworkStatsHistory.getIndexAfter(start)).thenReturn(0);
-        when(mNetworkStatsHistory.getIndexAfter(end)).thenReturn(5);
+    public void calcPoints_dataNotAvailableAtCycleStart_shouldIndicateStartOfData() {
         final UsageView usageView = mock(UsageView.class);
         final ArgumentCaptor<SparseIntArray> pointsCaptor =
                 ArgumentCaptor.forClass(SparseIntArray.class);
 
-        mPreference.calcPoints(usageView);
+        mPreference.calcPoints(usageView, mNetworkCycleData.subList(2, 7));
 
         verify(usageView).addPath(pointsCaptor.capture());
         SparseIntArray points = pointsCaptor.getValue();
@@ -98,35 +88,29 @@
         assertThat(points.valueAt(1)).isEqualTo(-1);
     }
 
-    private void addTestNetworkEntries() {
-        // create 10 arbitary network data
-        mNetworkStatsHistory.setValues(0, createEntry(1521583200000L, 743823454L, 16574289L));
-        mNetworkStatsHistory.setValues(1, createEntry(1521586800000L, 64396L, 160364L));
-        mNetworkStatsHistory.setValues(2, createEntry(1521590400000L, 2832L, 5299L));
-        mNetworkStatsHistory.setValues(3, createEntry(1521655200000L, 83849690L, 3558238L));
-        mNetworkStatsHistory.setValues(4, createEntry(1521658800000L, 1883657L, 353330L));
-        mNetworkStatsHistory.setValues(5, createEntry(1521662400000L, 705259L, 279065L));
-        mNetworkStatsHistory.setValues(6, createEntry(1521666000000L, 216169L, 155302L));
-        mNetworkStatsHistory.setValues(7, createEntry(1521669600000L, 6069175L, 427581L));
-        mNetworkStatsHistory.setValues(8, createEntry(1521673200000L, 120389L, 110807L));
-        mNetworkStatsHistory.setValues(9, createEntry(1521676800000L, 29947L, 73257L));
+    private void createTestNetworkData() {
+        mNetworkCycleData = new ArrayList<>();
+        // create 10 arbitrary network data
+        mNetworkCycleData.add(createNetworkCycleData(1521583200000L, 1521586800000L, 743823454L));
+        mNetworkCycleData.add(createNetworkCycleData(1521586800000L, 1521590400000L, 64396L));
+        mNetworkCycleData.add(createNetworkCycleData(1521590400000L, 1521655200000L, 2832L));
+        mNetworkCycleData.add(createNetworkCycleData(1521655200000L, 1521658800000L, 83849690L));
+        mNetworkCycleData.add(createNetworkCycleData(1521658800000L, 1521662400000L, 1883657L));
+        mNetworkCycleData.add(createNetworkCycleData(1521662400000L, 1521666000000L, 705259L));
+        mNetworkCycleData.add(createNetworkCycleData(1521666000000L, 1521669600000L, 216169L));
+        mNetworkCycleData.add(createNetworkCycleData(1521669600000L, 1521673200000L, 6069175L));
+        mNetworkCycleData.add(createNetworkCycleData(1521673200000L, 1521676800000L, 120389L));
+        mNetworkCycleData.add(createNetworkCycleData(1521676800000L, 1521678800000L, 29947L));
+
+        final NetworkCycleChartData.Builder builder = new NetworkCycleChartData.Builder();
+        builder.setUsageBuckets(mNetworkCycleData)
+            .setStartTime(TIMESTAMP_START)
+            .setEndTime(TIMESTAMP_END);
+        mNetworkCycleChartData = builder.build();
     }
 
-    /**
-     * Create a network entry to be used to calculate the usage chart. In the calculation, we only
-     * need bucketStart, total bytes (rx + tx), and bucketDuration (which is set when we create
-     * the NetworkStatsHistory object). Other fields are ignored, so we don't initialize here.
-     *
-     * @param start the timestamp when this entry begins
-     * @param rx    the total number of received bytes
-     * @param tx    the total number of transmitted bytes
-     * @return the network entry with the corresponding start time and data usage
-     */
-    private Entry createEntry(long start, long rx, long tx) {
-        Entry entry = new Entry();
-        entry.bucketStart = start;
-        entry.rxBytes = rx;
-        entry.txBytes = tx;
-        return entry;
+    private NetworkCycleData createNetworkCycleData(long start, long end, long usage) {
+        return new NetworkCycleData.Builder()
+            .setStartTime(start).setEndTime(end).setTotalUsage(usage).build();
     }
 }
diff --git a/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.java b/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.java
index acd00fd..7a10d70 100644
--- a/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.java
+++ b/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * 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.
@@ -26,13 +26,11 @@
 
 import android.content.Context;
 import android.content.Intent;
+import android.net.ConnectivityManager;
 import android.net.NetworkTemplate;
 import android.os.Bundle;
 import android.provider.Settings;
 
-import androidx.fragment.app.FragmentActivity;
-import androidx.preference.PreferenceManager;
-
 import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settingslib.NetworkPolicyEditor;
@@ -45,6 +43,9 @@
 import org.mockito.MockitoAnnotations;
 import org.robolectric.util.ReflectionHelpers;
 
+import androidx.fragment.app.FragmentActivity;
+import androidx.preference.PreferenceManager;
+
 @RunWith(SettingsRobolectricTestRunner.class)
 public class DataUsageListTest {
 
@@ -98,6 +99,18 @@
     }
 
     @Test
+    public void processArgument_shouldGetNetworkTypeFromArgument() {
+        final Bundle args = new Bundle();
+        args.putInt(DataUsageList.EXTRA_NETWORK_TYPE, ConnectivityManager.TYPE_WIFI);
+        args.putInt(DataUsageList.EXTRA_SUB_ID, 3);
+        mDataUsageList.setArguments(args);
+
+        mDataUsageList.processArgument();
+
+        assertThat(mDataUsageList.mNetworkType).isEqualTo(ConnectivityManager.TYPE_WIFI);
+    }
+
+    @Test
     public void processArgument_fromIntent_shouldGetTemplateFromIntent() {
         final FragmentActivity activity = mock(FragmentActivity.class);
         final Intent intent = new Intent();
diff --git a/tests/robotests/src/com/android/settings/datausage/DataUsageListV2Test.java b/tests/robotests/src/com/android/settings/datausage/DataUsageListV2Test.java
deleted file mode 100644
index f561a05..0000000
--- a/tests/robotests/src/com/android/settings/datausage/DataUsageListV2Test.java
+++ /dev/null
@@ -1,127 +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.datausage;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.content.Intent;
-import android.net.ConnectivityManager;
-import android.net.NetworkTemplate;
-import android.os.Bundle;
-import android.provider.Settings;
-
-import com.android.settings.testutils.FakeFeatureFactory;
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
-import com.android.settingslib.NetworkPolicyEditor;
-import com.android.settingslib.core.instrumentation.VisibilityLoggerMixin;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.util.ReflectionHelpers;
-
-import androidx.fragment.app.FragmentActivity;
-import androidx.preference.PreferenceManager;
-
-@RunWith(SettingsRobolectricTestRunner.class)
-public class DataUsageListV2Test {
-
-    @Mock
-    private CellDataPreference.DataStateListener mListener;
-    @Mock
-    private TemplatePreference.NetworkServices mNetworkServices;
-    @Mock
-    private Context mContext;
-    private DataUsageListV2 mDataUsageList;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        FakeFeatureFactory.setupForTest();
-        mNetworkServices.mPolicyEditor = mock(NetworkPolicyEditor.class);
-        mDataUsageList = spy(DataUsageListV2.class);
-
-        doReturn(mContext).when(mDataUsageList).getContext();
-        ReflectionHelpers.setField(mDataUsageList, "mDataStateListener", mListener);
-        ReflectionHelpers.setField(mDataUsageList, "services", mNetworkServices);
-    }
-
-    @Test
-    public void resumePause_shouldListenUnlistenDataStateChange() {
-        ReflectionHelpers.setField(
-                mDataUsageList, "mVisibilityLoggerMixin", mock(VisibilityLoggerMixin.class));
-        ReflectionHelpers.setField(
-                mDataUsageList, "mPreferenceManager", mock(PreferenceManager.class));
-
-        mDataUsageList.onResume();
-
-        verify(mListener).setListener(true, mDataUsageList.mSubId, mContext);
-
-        mDataUsageList.onPause();
-
-        verify(mListener).setListener(false, mDataUsageList.mSubId, mContext);
-    }
-
-    @Test
-    public void processArgument_shouldGetTemplateFromArgument() {
-        final Bundle args = new Bundle();
-        args.putParcelable(DataUsageListV2.EXTRA_NETWORK_TEMPLATE, mock(NetworkTemplate.class));
-        args.putInt(DataUsageListV2.EXTRA_SUB_ID, 3);
-        mDataUsageList.setArguments(args);
-
-        mDataUsageList.processArgument();
-
-        assertThat(mDataUsageList.mTemplate).isNotNull();
-        assertThat(mDataUsageList.mSubId).isEqualTo(3);
-    }
-
-    @Test
-    public void processArgument_shouldGetNetworkTypeFromArgument() {
-        final Bundle args = new Bundle();
-        args.putInt(DataUsageListV2.EXTRA_NETWORK_TYPE, ConnectivityManager.TYPE_WIFI);
-        args.putInt(DataUsageListV2.EXTRA_SUB_ID, 3);
-        mDataUsageList.setArguments(args);
-
-        mDataUsageList.processArgument();
-
-        assertThat(mDataUsageList.mNetworkType).isEqualTo(ConnectivityManager.TYPE_WIFI);
-    }
-
-    @Test
-    public void processArgument_fromIntent_shouldGetTemplateFromIntent() {
-        final FragmentActivity activity = mock(FragmentActivity.class);
-        final Intent intent = new Intent();
-        intent.putExtra(Settings.EXTRA_NETWORK_TEMPLATE, mock(NetworkTemplate.class));
-        intent.putExtra(Settings.EXTRA_SUB_ID, 3);
-        when(activity.getIntent()).thenReturn(intent);
-        doReturn(activity).when(mDataUsageList).getActivity();
-
-        mDataUsageList.processArgument();
-
-        assertThat(mDataUsageList.mTemplate).isNotNull();
-        assertThat(mDataUsageList.mSubId).isEqualTo(3);
-    }
-}
diff --git a/tests/robotests/src/com/android/settings/datausage/DataUsageUtilsTest.java b/tests/robotests/src/com/android/settings/datausage/DataUsageUtilsTest.java
index 9a67df8..4bd584e 100644
--- a/tests/robotests/src/com/android/settings/datausage/DataUsageUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/datausage/DataUsageUtilsTest.java
@@ -29,9 +29,7 @@
 import android.net.ConnectivityManager;
 import android.telephony.TelephonyManager;
 import android.util.DataUnit;
-import android.util.FeatureFlagUtils;
 
-import com.android.settings.core.FeatureFlags;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 
 import org.junit.Before;
@@ -102,7 +100,6 @@
 
     @Test
     public void hasEthernet_shouldQueryEthernetSummaryForUser() throws Exception {
-        FeatureFlagUtils.setEnabled(mContext, FeatureFlags.DATA_USAGE_V2, true);
         when(mManager.isNetworkSupported(anyInt())).thenReturn(true);
         final String subscriber = "TestSub";
         when(mTelephonyManager.getSubscriberId()).thenReturn(subscriber);
diff --git a/tests/robotests/src/com/android/settings/development/AllowBackgroundActivityStartsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/AllowBackgroundActivityStartsPreferenceControllerTest.java
new file mode 100644
index 0000000..8b9b14f
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/AllowBackgroundActivityStartsPreferenceControllerTest.java
@@ -0,0 +1,110 @@
+/*
+ * 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.development;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.provider.Settings;
+
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreference;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class AllowBackgroundActivityStartsPreferenceControllerTest {
+
+    @Mock
+    private SwitchPreference mPreference;
+    @Mock
+    private PreferenceScreen mPreferenceScreen;
+
+    private Context mContext;
+    private AllowBackgroundActivityStartsPreferenceController mController;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        mContext = RuntimeEnvironment.application;
+        mController = new AllowBackgroundActivityStartsPreferenceController(mContext);
+        when(mPreferenceScreen.findPreference(mController.getPreferenceKey()))
+            .thenReturn(mPreference);
+        mController.displayPreference(mPreferenceScreen);
+    }
+
+    @Test
+    public void onPreferenceChange_settingEnabled_allowBackgroundActivityStartsShouldBeOn() {
+        mController.onPreferenceChange(mPreference, true /* new value */);
+
+        final int mode = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED, 1 /* default */);
+
+        assertThat(mode).isEqualTo(1);
+    }
+
+    @Test
+    public void onPreferenceChange_settingDisabled_allowBackgroundActivityStartsShouldBeOff() {
+        mController.onPreferenceChange(mPreference, false /* new value */);
+
+        final int mode = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED, 1 /* default */);
+
+        assertThat(mode).isEqualTo(0);
+    }
+
+    @Test
+    public void updateState_settingDisabled_preferenceShouldNotBeChecked() {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED, 0);
+        mController.updateState(mPreference);
+
+        verify(mPreference).setChecked(false);
+    }
+
+    @Test
+    public void updateState_settingEnabled_preferenceShouldBeChecked() {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED, 1);
+        mController.updateState(mPreference);
+
+        verify(mPreference).setChecked(true);
+    }
+
+    @Test
+    public void onDeveloperOptionsSwitchDisabled_shouldDisablePreference() {
+        mController.onDeveloperOptionsSwitchDisabled();
+
+        final int mode = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED, 1 /* default */);
+
+        assertThat(mode).isEqualTo(0);
+        verify(mPreference).setChecked(false);
+        verify(mPreference).setEnabled(false);
+    }
+}
+
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/PrivateVolumeOptionMenuControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/PrivateVolumeOptionMenuControllerTest.java
index 983621c..a966417 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/PrivateVolumeOptionMenuControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/PrivateVolumeOptionMenuControllerTest.java
@@ -64,6 +64,7 @@
         MockitoAnnotations.initMocks(this);
 
         when(mVolumeInfo.getType()).thenReturn(VolumeInfo.TYPE_PRIVATE);
+        when(mVolumeInfo.isMountedWritable()).thenReturn(true);
         when(mPrimaryInfo.getType()).thenReturn(VolumeInfo.TYPE_PRIVATE);
         when(mMenu.findItem(anyInt())).thenReturn(mMigrateMenuItem);
         when(mMigrateMenuItem.getItemId()).thenReturn(100);
@@ -82,6 +83,7 @@
     @Test
     public void testMigrateDataIsNotVisibleNormally() {
         when(mPm.getPrimaryStorageCurrentVolume()).thenReturn(mPrimaryInfo);
+        when(mPrimaryInfo.isMountedWritable()).thenReturn(true);
 
         mController.onCreateOptionsMenu(mMenu, mMenuInflater);
         mController.onPrepareOptionsMenu(mMenu);
@@ -100,6 +102,17 @@
     }
 
     @Test
+    public void testMigrateDataIsNotVisibleWhenExternalVolumeIsNotMounted() {
+        when(mPm.getPrimaryStorageCurrentVolume()).thenReturn(mVolumeInfo);
+        when(mVolumeInfo.isMountedWritable()).thenReturn(false);
+
+        mController.onCreateOptionsMenu(mMenu, mMenuInflater);
+        mController.onPrepareOptionsMenu(mMenu);
+
+        verify(mMigrateMenuItem).setVisible(false);
+    }
+
+    @Test
     public void testMigrateDataGoesToMigrateWizard() {
         when(mPm.getPrimaryStorageCurrentVolume()).thenReturn(mVolumeInfo);
 
diff --git a/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacySettingsTest.java b/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacySettingsTest.java
index f1d03c7..f7a61c8 100644
--- a/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacySettingsTest.java
+++ b/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacySettingsTest.java
@@ -28,6 +28,7 @@
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.widget.PreferenceCategoryController;
 import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.drawer.CategoryKey;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -59,7 +60,7 @@
         assertThat(mSettings.getMetricsCategory())
                 .isEqualTo(MetricsEvent.ENTERPRISE_PRIVACY_SETTINGS);
         assertThat(mSettings.getLogTag()).isEqualTo("EnterprisePrivacySettings");
-        assertThat(mSettings.getCategoryKey()).isNull();
+        assertThat(mSettings.getCategoryKey()).isEqualTo(CategoryKey.CATEGORY_ENTERPRISE_PRIVACY);
         assertThat(mSettings.getPreferenceScreenResId())
                 .isEqualTo(R.xml.enterprise_privacy_settings);
     }
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 c09af2b..051ef39 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverButtonPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverButtonPreferenceControllerTest.java
@@ -21,6 +21,8 @@
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import android.content.Context;
 import android.os.PowerManager;
@@ -37,22 +39,20 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowPowerManager;
 import org.robolectric.util.ReflectionHelpers;
 
 @RunWith(SettingsRobolectricTestRunner.class)
-@Config(shadows = ShadowPowerManager.class)
 public class BatterySaverButtonPreferenceControllerTest {
 
     private BatterySaverButtonPreferenceController mController;
     private Context mContext;
     private Button mButtonOn;
     private Button mButtonOff;
-    private PowerManager mPowerManager;
     private TwoStateButtonPreference mPreference;
 
     @Mock
+    private PowerManager mPowerManager;
+    @Mock
     private PreferenceScreen mPreferenceScreen;
 
     @Before
@@ -61,10 +61,11 @@
         mContext = spy(RuntimeEnvironment.application);
         mButtonOn = new Button(mContext);
         mButtonOff = new Button(mContext);
-        mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
         mPreference = spy(new TwoStateButtonPreference(mContext, null /* AttributeSet */));
         ReflectionHelpers.setField(mPreference, "mButtonOn", mButtonOn);
         ReflectionHelpers.setField(mPreference, "mButtonOff", mButtonOff);
+
+        doReturn(mPowerManager).when(mContext).getSystemService(Context.POWER_SERVICE);
         doReturn(mPreference).when(mPreferenceScreen).findPreference(anyString());
 
         mController = new BatterySaverButtonPreferenceController(mContext, "test_key");
@@ -73,7 +74,7 @@
 
     @Test
     public void updateState_lowPowerOn_preferenceIsChecked() {
-        mPowerManager.setPowerSaveMode(true);
+        when(mPowerManager.isPowerSaveMode()).thenReturn(true);
 
         mController.updateState(mPreference);
 
@@ -82,7 +83,7 @@
 
     @Test
     public void testUpdateState_lowPowerOff_preferenceIsUnchecked() {
-        mPowerManager.setPowerSaveMode(false);
+        when(mPowerManager.isPowerSaveMode()).thenReturn(false);
 
         mController.updateState(mPreference);
 
@@ -93,13 +94,13 @@
     public void setChecked_on_setPowerSaveMode() {
         mController.setChecked(true);
 
-        assertThat(mPowerManager.isPowerSaveMode()).isTrue();
+        verify(mPowerManager).setPowerSaveMode(true);
     }
 
     @Test
     public void setChecked_off_unsetPowerSaveMode() {
         mController.setChecked(false);
 
-        assertThat(mPowerManager.isPowerSaveMode()).isFalse();
+        verify(mPowerManager).setPowerSaveMode(false);
     }
 }
diff --git a/tests/robotests/src/com/android/settings/gestures/GesturesSettingsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/GesturesSettingsPreferenceControllerTest.java
index d8f800d..e892eb2 100644
--- a/tests/robotests/src/com/android/settings/gestures/GesturesSettingsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/GesturesSettingsPreferenceControllerTest.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.gestures;
 
+import static com.android.settings.core.BasePreferenceController.AVAILABLE;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.Matchers.any;
@@ -81,7 +83,7 @@
         });
         ReflectionHelpers.setField(mController, "mGestureControllers", mControllers);
 
-        assertThat(mController.isAvailable()).isTrue();
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImplTest.java
new file mode 100644
index 0000000..08631f7
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImplTest.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.homepage.contextualcards;
+
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.content.Intent;
+
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class ContextualCardFeatureProviderImplTest {
+
+    private Context mContext;
+    private ContextualCardFeatureProviderImpl mImpl;
+
+    @Before
+    public void setUp() {
+        mContext = spy(RuntimeEnvironment.application);
+        mImpl = new ContextualCardFeatureProviderImpl();
+    }
+
+    @Test
+    public void sendBroadcast_emptyAction_notSendBroadcast() {
+        final Intent intent = new Intent();
+        mImpl.sendBroadcast(mContext, intent);
+
+        verify(mContext, never()).sendBroadcast(intent);
+    }
+
+    @Test
+    @Config(qualifiers = "mcc999")
+    public void sendBroadcast_hasAction_sendBroadcast() {
+        final Intent intent = new Intent();
+        mImpl.sendBroadcast(mContext, intent);
+
+        verify(mContext).sendBroadcast(intent);
+    }
+}
\ No newline at end of file
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 e8cb674..4f50197 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java
@@ -27,11 +27,9 @@
 import android.content.Context;
 import android.net.Uri;
 
-import com.android.settings.homepage.contextualcards.deviceinfo.BatterySlice;
-import com.android.settings.homepage.contextualcards.slices.ConnectedDeviceSlice;
+import com.android.settings.slices.CustomSliceRegistry;
 import com.android.settings.slices.SettingsSliceProvider;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
-import com.android.settings.wifi.WifiSlice;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -153,7 +151,7 @@
         cards.add(new ContextualCard.Builder()
                 .setName("test_wifi")
                 .setCardType(ContextualCard.CardType.SLICE)
-                .setSliceUri(WifiSlice.WIFI_URI)
+                .setSliceUri(CustomSliceRegistry.WIFI_SLICE_URI)
                 .build());
         cards.add(new ContextualCard.Builder()
                 .setName("test_flashlight")
@@ -164,7 +162,7 @@
         cards.add(new ContextualCard.Builder()
                 .setName("test_connected")
                 .setCardType(ContextualCard.CardType.SLICE)
-                .setSliceUri(ConnectedDeviceSlice.CONNECTED_DEVICE_URI)
+                .setSliceUri(CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI)
                 .build());
         cards.add(new ContextualCard.Builder()
                 .setName("test_gesture")
@@ -175,7 +173,7 @@
         cards.add(new ContextualCard.Builder()
                 .setName("test_battery")
                 .setCardType(ContextualCard.CardType.SLICE)
-                .setSliceUri(BatterySlice.BATTERY_CARD_URI)
+                .setSliceUri(CustomSliceRegistry.BATTERY_INFO_SLICE_URI)
                 .build());
         return cards;
     }
@@ -208,7 +206,7 @@
         cards.add(new ContextualCard.Builder()
                 .setName("test_battery")
                 .setCardType(ContextualCard.CardType.SLICE)
-                .setSliceUri(BatterySlice.BATTERY_CARD_URI)
+                .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 8287672..64a7c9c 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardManagerTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardManagerTest.java
@@ -18,13 +18,12 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.ArgumentMatchers.anyMap;
-import static org.mockito.Mockito.doNothing;
-
 import android.content.Context;
 import android.net.Uri;
 import android.util.ArrayMap;
 
+import com.android.settings.homepage.contextualcards.conditional.ConditionFooterContextualCard;
+import com.android.settings.homepage.contextualcards.conditional.ConditionHeaderContextualCard;
 import com.android.settings.homepage.contextualcards.conditional.ConditionalContextualCard;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 
@@ -70,7 +69,7 @@
     }
 
     @Test
-    public void onContextualCardUpdated_emtpyMapWithExistingCards_shouldOnlyKeepConditionalCard() {
+    public void onContextualCardUpdated_emptyMapWithExistingCards_shouldOnlyKeepConditionalCard() {
         mManager.mContextualCards.add(new ConditionalContextualCard.Builder().build());
         mManager.mContextualCards.add(
                 buildContextualCard(TEST_SLICE_URI));
@@ -84,6 +83,31 @@
                 .isEqualTo(ContextualCard.CardType.CONDITIONAL);
     }
 
+    @Test
+    public void onContextualCardUpdated_hasEmptyMap_shouldKeepConditionalHeaderCard() {
+        mManager.mContextualCards.add(new ConditionHeaderContextualCard.Builder().build());
+        mManager.setListener(mListener);
+
+        mManager.onContextualCardUpdated(new ArrayMap<>());
+
+        assertThat(mManager.mContextualCards).hasSize(1);
+        assertThat(mManager.mContextualCards.get(0).getCardType())
+                .isEqualTo(ContextualCard.CardType.CONDITIONAL_HEADER);
+    }
+
+    @Test
+    public void onContextualCardUpdated_hasEmptyMap_shouldKeepConditionalFooterCard() {
+        mManager.mContextualCards.add(new ConditionFooterContextualCard.Builder().build());
+        mManager.setListener(mListener);
+
+        mManager.onContextualCardUpdated(new ArrayMap<>());
+
+        assertThat(mManager.mContextualCards).hasSize(1);
+        assertThat(mManager.mContextualCards.get(0).getCardType())
+                .isEqualTo(ContextualCard.CardType.CONDITIONAL_FOOTER);
+    }
+
+
     private ContextualCard buildContextualCard(String sliceUri) {
         return new ContextualCard.Builder()
                 .setName("test_name")
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProviderTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProviderTest.java
index 6b1f8b1..4b0b085 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProviderTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProviderTest.java
@@ -23,15 +23,13 @@
 import static org.mockito.Mockito.spy;
 
 import android.app.slice.SliceManager;
-import android.content.ContentResolver;
 import android.content.Context;
-import android.net.Uri;
 import android.os.Bundle;
 
 import com.android.settings.intelligence.ContextualCardProto.ContextualCard;
 import com.android.settings.intelligence.ContextualCardProto.ContextualCardList;
+import com.android.settings.slices.CustomSliceRegistry;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
-import com.android.settings.wifi.WifiSlice;
 
 import com.google.android.settings.intelligence.libs.contextualcards.ContextualCardProvider;
 
@@ -48,18 +46,11 @@
 
     @Mock
     private SliceManager mSliceManager;
-    private ContentResolver mResolver;
-    private Uri mUri;
     private SettingsContextualCardProvider mProvider;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mResolver = RuntimeEnvironment.application.getContentResolver();
-        mUri = new Uri.Builder()
-                .scheme(ContentResolver.SCHEME_CONTENT)
-                .authority(SettingsContextualCardProvider.CARD_AUTHORITY)
-                .build();
         mProvider = spy(Robolectric.setupContentProvider(SettingsContextualCardProvider.class));
         final Context context = spy(RuntimeEnvironment.application);
         doReturn(mSliceManager).when(context).getSystemService(SliceManager.class);
@@ -83,7 +74,7 @@
         final ContextualCardList cards = mProvider.getContextualCards();
         ContextualCard wifiCard = null;
         for (ContextualCard card : cards.getCardList()) {
-            if (card.getSliceUri().equals(WifiSlice.WIFI_URI.toString())) {
+            if (card.getSliceUri().equals(CustomSliceRegistry.WIFI_SLICE_URI.toString())) {
                 wifiCard = card;
             }
         }
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardRendererTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardRendererTest.java
index bb61c7d..25689e6 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardRendererTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardRendererTest.java
@@ -58,7 +58,7 @@
         final ActivityController<Activity> activityController = Robolectric.buildActivity(
                 Activity.class);
         mActivity = activityController.get();
-        mActivity.setTheme(R.style.Theme_AppCompat);
+        mActivity.setTheme(R.style.Theme_Settings_Home);
         activityController.create();
         mRenderer = new ConditionContextualCardRenderer(mActivity, mControllerRendererPool);
     }
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionHeaderContextualCardRendererTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionHeaderContextualCardRendererTest.java
index d0b5a24..ee8a582 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionHeaderContextualCardRendererTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionHeaderContextualCardRendererTest.java
@@ -60,7 +60,7 @@
         final ActivityController<Activity> activityController = Robolectric.buildActivity(
                 Activity.class);
         mActivity = activityController.get();
-        mActivity.setTheme(R.style.Theme_AppCompat);
+        mActivity.setTheme(R.style.Theme_Settings_Home);
         activityController.create();
         mRenderer = new ConditionHeaderContextualCardRenderer(mActivity, mControllerRendererPool);
     }
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/legacysuggestion/LegacySuggestionContextualCardRendererTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/legacysuggestion/LegacySuggestionContextualCardRendererTest.java
index 2618e1b..c337df1 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/legacysuggestion/LegacySuggestionContextualCardRendererTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/legacysuggestion/LegacySuggestionContextualCardRendererTest.java
@@ -59,7 +59,7 @@
         final ActivityController<Activity> activityController = Robolectric.buildActivity(
                 Activity.class);
         mActivity = activityController.get();
-        mActivity.setTheme(R.style.Theme_AppCompat);
+        mActivity.setTheme(R.style.Theme_Settings_Home);
         activityController.create();
 
         mRenderer = new LegacySuggestionContextualCardRenderer(mActivity, mControllerRendererPool);
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/ConnectedDeviceSliceTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/ConnectedDeviceSliceTest.java
index 23da127..472d2ca 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/ConnectedDeviceSliceTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/ConnectedDeviceSliceTest.java
@@ -36,6 +36,7 @@
 import com.android.settings.testutils.SliceTester;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -49,12 +50,17 @@
 @RunWith(SettingsRobolectricTestRunner.class)
 public class ConnectedDeviceSliceTest {
 
+    private static final String BLUETOOTH_SUMMARY = "BluetoothSummary";
+    private static final String BLUETOOTH_TITLE = "BluetoothTitle";
+
     @Mock
     private CachedBluetoothDevice mCachedBluetoothDevice;
 
-    private List<CachedBluetoothDevice> mCachedDevices = new ArrayList<CachedBluetoothDevice>();
-    private Context mContext;
+    private List<CachedBluetoothDevice> mBluetoothConnectedDeviceList;
     private ConnectedDeviceSlice mConnectedDeviceSlice;
+    private Context mContext;
+    private IconCompat mIcon;
+    private PendingIntent mDetailIntent;
 
     @Before
     public void setUp() {
@@ -65,35 +71,63 @@
         SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
 
         mConnectedDeviceSlice = spy(new ConnectedDeviceSlice(mContext));
+
+        // Mock the icon and detail intent of Bluetooth.
+        mIcon = IconCompat.createWithResource(mContext, R.drawable.ic_homepage_connected_device);
+        mDetailIntent = PendingIntent.getActivity(mContext, 0, new Intent("test action"), 0);
+        doReturn(mIcon).when(mConnectedDeviceSlice).getConnectedDeviceIcon(any());
+        doReturn(mDetailIntent).when(mConnectedDeviceSlice).getBluetoothDetailIntent(any());
+
+        // Initial Bluetooth connected device list.
+        mBluetoothConnectedDeviceList = new ArrayList<>();
+    }
+
+    @After
+    public void tearDown() {
+        if (!mBluetoothConnectedDeviceList.isEmpty()) {
+            mBluetoothConnectedDeviceList.clear();
+        }
     }
 
     @Test
-    public void getSlice_hasConnectedDevices_shouldBeCorrectSliceContent() {
-        final String title = "BluetoothTitle";
-        final String summary = "BluetoothSummary";
-        final IconCompat icon = IconCompat.createWithResource(mContext,
-                R.drawable.ic_homepage_connected_device);
-        final PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0,
-                new Intent("test action"), 0);
-        doReturn(title).when(mCachedBluetoothDevice).getName();
-        doReturn(summary).when(mCachedBluetoothDevice).getConnectionSummary();
-        mCachedDevices.add(mCachedBluetoothDevice);
-        doReturn(mCachedDevices).when(mConnectedDeviceSlice).getBluetoothConnectedDevices();
-        doReturn(icon).when(mConnectedDeviceSlice).getConnectedDeviceIcon(any());
-        doReturn(pendingIntent).when(mConnectedDeviceSlice).getBluetoothDetailIntent(any());
+    public void getSlice_hasConnectedDevices_shouldHaveCorrectTitle() {
+        mockBluetoothDeviceList();
+        doReturn(mBluetoothConnectedDeviceList).when(
+                mConnectedDeviceSlice).getBluetoothConnectedDevices();
+
         final Slice slice = mConnectedDeviceSlice.getSlice();
 
         final List<SliceItem> sliceItems = slice.getItems();
-        SliceTester.assertTitle(sliceItems, title);
+        SliceTester.assertTitle(sliceItems,
+                mContext.getString(R.string.bluetooth_connected_devices));
     }
 
     @Test
-    public void getSlice_hasNoConnectedDevices_shouldReturnCorrectHeader() {
-        final List<CachedBluetoothDevice> connectedBluetoothList = new ArrayList<>();
-        doReturn(connectedBluetoothList).when(mConnectedDeviceSlice).getBluetoothConnectedDevices();
+    public void getSlice_hasConnectedDevices_shouldHaveCorrectContent() {
+        mockBluetoothDeviceList();
+        doReturn(mBluetoothConnectedDeviceList).when(
+                mConnectedDeviceSlice).getBluetoothConnectedDevices();
+
+        final Slice slice = mConnectedDeviceSlice.getSlice();
+
+        final List<SliceItem> sliceItems = slice.getItems();
+        SliceTester.assertTitle(sliceItems, BLUETOOTH_TITLE);
+    }
+
+    @Test
+    public void getSlice_noConnectedDevices_shouldHaveCorrectTitle() {
+        doReturn(mBluetoothConnectedDeviceList).when(
+                mConnectedDeviceSlice).getBluetoothConnectedDevices();
+
         final Slice slice = mConnectedDeviceSlice.getSlice();
 
         final List<SliceItem> sliceItems = slice.getItems();
         SliceTester.assertTitle(sliceItems, mContext.getString(R.string.no_connected_devices));
     }
+
+    private void mockBluetoothDeviceList() {
+        doReturn(BLUETOOTH_TITLE).when(mCachedBluetoothDevice).getName();
+        doReturn(BLUETOOTH_SUMMARY).when(mCachedBluetoothDevice).getConnectionSummary();
+        mBluetoothConnectedDeviceList.add(mCachedBluetoothDevice);
+    }
 }
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/LowStorageSliceTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/LowStorageSliceTest.java
index 0be55d9..9787aee 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/LowStorageSliceTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/LowStorageSliceTest.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.homepage.contextualcards.slices;
 
+import static android.app.slice.Slice.HINT_ERROR;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import android.content.Context;
@@ -66,7 +68,7 @@
 
     @Test
     @Config(shadows = ShadowPrivateStorageInfo.class)
-    public void getSlice_hasLowStorage_shouldBeCorrectSliceContent() {
+    public void getSlice_lowStorage_shouldHaveStorageFreeTitle() {
         ShadowPrivateStorageInfo.setPrivateStorageInfo(new PrivateStorageInfo(10L, 100L));
 
         final Slice slice = mLowStorageSlice.getSlice();
@@ -77,12 +79,33 @@
 
     @Test
     @Config(shadows = ShadowPrivateStorageInfo.class)
-    public void getSlice_hasNoLowStorage_shouldBeNull() {
+    public void getSlice_lowStorage_shouldNotHaveErrorHint() {
+        ShadowPrivateStorageInfo.setPrivateStorageInfo(new PrivateStorageInfo(10L, 100L));
+
+        final Slice slice = mLowStorageSlice.getSlice();
+
+        assertThat(slice.hasHint(HINT_ERROR)).isFalse();
+    }
+
+    @Test
+    @Config(shadows = ShadowPrivateStorageInfo.class)
+    public void getSlice_storageFree_shouldHaveStorageSettingsTitle() {
         ShadowPrivateStorageInfo.setPrivateStorageInfo(new PrivateStorageInfo(100L, 100L));
 
         final Slice slice = mLowStorageSlice.getSlice();
 
-        assertThat(slice).isNull();
+        final List<SliceItem> sliceItems = slice.getItems();
+        SliceTester.assertTitle(sliceItems, mContext.getString(R.string.storage_settings));
+    }
+
+    @Test
+    @Config(shadows = ShadowPrivateStorageInfo.class)
+    public void getSlice_storageFree_shouldHaveErrorHint() {
+        ShadowPrivateStorageInfo.setPrivateStorageInfo(new PrivateStorageInfo(100L, 100L));
+
+        final Slice slice = mLowStorageSlice.getSlice();
+
+        assertThat(slice.hasHint(HINT_ERROR)).isTrue();
     }
 
     @Implements(PrivateStorageInfo.class)
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardControllerTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardControllerTest.java
index 362e1f5..af3b2e8 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardControllerTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardControllerTest.java
@@ -18,6 +18,11 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Context;
@@ -27,14 +32,22 @@
 import com.android.settings.homepage.contextualcards.CardContentProvider;
 import com.android.settings.homepage.contextualcards.CardDatabaseHelper;
 import com.android.settings.homepage.contextualcards.ContextualCard;
+import com.android.settings.homepage.contextualcards.ContextualCardFeedbackDialog;
+import com.android.settings.homepage.contextualcards.ContextualCardsFragment;
+import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
 import org.robolectric.Robolectric;
 import org.robolectric.RuntimeEnvironment;
+import org.robolectric.Shadows;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowActivity;
 import org.robolectric.shadows.ShadowContentResolver;
+import org.robolectric.shadows.androidx.fragment.FragmentController;
 
 @RunWith(SettingsRobolectricTestRunner.class)
 public class SliceContextualCardControllerTest {
@@ -46,27 +59,27 @@
     private CardContentProvider mProvider;
     private ContentResolver mResolver;
     private SliceContextualCardController mController;
+    private FakeFeatureFactory mFeatureFactory;
 
     @Before
     public void setUp() {
+        MockitoAnnotations.initMocks(this);
         mContext = RuntimeEnvironment.application;
         mProvider = Robolectric.setupContentProvider(CardContentProvider.class);
         ShadowContentResolver.registerProviderInternal(CardContentProvider.CARD_AUTHORITY,
                 mProvider);
         mResolver = mContext.getContentResolver();
-        mController = new SliceContextualCardController(mContext);
+        mController = spy(new SliceContextualCardController(mContext));
+        mFeatureFactory = FakeFeatureFactory.setupForTest();
     }
 
     @Test
     public void onDismissed_cardShouldBeMarkedAsDismissed() {
         final Uri providerUri = CardContentProvider.URI;
-        final ContextualCard card = new ContextualCard.Builder()
-                .setName(TEST_CARD_NAME)
-                .setCardType(ContextualCard.CardType.SLICE)
-                .setSliceUri(Uri.parse(TEST_SLICE_URI))
-                .build();
         mResolver.insert(providerUri, generateOneRow());
+        doNothing().when(mController).showFeedbackDialog(any(ContextualCard.class));
 
+        final ContextualCard card = getTestSliceCard();
         mController.onDismissed(card);
 
         final String[] columns = {CardDatabaseHelper.CardColumns.CARD_DISMISSED};
@@ -78,6 +91,34 @@
         cr.close();
 
         assertThat(qryDismissed).isEqualTo(1);
+        verify(mFeatureFactory.mContextualCardFeatureProvider).logContextualCardDismiss(
+                mContext, card);
+    }
+
+    @Test
+    public void onDismissed_noFeedbackEmail_shouldNotShowFeedbackDialog() {
+        mResolver.insert(CardContentProvider.URI, generateOneRow());
+        final ContextualCardsFragment fragment =
+                FragmentController.of(new ContextualCardsFragment()).create().get();
+        final ShadowActivity shadowActivity = Shadows.shadowOf(fragment.getActivity());
+
+        mController.onDismissed(getTestSliceCard());
+
+        assertThat(shadowActivity.getNextStartedActivity()).isNull();
+    }
+
+    @Test
+    @Config(qualifiers = "mcc999")
+    public void onDismissed_hasFeedbackEmail_shouldShowFeedbackDialog() {
+        mResolver.insert(CardContentProvider.URI, generateOneRow());
+        final ContextualCardsFragment fragment =
+                FragmentController.of(new ContextualCardsFragment()).create().get();
+        final ShadowActivity shadowActivity = Shadows.shadowOf(fragment.getActivity());
+
+        mController.onDismissed(getTestSliceCard());
+
+        assertThat(shadowActivity.getNextStartedActivity().getComponent().getClassName())
+                .isEqualTo(ContextualCardFeedbackDialog.class.getName());
     }
 
     private ContentValues generateOneRow() {
@@ -93,4 +134,12 @@
 
         return values;
     }
+
+    private ContextualCard getTestSliceCard() {
+        return new ContextualCard.Builder()
+                .setName(TEST_CARD_NAME)
+                .setCardType(ContextualCard.CardType.SLICE)
+                .setSliceUri(Uri.parse(TEST_SLICE_URI))
+                .build();
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRendererTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRendererTest.java
index abfddbb..13a2bc5 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRendererTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRendererTest.java
@@ -66,7 +66,7 @@
         final ActivityController<Activity> activityController = Robolectric.buildActivity(
                 Activity.class);
         mActivity = activityController.get();
-        mActivity.setTheme(R.style.Theme_AppCompat);
+        mActivity.setTheme(R.style.Theme_Settings_Home);
         activityController.create();
         mLifecycleOwner = new ContextualCardsFragment();
         mRenderer = new SliceContextualCardRenderer(mActivity, mLifecycleOwner,
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 d260a97..5269dd7 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/Enhanced4gLteSliceHelperTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/Enhanced4gLteSliceHelperTest.java
@@ -44,6 +44,7 @@
 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;
 import com.android.settings.slices.SlicesFeatureProvider;
@@ -107,7 +108,7 @@
         mEnhanced4gLteSliceHelper.setDefaultVoiceSubId(-1);
 
         final Slice slice = mEnhanced4gLteSliceHelper.createEnhanced4gLteSlice(
-                Enhanced4gLteSliceHelper.SLICE_URI);
+                CustomSliceRegistry.ENHANCED_4G_SLICE_URI);
 
         assertThat(slice).isNull();
     }
@@ -117,7 +118,7 @@
         when(mMockImsManager.isVolteEnabledByPlatform()).thenReturn(false);
 
         final Slice slice = mEnhanced4gLteSliceHelper.createEnhanced4gLteSlice(
-                Enhanced4gLteSliceHelper.SLICE_URI);
+                CustomSliceRegistry.ENHANCED_4G_SLICE_URI);
 
         assertThat(mEnhanced4gLteSliceHelper.getDefaultVoiceSubId()).isEqualTo(1);
         assertThat(slice).isNull();
@@ -132,7 +133,7 @@
         when(mMockCarrierConfigManager.getConfigForSubId(1)).thenReturn(null);
 
         final Slice slice = mEnhanced4gLteSliceHelper.createEnhanced4gLteSlice(
-                Enhanced4gLteSliceHelper.SLICE_URI);
+                CustomSliceRegistry.ENHANCED_4G_SLICE_URI);
 
         assertThat(mEnhanced4gLteSliceHelper.getDefaultVoiceSubId()).isEqualTo(1);
         testEnhanced4gLteSettingsToggleSlice(slice);
@@ -148,7 +149,7 @@
         when(mSlicesFeatureProvider.getNewEnhanced4gLteSliceHelper(mContext))
                 .thenReturn(mEnhanced4gLteSliceHelper);
 
-        final Slice slice = mProvider.onBindSlice(Enhanced4gLteSliceHelper.SLICE_URI);
+        final Slice slice = mProvider.onBindSlice(CustomSliceRegistry.ENHANCED_4G_SLICE_URI);
 
         assertThat(mEnhanced4gLteSliceHelper.getDefaultVoiceSubId()).isEqualTo(1);
         testEnhanced4gLteSettingsToggleSlice(slice);
diff --git a/tests/robotests/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceControllerTest.java
index ec50e2b..3eae266 100644
--- a/tests/robotests/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceControllerTest.java
@@ -16,13 +16,17 @@
 
 package com.android.settings.notification;
 
-import static junit.framework.Assert.assertEquals;
-
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+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.times;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.app.AutomaticZenRule;
-import android.app.NotificationManager;
 import android.content.Context;
 import android.provider.Settings;
 
@@ -31,161 +35,122 @@
 import androidx.preference.PreferenceScreen;
 
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
-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.mockito.internal.util.reflection.FieldSetter;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.shadows.ShadowApplication;
 import org.robolectric.util.ReflectionHelpers;
 
-import java.util.Arrays;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 
 @RunWith(SettingsRobolectricTestRunner.class)
 public class ZenModeAutomaticRulesPreferenceControllerTest {
 
-    private static final String GENERIC_RULE_NAME = "test";
-    private static final String DEFAULT_ID_1 = "DEFAULT_1";
-    private static final String DEFAULT_ID_2 = "DEFAULT_2";
-
     private ZenModeAutomaticRulesPreferenceController mController;
-    private final List<String> mDefaultIds = Arrays.asList(DEFAULT_ID_1, DEFAULT_ID_2);
-
     @Mock
     private ZenModeBackend mBackend;
     @Mock
-    private NotificationManager mNotificationManager;
-    @Mock
     private PreferenceCategory mockPref;
     @Mock
-    private NotificationManager.Policy mPolicy;
-    @Mock
     private PreferenceScreen mPreferenceScreen;
-
+    @Mock
+    private ZenRulePreference mZenRulePreference;
     private Context mContext;
 
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
-        ShadowApplication shadowApplication = ShadowApplication.getInstance();
-        shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
-
         mContext = RuntimeEnvironment.application;
-        when(mNotificationManager.getNotificationPolicy()).thenReturn(mPolicy);
-        mController = new ZenModeAutomaticRulesPreferenceController(mContext, mock(Fragment.class),
-                mock(Lifecycle.class));
-
+        mController = spy(new ZenModeAutomaticRulesPreferenceController(mContext, mock(Fragment.class),
+                null));
         ReflectionHelpers.setField(mController, "mBackend", mBackend);
-        ReflectionHelpers.setField(mController, "mDefaultRuleIds", mDefaultIds);
-
         when(mPreferenceScreen.findPreference(mController.getPreferenceKey())).thenReturn(
                 mockPref);
         mController.displayPreference(mPreferenceScreen);
+        doReturn(mZenRulePreference).when(mController).createZenRulePreference(any());
     }
 
     @Test
-    public void updateState_checkRuleOrderingDescending() {
-        final int NUM_RULES = 4;
-        when(mNotificationManager.getAutomaticZenRules()).thenReturn(
-                mockAutoZenRulesDecreasingCreationTime(NUM_RULES));
+    public void testUpdateState_clearsPreferencesWhenAddingNewPreferences() {
+        final int NUM_RULES = 3;
+        Map<String, AutomaticZenRule> rMap = new HashMap<>();
 
-        Map.Entry<String, AutomaticZenRule>[] rules = mController.sortedRules();
-        assertEquals(NUM_RULES, rules.length);
+        String ruleId1 = "test1_id";
+        String ruleId2 = "test2_id";
+        String ruleId3 = "test3_id";
 
-        // check ordering, most recent should be at the bottom/end (ie higher creation time)
-        for (int i = 0; i < NUM_RULES; i++) {
-            assertEquals(GENERIC_RULE_NAME + (NUM_RULES - 1 - i), rules[i].getKey());
-        }
+        AutomaticZenRule autoRule1 = new AutomaticZenRule("test_rule_1", null,
+                null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 10);
+        AutomaticZenRule autoRule2 = new AutomaticZenRule("test_rule_2", null,
+                null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 20);
+        AutomaticZenRule autoRule3 = new AutomaticZenRule("test_rule_3", null,
+                null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 30);
+
+        rMap.put(ruleId1, autoRule1);
+        rMap.put(ruleId2, autoRule2);
+        rMap.put(ruleId3, autoRule3);
+
+        // should add 3 new preferences to mockPref
+        mockGetAutomaticZenRules(NUM_RULES, rMap);
+        mController.updateState(mockPref);
+        verify(mockPref, times(1)).removeAll();
+        verify(mockPref, times(NUM_RULES)).addPreference(any());
     }
 
     @Test
-    public void updateState_checkRuleOrderingAscending() {
-        final int NUM_RULES = 4;
-        when(mNotificationManager.getAutomaticZenRules()).thenReturn(
-                mockAutoZenRulesAscendingCreationTime(NUM_RULES));
+    public void testUpdateState_clearsPreferencesWhenRemovingPreferences(){
+        final int NUM_RULES = 2;
+        Map<String, AutomaticZenRule> rMap = new HashMap<>();
 
-        Map.Entry<String, AutomaticZenRule>[] rules = mController.sortedRules();
-        assertEquals(NUM_RULES, rules.length);
+        String ruleId1 = "test1_id";
+        String ruleId2 = "test2_id";
 
-        // check ordering, most recent should be at the bottom/end (ie higher creation time)
-        for (int i = 0; i < NUM_RULES; i++) {
-            assertEquals(GENERIC_RULE_NAME + i, rules[i].getKey());
-        }
+        AutomaticZenRule autoRule1 = new AutomaticZenRule("test_rule_1", null,
+                null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 10);
+        AutomaticZenRule autoRule2 = new AutomaticZenRule("test_rule_2", null,
+                null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 20);
+
+        rMap.put(ruleId1, autoRule1);
+        rMap.put(ruleId2, autoRule2);
+
+        // update state should re-add all preferences since a preference was deleted
+        when(mockPref.getPreferenceCount()).thenReturn(NUM_RULES + 2);
+        mockGetAutomaticZenRules(NUM_RULES, rMap);
+        mController.updateState(mockPref);
+        verify(mockPref, times(1)).removeAll();
+        verify(mockPref, times(NUM_RULES)).addPreference(any());
     }
 
     @Test
-    public void updateState_checkRuleOrderingDescending_withDefaultRules() {
-        final int NUM_RULES = 4;
+    public void testUpdateState_updateEnableState() throws NoSuchFieldException {
+        final int NUM_RULES = 1;
+        Map<String, AutomaticZenRule> rMap = new HashMap<>();
+        String testId = "test1_id";
+        AutomaticZenRule rule = new AutomaticZenRule("rule_name", null,
+                null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 10);
+        rMap.put(testId, rule);
 
-        Map<String, AutomaticZenRule> ruleMap = mockAutoZenRulesDecreasingCreationTime(NUM_RULES);
-        ruleMap.put(DEFAULT_ID_2, new AutomaticZenRule("DEFAULT_1_NAME", null,
-                null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 20));
-        ruleMap.put(DEFAULT_ID_1, new AutomaticZenRule("DEFAULT_1_NAME", null,
-                null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 10));
-        when(mNotificationManager.getAutomaticZenRules()).thenReturn(ruleMap);
+        when(mockPref.getPreferenceCount()).thenReturn(NUM_RULES);
+        when(mockPref.getPreference(anyInt())).thenReturn(mZenRulePreference);
 
-        Map.Entry<String, AutomaticZenRule>[] rules = mController.sortedRules();
-        assertEquals(NUM_RULES + 2, rules.length);
-
-        assertEquals(rules[0].getKey(), DEFAULT_ID_1);
-        assertEquals(rules[1].getKey(), DEFAULT_ID_2);
-        // NON-DEFAULT RULES check ordering, most recent at the bottom/end
-        for (int i = 0; i < NUM_RULES; i++) {
-            assertEquals(GENERIC_RULE_NAME + (NUM_RULES - 1 - i), rules[i + 2].getKey());
-        }
+        // update state should NOT re-add all the preferences, should only update enable state
+        rule.setEnabled(false);
+        rMap.put(testId, rule);
+        mockGetAutomaticZenRules(NUM_RULES, rMap);
+        FieldSetter.setField(mZenRulePreference, ZenRulePreference.class.getDeclaredField("mId"), testId);
+        mController.updateState(mockPref);
+        verify(mZenRulePreference, times(1)).setChecked(false);
+        verify(mController, never()).reloadAllRules(any());
     }
 
-    @Test
-    public void updateState_checkRuleOrderingMix() {
-        final int NUM_RULES = 4;
-        // map with creation times: 0, 2, 4, 6
-        Map<String,AutomaticZenRule> rMap = mockAutoZenRulesAscendingCreationTime(NUM_RULES);
-
-        final String insertedRule1 = "insertedRule1";
-        rMap.put(insertedRule1, new AutomaticZenRule(insertedRule1, null, null,
-                Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 5));
-
-        final String insertedRule2 = "insertedRule2";
-        rMap.put(insertedRule2, new AutomaticZenRule(insertedRule2, null, null,
-                Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 3));
-
-        // rule map with rule creation times, 0, 2, 4, 6, 5, 3
-        // sort should create ordering based on creation times: 0, 2, 3, 4, 5, 6
-        when(mNotificationManager.getAutomaticZenRules()).thenReturn(rMap);
-
-        Map.Entry<String, AutomaticZenRule>[] rules = mController.sortedRules();
-        assertEquals(NUM_RULES + 2, rules.length); // inserted 2 rules
-
-        // check ordering of inserted rules
-        assertEquals(insertedRule1, rules[4].getKey());
-        assertEquals(insertedRule2, rules[2].getKey());
-    }
-
-    private Map<String, AutomaticZenRule> mockAutoZenRulesAscendingCreationTime(int numRules) {
-        Map<String, AutomaticZenRule> ruleMap = new HashMap<>();
-
-        for (int i = 0; i < numRules; i++) {
-            ruleMap.put(GENERIC_RULE_NAME + i, new AutomaticZenRule(GENERIC_RULE_NAME + i, null,
-                    null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, i * 2));
-        }
-
-        return ruleMap;
-    }
-
-    private Map<String, AutomaticZenRule> mockAutoZenRulesDecreasingCreationTime(int numRules) {
-        Map<String, AutomaticZenRule> ruleMap = new HashMap<>();
-
-        for (int i = 0; i < numRules; i++) {
-            ruleMap.put(GENERIC_RULE_NAME + i, new AutomaticZenRule(GENERIC_RULE_NAME + i, null,
-                    null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, numRules - i));
-        }
-
-        return ruleMap;
+    private void mockGetAutomaticZenRules(int numRules, Map<String, AutomaticZenRule> rules) {
+        Map.Entry<String, AutomaticZenRule>[] arr = new Map.Entry[numRules];
+        rules.entrySet().toArray(arr);
+        when(mBackend.getAutomaticZenRules()).thenReturn(arr);
     }
 }
diff --git a/tests/robotests/src/com/android/settings/notification/ZenModeBackendTest.java b/tests/robotests/src/com/android/settings/notification/ZenModeBackendTest.java
new file mode 100644
index 0000000..94a3c01
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/ZenModeBackendTest.java
@@ -0,0 +1,108 @@
+package com.android.settings.notification;
+
+import static junit.framework.Assert.assertEquals;
+
+import android.app.AutomaticZenRule;
+import android.provider.Settings;
+import android.service.notification.ZenModeConfig;
+
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class ZenModeBackendTest {
+
+    private static final String GENERIC_RULE_NAME = "test";
+    private static final String DEFAULT_ID_1 = ZenModeConfig.EVENTS_DEFAULT_RULE_ID;
+    private static final String DEFAULT_ID_2 = ZenModeConfig.EVERY_NIGHT_DEFAULT_RULE_ID;
+
+    @Test
+    public void updateState_checkRuleOrderingDescending() {
+        final int NUM_RULES = 4;
+        Map.Entry<String, AutomaticZenRule>[] rules = populateAutoZenRulesDescendingCreationTime(
+                NUM_RULES, false);
+        Arrays.sort(rules, ZenModeBackend.RULE_COMPARATOR);
+
+        // check ordering, most recent should be at the end
+        for (int i = 0; i < NUM_RULES; i++) {
+            assertEquals(GENERIC_RULE_NAME + (NUM_RULES - 1 - i), rules[i].getKey());
+        }
+    }
+
+    @Test
+    public void updateState_checkRuleOrderingAscending() {
+        final int NUM_RULES = 4;
+        Map.Entry<String, AutomaticZenRule>[] rules = populateAutoZenRulesAscendingCreationTime(
+                NUM_RULES, false);
+        Arrays.sort(rules, ZenModeBackend.RULE_COMPARATOR);
+
+        // check ordering, most recent should be at the end
+        for (int i = 0; i < NUM_RULES; i++) {
+            assertEquals(GENERIC_RULE_NAME + i, rules[i].getKey());
+        }
+    }
+
+    @Test
+    public void updateState_checkRuleOrderingDescending_withDefaultRules() {
+        final int NUM_RULES = 4;
+
+        Map.Entry<String, AutomaticZenRule>[] rules = populateAutoZenRulesDescendingCreationTime(NUM_RULES,
+                true);
+        Arrays.sort(rules, ZenModeBackend.RULE_COMPARATOR);
+
+        assertEquals(rules[0].getKey(), DEFAULT_ID_1);
+        assertEquals(rules[1].getKey(), DEFAULT_ID_2);
+        // NON-DEFAULT RULES check ordering, most recent at the bottom/end
+        for (int i = 0; i < NUM_RULES; i++) {
+            assertEquals(GENERIC_RULE_NAME + (NUM_RULES - 1 - i), rules[i + 2].getKey());
+        }
+    }
+
+    private Map.Entry<String, AutomaticZenRule>[] populateAutoZenRulesAscendingCreationTime(
+            int numRules, boolean addDefaultRules) {
+        Map<String, AutomaticZenRule> ruleMap = new HashMap<>();
+
+        for (int i = 0; i < numRules; i++) {
+            ruleMap.put(GENERIC_RULE_NAME + i, new AutomaticZenRule(GENERIC_RULE_NAME + i, null,
+                    null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, i * 2));
+        }
+
+        if (addDefaultRules) {
+            ruleMap.put(DEFAULT_ID_1, new AutomaticZenRule("DEFAULT_1_NAME", null,
+                    null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 20));
+            ruleMap.put(DEFAULT_ID_2, new AutomaticZenRule("DEFAULT_2_NAME", null,
+                    null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 10));
+        }
+
+        Map.Entry<String, AutomaticZenRule>[] toReturn = new Map.Entry[ruleMap.size()];
+        ruleMap.entrySet().toArray(toReturn);
+        return toReturn;
+    }
+
+    private Map.Entry<String, AutomaticZenRule>[] populateAutoZenRulesDescendingCreationTime(
+            int numRules, boolean addDefaultRules) {
+        Map<String, AutomaticZenRule> ruleMap = new HashMap<>();
+
+        for (int i = 0; i < numRules; i++) {
+            ruleMap.put(GENERIC_RULE_NAME + i, new AutomaticZenRule(GENERIC_RULE_NAME + i, null,
+                    null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, numRules - i));
+        }
+
+        if (addDefaultRules) {
+            ruleMap.put(DEFAULT_ID_1, new AutomaticZenRule("DEFAULT_1_NAME", null,
+                    null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 10));
+            ruleMap.put(DEFAULT_ID_2, new AutomaticZenRule("DEFAULT_2_NAME", null,
+                    null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 20));
+        }
+
+        Map.Entry<String, AutomaticZenRule>[] toReturn = new Map.Entry[ruleMap.size()];
+        ruleMap.entrySet().toArray(toReturn);
+        return toReturn;
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/ZenModeSettingsFooterPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenModeSettingsFooterPreferenceControllerTest.java
index c1634fb..ca9f942 100644
--- a/tests/robotests/src/com/android/settings/notification/ZenModeSettingsFooterPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/ZenModeSettingsFooterPreferenceControllerTest.java
@@ -126,7 +126,7 @@
     }
 
     @Test
-    public void app_manualRule_setFooterTitle() {
+    public void testDefaultNotifPolicy_app_manualRule_setFooterTitle() {
         Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
         injectManualRuleFromApp();
         mController.updateState(mockPref);
@@ -137,7 +137,7 @@
     }
 
     @Test
-    public void time_manualRule_setFooterTitle() {
+    public void testDefaultNotifPolicy_time_manualRule_setFooterTitle() {
         Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
         String placeholder = "placeholder";
         injectManualRuleWithTimeCountdown(1000, placeholder);
@@ -148,7 +148,7 @@
     }
 
     @Test
-    public void forever_manualRule_setFooterTitle() {
+    public void testDefaultNotifPolicy_forever_manualRule_setFooterTitle() {
         Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
         injectManualRuleWithIndefiniteEnd();
         mController.updateState(mockPref);
@@ -158,7 +158,7 @@
     }
 
     @Test
-    public void automaticRule_noManualRule_setFooterTitle() {
+    public void testDefaultNotifPolicy_automaticRule_noManualRule_setFooterTitle() {
         Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
         // no manual rule
         ReflectionHelpers.setField(mZenModeConfig, MANUAL_RULE_FIELD, null);
@@ -174,7 +174,7 @@
     }
 
     @Test
-    public void manualRuleEndsLast_hasAutomaticRule_setFooterTitle() {
+    public void testDefaultNotifPolicy_manualRuleEndsLast_hasAutomaticRule_setFooterTitle() {
         Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
         // manual rule that ends after automatic rule ends
         injectManualRuleWithIndefiniteEnd();
@@ -190,7 +190,7 @@
     }
 
     @Test
-    public void automaticRuleEndsLast_hasManualRule_setFooterTitle() {
+    public void testDefaultNotifPolicy_automaticRuleEndsLast_hasManualRule_setFooterTitle() {
         Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
         // manual rule that ends before automatic rule ends
         injectManualRuleWithTimeCountdown(1000, "");
@@ -208,14 +208,15 @@
     }
 
     @Test
-    public void multipleAutomaticRules_appAutoRuleautomaticRuleApp_setFooterTitle() {
+    public void testDefaultNotifPolicy_multipleAutomaticRules_autoRuleApp_setFooterTitle() {
         Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
 
         // automatic rule that ends after manual rule ends
         ZenRule rule1 = injectNewAutomaticRule(TEST_RULE_NAME + "1", false, false);
         when(mConfigWrapper.parseAutomaticRuleEndTime(rule1.conditionId)).thenReturn(10000L);
 
-        ZenRule rule2 = injectNewAutomaticRule(TEST_RULE_NAME + "2", true, true);
+        // automatic rule that is an app
+        injectNewAutomaticRule(TEST_RULE_NAME + "2", true, true);
 
         ZenRule rule3 = injectNewAutomaticRule(TEST_RULE_NAME + "3", true, false);
         when(mConfigWrapper.parseAutomaticRuleEndTime(rule3.conditionId)).thenReturn(9000L);
@@ -229,7 +230,7 @@
     }
 
     @Test
-    public void multipleAutomaticRules_setFooterTitle() {
+    public void testDefaultNotifPolicy_multipleAutomaticRules_setFooterTitle() {
         Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
 
         // automatic rule that ends after manual rule ends
diff --git a/tests/robotests/src/com/android/settings/panel/FakePanelContent.java b/tests/robotests/src/com/android/settings/panel/FakePanelContent.java
new file mode 100644
index 0000000..60f0d5d
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/panel/FakePanelContent.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.panel;
+
+import static com.android.settings.slices.CustomSliceRegistry.WIFI_SLICE_URI;
+
+import android.content.Intent;
+import android.net.Uri;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Fake PanelContent for testing.
+ */
+public class FakePanelContent implements PanelContent {
+
+    public static final String FAKE_KEY = "fake_key";
+
+    public static final CharSequence TITLE = "title";
+
+    public static final List<Uri> SLICE_URIS = Arrays.asList(
+        WIFI_SLICE_URI
+    );
+
+    public static final Intent INTENT = new Intent();
+
+    @Override
+    public CharSequence getTitle() {
+        return TITLE;
+    }
+
+    @Override
+    public List<Uri> getSlices() {
+        return SLICE_URIS;
+    }
+
+    @Override
+    public Intent getSeeMoreIntent() {
+        return INTENT;
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/panel/FakeSettingsPanelActivity.java b/tests/robotests/src/com/android/settings/panel/FakeSettingsPanelActivity.java
new file mode 100644
index 0000000..afd0bec
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/panel/FakeSettingsPanelActivity.java
@@ -0,0 +1,34 @@
+/*
+ * 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.panel;
+
+import android.content.ComponentName;
+import android.content.Intent;
+
+public class FakeSettingsPanelActivity extends SettingsPanelActivity {
+    @Override
+    public ComponentName getCallingActivity() {
+        return new ComponentName("fake-package", "fake-class");
+    }
+
+    @Override
+    public Intent getIntent() {
+        final Intent intent = new Intent();
+        intent.putExtra(SettingsPanelActivity.EXTRA_PANEL_TYPE, FakePanelContent.FAKE_KEY);
+        return intent;
+    }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/panel/InternetConnectivityPanelTest.java b/tests/robotests/src/com/android/settings/panel/InternetConnectivityPanelTest.java
index 3e210f5..aae85ab 100644
--- a/tests/robotests/src/com/android/settings/panel/InternetConnectivityPanelTest.java
+++ b/tests/robotests/src/com/android/settings/panel/InternetConnectivityPanelTest.java
@@ -21,8 +21,8 @@
 
 import android.net.Uri;
 
+import com.android.settings.slices.CustomSliceRegistry;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
-import com.android.settings.wifi.WifiSlice;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -46,7 +46,12 @@
     public void getSlices_containsNecessarySlices() {
         final List<Uri> uris = mPanel.getSlices();
 
-        assertThat(uris).containsExactly(WifiSlice.WIFI_URI,
-                InternetConnectivityPanel.AIRPLANE_URI);
+        assertThat(uris).containsExactly(CustomSliceRegistry.WIFI_SLICE_URI,
+                CustomSliceRegistry.AIRPLANE_URI);
+    }
+
+    @Test
+    public void getSeeMoreIntent_notNull() {
+        assertThat(mPanel.getSeeMoreIntent()).isNotNull();
     }
 }
diff --git a/tests/robotests/src/com/android/settings/panel/PanelFragmentTest.java b/tests/robotests/src/com/android/settings/panel/PanelFragmentTest.java
new file mode 100644
index 0000000..cf344d2
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/panel/PanelFragmentTest.java
@@ -0,0 +1,88 @@
+/*
+ * 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.panel;
+
+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 android.content.Context;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.widget.LinearLayout;
+
+import com.android.settings.R;
+import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.robolectric.Robolectric;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.android.controller.ActivityController;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class PanelFragmentTest {
+
+    private Context mContext;
+    private PanelFragment mPanelFragment;
+    private FakeFeatureFactory mFakeFeatureFactory;
+    private PanelFeatureProvider mPanelFeatureProvider;
+    private FakePanelContent mFakePanelContent;
+
+    private final String FAKE_EXTRA = "fake_extra";
+
+    @Before
+    public void setUp() {
+        mContext = RuntimeEnvironment.application;
+
+        mPanelFeatureProvider = spy(new PanelFeatureProviderImpl());
+        mFakeFeatureFactory = FakeFeatureFactory.setupForTest();
+        mFakeFeatureFactory.panelFeatureProvider = mPanelFeatureProvider;
+        mFakePanelContent = new FakePanelContent();
+        doReturn(mFakePanelContent).when(mPanelFeatureProvider).getPanel(any(), any());
+
+        ActivityController<FakeSettingsPanelActivity> activityController =
+                Robolectric.buildActivity(FakeSettingsPanelActivity.class);
+        activityController.setup();
+
+        mPanelFragment =
+                spy((PanelFragment)
+                        activityController
+                                .get()
+                                .getSupportFragmentManager()
+                                .findFragmentById(R.id.main_content));
+    }
+
+    @Test
+    public void onCreateView_adapterGetsDataset() {
+        final Bundle bundle = new Bundle();
+        bundle.putString(SettingsPanelActivity.KEY_PANEL_TYPE_ARGUMENT, FAKE_EXTRA);
+        doReturn(bundle).when(mPanelFragment).getArguments();
+        mPanelFragment.onCreateView(LayoutInflater.from(mContext),
+                new LinearLayout(mContext), null);
+        PanelSlicesAdapter adapter = mPanelFragment.mAdapter;
+
+        assertThat(adapter.getData()).containsAllIn(mFakePanelContent.getSlices());
+    }
+
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/panel/PanelSlicesAdapterTest.java b/tests/robotests/src/com/android/settings/panel/PanelSlicesAdapterTest.java
new file mode 100644
index 0000000..02a7d0a
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/panel/PanelSlicesAdapterTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.panel;
+
+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 android.content.Context;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+
+import com.android.settings.R;
+import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.robolectric.Robolectric;
+
+import org.junit.Test;
+
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.android.controller.ActivityController;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class PanelSlicesAdapterTest {
+
+    private Context mContext;
+    private PanelFragment mPanelFragment;
+    private FakePanelContent mFakePanelContent;
+    private FakeFeatureFactory mFakeFeatureFactory;
+    private PanelFeatureProvider mPanelFeatureProvider;
+
+    private PanelSlicesAdapter mAdapter;
+
+    @Before
+    public void setUp() {
+        mContext = RuntimeEnvironment.application;
+
+        mPanelFeatureProvider = spy(new PanelFeatureProviderImpl());
+        mFakeFeatureFactory = FakeFeatureFactory.setupForTest();
+        mFakeFeatureFactory.panelFeatureProvider = mPanelFeatureProvider;
+        mFakePanelContent = new FakePanelContent();
+        doReturn(mFakePanelContent).when(mPanelFeatureProvider).getPanel(any(), any());
+
+        ActivityController<FakeSettingsPanelActivity> activityController =
+                Robolectric.buildActivity(FakeSettingsPanelActivity.class);
+        activityController.setup();
+
+        mPanelFragment =
+                spy((PanelFragment)
+                        activityController
+                                .get()
+                                .getSupportFragmentManager()
+                                .findFragmentById(R.id.main_content));
+
+        mAdapter = new PanelSlicesAdapter(mPanelFragment, mFakePanelContent.getSlices());
+    }
+
+    @Test
+    public void onCreateViewHolder_returnsSliceRowViewHolder() {
+        final ViewGroup view = new FrameLayout(mContext);
+        final PanelSlicesAdapter.SliceRowViewHolder viewHolder =
+                mAdapter.onCreateViewHolder(view, 0);
+
+        assertThat(viewHolder.sliceView).isNotNull();
+    }
+
+    @Test
+    public void onBindViewHolder_bindsSlice() {
+        final int position = 0;
+        final ViewGroup view = new FrameLayout(mContext);
+        final PanelSlicesAdapter.SliceRowViewHolder viewHolder =
+                mAdapter.onCreateViewHolder(view, 0 /* view type*/);
+
+        mAdapter.onBindViewHolder(viewHolder, position);
+
+        assertThat(viewHolder.sliceLiveData).isNotNull();
+    }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/panel/VolumePanelTest.java b/tests/robotests/src/com/android/settings/panel/VolumePanelTest.java
new file mode 100644
index 0000000..21019d3
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/panel/VolumePanelTest.java
@@ -0,0 +1,58 @@
+/*
+ * 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.panel;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.net.Uri;
+
+import com.android.settings.slices.CustomSliceRegistry;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+
+import java.util.List;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class VolumePanelTest {
+
+    private VolumePanel mPanel;
+
+    @Before
+    public void setUp() {
+        mPanel = VolumePanel.create(RuntimeEnvironment.application);
+    }
+
+    @Test
+    public void getSlices_containsNecessarySlices() {
+        final List<Uri> uris = mPanel.getSlices();
+
+        assertThat(uris).containsExactly(
+                CustomSliceRegistry.VOLUME_CALL_URI,
+                CustomSliceRegistry.VOLUME_MEDIA_URI,
+                CustomSliceRegistry.VOLUME_RINGER_URI,
+                CustomSliceRegistry.VOLUME_ALARM_URI);
+    }
+
+    @Test
+    public void getSeeMoreIntent_notNull() {
+        assertThat(mPanel.getSeeMoreIntent()).isNotNull();
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java
index b0e4025..37fd888 100644
--- a/tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java
@@ -53,6 +53,8 @@
         mActivity = Robolectric.setupActivity(Activity.class);
         mProvider = new SearchFeatureProviderImpl();
         mPackageManager = Shadows.shadowOf(mActivity.getPackageManager());
+        Settings.Global.putInt(mActivity.getContentResolver(),
+                Settings.Global.DEVICE_PROVISIONED, 1);
     }
 
     @Test
@@ -82,7 +84,7 @@
 
     @Test
     @Config(shadows = ShadowUtils.class)
-    public void initSearchToolbar_NotHaveResolvedInfo_shouldNotStartActivity() {
+    public void initSearchToolbar_noResolvedInfo_shouldNotStartActivity() {
         final Toolbar toolbar = new Toolbar(mActivity);
         // This ensures navigationView is created.
         toolbar.setNavigationContentDescription("test");
@@ -90,9 +92,21 @@
 
         toolbar.performClick();
 
-        final Intent launchIntent = Shadows.shadowOf(mActivity).getNextStartedActivity();
+        assertThat(Shadows.shadowOf(mActivity).getNextStartedActivity()).isNull();
+    }
 
-        assertThat(launchIntent).isNull();
+    @Test
+    public void initSearchToolbar_deviceNotProvisioned_shouldNotCreateSearchBar() {
+        final Toolbar toolbar = new Toolbar(mActivity);
+        // This ensures navigationView is created.
+        toolbar.setNavigationContentDescription("test");
+
+        Settings.Global.putInt(mActivity.getContentResolver(),
+                Settings.Global.DEVICE_PROVISIONED, 0);
+
+        toolbar.performClick();
+
+        assertThat(Shadows.shadowOf(mActivity).getNextStartedActivity()).isNull();
     }
 
     @Test(expected = IllegalArgumentException.class)
diff --git a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
index 3c2cbdb..8e3c1c8 100644
--- a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
@@ -48,10 +48,6 @@
 import androidx.slice.widget.SliceLiveData;
 
 import com.android.settings.R;
-import com.android.settings.bluetooth.BluetoothSliceBuilder;
-import com.android.settings.flashlight.FlashlightSliceBuilder;
-import com.android.settings.location.LocationSliceBuilder;
-import com.android.settings.notification.ZenModeSliceBuilder;
 import com.android.settings.testutils.DatabaseTestUtils;
 import com.android.settings.testutils.FakeToggleController;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
@@ -113,14 +109,14 @@
     private SliceManager mManager;
 
     private static final List<Uri> SPECIAL_CASE_PLATFORM_URIS = Arrays.asList(
-            WifiSlice.WIFI_URI,
-            BluetoothSliceBuilder.BLUETOOTH_URI,
-            LocationSliceBuilder.LOCATION_URI
+            CustomSliceRegistry.WIFI_SLICE_URI,
+            CustomSliceRegistry.BLUETOOTH_URI,
+            CustomSliceRegistry.LOCATION_SLICE_URI
     );
 
     private static final List<Uri> SPECIAL_CASE_OEM_URIS = Arrays.asList(
-            ZenModeSliceBuilder.ZEN_MODE_URI,
-            FlashlightSliceBuilder.FLASHLIGHT_URI
+            CustomSliceRegistry.ZEN_MODE_SLICE_URI,
+            CustomSliceRegistry.FLASHLIGHT_SLICE_URI
     );
 
     @Before
@@ -472,9 +468,9 @@
 
     @Test
     public void bindSlice_wifiSlice_returnsWifiSlice() {
-        final Slice wifiSlice = mProvider.onBindSlice(WifiSlice.WIFI_URI);
+        final Slice wifiSlice = mProvider.onBindSlice(CustomSliceRegistry.WIFI_SLICE_URI);
 
-        assertThat(wifiSlice.getUri()).isEqualTo(WifiSlice.WIFI_URI);
+        assertThat(wifiSlice.getUri()).isEqualTo(CustomSliceRegistry.WIFI_SLICE_URI);
     }
 
     @Test
@@ -482,9 +478,10 @@
         Settings.Secure.putInt(
                 mContext.getContentResolver(), Settings.Secure.FLASHLIGHT_AVAILABLE, 1);
 
-        final Slice flashlightSlice = mProvider.onBindSlice(FlashlightSliceBuilder.FLASHLIGHT_URI);
+        final Slice flashlightSlice = mProvider.onBindSlice(
+                CustomSliceRegistry.FLASHLIGHT_SLICE_URI);
 
-        assertThat(flashlightSlice.getUri()).isEqualTo(FlashlightSliceBuilder.FLASHLIGHT_URI);
+        assertThat(flashlightSlice.getUri()).isEqualTo(CustomSliceRegistry.FLASHLIGHT_SLICE_URI);
     }
 
     @Test
@@ -526,22 +523,22 @@
 
     @Test
     public void onSlicePinned_backgroundWorker_started() {
-        mProvider.onSlicePinned(WifiSlice.WIFI_URI);
+        mProvider.onSlicePinned(CustomSliceRegistry.WIFI_SLICE_URI);
 
         verify(ShadowWifiScanWorker.getWifiTracker()).onStart();
     }
 
     @Test
     public void onSlicePinned_backgroundWorker_stopped() {
-        mProvider.onSlicePinned(WifiSlice.WIFI_URI);
-        mProvider.onSliceUnpinned(WifiSlice.WIFI_URI);
+        mProvider.onSlicePinned(CustomSliceRegistry.WIFI_SLICE_URI);
+        mProvider.onSliceUnpinned(CustomSliceRegistry.WIFI_SLICE_URI);
 
         verify(ShadowWifiScanWorker.getWifiTracker()).onStop();
     }
 
     @Test
     public void shutdown_backgroundWorker_closed() {
-        mProvider.onSlicePinned(WifiSlice.WIFI_URI);
+        mProvider.onSlicePinned(CustomSliceRegistry.WIFI_SLICE_URI);
         mProvider.shutdown();
 
         verify(ShadowWifiScanWorker.getWifiTracker()).onDestroy();
diff --git a/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java b/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
index 2e2104b..f9937f4 100644
--- a/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
@@ -218,6 +218,19 @@
     }
 
     @Test
+    public void getDynamicSummary_allowDynamicSummary_nullSummary_returnsNull() {
+        final SliceData data = getDummyData(true /*isDynamicSummaryAllowed*/);
+        final FakePreferenceController controller = spy(
+                new FakePreferenceController(mContext, KEY));
+        final String controllerSummary = null;
+        doReturn(controllerSummary).when(controller).getSummary();
+
+        final CharSequence summary = SliceBuilderUtils.getSubtitleText(mContext, controller, data);
+
+        assertThat(summary).isNull();
+    }
+
+    @Test
     public void getDynamicSummary_returnsScreenTitle() {
         final SliceData data = getDummyData();
         final FakePreferenceController controller = new FakePreferenceController(mContext, KEY);
diff --git a/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java b/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
index e14ef1f..bb475f3 100644
--- a/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
+++ b/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
@@ -28,6 +28,7 @@
 import com.android.settings.enterprise.EnterprisePrivacyFeatureProvider;
 import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
 import com.android.settings.gestures.AssistGestureFeatureProvider;
+import com.android.settings.homepage.contextualcards.ContextualCardFeatureProvider;
 import com.android.settings.localepicker.LocaleFeatureProvider;
 import com.android.settings.overlay.DockUpdaterFeatureProvider;
 import com.android.settings.overlay.FeatureFactory;
@@ -62,8 +63,9 @@
     public final UserFeatureProvider userFeatureProvider;
     public final AssistGestureFeatureProvider assistGestureFeatureProvider;
     public final AccountFeatureProvider mAccountFeatureProvider;
-    public final PanelFeatureProvider mPanelFeatureProvider;
+    public final ContextualCardFeatureProvider mContextualCardFeatureProvider;
 
+    public PanelFeatureProvider panelFeatureProvider;
     public SlicesFeatureProvider slicesFeatureProvider;
     public SearchFeatureProvider searchFeatureProvider;
 
@@ -104,7 +106,8 @@
         assistGestureFeatureProvider = mock(AssistGestureFeatureProvider.class);
         slicesFeatureProvider = mock(SlicesFeatureProvider.class);
         mAccountFeatureProvider = mock(AccountFeatureProvider.class);
-        mPanelFeatureProvider = mock(PanelFeatureProvider.class);
+        mContextualCardFeatureProvider = mock(ContextualCardFeatureProvider.class);
+        panelFeatureProvider = mock(PanelFeatureProvider.class);
     }
 
     @Override
@@ -189,6 +192,10 @@
 
     @Override
     public PanelFeatureProvider getPanelFeatureProvider() {
-        return mPanelFeatureProvider;
+        return panelFeatureProvider;
+    }
+
+    public ContextualCardFeatureProvider getContextualCardFeatureProvider() {
+        return mContextualCardFeatureProvider;
     }
 }
diff --git a/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java b/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java
index 9417e9c..74914f4 100644
--- a/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java
+++ b/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java
@@ -84,6 +84,8 @@
             paths.add(new ResourcePath(null,
                     Fs.fromURL(new URL("file:frameworks/base/packages/SettingsLib/SearchWidget/res/")), null));
             paths.add(new ResourcePath(null,
+                    Fs.fromURL(new URL("file:frameworks/base/packages/SettingsLib/ActionButtonsPreference/res")), null));
+            paths.add(new ResourcePath(null,
                     Fs.fromURL(new URL("file:frameworks/base/packages/SettingsLib/SettingsLayoutPreference/res")), null));
             paths.add(new ResourcePath(null,
                 Fs.fromURL(new URL("file:frameworks/base/core/res/res")), null));
diff --git a/tests/robotests/src/com/android/settings/testutils/SliceTester.java b/tests/robotests/src/com/android/settings/testutils/SliceTester.java
index be4199d..26eeb71 100644
--- a/tests/robotests/src/com/android/settings/testutils/SliceTester.java
+++ b/tests/robotests/src/com/android/settings/testutils/SliceTester.java
@@ -110,8 +110,6 @@
 
         final SliceAction mainToggleAction = toggles.get(0);
 
-        final IconCompat expectedToggleIcon = IconCompat.createWithResource(context,
-                sliceData.getIconResource());
         assertThat(mainToggleAction.getIcon()).isNull();
 
         // Check intent in Toggle Action
diff --git a/tests/robotests/src/com/android/settings/widget/ActionButtonPreferenceTest.java b/tests/robotests/src/com/android/settings/widget/ActionButtonPreferenceTest.java
deleted file mode 100644
index 34a9872..0000000
--- a/tests/robotests/src/com/android/settings/widget/ActionButtonPreferenceTest.java
+++ /dev/null
@@ -1,283 +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.widget;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.graphics.drawable.Drawable;
-import android.view.View;
-import android.widget.Button;
-
-import androidx.preference.PreferenceViewHolder;
-
-import com.android.settings.R;
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RuntimeEnvironment;
-
-@RunWith(SettingsRobolectricTestRunner.class)
-public class ActionButtonPreferenceTest {
-
-    private Context mContext;
-    private View mRootView;
-    private ActionButtonPreference mPref;
-    private PreferenceViewHolder mHolder;
-
-    @Before
-    public void setUp() {
-        mContext = RuntimeEnvironment.application;
-        mRootView = View.inflate(mContext, R.layout.settings_action_buttons, null /* parent */);
-        mHolder = PreferenceViewHolder.createInstanceForTests(mRootView);
-        mPref = new ActionButtonPreference(mContext);
-    }
-
-    @Test
-    public void onBindViewHolder_setTitle_shouldShowButtonByDefault() {
-        mPref.setButton1Text(R.string.settings_label);
-        mPref.setButton2Text(R.string.settings_label);
-        mPref.setButton3Text(R.string.settings_label);
-        mPref.setButton4Text(R.string.settings_label);
-
-        mPref.onBindViewHolder(mHolder);
-
-        assertThat(mRootView.findViewById(R.id.button1).getVisibility())
-                .isEqualTo(View.VISIBLE);
-        assertThat(mRootView.findViewById(R.id.button2).getVisibility())
-                .isEqualTo(View.VISIBLE);
-        assertThat(mRootView.findViewById(R.id.button3).getVisibility())
-                .isEqualTo(View.VISIBLE);
-        assertThat(mRootView.findViewById(R.id.button4).getVisibility())
-                .isEqualTo(View.VISIBLE);
-    }
-
-    @Test
-    public void onBindViewHolder_setIcon_shouldShowButtonByDefault() {
-        mPref.setButton1Icon(R.drawable.ic_settings);
-        mPref.setButton2Icon(R.drawable.ic_settings);
-        mPref.setButton3Icon(R.drawable.ic_settings);
-        mPref.setButton4Icon(R.drawable.ic_settings);
-
-        mPref.onBindViewHolder(mHolder);
-
-        assertThat(mRootView.findViewById(R.id.button1).getVisibility())
-                .isEqualTo(View.VISIBLE);
-        assertThat(mRootView.findViewById(R.id.button2).getVisibility())
-                .isEqualTo(View.VISIBLE);
-        assertThat(mRootView.findViewById(R.id.button3).getVisibility())
-                .isEqualTo(View.VISIBLE);
-        assertThat(mRootView.findViewById(R.id.button4).getVisibility())
-                .isEqualTo(View.VISIBLE);
-    }
-
-    @Test
-    public void onBindViewHolder_notSetTitleOrIcon_shouldNotShowButtonByDefault() {
-        mPref.onBindViewHolder(mHolder);
-
-        assertThat(mRootView.findViewById(R.id.button1).getVisibility())
-                .isEqualTo(View.GONE);
-        assertThat(mRootView.findViewById(R.id.button2).getVisibility())
-                .isEqualTo(View.GONE);
-        assertThat(mRootView.findViewById(R.id.button3).getVisibility())
-                .isEqualTo(View.GONE);
-        assertThat(mRootView.findViewById(R.id.button4).getVisibility())
-                .isEqualTo(View.GONE);
-    }
-
-    @Test
-    public void onBindViewHolder_setVisibleIsGoneAndSetTitle_shouldNotShowButton() {
-        mPref.setButton1Text(R.string.settings_label).setButton1Visible(false);
-        mPref.setButton2Text(R.string.settings_label).setButton2Visible(false);
-        mPref.setButton3Text(R.string.settings_label).setButton3Visible(false);
-        mPref.setButton4Text(R.string.settings_label).setButton4Visible(false);
-
-        mPref.onBindViewHolder(mHolder);
-
-        assertThat(mRootView.findViewById(R.id.button1).getVisibility())
-                .isEqualTo(View.GONE);
-        assertThat(mRootView.findViewById(R.id.button2).getVisibility())
-                .isEqualTo(View.GONE);
-        assertThat(mRootView.findViewById(R.id.button3).getVisibility())
-                .isEqualTo(View.GONE);
-        assertThat(mRootView.findViewById(R.id.button4).getVisibility())
-                .isEqualTo(View.GONE);
-    }
-
-    @Test
-    public void onBindViewHolder_setVisibleIsGoneAndSetIcon_shouldNotShowButton() {
-        mPref.setButton1Icon(R.drawable.ic_settings).setButton1Visible(false);
-        mPref.setButton2Icon(R.drawable.ic_settings).setButton2Visible(false);
-        mPref.setButton3Icon(R.drawable.ic_settings).setButton3Visible(false);
-        mPref.setButton4Icon(R.drawable.ic_settings).setButton4Visible(false);
-
-        mPref.onBindViewHolder(mHolder);
-
-        assertThat(mRootView.findViewById(R.id.button1).getVisibility())
-                .isEqualTo(View.GONE);
-        assertThat(mRootView.findViewById(R.id.button2).getVisibility())
-                .isEqualTo(View.GONE);
-        assertThat(mRootView.findViewById(R.id.button3).getVisibility())
-                .isEqualTo(View.GONE);
-        assertThat(mRootView.findViewById(R.id.button4).getVisibility())
-                .isEqualTo(View.GONE);
-    }
-
-    @Test
-    public void onBindViewHolder_setVisibility_shouldUpdateButtonVisibility() {
-        mPref.setButton1Text(R.string.settings_label).setButton1Visible(false);
-        mPref.setButton2Text(R.string.settings_label).setButton2Visible(false);
-        mPref.setButton3Text(R.string.settings_label).setButton3Visible(false);
-        mPref.setButton4Text(R.string.settings_label).setButton4Visible(false);
-
-        mPref.onBindViewHolder(mHolder);
-
-        assertThat(mRootView.findViewById(R.id.button1).getVisibility())
-                .isEqualTo(View.GONE);
-        assertThat(mRootView.findViewById(R.id.button2).getVisibility())
-                .isEqualTo(View.GONE);
-        assertThat(mRootView.findViewById(R.id.button3).getVisibility())
-                .isEqualTo(View.GONE);
-        assertThat(mRootView.findViewById(R.id.button4).getVisibility())
-                .isEqualTo(View.GONE);
-
-        mPref.setButton1Visible(true);
-        mPref.setButton2Visible(true);
-        mPref.setButton3Visible(true);
-        mPref.setButton4Visible(true);
-
-        mPref.onBindViewHolder(mHolder);
-
-        assertThat(mRootView.findViewById(R.id.button1).getVisibility())
-                .isEqualTo(View.VISIBLE);
-        assertThat(mRootView.findViewById(R.id.button2).getVisibility())
-                .isEqualTo(View.VISIBLE);
-        assertThat(mRootView.findViewById(R.id.button3).getVisibility())
-                .isEqualTo(View.VISIBLE);
-        assertThat(mRootView.findViewById(R.id.button4).getVisibility())
-                .isEqualTo(View.VISIBLE);
-    }
-
-    @Test
-    public void onBindViewHolder_setEnabled_shouldEnableButton() {
-        mPref.setButton1Enabled(true);
-        mPref.setButton2Enabled(false);
-        mPref.setButton3Enabled(true);
-        mPref.setButton4Enabled(false);
-
-        mPref.onBindViewHolder(mHolder);
-
-        assertThat(mRootView.findViewById(R.id.button1).isEnabled()).isTrue();
-        assertThat(mRootView.findViewById(R.id.button2).isEnabled()).isFalse();
-        assertThat(mRootView.findViewById(R.id.button3).isEnabled()).isTrue();
-        assertThat(mRootView.findViewById(R.id.button4).isEnabled()).isFalse();
-    }
-
-    @Test
-    public void onBindViewHolder_setText_shouldShowSameText() {
-        mPref.setButton1Text(R.string.settings_label);
-        mPref.setButton2Text(R.string.settings_label);
-        mPref.setButton3Text(R.string.settings_label);
-        mPref.setButton4Text(R.string.settings_label);
-
-        mPref.onBindViewHolder(mHolder);
-
-        assertThat(((Button) mRootView.findViewById(R.id.button1)).getText())
-                .isEqualTo(mContext.getText(R.string.settings_label));
-        assertThat(((Button) mRootView.findViewById(R.id.button2)).getText())
-                .isEqualTo(mContext.getText(R.string.settings_label));
-        assertThat(((Button) mRootView.findViewById(R.id.button3)).getText())
-                .isEqualTo(mContext.getText(R.string.settings_label));
-        assertThat(((Button) mRootView.findViewById(R.id.button4)).getText())
-                .isEqualTo(mContext.getText(R.string.settings_label));
-    }
-
-    @Test
-    public void onBindViewHolder_setButtonIcon_iconMustDisplayAboveText() {
-        mPref.setButton1Text(R.string.settings_label);
-        mPref.setButton1Icon(R.drawable.ic_settings);
-
-        mPref.onBindViewHolder(mHolder);
-        final Drawable[] drawablesAroundText =
-                ((Button) mRootView.findViewById(R.id.button1))
-                        .getCompoundDrawables();
-
-        assertThat(drawablesAroundText[1 /* top */]).isNotNull();
-    }
-
-    @Test
-    public void setButtonIcon_iconResourceIdIsZero_shouldNotDisplayIcon() {
-        mPref.setButton1Text(R.string.settings_label);
-        mPref.setButton1Icon(0);
-
-        mPref.onBindViewHolder(mHolder);
-        final Drawable[] drawablesAroundText =
-                ((Button) mRootView.findViewById(R.id.button1))
-                        .getCompoundDrawables();
-
-        assertThat(drawablesAroundText[1 /* top */]).isNull();
-    }
-
-    @Test
-    public void setButtonIcon_iconResourceIdNotExisting_shouldNotDisplayIconAndCrash() {
-        mPref.setButton1Text(R.string.settings_label);
-        mPref.setButton1Icon(999999999 /* not existing id */);
-        // Should not crash here
-        mPref.onBindViewHolder(mHolder);
-        final Drawable[] drawablesAroundText =
-                ((Button) mRootView.findViewById(R.id.button1))
-                        .getCompoundDrawables();
-
-        assertThat(drawablesAroundText[1 /* top */]).isNull();
-    }
-
-    public static ActionButtonPreference createMock() {
-        final ActionButtonPreference pref = mock(ActionButtonPreference.class);
-        when(pref.setButton1Text(anyInt())).thenReturn(pref);
-        when(pref.setButton1Icon(anyInt())).thenReturn(pref);
-        when(pref.setButton1Enabled(anyBoolean())).thenReturn(pref);
-        when(pref.setButton1Visible(anyBoolean())).thenReturn(pref);
-        when(pref.setButton1OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
-
-        when(pref.setButton2Text(anyInt())).thenReturn(pref);
-        when(pref.setButton2Icon(anyInt())).thenReturn(pref);
-        when(pref.setButton2Enabled(anyBoolean())).thenReturn(pref);
-        when(pref.setButton2Visible(anyBoolean())).thenReturn(pref);
-        when(pref.setButton2OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
-
-        when(pref.setButton3Text(anyInt())).thenReturn(pref);
-        when(pref.setButton3Icon(anyInt())).thenReturn(pref);
-        when(pref.setButton3Enabled(anyBoolean())).thenReturn(pref);
-        when(pref.setButton3Visible(anyBoolean())).thenReturn(pref);
-        when(pref.setButton3OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
-
-        when(pref.setButton4Text(anyInt())).thenReturn(pref);
-        when(pref.setButton4Icon(anyInt())).thenReturn(pref);
-        when(pref.setButton4Enabled(anyBoolean())).thenReturn(pref);
-        when(pref.setButton4Visible(anyBoolean())).thenReturn(pref);
-        when(pref.setButton4OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
-        return pref;
-    }
-}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/widget/RoundedHomepageIconTest.java b/tests/robotests/src/com/android/settings/widget/RoundedHomepageIconTest.java
index aaffa93..5bc8dda 100644
--- a/tests/robotests/src/com/android/settings/widget/RoundedHomepageIconTest.java
+++ b/tests/robotests/src/com/android/settings/widget/RoundedHomepageIconTest.java
@@ -101,7 +101,7 @@
     public void onBindTile_externalTileWithBackgroundColorHint_shouldUpdateIcon() {
         final Tile tile = spy(new Tile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE));
         mActivityInfo.metaData.putInt(META_DATA_PREFERENCE_ICON_BACKGROUND_HINT,
-                R.color.memory_critical);
+                R.color.material_blue_500);
         doReturn(Icon.createWithResource(mContext, R.drawable.ic_settings))
                 .when(tile).getIcon(mContext);
 
@@ -110,7 +110,7 @@
         icon.setBackgroundColor(mContext, tile);
 
         assertThat(icon.mBackgroundColor)
-                .isEqualTo(mContext.getColor(R.color.memory_critical));
+                .isEqualTo(mContext.getColor(R.color.material_blue_500));
     }
 
 }
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 ae4c753..11dd56e 100644
--- a/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSliceHelperTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSliceHelperTest.java
@@ -49,6 +49,7 @@
 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;
 import com.android.settings.slices.SliceData;
@@ -113,7 +114,7 @@
         mWfcSliceHelper.setDefaultVoiceSubId(-1);
 
         final Slice slice = mWfcSliceHelper.createWifiCallingSlice(
-                WifiCallingSliceHelper.WIFI_CALLING_URI);
+                CustomSliceRegistry.WIFI_CALLING_URI);
 
         assertThat(slice).isNull();
     }
@@ -123,7 +124,7 @@
         when(mMockImsManager.isWfcEnabledByPlatform()).thenReturn(false);
 
         final Slice slice = mWfcSliceHelper.createWifiCallingSlice(
-                WifiCallingSliceHelper.WIFI_CALLING_URI);
+                CustomSliceRegistry.WIFI_CALLING_URI);
 
         assertThat(mWfcSliceHelper.getDefaultVoiceSubId()).isEqualTo(1);
         assertThat(slice).isNull();
@@ -144,7 +145,7 @@
         mWfcSliceHelper.setActivationAppIntent(new Intent()); // dummy Intent
 
         final Slice slice  = mWfcSliceHelper.createWifiCallingSlice(
-                WifiCallingSliceHelper.WIFI_CALLING_URI);
+                CustomSliceRegistry.WIFI_CALLING_URI);
 
         assertThat(mWfcSliceHelper.getDefaultVoiceSubId()).isEqualTo(1);
         testWifiCallingSettingsUnavailableSlice(slice, null,
@@ -161,7 +162,7 @@
         when(mMockCarrierConfigManager.getConfigForSubId(1)).thenReturn(null);
 
         final Slice slice = mWfcSliceHelper.createWifiCallingSlice(
-                WifiCallingSliceHelper.WIFI_CALLING_URI);
+                CustomSliceRegistry.WIFI_CALLING_URI);
 
         assertThat(mWfcSliceHelper.getDefaultVoiceSubId()).isEqualTo(1);
         testWifiCallingSettingsToggleSlice(slice, null);
@@ -177,7 +178,7 @@
         when(mSlicesFeatureProvider.getNewWifiCallingSliceHelper(mContext))
                 .thenReturn(mWfcSliceHelper);
 
-        final Slice slice = mProvider.onBindSlice(WifiCallingSliceHelper.WIFI_CALLING_URI);
+        final Slice slice = mProvider.onBindSlice(CustomSliceRegistry.WIFI_CALLING_URI);
 
         assertThat(mWfcSliceHelper.getDefaultVoiceSubId()).isEqualTo(1);
         testWifiCallingSettingsToggleSlice(slice, null);
@@ -217,7 +218,7 @@
         mWfcSliceHelper.setIsWifiCallingPrefEditable(false);
 
         final Slice slice = mWfcSliceHelper.createWifiCallingPreferenceSlice(
-                WifiCallingSliceHelper.WIFI_CALLING_PREFERENCE_URI);
+                CustomSliceRegistry.WIFI_CALLING_PREFERENCE_URI);
 
         assertThat(mWfcSliceHelper.getDefaultVoiceSubId()).isEqualTo(1);
         assertThat(slice).isNull();
@@ -232,7 +233,7 @@
         mWfcSliceHelper.setIsWifiCallingPrefEditable(true);
 
         final Slice slice = mWfcSliceHelper.createWifiCallingPreferenceSlice(
-                WifiCallingSliceHelper.WIFI_CALLING_PREFERENCE_URI);
+                CustomSliceRegistry.WIFI_CALLING_PREFERENCE_URI);
 
         assertThat(mWfcSliceHelper.getDefaultVoiceSubId()).isEqualTo(1);
         testWifiCallingSettingsUnavailableSlice(slice, null,
@@ -251,7 +252,7 @@
         mWfcSliceHelper.setIsWifiCallingPrefEditable(true);
 
         final Slice slice = mWfcSliceHelper.createWifiCallingPreferenceSlice(
-                WifiCallingSliceHelper.WIFI_CALLING_PREFERENCE_URI);
+                CustomSliceRegistry.WIFI_CALLING_PREFERENCE_URI);
 
         assertThat(mWfcSliceHelper.getDefaultVoiceSubId()).isEqualTo(1);
         testWifiCallingPreferenceSlice(slice, null,
@@ -271,7 +272,7 @@
         mWfcSliceHelper.setIsWifiCallingPrefEditable(true);
 
         final Slice slice = mProvider.onBindSlice(
-                WifiCallingSliceHelper.WIFI_CALLING_PREFERENCE_URI);
+                CustomSliceRegistry.WIFI_CALLING_PREFERENCE_URI);
 
         assertThat(mWfcSliceHelper.getDefaultVoiceSubId()).isEqualTo(1);
         testWifiCallingPreferenceSlice(slice, null,
diff --git a/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
index 4a0988a..39215c1 100644
--- a/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
@@ -17,12 +17,14 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.nullable;
 import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.spy;
@@ -57,6 +59,7 @@
 
 import androidx.fragment.app.FragmentActivity;
 import androidx.lifecycle.LifecycleOwner;
+import androidx.preference.Preference;
 import androidx.preference.PreferenceCategory;
 import androidx.preference.PreferenceScreen;
 
@@ -66,12 +69,10 @@
 import com.android.settings.testutils.shadow.ShadowBidiFormatter;
 import com.android.settings.testutils.shadow.ShadowDevicePolicyManager;
 import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
-import com.android.settings.widget.ActionButtonPreference;
-import com.android.settings.widget.ActionButtonPreferenceTest;
 import com.android.settings.widget.EntityHeaderController;
-import com.android.settings.wifi.WifiDetailPreference;
 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
 import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.widget.ActionButtonsPreference;
 import com.android.settingslib.widget.LayoutPreference;
 import com.android.settingslib.wifi.AccessPoint;
 
@@ -142,29 +143,29 @@
     private ImageView mockHeaderIcon;
 
     @Mock
-    private ActionButtonPreference mockButtonsPref;
+    private ActionButtonsPreference mockButtonsPref;
     @Mock
-    private WifiDetailPreference mockSignalStrengthPref;
+    private Preference mockSignalStrengthPref;
     @Mock
-    private WifiDetailPreference mockLinkSpeedPref;
+    private Preference mockLinkSpeedPref;
     @Mock
-    private WifiDetailPreference mockFrequencyPref;
+    private Preference mockFrequencyPref;
     @Mock
-    private WifiDetailPreference mockSecurityPref;
+    private Preference mockSecurityPref;
     @Mock
-    private WifiDetailPreference mockMacAddressPref;
+    private Preference mockMacAddressPref;
     @Mock
-    private WifiDetailPreference mockIpAddressPref;
+    private Preference mockIpAddressPref;
     @Mock
-    private WifiDetailPreference mockGatewayPref;
+    private Preference mockGatewayPref;
     @Mock
-    private WifiDetailPreference mockSubnetPref;
+    private Preference mockSubnetPref;
     @Mock
-    private WifiDetailPreference mockDnsPref;
+    private Preference mockDnsPref;
     @Mock
     private PreferenceCategory mockIpv6Category;
     @Mock
-    private WifiDetailPreference mockIpv6AddressesPref;
+    private Preference mockIpv6AddressesPref;
     @Mock
     private PackageManager mockPackageManager;
 
@@ -247,7 +248,7 @@
                 .thenReturn(mockNetworkInfo);
         doNothing().when(mockConnectivityManager).registerNetworkCallback(
                 nullable(NetworkRequest.class), mCallbackCaptor.capture(), nullable(Handler.class));
-        mockButtonsPref = ActionButtonPreferenceTest.createMock();
+        mockButtonsPref = createMock();
         when(mockButtonsPref.setButton1OnClickListener(mForgetClickListener.capture()))
                 .thenReturn(mockButtonsPref);
 
@@ -336,7 +337,7 @@
     public void securityPreference_stringShouldBeSet() {
         displayAndResume();
 
-        verify(mockSecurityPref).setDetailText(SECURITY);
+        verify(mockSecurityPref).setSummary(SECURITY);
     }
 
     @Test
@@ -413,7 +414,7 @@
 
         displayAndResume();
 
-        verify(mockSignalStrengthPref).setDetailText(expectedStrength);
+        verify(mockSignalStrengthPref).setSummary(expectedStrength);
     }
 
     @Test
@@ -422,7 +423,7 @@
 
         displayAndResume();
 
-        verify(mockLinkSpeedPref).setDetailText(expectedLinkSpeed);
+        verify(mockLinkSpeedPref).setSummary(expectedLinkSpeed);
     }
 
     @Test
@@ -438,7 +439,7 @@
     public void macAddressPref_shouldHaveDetailTextSet() {
         displayAndResume();
 
-        verify(mockMacAddressPref).setDetailText(MAC_ADDRESS);
+        verify(mockMacAddressPref).setSummary(MAC_ADDRESS);
     }
 
     @Test
@@ -447,7 +448,7 @@
 
         displayAndResume();
 
-        verify(mockIpAddressPref).setDetailText(Constants.IPV4_ADDR.getAddress().getHostAddress());
+        verify(mockIpAddressPref).setSummary(Constants.IPV4_ADDR.getAddress().getHostAddress());
     }
 
     @Test
@@ -458,8 +459,8 @@
 
         displayAndResume();
 
-        verify(mockSubnetPref).setDetailText("255.255.255.128");
-        verify(mockGatewayPref).setDetailText("192.0.2.127");
+        verify(mockSubnetPref).setSummary("255.255.255.128");
+        verify(mockGatewayPref).setSummary("192.0.2.127");
     }
 
     @Test
@@ -470,7 +471,7 @@
 
         displayAndResume();
 
-        verify(mockDnsPref).setDetailText(
+        verify(mockDnsPref).setSummary(
                 "8.8.4.4\n" +
                         "8.8.8.8\n" +
                         Constants.IPV6_DNS.getHostAddress());
@@ -551,15 +552,15 @@
 
         lp.addRoute(Constants.IPV4_DEFAULT);
         updateLinkProperties(lp);
-        inOrder.verify(mockGatewayPref).setDetailText(Constants.IPV4_GATEWAY.getHostAddress());
+        inOrder.verify(mockGatewayPref).setSummary(Constants.IPV4_GATEWAY.getHostAddress());
         inOrder.verify(mockGatewayPref).setVisible(true);
 
         lp.addLinkAddress(Constants.IPV4_ADDR);
         lp.addRoute(Constants.IPV4_SUBNET);
         updateLinkProperties(lp);
-        inOrder.verify(mockIpAddressPref).setDetailText(asString(Constants.IPV4_ADDR));
+        inOrder.verify(mockIpAddressPref).setSummary(asString(Constants.IPV4_ADDR));
         inOrder.verify(mockIpAddressPref).setVisible(true);
-        inOrder.verify(mockSubnetPref).setDetailText("255.255.255.128");
+        inOrder.verify(mockSubnetPref).setSummary("255.255.255.128");
         inOrder.verify(mockSubnetPref).setVisible(true);
 
         lp.addLinkAddress(Constants.IPV6_GLOBAL1);
@@ -578,13 +579,13 @@
 
         lp.addDnsServer(Constants.IPV6_DNS);
         updateLinkProperties(lp);
-        inOrder.verify(mockDnsPref).setDetailText(Constants.IPV6_DNS.getHostAddress());
+        inOrder.verify(mockDnsPref).setSummary(Constants.IPV6_DNS.getHostAddress());
         inOrder.verify(mockDnsPref).setVisible(true);
 
         lp.addDnsServer(Constants.IPV4_DNS1);
         lp.addDnsServer(Constants.IPV4_DNS2);
         updateLinkProperties(lp);
-        inOrder.verify(mockDnsPref).setDetailText(
+        inOrder.verify(mockDnsPref).setSummary(
                 Constants.IPV6_DNS.getHostAddress() + "\n" +
                         Constants.IPV4_DNS1.getHostAddress() + "\n" +
                         Constants.IPV4_DNS2.getHostAddress());
@@ -849,4 +850,21 @@
         verify(mockAccessPoint, times(2)).getLevel();
         verify(mockIconInjector, times(2)).getIcon(anyInt());
     }
+
+    private ActionButtonsPreference createMock() {
+        final ActionButtonsPreference pref = mock(ActionButtonsPreference.class);
+        when(pref.setButton1Text(anyInt())).thenReturn(pref);
+        when(pref.setButton1Icon(anyInt())).thenReturn(pref);
+        when(pref.setButton1Enabled(anyBoolean())).thenReturn(pref);
+        when(pref.setButton1Visible(anyBoolean())).thenReturn(pref);
+        when(pref.setButton1OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
+
+        when(pref.setButton2Text(anyInt())).thenReturn(pref);
+        when(pref.setButton2Icon(anyInt())).thenReturn(pref);
+        when(pref.setButton2Enabled(anyBoolean())).thenReturn(pref);
+        when(pref.setButton2Visible(anyBoolean())).thenReturn(pref);
+        when(pref.setButton2OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
+
+        return pref;
+    }
 }
diff --git a/tests/unit/src/com/android/settings/slices/SliceDeepLinkSpringBoardTest.java b/tests/unit/src/com/android/settings/slices/SliceDeepLinkSpringBoardTest.java
index 81f1fac..bd8649d 100644
--- a/tests/unit/src/com/android/settings/slices/SliceDeepLinkSpringBoardTest.java
+++ b/tests/unit/src/com/android/settings/slices/SliceDeepLinkSpringBoardTest.java
@@ -26,11 +26,6 @@
 import android.support.test.filters.MediumTest;
 import android.support.test.runner.AndroidJUnit4;
 
-import com.android.settings.bluetooth.BluetoothSliceBuilder;
-import com.android.settings.location.LocationSliceBuilder;
-import com.android.settings.notification.ZenModeSliceBuilder;
-import com.android.settings.wifi.WifiSlice;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -57,7 +52,8 @@
     @Test
     @Presubmit
     public void launchesDeepLinkIntent_wifiSlice_shouldNotCrash() {
-        final Intent deepLinkIntent = getSpringboardIntent(WifiSlice.WIFI_URI.toString());
+        final Intent deepLinkIntent = getSpringboardIntent(
+                CustomSliceRegistry.WIFI_SLICE_URI.toString());
 
         mContext.startActivity(deepLinkIntent);
     }
@@ -66,7 +62,7 @@
     @Presubmit
     public void launchesDeepLinkIntent_bluetoothSlice_shouldNotCrash() {
         final Intent deepLinkIntent = getSpringboardIntent(
-                BluetoothSliceBuilder.BLUETOOTH_URI.toString());
+                CustomSliceRegistry.BLUETOOTH_URI.toString());
 
         mContext.startActivity(deepLinkIntent);
     }
@@ -75,7 +71,7 @@
     @Presubmit
     public void launchesDeepLinkIntent_dndSlice_shouldNotCrash() {
         final Intent deepLinkIntent = getSpringboardIntent(
-                ZenModeSliceBuilder.ZEN_MODE_URI.toString());
+                CustomSliceRegistry.ZEN_MODE_SLICE_URI.toString());
 
         mContext.startActivity(deepLinkIntent);
     }
@@ -84,7 +80,7 @@
     @Presubmit
     public void launchesDeepLinkIntent_locationSlice_shouldNotCrash() {
         final Intent deepLinkIntent = getSpringboardIntent(
-                LocationSliceBuilder.LOCATION_URI.toString());
+                CustomSliceRegistry.LOCATION_SLICE_URI.toString());
 
         mContext.startActivity(deepLinkIntent);
     }
diff --git a/tests/unit/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivityTest.java b/tests/unit/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivityTest.java
index d101c92..70e9587 100644
--- a/tests/unit/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivityTest.java
+++ b/tests/unit/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivityTest.java
@@ -35,23 +35,42 @@
             new ActivityTestRule<>(WifiDppConfiguratorActivity.class);
 
     @Test
-    public void testLaunchModeQrCodeScanner_shouldNotAutoFinish() {
-        Intent intent = new Intent();
-        intent.putExtra(WifiDppConfiguratorActivity.EXTRA_LAUNCH_MODE,
-                WifiDppConfiguratorActivity.LaunchMode.LAUNCH_MODE_QR_CODE_SCANNER.getMode());
+    public void launchActivity_qrCodeScanner_shouldNotAutoFinish() {
+        Intent intent = new Intent(WifiDppConfiguratorActivity.ACTION_CONFIGURATOR_QR_CODE_SCANNER);
+        intent.putExtra(WifiDppUtils.EXTRA_WIFI_SECURITY, "WEP");
+        intent.putExtra(WifiDppUtils.EXTRA_WIFI_SSID, "GoogleGuest");
+
         mActivityRule.launchActivity(intent);
 
         assertThat(mActivityRule.getActivity().isFinishing()).isEqualTo(false);
-        mActivityRule.finishActivity();
     }
 
     @Test
-    public void testNoLaunchMode_shouldFinishActivityWithResultCodeCanceled() {
-        // If we do not specify launch mode, the activity will finish itself right away
-        Intent intent = new Intent();
+    public void launchActivity_qrCodeGenerator_shouldNotAutoFinish() {
+        Intent intent = new Intent(
+                WifiDppConfiguratorActivity.ACTION_CONFIGURATOR_QR_CODE_GENERATOR);
+        intent.putExtra(WifiDppUtils.EXTRA_WIFI_SECURITY, "WEP");
+        intent.putExtra(WifiDppUtils.EXTRA_WIFI_SSID, "GoogleGuest");
+
         mActivityRule.launchActivity(intent);
 
-        assertThat(mActivityRule.getActivityResult().getResultCode()).
-                isEqualTo(Activity.RESULT_CANCELED);
+        assertThat(mActivityRule.getActivity().isFinishing()).isEqualTo(false);
+    }
+
+    @Test
+    public void launchActivity_chooseSavedWifiNetwork_shouldNotAutoFinish() {
+        Intent intent = new Intent(
+                WifiDppConfiguratorActivity.ACTION_CONFIGURATOR_CHOOSE_SAVED_WIFI_NETWORK);
+
+        mActivityRule.launchActivity(intent);
+
+        assertThat(mActivityRule.getActivity().isFinishing()).isEqualTo(false);
+    }
+
+    @Test
+    public void testActivity_shouldImplementsWifiNetworkConfigRetriever() {
+        WifiDppConfiguratorActivity activity = mActivityRule.getActivity();
+
+        assertThat(activity instanceof WifiNetworkConfig.Retriever).isEqualTo(true);
     }
 }
diff --git a/tests/unit/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragmentTest.java b/tests/unit/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragmentTest.java
index 58fa61f..98742ed 100644
--- a/tests/unit/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragmentTest.java
+++ b/tests/unit/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragmentTest.java
@@ -24,9 +24,12 @@
 
 import android.app.Activity;
 import android.content.Intent;
+import android.content.pm.ActivityInfo;
 import android.support.test.rule.ActivityTestRule;
 import android.support.test.runner.AndroidJUnit4;
 
+import com.android.settings.R;
+
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -40,16 +43,17 @@
 
     @Before
     public void setUp() {
-        Intent intent = new Intent();
-        intent.putExtra(WifiDppConfiguratorActivity.EXTRA_LAUNCH_MODE,
-                WifiDppConfiguratorActivity.LaunchMode.LAUNCH_MODE_QR_CODE_SCANNER.getMode());
+        Intent intent = new Intent(WifiDppConfiguratorActivity.ACTION_CONFIGURATOR_QR_CODE_SCANNER);
+        intent.putExtra(WifiDppUtils.EXTRA_WIFI_SECURITY, "WEP");
+        intent.putExtra(WifiDppUtils.EXTRA_WIFI_SSID, "GoogleGuest");
         mActivityRule.launchActivity(intent);
     }
 
     @Test
-    public void testLeftButton_shouldFinishActivityWithResultCodeCanceled() {
-        onView(withText("Cancel")).perform(click());
-        assertThat(mActivityRule.getActivityResult().getResultCode()).
-                isEqualTo(Activity.RESULT_CANCELED);
+    public void rotateScreen_shouldNotCrash() {
+        mActivityRule.getActivity().setRequestedOrientation(
+                ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
+        mActivityRule.getActivity().setRequestedOrientation(
+                ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
     }
 }