Merge "[Settings] Adds an intent extra when setup wizard start the WallpaperSuggestionActivity"
diff --git a/Android.bp b/Android.bp
index b997b91..d21a430 100644
--- a/Android.bp
+++ b/Android.bp
@@ -43,7 +43,17 @@
     libs: [
         "telephony-common",
         "ims-common",
+        "app-compat-annotations",
     ],
+
+    plugins: [
+        "compat-changeid-annotation-processor",
+    ]
+}
+
+platform_compat_config {
+    name: "settings-platform-compat-config",
+    src: ":Settings-core",
 }
 
 android_app {
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 6ee6a87..a4803a9 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -3244,6 +3244,24 @@
                 android:value="com.android.settings.gestures.GlobalActionsPanelSettings" />
         </activity>
 
+        <activity
+            android:name="Settings$GestureNavigationSettingsActivity"
+            android:label="@string/gesture_settings_activity_title"
+            android:enabled="true">
+            <intent-filter android:priority="32">
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="com.android.settings.SHORTCUT" />
+            </intent-filter>
+            <intent-filter android:priority="1">
+                <action android:name="com.android.settings.GESTURE_NAVIGATION_SETTINGS" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                       android:value="com.android.settings.gestures.GestureNavigationSettingsFragment" />
+            <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
+                       android:value="true" />
+        </activity>
+
         <!-- This is the longest AndroidManifest.xml ever. -->
     </application>
 </manifest>
diff --git a/color-check-baseline.xml b/color-check-baseline.xml
index 3cb964f..a258cc6 100644
--- a/color-check-baseline.xml
+++ b/color-check-baseline.xml
@@ -2,18 +2,6 @@
 <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"
@@ -121,7 +109,7 @@
         errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/layout-land/choose_lock_pattern.xml"
-            line="178"
+            line="127"
             column="17"/>
     </issue>
 
@@ -1081,7 +1069,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="113"
+            line="111"
             column="5"/>
     </issue>
 
@@ -1097,7 +1085,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="114"
+            line="112"
             column="5"/>
     </issue>
 
@@ -1113,7 +1101,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="115"
+            line="113"
             column="5"/>
     </issue>
 
@@ -1129,7 +1117,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="116"
+            line="114"
             column="5"/>
     </issue>
 
@@ -1145,7 +1133,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="117"
+            line="115"
             column="5"/>
     </issue>
 
@@ -1161,7 +1149,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="118"
+            line="116"
             column="5"/>
     </issue>
 
@@ -1177,7 +1165,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="121"
+            line="119"
             column="5"/>
     </issue>
 
@@ -1193,7 +1181,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="122"
+            line="120"
             column="5"/>
     </issue>
 
@@ -1209,7 +1197,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="123"
+            line="121"
             column="5"/>
     </issue>
 
@@ -1225,7 +1213,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="124"
+            line="122"
             column="5"/>
     </issue>
 
@@ -1241,7 +1229,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="125"
+            line="123"
             column="5"/>
     </issue>
 
@@ -1257,7 +1245,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="128"
+            line="126"
             column="5"/>
     </issue>
 
@@ -1273,7 +1261,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="129"
+            line="127"
             column="5"/>
     </issue>
 
@@ -1289,7 +1277,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="130"
+            line="128"
             column="5"/>
     </issue>
 
@@ -1305,7 +1293,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="131"
+            line="129"
             column="5"/>
     </issue>
 
@@ -1321,7 +1309,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="132"
+            line="130"
             column="5"/>
     </issue>
 
@@ -1337,7 +1325,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="133"
+            line="131"
             column="5"/>
     </issue>
 
@@ -1353,7 +1341,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="139"
+            line="137"
             column="5"/>
     </issue>
 
@@ -1369,7 +1357,7 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="140"
+            line="138"
             column="5"/>
     </issue>
 
@@ -1385,7 +1373,39 @@
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
-            line="141"
+            line="139"
+            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;face_intro_outline&quot;>#ffdadce0&lt;/color>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="res/values/colors.xml"
+            line="148"
+            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;back_gesture_indicator&quot;>#4182ef&lt;/color>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="res/values/colors.xml"
+            line="150"
             column="5"/>
     </issue>
 
@@ -1433,7 +1453,7 @@
         errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/layout/crypt_keeper_emergency_button.xml"
-            line="36"
+            line="35"
             column="9"/>
     </issue>
 
@@ -1509,6 +1529,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:fillColor=&quot;@color/face_intro_outline&quot;"
+        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="res/drawable/face_enroll_introduction.xml"
+            line="25"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="HardCodedColor"
+        severity="Error"
+        message="Avoid using hardcoded color"
+        category="Correctness"
+        priority="4"
+        summary="Using hardcoded color"
+        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
         errorLine1="    android:background=&quot;#80000000&quot;"
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
@@ -2393,7 +2429,7 @@
         errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/layout/running_processes_header.xml"
-            line="146"
+            line="129"
             column="13"/>
     </issue>
 
@@ -2581,27 +2617,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;string name=&quot;sync_plug&quot; msgid=&quot;3905078969081888738&quot;>&quot;‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‏‏‎‎‎‏‏‎‎‎‏‏‎‏‎‎‎‎‎‏‎‏‎‎‎‎‏‏‏‏‎‎‎‏‏‏‏‏‏‏‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‎‏‎‎‏‏‎&quot;&lt;font fgcolor=&quot;#ffffffff&quot;>&quot;‎‏‎‎‏‏‏‎Welcome to Google sync!‎‏‎‎‏‏‎&quot;&lt;/font>&quot;‎‏‎‎‏‏‏‎ ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎A Google approach to syncing data to allow access to your contacts, appointments, and more from wherever you are.‎‏‎‎‏‎&quot;&lt;/string>"
-        errorLine2="                                                                                                                                                                        ~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="res/values-en-rXC/strings.xml"
-            line="2652"
-            column="169"/>
-    </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;string name=&quot;sync_plug&quot; msgid=&quot;3905078969081888738&quot;>&lt;font fgcolor=&quot;#ffffffff&quot;>&quot;Welcome to Google sync!&quot;&lt;/font>&quot; \nA Google approach to syncing data to allow access to your contacts, appointments and more from wherever you are.&quot;&lt;/string>"
+        errorLine1="    &lt;string name=&quot;sync_plug&quot; msgid=&quot;7956982719077985381&quot;>&lt;font fgcolor=&quot;#ffffffff&quot;>&quot;Welcome to Google sync!&quot;&lt;/font>&quot; \nA Google approach to syncing data to allow access to your contacts, appointments and more from wherever you are.&quot;&lt;/string>"
         errorLine2="                                                               ~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values-en-rAU/strings.xml"
-            line="2653"
+            line="2663"
             column="64"/>
     </issue>
 
@@ -2613,11 +2633,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;string name=&quot;sync_plug&quot; msgid=&quot;3905078969081888738&quot;>&lt;font fgcolor=&quot;#ffffffff&quot;>&quot;Welcome to Google sync!&quot;&lt;/font>&quot; \nA Google approach to syncing data to allow access to your contacts, appointments and more from wherever you are.&quot;&lt;/string>"
+        errorLine1="    &lt;string name=&quot;sync_plug&quot; msgid=&quot;7956982719077985381&quot;>&lt;font fgcolor=&quot;#ffffffff&quot;>&quot;Welcome to Google sync!&quot;&lt;/font>&quot; \nA Google approach to syncing data to allow access to your contacts, appointments and more from wherever you are.&quot;&lt;/string>"
         errorLine2="                                                               ~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values-en-rCA/strings.xml"
-            line="2653"
+            line="2663"
             column="64"/>
     </issue>
 
@@ -2629,11 +2649,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;string name=&quot;sync_plug&quot; msgid=&quot;3905078969081888738&quot;>&lt;font fgcolor=&quot;#ffffffff&quot;>&quot;Welcome to Google sync!&quot;&lt;/font>&quot; \nA Google approach to syncing data to allow access to your contacts, appointments and more from wherever you are.&quot;&lt;/string>"
+        errorLine1="    &lt;string name=&quot;sync_plug&quot; msgid=&quot;7956982719077985381&quot;>&lt;font fgcolor=&quot;#ffffffff&quot;>&quot;Welcome to Google sync!&quot;&lt;/font>&quot; \nA Google approach to syncing data to allow access to your contacts, appointments and more from wherever you are.&quot;&lt;/string>"
         errorLine2="                                                               ~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values-en-rGB/strings.xml"
-            line="2653"
+            line="2663"
             column="64"/>
     </issue>
 
@@ -2645,11 +2665,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;string name=&quot;sync_plug&quot; msgid=&quot;3905078969081888738&quot;>&lt;font fgcolor=&quot;#ffffffff&quot;>&quot;Welcome to Google sync!&quot;&lt;/font>&quot; \nA Google approach to syncing data to allow access to your contacts, appointments and more from wherever you are.&quot;&lt;/string>"
+        errorLine1="    &lt;string name=&quot;sync_plug&quot; msgid=&quot;7956982719077985381&quot;>&lt;font fgcolor=&quot;#ffffffff&quot;>&quot;Welcome to Google sync!&quot;&lt;/font>&quot; \nA Google approach to syncing data to allow access to your contacts, appointments and more from wherever you are.&quot;&lt;/string>"
         errorLine2="                                                               ~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values-en-rIN/strings.xml"
-            line="2653"
+            line="2663"
             column="64"/>
     </issue>
 
@@ -2661,11 +2681,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;string name=&quot;sync_plug&quot; msgid=&quot;7956982719077985381&quot;>&quot;‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‏‎‏‏‎‎‏‏‏‎‎‎‎‏‏‎‏‎‎‎‎‎‎‎‎‎‎‏‏‎‏‎‎‏‎‎‎‎‏‎‏‎‏‏‎‎‎‏‏‎‎‏‎‏‎‎‏‎‎‏‏‎&quot;&lt;font fgcolor=&quot;#ffffffff&quot;>&quot;‎‏‎‎‏‏‏‎Welcome to Google sync!‎‏‎‎‏‏‎&quot;&lt;/font>&quot;‎‏‎‎‏‏‏‎ ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎A Google approach to syncing data to allow access to your contacts, appointments, and more from wherever you are.‎‏‎‎‏‎&quot;&lt;/string>"
+        errorLine2="                                                                                                                                                                         ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="res/values-en-rXC/strings.xml"
+            line="2663"
+            column="170"/>
+    </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;string name=&quot;sync_plug&quot;>&lt;font fgcolor=&quot;#ffffffff&quot;>Welcome to Google sync!&lt;/font>"
         errorLine2="                                   ~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/strings.xml"
-            line="6186"
+            line="6183"
             column="36"/>
     </issue>
 
@@ -2697,7 +2733,7 @@
         errorLine2="                                           ^">
         <location
             file="res/values/styles.xml"
-            line="380"
+            line="378"
             column="44"/>
     </issue>
 
@@ -2713,7 +2749,7 @@
         errorLine2="                                           ^">
         <location
             file="res/values/styles.xml"
-            line="386"
+            line="384"
             column="44"/>
     </issue>
 
@@ -2729,7 +2765,7 @@
         errorLine2="                                           ^">
         <location
             file="res/values/styles.xml"
-            line="387"
+            line="385"
             column="44"/>
     </issue>
 
@@ -2745,7 +2781,7 @@
         errorLine2="                                 ^">
         <location
             file="res/values/styles.xml"
-            line="423"
+            line="421"
             column="34"/>
     </issue>
 
@@ -2761,7 +2797,7 @@
         errorLine2="                                       ^">
         <location
             file="res/values/themes.xml"
-            line="103"
+            line="106"
             column="40"/>
     </issue>
 
@@ -2777,7 +2813,7 @@
         errorLine2="                                       ^">
         <location
             file="res/values/themes.xml"
-            line="103"
+            line="106"
             column="40"/>
     </issue>
 
@@ -2793,7 +2829,7 @@
         errorLine2="                                            ^">
         <location
             file="res/values/themes.xml"
-            line="171"
+            line="176"
             column="45"/>
     </issue>
 
@@ -2809,7 +2845,7 @@
         errorLine2="                                                ^">
         <location
             file="res/values/themes.xml"
-            line="172"
+            line="177"
             column="49"/>
     </issue>
 
@@ -2825,7 +2861,7 @@
         errorLine2="                                            ^">
         <location
             file="res/values/themes.xml"
-            line="180"
+            line="185"
             column="45"/>
     </issue>
 
@@ -2841,7 +2877,7 @@
         errorLine2="                                                ^">
         <location
             file="res/values/themes.xml"
-            line="181"
+            line="186"
             column="49"/>
     </issue>
 
@@ -2857,7 +2893,7 @@
         errorLine2="                                         ^">
         <location
             file="res/values/themes.xml"
-            line="249"
+            line="254"
             column="42"/>
     </issue>
 
@@ -2905,7 +2941,7 @@
         errorLine2="                                       ^">
         <location
             file="res/values/themes_suw.xml"
-            line="67"
+            line="66"
             column="40"/>
     </issue>
 
@@ -2921,7 +2957,7 @@
         errorLine2="                                       ^">
         <location
             file="res/values/themes_suw.xml"
-            line="86"
+            line="85"
             column="40"/>
     </issue>
 
@@ -2937,7 +2973,7 @@
         errorLine2="                                       ^">
         <location
             file="res/values/themes_suw.xml"
-            line="105"
+            line="103"
             column="40"/>
     </issue>
 
@@ -2953,7 +2989,7 @@
         errorLine2="                                       ^">
         <location
             file="res/values/themes_suw.xml"
-            line="124"
+            line="127"
             column="40"/>
     </issue>
 
@@ -2969,7 +3005,7 @@
         errorLine2="                                          ^">
         <location
             file="res/values/themes_suw.xml"
-            line="186"
+            line="188"
             column="43"/>
     </issue>
 
@@ -2985,7 +3021,7 @@
         errorLine2="                                         ^">
         <location
             file="res/values/themes_suw.xml"
-            line="187"
+            line="189"
             column="42"/>
     </issue>
 
@@ -3001,7 +3037,7 @@
         errorLine2="                                            ^">
         <location
             file="res/values/themes_suw.xml"
-            line="188"
+            line="190"
             column="45"/>
     </issue>
 
@@ -3037,36 +3073,4 @@
             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;face_intro_outline&quot;>#ffdadce0&lt;/color> &lt;/color>"
-        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="res/values/colors.xml"
-            line="150"
-            column="40"/>
-    </issue>
-
-    <issue
-        id="HardCodedColor"
-        severity="Error"
-        message="Avoid using hardcoded color"
-        category="Correctness"
-        priority="4"
-        summary="Using hardcoded color"
-        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
-        errorLine1="                android:fillColor=&quot;@color/face_intro_outline&quot;"
-        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="res/drawable/face_enroll_introduction.xml"
-            line="25"
-            column="40"/>
-    </issue>
-
 </issues>
diff --git a/res/drawable/accessibility_magnification_full_screen.png b/res/drawable/accessibility_magnification_full_screen.png
new file mode 100644
index 0000000..7fcd17d
--- /dev/null
+++ b/res/drawable/accessibility_magnification_full_screen.png
Binary files differ
diff --git a/res/drawable/accessibility_magnification_window_screen.png b/res/drawable/accessibility_magnification_window_screen.png
new file mode 100644
index 0000000..db1f332
--- /dev/null
+++ b/res/drawable/accessibility_magnification_window_screen.png
Binary files differ
diff --git a/res/drawable/accessibility_shortcut_type_hardware.png b/res/drawable/accessibility_shortcut_type_hardware.png
new file mode 100644
index 0000000..141af83
--- /dev/null
+++ b/res/drawable/accessibility_shortcut_type_hardware.png
Binary files differ
diff --git a/res/drawable/accessibility_shortcut_type_software.png b/res/drawable/accessibility_shortcut_type_software.png
new file mode 100644
index 0000000..5b0611d
--- /dev/null
+++ b/res/drawable/accessibility_shortcut_type_software.png
Binary files differ
diff --git a/res/drawable/accessibility_shortcut_type_software_gesture.png b/res/drawable/accessibility_shortcut_type_software_gesture.png
new file mode 100644
index 0000000..a5df752
--- /dev/null
+++ b/res/drawable/accessibility_shortcut_type_software_gesture.png
Binary files differ
diff --git a/res/drawable/accessibility_shortcut_type_triple_tap.png b/res/drawable/accessibility_shortcut_type_triple_tap.png
new file mode 100644
index 0000000..5c6ce95
--- /dev/null
+++ b/res/drawable/accessibility_shortcut_type_triple_tap.png
Binary files differ
diff --git a/res/layout/accessibility_edit_magnification_mode.xml b/res/layout/accessibility_edit_magnification_mode.xml
new file mode 100644
index 0000000..e34f32e
--- /dev/null
+++ b/res/layout/accessibility_edit_magnification_mode.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2019 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License
+  -->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:scrollbarStyle="outsideOverlay">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        android:paddingEnd="24dp"
+        android:paddingStart="24dp">
+
+        <TextView
+            style="@style/AccessibilityDialogDescription"
+            android:text="@string/accessibility_magnification_area_settings_message" />
+
+        <include
+            android:id="@+id/magnify_full_screen"
+            layout="@layout/accessibility_edit_shortcut_component" />
+
+        <include
+            android:id="@+id/magnify_window_screen"
+            layout="@layout/accessibility_edit_shortcut_component" />
+
+    </LinearLayout>
+
+</ScrollView>
diff --git a/res/layout/accessibility_edit_shortcut_component.xml b/res/layout/accessibility_edit_shortcut_component.xml
index 2e1ad2d..52b8935 100644
--- a/res/layout/accessibility_edit_shortcut_component.xml
+++ b/res/layout/accessibility_edit_shortcut_component.xml
@@ -19,12 +19,14 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:orientation="vertical">
+    android:orientation="vertical"
+    android:paddingBottom="16dp">
 
     <CheckBox
         android:id="@+id/checkbox"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"/>
+        android:layout_height="wrap_content"
+        android:saveEnabled="false"/>
 
     <TextView
         android:id="@+id/summary"
diff --git a/res/layout/accessibility_shortcut_secondary_action.xml b/res/layout/accessibility_shortcut_secondary_action.xml
index 81d7bd5..9d59b2e 100644
--- a/res/layout/accessibility_shortcut_secondary_action.xml
+++ b/res/layout/accessibility_shortcut_secondary_action.xml
@@ -60,7 +60,7 @@
             android:paddingBottom="16dp">
 
             <TextView
-                android:id="@+android:id/title"
+                android:id="@android:id/title"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:singleLine="true"
@@ -68,7 +68,7 @@
                 android:ellipsize="marquee" />
 
             <TextView
-                android:id="@+android:id/summary"
+                android:id="@android:id/summary"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_below="@+android:id/title"
diff --git a/res/layout/back_gesture_indicator_container.xml b/res/layout/back_gesture_indicator_container.xml
new file mode 100644
index 0000000..17b9126
--- /dev/null
+++ b/res/layout/back_gesture_indicator_container.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2019 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:orientation="horizontal"
+              android:layout_width="match_parent"
+              android:layout_height="match_parent">
+
+    <ImageView
+        android:layout_width="@dimen/back_gesture_indicator_width"
+        android:layout_height="match_parent"
+        android:id="@+id/indicator_left">
+    </ImageView>
+
+    <Space
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        android:layout_weight="1" />
+
+    <ImageView
+        android:layout_width="@dimen/back_gesture_indicator_width"
+        android:layout_height="match_parent"
+        android:id="@+id/indicator_right">
+    </ImageView>
+
+</LinearLayout>
+
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index 6b7f842..e4a6b27 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -277,8 +277,8 @@
    <!-- Wi-Fi AP band settings.  Either Auto, 2.4GHz or 5GHz. -->
    <!-- Note that adding/removing/moving the items will need wifi settings code change. -->
     <string-array translatable="false" name="wifi_ap_band_config_full">
-        <item>0</item>
         <item>1</item>
+        <item>2</item>
     </string-array>
 
     <string-array translatable="false" name="wifi_ap_band_summary_full">
@@ -287,8 +287,8 @@
     </string-array>
 
     <string-array translatable="false" name="wifi_ap_band_dual_mode">
-        <item>0</item>
-        <item>-1</item>
+        <item>1</item>
+        <item>3</item>
     </string-array>
 
     <string-array translatable="false" name="wifi_ap_band_dual_mode_summary">
@@ -482,6 +482,11 @@
         <item>1xRTT</item>
         <item>IS95B</item>
         <item>IS95A</item>
+        <item>GSM</item>
+        <item>TD_SCDMA</item>
+        <item>IWLAN</item>
+        <item>LTE_CA</item>
+        <item>NR</item>
     </string-array>
 
     <string-array translatable="false" name="bearer_values">
@@ -517,6 +522,16 @@
         <item>5</item>
         <!-- Do not translate. -->
         <item>4</item>
+        <!-- Do not translate. -->
+        <item>16</item>
+        <!-- Do not translate. -->
+        <item>17</item>
+        <!-- Do not translate. -->
+        <item>18</item>
+        <!-- Do not translate. -->
+        <item>19</item>
+        <!-- Do not translate. -->
+        <item>20</item>
     </string-array>
 
     <!-- MVNO Info used in APN editor -->
@@ -1014,8 +1029,25 @@
         <item>\?</item>
     </string-array>
 
+    <!-- Summary for magnification adjustment modes for accessibility -->
+    <string-array name="magnification_mode_summaries" translatable="false">
+        <item>@string/accessibility_magnification_area_settings_full_screen_summary</item>
+        <item>@string/accessibility_magnification_area_settings_window_screen_summary</item>
+        <item>@string/accessibility_magnification_area_settings_all_summary</item>
+    </string-array>
+
+    <!-- Values for magnification adjustment modes for accessibility -->
+    <integer-array name="magnification_mode_values" translatable="false">
+        <!-- Full screen -->
+        <item>1</item>
+        <!-- Window screen -->
+        <item>2</item>
+        <!-- Full screen and window screen. -->
+        <item>3</item>
+    </integer-array>
+
     <!-- Summary for color space adjustment modes for accessibility -->
-    <string-array name="daltonizer_mode_summary" translatable="false">
+    <string-array name="daltonizer_mode_summaries" translatable="false">
         <item>@string/daltonizer_mode_deuteranomaly</item>
         <item>@string/daltonizer_mode_protanomaly</item>
         <item>@string/daltonizer_mode_tritanomaly</item>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index a1cb8fc..3fd77e8 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -146,4 +146,6 @@
     <color name="dialog_background">@*android:color/background_device_default_light</color>
 
     <color name="face_intro_outline">#ffdadce0</color>
+
+    <color name="back_gesture_indicator">#4182ef</color>
 </resources>
\ No newline at end of file
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 41c059c..aca64fb 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -216,8 +216,8 @@
     <dimen name="fingerprint_finish_max_size">288dp</dimen>
 
     <!-- Face -->
-    <dimen name="face_preview_translate_y">0dp</dimen>
-    <dimen name="face_preview_translate_x">0dp</dimen>
+    <item name="face_preview_translate_y" format="float" type="dimen">0</item>
+    <item name="face_preview_translate_x" format="float" type="dimen">0</item>
     <item name="face_preview_scale" format="float" type="dimen">1.0</item>
 
     <!-- Confirm device credentials -->
@@ -403,6 +403,8 @@
     <!-- System navigation settings illustration height -->
     <dimen name="system_navigation_illustration_height">320dp</dimen>
 
+    <dimen name="back_gesture_indicator_width">60dp</dimen>
+
     <!-- Header title size of advanced bluetooth device -->
     <dimen name="advanced_bluetooth_header_title_text_size">16sp</dimen>
 
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 206c704..86708a4 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1776,6 +1776,11 @@
     <!-- Debugging developer settings: Enable ART verifier for Debuggable Apps [CHAR LIMIT=NONE] -->
     <string name="art_verifier_for_debuggable_summary">Allow ART to verify bytecode for debuggable apps</string>
 
+    <!-- Debugging developer settings: show refresh rate? [CHAR LIMIT=25] -->
+    <string name="show_refresh_rate">Show refresh rate</string>
+    <!-- Debugging developer settings: show refresh rate summary [CHAR LIMIT=50] -->
+    <string name="show_refresh_rate_summary">Show the current display refresh rate</string>
+
     <!-- NFC settings -->
     <!-- Used in the 1st-level settings screen to turn on NFC -->
     <string name="nfc_quick_toggle_title">NFC</string>
@@ -4750,6 +4755,26 @@
     <string name="accessibility_captioning_title">Caption preferences</string>
     <!-- Title for the accessibility preference screen to enable screen magnification. [CHAR LIMIT=35] -->
     <string name="accessibility_screen_magnification_title">Magnification</string>
+    <!-- Title for the accessibility preference screen to edit magnification area. [CHAR LIMIT=35] -->
+    <string name="accessibility_magnification_mode_title">Magnification area</string>
+    <!-- Message for the accessibility preference screen to edit magnification area dialog. [CHAR LIMIT=none] -->
+    <string name="accessibility_magnification_area_settings_message">Choose the magnification area(s) you want to use when magnifying the screen</string>
+    <!-- Summary for the accessibility preference screen to edit full screen. [CHAR LIMIT=none] -->
+    <string name="accessibility_magnification_area_settings_full_screen_summary">Full screen</string>
+    <!-- Summary for the accessibility preference screen to edit window screen. [CHAR LIMIT=none] -->
+    <string name="accessibility_magnification_area_settings_window_screen_summary">Part of screen</string>
+    <!-- Summary for the accessibility preference screen to edit entire screen. [CHAR LIMIT=none] -->
+    <string name="accessibility_magnification_area_settings_all_summary">Full screen &amp; part of screen</string>
+    <!-- Message for the accessibility preference screen to edit entire screen. [CHAR LIMIT=none] -->
+    <string name="accessibility_magnification_area_settings_full_screen">Magnify entire screen</string>
+    <!-- Message for the accessibility preference screen to edit part of screen. [CHAR LIMIT=none] -->
+    <string name="accessibility_magnification_area_settings_window_screen">Magnify part of screen</string>
+    <!-- Title for the accessibility preference screen to show move controller. [CHAR LIMIT=35] -->
+    <string name="accessibility_magnification_window_control_switch_title">Show move controller</string>
+    <!-- Summary for the accessibility preference screen to show move controller. [CHAR LIMIT=none] -->
+    <string name="accessibility_magnification_window_control_switch_summary">Show a joystick-like controller to move the magnification area</string>
+    <!-- Title for the accessibility preference screen to enable screen magnification settings. [CHAR LIMIT=35] -->
+    <string name="accessibility_magnification_service_settings_title">Magnify settings</string>
     <!-- Title for the accessibility preference screen to enable triple-tap gesture screen magnification. [CHAR LIMIT=35] -->
     <string name="accessibility_screen_magnification_gestures_title">Magnify with triple-tap</string>
     <!-- Title for the accessibility preference screen to enable navigation bar screen magnification. [CHAR LIMIT=35] -->
@@ -4784,6 +4809,16 @@
     <string name="accessibility_tutorial_dialog_message_gesture_settings_with_talkback">To turn an accessibility service on or off, swipe up from the bottom of the screen with three fingers.\n\nTo switch between services, swipe up with three fingers and hold.</string>
     <!-- Button for the Accessibility tutorial dialog to dismiss the dialog when user clicks it. [CHAR LIMIT=10] -->
     <string name="accessibility_tutorial_dialog_button">Got it</string>
+    <!-- Title for accessibility shortcut preference for accessibility apps. [CHAR LIMIT=40] -->
+    <string name="accessibility_shortcut_title">Use shortcut to open</string>
+    <!-- Title for accessibility shortcut preference for magnification. [CHAR LIMIT=40] -->
+    <string name="accessibility_magnification_shortcut_title">Use shortcut to magnify</string>
+    <!-- Title for Accessibility edit shortcut dialog. [CHAR LIMIT=40] -->
+    <string name="accessibility_shortcut_edit_dialog_title">Shortcut to open <xliff:g id="service" example="Select to Speak">%1$s</xliff:g></string>
+    <!-- Title for Accessibility edit shortcut dialog in Magnify. [CHAR LIMIT=40] -->
+    <string name="accessibility_shortcut_edit_dialog_title_magnification">Shortcut to magnify</string>
+    <!-- Title for Accessibility edit shortcut dialog in Color correction. [CHAR LIMIT=40] -->
+    <string name="accessibility_shortcut_edit_dialog_title_daltonizer">Shortcut to open Color correction</string>
     <!-- Title for software shortcut in Accessibility edit shortcut dialog. [CHAR LIMIT=NONE] -->
     <string name="accessibility_shortcut_edit_dialog_title_software">Accessibility Button</string>
     <!-- Title for software shortcut in gesture mode in Accessibility edit shortcut dialog. [CHAR LIMIT=NONE] -->
@@ -10237,6 +10272,9 @@
     <!-- Title for the screen to show all the gesture navigation settings [CHAR LIMIT=80] -->
     <string name="gesture_settings_activity_title">Gesture Settings</string>
 
+    <!-- Keywords for the gesture navigation settings. [CHAR LIMIT=NONE] -->
+    <string name="keywords_gesture_navigation_settings">gesture navigation, back sensitivity, back gesture</string>
+
     <!-- Preference and settings suggestion title text for ambient display double tap (phone) [CHAR LIMIT=60]-->
     <string name="ambient_display_title" product="default">Double-tap to check phone</string>
     <!-- Preference and settings suggestion title text for ambient display double tap (tablet) [CHAR LIMIT=60]-->
@@ -11386,14 +11424,14 @@
     <!-- Developer Settings: Footer text for bug report handler picker [CHAR LIMIT=NONE] -->
     <string name="bug_report_handler_picker_footer_text">Determines which app handles the Bug Report shortcut on your device.</string>
 
-    <!-- Label of personal profile app for current setting [CHAR LIMIT=NONE] -->
-    <string name="personal_profile_app">(Personal)</string>
+    <!-- Subtext of personal profile app for current setting [CHAR LIMIT=NONE] -->
+    <string name="personal_profile_app_subtext">Personal</string>
 
-    <!-- Label of work profile app for current setting [CHAR LIMIT=NONE] -->
-    <string name="work_profile_app">(Work)</string>
+    <!-- Subtext of work profile app for current setting [CHAR LIMIT=NONE] -->
+    <string name="work_profile_app_subtext">Work</string>
 
-    <!-- Title of Shell app for current setting [CHAR LIMIT=NONE] -->
-    <string name="shell_app">Android System (Shell)</string>
+    <!-- Subtext of system default app for current setting [CHAR LIMIT=NONE] -->
+    <string name="system_default_app_subtext">System default</string>
 
     <!-- Developer settings: text for the bug report handler selection toast shown if an invalid bug report handler was chosen. [CHAR LIMIT=NONE] -->
     <string name="select_invalid_bug_report_handler_toast_text">This choice is no longer valid. Try again.</string>
diff --git a/res/xml/accessibility_magnification_service_settings.xml b/res/xml/accessibility_magnification_service_settings.xml
new file mode 100644
index 0000000..d67fc66
--- /dev/null
+++ b/res/xml/accessibility_magnification_service_settings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2019 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:settings="http://schemas.android.com/apk/res-auto"
+    android:key="magnification_mode_screen"
+    android:persistent="false"
+    android:title="@string/accessibility_magnification_service_settings_title">
+
+    <Preference
+        android:key="magnification_mode"
+        android:persistent="false"
+        android:title="@string/accessibility_magnification_mode_title"
+        settings:controller="com.android.settings.accessibility.MagnificationModePreferenceController" />
+
+    <SwitchPreference
+        android:key="magnification_window_control_switch"
+        android:persistent="false"
+        android:summary="@string/accessibility_magnification_window_control_switch_summary"
+        android:title="@string/accessibility_magnification_window_control_switch_title"
+        settings:controller="com.android.settings.accessibility.MagnificationWindowControlPreferenceController" />
+</PreferenceScreen>
diff --git a/res/xml/development_settings.xml b/res/xml/development_settings.xml
index 42ce465..9a4add4 100644
--- a/res/xml/development_settings.xml
+++ b/res/xml/development_settings.xml
@@ -230,6 +230,11 @@
             android:fragment="com.android.settings.development.compat.PlatformCompatDashboard"
             />
 
+        <SwitchPreference
+            android:key="show_refresh_rate"
+            android:title="@string/show_refresh_rate"
+            android:summary="@string/show_refresh_rate_summary" />
+
     </PreferenceCategory>
 
     <PreferenceCategory
diff --git a/res/xml/gesture_navigation_settings.xml b/res/xml/gesture_navigation_settings.xml
new file mode 100644
index 0000000..2751f88
--- /dev/null
+++ b/res/xml/gesture_navigation_settings.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  ~ Copyright (C) 2019 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<PreferenceScreen
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:settings="http://schemas.android.com/apk/res-auto"
+    android:key="gesture_navigation_settings_page"
+    android:title="@string/gesture_settings_activity_title"
+    settings:keywords="@string/keywords_gesture_navigation_settings">
+
+    <PreferenceCategory
+        android:key="back_sensitivity_category"
+        android:persistent="false"
+        android:title="@string/back_sensitivity_dialog_title">
+
+        <com.android.settings.gestures.GestureNavigationSeekBarPreference
+            android:key="gesture_left_back_sensitivity"
+            android:title="@string/left_edge"
+            android:max="3"
+            android:selectable="true"/>
+
+        <com.android.settings.gestures.GestureNavigationSeekBarPreference
+            android:key="gesture_right_back_sensitivity"
+            android:title="@string/right_edge"
+            android:max="3"
+            android:selectable="true"/>
+    </PreferenceCategory>
+
+    <com.android.settingslib.widget.FooterPreference
+        android:key="gesture_navigation_settings_footer"
+        android:title="@string/back_sensitivity_dialog_message"
+        android:selectable="false"
+        settings:searchable="false"
+        settings:allowDividerAbove="true"/>
+</PreferenceScreen>
+
diff --git a/res/xml/security_settings_face.xml b/res/xml/security_settings_face.xml
index b7d444b..cd05512 100644
--- a/res/xml/security_settings_face.xml
+++ b/res/xml/security_settings_face.xml
@@ -64,7 +64,11 @@
             android:summary="@string/security_settings_face_settings_require_confirmation_details"
             app:keywords="@string/keywords_face_unlock"
             app:controller="com.android.settings.biometrics.face.FaceSettingsConfirmPreferenceController"/>
+    </PreferenceCategory>
 
+    <PreferenceCategory
+        android:key="security_settings_face_button_category"
+        android:title="@string/security_settings_face_preference_title">
         <com.android.settingslib.widget.LayoutPreference
             android:key="security_settings_face_delete_faces_container"
             android:selectable="false"
diff --git a/src/com/android/settings/ResetNetworkConfirm.java b/src/com/android/settings/ResetNetworkConfirm.java
index c50e200..ffc0412 100644
--- a/src/com/android/settings/ResetNetworkConfirm.java
+++ b/src/com/android/settings/ResetNetworkConfirm.java
@@ -105,9 +105,10 @@
             p2pFactoryReset(mContext);
 
             TelephonyManager telephonyManager = (TelephonyManager)
-                    mContext.getSystemService(Context.TELEPHONY_SERVICE);
+                    mContext.getSystemService(TelephonyManager.class)
+                            .createForSubscriptionId(mSubId);
             if (telephonyManager != null) {
-                telephonyManager.factoryReset(mSubId);
+                telephonyManager.resetSettings();
             }
 
             NetworkPolicyManager policyManager = (NetworkPolicyManager)
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index 46992ef..50caf32 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -131,6 +131,7 @@
     public static class PhotosStorageActivity extends SettingsActivity {
         /* empty */
     }
+    public static class GestureNavigationSettingsActivity extends SettingsActivity { /* empty */ }
 
     public static class ApnSettingsActivity extends SettingsActivity { /* empty */ }
     public static class WifiCallingSettingsActivity extends SettingsActivity { /* empty */ }
diff --git a/src/com/android/settings/accessibility/AccessibilityEditDialogUtils.java b/src/com/android/settings/accessibility/AccessibilityEditDialogUtils.java
index 62d6d34..1d87477 100644
--- a/src/com/android/settings/accessibility/AccessibilityEditDialogUtils.java
+++ b/src/com/android/settings/accessibility/AccessibilityEditDialogUtils.java
@@ -24,6 +24,7 @@
 import android.graphics.drawable.Drawable;
 import android.text.Spannable;
 import android.text.SpannableString;
+import android.text.TextUtils;
 import android.text.style.ImageSpan;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -53,13 +54,15 @@
      */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({
-            DialogType.EDIT_SHORTCUT_GENERIC,
-            DialogType.EDIT_SHORTCUT_MAGNIFICATION,
+         DialogType.EDIT_SHORTCUT_GENERIC,
+         DialogType.EDIT_SHORTCUT_MAGNIFICATION,
+         DialogType.EDIT_MAGNIFICATION_MODE,
     })
 
     private @interface DialogType {
         int EDIT_SHORTCUT_GENERIC = 0;
         int EDIT_SHORTCUT_MAGNIFICATION = 1;
+        int EDIT_MAGNIFICATION_MODE = 2;
     }
 
     /**
@@ -96,6 +99,23 @@
         return alertDialog;
     }
 
+    /**
+     * Method to show the magnification mode dialog in Magnification.
+     *
+     * @param context A valid context
+     * @param dialogTitle The title of magnify mode dialog
+     * @param listener The listener to determine the action of magnify mode dialog
+     * @return A magnification mode dialog in Magnification
+     */
+    public static AlertDialog showMagnificationModeDialog(Context context,
+            CharSequence dialogTitle, DialogInterface.OnClickListener listener) {
+        final AlertDialog alertDialog = createDialog(context,
+                DialogType.EDIT_MAGNIFICATION_MODE, dialogTitle, listener);
+        alertDialog.show();
+
+        return alertDialog;
+    }
+
     private static AlertDialog createDialog(Context context, int dialogType,
             CharSequence dialogTitle, DialogInterface.OnClickListener listener) {
 
@@ -138,6 +158,12 @@
                 initMagnifyShortcut(context, contentView);
                 initAdvancedWidget(contentView);
                 break;
+            case DialogType.EDIT_MAGNIFICATION_MODE:
+                contentView = inflater.inflate(
+                        R.layout.accessibility_edit_magnification_mode, null);
+                initMagnifyFullScreen(context, contentView);
+                initMagnifyWindowScreen(context, contentView);
+                break;
             default:
                 throw new IllegalArgumentException();
         }
@@ -145,12 +171,37 @@
         return contentView;
     }
 
+    private static void initMagnifyFullScreen(Context context, View view) {
+        final View dialogView = view.findViewById(R.id.magnify_full_screen);
+        final String title = context.getString(
+                R.string.accessibility_magnification_area_settings_full_screen);
+        // TODO(b/146019459): Use vector drawable instead of temporal png file to avoid distorted.
+        setupShortcutWidget(dialogView, title, R.drawable.accessibility_magnification_full_screen);
+    }
+
+    private static void initMagnifyWindowScreen(Context context, View view) {
+        final View dialogView = view.findViewById(R.id.magnify_window_screen);
+        final String title = context.getString(
+                R.string.accessibility_magnification_area_settings_window_screen);
+        // TODO(b/146019459): Use vector drawable instead of temporal png file to avoid distorted.
+        setupShortcutWidget(dialogView, title,
+                R.drawable.accessibility_magnification_window_screen);
+    }
+
+    private static void setupShortcutWidget(View view, CharSequence titleText, int imageResId) {
+        setupShortcutWidget(view, titleText, null, imageResId);
+    }
+
     private static void setupShortcutWidget(View view, CharSequence titleText,
             CharSequence summaryText, int imageResId) {
         final CheckBox checkBox = view.findViewById(R.id.checkbox);
         checkBox.setText(titleText);
         final TextView summary = view.findViewById(R.id.summary);
-        summary.setText(summaryText);
+        if (TextUtils.isEmpty(summaryText)) {
+            summary.setVisibility(View.GONE);
+        } else {
+            summary.setText(summaryText);
+        }
         final ImageView image = view.findViewById(R.id.image);
         image.setImageResource(imageResId);
     }
@@ -170,7 +221,8 @@
         final String summary = context.getString(
                 R.string.accessibility_shortcut_edit_dialog_summary_hardware);
         setupShortcutWidget(dialogView, title, summary,
-                R.drawable.illustration_accessibility_button);
+                R.drawable.accessibility_shortcut_type_hardware);
+        // TODO(b/142531156): Use vector drawable instead of temporal png file to avoid distorted.
     }
 
     private static void initMagnifyShortcut(Context context, View view) {
@@ -180,7 +232,8 @@
         final String summary = context.getString(
                 R.string.accessibility_shortcut_edit_dialog_summary_triple_tap);
         setupShortcutWidget(dialogView, title, summary,
-                R.drawable.illustration_accessibility_button);
+                R.drawable.accessibility_shortcut_type_triple_tap);
+        // TODO(b/142531156): Use vector drawable instead of temporal png file to avoid distorted.
     }
 
     private static void initAdvancedWidget(View view) {
@@ -213,8 +266,9 @@
 
     private static int retrieveImageResId(Context context) {
         return isGestureNavigateEnabled(context)
-                ? R.drawable.illustration_accessibility_button
-                : R.drawable.illustration_accessibility_button;
+                ? R.drawable.accessibility_shortcut_type_software_gesture
+                : R.drawable.accessibility_shortcut_type_software;
+        // TODO(b/142531156): Use vector drawable instead of temporal png file to avoid distorted.
     }
 
     private static SpannableString getSummaryStringWithIcon(Context context, int lineHeight) {
diff --git a/src/com/android/settings/accessibility/DaltonizerPreferenceController.java b/src/com/android/settings/accessibility/DaltonizerPreferenceController.java
index e026313..2922b76 100644
--- a/src/com/android/settings/accessibility/DaltonizerPreferenceController.java
+++ b/src/com/android/settings/accessibility/DaltonizerPreferenceController.java
@@ -42,15 +42,15 @@
 
     @Override
     public CharSequence getSummary() {
-        final String[] daltonizerSummarys = mContext.getResources().getStringArray(
-                R.array.daltonizer_mode_summary);
+        final String[] daltonizerSummaries = mContext.getResources().getStringArray(
+                R.array.daltonizer_mode_summaries);
         final int[] daltonizerValues = mContext.getResources().getIntArray(
                 R.array.daltonizer_type_values);
         final int timeoutValue =
                 DaltonizerRadioButtonPreferenceController.getSecureAccessibilityDaltonizerValue(
                         mContext.getContentResolver(), DALTONIZER_TYPE);
         final int idx = Ints.indexOf(daltonizerValues, timeoutValue);
-        final String serviceSummary = daltonizerSummarys[idx == -1 ? 0 : idx];
+        final String serviceSummary = daltonizerSummaries[idx == -1 ? 0 : idx];
 
         final CharSequence serviceState = AccessibilityUtil.getSummary(mContext,
                 DALTONIZER_ENABLED);
diff --git a/src/com/android/settings/accessibility/MagnificationModePreferenceController.java b/src/com/android/settings/accessibility/MagnificationModePreferenceController.java
new file mode 100644
index 0000000..b45ad88
--- /dev/null
+++ b/src/com/android/settings/accessibility/MagnificationModePreferenceController.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.accessibility;
+
+import android.content.Context;
+
+import com.android.settings.core.BasePreferenceController;
+
+/** Controller that shows the magnification area mode summary. */
+public class MagnificationModePreferenceController extends BasePreferenceController {
+
+    public MagnificationModePreferenceController(Context context, String preferenceKey) {
+        super(context, preferenceKey);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return AVAILABLE;
+    }
+
+
+    @Override
+    public CharSequence getSummary() {
+        return MagnificationSettingsFragment.getMagnificationCapabilitiesSummary(
+                mContext);
+    }
+}
diff --git a/src/com/android/settings/accessibility/MagnificationSettingsFragment.java b/src/com/android/settings/accessibility/MagnificationSettingsFragment.java
new file mode 100644
index 0000000..0e766b4
--- /dev/null
+++ b/src/com/android/settings/accessibility/MagnificationSettingsFragment.java
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.accessibility;
+
+import android.app.Dialog;
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.view.View;
+import android.widget.CheckBox;
+
+import androidx.annotation.IntDef;
+import androidx.appcompat.app.AlertDialog;
+import androidx.preference.Preference;
+
+import com.android.settings.R;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settingslib.search.SearchIndexable;
+
+import com.google.common.primitives.Ints;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/** Settings page for magnification. */
+@SearchIndexable
+public class MagnificationSettingsFragment extends DashboardFragment {
+
+    private static final String TAG = "MagnificationSettingsFragment";
+    private static final String PREF_KEY_MODE = "magnification_mode";
+    // TODO(b/146019459): Use magnification_capability.
+    private static final String KEY_CAPABILITY = Settings.System.MASTER_MONO;
+    private static final int DIALOG_MAGNIFICATION_CAPABILITY = 1;
+    private static final String EXTRA_CAPABILITY = "capability";
+    private Preference mModePreference;
+    private int mCapabilities = MagnifyMode.NONE;
+    private CheckBox mMagnifyFullScreenCheckBox;
+    private CheckBox mMagnifyWindowCheckBox;
+
+    static String getMagnificationCapabilitiesSummary(Context context) {
+        final String[] magnificationModeSummaries = context.getResources().getStringArray(
+                R.array.magnification_mode_summaries);
+        final int[] magnificationModeValues = context.getResources().getIntArray(
+                R.array.magnification_mode_values);
+        final int capabilities = MagnificationSettingsFragment.getMagnificationCapabilities(
+                context);
+
+        final int idx = Ints.indexOf(magnificationModeValues, capabilities);
+        return magnificationModeSummaries[idx == -1 ? 0 : idx];
+    }
+
+    private static int getMagnificationCapabilities(Context context) {
+        return getSecureIntValue(context, KEY_CAPABILITY, MagnifyMode.FULLSCREEN);
+    }
+
+    private static int getSecureIntValue(Context context, String key, int defaultValue) {
+        return Settings.Secure.getIntForUser(
+                context.getContentResolver(),
+                key, defaultValue, context.getContentResolver().getUserId());
+    }
+
+    @Override
+    public int getMetricsCategory() {
+        return SettingsEnums.ACCESSIBILITY_MAGNIFICATION_SETTINGS;
+    }
+
+    @Override
+    public void onSaveInstanceState(Bundle outState) {
+        outState.putInt(EXTRA_CAPABILITY, mCapabilities);
+        super.onSaveInstanceState(outState);
+    }
+
+    @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+        if (savedInstanceState != null) {
+            mCapabilities = savedInstanceState.getInt(EXTRA_CAPABILITY, MagnifyMode.NONE);
+        }
+        if (mCapabilities == MagnifyMode.NONE) {
+            mCapabilities = getMagnificationCapabilities(getPrefContext());
+        }
+    }
+
+    @Override
+    public int getDialogMetricsCategory(int dialogId) {
+        switch (dialogId) {
+            case DIALOG_MAGNIFICATION_CAPABILITY:
+                return SettingsEnums.DIALOG_MAGNIFICATION_CAPABILITY;
+            default:
+                return 0;
+        }
+    }
+
+    @Override
+    protected String getLogTag() {
+        return TAG;
+    }
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        mModePreference = findPreference(PREF_KEY_MODE);
+        mModePreference.setOnPreferenceClickListener(preference -> {
+            mCapabilities = getMagnificationCapabilities(getPrefContext());
+            showDialog(DIALOG_MAGNIFICATION_CAPABILITY);
+            return true;
+        });
+    }
+
+    @Override
+    protected int getPreferenceScreenResId() {
+        return R.xml.accessibility_magnification_service_settings;
+    }
+
+    @Override
+    public Dialog onCreateDialog(int dialogId) {
+        if (dialogId == DIALOG_MAGNIFICATION_CAPABILITY) {
+            final String title = getPrefContext().getString(
+                    R.string.accessibility_magnification_mode_title);
+            AlertDialog alertDialog = AccessibilityEditDialogUtils
+                    .showMagnificationModeDialog(getPrefContext(), title,
+                            this::callOnAlertDialogCheckboxClicked);
+            initializeDialogCheckBox(alertDialog);
+            return alertDialog;
+        }
+        throw new IllegalArgumentException("Unsupported dialogId " + dialogId);
+    }
+
+    private void callOnAlertDialogCheckboxClicked(DialogInterface dialog, int which) {
+        updateCapabilities(true);
+        mModePreference.setSummary(
+                getMagnificationCapabilitiesSummary(getPrefContext()));
+    }
+
+    private void initializeDialogCheckBox(AlertDialog dialog) {
+        final View dialogFullScreenView = dialog.findViewById(R.id.magnify_full_screen);
+        mMagnifyFullScreenCheckBox = dialogFullScreenView.findViewById(R.id.checkbox);
+
+        final View dialogWidowView = dialog.findViewById(R.id.magnify_window_screen);
+        mMagnifyWindowCheckBox = dialogWidowView.findViewById(R.id.checkbox);
+
+        updateAlertDialogCheckState();
+        updateAlertDialogEnableState();
+    }
+
+    private void updateAlertDialogCheckState() {
+        updateCheckStatus(mMagnifyWindowCheckBox, MagnifyMode.WINDOW);
+        updateCheckStatus(mMagnifyFullScreenCheckBox, MagnifyMode.FULLSCREEN);
+
+    }
+
+    private void updateCheckStatus(CheckBox checkBox, int mode) {
+        checkBox.setChecked((mode & mCapabilities) != 0);
+        checkBox.setOnClickListener(v -> {
+            updateCapabilities(false);
+            updateAlertDialogEnableState();
+        });
+    }
+
+    private void updateAlertDialogEnableState() {
+        if (mCapabilities != MagnifyMode.ALL) {
+            disableEnabledMagnificationModePreference();
+        } else {
+            enableAllPreference();
+        }
+    }
+
+    private void enableAllPreference() {
+        mMagnifyFullScreenCheckBox.setEnabled(true);
+        mMagnifyWindowCheckBox.setEnabled(true);
+    }
+
+    private void disableEnabledMagnificationModePreference() {
+        if (!mMagnifyFullScreenCheckBox.isChecked()) {
+            mMagnifyWindowCheckBox.setEnabled(false);
+        } else if (!mMagnifyWindowCheckBox.isChecked()) {
+            mMagnifyFullScreenCheckBox.setEnabled(false);
+        }
+    }
+
+    private void updateCapabilities(boolean saveToDB) {
+        int capabilities = 0;
+        capabilities |=
+                mMagnifyFullScreenCheckBox.isChecked() ? MagnifyMode.FULLSCREEN : 0;
+        capabilities |= mMagnifyWindowCheckBox.isChecked() ? MagnifyMode.WINDOW : 0;
+        mCapabilities = capabilities;
+        if (saveToDB) {
+            setMagnificationCapabilities(capabilities);
+        }
+    }
+
+    private void setSecureIntValue(String key, int value) {
+        Settings.Secure.putIntForUser(getPrefContext().getContentResolver(),
+                key, value, getPrefContext().getContentResolver().getUserId());
+    }
+
+    private void setMagnificationCapabilities(int capabilities) {
+        setSecureIntValue(KEY_CAPABILITY, capabilities);
+    }
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({
+            MagnifyMode.NONE,
+            MagnifyMode.FULLSCREEN,
+            MagnifyMode.WINDOW,
+            MagnifyMode.ALL,
+    })
+    private @interface MagnifyMode {
+        int NONE = 0;
+        int FULLSCREEN = 1;
+        int WINDOW = 2;
+        int ALL = 3;
+    }
+
+    public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+            new BaseSearchIndexProvider(R.xml.accessibility_magnification_service_settings);
+}
diff --git a/src/com/android/settings/accessibility/MagnificationWindowControlPreferenceController.java b/src/com/android/settings/accessibility/MagnificationWindowControlPreferenceController.java
new file mode 100644
index 0000000..4badc3f
--- /dev/null
+++ b/src/com/android/settings/accessibility/MagnificationWindowControlPreferenceController.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.accessibility;
+
+import android.content.Context;
+import android.os.UserHandle;
+import android.provider.Settings;
+
+import com.android.settings.core.TogglePreferenceController;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/** Controller that shows and updates the magnification window control switch. */
+public class MagnificationWindowControlPreferenceController extends TogglePreferenceController {
+
+    // TODO(b/146019459): Use magnification_window_control_enabled.
+    private static final String KEY_CONTROL = Settings.System.MASTER_MONO;
+
+    public MagnificationWindowControlPreferenceController(Context context, String preferenceKey) {
+        super(context, preferenceKey);
+    }
+
+    @Override
+    public boolean isChecked() {
+        return Settings.System.getIntForUser(mContext.getContentResolver(),
+                KEY_CONTROL, State.OFF, UserHandle.USER_CURRENT) == State.ON;
+    }
+
+    @Override
+    public boolean setChecked(boolean isChecked) {
+        return Settings.System.putIntForUser(mContext.getContentResolver(),
+                KEY_CONTROL, isChecked ? State.ON : State.OFF, UserHandle.USER_CURRENT);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return AVAILABLE;
+    }
+
+    @Retention(RetentionPolicy.SOURCE)
+    private @interface State {
+        int OFF = 0;
+        int ON = 1;
+    }
+}
diff --git a/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java b/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java
index ea293b7..e54446f 100644
--- a/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java
@@ -37,10 +37,15 @@
 import android.os.storage.StorageManager;
 import android.provider.Settings;
 import android.text.TextUtils;
+import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.View;
+import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityManager;
+import android.widget.CheckBox;
+
+import androidx.preference.PreferenceScreen;
 
 import com.android.internal.widget.LockPatternUtils;
 import com.android.settings.R;
@@ -57,11 +62,33 @@
     private static final int DIALOG_ID_ENABLE_WARNING = 1;
     private static final int DIALOG_ID_DISABLE_WARNING = 2;
     private static final int DIALOG_ID_LAUNCH_ACCESSIBILITY_TUTORIAL = 3;
+    private static final int DIALOG_ID_EDIT_SHORTCUT = 4;
 
     public static final int ACTIVITY_REQUEST_CONFIRM_CREDENTIAL_FOR_WEAKER_ENCRYPTION = 1;
 
+    private CharSequence mDialogTitle;
+
     private LockPatternUtils mLockPatternUtils;
 
+    private final DialogInterface.OnClickListener mDialogListener =
+            (DialogInterface dialog, int id) -> {
+                if (id == DialogInterface.BUTTON_POSITIVE) {
+                    // TODO(b/142531156): Save the shortcut type preference.
+                }
+            };
+
+    private final View.OnClickListener mSettingButtonListener = (View view) -> showDialog(
+            DIALOG_ID_EDIT_SHORTCUT);
+
+    private final View.OnClickListener mCheckBoxListener = (View view) -> {
+        CheckBox checkBox = (CheckBox) view;
+        if (checkBox.isChecked()) {
+            // TODO(b/142530063): Enable shortcut when checkbox is checked.
+        } else {
+            // TODO(b/142530063): Disable shortcut when checkbox is unchecked.
+        }
+    };
+
     private final SettingsContentObserver mSettingsContentObserver =
             new SettingsContentObserver(new Handler()) {
                 @Override
@@ -127,6 +154,13 @@
     }
 
     @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        initShortcutPreference();
+        return super.onCreateView(inflater, container, savedInstanceState);
+    }
+
+    @Override
     public void onResume() {
         mSettingsContentObserver.register(getContentResolver());
         updateSwitchBarToggleSwitch();
@@ -195,6 +229,13 @@
                 }
                 break;
             }
+            case DIALOG_ID_EDIT_SHORTCUT: {
+                final CharSequence dialogTitle = getActivity().getString(
+                        R.string.accessibility_shortcut_edit_dialog_title, mDialogTitle);
+                mDialog = AccessibilityEditDialogUtils.showEditShortcutDialog(getActivity(),
+                        dialogTitle, mDialogListener);
+                break;
+            }
             default: {
                 throw new IllegalArgumentException();
             }
@@ -204,10 +245,19 @@
 
     @Override
     public int getDialogMetricsCategory(int dialogId) {
-        if (dialogId == DIALOG_ID_ENABLE_WARNING) {
-            return SettingsEnums.DIALOG_ACCESSIBILITY_SERVICE_ENABLE;
-        } else {
-            return SettingsEnums.DIALOG_ACCESSIBILITY_SERVICE_DISABLE;
+        switch (dialogId) {
+            case DIALOG_ID_ENABLE_WARNING:
+                return SettingsEnums.DIALOG_ACCESSIBILITY_SERVICE_ENABLE;
+            case DIALOG_ID_DISABLE_WARNING:
+                return SettingsEnums.DIALOG_ACCESSIBILITY_SERVICE_DISABLE;
+            case DIALOG_ID_LAUNCH_ACCESSIBILITY_TUTORIAL:
+                return isGestureNavigateEnabled()
+                        ? SettingsEnums.DIALOG_TOGGLE_SCREEN_GESTURE_NAVIGATION
+                        : SettingsEnums.DIALOG_TOGGLE_SCREEN_ACCESSIBILITY_BUTTON;
+            case DIALOG_ID_EDIT_SHORTCUT:
+                return SettingsEnums.DIALOG_ACCESSIBILITY_SERVICE_EDIT_SHORTCUT;
+            default:
+                return 0;
         }
     }
 
@@ -220,6 +270,21 @@
         switchBar.setSwitchBarText(switchBarText, switchBarText);
     }
 
+    private void initShortcutPreference() {
+        final PreferenceScreen preferenceScreen = getPreferenceScreen();
+        final ShortcutPreference shortcutPreference = new ShortcutPreference(
+                preferenceScreen.getContext(), null);
+        // Put the shortcutPreference before settingsPreference.
+        shortcutPreference.setOrder(-1);
+        shortcutPreference.setTitle(R.string.accessibility_shortcut_title);
+        // TODO(b/142530063): Check the new setting key to decide which summary should be shown.
+        // TODO(b/142530063): Check if gesture mode is on to decide which summary should be shown.
+        // TODO(b/142530063): Check the new key to decide whether checkbox should be checked.
+        shortcutPreference.setSettingButtonListener(mSettingButtonListener);
+        shortcutPreference.setCheckBoxListener(mCheckBoxListener);
+        preferenceScreen.addPreference(shortcutPreference);
+    }
+
     private void updateSwitchBarToggleSwitch() {
         final boolean checked = AccessibilityUtils.getEnabledServicesFromSettings(getActivity())
                 .contains(mComponentName);
@@ -350,5 +415,9 @@
 
         // Settings html description.
         mHtmlDescription = arguments.getCharSequence(AccessibilitySettings.EXTRA_HTML_DESCRIPTION);
+
+        // Get Accessibility service name.
+        mDialogTitle = getAccessibilityServiceInfo().getResolveInfo().loadLabel(
+                getPackageManager());
     }
 }
diff --git a/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java
index 3cde80a..f093dc7 100644
--- a/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java
@@ -16,13 +16,21 @@
 
 package com.android.settings.accessibility;
 
+import android.app.Dialog;
 import android.app.settings.SettingsEnums;
 import android.content.Context;
+import android.content.DialogInterface;
 import android.content.res.Resources;
+import android.os.Bundle;
 import android.provider.Settings;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.CheckBox;
 import android.widget.Switch;
 
 import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
 
 import com.android.settings.R;
 import com.android.settings.search.BaseSearchIndexProvider;
@@ -30,6 +38,7 @@
 import com.android.settingslib.core.AbstractPreferenceController;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 import com.android.settingslib.search.SearchIndexable;
+import com.android.settingslib.widget.RadioButtonPreference;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -42,6 +51,8 @@
     public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
             new BaseSearchIndexProvider(R.xml.accessibility_daltonizer_settings);
     private static final String ENABLED = Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED;
+    private static final String RADIOPREFERENCE_KEY = "daltonizer_mode_deuteranomaly";
+    private static final int DIALOG_ID_EDIT_SHORTCUT = 1;
     private static final List<AbstractPreferenceController> sControllers = new ArrayList<>();
 
     private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
@@ -59,6 +70,27 @@
         return sControllers;
     }
 
+    private final DialogInterface.OnClickListener mDialogListener =
+            (DialogInterface dialog, int id) -> {
+                if (id == DialogInterface.BUTTON_POSITIVE) {
+                    // TODO(b/142531156): Save the shortcut type preference.
+                }
+            };
+
+    private final View.OnClickListener mSettingButtonListener =
+            (View view) -> showDialog(DIALOG_ID_EDIT_SHORTCUT);
+
+    private final View.OnClickListener mCheckBoxListener = (View view) -> {
+        CheckBox checkBox = (CheckBox) view;
+        if (checkBox.isChecked()) {
+            // TODO(b/142530063): Enable shortcut when checkbox is checked.
+        } else {
+            // TODO(b/142530063): Disable shortcut when checkbox is unchecked.
+        }
+    };
+
+    private Dialog mDialog;
+
     @Override
     public void onCheckedChanged(Preference preference) {
         for (AbstractPreferenceController controller : sControllers) {
@@ -67,6 +99,13 @@
     }
 
     @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        initShortcutPreference();
+        return super.onCreateView(inflater, container, savedInstanceState);
+    }
+
+    @Override
     public void onResume() {
         super.onResume();
         for (AbstractPreferenceController controller :
@@ -87,11 +126,31 @@
     }
 
     @Override
+    public Dialog onCreateDialog(int dialogId) {
+        if (dialogId == DIALOG_ID_EDIT_SHORTCUT) {
+            final CharSequence dialogTitle = getActivity().getString(
+                    R.string.accessibility_shortcut_edit_dialog_title_daltonizer);
+            mDialog = AccessibilityEditDialogUtils.showEditShortcutDialog(getActivity(),
+                    dialogTitle, mDialogListener);
+        }
+
+        return mDialog;
+    }
+
+    @Override
     public int getMetricsCategory() {
         return SettingsEnums.ACCESSIBILITY_TOGGLE_DALTONIZER;
     }
 
     @Override
+    public int getDialogMetricsCategory(int dialogId) {
+        if (dialogId == DIALOG_ID_EDIT_SHORTCUT) {
+            return SettingsEnums.DIALOG_DALTONIZER_EDIT_SHORTCUT;
+        }
+        return 0;
+    }
+
+    @Override
     public int getHelpResource() {
         return R.string.help_url_color_correction;
     }
@@ -131,4 +190,20 @@
                 Settings.Secure.getInt(getContentResolver(), ENABLED, 0) == 1);
         mSwitchBar.addOnSwitchChangeListener(this);
     }
+
+    private void initShortcutPreference() {
+        final PreferenceScreen preferenceScreen = getPreferenceScreen();
+        final ShortcutPreference shortcutPreference = new ShortcutPreference(
+                preferenceScreen.getContext(), null);
+        final RadioButtonPreference radioButtonPreference = findPreference(RADIOPREFERENCE_KEY);
+        // Put the shortcutPreference before radioButtonPreference.
+        shortcutPreference.setOrder(radioButtonPreference.getOrder() - 1);
+        shortcutPreference.setTitle(R.string.accessibility_shortcut_title);
+        // TODO(b/142530063): Check the new setting key to decide which summary should be shown.
+        // TODO(b/142530063): Check if gesture mode is on to decide which summary should be shown.
+        // TODO(b/142530063): Check the new key to decide whether checkbox should be checked.
+        shortcutPreference.setSettingButtonListener(mSettingButtonListener);
+        shortcutPreference.setCheckBoxListener(mCheckBoxListener);
+        preferenceScreen.addPreference(shortcutPreference);
+    }
 }
diff --git a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java
index 842ec5c..f9016e8 100644
--- a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java
@@ -22,6 +22,7 @@
 import android.app.settings.SettingsEnums;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.DialogInterface;
 import android.content.res.Resources;
 import android.graphics.Point;
 import android.media.AudioManager;
@@ -32,8 +33,12 @@
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.view.Display;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
 import android.view.ViewTreeObserver.OnGlobalLayoutListener;
 import android.view.WindowManager;
+import android.widget.CheckBox;
 import android.widget.ImageView;
 import android.widget.RelativeLayout.LayoutParams;
 import android.widget.Switch;
@@ -49,8 +54,29 @@
 public class ToggleScreenMagnificationPreferenceFragment extends
         ToggleFeaturePreferenceFragment implements SwitchBar.OnSwitchChangeListener {
 
+    private static final String SETTINGS_KEY = "screen_magnification_settings";
     private static final int DIALOG_ID_GESTURE_NAVIGATION_TUTORIAL = 1;
     private static final int DIALOG_ID_ACCESSIBILITY_BUTTON_TUTORIAL = 2;
+    private static final int DIALOG_ID_EDIT_SHORTCUT = 3;
+
+    private final DialogInterface.OnClickListener mDialogListener =
+            (DialogInterface dialog, int id) -> {
+                if (id == DialogInterface.BUTTON_POSITIVE) {
+                    // TODO(b/142531156): Save the shortcut type preference.
+                }
+            };
+
+    private final View.OnClickListener mSettingButtonListener =
+            (View view) -> showDialog(DIALOG_ID_EDIT_SHORTCUT);
+
+    private final View.OnClickListener mCheckBoxListener = (View view) -> {
+        CheckBox checkBox = (CheckBox) view;
+        if (checkBox.isChecked()) {
+            // TODO(b/142530063): Enable shortcut when checkbox is checked.
+        } else {
+            // TODO(b/142530063): Disable shortcut when checkbox is unchecked.
+        }
+    };
 
     private Dialog mDialog;
 
@@ -145,6 +171,13 @@
         mVideoPreference.setPersistent(false);
         mVideoPreference.setLayoutResource(R.layout.magnification_video_preference);
 
+        final Preference settingsPreference = new Preference(getPrefContext());
+        final String SettingsText = getString(R.string.settings_button);
+        settingsPreference.setTitle(SettingsText);
+        settingsPreference.setKey(SETTINGS_KEY);
+        settingsPreference.setFragment(MagnificationSettingsFragment.class.getName());
+        settingsPreference.setPersistent(false);
+
         mConfigWarningPreference = new Preference(getPrefContext());
         mConfigWarningPreference.setSelectable(false);
         mConfigWarningPreference.setPersistent(false);
@@ -154,12 +187,21 @@
         final PreferenceScreen preferenceScreen = getPreferenceManager().getPreferenceScreen();
         preferenceScreen.setOrderingAsAdded(false);
         mVideoPreference.setOrder(0);
+        settingsPreference.setOrder(1);
         mConfigWarningPreference.setOrder(2);
         preferenceScreen.addPreference(mVideoPreference);
+        preferenceScreen.addPreference(settingsPreference);
         preferenceScreen.addPreference(mConfigWarningPreference);
     }
 
     @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        initShortcutPreference();
+        return super.onCreateView(inflater, container, savedInstanceState);
+    }
+
+    @Override
     public void onResume() {
         super.onResume();
 
@@ -182,6 +224,12 @@
                 mDialog = AccessibilityGestureNavigationTutorial
                         .showAccessibilityButtonTutorialDialog(getActivity());
                 break;
+            case DIALOG_ID_EDIT_SHORTCUT:
+                final CharSequence dialogTitle = getActivity().getString(
+                        R.string.accessibility_shortcut_edit_dialog_title_magnification);
+                mDialog = AccessibilityEditDialogUtils.showMagnificationEditShortcutDialog(
+                        getActivity(), dialogTitle, mDialogListener);
+                break;
             default:
                 throw new IllegalArgumentException();
         }
@@ -202,6 +250,8 @@
                 return SettingsEnums.DIALOG_TOGGLE_SCREEN_MAGNIFICATION_GESTURE_NAVIGATION;
             case DIALOG_ID_ACCESSIBILITY_BUTTON_TUTORIAL:
                 return SettingsEnums.DIALOG_TOGGLE_SCREEN_MAGNIFICATION_ACCESSIBILITY_BUTTON;
+            case DIALOG_ID_EDIT_SHORTCUT:
+                return SettingsEnums.DIALOG_MAGNIFICATION_EDIT_SHORTCUT;
             default:
                 return 0;
         }
@@ -277,6 +327,21 @@
         }
     }
 
+    private void initShortcutPreference() {
+        final PreferenceScreen preferenceScreen = getPreferenceScreen();
+        final ShortcutPreference shortcutPreference = new ShortcutPreference(
+                preferenceScreen.getContext(), null);
+        // Put the shortcutPreference before videoPreference.
+        shortcutPreference.setOrder(mVideoPreference.getOrder() - 1);
+        shortcutPreference.setTitle(R.string.accessibility_magnification_shortcut_title);
+        // TODO(b/142530063): Check the new setting key to decide which summary should be shown.
+        // TODO(b/142530063): Check if gesture mode is on to decide which summary should be shown.
+        // TODO(b/142530063): Check the new key to decide whether checkbox should be checked.
+        shortcutPreference.setSettingButtonListener(mSettingButtonListener);
+        shortcutPreference.setCheckBoxListener(mCheckBoxListener);
+        preferenceScreen.addPreference(shortcutPreference);
+    }
+
     private boolean isGestureNavigateEnabled() {
         return getContext().getResources().getInteger(
                 com.android.internal.R.integer.config_navBarInteractionMode)
diff --git a/src/com/android/settings/accounts/AccountDashboardFragment.java b/src/com/android/settings/accounts/AccountDashboardFragment.java
index 53b5ea3..7b50b46 100644
--- a/src/com/android/settings/accounts/AccountDashboardFragment.java
+++ b/src/com/android/settings/accounts/AccountDashboardFragment.java
@@ -17,8 +17,13 @@
 
 import static android.provider.Settings.EXTRA_AUTHORITIES;
 
+import android.accounts.Account;
+import android.accounts.AccountManager;
 import android.app.settings.SettingsEnums;
 import android.content.Context;
+import android.content.pm.UserInfo;
+import android.os.UserHandle;
+import android.os.UserManager;
 
 import com.android.settings.R;
 import com.android.settings.SettingsPreferenceFragment;
@@ -97,7 +102,26 @@
                 @Override
                 public List<SearchIndexableRaw> getDynamicRawDataToIndex(Context context,
                         boolean enabled) {
-                    return null;
+                    final List<SearchIndexableRaw> indexRaws = new ArrayList<>();
+                    final UserManager userManager = (UserManager) context.getSystemService(
+                            Context.USER_SERVICE);
+                    final List<UserInfo> profiles = userManager.getProfiles(UserHandle.myUserId());
+                    for (final UserInfo userInfo : profiles) {
+                        if (userInfo.isManagedProfile()) {
+                            return indexRaws;
+                        }
+                    }
+
+                    final AccountManager accountManager = AccountManager.get(context);
+                    final Account[] accounts = accountManager.getAccounts();
+                    for (Account account : accounts) {
+                        final SearchIndexableRaw raw = new SearchIndexableRaw(context);
+                        raw.key = AccountTypePreference.buildKey(account);
+                        raw.title = account.name;
+                        indexRaws.add(raw);
+                    }
+
+                    return indexRaws;
                 }
             };
 }
diff --git a/src/com/android/settings/applications/appops/AppOpsState.java b/src/com/android/settings/applications/appops/AppOpsState.java
index fed77ae..cbffe47 100644
--- a/src/com/android/settings/applications/appops/AppOpsState.java
+++ b/src/com/android/settings/applications/appops/AppOpsState.java
@@ -28,7 +28,6 @@
 import android.os.Parcelable;
 import android.text.format.DateUtils;
 import android.util.Log;
-import android.util.Pair;
 import android.util.SparseArray;
 
 import com.android.settings.R;
@@ -619,7 +618,7 @@
 
                         }
                         AppOpsManager.OpEntry opEntry = new AppOpsManager.OpEntry(
-                                permOps.get(k), AppOpsManager.MODE_ALLOWED, new Pair[0]);
+                                permOps.get(k), AppOpsManager.MODE_ALLOWED, Collections.emptyMap());
                         dummyOps.add(opEntry);
                         addOp(entries, pkgOps, appEntry, opEntry, packageName == null,
                                 packageName == null ? 0 : opToOrder[opEntry.getOp()]);
diff --git a/src/com/android/settings/applications/manageapplications/ManageApplications.java b/src/com/android/settings/applications/manageapplications/ManageApplications.java
index 7da89e4..02e42e2 100644
--- a/src/com/android/settings/applications/manageapplications/ManageApplications.java
+++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java
@@ -34,14 +34,19 @@
 import android.annotation.Nullable;
 import android.annotation.StringRes;
 import android.app.Activity;
+import android.app.ActivityManager;
 import android.app.settings.SettingsEnums;
 import android.app.usage.IUsageStatsManager;
+import android.compat.annotation.ChangeId;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageItemInfo;
+import android.net.Uri;
 import android.os.Bundle;
 import android.os.Environment;
+import android.os.IBinder;
+import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -69,6 +74,7 @@
 import androidx.recyclerview.widget.LinearLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
 
+import com.android.internal.compat.IPlatformCompat;
 import com.android.settings.R;
 import com.android.settings.Settings;
 import com.android.settings.Settings.GamesStorageActivity;
@@ -172,6 +178,15 @@
 
     private static final int NO_USER_SPECIFIED = -1;
 
+    /**
+     * Intents with action {@link android.provider.Settings#ACTION_MANAGE_APP_OVERLAY_PERMISSION}
+     * and data URI scheme "package" don't go to the app-specific screen for managing the permission
+     * anymore. Instead, they redirect to this screen for managing all the apps that have requested
+     * such permission.
+     */
+    @ChangeId
+    private static final long CHANGE_RESTRICT_SAW_INTENT = 135920175L;
+
     // sort order
     @VisibleForTesting
     int mSortOrder = R.id.sort_order_alpha;
@@ -275,6 +290,8 @@
         } else if (className.equals(OverlaySettingsActivity.class.getName())) {
             mListType = LIST_TYPE_OVERLAY;
             screenTitle = R.string.system_alert_window_settings;
+
+            reportIfRestrictedSawIntent(intent);
         } else if (className.equals(WriteSettingsActivity.class.getName())) {
             mListType = LIST_TYPE_WRITE_SETTINGS;
             screenTitle = R.string.write_settings;
@@ -334,6 +351,31 @@
         }
     }
 
+    private void reportIfRestrictedSawIntent(Intent intent) {
+        try {
+            Uri data = intent.getData();
+            if (data == null || !TextUtils.equals("package", data.getScheme())) {
+                // Not a restricted intent
+                return;
+            }
+            IBinder activityToken = getActivity().getActivityToken();
+            int callingUid = ActivityManager.getService().getLaunchedFromUid(activityToken);
+            if (callingUid == -1) {
+                Log.w(TAG, "Error obtaining calling uid");
+                return;
+            }
+            IPlatformCompat platformCompat = IPlatformCompat.Stub.asInterface(
+                    ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
+            if (platformCompat == null) {
+                Log.w(TAG, "Error obtaining IPlatformCompat service");
+                return;
+            }
+            platformCompat.reportChangeByUid(CHANGE_RESTRICT_SAW_INTENT, callingUid);
+        } catch (RemoteException e) {
+            Log.w(TAG, "Error reporting SAW intent restriction", e);
+        }
+    }
+
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
             Bundle savedInstanceState) {
diff --git a/src/com/android/settings/biometrics/BiometricEnrollActivity.java b/src/com/android/settings/biometrics/BiometricEnrollActivity.java
index 64ddf4f..61c417c 100644
--- a/src/com/android/settings/biometrics/BiometricEnrollActivity.java
+++ b/src/com/android/settings/biometrics/BiometricEnrollActivity.java
@@ -21,6 +21,8 @@
 import android.content.pm.PackageManager;
 import android.os.Bundle;
 import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.Log;
 
 import com.android.settings.SetupWizardUtils;
 import com.android.settings.biometrics.face.FaceEnrollIntroduction;
@@ -50,6 +52,9 @@
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
+        Log.d(TAG, "Min strength: " + getIntent()
+                .getIntExtra(Settings.EXTRA_BIOMETRIC_MINIMUM_STRENGTH_REQUIRED, 0));
+
         final PackageManager pm = getApplicationContext().getPackageManager();
         Intent intent = null;
 
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollPreviewFragment.java b/src/com/android/settings/biometrics/face/FaceEnrollPreviewFragment.java
index 8806712..853ca7c 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollPreviewFragment.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollPreviewFragment.java
@@ -18,6 +18,7 @@
 
 import android.app.settings.SettingsEnums;
 import android.content.Context;
+import android.graphics.Matrix;
 import android.graphics.SurfaceTexture;
 import android.hardware.camera2.CameraAccessException;
 import android.hardware.camera2.CameraCaptureSession;
@@ -316,14 +317,19 @@
         scaleX = scaleX / smaller;
         scaleY = scaleY / smaller;
 
-        // Apply the transformation/scale
-        mTextureView.setTranslationX(getResources().getDimension(R.dimen.face_preview_translate_x));
-        mTextureView.setTranslationY(getResources().getDimension(R.dimen.face_preview_translate_y));
-
+        final TypedValue tx = new TypedValue();
+        final TypedValue ty = new TypedValue();
         final TypedValue scale = new TypedValue();
+        getResources().getValue(R.dimen.face_preview_translate_x, tx, true /* resolveRefs */);
+        getResources().getValue(R.dimen.face_preview_translate_y, ty, true /* resolveRefs */);
         getResources().getValue(R.dimen.face_preview_scale, scale, true /* resolveRefs */);
-        mTextureView.setScaleX(scaleX * scale.getFloat());
-        mTextureView.setScaleY(scaleY * scale.getFloat());
+
+        // Apply the transformation/scale
+        final Matrix transform = new Matrix();
+        mTextureView.getTransform(transform);
+        transform.setScale(scaleX * scale.getFloat(), scaleY * scale.getFloat());
+        transform.postTranslate(tx.getFloat(), ty.getFloat());
+        mTextureView.setTransform(transform);
     }
 
     private void closeCamera() {
diff --git a/src/com/android/settings/bugreporthandler/BugReportHandlerPicker.java b/src/com/android/settings/bugreporthandler/BugReportHandlerPicker.java
index 9c2ac9e..1db2b86 100644
--- a/src/com/android/settings/bugreporthandler/BugReportHandlerPicker.java
+++ b/src/com/android/settings/bugreporthandler/BugReportHandlerPicker.java
@@ -164,13 +164,13 @@
     private String getDescription(String handlerApp, int handlerUser) {
         final Context context = getContext();
         if (BugReportHandlerUtil.SHELL_APP_PACKAGE.equals(handlerApp)) {
-            return context.getString(R.string.system_default_app);
+            return context.getString(R.string.system_default_app_subtext);
         }
         final UserHandle managedProfile = Utils.getManagedProfile(mUserManager);
         if (managedProfile != null && managedProfile.getIdentifier() == handlerUser) {
-            return context.getString(R.string.work_profile_app);
+            return context.getString(R.string.work_profile_app_subtext);
         }
-        return context.getString(R.string.personal_profile_app);
+        return context.getString(R.string.personal_profile_app_subtext);
     }
 
     private static class BugreportHandlerAppInfo extends DefaultAppInfo {
@@ -197,7 +197,7 @@
                 return null;
             }
             if (BugReportHandlerUtil.SHELL_APP_PACKAGE.equals(packageItemInfo.packageName)) {
-                return mContext.getString(R.string.shell_app);
+                return mContext.getString(com.android.internal.R.string.android_system_label);
             }
             return super.loadLabel();
         }
diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java
index 01b1598..1e97bdb 100644
--- a/src/com/android/settings/core/gateway/SettingsGateway.java
+++ b/src/com/android/settings/core/gateway/SettingsGateway.java
@@ -87,6 +87,7 @@
 import com.android.settings.gestures.DoubleTapPowerSettings;
 import com.android.settings.gestures.DoubleTapScreenSettings;
 import com.android.settings.gestures.DoubleTwistGestureSettings;
+import com.android.settings.gestures.GestureNavigationSettingsFragment;
 import com.android.settings.gestures.GlobalActionsPanelSettings;
 import com.android.settings.gestures.PickupGestureSettings;
 import com.android.settings.gestures.SwipeToNotificationSettings;
@@ -289,7 +290,8 @@
             MobileNetworkListFragment.class.getName(),
             GlobalActionsPanelSettings.class.getName(),
             DarkModeSettingsFragment.class.getName(),
-            BugReportHandlerPicker.class.getName()
+            BugReportHandlerPicker.class.getName(),
+            GestureNavigationSettingsFragment.class.getName()
     };
 
     public static final String[] SETTINGS_FOR_RESTRICTED = {
diff --git a/src/com/android/settings/dashboard/profileselector/ProfileSelectFragment.java b/src/com/android/settings/dashboard/profileselector/ProfileSelectFragment.java
index 9ae8284..d0187b9 100644
--- a/src/com/android/settings/dashboard/profileselector/ProfileSelectFragment.java
+++ b/src/com/android/settings/dashboard/profileselector/ProfileSelectFragment.java
@@ -150,7 +150,7 @@
         if (bundle != null) {
             final int extraTab = bundle.getInt(SettingsActivity.EXTRA_SHOW_FRAGMENT_TAB, -1);
             if (extraTab != -1) {
-                return WORK_TAB;
+                return extraTab;
             }
             final int userId = bundle.getInt(EXTRA_USER_ID, UserHandle.SYSTEM.getIdentifier());
             final boolean isWorkProfile = UserManager.get(activity).isManagedProfile(userId);
diff --git a/src/com/android/settings/development/BugReportHandlerPreferenceController.java b/src/com/android/settings/development/BugReportHandlerPreferenceController.java
index b95d31b..f154537 100644
--- a/src/com/android/settings/development/BugReportHandlerPreferenceController.java
+++ b/src/com/android/settings/development/BugReportHandlerPreferenceController.java
@@ -73,7 +73,7 @@
         final String handlerApp = mBugReportHandlerUtil.getCurrentBugReportHandlerAppAndUser(
                 mContext).first;
         if (BugReportHandlerUtil.SHELL_APP_PACKAGE.equals(handlerApp)) {
-            return mContext.getString(R.string.shell_app);
+            return mContext.getString(com.android.internal.R.string.android_system_label);
         }
         ApplicationInfo applicationInfo;
         try {
diff --git a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
index 9387d52..88f2c50 100644
--- a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
+++ b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
@@ -471,6 +471,7 @@
         controllers.add(new PointerLocationPreferenceController(context));
         controllers.add(new ShowSurfaceUpdatesPreferenceController(context));
         controllers.add(new ShowLayoutBoundsPreferenceController(context));
+        controllers.add(new ShowRefreshRatePreferenceController(context));
         controllers.add(new RtlLayoutPreferenceController(context));
         controllers.add(new WindowAnimationScalePreferenceController(context));
         controllers.add(new EmulateDisplayCutoutPreferenceController(context));
diff --git a/src/com/android/settings/development/ShowRefreshRatePreferenceController.java b/src/com/android/settings/development/ShowRefreshRatePreferenceController.java
new file mode 100644
index 0000000..e56268d
--- /dev/null
+++ b/src/com/android/settings/development/ShowRefreshRatePreferenceController.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.development;
+
+import android.content.Context;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+import androidx.preference.SwitchPreference;
+
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.development.DeveloperOptionsPreferenceController;
+
+/**
+ * Controller class for controlling the refresh rate overlay on SurfaceFlinger
+ */
+public class ShowRefreshRatePreferenceController extends DeveloperOptionsPreferenceController
+        implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin {
+
+    private static final String SHOW_REFRESH_RATE_KEY = "show_refresh_rate";
+
+    private static final int SETTING_VALUE_QUERY = 2;
+    private static final int SETTING_VALUE_ON = 1;
+    private static final int SETTING_VALUE_OFF = 0;
+
+    @VisibleForTesting
+    static final String SURFACE_FLINGER_SERVICE_KEY = "SurfaceFlinger";
+    @VisibleForTesting
+    static final int SURFACE_FLINGER_CODE = 1034;
+
+    private static final String SURFACE_COMPOSER_INTERFACE_KEY = "android.ui.ISurfaceComposer";
+
+    private final IBinder mSurfaceFlinger;
+
+    public ShowRefreshRatePreferenceController(Context context) {
+        super(context);
+        mSurfaceFlinger = ServiceManager.getService(SURFACE_FLINGER_SERVICE_KEY);
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return SHOW_REFRESH_RATE_KEY;
+    }
+
+    @Override
+    public boolean onPreferenceChange(Preference preference, Object newValue) {
+        final boolean isEnabled = (Boolean) newValue;
+        writeShowRefreshRateSetting(isEnabled);
+        return true;
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        updateShowRefreshRateSetting();
+    }
+
+    @Override
+    protected void onDeveloperOptionsSwitchDisabled() {
+        super.onDeveloperOptionsSwitchDisabled();
+        final SwitchPreference preference = (SwitchPreference) mPreference;
+        if (preference.isChecked()) {
+            // Writing false to the preference when the setting is already off will have a
+            // side effect of turning on the preference that we wish to avoid
+            writeShowRefreshRateSetting(false);
+            preference.setChecked(false);
+        }
+    }
+
+    @VisibleForTesting
+    void updateShowRefreshRateSetting() {
+        // magic communication with surface flinger.
+        try {
+            if (mSurfaceFlinger != null) {
+                final Parcel data = Parcel.obtain();
+                final Parcel reply = Parcel.obtain();
+                data.writeInterfaceToken(SURFACE_COMPOSER_INTERFACE_KEY);
+                data.writeInt(SETTING_VALUE_QUERY);
+                mSurfaceFlinger.transact(SURFACE_FLINGER_CODE, data, reply, 0 /* flags */);
+                final boolean enabled = reply.readBoolean();
+                ((SwitchPreference) mPreference).setChecked(enabled);
+                reply.recycle();
+                data.recycle();
+            }
+        } catch (RemoteException ex) {
+            // intentional no-op
+        }
+    }
+
+    @VisibleForTesting
+    void writeShowRefreshRateSetting(boolean isEnabled) {
+        try {
+            if (mSurfaceFlinger != null) {
+                final Parcel data = Parcel.obtain();
+                data.writeInterfaceToken(SURFACE_COMPOSER_INTERFACE_KEY);
+                final int showRefreshRate = isEnabled ? SETTING_VALUE_ON : SETTING_VALUE_OFF;
+                data.writeInt(showRefreshRate);
+                mSurfaceFlinger.transact(SURFACE_FLINGER_CODE, data,
+                        null /* reply */, 0 /* flags */);
+                data.recycle();
+            }
+        } catch (RemoteException ex) {
+            // intentional no-op
+        }
+        updateShowRefreshRateSetting();
+    }
+}
diff --git a/src/com/android/settings/gestures/BackGestureIndicatorDrawable.java b/src/com/android/settings/gestures/BackGestureIndicatorDrawable.java
new file mode 100644
index 0000000..2d09e6b
--- /dev/null
+++ b/src/com/android/settings/gestures/BackGestureIndicatorDrawable.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.gestures;
+
+import android.animation.TimeAnimator;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.settings.R;
+
+/** A drawable to animate the inset back gesture in both edges of the screen */
+public class BackGestureIndicatorDrawable extends Drawable {
+
+    private static final String TAG = "BackGestureIndicatorDrawable";
+
+    private static final int MSG_SET_INDICATOR_WIDTH = 1;
+    private static final int MSG_HIDE_INDICATOR = 3;
+
+    private static final long ANIMATION_DURATION_MS = 200L;
+    private static final long HIDE_DELAY_MS = 700L;
+
+    private static final int ALPHA_MAX = 64;
+
+    private Context mContext;
+
+    private Paint mPaint = new Paint();
+    private boolean mReversed;
+
+    private float mFinalWidth;
+    private float mCurrentWidth;
+    private float mWidthChangePerMs;
+
+    private TimeAnimator mTimeAnimator = new TimeAnimator();
+
+    private final Handler mHandler = new Handler(Looper.getMainLooper()) {
+        @Override
+        public void handleMessage(Message msg) {
+            switch(msg.what) {
+                case MSG_SET_INDICATOR_WIDTH:
+                    mTimeAnimator.end();
+                    mFinalWidth = msg.arg1;
+                    mWidthChangePerMs = Math.abs(mCurrentWidth - mFinalWidth)
+                            / ANIMATION_DURATION_MS;
+                    mTimeAnimator.start();
+                    break;
+                case MSG_HIDE_INDICATOR:
+                    mCurrentWidth = mFinalWidth;
+                    removeMessages(MSG_SET_INDICATOR_WIDTH);
+                    sendMessageDelayed(obtainMessage(MSG_SET_INDICATOR_WIDTH, 0, 0), HIDE_DELAY_MS);
+                    invalidateSelf();
+                    break;
+                default:
+                    break;
+            }
+        }
+    };
+
+    /**
+     * Creates an indicator drawable that responds to back gesture inset size change
+     * @param reversed If false, indicator will expand right. If true, indicator will expand left
+     */
+    public BackGestureIndicatorDrawable(Context context, boolean reversed) {
+        mContext = context;
+        mReversed = reversed;
+
+        // Restart the timer whenever a change is detected, so we can shrink/fade the indicators
+        mTimeAnimator.setTimeListener((TimeAnimator animation, long totalTime, long deltaTime) -> {
+            updateCurrentWidth(totalTime, deltaTime);
+            invalidateSelf();
+        });
+    }
+
+    private void updateCurrentWidth(long totalTime, long deltaTime) {
+        synchronized (mTimeAnimator) {
+            float step = deltaTime * mWidthChangePerMs;
+            if (totalTime >= ANIMATION_DURATION_MS
+                    || step >= Math.abs(mFinalWidth - mCurrentWidth)) {
+                mCurrentWidth = mFinalWidth;
+                mTimeAnimator.end();
+            } else {
+                float direction = mCurrentWidth < mFinalWidth ? 1 : -1;
+                mCurrentWidth += direction * step;
+            }
+        }
+    }
+
+    @Override
+    public void draw(@NonNull Canvas canvas) {
+
+        mPaint.setAntiAlias(true);
+        mPaint.setColor(mContext.getResources().getColor(R.color.back_gesture_indicator));
+        mPaint.setAlpha(ALPHA_MAX);
+
+        final int top = 0;
+        final int bottom = canvas.getHeight();
+        final int width = (int) mCurrentWidth;
+
+        Rect rect = new Rect(0, top, width, bottom);
+        if (mReversed) {
+            rect.offset(canvas.getWidth() - width, 0);
+        }
+
+        canvas.drawRect(rect, mPaint);
+    }
+
+    @Override
+    public void setAlpha(@IntRange(from = 0, to = 255) int alpha) {
+
+    }
+
+    @Override
+    public void setColorFilter(@Nullable ColorFilter colorFilter) {
+
+    }
+
+    @Override
+    public int getOpacity() {
+        return 0;
+    }
+
+    /**
+     * Sets the visible width of the indicator in pixels.
+     */
+    public void setWidth(int width) {
+        if (width == 0) {
+            mHandler.sendEmptyMessage(MSG_HIDE_INDICATOR);
+        } else {
+            mHandler.sendMessage(mHandler.obtainMessage(MSG_SET_INDICATOR_WIDTH, width, 0));
+        }
+    }
+
+    @VisibleForTesting
+    public int getWidth() {
+        return (int) mFinalWidth;
+    }
+}
diff --git a/src/com/android/settings/gestures/BackGestureIndicatorView.java b/src/com/android/settings/gestures/BackGestureIndicatorView.java
new file mode 100644
index 0000000..2bb8435
--- /dev/null
+++ b/src/com/android/settings/gestures/BackGestureIndicatorView.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.gestures;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.PixelFormat;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+
+import com.android.settings.R;
+
+/**
+ * A linear layout containing the left and right location indicators.
+ */
+public class BackGestureIndicatorView extends LinearLayout {
+    private ViewGroup mLayout;
+    private ImageView mLeftIndicator;
+    private ImageView mRightIndicator;
+    private BackGestureIndicatorDrawable mLeftDrawable;
+    private BackGestureIndicatorDrawable mRightDrawable;
+
+    public BackGestureIndicatorView(Context context) {
+        super(context);
+
+        LayoutInflater factory = LayoutInflater.from(context);
+        mLayout = (ViewGroup) factory.inflate(R.layout.back_gesture_indicator_container,
+                this, false);
+
+        if (mLayout == null) {
+            return;
+        }
+
+        addView(mLayout);
+
+        mLeftDrawable = new BackGestureIndicatorDrawable(context, false);
+        mRightDrawable = new BackGestureIndicatorDrawable(context, true);
+
+        mLeftIndicator = mLayout.findViewById(R.id.indicator_left);
+        mRightIndicator = mLayout.findViewById(R.id.indicator_right);
+
+        mLeftIndicator.setImageDrawable(mLeftDrawable);
+        mRightIndicator.setImageDrawable(mRightDrawable);
+
+        TypedArray a = context.obtainStyledAttributes(new int[] {
+                android.R.attr.windowLightNavigationBar,
+                android.R.attr.windowLightStatusBar});
+        if (a.getBoolean(0, false)) {
+            setSystemUiVisibility(
+                    getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR);
+        }
+        if (a.getBoolean(1, false)) {
+            setSystemUiVisibility(
+                    getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
+        }
+        a.recycle();
+    }
+
+    public void setIndicatorWidth(int width, boolean leftIndicator) {
+        BackGestureIndicatorDrawable indicator = leftIndicator ? mLeftDrawable : mRightDrawable;
+        indicator.setWidth(width);
+    }
+
+    public WindowManager.LayoutParams getLayoutParams(
+            WindowManager.LayoutParams parentWindowAttributes) {
+        int copiedFlags = (parentWindowAttributes.flags
+                & WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
+        final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                WindowManager.LayoutParams.TYPE_APPLICATION,
+                WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
+                        | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
+                        | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                        | copiedFlags,
+                PixelFormat.TRANSLUCENT);
+
+        lp.setTitle("BackGestureIndicatorView");
+        lp.token = getContext().getActivityToken();
+        return lp;
+    }
+}
diff --git a/src/com/android/settings/gestures/GestureNavigationSettingsFragment.java b/src/com/android/settings/gestures/GestureNavigationSettingsFragment.java
new file mode 100644
index 0000000..c209c81
--- /dev/null
+++ b/src/com/android/settings/gestures/GestureNavigationSettingsFragment.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.gestures;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.view.WindowManager;
+
+import com.android.settings.R;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settingslib.search.SearchIndexable;
+
+/**
+ * A fragment to include all the settings related to Gesture Navigation mode.
+ */
+@SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
+public class GestureNavigationSettingsFragment extends DashboardFragment {
+
+    public static final String TAG = "GestureNavigationSettingsFragment";
+
+    public static final String GESTURE_NAVIGATION_SETTINGS =
+            "com.android.settings.GESTURE_NAVIGATION_SETTINGS";
+
+    private static final String LEFT_EDGE_SEEKBAR_KEY = "gesture_left_back_sensitivity";
+    private static final String RIGHT_EDGE_SEEKBAR_KEY = "gesture_right_back_sensitivity";
+
+    private WindowManager mWindowManager;
+    private BackGestureIndicatorView mIndicatorView;
+
+    private static final float[] BACK_GESTURE_INSET_SCALES = {0.75f, 1.0f, 1.33f, 1.66f};
+
+    private float mDefaultBackGestureInset;
+
+    public GestureNavigationSettingsFragment() {
+        super();
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        mIndicatorView = new BackGestureIndicatorView(getActivity());
+        mWindowManager = (WindowManager) getActivity().getSystemService(Context.WINDOW_SERVICE);
+
+        mDefaultBackGestureInset = getActivity().getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.config_backGestureInset);
+    }
+
+    @Override
+    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
+        super.onCreatePreferences(savedInstanceState, rootKey);
+
+        initSeekBarPreference(LEFT_EDGE_SEEKBAR_KEY);
+        initSeekBarPreference(RIGHT_EDGE_SEEKBAR_KEY);
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+
+        mWindowManager.addView(mIndicatorView, mIndicatorView.getLayoutParams(
+                getActivity().getWindow().getAttributes()));
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+
+        mWindowManager.removeView(mIndicatorView);
+    }
+
+    @Override
+    protected int getPreferenceScreenResId() {
+        return R.xml.gesture_navigation_settings;
+    }
+
+    @Override
+    public int getHelpResource() {
+        // TODO(b/146001201): Replace with gesture navigation help page when ready.
+        return R.string.help_uri_default;
+    }
+
+    @Override
+    protected String getLogTag() {
+        return TAG;
+    }
+
+    @Override
+    public int getMetricsCategory() {
+        return SettingsEnums.SETTINGS_GESTURE_NAV_BACK_SENSITIVITY_DLG;
+    }
+
+    private void initSeekBarPreference(final String key) {
+        final GestureNavigationSeekBarPreference pref = getPreferenceScreen().findPreference(key);
+        pref.setContinuousUpdates(true);
+
+        final String settingsKey = key == LEFT_EDGE_SEEKBAR_KEY
+                ? Settings.Secure.BACK_GESTURE_INSET_SCALE_LEFT
+                : Settings.Secure.BACK_GESTURE_INSET_SCALE_RIGHT;
+        final float initScale = Settings.Secure.getFloat(
+                getContext().getContentResolver(), settingsKey, 1.0f);
+
+        // Find the closest value to initScale
+        float minDistance = Float.MAX_VALUE;
+        int minDistanceIndex = -1;
+        for (int i = 0; i < BACK_GESTURE_INSET_SCALES.length; i++) {
+            float d = Math.abs(BACK_GESTURE_INSET_SCALES[i] - initScale);
+            if (d < minDistance) {
+                minDistance = d;
+                minDistanceIndex = i;
+            }
+        }
+        pref.setProgress(minDistanceIndex);
+
+        pref.setOnPreferenceChangeListener((p, v) -> {
+            final int width = (int) (mDefaultBackGestureInset * BACK_GESTURE_INSET_SCALES[(int) v]);
+            mIndicatorView.setIndicatorWidth(width, key == LEFT_EDGE_SEEKBAR_KEY);
+            return true;
+        });
+
+        pref.setOnPreferenceChangeStopListener((p, v) -> {
+            mIndicatorView.setIndicatorWidth(0, key == LEFT_EDGE_SEEKBAR_KEY);
+            final float scale = BACK_GESTURE_INSET_SCALES[(int) v];
+            Settings.Secure.putFloat(getContext().getContentResolver(), settingsKey, scale);
+            return true;
+        });
+    }
+
+    public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+            new BaseSearchIndexProvider(R.xml.gesture_navigation_settings);
+}
diff --git a/src/com/android/settings/network/AirplaneModePreferenceController.java b/src/com/android/settings/network/AirplaneModePreferenceController.java
index 3c79be3..f5fff1c 100644
--- a/src/com/android/settings/network/AirplaneModePreferenceController.java
+++ b/src/com/android/settings/network/AirplaneModePreferenceController.java
@@ -23,13 +23,13 @@
 import android.content.pm.PackageManager;
 import android.net.Uri;
 import android.provider.SettingsSlicesContract;
+import android.telephony.TelephonyManager;
 
 import androidx.fragment.app.Fragment;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
 import androidx.preference.SwitchPreference;
 
-import com.android.internal.telephony.TelephonyIntents;
 import com.android.settings.AirplaneModeEnabler;
 import com.android.settings.R;
 import com.android.settings.core.TogglePreferenceController;
@@ -77,7 +77,7 @@
             // In ECM mode launch ECM app dialog
             if (mFragment != null) {
                 mFragment.startActivityForResult(
-                        new Intent(TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS, null),
+                        new Intent(TelephonyManager.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS, null),
                         REQUEST_CODE_EXIT_ECM);
             }
             return true;
diff --git a/src/com/android/settings/network/MobileDataContentObserver.java b/src/com/android/settings/network/MobileDataContentObserver.java
index b8a1c8c..15e726f 100644
--- a/src/com/android/settings/network/MobileDataContentObserver.java
+++ b/src/com/android/settings/network/MobileDataContentObserver.java
@@ -33,9 +33,13 @@
         super(handler);
     }
 
-    public static Uri getObservableUri(int subId) {
+    /**
+     * Return a URI of mobile data(ON vs OFF)
+     */
+    public static Uri getObservableUri(Context context, int subId) {
         Uri uri = Settings.Global.getUriFor(Settings.Global.MOBILE_DATA);
-        if (TelephonyManager.getDefault().getSimCount() != 1) {
+        TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class);
+        if (telephonyManager.getSimCount() != 1) {
             uri = Settings.Global.getUriFor(Settings.Global.MOBILE_DATA + subId);
         }
         return uri;
@@ -54,7 +58,7 @@
     }
 
     public void register(Context context, int subId) {
-        final Uri uri = getObservableUri(subId);
+        final Uri uri = getObservableUri(context, subId);
         context.getContentResolver().registerContentObserver(uri, false, this);
 
     }
diff --git a/src/com/android/settings/network/SubscriptionUtil.java b/src/com/android/settings/network/SubscriptionUtil.java
index 7e355c4..6220d45 100644
--- a/src/com/android/settings/network/SubscriptionUtil.java
+++ b/src/com/android/settings/network/SubscriptionUtil.java
@@ -22,10 +22,12 @@
 import static com.android.internal.util.CollectionUtils.emptyIfNull;
 
 import android.content.Context;
+import android.os.ParcelUuid;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.telephony.UiccSlotInfo;
+import android.text.TextUtils;
 
 import androidx.annotation.VisibleForTesting;
 
@@ -67,6 +69,12 @@
                 slotInfo.getCardStateInfo() == CARD_STATE_INFO_PRESENT;
     }
 
+    /**
+     * Get all of the subscriptions which is available to display to the user.
+     *
+     * @param context {@code Context}
+     * @return list of {@code SubscriptionInfo}
+     */
     public static List<SubscriptionInfo> getAvailableSubscriptions(Context context) {
         if (sAvailableResultsForTesting != null) {
             return sAvailableResultsForTesting;
@@ -74,12 +82,12 @@
         final SubscriptionManager subMgr = context.getSystemService(SubscriptionManager.class);
         final TelephonyManager telMgr = context.getSystemService(TelephonyManager.class);
 
-        List<SubscriptionInfo> subscriptions =
+        final List<SubscriptionInfo> subscriptions =
                 new ArrayList<>(emptyIfNull(subMgr.getSelectableSubscriptionInfoList()));
 
         // Look for inactive but present physical SIMs that are missing from the selectable list.
         final List<UiccSlotInfo> missing = new ArrayList<>();
-        UiccSlotInfo[] slotsInfo =  telMgr.getUiccSlotsInfo();
+        final UiccSlotInfo[] slotsInfo = telMgr.getUiccSlotsInfo();
         for (int i = 0; slotsInfo != null && i < slotsInfo.length; i++) {
             final UiccSlotInfo slotInfo = slotsInfo[i];
             if (isInactiveInsertedPSim(slotInfo)) {
@@ -93,20 +101,164 @@
                 }
             }
         }
-        if (!missing.isEmpty()) {
-            for (SubscriptionInfo info : subMgr.getAllSubscriptionInfoList()) {
-                for (UiccSlotInfo slotInfo : missing) {
-                    if (info.getSimSlotIndex() == slotInfo.getLogicalSlotIdx() &&
-                    info.getCardString().equals(slotInfo.getCardId())) {
-                        subscriptions.add(info);
-                        break;
-                    }
+        if (missing.isEmpty()) {
+            return subscriptions;
+        }
+        for (SubscriptionInfo info : subMgr.getAllSubscriptionInfoList()) {
+            for (UiccSlotInfo slotInfo : missing) {
+                if (info.getSimSlotIndex() == slotInfo.getLogicalSlotIdx()
+                        && info.getCardString().equals(slotInfo.getCardId())) {
+                    subscriptions.add(info);
+                    break;
                 }
             }
         }
         return subscriptions;
     }
 
+    /**
+     * Get subscription which is available to be displayed to the user
+     * per subscription id.
+     *
+     * @param context {@code Context}
+     * @param subscriptionManager The ProxySubscriptionManager for accessing subcription
+     *         information
+     * @param subId The id of subscription to be retrieved
+     * @return {@code SubscriptionInfo} based on the given subscription id. Null of subscription
+     *         is invalid or not allowed to be displayed to the user.
+     */
+    public static SubscriptionInfo getAvailableSubscription(Context context,
+            ProxySubscriptionManager subscriptionManager, int subId) {
+        final SubscriptionInfo subInfo = subscriptionManager.getAccessibleSubscriptionInfo(subId);
+        if (subInfo == null) {
+            return null;
+        }
+
+        final ParcelUuid groupUuid = subInfo.getGroupUuid();
+
+        if (groupUuid != null) {
+            if (isPrimarySubscriptionWithinSameUuid(getUiccSlotsInfo(context), groupUuid,
+                    subscriptionManager.getAccessibleSubscriptionsInfo(), subId)) {
+                return subInfo;
+            }
+            return null;
+        }
+
+        if (subInfo.isEmbedded()) {
+            return subInfo;
+        }
+
+        // Look for physical SIM which presented in slots no mater active or not.
+        final UiccSlotInfo[] slotsInfo = getUiccSlotsInfo(context);
+        if (slotsInfo == null) {
+            return null;
+        }
+        for (UiccSlotInfo slotInfo : slotsInfo) {
+            if ((!slotInfo.getIsEuicc())
+                    && (slotInfo.getCardStateInfo() == CARD_STATE_INFO_PRESENT)
+                    && (slotInfo.getLogicalSlotIdx() == subInfo.getSimSlotIndex())
+                    && TextUtils.equals(slotInfo.getCardId(), subInfo.getCardString())) {
+                return subInfo;
+            }
+        }
+        return null;
+    }
+
+    private static UiccSlotInfo [] getUiccSlotsInfo(Context context) {
+        final TelephonyManager telMgr = context.getSystemService(TelephonyManager.class);
+        return telMgr.getUiccSlotsInfo();
+    }
+
+    private static boolean isPrimarySubscriptionWithinSameUuid(UiccSlotInfo[] slotsInfo,
+            ParcelUuid groupUuid, List<SubscriptionInfo> subscriptions, int subId) {
+        // only interested in subscriptions with this group UUID
+        final ArrayList<SubscriptionInfo> physicalSubInfoList =
+                new ArrayList<SubscriptionInfo>();
+        final ArrayList<SubscriptionInfo> nonOpportunisticSubInfoList =
+                new ArrayList<SubscriptionInfo>();
+        final ArrayList<SubscriptionInfo> activeSlotSubInfoList =
+                new ArrayList<SubscriptionInfo>();
+        final ArrayList<SubscriptionInfo> inactiveSlotSubInfoList =
+                new ArrayList<SubscriptionInfo>();
+        for (SubscriptionInfo subInfo : subscriptions) {
+            if (groupUuid.equals(subInfo.getGroupUuid())) {
+                if (!subInfo.isEmbedded()) {
+                    physicalSubInfoList.add(subInfo);
+                } else  {
+                    if (!subInfo.isOpportunistic()) {
+                        nonOpportunisticSubInfoList.add(subInfo);
+                    }
+                    if (subInfo.getSimSlotIndex()
+                            != SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
+                        activeSlotSubInfoList.add(subInfo);
+                    } else {
+                        inactiveSlotSubInfoList.add(subInfo);
+                    }
+                }
+            }
+        }
+
+        // find any physical SIM which is currently inserted within logical slot
+        // and which is our target subscription
+        if ((slotsInfo != null) && (physicalSubInfoList.size() > 0)) {
+            final SubscriptionInfo subInfo = searchForSubscriptionId(physicalSubInfoList, subId);
+            if (subInfo == null) {
+                return false;
+            }
+            // verify if subscription is inserted within slot
+            for (UiccSlotInfo slotInfo : slotsInfo) {
+                if ((slotInfo != null) && (!slotInfo.getIsEuicc())
+                        && (slotInfo.getCardStateInfo() == CARD_STATE_INFO_PRESENT)
+                        && (slotInfo.getLogicalSlotIdx() == subInfo.getSimSlotIndex())
+                        && TextUtils.equals(slotInfo.getCardId(), subInfo.getCardString())) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        // When all of the eSIM profiles are opprtunistic and no physical SIM,
+        // first opportunistic subscriptions with same group UUID can be primary.
+        if (nonOpportunisticSubInfoList.size() <= 0) {
+            if (physicalSubInfoList.size() > 0) {
+                return false;
+            }
+            if (activeSlotSubInfoList.size() > 0) {
+                return (activeSlotSubInfoList.get(0).getSubscriptionId() == subId);
+            }
+            return (inactiveSlotSubInfoList.get(0).getSubscriptionId() == subId);
+        }
+
+        // Allow non-opportunistic + active eSIM subscription as primary
+        int numberOfActiveNonOpportunisticSubs = 0;
+        boolean isTargetNonOpportunistic = false;
+        for (SubscriptionInfo subInfo : nonOpportunisticSubInfoList) {
+            final boolean isTargetSubInfo = (subInfo.getSubscriptionId() == subId);
+            if (subInfo.getSimSlotIndex() != SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
+                if (isTargetSubInfo) {
+                    return true;
+                }
+                numberOfActiveNonOpportunisticSubs++;
+            } else {
+                isTargetNonOpportunistic |= isTargetSubInfo;
+            }
+        }
+        if (numberOfActiveNonOpportunisticSubs > 0) {
+            return false;
+        }
+        return isTargetNonOpportunistic;
+    }
+
+    private static SubscriptionInfo searchForSubscriptionId(List<SubscriptionInfo> subInfoList,
+            int subscriptionId) {
+        for (SubscriptionInfo subInfo : subInfoList) {
+            if (subInfo.getSubscriptionId() == subscriptionId) {
+                return subInfo;
+            }
+        }
+        return null;
+    }
+
     public static String getDisplayName(SubscriptionInfo info) {
         final CharSequence name = info.getDisplayName();
         if (name != null) {
diff --git a/src/com/android/settings/network/TetherEnabler.java b/src/com/android/settings/network/TetherEnabler.java
new file mode 100644
index 0000000..9106aa1
--- /dev/null
+++ b/src/com/android/settings/network/TetherEnabler.java
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network;
+
+import static android.net.ConnectivityManager.TETHERING_BLUETOOTH;
+import static android.net.ConnectivityManager.TETHERING_USB;
+import static android.net.ConnectivityManager.TETHERING_WIFI;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothPan;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.SharedPreferences;
+import android.net.ConnectivityManager;
+import android.net.wifi.WifiManager;
+import android.os.Handler;
+import android.os.Looper;
+import android.text.TextUtils;
+
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.LifecycleObserver;
+import androidx.lifecycle.OnLifecycleEvent;
+import androidx.preference.PreferenceManager;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.settings.datausage.DataSaverBackend;
+import com.android.settings.widget.SwitchWidgetController;
+
+import java.util.ArrayList;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * TetherEnabler is a helper to manage Tethering switch on/off state. It turns on/off
+ * different types of tethering based on stored values in {@link SharedPreferences} and ensures
+ * tethering state updated by data saver state.
+ */
+
+public final class TetherEnabler implements SwitchWidgetController.OnSwitchChangeListener,
+        DataSaverBackend.Listener, LifecycleObserver {
+    @VisibleForTesting
+    static final String WIFI_TETHER_KEY = "enable_wifi_tethering";
+    @VisibleForTesting
+    static final String USB_TETHER_KEY = "enable_usb_tethering";
+    @VisibleForTesting
+    static final String BLUETOOTH_TETHER_KEY = "enable_bluetooth_tethering";
+
+    private final SwitchWidgetController mSwitchWidgetController;
+    private final WifiManager mWifiManager;
+    private final ConnectivityManager mConnectivityManager;
+
+    private final DataSaverBackend mDataSaverBackend;
+    private boolean mDataSaverEnabled;
+
+    private final Context mContext;
+
+    @VisibleForTesting
+    final ConnectivityManager.OnStartTetheringCallback mOnStartTetheringCallback =
+            new ConnectivityManager.OnStartTetheringCallback() {
+                @Override
+                public void onTetheringFailed() {
+                    super.onTetheringFailed();
+                    mSwitchWidgetController.setChecked(false);
+                    setSwitchWidgetEnabled(true);
+                }
+            };
+    private final AtomicReference<BluetoothPan> mBluetoothPan;
+    private final SharedPreferences mSharedPreferences;
+    private boolean mBluetoothEnableForTether;
+    private final BluetoothAdapter mBluetoothAdapter;
+
+    TetherEnabler(Context context, SwitchWidgetController switchWidgetController,
+            AtomicReference<BluetoothPan> bluetoothPan) {
+        mContext = context;
+        mSwitchWidgetController = switchWidgetController;
+        mDataSaverBackend = new DataSaverBackend(context);
+        mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(mContext);
+        mConnectivityManager =
+                (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+        mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+        mBluetoothPan = bluetoothPan;
+        mDataSaverEnabled = mDataSaverBackend.isDataSaverEnabled();
+    }
+
+    @OnLifecycleEvent(Lifecycle.Event.ON_START)
+    public void onStart() {
+        mDataSaverBackend.addListener(this);
+        mSwitchWidgetController.setListener(this);
+        mSwitchWidgetController.startListening();
+        IntentFilter filter = new IntentFilter(ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
+        filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
+        mContext.registerReceiver(mTetherChangeReceiver, filter);
+        mSwitchWidgetController.setChecked(isTethering());
+        setSwitchWidgetEnabled(true);
+    }
+
+    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
+    public void onStop() {
+        mDataSaverBackend.remListener(this);
+        mSwitchWidgetController.stopListening();
+        mContext.unregisterReceiver(mTetherChangeReceiver);
+    }
+
+    private void setSwitchWidgetEnabled(boolean enabled) {
+        mSwitchWidgetController.setEnabled(enabled && !mDataSaverEnabled);
+    }
+
+    private boolean isTethering() {
+        String[] tethered = mConnectivityManager.getTetheredIfaces();
+        return isTethering(tethered);
+    }
+
+    private boolean isTethering(String[] tethered) {
+        if (tethered != null && tethered.length != 0) {
+            return true;
+        }
+
+        final BluetoothPan pan = mBluetoothPan.get();
+
+        return pan != null && pan.isTetheringOn();
+    }
+
+    @Override
+    public boolean onSwitchToggled(boolean isChecked) {
+        if (isChecked) {
+            startTether();
+        } else {
+            stopTether();
+        }
+        return true;
+    }
+
+    @VisibleForTesting
+    void stopTether() {
+        setSwitchWidgetEnabled(false);
+
+        // Wi-Fi tether is selected by default
+        if (mSharedPreferences.getBoolean(WIFI_TETHER_KEY, true)) {
+            mConnectivityManager.stopTethering(TETHERING_WIFI);
+        }
+
+        // USB tether is not selected by default
+        if (mSharedPreferences.getBoolean(USB_TETHER_KEY, false)) {
+            mConnectivityManager.stopTethering(TETHERING_USB);
+        }
+
+        // Bluetooth tether is not selected by default
+        if (mSharedPreferences.getBoolean(BLUETOOTH_TETHER_KEY, false)) {
+            mConnectivityManager.stopTethering(TETHERING_BLUETOOTH);
+        }
+    }
+
+    @VisibleForTesting
+    void startTether() {
+        setSwitchWidgetEnabled(false);
+
+        // Wi-Fi tether is selected by default
+        if (mSharedPreferences.getBoolean(WIFI_TETHER_KEY, true)) {
+            startTethering(TETHERING_WIFI);
+        }
+
+        // USB tether is not selected by default
+        if (mSharedPreferences.getBoolean(USB_TETHER_KEY, false)) {
+            startTethering(TETHERING_USB);
+        }
+
+        // Bluetooth tether is not selected by default
+        if (mSharedPreferences.getBoolean(BLUETOOTH_TETHER_KEY, false)) {
+            startTethering(TETHERING_BLUETOOTH);
+        }
+    }
+
+    @VisibleForTesting
+    void startTethering(int choice) {
+        if (choice == TETHERING_BLUETOOTH) {
+            // Turn on Bluetooth first.
+            if (mBluetoothAdapter.getState() == BluetoothAdapter.STATE_OFF) {
+                mBluetoothEnableForTether = true;
+                mBluetoothAdapter.enable();
+                return;
+            }
+        } else if (choice == TETHERING_WIFI && mWifiManager.isWifiApEnabled()) {
+            return;
+        }
+
+
+        mConnectivityManager.startTethering(choice, true /* showProvisioningUi */,
+                mOnStartTetheringCallback, new Handler(Looper.getMainLooper()));
+    }
+
+    private final BroadcastReceiver mTetherChangeReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            if (TextUtils.equals(ConnectivityManager.ACTION_TETHER_STATE_CHANGED, action)) {
+                ArrayList<String> active = intent.getStringArrayListExtra(
+                        ConnectivityManager.EXTRA_ACTIVE_TETHER);
+                mSwitchWidgetController.setChecked(
+                        isTethering(active.toArray(new String[active.size()])));
+                setSwitchWidgetEnabled(true);
+            } else if (TextUtils.equals(BluetoothAdapter.ACTION_STATE_CHANGED, action)) {
+                if (mBluetoothEnableForTether) {
+                    switch (intent
+                            .getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR)) {
+                        case BluetoothAdapter.STATE_ON:
+                            startTethering(TETHERING_BLUETOOTH);
+                            mBluetoothEnableForTether = false;
+                            break;
+
+                        case BluetoothAdapter.STATE_OFF:
+                        case BluetoothAdapter.ERROR:
+                            mBluetoothEnableForTether = false;
+                            break;
+
+                        default:
+                            // ignore transition states
+                    }
+                }
+            }
+        }
+    };
+
+    @Override
+    public void onDataSaverChanged(boolean isDataSaving) {
+        mDataSaverEnabled = isDataSaving;
+        setSwitchWidgetEnabled(!isDataSaving);
+    }
+
+    @Override
+    public void onWhitelistStatusChanged(int uid, boolean isWhitelisted) {
+        // we don't care, since we just want to read the value
+    }
+
+    @Override
+    public void onBlacklistStatusChanged(int uid, boolean isBlacklisted) {
+        // we don't care, since we just want to read the value
+    }
+}
diff --git a/src/com/android/settings/network/telephony/CallsDefaultSubscriptionController.java b/src/com/android/settings/network/telephony/CallsDefaultSubscriptionController.java
index 008a3e4..2348f70 100644
--- a/src/com/android/settings/network/telephony/CallsDefaultSubscriptionController.java
+++ b/src/com/android/settings/network/telephony/CallsDefaultSubscriptionController.java
@@ -38,6 +38,6 @@
 
     @Override
     protected void setDefaultSubscription(int subscriptionId) {
-        mManager.setDefaultVoiceSubId(subscriptionId);
+        mManager.setDefaultVoiceSubscriptionId(subscriptionId);
     }
 }
diff --git a/src/com/android/settings/network/telephony/MobileDataSlice.java b/src/com/android/settings/network/telephony/MobileDataSlice.java
index 152028c..c70ae1a 100644
--- a/src/com/android/settings/network/telephony/MobileDataSlice.java
+++ b/src/com/android/settings/network/telephony/MobileDataSlice.java
@@ -252,7 +252,7 @@
             }
 
             public void register(Context context, int subId) {
-                final Uri uri = MobileDataContentObserver.getObservableUri(subId);
+                final Uri uri = MobileDataContentObserver.getObservableUri(context, subId);
                 context.getContentResolver().registerContentObserver(uri, false, this);
             }
 
diff --git a/src/com/android/settings/network/telephony/MobileNetworkActivity.java b/src/com/android/settings/network/telephony/MobileNetworkActivity.java
index 9eb9e71..9dd6ddd 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkActivity.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkActivity.java
@@ -35,6 +35,7 @@
 import com.android.settings.R;
 import com.android.settings.core.SettingsBaseActivity;
 import com.android.settings.network.ProxySubscriptionManager;
+import com.android.settings.network.SubscriptionUtil;
 
 import java.util.List;
 
@@ -161,8 +162,8 @@
     @VisibleForTesting
     SubscriptionInfo getSubscription() {
         if (mCurSubscriptionId != SUB_ID_NULL) {
-            final SubscriptionInfo subInfo =
-                    mProxySubscriptionMgr.getActiveSubscriptionInfo(mCurSubscriptionId);
+            final SubscriptionInfo subInfo = SubscriptionUtil.getAvailableSubscription(
+                    this, mProxySubscriptionMgr, mCurSubscriptionId);
             if (subInfo != null) {
                 return subInfo;
             }
diff --git a/src/com/android/settings/network/telephony/MobileNetworkSettings.java b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
index 2c3cd3a..90d8d4e 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkSettings.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
@@ -34,7 +34,6 @@
 import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
 
-import com.android.internal.telephony.TelephonyIntents;
 import com.android.settings.R;
 import com.android.settings.dashboard.RestrictedDashboardFragment;
 import com.android.settings.datausage.BillingCyclePreferenceController;
@@ -98,7 +97,7 @@
                 || TextUtils.equals(key, BUTTON_CDMA_SUBSCRIPTION_KEY)) {
             if (mTelephonyManager.getEmergencyCallbackMode()) {
                 startActivityForResult(
-                        new Intent(TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS, null),
+                        new Intent(TelephonyManager.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS, null),
                         REQUEST_CODE_EXIT_ECM);
                 mClickedPrefKey = key;
             }
diff --git a/src/com/android/settings/password/BiometricFragment.java b/src/com/android/settings/password/BiometricFragment.java
index 9898719..fe0740b 100644
--- a/src/com/android/settings/password/BiometricFragment.java
+++ b/src/com/android/settings/password/BiometricFragment.java
@@ -16,8 +16,6 @@
 
 package com.android.settings.password;
 
-import android.app.Activity;
-import android.app.admin.DevicePolicyManager;
 import android.app.settings.SettingsEnums;
 import android.content.DialogInterface;
 import android.hardware.biometrics.BiometricConstants;
@@ -26,16 +24,10 @@
 import android.hardware.biometrics.BiometricPrompt.AuthenticationResult;
 import android.os.Bundle;
 import android.os.CancellationSignal;
-import android.os.Handler;
-import android.os.Looper;
-import android.util.Log;
 
 import androidx.annotation.NonNull;
 
-import com.android.internal.widget.LockPatternUtils;
-import com.android.settings.R;
 import com.android.settings.core.InstrumentedFragment;
-import com.android.settings.overlay.FeatureFactory;
 
 import java.util.concurrent.Executor;
 
@@ -139,7 +131,9 @@
                 .setSubtitle(mBundle.getString(BiometricPrompt.KEY_SUBTITLE))
                 .setDescription(mBundle.getString(BiometricPrompt.KEY_DESCRIPTION))
                 .setConfirmationRequired(
-                        mBundle.getBoolean(BiometricPrompt.KEY_REQUIRE_CONFIRMATION, true));
+                        mBundle.getBoolean(BiometricPrompt.KEY_REQUIRE_CONFIRMATION, true))
+                .setDisallowBiometricsIfPolicyExists(mBundle.getBoolean(
+                        BiometricPrompt.EXTRA_DISALLOW_BIOMETRICS_IF_POLICY_EXISTS, false));
 
         mBiometricPrompt = builder.build();
         mCancellationSignal = new CancellationSignal();
diff --git a/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java b/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
index bf8c571..912b600 100644
--- a/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
+++ b/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
@@ -25,7 +25,6 @@
 import android.app.trust.TrustManager;
 import android.content.Context;
 import android.content.Intent;
-import android.content.pm.PackageManager;
 import android.hardware.biometrics.BiometricConstants;
 import android.hardware.biometrics.BiometricManager;
 import android.hardware.biometrics.BiometricPrompt;
@@ -54,10 +53,11 @@
     public static final String TAG = ConfirmDeviceCredentialActivity.class.getSimpleName();
 
     /**
-     * If the intent is sent from {@link com.android.systemui.keyguard.WorkLockActivity} then
-     * check for device policy management flags.
+     * If the intent is sent from {@link com.android.systemui.keyguard.WorkLockActivityController}
+     * then check for device policy management flags.
      */
-    public static final String EXTRA_FROM_WORK_LOCK_ACTIVITY = "from_work_lock_activity";
+    public static final String EXTRA_FROM_WORK_LOCK_ACTIVITY_CONTROLLER =
+            "from_work_lock_activity_controller";
 
     // The normal flow that apps go through
     private static final int CREDENTIAL_NORMAL = 1;
@@ -98,7 +98,7 @@
     private ChooseLockSettingsHelper mChooseLockSettingsHelper;
     private Handler mHandler = new Handler(Looper.getMainLooper());
     private Context mContext;
-    private boolean mFromWorkLockActivity;
+    private boolean mCheckDevicePolicyManager;
 
     private String mTitle;
     private String mDetails;
@@ -159,7 +159,8 @@
 
         Intent intent = getIntent();
         mContext = this;
-        mFromWorkLockActivity = intent.getBooleanExtra(EXTRA_FROM_WORK_LOCK_ACTIVITY, false);
+        mCheckDevicePolicyManager = intent
+                .getBooleanExtra(BiometricPrompt.EXTRA_DISALLOW_BIOMETRICS_IF_POLICY_EXISTS, false);
         mTitle = intent.getStringExtra(KeyguardManager.EXTRA_TITLE);
         mDetails = intent.getStringExtra(KeyguardManager.EXTRA_DESCRIPTION);
         String alternateButton = intent.getStringExtra(
@@ -189,6 +190,8 @@
         mDetails = bpBundle.getString(BiometricPrompt.KEY_SUBTITLE);
         bpBundle.putString(BiometricPrompt.KEY_TITLE, mTitle);
         bpBundle.putString(BiometricPrompt.KEY_DESCRIPTION, mDetails);
+        bpBundle.putBoolean(BiometricPrompt.EXTRA_DISALLOW_BIOMETRICS_IF_POLICY_EXISTS,
+                mCheckDevicePolicyManager);
 
         boolean launchedBiometric = false;
         boolean launchedCDC = false;
@@ -201,7 +204,7 @@
         } else if (isManagedProfile && isInternalActivity()
                 && !lockPatternUtils.isSeparateProfileChallengeEnabled(mUserId)) {
             mCredentialMode = CREDENTIAL_MANAGED;
-            if (mFromWorkLockActivity && isBiometricAllowed(effectiveUserId, mUserId)) {
+            if (isBiometricAllowed(effectiveUserId, mUserId)) {
                 showBiometricPrompt(bpBundle);
                 launchedBiometric = true;
             } else {
@@ -267,42 +270,9 @@
                 || !mUserManager.isUserUnlocked(mUserId);
     }
 
-    /**
-     * TODO: Pass a list of disabled features to an internal BiometricPrompt API, so we can
-     * potentially show different modalities on multi-auth devices.
-     *
-     * @param effectiveUserId
-     * @return false if their exists one biometric on the device which is not disabled by the
-     * policy manager.
-     */
-    private boolean isBiometricDisabledByAdmin(int effectiveUserId) {
-        final int disabledFeatures =
-            mDevicePolicyManager.getKeyguardDisabledFeatures(null, effectiveUserId);
-
-        final PackageManager pm = mContext.getPackageManager();
-        if (pm.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)
-            && (disabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT) == 0) {
-            Log.d(TAG,"Fingerprint enabled & allowed by device policy manager");
-            return false;
-        }
-        if (pm.hasSystemFeature(PackageManager.FEATURE_IRIS)
-            && (disabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_IRIS) == 0) {
-            Log.d(TAG,"Iris enabled & allowed by device policy manager");
-            return false;
-        }
-        if (pm.hasSystemFeature(PackageManager.FEATURE_FACE)
-            && (disabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_FACE) == 0) {
-            Log.d(TAG,"Face enabled & allowed by device policy manager");
-            return false;
-        }
-
-        return true;
-    }
-
     private boolean isBiometricAllowed(int effectiveUserId, int realUserId) {
-        return !isStrongAuthRequired(effectiveUserId)
-                && !isBiometricDisabledByAdmin(effectiveUserId)
-                && !mLockPatternUtils.hasPendingEscrowToken(realUserId);
+        return !isStrongAuthRequired(effectiveUserId) && !mLockPatternUtils
+                .hasPendingEscrowToken(realUserId);
     }
 
     private void showBiometricPrompt(Bundle bundle) {
@@ -346,7 +316,7 @@
                     .launchConfirmationActivityWithExternalAndChallenge(
                             0 /* request code */, null /* title */, mTitle, mDetails,
                             true /* isExternal */, 0L /* challenge */, mUserId);
-        } else if (mCredentialMode == CREDENTIAL_NORMAL){
+        } else if (mCredentialMode == CREDENTIAL_NORMAL) {
             launched = mChooseLockSettingsHelper.launchConfirmationActivity(
                     0 /* request code */, null /* title */,
                     mTitle, mDetails, false /* returnCredentials */, true /* isExternal */,
diff --git a/src/com/android/settings/slices/SliceBuilderUtils.java b/src/com/android/settings/slices/SliceBuilderUtils.java
index 59a1768..2208c97 100644
--- a/src/com/android/settings/slices/SliceBuilderUtils.java
+++ b/src/com/android/settings/slices/SliceBuilderUtils.java
@@ -215,6 +215,8 @@
         searchDestination.putExtra(SettingsActivity.EXTRA_FRAGMENT_ARG_KEY, key)
                 .setAction("com.android.settings.SEARCH_RESULT_TRAMPOLINE")
                 .setComponent(null);
+        searchDestination.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
+
         return searchDestination;
     }
 
diff --git a/src/com/android/settings/wifi/WifiEntryShell.java b/src/com/android/settings/wifi/WifiEntryShell.java
new file mode 100644
index 0000000..6b6fef8
--- /dev/null
+++ b/src/com/android/settings/wifi/WifiEntryShell.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.wifi;
+
+import android.net.NetworkInfo.DetailedState;
+
+import com.android.wifitrackerlib.WifiEntry;
+
+/**
+ * {@link WifiEntry is working in progess, many methods are not available, this class is to group
+ * all the unavalable {@link AccessPoint} methods & constants.
+ *
+ * TODO(b/143326832): Replace all methods & constants with WifiEntry version when it's available.
+ * TODO(b/143326832): How about AccessPoint#getSettingsSummary(boolean convertSavedAsDisconnected)?
+ */
+public class WifiEntryShell {
+    public WifiEntryShell(){};
+
+    /**
+     * Lower bound on the 2.4 GHz (802.11b/g/n) WLAN channels
+     */
+    public static final int LOWER_FREQ_24GHZ = 2400;
+
+    /**
+     * Upper bound on the 2.4 GHz (802.11b/g/n) WLAN channels
+     */
+    public static final int HIGHER_FREQ_24GHZ = 2500;
+
+    /**
+     * Lower bound on the 5.0 GHz (802.11a/h/j/n/ac) WLAN channels
+     */
+    public static final int LOWER_FREQ_5GHZ = 4900;
+
+    /**
+     * Upper bound on the 5.0 GHz (802.11a/h/j/n/ac) WLAN channels
+     */
+    public static final int HIGHER_FREQ_5GHZ = 5900;
+
+    /**
+     * Mapping of the corresponding {@link WifiConfiguration} field
+     */
+    public static int getNetworkId(WifiEntry wifiEntry) {
+        return 0;
+    }
+
+    /**
+     * Mapping of the corresponding {@link WifiConfiguration} field
+     */
+    public static boolean hiddenSSID(WifiEntry wifiEntry) {
+        return false;
+    }
+
+    /**
+     * Mapping of the corresponding {@link WifiDetailPreferenceController} method
+     */
+    public static boolean canModifyNetwork(WifiEntry wifiEntry) {
+        return false;
+    }
+
+    /**
+     * Mapping of the corresponding {@link AccessPoint} method
+     */
+    public static String getSecurityString(WifiEntry wifiEntry, boolean concise) {
+        return "None";
+    }
+
+    /**
+     * Mapping of the corresponding {@link AccessPoint} method
+     */
+    public static DetailedState getDetailedState(WifiEntry wifiEntry) {
+        return null;
+    }
+
+    // Passpoint methods
+
+    /**
+     * Mapping of the corresponding {@link AccessPoint} method
+     */
+    public static boolean isPasspoint(WifiEntry wifiEntry) {
+        return false;
+    }
+
+    /**
+     * Mapping of the corresponding {@link AccessPoint} method
+     */
+    public static boolean isExpired(WifiEntry wifiEntry) {
+        return false;
+    }
+
+    /**
+     * Mapping of the corresponding {@link AccessPoint} method
+     */
+    public static boolean isPasspointConfigurationR1(WifiEntry wifiEntry) {
+        return false;
+    }
+
+    /**
+     * Mapping of the corresponding {@link AccessPoint} method
+     */
+    public static boolean isPasspointConfigurationOsuProvisioned(WifiEntry wifiEntry) {
+        return false;
+    }
+
+    /**
+     * Mapping of the corresponding {@link AccessPoint} method
+     */
+    public static boolean isOsuProvider(WifiEntry wifiEntry) {
+        return false;
+    }
+
+    /**
+     * Mapping of the corresponding {@link AccessPoint} method
+     */
+    public static String getPasspointFqdn(WifiEntry wifiEntry) {
+        return "Fake passpoint FQDN";
+    }
+}
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index 5369851..eb02833 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -68,7 +68,6 @@
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.widget.SwitchBarController;
 import com.android.settings.wifi.details.WifiNetworkDetailsFragment;
-import com.android.settings.wifi.details2.WifiNetworkDetailsFragment2;
 import com.android.settings.wifi.dpp.WifiDppUtils;
 import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.RestrictedLockUtilsInternal;
@@ -952,21 +951,12 @@
                         ? accessPoint.getTitle()
                         : context.getText(R.string.pref_title_network_details);
 
-        if (FeatureFlagUtils.isEnabled(context, FeatureFlagUtils.SETTINGS_WIFITRACKER2)) {
-            new SubSettingLauncher(getContext())
-                    .setTitleText(title)
-                    .setDestination(WifiNetworkDetailsFragment2.class.getName())
-                    .setArguments(pref.getExtras())
-                    .setSourceMetricsCategory(getMetricsCategory())
-                    .launch();
-        } else {
-            new SubSettingLauncher(getContext())
-                    .setTitleText(title)
-                    .setDestination(WifiNetworkDetailsFragment.class.getName())
-                    .setArguments(pref.getExtras())
-                    .setSourceMetricsCategory(getMetricsCategory())
-                    .launch();
-        }
+        new SubSettingLauncher(getContext())
+                .setTitleText(title)
+                .setDestination(WifiNetworkDetailsFragment.class.getName())
+                .setArguments(pref.getExtras())
+                .setSourceMetricsCategory(getMetricsCategory())
+                .launch();
     }
 
     private Network getCurrentWifiNetwork() {
diff --git a/src/com/android/settings/wifi/WifiSettings2.java b/src/com/android/settings/wifi/WifiSettings2.java
index df7950a..ac9374f 100644
--- a/src/com/android/settings/wifi/WifiSettings2.java
+++ b/src/com/android/settings/wifi/WifiSettings2.java
@@ -38,6 +38,7 @@
 import android.os.SimpleClock;
 import android.os.SystemClock;
 import android.provider.Settings;
+import android.util.FeatureFlagUtils;
 import android.util.Log;
 import android.view.ContextMenu;
 import android.view.ContextMenu.ContextMenuInfo;
@@ -55,12 +56,14 @@
 import com.android.settings.R;
 import com.android.settings.RestrictedSettingsFragment;
 import com.android.settings.SettingsActivity;
+import com.android.settings.core.FeatureFlags;
 import com.android.settings.core.SubSettingLauncher;
 import com.android.settings.datausage.DataUsagePreference;
 import com.android.settings.datausage.DataUsageUtils;
 import com.android.settings.location.ScanningSettings;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.widget.SwitchBarController;
+import com.android.settings.wifi.details2.WifiNetworkDetailsFragment2;
 import com.android.settingslib.search.Indexable;
 import com.android.settingslib.search.SearchIndexable;
 import com.android.settingslib.search.SearchIndexableRaw;
@@ -509,6 +512,14 @@
                 pref.setKey(connectedEntry.getKey());
                 pref.refresh();
                 mConnectedWifiEntryPreferenceCategory.addPreference(pref);
+                pref.setOnPreferenceClickListener(preference -> {
+                    if (connectedEntry.canSignIn()) {
+                        connectedEntry.signIn();
+                    } else {
+                        launchNetworkDetailsFragment(pref);
+                    }
+                    return true;
+                });
             }
         } else {
             mConnectedWifiEntryPreferenceCategory.removeAll();
@@ -554,6 +565,25 @@
         setAdditionalSettingsSummaries();
     }
 
+    private void launchNetworkDetailsFragment(LongPressWifiEntryPreference pref) {
+        final WifiEntry wifiEntry = pref.getWifiEntry();
+        final Context context = getContext();
+        final CharSequence title =
+                FeatureFlagUtils.isEnabled(context, FeatureFlags.WIFI_DETAILS_DATAUSAGE_HEADER)
+                        ? wifiEntry.getTitle()
+                        : context.getText(R.string.pref_title_network_details);
+
+        final Bundle bundle = new Bundle();
+        bundle.putString(WifiNetworkDetailsFragment2.KEY_CHOSEN_WIFIENTRY_KEY, wifiEntry.getKey());
+
+        new SubSettingLauncher(context)
+                .setTitleText(title)
+                .setDestination(WifiNetworkDetailsFragment2.class.getName())
+                .setArguments(bundle)
+                .setSourceMetricsCategory(getMetricsCategory())
+                .launch();
+    }
+
     private LongPressWifiEntryPreference createLongPressWifiEntryPreference(WifiEntry wifiEntry) {
         return new LongPressWifiEntryPreference(getPrefContext(), wifiEntry, this);
     }
diff --git a/src/com/android/settings/wifi/addappnetworks/AddAppNetworksFragment.java b/src/com/android/settings/wifi/addappnetworks/AddAppNetworksFragment.java
index 93f73db..80e14dc 100644
--- a/src/com/android/settings/wifi/addappnetworks/AddAppNetworksFragment.java
+++ b/src/com/android/settings/wifi/addappnetworks/AddAppNetworksFragment.java
@@ -164,7 +164,6 @@
         return inflater.inflate(R.layout.wifi_add_app_networks, container, false);
     }
 
-    // TODO: Makesure function work correctly after rotate.
     @Override
     public void onViewCreated(View view, Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
@@ -585,8 +584,7 @@
 
     @Override
     public int getMetricsCategory() {
-        // TODO(b/144891278): Need to define a new metric for this page, use the WIFI item first.
-        return SettingsEnums.WIFI;
+        return SettingsEnums.PANEL_ADD_WIFI_NETWORKS;
     }
 
     private void showSaveStatusByState(int status) {
diff --git a/src/com/android/settings/wifi/details2/AddDevicePreferenceController2.java b/src/com/android/settings/wifi/details2/AddDevicePreferenceController2.java
index de831b7..3a50107 100644
--- a/src/com/android/settings/wifi/details2/AddDevicePreferenceController2.java
+++ b/src/com/android/settings/wifi/details2/AddDevicePreferenceController2.java
@@ -25,7 +25,7 @@
 
 import com.android.settings.core.BasePreferenceController;
 import com.android.settings.wifi.dpp.WifiDppUtils;
-import com.android.settingslib.wifi.AccessPoint;
+import com.android.wifitrackerlib.WifiEntry;
 
 /**
  * {@link BasePreferenceController} that launches Wi-Fi Easy Connect configurator flow
@@ -36,7 +36,7 @@
 
     private static final String KEY_ADD_DEVICE = "add_device_to_network";
 
-    private AccessPoint mAccessPoint;
+    private WifiEntry mWifiEntry;
     private WifiManager mWifiManager;
 
     public AddDevicePreferenceController2(Context context) {
@@ -45,18 +45,13 @@
         mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
     }
 
-    /**
-     * Initiate with an {@link AccessPoint}.
-     */
-    public AddDevicePreferenceController2 init(AccessPoint accessPoint) {
-        mAccessPoint = accessPoint;
-
-        return this;
+    public void setWifiEntry(WifiEntry wifiEntry) {
+        mWifiEntry = wifiEntry;
     }
 
     @Override
     public int getAvailabilityStatus() {
-        if (WifiDppUtils.isSupportConfiguratorQrCodeScanner(mContext, mAccessPoint)) {
+        if (WifiDppUtils.isSupportConfiguratorQrCodeScanner(mContext, mWifiEntry)) {
             return AVAILABLE;
         } else {
             return CONDITIONALLY_UNAVAILABLE;
@@ -75,7 +70,7 @@
 
     private void launchWifiDppConfiguratorQrCodeScanner() {
         final Intent intent = WifiDppUtils.getConfiguratorQrCodeScannerIntentOrNull(mContext,
-                mWifiManager, mAccessPoint);
+                mWifiManager, mWifiEntry);
 
         if (intent == null) {
             Log.e(TAG, "Launch Wi-Fi QR code scanner with a wrong Wi-Fi network!");
diff --git a/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java b/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java
index 1d6e457..f94ca9d 100644
--- a/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java
+++ b/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java
@@ -23,10 +23,8 @@
 import android.app.Activity;
 import android.app.AlertDialog;
 import android.app.settings.SettingsEnums;
-import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
-import android.content.IntentFilter;
 import android.graphics.Bitmap;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
@@ -41,10 +39,8 @@
 import android.net.NetworkRequest;
 import android.net.NetworkUtils;
 import android.net.RouteInfo;
-import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
-import android.os.CountDownTimer;
 import android.os.Handler;
 import android.text.TextUtils;
 import android.util.FeatureFlagUtils;
@@ -67,7 +63,7 @@
 import com.android.settings.widget.EntityHeaderController;
 import com.android.settings.wifi.WifiDialog;
 import com.android.settings.wifi.WifiDialog.WifiDialogListener;
-import com.android.settings.wifi.WifiUtils;
+import com.android.settings.wifi.WifiEntryShell;
 import com.android.settings.wifi.dpp.WifiDppUtils;
 import com.android.settingslib.core.AbstractPreferenceController;
 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
@@ -77,15 +73,18 @@
 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;
-import com.android.settingslib.wifi.WifiTracker;
-import com.android.settingslib.wifi.WifiTrackerFactory;
+import com.android.wifitrackerlib.WifiEntry;
+import com.android.wifitrackerlib.WifiEntry.ConnectedInfo;
+import com.android.wifitrackerlib.WifiEntry.WifiEntryCallback;
+import com.android.wifitrackerlib.WifiEntry.WifiEntryCallback.ConnectStatus;
+import com.android.wifitrackerlib.WifiEntry.WifiEntryCallback.DisconnectStatus;
+import com.android.wifitrackerlib.WifiEntry.WifiEntryCallback.ForgetStatus;
+import com.android.wifitrackerlib.WifiEntry.WifiEntryCallback.SignInStatus;
 
 import java.net.Inet4Address;
 import java.net.Inet6Address;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
-import java.time.Duration;
 import java.util.StringJoiner;
 import java.util.stream.Collectors;
 
@@ -95,7 +94,7 @@
  */
 public class WifiDetailPreferenceController2 extends AbstractPreferenceController
         implements PreferenceControllerMixin, WifiDialogListener, LifecycleObserver, OnPause,
-        OnResume {
+        OnResume, WifiEntryCallback {
 
     private static final String TAG = "WifiDetailsPrefCtrl2";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -133,21 +132,7 @@
     @VisibleForTesting
     static final String KEY_IPV6_ADDRESSES_PREF = "ipv6_addresses";
 
-    private static final int STATE_NONE = 1;
-    private static final int STATE_ENABLE_WIFI = 2;
-    private static final int STATE_ENABLE_WIFI_FAILED = 3;
-    private static final int STATE_CONNECTING = 4;
-    private static final int STATE_CONNECTED = 5;
-    private static final int STATE_FAILED = 6;
-    private static final int STATE_NOT_IN_RANGE = 7;
-    private static final int STATE_DISCONNECTED = 8;
-    private static final long TIMEOUT = Duration.ofSeconds(10).toMillis();
-
-    // Be static to avoid too much object not be reset.
-    @VisibleForTesting
-    static CountDownTimer sTimer;
-
-    private AccessPoint mAccessPoint;
+    private final WifiEntry mWifiEntry;
     private final ConnectivityManager mConnectivityManager;
     private final PreferenceFragmentCompat mFragment;
     private final Handler mHandler;
@@ -157,16 +142,9 @@
     private NetworkCapabilities mNetworkCapabilities;
     private int mRssiSignalLevel = -1;
     private String[] mSignalStr;
-    private WifiConfiguration mWifiConfig;
     private WifiInfo mWifiInfo;
     private final WifiManager mWifiManager;
-    private final WifiTracker mWifiTracker;
     private final MetricsFeatureProvider mMetricsFeatureProvider;
-    private boolean mIsOutOfRange;
-    private boolean mIsEphemeral;
-    private boolean mConnected;
-    private int mConnectingState;
-    private WifiManager.ActionListener mConnectListener;
 
     // UI elements - in order of appearance
     private ActionButtonsPreference mButtonsPref;
@@ -189,36 +167,6 @@
     WifiDataUsageSummaryPreferenceController mSummaryHeaderController;
 
     private final IconInjector mIconInjector;
-    private final IntentFilter mFilter;
-
-    // Passpoint information - cache it in case of losing these information after
-    // updateAccessPointFromScannedList(). For R2, we should update these data from
-    // WifiManager#getPasspointConfigurations() after users manage the passpoint profile.
-    private boolean mIsExpired;
-    private boolean mIsPasspointConfigurationR1;
-
-    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            switch (intent.getAction()) {
-                case WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION:
-                    if (!intent.getBooleanExtra(WifiManager.EXTRA_MULTIPLE_NETWORKS_CHANGED,
-                            false /* defaultValue */)) {
-                        // only one network changed
-                        WifiConfiguration wifiConfiguration = intent
-                                .getParcelableExtra(WifiManager.EXTRA_WIFI_CONFIGURATION);
-                        if (mAccessPoint.matches(wifiConfiguration)) {
-                            mWifiConfig = wifiConfiguration;
-                        }
-                    }
-                    // fall through
-                case WifiManager.NETWORK_STATE_CHANGED_ACTION:
-                case WifiManager.RSSI_CHANGED_ACTION:
-                    refreshPage();
-                    break;
-            }
-        }
-    };
 
     private final NetworkRequest mNetworkRequest = new NetworkRequest.Builder()
             .clearCapabilities().addTransportType(TRANSPORT_WIFI).build();
@@ -265,7 +213,8 @@
                         || hasCapabilityChanged(nc, NET_CAPABILITY_VALIDATED)
                         || hasCapabilityChanged(nc, NET_CAPABILITY_CAPTIVE_PORTAL)
                         || hasCapabilityChanged(nc, NET_CAPABILITY_PARTIAL_CONNECTIVITY)) {
-                    mAccessPoint.update(mWifiConfig, mWifiInfo, mNetworkInfo);
+                    // TODO(b/143326832): What to do with WifiEntry?
+                    // mAccessPoint.update(mWifiConfig, mWifiInfo, mNetworkInfo);
                     refreshEntityHeader();
                 }
                 mNetworkCapabilities = nc;
@@ -277,45 +226,20 @@
         @Override
         public void onLost(Network network) {
             // Ephemeral network not a saved network, leave detail page once disconnected
-            if (mIsEphemeral && network.equals(mNetwork)) {
-                exitActivity();
+            if (!mWifiEntry.isSaved() && network.equals(mNetwork)) {
+                if (DEBUG) {
+                    Log.d(TAG, "OnLost and exit WifiNetworkDetailsPage");
+                }
+                mFragment.getActivity().finish();
             }
         }
     };
 
-    @VisibleForTesting
-    final WifiTracker.WifiListener mWifiListener = new WifiTracker.WifiListener() {
-        /** Called when the state of Wifi has changed. */
-        public void onWifiStateChanged(int state) {
-            Log.d(TAG, "onWifiStateChanged(" + state + ")");
-            if (mConnectingState == STATE_ENABLE_WIFI && state == WifiManager.WIFI_STATE_ENABLED) {
-                updateConnectingState(STATE_CONNECTING);
-            } else if (mConnectingState != STATE_NONE && state == WifiManager.WIFI_STATE_DISABLED) {
-                // update as disconnected once Wi-Fi disabled since may not received
-                // onConnectedChanged for this case.
-                updateConnectingState(STATE_DISCONNECTED);
-            }
-        }
-
-        /** Called when the connection state of wifi has changed. */
-        public void onConnectedChanged() {
-            refreshPage();
-        }
-
-        /**
-         * Called to indicate the list of AccessPoints has been updated and
-         * {@link WifiTracker#getAccessPoints()} should be called to get the updated list.
-         */
-        public void onAccessPointsChanged() {
-            refreshPage();
-        }
-    };
-
     /**
      * To get an instance of {@link WifiDetailPreferenceController2}
      */
     public static WifiDetailPreferenceController2 newInstance(
-            AccessPoint accessPoint,
+            WifiEntry wifiEntry,
             ConnectivityManager connectivityManager,
             Context context,
             PreferenceFragmentCompat fragment,
@@ -324,13 +248,13 @@
             WifiManager wifiManager,
             MetricsFeatureProvider metricsFeatureProvider) {
         return new WifiDetailPreferenceController2(
-                accessPoint, connectivityManager, context, fragment, handler, lifecycle,
+                wifiEntry, connectivityManager, context, fragment, handler, lifecycle,
                 wifiManager, metricsFeatureProvider, new IconInjector(context));
     }
 
     @VisibleForTesting
         /* package */ WifiDetailPreferenceController2(
-            AccessPoint accessPoint,
+            WifiEntry wifiEntry,
             ConnectivityManager connectivityManager,
             Context context,
             PreferenceFragmentCompat fragment,
@@ -341,49 +265,18 @@
             IconInjector injector) {
         super(context);
 
-        mAccessPoint = accessPoint;
+        mWifiEntry = wifiEntry;
+        mWifiEntry.setListener(this);
         mConnectivityManager = connectivityManager;
         mFragment = fragment;
         mHandler = handler;
         mSignalStr = context.getResources().getStringArray(R.array.wifi_signal);
-        mWifiConfig = accessPoint.getConfig();
         mWifiManager = wifiManager;
         mMetricsFeatureProvider = metricsFeatureProvider;
         mIconInjector = injector;
 
-        mFilter = new IntentFilter();
-        mFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
-        mFilter.addAction(WifiManager.RSSI_CHANGED_ACTION);
-        mFilter.addAction(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION);
-
         mLifecycle = lifecycle;
         lifecycle.addObserver(this);
-
-        mWifiTracker = WifiTrackerFactory.create(
-                mFragment.getActivity(),
-                mWifiListener,
-                mLifecycle,
-                true /*includeSaved*/,
-                true /*includeScans*/);
-        mConnected = mAccessPoint.isActive();
-        // When lost the network connection, WifiInfo/NetworkInfo will be clear. So causes we
-        // could not check if the AccessPoint is ephemeral. Need to cache it in first.
-        mIsEphemeral = mAccessPoint.isEphemeral();
-        mConnectingState = STATE_NONE;
-        mConnectListener = new WifiManager.ActionListener() {
-            @Override
-            public void onSuccess() {
-                // Do nothing
-            }
-
-            @Override
-            public void onFailure(int reason) {
-                updateConnectingState(STATE_FAILED);
-            }
-        };
-
-        mIsExpired = mAccessPoint.isExpired();
-        mIsPasspointConfigurationR1 = mAccessPoint.isPasspointConfigurationR1();
     }
 
     @Override
@@ -404,7 +297,8 @@
         setupEntityHeader(screen);
 
         mButtonsPref = ((ActionButtonsPreference) screen.findPreference(KEY_BUTTONS_PREF))
-                .setButton1Text(R.string.forget)
+                .setButton1Text(!mWifiEntry.isSaved()
+                        ? R.string.wifi_disconnect_button_text : R.string.forget)
                 .setButton1Icon(R.drawable.ic_settings_delete)
                 .setButton1OnClickListener(view -> forgetNetwork())
                 .setButton2Text(R.string.wifi_sign_in_button_text)
@@ -418,11 +312,6 @@
                 .setButton4Icon(R.drawable.ic_qrcode_24dp)
                 .setButton4OnClickListener(view -> shareNetwork());
 
-        if (isPasspointConfigurationR1Expired()) {
-            // Hide Connect button.
-            mButtonsPref.setButton3Visible(false);
-        }
-
         mSignalStrengthPref = screen.findPreference(KEY_SIGNAL_STRENGTH_PREF);
         mTxLinkSpeedPref = screen.findPreference(KEY_TX_LINK_SPEED);
         mRxLinkSpeedPref = screen.findPreference(KEY_RX_LINK_SPEED);
@@ -439,7 +328,7 @@
         mIpv6Category = screen.findPreference(KEY_IPV6_CATEGORY);
         mIpv6AddressPref = screen.findPreference(KEY_IPV6_ADDRESSES_PREF);
 
-        mSecurityPref.setSummary(mAccessPoint.getSecurityString(/* concise */ false));
+        mSecurityPref.setSummary(WifiEntryShell.getSecurityString(mWifiEntry, /* concise */ false));
     }
 
     private void setupEntityHeader(PreferenceScreen screen) {
@@ -451,7 +340,8 @@
             mDataUsageSummaryPref.setVisible(true);
             mSummaryHeaderController =
                 new WifiDataUsageSummaryPreferenceController(mFragment.getActivity(),
-                        mLifecycle, (PreferenceFragmentCompat) mFragment, mAccessPoint.getSsid());
+                        mLifecycle, (PreferenceFragmentCompat) mFragment,
+                        mWifiEntry.getTitle());
             return;
         }
 
@@ -464,22 +354,14 @@
 
         iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
 
-        mEntityHeaderController.setLabel(mAccessPoint.getTitle());
+        mEntityHeaderController.setLabel(mWifiEntry.getTitle());
     }
 
     private void refreshEntityHeader() {
         if (usingDataUsageHeader(mContext)) {
             mSummaryHeaderController.updateState(mDataUsageSummaryPref);
         } else {
-            String summary;
-            if (isPasspointConfigurationR1Expired()) {
-                // Not able to get summary from AccessPoint because we may lost
-                // PasspointConfiguration information after updateAccessPointFromScannedList().
-                summary = mContext.getResources().getString(
-                        com.android.settingslib.R.string.wifi_passpoint_expired);
-            } else {
-                summary = mAccessPoint.getSettingsSummary(true /* convertSavedAsDisconnected */);
-            }
+            String summary = mWifiEntry.getSummary();
 
             mEntityHeaderController
                     .setSummary(summary)
@@ -489,9 +371,19 @@
     }
 
     private void updateNetworkInfo() {
-        mNetwork = mWifiManager.getCurrentNetwork();
-        mLinkProperties = mConnectivityManager.getLinkProperties(mNetwork);
-        mNetworkCapabilities = mConnectivityManager.getNetworkCapabilities(mNetwork);
+        if (mWifiEntry.getConnectedState() == WifiEntry.CONNECTED_STATE_CONNECTED) {
+            mNetwork = mWifiManager.getCurrentNetwork();
+            mLinkProperties = mConnectivityManager.getLinkProperties(mNetwork);
+            mNetworkCapabilities = mConnectivityManager.getNetworkCapabilities(mNetwork);
+            mNetworkInfo = mConnectivityManager.getNetworkInfo(mNetwork);
+            mWifiInfo = mWifiManager.getConnectionInfo();
+        } else {
+            mNetwork = null;
+            mLinkProperties = null;
+            mNetworkCapabilities = null;
+            mNetworkInfo = null;
+            mWifiInfo = null;
+        }
     }
 
     @Override
@@ -500,27 +392,16 @@
         // NetworkCallback only looks at changes to mNetwork.
         updateNetworkInfo();
         refreshPage();
-        mContext.registerReceiver(mReceiver, mFilter);
         mConnectivityManager.registerNetworkCallback(mNetworkRequest, mNetworkCallback,
                 mHandler);
     }
 
     @Override
     public void onPause() {
-        mNetwork = null;
-        mLinkProperties = null;
-        mNetworkCapabilities = null;
-        mNetworkInfo = null;
-        mWifiInfo = null;
-        mContext.unregisterReceiver(mReceiver);
         mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
     }
 
     private void refreshPage() {
-        if (!updateAccessPoint()) {
-            return;
-        }
-
         Log.d(TAG, "Update UI!");
 
         // refresh header
@@ -545,65 +426,11 @@
         refreshMacAddress();
     }
 
-    @VisibleForTesting
-    boolean updateAccessPoint() {
-        boolean changed = false;
-        // remember mIsOutOfRange as old before updated
-        boolean oldState = mIsOutOfRange;
-        updateAccessPointFromScannedList();
-
-        if (mAccessPoint.isActive()) {
-            updateNetworkInfo();
-            mNetworkInfo = mConnectivityManager.getNetworkInfo(mNetwork);
-            mWifiInfo = mWifiManager.getConnectionInfo();
-            if (mNetwork == null || mNetworkInfo == null || mWifiInfo == null) {
-                // Once connected, can't get mNetwork immediately, return false and wait for
-                // next time to update UI. also reset {@code mIsOutOfRange}
-                mIsOutOfRange = oldState;
-                return false;
-            }
-            changed |= mAccessPoint.update(mWifiConfig, mWifiInfo, mNetworkInfo);
-        }
-
-        // signal level changed
-        changed |= mRssiSignalLevel != mAccessPoint.getLevel();
-        // In/Out of range changed
-        changed |= oldState != mIsOutOfRange;
-        // connect state changed
-        if (mConnected != mAccessPoint.isActive()) {
-            mConnected = mAccessPoint.isActive();
-            changed = true;
-            updateConnectingState(mAccessPoint.isActive() ? STATE_CONNECTED : STATE_DISCONNECTED);
-        }
-
-        return changed;
-    }
-
-    private void updateAccessPointFromScannedList() {
-        mIsOutOfRange = true;
-
-        for (AccessPoint ap : mWifiTracker.getAccessPoints()) {
-            if (mAccessPoint.matches(ap)) {
-                mAccessPoint = ap;
-                mWifiConfig = ap.getConfig();
-                mIsOutOfRange = !mAccessPoint.isReachable();
-                return;
-            }
-        }
-    }
-
-    private void exitActivity() {
-        if (DEBUG) {
-            Log.d(TAG, "Exiting the WifiNetworkDetailsPage");
-        }
-        mFragment.getActivity().finish();
-    }
-
     private void refreshRssiViews() {
-        int signalLevel = mAccessPoint.getLevel();
+        int signalLevel = mWifiEntry.getLevel();
 
         // Disappears signal view if not in range. e.g. for saved networks.
-        if (mIsOutOfRange) {
+        if (signalLevel == WifiEntry.WIFI_LEVEL_UNREACHABLE) {
             mSignalStrengthPref.setVisible(false);
             mRssiSignalLevel = -1;
             return;
@@ -656,24 +483,26 @@
     }
 
     private void refreshFrequency() {
-        if (mWifiInfo == null) {
+        final ConnectedInfo connectedInfo = mWifiEntry.getConnectedInfo();
+        if (connectedInfo == null) {
             mFrequencyPref.setVisible(false);
             return;
         }
 
-        final int frequency = mWifiInfo.getFrequency();
+        final int frequency = connectedInfo.frequencyMhz;
         String band = null;
-        if (frequency >= AccessPoint.LOWER_FREQ_24GHZ
-                && frequency < AccessPoint.HIGHER_FREQ_24GHZ) {
+        if (frequency >= WifiEntryShell.LOWER_FREQ_24GHZ
+                && frequency < WifiEntryShell.HIGHER_FREQ_24GHZ) {
             band = mContext.getResources().getString(R.string.wifi_band_24ghz);
-        } else if (frequency >= AccessPoint.LOWER_FREQ_5GHZ
-                && frequency < AccessPoint.HIGHER_FREQ_5GHZ) {
+        } else if (frequency >= WifiEntryShell.LOWER_FREQ_5GHZ
+                && frequency < WifiEntryShell.HIGHER_FREQ_5GHZ) {
             band = mContext.getResources().getString(R.string.wifi_band_5ghz);
         } else {
-            Log.e(TAG, "Unexpected frequency " + frequency);
             // Connecting state is unstable, make it disappeared if unexpected
-            if (mConnectingState == STATE_CONNECTING) {
+            if (mWifiEntry.getConnectedState() == WifiEntry.CONNECTED_STATE_CONNECTING) {
                 mFrequencyPref.setVisible(false);
+            } else {
+                Log.e(TAG, "Unexpected frequency " + frequency);
             }
             return;
         }
@@ -706,9 +535,9 @@
     }
 
     private void refreshSsid() {
-        if (mAccessPoint.isPasspoint() || mAccessPoint.isOsuProvider()) {
+        if (WifiEntryShell.isPasspoint(mWifiEntry) || WifiEntryShell.isOsuProvider(mWifiEntry)) {
             mSsidPref.setVisible(true);
-            mSsidPref.setSummary(mAccessPoint.getSsidStr());
+            mSsidPref.setSummary(mWifiEntry.getTitle());
         } else {
             mSsidPref.setVisible(false);
         }
@@ -733,15 +562,8 @@
     }
 
     private String getMacAddress() {
-        if (mWifiInfo != null) {
-            // get MAC address from connected network information
-            return mWifiInfo.getMacAddress();
-        }
-
-        // return randomized MAC address
-        if (mWifiConfig != null && mWifiConfig.macRandomizationSetting
-                == WifiConfiguration.RANDOMIZATION_PERSISTENT) {
-            return mWifiConfig.getRandomizedMacAddress().toString();
+        if (mWifiEntry.isSaved() && mWifiEntry.getPrivacy() == WifiEntry.PRIVACY_RANDOMIZED_MAC) {
+            return mWifiEntry.getMacAddress();
         }
 
         // return device MAC address
@@ -764,13 +586,9 @@
     }
 
     private void refreshButtons() {
-        // Ephemeral network won't be removed permanently, but be putted in blacklist.
-        mButtonsPref.setButton1Text(
-                mIsEphemeral ? R.string.wifi_disconnect_button_text : R.string.forget);
-
-        boolean canForgetNetwork = canForgetNetwork();
+        boolean canForgetNetwork = mWifiEntry.canForget();
         boolean canSignIntoNetwork = canSignIntoNetwork();
-        boolean canConnectNetwork = canConnectNetwork() && !isPasspointConfigurationR1Expired();
+        boolean canConnectNetwork = mWifiEntry.canConnect();
         boolean canShareNetwork = canShareNetwork();
 
         mButtonsPref.setButton1Visible(canForgetNetwork);
@@ -783,18 +601,10 @@
                 || canShareNetwork);
     }
 
-    private boolean canConnectNetwork() {
-        // Display connect button for disconnected AP even not in the range.
-        return !mAccessPoint.isActive();
-    }
-
-    private boolean isPasspointConfigurationR1Expired() {
-        return mIsPasspointConfigurationR1 && mIsExpired;
-    }
-
     private void refreshIpLayerInfo() {
         // Hide IP layer info if not a connected network.
-        if (!mAccessPoint.isActive() || mNetwork == null || mLinkProperties == null) {
+        if (mWifiEntry.getConnectedState() != WifiEntry.CONNECTED_STATE_CONNECTED
+                || mNetwork == null || mLinkProperties == null) {
             mIpAddressPref.setVisible(false);
             mSubnetPref.setVisible(false);
             mGatewayPref.setVisible(false);
@@ -857,47 +667,36 @@
     }
 
     /**
-     * Returns whether the network represented by this preference can be forgotten.
-     */
-    private boolean canForgetNetwork() {
-        return (mWifiInfo != null && mWifiInfo.isEphemeral()) || canModifyNetwork()
-                || mAccessPoint.isPasspoint() || mAccessPoint.isPasspointConfig();
-    }
-
-    /**
      * Returns whether the network represented by this preference can be modified.
      */
     public boolean canModifyNetwork() {
-        return mWifiConfig != null && !WifiUtils.isNetworkLockedDown(mContext, mWifiConfig);
+        return WifiEntryShell.canModifyNetwork(mWifiEntry);
     }
 
     /**
      * Returns whether the user can sign into the network represented by this preference.
      */
     private boolean canSignIntoNetwork() {
-        return mAccessPoint.isActive() && WifiUtils.canSignIntoNetwork(mNetworkCapabilities);
+        return mWifiEntry.canSignIn();
     }
 
     /**
      * Returns whether the user can share the network represented by this preference with QR code.
      */
     private boolean canShareNetwork() {
-        return mAccessPoint.getConfig() != null
-                && WifiDppUtils.isSupportConfiguratorQrCodeGenerator(mContext, mAccessPoint);
+        return mWifiEntry.canShare();
     }
 
     /**
      * Forgets the wifi network associated with this preference.
      */
     private void forgetNetwork() {
-        if (mWifiInfo != null && mWifiInfo.isEphemeral()) {
-            mWifiManager.disableEphemeralNetwork(mWifiInfo.getSSID());
-        } else if (mAccessPoint.isPasspoint() || mAccessPoint.isPasspointConfig()) {
+        if (WifiEntryShell.isPasspoint(mWifiEntry)) {
             // Post a dialog to confirm if user really want to forget the passpoint network.
             showConfirmForgetDialog();
             return;
-        } else if (mWifiConfig != null) {
-            mWifiManager.forget(mWifiConfig.networkId, null /* action listener */);
+        } else {
+            mWifiEntry.forget();
         }
 
         mMetricsFeatureProvider.action(
@@ -910,10 +709,10 @@
         final AlertDialog dialog = new AlertDialog.Builder(mContext)
                 .setPositiveButton(R.string.forget, ((dialog1, which) -> {
                     try {
-                        mWifiManager.removePasspointConfiguration(mAccessPoint.getPasspointFqdn());
+                        mWifiEntry.forget();
                     } catch (RuntimeException e) {
                         Log.e(TAG, "Failed to remove Passpoint configuration for "
-                                + mAccessPoint.getPasspointFqdn());
+                                + WifiEntryShell.getPasspointFqdn(mWifiEntry));
                     }
                     mMetricsFeatureProvider.action(
                             mFragment.getActivity(), SettingsEnums.ACTION_WIFI_FORGET);
@@ -931,7 +730,7 @@
      */
     private void launchWifiDppConfiguratorActivity() {
         final Intent intent = WifiDppUtils.getConfiguratorQrCodeGeneratorIntentOrNull(mContext,
-                mWifiManager, mAccessPoint);
+                mWifiManager, mWifiEntry);
 
         if (intent == null) {
             Log.e(TAG, "Launch Wi-Fi DPP QR code generator with a wrong Wi-Fi network!");
@@ -1005,203 +804,95 @@
 
     @VisibleForTesting
     void connectNetwork() {
-        final Activity activity = mFragment.getActivity();
-        // error handling, connected/saved network should have mWifiConfig.
-        if (mWifiConfig == null) {
-            Toast.makeText(activity,
-                    R.string.wifi_failed_connect_message,
-                    Toast.LENGTH_SHORT).show();
-            return;
-        }
-
-        // init state before connect
-        mConnectingState = STATE_NONE;
-
-        if (mWifiManager.isWifiEnabled()) {
-            updateConnectingState(STATE_CONNECTING);
-        } else {
-            // Enable Wi-Fi automatically to connect AP
-            updateConnectingState(STATE_ENABLE_WIFI);
-        }
-    }
-
-    private void updateConnectingState(int state) {
-        final Activity activity = mFragment.getActivity();
-        Log.d(TAG, "updateConnectingState from " + mConnectingState + " to " + state);
-        switch (mConnectingState) {
-            case STATE_NONE:
-            case STATE_ENABLE_WIFI:
-                if (state == STATE_ENABLE_WIFI) {
-                    Log.d(TAG, "Turn on Wi-Fi automatically!");
-                    updateConnectedButton(STATE_ENABLE_WIFI);
-                    Toast.makeText(activity,
-                            R.string.wifi_turned_on_message,
-                            Toast.LENGTH_SHORT).show();
-                    mWifiManager.setWifiEnabled(true);
-                    // start timer for error handling
-                    startTimer();
-                } else if (state == STATE_CONNECTING) {
-                    Log.d(TAG, "connecting...");
-                    updateConnectedButton(STATE_CONNECTING);
-                    if (mAccessPoint.isPasspoint()) {
-                        mWifiManager.connect(mWifiConfig, mConnectListener);
-                    } else {
-                        mWifiManager.connect(mWifiConfig.networkId, mConnectListener);
-                    }
-                    // start timer for error handling since framework didn't call back if failed
-                    startTimer();
-                } else if (state == STATE_ENABLE_WIFI_FAILED) {
-                    Log.e(TAG, "Wi-Fi failed to enable network!");
-                    stopTimer();
-                    // reset state
-                    state = STATE_NONE;
-                    Toast.makeText(activity,
-                            R.string.wifi_failed_connect_message,
-                            Toast.LENGTH_SHORT).show();
-                    updateConnectedButton(STATE_ENABLE_WIFI_FAILED);
-                }
-                // Do not break here for disconnected event.
-            case STATE_CONNECTED:
-                if (state == STATE_DISCONNECTED) {
-                    Log.d(TAG, "disconnected");
-                    // reset state
-                    state = STATE_NONE;
-                    updateConnectedButton(STATE_DISCONNECTED);
-                    refreshPage();
-                    // clear for getting MAC Address from saved configuration
-                    mWifiInfo = null;
-                }
-                break;
-            case STATE_CONNECTING:
-                if (state == STATE_CONNECTED) {
-                    Log.d(TAG, "connected");
-                    stopTimer();
-                    updateConnectedButton(STATE_CONNECTED);
-                    Toast.makeText(activity,
-                            mContext.getString(R.string.wifi_connected_to_message,
-                                    mAccessPoint.getTitle()),
-                            Toast.LENGTH_SHORT).show();
-
-                    refreshPage();
-                } else if (state == STATE_NOT_IN_RANGE) {
-                    Log.d(TAG, "AP not in range");
-                    stopTimer();
-                    // reset state
-                    state = STATE_NONE;
-                    Toast.makeText(activity,
-                            R.string.wifi_not_in_range_message,
-                            Toast.LENGTH_SHORT).show();
-                    updateConnectedButton(STATE_NOT_IN_RANGE);
-                } else if (state == STATE_FAILED) {
-                    Log.d(TAG, "failed");
-                    stopTimer();
-                    // reset state
-                    state = STATE_NONE;
-                    Toast.makeText(activity,
-                            R.string.wifi_failed_connect_message,
-                            Toast.LENGTH_SHORT).show();
-                    updateConnectedButton(STATE_FAILED);
-                }
-                break;
-            default:
-                Log.e(TAG, "Invalid state : " + mConnectingState);
-                // don't update invalid state
-                return;
-        }
-
-        mConnectingState = state;
-    }
-
-    private void updateConnectedButton(int state) {
-        switch (state) {
-            case STATE_ENABLE_WIFI:
-            case STATE_CONNECTING:
-                mButtonsPref.setButton3Text(R.string.wifi_connecting)
-                        .setButton3Enabled(false);
-                break;
-            case STATE_CONNECTED:
-                // init button state and set as invisible
-                mButtonsPref.setButton3Text(R.string.wifi_connect)
-                        .setButton3Icon(R.drawable.ic_settings_wireless)
-                        .setButton3Enabled(true)
-                        .setButton3Visible(false);
-                break;
-            case STATE_DISCONNECTED:
-            case STATE_NOT_IN_RANGE:
-            case STATE_FAILED:
-            case STATE_ENABLE_WIFI_FAILED:
-                if (isPasspointConfigurationR1Expired()) {
-                    // Hide Connect button.
-                    mButtonsPref.setButton3Visible(false);
-                } else {
-                    mButtonsPref.setButton3Text(R.string.wifi_connect)
-                            .setButton3Icon(R.drawable.ic_settings_wireless)
-                            .setButton3Enabled(true)
-                            .setButton3Visible(true);
-                }
-                break;
-            default:
-                Log.e(TAG, "Invalid connect button state : " + state);
-                break;
-        }
-    }
-
-    private void startTimer() {
-        if (sTimer != null) {
-            stopTimer();
-        }
-
-        sTimer = new CountDownTimer(TIMEOUT, TIMEOUT + 1) {
-            @Override
-            public void onTick(long millisUntilFinished) {
-                // Do nothing
-            }
-            @Override
-            public void onFinish() {
-                if (mFragment == null || mFragment.getActivity() == null) {
-                    Log.d(TAG, "Ignore timeout since activity not exist!");
-                    return;
-                }
-                Log.e(TAG, "Timeout for state:" + mConnectingState);
-                if (mConnectingState == STATE_ENABLE_WIFI) {
-                    updateConnectingState(STATE_ENABLE_WIFI_FAILED);
-                } else if (mConnectingState == STATE_CONNECTING) {
-                    updateAccessPointFromScannedList();
-                    if (mIsOutOfRange) {
-                        updateConnectingState(STATE_NOT_IN_RANGE);
-                    } else {
-                        updateConnectingState(STATE_FAILED);
-                    }
-                }
-            }
-        };
-        sTimer.start();
-    }
-
-    private void stopTimer() {
-        if (sTimer == null) return;
-
-        sTimer.cancel();
-        sTimer = null;
+        // TODO(b/143326832): What to do with WifiManager#isWifiEnabled() false case?
+        mButtonsPref.setButton3Text(R.string.wifi_connecting).setButton3Enabled(false);
+        mWifiEntry.connect();
     }
 
     private void refreshMacTitle() {
-        if (mWifiConfig == null) {
+        if (!mWifiEntry.isSaved()) {
             return;
         }
 
         // For saved Passpoint network, framework doesn't have the field to keep the MAC choice
         // persistently, so Passpoint network will always use the default value so far, which is
         // randomized MAC address, so don't need to modify title.
-        if (mAccessPoint.isPasspoint() || mAccessPoint.isPasspointConfig()) {
+        if (WifiEntryShell.isPasspoint(mWifiEntry)) {
             return;
         }
 
         mMacAddressPref.setTitle(
-                (mWifiConfig.macRandomizationSetting
-                        == WifiConfiguration.RANDOMIZATION_PERSISTENT)
+                (mWifiEntry.getPrivacy() == WifiEntry.PRIVACY_RANDOMIZED_MAC)
                         ? R.string.wifi_advanced_randomized_mac_address_title
                         : R.string.wifi_advanced_device_mac_address_title);
+    }
 
+    /**
+     * Indicates the state of the WifiEntry has changed and clients may retrieve updates through
+     * the WifiEntry getter methods.
+     */
+    @Override
+    public void onUpdated() {
+        refreshPage();
+    }
+
+    /**
+     * Result of the connect request indicated by the CONNECT_STATUS constants.
+     */
+    @Override
+    public void onConnectResult(@ConnectStatus int status) {
+        if (status == WifiEntryCallback.CONNECT_STATUS_SUCCESS) {
+            Toast.makeText(mContext,
+                    mContext.getString(R.string.wifi_connected_to_message, mWifiEntry.getTitle()),
+                    Toast.LENGTH_SHORT).show();
+            updateNetworkInfo();
+            refreshPage();
+        } else if (mWifiEntry.getLevel() == WifiEntry.WIFI_LEVEL_UNREACHABLE) {
+            Toast.makeText(mContext,
+                    R.string.wifi_not_in_range_message,
+                    Toast.LENGTH_SHORT).show();
+        } else {
+            Toast.makeText(mContext,
+                    R.string.wifi_failed_connect_message,
+                    Toast.LENGTH_SHORT).show();
+        }
+        mButtonsPref.setButton3Text(R.string.wifi_connect)
+                .setButton3Icon(R.drawable.ic_settings_wireless)
+                .setButton3Enabled(true)
+                .setButton3Visible(true);
+    }
+
+    /**
+     * Result of the disconnect request indicated by the DISCONNECT_STATUS constants.
+     */
+    @Override
+    public void onDisconnectResult(@DisconnectStatus int status) {
+        if (status != WifiEntryCallback.DISCONNECT_STATUS_SUCCESS) {
+            Log.e(TAG, "Disconnect Wi-Fi network failed");
+        }
+
+        updateNetworkInfo();
+        refreshPage();
+    }
+
+    /**
+     * Result of the forget request indicated by the FORGET_STATUS constants.
+     */
+    @Override
+    public void onForgetResult(@ForgetStatus int status) {
+        if (status != WifiEntryCallback.FORGET_STATUS_SUCCESS) {
+            Log.e(TAG, "Forget Wi-Fi network failed");
+        }
+
+        mMetricsFeatureProvider.action(mFragment.getActivity(), SettingsEnums.ACTION_WIFI_FORGET);
+        mFragment.getActivity().finish();
+    }
+
+    /**
+     * Result of the sign-in request indicated by the SIGNIN_STATUS constants.
+     */
+    @Override
+    public void onSignInResult(@SignInStatus int status) {
+        refreshPage();
     }
 }
diff --git a/src/com/android/settings/wifi/details2/WifiMeteredPreferenceController2.java b/src/com/android/settings/wifi/details2/WifiMeteredPreferenceController2.java
index 99967dc..0915152 100644
--- a/src/com/android/settings/wifi/details2/WifiMeteredPreferenceController2.java
+++ b/src/com/android/settings/wifi/details2/WifiMeteredPreferenceController2.java
@@ -18,8 +18,6 @@
 
 import android.app.backup.BackupManager;
 import android.content.Context;
-import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiManager;
 
 import androidx.annotation.VisibleForTesting;
 import androidx.preference.DropDownPreference;
@@ -29,6 +27,7 @@
 import com.android.settings.core.BasePreferenceController;
 import com.android.settings.wifi.WifiDialog;
 import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.wifitrackerlib.WifiEntry;
 
 /**
  * {@link AbstractPreferenceController} that controls whether the wifi network is metered or not
@@ -37,14 +36,12 @@
         Preference.OnPreferenceChangeListener, WifiDialog.WifiDialogListener {
 
     private static final String KEY_WIFI_METERED = "metered";
-    private WifiConfiguration mWifiConfiguration;
-    private WifiManager mWifiManager;
+    private WifiEntry mWifiEntry;
     private Preference mPreference;
 
-    public WifiMeteredPreferenceController2(Context context, WifiConfiguration wifiConfiguration) {
+    public WifiMeteredPreferenceController2(Context context, WifiEntry wifiEntry) {
         super(context, KEY_WIFI_METERED);
-        mWifiConfiguration = wifiConfiguration;
-        mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+        mWifiEntry = wifiEntry;
     }
 
     @Override
@@ -62,10 +59,10 @@
 
     @Override
     public boolean onPreferenceChange(Preference preference, Object newValue) {
-        if (mWifiConfiguration != null) {
-            mWifiConfiguration.meteredOverride = Integer.parseInt((String) newValue);
+        if (mWifiEntry.isSaved()) {
+            mWifiEntry.setMeteredChoice(Integer.parseInt((String) newValue));
         }
-        mWifiManager.updateNetwork(mWifiConfiguration);
+
         // Stage the backup of the SettingsProvider package which backs this up
         BackupManager.dataChanged("com.android.providers.settings");
         updateSummary((DropDownPreference) preference, getMeteredOverride());
@@ -74,11 +71,11 @@
 
     @VisibleForTesting
     int getMeteredOverride() {
-        if (mWifiConfiguration != null) {
+        if (mWifiEntry.isSaved()) {
             // Wrap the meteredOverride since robolectric cannot recognize it
-            return mWifiConfiguration.meteredOverride;
+            return mWifiEntry.getMeteredChoice();
         }
-        return WifiConfiguration.METERED_OVERRIDE_NONE;
+        return WifiEntry.METERED_CHOICE_AUTO;
     }
 
     private void updateSummary(DropDownPreference preference, int meteredOverride) {
@@ -93,16 +90,17 @@
 
     @Override
     public void onSubmit(WifiDialog dialog) {
-        if (dialog.getController() != null) {
-            final WifiConfiguration newConfig = dialog.getController().getConfig();
-            if (newConfig == null || mWifiConfiguration == null) {
-                return;
-            }
-
-            if (newConfig.meteredOverride != mWifiConfiguration.meteredOverride) {
-                mWifiConfiguration = newConfig;
-                onPreferenceChange(mPreference, String.valueOf(newConfig.meteredOverride));
-            }
-        }
+        // TODO(b/143326832): Create WifiDialog2 and let it work for WifiEntry.
+        //if (dialog.getController() != null) {
+        //    final WifiConfiguration newConfig = dialog.getController().getConfig();
+        //    if (newConfig == null || mWifiConfiguration == null) {
+        //        return;
+        //    }
+        //
+        //    if (newConfig.meteredOverride != mWifiConfiguration.meteredOverride) {
+        //        mWifiConfiguration = newConfig;
+        //        onPreferenceChange(mPreference, String.valueOf(newConfig.meteredOverride));
+        //    }
+        //}
     }
 }
diff --git a/src/com/android/settings/wifi/details2/WifiNetworkDetailsFragment2.java b/src/com/android/settings/wifi/details2/WifiNetworkDetailsFragment2.java
index 5eb4b28..7e4c856 100644
--- a/src/com/android/settings/wifi/details2/WifiNetworkDetailsFragment2.java
+++ b/src/com/android/settings/wifi/details2/WifiNetworkDetailsFragment2.java
@@ -21,45 +21,61 @@
 import android.app.settings.SettingsEnums;
 import android.content.Context;
 import android.net.ConnectivityManager;
+import android.net.NetworkScoreManager;
 import android.net.wifi.WifiManager;
-import android.os.Bundle;
 import android.os.Handler;
+import android.os.HandlerThread;
 import android.os.Looper;
+import android.os.Process;
+import android.os.SimpleClock;
+import android.os.SystemClock;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
 
 import com.android.settings.R;
 import com.android.settings.dashboard.DashboardFragment;
-import com.android.settings.wifi.WifiConfigUiBase;
 import com.android.settings.wifi.WifiDialog;
 import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.core.AbstractPreferenceController;
-import com.android.settingslib.wifi.AccessPoint;
+import com.android.wifitrackerlib.NetworkDetailsTracker;
+import com.android.wifitrackerlib.WifiEntry;
 
+import java.time.Clock;
+import java.time.ZoneOffset;
 import java.util.ArrayList;
 import java.util.List;
 
 /**
  * Detail page for the currently connected wifi network.
  *
- * <p>The AccessPoint should be saved to the intent Extras when launching this class via
- * {@link AccessPoint#saveWifiState(Bundle)} in order to properly render this page.
+ * <p>The key of {@link WifiEntry} should be saved to the intent Extras when launching this class
+ * in order to properly render this page.
  */
 public class WifiNetworkDetailsFragment2 extends DashboardFragment implements
         WifiDialog.WifiDialogListener {
 
     private static final String TAG = "WifiNetworkDetailsFrg2";
 
-    private AccessPoint mAccessPoint;
+    // Key of a Bundle to save/restore the selected WifiEntry
+    public static final String KEY_CHOSEN_WIFIENTRY_KEY = "key_chosen_wifientry_key";
+
+    // Max age of tracked WifiEntries
+    private static final long MAX_SCAN_AGE_MILLIS = 15_000;
+    // Interval between initiating SavedNetworkTracker scans
+    private static final long SCAN_INTERVAL_MILLIS = 10_000;
+
+    private NetworkDetailsTracker mNetworkDetailsTracker;
+    private HandlerThread mWorkerThread;
     private WifiDetailPreferenceController2 mWifiDetailPreferenceController2;
     private List<WifiDialog.WifiDialogListener> mWifiDialogListeners = new ArrayList<>();
 
     @Override
-    public void onAttach(Context context) {
-        mAccessPoint = new AccessPoint(context, getArguments());
-        super.onAttach(context);
+    public void onDestroy() {
+        mWorkerThread.quit();
+
+        super.onDestroy();
     }
 
     @Override
@@ -87,15 +103,15 @@
 
     @Override
     public Dialog onCreateDialog(int dialogId) {
-        if (getActivity() == null || mWifiDetailPreferenceController2 == null
-                || mAccessPoint == null) {
+        if (getActivity() == null || mWifiDetailPreferenceController2 == null) {
             return null;
         }
-        return WifiDialog.createModal(getActivity(), this, mAccessPoint,
-                WifiConfigUiBase.MODE_MODIFY);
+        // TODO(b/143326832): Replace it with WifiEntry.
+        return null;
+        //return WifiDialog.createModal(getActivity(), this, mAccessPoint,
+        //        WifiConfigUiBase.MODE_MODIFY);
     }
 
-
     @Override
     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
         MenuItem item = menu.add(0, Menu.FIRST, 0, R.string.wifi_modify);
@@ -124,9 +140,11 @@
     protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
         final List<AbstractPreferenceController> controllers = new ArrayList<>();
         final ConnectivityManager cm = context.getSystemService(ConnectivityManager.class);
+        setupNetworksDetailTracker();
+        final WifiEntry wifiEntry = mNetworkDetailsTracker.getWifiEntry();
 
         mWifiDetailPreferenceController2 = WifiDetailPreferenceController2.newInstance(
-                mAccessPoint,
+                wifiEntry,
                 cm,
                 context,
                 this,
@@ -134,20 +152,20 @@
                 getSettingsLifecycle(),
                 context.getSystemService(WifiManager.class),
                 mMetricsFeatureProvider);
-
         controllers.add(mWifiDetailPreferenceController2);
-        controllers.add(new AddDevicePreferenceController2(context).init(mAccessPoint));
+
+        final AddDevicePreferenceController2 addDevicePreferenceController2 =
+                new AddDevicePreferenceController2(context);
+        addDevicePreferenceController2.setWifiEntry(wifiEntry);
+        controllers.add(addDevicePreferenceController2);
 
         final WifiMeteredPreferenceController2 meteredPreferenceController2 =
-                new WifiMeteredPreferenceController2(context, mAccessPoint.getConfig());
+                new WifiMeteredPreferenceController2(context, wifiEntry);
         controllers.add(meteredPreferenceController2);
 
         final WifiPrivacyPreferenceController2 privacyController2 =
                 new WifiPrivacyPreferenceController2(context);
-        privacyController2.setWifiConfiguration(mAccessPoint.getConfig());
-        privacyController2.setIsEphemeral(mAccessPoint.isEphemeral());
-        privacyController2.setIsPasspoint(
-                mAccessPoint.isPasspoint() || mAccessPoint.isPasspointConfig());
+        privacyController2.setWifiEntry(wifiEntry);
         controllers.add(privacyController2);
 
         // Sets callback listener for wifi dialog.
@@ -164,4 +182,35 @@
             listener.onSubmit(dialog);
         }
     }
+
+    private void setupNetworksDetailTracker() {
+        if (mNetworkDetailsTracker != null) {
+            return;
+        }
+
+        final Context context = getContext();
+        mWorkerThread = new HandlerThread(TAG
+                + "{" + Integer.toHexString(System.identityHashCode(this)) + "}",
+                Process.THREAD_PRIORITY_BACKGROUND);
+        mWorkerThread.start();
+        final Clock elapsedRealtimeClock = new SimpleClock(ZoneOffset.UTC) {
+            @Override
+            public long millis() {
+                return SystemClock.elapsedRealtime();
+            }
+        };
+
+        mNetworkDetailsTracker = NetworkDetailsTracker.createNetworkDetailsTracker(
+                getSettingsLifecycle(),
+                context,
+                context.getSystemService(WifiManager.class),
+                context.getSystemService(ConnectivityManager.class),
+                context.getSystemService(NetworkScoreManager.class),
+                new Handler(Looper.getMainLooper()),
+                mWorkerThread.getThreadHandler(),
+                elapsedRealtimeClock,
+                MAX_SCAN_AGE_MILLIS,
+                SCAN_INTERVAL_MILLIS,
+                getArguments().getString(KEY_CHOSEN_WIFIENTRY_KEY));
+    }
 }
diff --git a/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2.java b/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2.java
index d85b607..bca4de1 100644
--- a/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2.java
+++ b/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2.java
@@ -17,8 +17,6 @@
 package com.android.settings.wifi.details2;
 
 import android.content.Context;
-import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
 
 import androidx.annotation.VisibleForTesting;
@@ -30,6 +28,7 @@
 import com.android.settings.core.BasePreferenceController;
 import com.android.settings.wifi.WifiDialog;
 import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.wifitrackerlib.WifiEntry;
 
 /**
  * {@link AbstractPreferenceController} that controls whether the wifi network is mac randomized
@@ -39,28 +38,18 @@
         Preference.OnPreferenceChangeListener, WifiDialog.WifiDialogListener {
 
     private static final String KEY_WIFI_PRIVACY = "privacy";
-    private WifiConfiguration mWifiConfiguration;
     private WifiManager mWifiManager;
-    private boolean mIsEphemeral = false;
-    private boolean mIsPasspoint = false;
+    private WifiEntry mWifiEntry;
     private Preference mPreference;
 
     public WifiPrivacyPreferenceController2(Context context) {
         super(context, KEY_WIFI_PRIVACY);
-        mWifiConfiguration = null;
+
         mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
     }
 
-    public void setWifiConfiguration(WifiConfiguration wifiConfiguration) {
-        mWifiConfiguration = wifiConfiguration;
-    }
-
-    public void setIsEphemeral(boolean isEphemeral) {
-        mIsEphemeral = isEphemeral;
-    }
-
-    public void setIsPasspoint(boolean isPasspoint) {
-        mIsPasspoint = isPasspoint;
+    public void setWifiEntry(WifiEntry wifiEntry) {
+        mWifiEntry = wifiEntry;
     }
 
     @Override
@@ -83,7 +72,7 @@
         updateSummary(dropDownPreference, randomizationLevel);
 
         // Makes preference not selectable, when this is a ephemeral network.
-        if (mIsEphemeral || mIsPasspoint) {
+        if (!mWifiEntry.canSetPrivacy()) {
             preference.setSelectable(false);
             dropDownPreference.setSummary(R.string.wifi_privacy_settings_ephemeral_summary);
         }
@@ -91,27 +80,26 @@
 
     @Override
     public boolean onPreferenceChange(Preference preference, Object newValue) {
-        if (mWifiConfiguration != null) {
-            mWifiConfiguration.macRandomizationSetting = Integer.parseInt((String) newValue);
-            mWifiManager.updateNetwork(mWifiConfiguration);
+        final int privacy = Integer.parseInt((String) newValue);
+        if (mWifiEntry.isSaved()) {
+            mWifiEntry.setPrivacy(privacy);
 
             // To activate changing, we need to reconnect network. WiFi will auto connect to
             // current network after disconnect(). Only needed when this is connected network.
-            final WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
-            if (wifiInfo != null && wifiInfo.getNetworkId() == mWifiConfiguration.networkId) {
-                mWifiManager.disconnect();
+            if (mWifiEntry.getConnectedState() == WifiEntry.CONNECTED_STATE_CONNECTED) {
+                mWifiEntry.disconnect();
             }
         }
-        updateSummary((DropDownPreference) preference, Integer.parseInt((String) newValue));
+        updateSummary((DropDownPreference) preference, privacy);
         return true;
     }
 
     @VisibleForTesting
     int getRandomizationValue() {
-        if (mWifiConfiguration != null) {
-            return mWifiConfiguration.macRandomizationSetting;
+        if (mWifiEntry.isSaved()) {
+            return mWifiEntry.getPrivacy();
         }
-        return WifiConfiguration.RANDOMIZATION_PERSISTENT;
+        return WifiEntry.PRIVACY_RANDOMIZED_MAC;
     }
 
     private static final int PREF_RANDOMIZATION_PERSISTENT = 0;
@@ -124,7 +112,7 @@
      * @return index value of preference
      */
     public static int translateMacRandomizedValueToPrefValue(int macRandomized) {
-        return (macRandomized == WifiConfiguration.RANDOMIZATION_PERSISTENT)
+        return (macRandomized == WifiEntry.PRIVACY_RANDOMIZED_MAC)
             ? PREF_RANDOMIZATION_PERSISTENT : PREF_RANDOMIZATION_NONE;
     }
 
@@ -136,7 +124,7 @@
      */
     public static int translatePrefValueToMacRandomizedValue(int prefMacRandomized) {
         return (prefMacRandomized == PREF_RANDOMIZATION_PERSISTENT)
-            ? WifiConfiguration.RANDOMIZATION_PERSISTENT : WifiConfiguration.RANDOMIZATION_NONE;
+            ? WifiEntry.PRIVACY_RANDOMIZED_MAC : WifiEntry.PRIVACY_DEVICE_MAC;
     }
 
     private void updateSummary(DropDownPreference preference, int macRandomized) {
@@ -147,16 +135,17 @@
 
     @Override
     public void onSubmit(WifiDialog dialog) {
-        if (dialog.getController() != null) {
-            final WifiConfiguration newConfig = dialog.getController().getConfig();
-            if (newConfig == null || mWifiConfiguration == null) {
-                return;
-            }
-
-            if (newConfig.macRandomizationSetting != mWifiConfiguration.macRandomizationSetting) {
-                mWifiConfiguration = newConfig;
-                onPreferenceChange(mPreference, String.valueOf(newConfig.macRandomizationSetting));
-            }
-        }
+        // TODO(b/143326832): Create WifiDialog2 and let it work for WifiEntry.
+        //if (dialog.getController() != null) {
+        //    final WifiConfiguration newConfig = dialog.getController().getConfig();
+        //    if (newConfig == null || mWifiConfiguration == null) {
+        //        return;
+        //    }
+        //
+        //    if (newConfig.macRandomizationSetting != mWifiConfiguration.macRandomizationSetting) {
+        //        mWifiConfiguration = newConfig;
+       //        onPreferenceChange(mPreference, String.valueOf(newConfig.macRandomizationSetting));
+        //    }
+        //}
     }
 }
diff --git a/src/com/android/settings/wifi/dpp/WifiDppUtils.java b/src/com/android/settings/wifi/dpp/WifiDppUtils.java
index 6e01aef..22180c3 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppUtils.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppUtils.java
@@ -32,7 +32,9 @@
 import android.text.TextUtils;
 
 import com.android.settings.R;
+import com.android.settings.wifi.WifiEntryShell;
 import com.android.settingslib.wifi.AccessPoint;
+import com.android.wifitrackerlib.WifiEntry;
 
 import java.time.Duration;
 import java.util.List;
@@ -148,6 +150,24 @@
         return wifiConfiguration.preSharedKey;
     }
 
+    private static String getPresharedKey(WifiManager wifiManager, WifiEntry wifiEntry) {
+        final List<WifiConfiguration> privilegedWifiConfigurations =
+                wifiManager.getPrivilegedConfiguredNetworks();
+
+        for (WifiConfiguration privilegedWifiConfiguration : privilegedWifiConfigurations) {
+            if (privilegedWifiConfiguration.networkId == WifiEntryShell.getNetworkId(wifiEntry)) {
+                // WEP uses a shared key hence the AuthAlgorithm.SHARED is used to identify it.
+                if (wifiEntry.getSecurity() == WifiEntry.SECURITY_WEP) {
+                    return privilegedWifiConfiguration
+                            .wepKeys[privilegedWifiConfiguration.wepTxKeyIndex];
+                } else {
+                    return privilegedWifiConfiguration.preSharedKey;
+                }
+            }
+        }
+        return "";
+    }
+
     private static String removeFirstAndLastDoubleQuotes(String str) {
         if (TextUtils.isEmpty(str)) {
             return str;
@@ -179,6 +199,22 @@
                 WifiQrCode.SECURITY_NO_PASSWORD : WifiQrCode.SECURITY_WEP;
     }
 
+    static String getSecurityString(WifiEntry wifiEntry) {
+        final int security = wifiEntry.getSecurity();
+        switch (security) {
+            case WifiEntry.SECURITY_SAE:
+                return WifiQrCode.SECURITY_SAE;
+            case WifiEntry.SECURITY_PSK:
+                return WifiQrCode.SECURITY_WPA_PSK;
+            case WifiEntry.SECURITY_WEP:
+                return WifiQrCode.SECURITY_WEP;
+            case WifiEntry.SECURITY_OWE:
+            case WifiEntry.SECURITY_NONE:
+            default:
+                return WifiQrCode.SECURITY_NO_PASSWORD;
+        }
+    }
+
     /**
      * Returns an intent to launch QR code generator. It may return null if the security is not
      * supported by QR code generator.
@@ -212,6 +248,37 @@
     }
 
     /**
+     * Returns an intent to launch QR code generator. It may return null if the security is not
+     * supported by QR code generator.
+     *
+     * Do not use this method for Wi-Fi hotspot network, use
+     * {@code getHotspotConfiguratorIntentOrNull} instead.
+     *
+     * @param context     The context to use for the content resolver
+     * @param wifiManager An instance of {@link WifiManager}
+     * @param wifiEntry An instance of {@link WifiEntry}
+     * @return Intent for launching QR code generator
+     */
+    public static Intent getConfiguratorQrCodeGeneratorIntentOrNull(Context context,
+            WifiManager wifiManager, WifiEntry wifiEntry) {
+        final Intent intent = new Intent(context, WifiDppConfiguratorActivity.class);
+        if (wifiEntry.canShare()) {
+            intent.setAction(WifiDppConfiguratorActivity.ACTION_CONFIGURATOR_QR_CODE_GENERATOR);
+        } else {
+            return null;
+        }
+
+        setConfiguratorIntentExtra(intent, wifiManager, wifiEntry);
+
+        // For a transition mode Wi-Fi AP, creates a QR code that's compatible with more devices
+        if (wifiEntry.getSecurity() == WifiEntry.SECURITY_PSK_SAE_TRANSITION) {
+            intent.putExtra(EXTRA_WIFI_SECURITY, WifiQrCode.SECURITY_WPA_PSK);
+        }
+
+        return intent;
+    }
+
+    /**
      * Returns an intent to launch QR code scanner. It may return null if the security is not
      * supported by QR code scanner.
      *
@@ -242,6 +309,36 @@
     }
 
     /**
+     * Returns an intent to launch QR code scanner. It may return null if the security is not
+     * supported by QR code scanner.
+     *
+     * @param context     The context to use for the content resolver
+     * @param wifiManager An instance of {@link WifiManager}
+     * @param wifiEntry An instance of {@link WifiEntry}
+     * @return Intent for launching QR code scanner
+     */
+    public static Intent getConfiguratorQrCodeScannerIntentOrNull(Context context,
+            WifiManager wifiManager, WifiEntry wifiEntry) {
+        final Intent intent = new Intent(context, WifiDppConfiguratorActivity.class);
+        if (isSupportConfiguratorQrCodeScanner(context, wifiEntry)) {
+            intent.setAction(WifiDppConfiguratorActivity.ACTION_CONFIGURATOR_QR_CODE_SCANNER);
+        } else {
+            return null;
+        }
+
+        setConfiguratorIntentExtra(intent, wifiManager, wifiEntry);
+
+        final int networkId = WifiEntryShell.getNetworkId(wifiEntry);
+        if (networkId == WifiConfiguration.INVALID_NETWORK_ID) {
+            throw new IllegalArgumentException("Invalid network ID");
+        } else {
+            intent.putExtra(EXTRA_WIFI_NETWORK_ID, networkId);
+        }
+
+        return intent;
+    }
+
+    /**
      * Returns an intent to launch QR code generator for the Wi-Fi hotspot. It may return null if
      * the security is not supported by QR code generator.
      *
@@ -320,6 +417,28 @@
         intent.putExtra(EXTRA_WIFI_HIDDEN_SSID, wifiConfiguration.hiddenSSID);
     }
 
+    private static void setConfiguratorIntentExtra(Intent intent, WifiManager wifiManager,
+            WifiEntry wifiEntry) {
+        final String ssid = removeFirstAndLastDoubleQuotes(wifiEntry.getTitle());
+        final String security = getSecurityString(wifiEntry);
+
+        // When the value of this key is read, the actual key is not returned, just a "*".
+        // Call privileged system API to obtain actual key.
+        final String preSharedKey = removeFirstAndLastDoubleQuotes(getPresharedKey(wifiManager,
+                wifiEntry));
+
+        if (!TextUtils.isEmpty(ssid)) {
+            intent.putExtra(EXTRA_WIFI_SSID, ssid);
+        }
+        if (!TextUtils.isEmpty(security)) {
+            intent.putExtra(EXTRA_WIFI_SECURITY, security);
+        }
+        if (!TextUtils.isEmpty(preSharedKey)) {
+            intent.putExtra(EXTRA_WIFI_PRE_SHARED_KEY, preSharedKey);
+        }
+        intent.putExtra(EXTRA_WIFI_HIDDEN_SSID, WifiEntryShell.hiddenSSID(wifiEntry));
+    }
+
     /**
      * Shows authentication screen to confirm credentials (pin, pattern or password) for the current
      * user of the device.
@@ -379,6 +498,19 @@
     }
 
     /**
+     * Checks if QR code scanner supports to config other devices with the Wi-Fi network
+     *
+     * @param context The context to use for {@link WifiManager#isEasyConnectSupported()}
+     * @param wifiEntry The {@link WifiEntry} of the Wi-Fi network
+     */
+    public static boolean isSupportConfiguratorQrCodeScanner(Context context, WifiEntry wifiEntry) {
+        if (WifiEntryShell.isPasspoint(wifiEntry)) {
+            return false;
+        }
+        return isSupportWifiDpp(context, wifiEntry.getSecurity());
+    }
+
+    /**
      * Checks if QR code generator supports to config other devices with the Wi-Fi network
      *
      * @param context The context to use for {@code WifiManager}
diff --git a/src/com/android/settings/wifi/savedaccesspoints2/SavedAccessPointsWifiSettings2.java b/src/com/android/settings/wifi/savedaccesspoints2/SavedAccessPointsWifiSettings2.java
index e094051..0145bb4 100644
--- a/src/com/android/settings/wifi/savedaccesspoints2/SavedAccessPointsWifiSettings2.java
+++ b/src/com/android/settings/wifi/savedaccesspoints2/SavedAccessPointsWifiSettings2.java
@@ -52,9 +52,6 @@
 
     private static final String TAG = "SavedAccessPoints2";
 
-    // Key of a Bundle to save/restore the selected WifiEntry
-    static final String KEY_KEY = "key_key";
-
     // Max age of tracked WifiEntries
     private static final long MAX_SCAN_AGE_MILLIS = 15_000;
     // Interval between initiating SavedNetworkTracker scans
@@ -139,7 +136,7 @@
         }
 
         final Bundle bundle = new Bundle();
-        bundle.putString(KEY_KEY, key);
+        bundle.putString(WifiNetworkDetailsFragment2.KEY_CHOSEN_WIFIENTRY_KEY, key);
 
         new SubSettingLauncher(getContext())
                 .setTitleText(title)
diff --git a/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceController.java b/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceController.java
index 78e592c..0741695 100644
--- a/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceController.java
+++ b/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceController.java
@@ -48,16 +48,17 @@
     public void updateDisplay() {
         final SoftApConfiguration config = mWifiManager.getSoftApConfiguration();
         if (config == null) {
-            mBandIndex = 0;
-            Log.d(TAG, "Updating band index to 0 because no config");
+            mBandIndex = SoftApConfiguration.BAND_2GHZ;
+            Log.d(TAG, "Updating band index to BAND_2GHZ because no config");
         } else if (is5GhzBandSupported()) {
             mBandIndex = validateSelection(config.getBand());
             Log.d(TAG, "Updating band index to " + mBandIndex);
         } else {
             mWifiManager.setSoftApConfiguration(
-                    new SoftApConfiguration.Builder(config).setBand(0).build());
-            mBandIndex = config.getBand();
-            Log.d(TAG, "5Ghz not supported, updating band index to " + mBandIndex);
+                    new SoftApConfiguration.Builder(config).setBand(SoftApConfiguration.BAND_2GHZ)
+                        .build());
+            mBandIndex = SoftApConfiguration.BAND_2GHZ;
+            Log.d(TAG, "5Ghz not supported, updating band index to 2GHz");
         }
         ListPreference preference =
                 (ListPreference) mPreference;
@@ -74,10 +75,14 @@
     }
 
     String getConfigSummary() {
-        if (mBandIndex == SoftApConfiguration.BAND_ANY) {
-           return mContext.getString(R.string.wifi_ap_prefer_5G);
+        switch (mBandIndex) {
+            case SoftApConfiguration.BAND_2GHZ:
+                return mBandSummaries[0];
+            case SoftApConfiguration.BAND_5GHZ:
+                return mBandSummaries[1];
+            default:
+                return mContext.getString(R.string.wifi_ap_prefer_5G);
         }
-        return mBandSummaries[mBandIndex];
     }
 
     @Override
@@ -95,19 +100,18 @@
     }
 
     private int validateSelection(int band) {
-        // Reset the band to 2.4 GHz if we get a weird config back to avoid a crash.
-        final boolean isDualMode = mWifiManager.isDualModeSupported();
-
         // unsupported states:
-        // 1: no dual mode means we can't have AP_BAND_ANY - default to 5GHZ
-        // 2: no 5 GHZ support means we can't have AP_BAND_5GHZ - default to 2GHZ
-        // 3: With Dual mode support we can't have AP_BAND_5GHZ - default to ANY
-        if (!isDualMode && SoftApConfiguration.BAND_ANY == band) {
+        // 1: no dual mode means we can't have multiband - default to 5GHZ
+        // 2: no 5 GHZ support means we can't have BAND_5GHZ - default to 2GHZ
+        // 3: With Dual mode support we can't have BAND_5GHZ only - include 2GHZ
+        if (!isDualMode
+                && ((band & (SoftApConfiguration.BAND_5GHZ
+                | SoftApConfiguration.BAND_2GHZ)) != 0)) {
             return SoftApConfiguration.BAND_5GHZ;
         } else if (!is5GhzBandSupported() && SoftApConfiguration.BAND_5GHZ == band) {
             return SoftApConfiguration.BAND_2GHZ;
         } else if (isDualMode && SoftApConfiguration.BAND_5GHZ == band) {
-            return SoftApConfiguration.BAND_ANY;
+            return SoftApConfiguration.BAND_5GHZ | SoftApConfiguration.BAND_2GHZ;
         }
 
         return band;
diff --git a/tests/robotests/assets/grandfather_not_implementing_index_provider b/tests/robotests/assets/grandfather_not_implementing_index_provider
index f836e64..80e179a 100644
--- a/tests/robotests/assets/grandfather_not_implementing_index_provider
+++ b/tests/robotests/assets/grandfather_not_implementing_index_provider
@@ -30,7 +30,6 @@
 com.android.settings.bluetooth.DevicePickerFragment
 com.android.settings.dashboard.profileselector.ProfileSelectAccountFragment
 com.android.settings.dashboard.profileselector.ProfileSelectManageApplications
-com.android.settings.dashboard.profileselector.ProfileSelectStorageFragment
 com.android.settings.dashboard.profileselector.ProfileSelectLocationFragment
 com.android.settings.datausage.AppDataUsage
 com.android.settings.datausage.DataUsageList
@@ -95,3 +94,4 @@
 com.android.settings.applications.specialaccess.notificationaccess.NotificationAccessDetails
 com.android.settings.wifi.details2.WifiNetworkDetailsFragment2
 com.android.settings.wifi.savedaccesspoints2.SavedAccessPointsWifiSettings2
+com.android.settings.dashboard.profileselector.ProfileSelectRecentLocationRequestFragment
diff --git a/tests/robotests/src/com/android/settings/accessibility/MagnificationModePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/MagnificationModePreferenceControllerTest.java
new file mode 100644
index 0000000..5162bc2
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/accessibility/MagnificationModePreferenceControllerTest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.accessibility;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.provider.Settings;
+
+import com.android.settings.R;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class MagnificationModePreferenceControllerTest {
+    private static final String PREF_KEY = "screen_magnification_mode";
+    // TODO(b/146019459): Use magnification_capability.
+    private static final String KEY_CAPABILITY = Settings.System.MASTER_MONO;
+    private static final int WINDOW_SCREEN_VALUE = 2;
+    private static final int ALL_VALUE = 3;
+
+    private Context mContext;
+    private MagnificationModePreferenceController mController;
+
+    @Before
+    public void setUp() {
+        mContext = RuntimeEnvironment.application;
+        mController = new MagnificationModePreferenceController(mContext, PREF_KEY);
+    }
+
+    @Test
+    public void getSummary_saveWindowScreen_shouldReturnWindowScreenSummary() {
+        Settings.Secure.putInt(mContext.getContentResolver(),
+                KEY_CAPABILITY, WINDOW_SCREEN_VALUE);
+
+        assertThat(mController.getSummary())
+                .isEqualTo(mContext.getString(
+                        R.string.accessibility_magnification_area_settings_window_screen_summary));
+    }
+
+    @Test
+    public void getSummary_saveAll_shouldReturnAllSummary() {
+        Settings.Secure.putInt(mContext.getContentResolver(),
+                KEY_CAPABILITY, ALL_VALUE);
+
+        assertThat(mController.getSummary())
+                .isEqualTo(mContext.getString(
+                        R.string.accessibility_magnification_area_settings_all_summary));
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/accessibility/MagnificationWindowControlPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/MagnificationWindowControlPreferenceControllerTest.java
new file mode 100644
index 0000000..05dbb57
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/accessibility/MagnificationWindowControlPreferenceControllerTest.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.accessibility;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.os.UserHandle;
+import android.provider.Settings;
+
+import androidx.preference.SwitchPreference;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@RunWith(RobolectricTestRunner.class)
+public class MagnificationWindowControlPreferenceControllerTest {
+    private static final String PREF_KEY = "screen_magnification_window_control_switch";
+    // TODO(b/146019459): Use magnification_window_control_enabled.
+    private static final String KEY_CONTROL = Settings.System.MASTER_MONO;
+    private Context mContext;
+    private SwitchPreference mPreference;
+    private MagnificationWindowControlPreferenceController mController;
+
+    @Before
+    public void setUp() {
+        mContext = RuntimeEnvironment.application;
+        mPreference = new SwitchPreference(mContext);
+        mController = new MagnificationWindowControlPreferenceController(mContext, PREF_KEY);
+    }
+
+    @Test
+    public void isChecked_enabledWindowControl_shouldReturnTrue() {
+        Settings.System.putIntForUser(mContext.getContentResolver(),
+                KEY_CONTROL, State.ON, UserHandle.USER_CURRENT);
+
+        mController.updateState(mPreference);
+
+        assertThat(mController.isChecked()).isTrue();
+        assertThat(mPreference.isChecked()).isTrue();
+    }
+
+    @Test
+    public void isChecked_disabledWindowControl_shouldReturnFalse() {
+        Settings.System.putIntForUser(mContext.getContentResolver(),
+                KEY_CONTROL, State.OFF, UserHandle.USER_CURRENT);
+
+        mController.updateState(mPreference);
+
+        assertThat(mController.isChecked()).isFalse();
+        assertThat(mPreference.isChecked()).isFalse();
+    }
+
+    @Test
+    public void setChecked_setTrue_shouldEnableWindowControl() {
+        mController.setChecked(true);
+
+        assertThat(Settings.System.getIntForUser(mContext.getContentResolver(),
+                KEY_CONTROL, State.UNKNOWN, UserHandle.USER_CURRENT)).isEqualTo(State.ON);
+    }
+
+    @Test
+    public void setChecked_setFalse_shouldDisableWindowControl() {
+        mController.setChecked(false);
+
+        assertThat(Settings.System.getIntForUser(mContext.getContentResolver(),
+                KEY_CONTROL, State.UNKNOWN, UserHandle.USER_CURRENT)).isEqualTo(State.OFF);
+    }
+
+    @Retention(RetentionPolicy.SOURCE)
+    private @interface State {
+        int UNKNOWN = -1;
+        int OFF = 0;
+        int ON = 1;
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/accounts/AccountDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/accounts/AccountDashboardFragmentTest.java
index 0060875..fe57090 100644
--- a/tests/robotests/src/com/android/settings/accounts/AccountDashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/accounts/AccountDashboardFragmentTest.java
@@ -17,26 +17,55 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.content.Context;
+import android.content.pm.UserInfo;
+import android.os.UserManager;
 import android.provider.SearchIndexableResource;
 
 import com.android.settingslib.drawer.CategoryKey;
+import com.android.settingslib.search.SearchIndexableRaw;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 
+import java.util.ArrayList;
 import java.util.List;
 
 @RunWith(RobolectricTestRunner.class)
 public class AccountDashboardFragmentTest {
 
+    private static final int PROFILE_ID = 10;
+    private static final String PROFILE_NAME = "User";
+    private static final String ACCOUNT_TYPE = "com.android.settings";
+    private static final String ACCOUNT_NAME = "test account";
+
+    @Mock
+    private UserManager mUserManager;
+    @Mock
+    private AccountManager mAccountManager;
+
+    private Context mContext;
     private AccountDashboardFragment mFragment;
 
     @Before
     public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = spy(RuntimeEnvironment.application);
         mFragment = new AccountDashboardFragment();
+
+        doReturn(mUserManager).when(mContext).getSystemService(Context.USER_SERVICE);
     }
 
     @Test
@@ -45,7 +74,7 @@
     }
 
     @Test
-    public void testSearchIndexProvider_shouldIndexResource() {
+    public void searchIndexProvider_shouldIndexResource() {
         final List<SearchIndexableResource> indexRes =
                 AccountDashboardFragment.SEARCH_INDEX_DATA_PROVIDER
                         .getXmlResourcesToIndex(RuntimeEnvironment.application, true /* enabled */);
@@ -53,4 +82,36 @@
         assertThat(indexRes).isNotNull();
         assertThat(indexRes.get(0).xmlResId).isEqualTo(mFragment.getPreferenceScreenResId());
     }
+
+    @Test
+    public void searchIndexProvider_hasManagedProfile_shouldNotIndex() {
+        final List<UserInfo> infos = new ArrayList<>();
+        infos.add(new UserInfo(PROFILE_ID, PROFILE_NAME, UserInfo.FLAG_MANAGED_PROFILE));
+        doReturn(infos).when(mUserManager).getProfiles(anyInt());
+
+        final List<SearchIndexableRaw> indexRaws =
+                AccountDashboardFragment.SEARCH_INDEX_DATA_PROVIDER
+                        .getDynamicRawDataToIndex(mContext, true /* enabled */);
+
+        assertThat(indexRaws).isEmpty();
+    }
+
+    @Test
+    public void searchIndexProvider_hasAccounts_shouldIndex() {
+        final List<UserInfo> infos = new ArrayList<>();
+        infos.add(new UserInfo(PROFILE_ID, PROFILE_NAME, UserInfo.FLAG_PRIMARY));
+        doReturn(infos).when(mUserManager).getProfiles(anyInt());
+
+        final Account[] accounts = {
+                new Account(ACCOUNT_NAME, ACCOUNT_TYPE)
+        };
+        when(AccountManager.get(mContext)).thenReturn(mAccountManager);
+        doReturn(accounts).when(mAccountManager).getAccounts();
+
+        final List<SearchIndexableRaw> indexRaws =
+                AccountDashboardFragment.SEARCH_INDEX_DATA_PROVIDER
+                        .getDynamicRawDataToIndex(mContext, true /* enabled */);
+
+        assertThat(indexRaws).isNotEmpty();
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/dashboard/profileselector/ProfileSelectFragmentTest.java b/tests/robotests/src/com/android/settings/dashboard/profileselector/ProfileSelectFragmentTest.java
index 3f6f95a..1e19325 100644
--- a/tests/robotests/src/com/android/settings/dashboard/profileselector/ProfileSelectFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/profileselector/ProfileSelectFragmentTest.java
@@ -75,7 +75,7 @@
     }
 
     @Test
-    public void getTabId_setArgument_setCorrectTab() {
+    public void getTabId_setArgumentWork_setCorrectTab() {
         final Bundle bundle = new Bundle();
         bundle.putInt(SettingsActivity.EXTRA_SHOW_FRAGMENT_TAB, WORK_TAB);
 
@@ -83,6 +83,14 @@
     }
 
     @Test
+    public void getTabId_setArgumentPersonal_setCorrectTab() {
+        final Bundle bundle = new Bundle();
+        bundle.putInt(SettingsActivity.EXTRA_SHOW_FRAGMENT_TAB, PERSONAL_TAB);
+
+        assertThat(mFragment.getTabId(mActivity, bundle)).isEqualTo(PERSONAL_TAB);
+    }
+
+    @Test
     public void getTabId_setWorkId_getCorrectTab() {
         final Bundle bundle = new Bundle();
         bundle.putInt(EXTRA_USER_ID, 10);
diff --git a/tests/robotests/src/com/android/settings/development/MockLocationAppPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/MockLocationAppPreferenceControllerTest.java
index 3be4347..0a8f7d6 100644
--- a/tests/robotests/src/com/android/settings/development/MockLocationAppPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/MockLocationAppPreferenceControllerTest.java
@@ -146,6 +146,6 @@
     }
 
     private AppOpsManager.OpEntry createOpEntry(int opMode) {
-        return new OpEntry(0, opMode, new Pair[0]);
+        return new OpEntry(0, opMode, Collections.emptyMap());
     }
 }
diff --git a/tests/robotests/src/com/android/settings/development/SelectDSUPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/SelectDSUPreferenceControllerTest.java
index 0aeafc7..b2d12ef 100644
--- a/tests/robotests/src/com/android/settings/development/SelectDSUPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/SelectDSUPreferenceControllerTest.java
@@ -27,6 +27,7 @@
 import androidx.preference.SwitchPreference;
 
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
@@ -56,6 +57,7 @@
     }
 
     @Test
+    @Ignore
     public void onPreferenceChanged_settingEnabled_turnOnGpuViewUpdates() {
         mController.handlePreferenceTreeClick(mPreference);
         String flag = SystemProperties.get(DSULoader.PROPERTY_KEY_FEATURE_FLAG);
diff --git a/tests/robotests/src/com/android/settings/development/ShowRefreshRatePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/ShowRefreshRatePreferenceControllerTest.java
new file mode 100644
index 0000000..495b723
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/ShowRefreshRatePreferenceControllerTest.java
@@ -0,0 +1,129 @@
+/*
+ * 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.development;
+
+import static com.android.settings.development.ShowRefreshRatePreferenceController
+        .SURFACE_FLINGER_CODE;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.os.IBinder;
+import android.os.RemoteException;
+
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreference;
+
+import com.android.settings.testutils.shadow.ShadowParcel;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(RobolectricTestRunner.class)
+public class ShowRefreshRatePreferenceControllerTest {
+
+    @Mock
+    private Context mContext;
+    @Mock
+    private PreferenceScreen mScreen;
+    @Mock
+    private SwitchPreference mPreference;
+    @Mock
+    private IBinder mSurfaceFlinger;
+
+    private ShowRefreshRatePreferenceController mController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mController = spy(new ShowRefreshRatePreferenceController(mContext));
+        ReflectionHelpers.setField(mController, "mSurfaceFlinger", mSurfaceFlinger);
+        doNothing().when(mController).writeShowRefreshRateSetting(anyBoolean());
+        when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
+        mController.displayPreference(mScreen);
+    }
+
+    @Test
+    public void onPreferenceChange_settingToggledOn_shouldWriteTrueToShowRefreshRateSetting() {
+        mController.onPreferenceChange(mPreference, true /* new value */);
+
+        verify(mController).writeShowRefreshRateSetting(true);
+    }
+
+    @Test
+    public void onPreferenceChange_settingToggledOff_shouldWriteFalseToShowRefreshRateSetting() {
+        mController.onPreferenceChange(mPreference, false /* new value */);
+
+        verify(mController).writeShowRefreshRateSetting(false);
+    }
+
+    @Test
+    @Config(shadows = ShadowParcel.class)
+    public void updateState_settingEnabled_shouldCheckPreference() throws RemoteException {
+        ShadowParcel.sReadIntResult = 1;
+        doReturn(true).when(mSurfaceFlinger)
+            .transact(eq(SURFACE_FLINGER_CODE), any(), any(), eq(0 /* flags */));
+        mController.updateState(mPreference);
+
+        verify(mPreference).setChecked(true);
+    }
+
+    @Test
+    @Config(shadows = {ShadowParcel.class})
+    public void updateState_settingDisabled_shouldUnCheckPreference() throws RemoteException {
+        ShadowParcel.sReadIntResult = 0;
+        doReturn(true).when(mSurfaceFlinger)
+            .transact(eq(SURFACE_FLINGER_CODE), any(), any(), eq(0 /* flags */));
+        mController.updateState(mPreference);
+
+        verify(mPreference).setChecked(false);
+    }
+
+    @Test
+    public void onDeveloperOptionsSwitchDisabled_preferenceUnchecked_shouldNotTurnOffPreference() {
+        when(mPreference.isChecked()).thenReturn(false);
+        mController.onDeveloperOptionsSwitchDisabled();
+
+        verify(mController, never()).writeShowRefreshRateSetting(anyBoolean());
+        verify(mPreference, never()).setChecked(anyBoolean());
+        verify(mPreference).setEnabled(false);
+    }
+
+    @Test
+    public void onDeveloperOptionsSwitchDisabled_preferenceChecked_shouldTurnOffPreference() {
+        when(mPreference.isChecked()).thenReturn(true);
+        mController.onDeveloperOptionsSwitchDisabled();
+
+        verify(mController).writeShowRefreshRateSetting(false);
+        verify(mPreference).setChecked(false);
+        verify(mPreference).setEnabled(false);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragmentTest.java b/tests/robotests/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragmentTest.java
index 572f1d8..b2ac7f1 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragmentTest.java
@@ -28,6 +28,7 @@
 
 import com.android.settings.deviceinfo.BuildNumberPreferenceController;
 
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.RobolectricTestRunner;
@@ -35,6 +36,7 @@
 import org.robolectric.util.ReflectionHelpers;
 
 @RunWith(RobolectricTestRunner.class)
+@Ignore
 public class MyDeviceInfoFragmentTest {
 
     private MyDeviceInfoFragment mMyDeviceInfoFragment;
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/RestrictAppPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/RestrictAppPreferenceControllerTest.java
index 1febbe4..598ef6e 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/RestrictAppPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/RestrictAppPreferenceControllerTest.java
@@ -54,6 +54,7 @@
 import org.robolectric.RobolectricTestRunner;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
 @RunWith(RobolectricTestRunner.class)
@@ -84,10 +85,12 @@
         MockitoAnnotations.initMocks(this);
         final List<AppOpsManager.OpEntry> allowOps = new ArrayList<>();
         allowOps.add(new AppOpsManager.OpEntry(
-                AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, AppOpsManager.MODE_ALLOWED, new Pair[0]));
+                AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, AppOpsManager.MODE_ALLOWED,
+                Collections.emptyMap()));
         final List<AppOpsManager.OpEntry> restrictedOps = new ArrayList<>();
         restrictedOps.add(new AppOpsManager.OpEntry(
-                AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, AppOpsManager.MODE_IGNORED, new Pair[0]));
+                AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, AppOpsManager.MODE_IGNORED,
+                Collections.emptyMap()));
         mAllowedPackageOps = new AppOpsManager.PackageOps(
                 ALLOWED_PACKAGE_NAME, ALLOWED_UID, allowOps);
         mRestrictedPackageOps = new AppOpsManager.PackageOps(
diff --git a/tests/robotests/src/com/android/settings/gestures/BackGestureIndicatorViewTest.java b/tests/robotests/src/com/android/settings/gestures/BackGestureIndicatorViewTest.java
new file mode 100644
index 0000000..8d43aaa
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/gestures/BackGestureIndicatorViewTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.gestures;
+
+import static org.junit.Assert.assertEquals;
+
+import android.content.Context;
+import android.widget.ImageView;
+
+import com.android.settings.R;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class BackGestureIndicatorViewTest {
+
+    private Context mContext;
+
+    private BackGestureIndicatorDrawable mLeftDrawable;
+    private BackGestureIndicatorDrawable mRightDrawable;
+
+    private BackGestureIndicatorView mView;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mContext = RuntimeEnvironment.application;
+        mView = new BackGestureIndicatorView(mContext);
+
+        mLeftDrawable = (BackGestureIndicatorDrawable) ((ImageView) mView.findViewById(
+                R.id.indicator_left)).getDrawable();
+        mRightDrawable = (BackGestureIndicatorDrawable) ((ImageView) mView.findViewById(
+                R.id.indicator_right)).getDrawable();
+    }
+
+    @Test
+    public void testSetIndicatoreWidth() {
+        mView.setIndicatorWidth(25, true);
+        mView.setIndicatorWidth(52, false);
+
+        assertEquals(25, mLeftDrawable.getWidth());
+        assertEquals(52, mRightDrawable.getWidth());
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/network/MobileNetworkSummaryControllerTest.java b/tests/robotests/src/com/android/settings/network/MobileNetworkSummaryControllerTest.java
index 5913f7b..f6bc05a 100644
--- a/tests/robotests/src/com/android/settings/network/MobileNetworkSummaryControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/MobileNetworkSummaryControllerTest.java
@@ -40,12 +40,16 @@
 import android.telephony.euicc.EuiccManager;
 import android.text.TextUtils;
 
+import androidx.lifecycle.Lifecycle;
+import androidx.preference.PreferenceScreen;
+
 import com.android.settings.network.telephony.MobileNetworkActivity;
 import com.android.settings.widget.AddPreference;
 import com.android.settingslib.RestrictedLockUtils;
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
@@ -56,10 +60,8 @@
 
 import java.util.Arrays;
 
-import androidx.lifecycle.Lifecycle;
-import androidx.preference.PreferenceScreen;
-
 @RunWith(RobolectricTestRunner.class)
+@Ignore
 public class MobileNetworkSummaryControllerTest {
     @Mock
     private Lifecycle mLifecycle;
diff --git a/tests/robotests/src/com/android/settings/network/TetherEnablerTest.java b/tests/robotests/src/com/android/settings/network/TetherEnablerTest.java
new file mode 100644
index 0000000..06f3893
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/network/TetherEnablerTest.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothPan;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.net.ConnectivityManager;
+import android.net.NetworkPolicyManager;
+import android.net.wifi.WifiManager;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settings.widget.SwitchBar;
+import com.android.settings.widget.SwitchBarController;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.util.ReflectionHelpers;
+
+import java.util.concurrent.atomic.AtomicReference;
+
+@RunWith(RobolectricTestRunner.class)
+public class TetherEnablerTest {
+    @Mock
+    private WifiManager mWifiManager;
+    @Mock
+    private ConnectivityManager mConnectivityManager;
+    @Mock
+    private NetworkPolicyManager mNetworkPolicyManager;
+    @Mock
+    private BluetoothPan mBluetoothPan;
+    @Mock
+    private SharedPreferences mSharedPreferences;
+
+    private SwitchBar mSwitchBar;
+    private TetherEnabler mEnabler;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        Context context = spy(ApplicationProvider.getApplicationContext());
+        AtomicReference<BluetoothPan> panReference = spy(AtomicReference.class);
+        mSwitchBar = new SwitchBar(context);
+        when(context.getSystemService(Context.WIFI_SERVICE)).thenReturn(mWifiManager);
+        when(context.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(
+                mConnectivityManager);
+        when(context.getSystemService(Context.NETWORK_POLICY_SERVICE)).thenReturn(
+                mNetworkPolicyManager);
+        when(mConnectivityManager.getTetherableIfaces()).thenReturn(new String[0]);
+        panReference.set(mBluetoothPan);
+        mEnabler = new TetherEnabler(context, new SwitchBarController(mSwitchBar), panReference);
+    }
+
+    @Test
+    public void lifecycle_onStart_setCheckedCorrectly() {
+        when(mConnectivityManager.getTetheredIfaces()).thenReturn(new String[]{""});
+
+        mEnabler.onStart();
+        assertThat(mSwitchBar.isChecked()).isTrue();
+    }
+
+    @Test
+    public void startTether_fail_resetSwitchBar() {
+        when(mNetworkPolicyManager.getRestrictBackground()).thenReturn(false);
+
+        mEnabler.startTether();
+        mEnabler.mOnStartTetheringCallback.onTetheringFailed();
+
+        assertThat(mSwitchBar.isChecked()).isFalse();
+        assertThat(mSwitchBar.isEnabled()).isTrue();
+    }
+
+    @Test
+    public void onDataSaverChanged_setsEnabledCorrectly() {
+        assertThat(mSwitchBar.isEnabled()).isTrue();
+
+        // try to turn data saver on
+        when(mNetworkPolicyManager.getRestrictBackground()).thenReturn(true);
+        mEnabler.onDataSaverChanged(true);
+        assertThat(mSwitchBar.isEnabled()).isFalse();
+
+        // lets turn data saver off again
+        when(mNetworkPolicyManager.getRestrictBackground()).thenReturn(false);
+        mEnabler.onDataSaverChanged(false);
+        assertThat(mSwitchBar.isEnabled()).isTrue();
+    }
+
+    @Test
+    public void onSwitchToggled_onlyStartsWifiTetherWhenNeeded() {
+        when(mWifiManager.isWifiApEnabled()).thenReturn(true);
+        mEnabler.onSwitchToggled(true);
+
+        verify(mConnectivityManager, never()).startTethering(anyInt(), anyBoolean(), any(), any());
+
+        doReturn(false).when(mWifiManager).isWifiApEnabled();
+        mEnabler.onSwitchToggled(true);
+
+        verify(mConnectivityManager, times(1))
+                .startTethering(anyInt(), anyBoolean(), any(), any());
+    }
+
+    @Test
+    public void onSwitchToggled_shouldStartUSBTetherWhenSelected() {
+        SharedPreferences preference = mock(SharedPreferences.class);
+        ReflectionHelpers.setField(mEnabler, "mSharedPreferences", preference);
+        when(preference.getBoolean(mEnabler.WIFI_TETHER_KEY, true)).thenReturn(false);
+        when(preference.getBoolean(mEnabler.USB_TETHER_KEY, false)).thenReturn(true);
+        when(preference.getBoolean(mEnabler.BLUETOOTH_TETHER_KEY, true)).thenReturn(false);
+
+        mEnabler.startTether();
+        verify(mConnectivityManager, times(1))
+                .startTethering(eq(ConnectivityManager.TETHERING_USB), anyBoolean(), any(), any());
+        verify(mConnectivityManager, never())
+                .startTethering(eq(ConnectivityManager.TETHERING_WIFI), anyBoolean(), any(), any());
+        verify(mConnectivityManager, never()).startTethering(
+                eq(ConnectivityManager.TETHERING_BLUETOOTH), anyBoolean(), any(), any());
+    }
+
+    @Test
+    public void startTether_startsBluetoothTetherWhenOff() {
+        BluetoothAdapter adapter = mock(BluetoothAdapter.class);
+        ReflectionHelpers.setField(mEnabler, "mBluetoothAdapter", adapter);
+        when(adapter.getState()).thenReturn(BluetoothAdapter.STATE_OFF);
+
+        mEnabler.startTethering(ConnectivityManager.TETHERING_BLUETOOTH);
+        verify(adapter, times(1)).enable();
+
+        when(adapter.getState()).thenReturn(BluetoothAdapter.STATE_ON);
+        mEnabler.startTethering(ConnectivityManager.TETHERING_BLUETOOTH);
+        verify(mConnectivityManager, times(1)).startTethering(
+                eq(ConnectivityManager.TETHERING_BLUETOOTH), anyBoolean(), any(), any());
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/sim/SimListDialogFragmentTest.java b/tests/robotests/src/com/android/settings/sim/SimListDialogFragmentTest.java
index 6a9590b..0fefbe0 100644
--- a/tests/robotests/src/com/android/settings/sim/SimListDialogFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/sim/SimListDialogFragmentTest.java
@@ -36,6 +36,7 @@
 import com.android.settings.R;
 import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
 
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.RobolectricTestRunner;
@@ -95,6 +96,7 @@
     }
 
     @Test
+    @Ignore
     public void onCreateDialog_twoSubscriptionsAskEveryTime_threeSubsForDisplay() {
         final int dialogType = SMS_PICK;
         setDialogType(dialogType);
diff --git a/tests/robotests/src/com/android/settings/wifi/addappnetworks/AddAppNetworksFragmentTest.java b/tests/robotests/src/com/android/settings/wifi/addappnetworks/AddAppNetworksFragmentTest.java
index 765f14d..065186b 100644
--- a/tests/robotests/src/com/android/settings/wifi/addappnetworks/AddAppNetworksFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/addappnetworks/AddAppNetworksFragmentTest.java
@@ -21,6 +21,7 @@
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
 
+import android.app.settings.SettingsEnums;
 import android.net.wifi.WifiConfiguration;
 import android.os.Bundle;
 import android.os.Parcelable;
@@ -139,6 +140,12 @@
                 0).mWifiConfiguration.SSID).isEqualTo(FAKE_NEW_OPEN_SSID);
     }
 
+    @Test
+    public void getMetricsCategory_shouldReturnPanelAddWifiNetworks() {
+        assertThat(mAddAppNetworksFragment.getMetricsCategory()).isEqualTo(
+                SettingsEnums.PANEL_ADD_WIFI_NETWORKS);
+    }
+
     private void addOneSavedNetworkConfig(@NonNull WifiConfiguration wifiConfiguration) {
         if (mFakeSavedNetworksList == null) {
             mFakeSavedNetworksList = new ArrayList<>();
@@ -180,5 +187,4 @@
         }
         return config;
     }
-
 }
diff --git a/tests/robotests/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2Test.java b/tests/robotests/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2Test.java
index 5b125e9..e60303e 100644
--- a/tests/robotests/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2Test.java
+++ b/tests/robotests/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2Test.java
@@ -22,7 +22,6 @@
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.nullable;
-import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.mock;
@@ -77,11 +76,11 @@
 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;
-import com.android.settingslib.wifi.WifiTracker;
-import com.android.settingslib.wifi.WifiTrackerFactory;
+import com.android.wifitrackerlib.NetworkDetailsTracker;
+import com.android.wifitrackerlib.WifiEntry;
 
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Answers;
@@ -99,10 +98,12 @@
 import java.net.Inet4Address;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.stream.Collectors;
 
+// TODO(b/143326832): Should add test cases for connect button.
+// TODO(b/143326832): WifiEntry is not mature, should remove @Ignore after it's constructed.
+@Ignore
 @RunWith(RobolectricTestRunner.class)
 @Config(shadows = {ShadowDevicePolicyManager.class, ShadowEntityHeaderController.class})
 public class WifiDetailPreferenceController2Test {
@@ -115,14 +116,15 @@
     private static final String MAC_ADDRESS = "01:23:45:67:89:ab";
     private static final String RANDOMIZED_MAC_ADDRESS = "RANDOMIZED_MAC_ADDRESS";
     private static final String FACTORY_MAC_ADDRESS = "FACTORY_MAC_ADDRESS";
-    private static final String SECURITY = "None";
+    // TODO(b/143326832): Add WifiEntry#getSecurityString
+    //private static final String SECURITY = "None";
     private static final String FQDN = "fqdn";
 
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private PreferenceScreen mMockScreen;
 
     @Mock
-    private AccessPoint mMockAccessPoint;
+    private WifiEntry mMockWifiEntry;
     @Mock
     private FragmentActivity mMockActivity;
     @Mock
@@ -140,7 +142,7 @@
     @Mock
     private WifiManager mMockWifiManager;
     @Mock
-    private WifiTracker mMockWifiTracker;
+    private NetworkDetailsTracker mMockNetworkDetailsTracker;
     @Mock
     private MetricsFeatureProvider mMockMetricsFeatureProvider;
     @Mock
@@ -258,10 +260,10 @@
         mLifecycle = new Lifecycle(mLifecycleOwner);
 
         when(mContext.getPackageManager()).thenReturn(mMockPackageManager);
-        when(mMockAccessPoint.getConfig()).thenReturn(mMockWifiConfig);
-        when(mMockAccessPoint.getLevel()).thenReturn(LEVEL);
-        when(mMockAccessPoint.getSecurityString(false)).thenReturn(SECURITY);
-        when(mMockAccessPoint.getSsidStr()).thenReturn(SSID);
+        when(mMockWifiEntry.getLevel()).thenReturn(LEVEL);
+        // TODO(b/143326832): Add WifiEntry#getSecurityString
+        //when(mMockWifiEntry.getSecurityString(false)).thenReturn(SECURITY);
+        when(mMockWifiEntry.getTitle()).thenReturn(SSID);
         when(mMockConnectivityManager.getNetworkInfo(any(Network.class)))
                 .thenReturn(mMockNetworkInfo);
         doNothing().when(mMockConnectivityManager).registerNetworkCallback(
@@ -293,44 +295,30 @@
     }
 
     private void setUpForConnectedNetwork() {
-        when(mMockAccessPoint.isActive()).thenReturn(true);
-        ArrayList list = new ArrayList<>();
-        list.add(mMockAccessPoint);
-        when(mMockWifiTracker.getAccessPoints()).thenReturn(list);
-        WifiTrackerFactory.setTestingWifiTracker(mMockWifiTracker);
-        when(mMockAccessPoint.matches(any(AccessPoint.class))).thenReturn(true);
-        when(mMockAccessPoint.isReachable()).thenReturn(true);
+        when(mMockNetworkDetailsTracker.getWifiEntry()).thenReturn(mMockWifiEntry);
+        when(mMockWifiEntry.getConnectedState()).thenReturn(WifiEntry.CONNECTED_STATE_CONNECTED);
 
         mController = newWifiDetailPreferenceController2();
     }
 
     private void setUpForDisconnectedNetwork() {
-        when(mMockAccessPoint.isActive()).thenReturn(false);
-        ArrayList list = new ArrayList<>();
-        list.add(mMockAccessPoint);
-        when(mMockWifiTracker.getAccessPoints()).thenReturn(list);
-        WifiTrackerFactory.setTestingWifiTracker(mMockWifiTracker);
-        when(mMockAccessPoint.matches(any(AccessPoint.class))).thenReturn(true);
-        when(mMockAccessPoint.isReachable()).thenReturn(true);
+        when(mMockNetworkDetailsTracker.getWifiEntry()).thenReturn(mMockWifiEntry);
+        when(mMockWifiEntry.getConnectedState()).thenReturn(WifiEntry.CONNECTED_STATE_DISCONNECTED);
 
         mController = newWifiDetailPreferenceController2();
     }
 
     private void setUpForNotInRangeNetwork() {
-        when(mMockAccessPoint.isActive()).thenReturn(false);
-        ArrayList list = new ArrayList<>();
-        list.add(mMockAccessPoint);
-        when(mMockWifiTracker.getAccessPoints()).thenReturn(list);
-        WifiTrackerFactory.setTestingWifiTracker(mMockWifiTracker);
-        when(mMockAccessPoint.matches(any(AccessPoint.class))).thenReturn(false);
-        when(mMockAccessPoint.isReachable()).thenReturn(false);
+        when(mMockWifiEntry.getConnectedState()).thenReturn(WifiEntry.CONNECTED_STATE_DISCONNECTED);
+        when(mMockNetworkDetailsTracker.getWifiEntry()).thenReturn(mMockWifiEntry);
+        when(mMockWifiEntry.getLevel()).thenReturn(WifiEntry.WIFI_LEVEL_UNREACHABLE);
 
         mController = newWifiDetailPreferenceController2();
     }
 
     private WifiDetailPreferenceController2 newWifiDetailPreferenceController2() {
-        return new WifiDetailPreferenceController2(
-                mMockAccessPoint,
+        return spy(new WifiDetailPreferenceController2(
+                mMockWifiEntry,
                 mMockConnectivityManager,
                 mContext,
                 mMockFragment,
@@ -338,7 +326,7 @@
                 mLifecycle,
                 mMockWifiManager,
                 mMockMetricsFeatureProvider,
-                mMockIconInjector);
+                mMockIconInjector));
     }
 
     private void setupMockedPreferenceScreen() {
@@ -392,6 +380,7 @@
         assertThat(mController.isAvailable()).isTrue();
     }
 
+    /* TODO(b/143326832): Add WifiEntry#getSecurityString
     @Test
     public void securityPreference_stringShouldBeSet() {
         setUpForConnectedNetwork();
@@ -399,6 +388,7 @@
 
         verify(mMockSecurityPref).setSummary(SECURITY);
     }
+    */
 
     @Test
     public void latestWifiInfo_shouldBeFetchedInDisplayPreferenceForConnectedNetwork() {
@@ -506,7 +496,7 @@
     public void entityHeader_shouldHaveLabelSetToTitle() {
         setUpForConnectedNetwork();
         String label = "title";
-        when(mMockAccessPoint.getTitle()).thenReturn(label);
+        when(mMockWifiEntry.getTitle()).thenReturn(label);
 
         displayAndResume();
 
@@ -517,8 +507,7 @@
     public void entityHeader_shouldHaveSummarySet() {
         setUpForConnectedNetwork();
         String summary = "summary";
-        when(mMockAccessPoint.getSettingsSummary(true /*convertSavedAsDisconnected*/))
-                .thenReturn(summary);
+        when(mMockWifiEntry.getSummary()).thenReturn(summary);
 
         displayAndResume();
 
@@ -531,7 +520,7 @@
 
         displayAndResume();
 
-        verify(mMockAccessPoint, times(1)).getSettingsSummary(true /*convertSavedAsDisconnected*/);
+        verify(mMockWifiEntry, times(1)).getSummary();
     }
 
     @Test
@@ -674,6 +663,7 @@
         verify(mMockRxLinkSpeedPref, never()).setSummary(any(String.class));
     }
 
+    /* TODO(b/143326832): Support Passpoint test cases while WifiTracker2 supports it.
     @Test
     public void ssidPref_shouldHaveDetailTextSetForPasspointR1() {
         setUpForConnectedNetwork();
@@ -708,6 +698,7 @@
 
         verify(mMockSsidPref).setVisible(false);
     }
+    */
 
     @Test
     public void macAddressPref_shouldVisibleForConnectedNetwork() {
@@ -958,8 +949,7 @@
                 .thenReturn(new NetworkCapabilities(nc));
 
         String summary = "Connected, no Internet";
-        when(mMockAccessPoint.getSettingsSummary(true /*convertSavedAsDisconnected*/))
-                .thenReturn(summary);
+        when(mMockWifiEntry.getSummary()).thenReturn(summary);
 
         InOrder inOrder = inOrder(mMockHeaderController);
         displayAndResume();
@@ -968,8 +958,7 @@
         // Check that an irrelevant capability update does not update the access point summary, as
         // doing so could cause unnecessary jank...
         summary = "Connected";
-        when(mMockAccessPoint.getSettingsSummary(true /*convertSavedAsDisconnected*/))
-                .thenReturn(summary);
+        when(mMockWifiEntry.getSummary()).thenReturn(summary);
         updateNetworkCapabilities(nc);
         inOrder.verify(mMockHeaderController, never()).setSummary(any(CharSequence.class));
 
@@ -979,8 +968,7 @@
         inOrder.verify(mMockHeaderController).setSummary(summary);
 
         summary = "Connected, no Internet";
-        when(mMockAccessPoint.getSettingsSummary(true /*convertSavedAsDisconnected*/))
-                .thenReturn(summary);
+        when(mMockWifiEntry.getSummary()).thenReturn(summary);
 
         // Another irrelevant update won't cause the UI to refresh...
         updateNetworkCapabilities(nc);
@@ -993,16 +981,14 @@
 
         // UI will be refreshed when private DNS is broken.
         summary = "Private DNS server cannot be accessed";
-        when(mMockAccessPoint.getSettingsSummary(true /* convertSavedAsDisconnected */))
-                .thenReturn(summary);
+        when(mMockWifiEntry.getSummary()).thenReturn(summary);
         nc.setPrivateDnsBroken(true);
         updateNetworkCapabilities(nc);
         inOrder.verify(mMockHeaderController).setSummary(summary);
 
         // UI will be refreshed when device connects to a partial connectivity network.
         summary = "Limited connection";
-        when(mMockAccessPoint.getSettingsSummary(true /*convertSavedAsDisconnected*/))
-                .thenReturn(summary);
+        when(mMockWifiEntry.getSummary()).thenReturn(summary);
         nc.addCapability(NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY);
         updateNetworkCapabilities(nc);
         inOrder.verify(mMockHeaderController).setSummary(summary);
@@ -1017,7 +1003,7 @@
     @Test
     public void canForgetNetwork_shouldInvisibleIfWithoutConfiguration() {
         setUpForConnectedNetwork();
-        when(mMockAccessPoint.getConfig()).thenReturn(null);
+        when(mMockWifiEntry.isSaved()).thenReturn(false);
         mController = newWifiDetailPreferenceController2();
 
         displayAndResume();
@@ -1029,7 +1015,7 @@
     public void canForgetNetwork_ephemeral() {
         setUpForConnectedNetwork();
         when(mMockWifiInfo.isEphemeral()).thenReturn(true);
-        when(mMockAccessPoint.getConfig()).thenReturn(null);
+        when(mMockWifiEntry.isSaved()).thenReturn(false);
 
         displayAndResume();
 
@@ -1057,7 +1043,7 @@
     @Test
     public void canShareNetwork_shouldInvisibleIfWithoutConfiguration() {
         setUpForConnectedNetwork();
-        when(mMockAccessPoint.getConfig()).thenReturn(null);
+        when(mMockWifiEntry.isSaved()).thenReturn(false);
 
         displayAndResume();
 
@@ -1129,6 +1115,7 @@
                 .action(mMockActivity, MetricsProto.MetricsEvent.ACTION_WIFI_FORGET);
     }
 
+    /* TODO(b/143326832): Support Passpoint test cases while WifiTracker2 supports it.
     @Test
     public void forgetNetwork_shouldShowDialog() {
         setUpForConnectedNetwork();
@@ -1146,6 +1133,7 @@
                 .action(mMockActivity, MetricsProto.MetricsEvent.ACTION_WIFI_FORGET);
         verify(spyController).showConfirmForgetDialog();
     }
+    */
 
     @Test
     public void networkStateChangedIntent_shouldRefetchInfo() {
@@ -1344,7 +1332,7 @@
         when(mMockWifiManager.isWifiEnabled()).thenReturn(true);
         InOrder inOrder = inOrder(mMockButtonsPref);
         String label = "title";
-        when(mMockAccessPoint.getTitle()).thenReturn(label);
+        when(mMockWifiEntry.getTitle()).thenReturn(label);
         setUpForToast();
 
         displayAndResume();
@@ -1360,8 +1348,7 @@
         verifyConnectBtnSetUpAsConnecting(inOrder);
 
         // update as connected
-        when(mMockAccessPoint.isActive()).thenReturn(true);
-        mController.updateAccessPoint();
+        when(mMockWifiEntry.getConnectedState()).thenReturn(WifiEntry.CONNECTED_STATE_CONNECTED);
 
         // check connect button invisible, be init as default state and toast success message
         verifyConnectBtnBeInitAsDefault(inOrder);
@@ -1419,364 +1406,21 @@
     }
 
     @Test
-    public void testConnectButton_clickConnectButTimeout_displayFailMessage() {
-        setUpForDisconnectedNetwork();
-        when(mMockWifiManager.isWifiEnabled()).thenReturn(true);
-        InOrder inOrder = inOrder(mMockButtonsPref);
-        setUpForToast();
-
-        displayAndResume();
-
-        // check connect button exist
-        verifyConnectBtnSetUpAsVisible(inOrder);
-
-        // click connect button
-        mController.connectNetwork();
-
-        // check display button as connecting
-        verify(mMockWifiManager, times(1)).connect(anyInt(), any(WifiManager.ActionListener.class));
-        verifyConnectBtnSetUpAsConnecting(inOrder);
-
-        // update as failed
-        mController.sTimer.onFinish();
-
-        // check connect button visible, be init as default and toast failed message
-        verifyConnectBtnBeInitAsDefault(inOrder);
-        inOrder.verify(mMockButtonsPref, times(1)).setButton3Visible(true);
-        assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
-                mContext.getString(R.string.wifi_failed_connect_message));
-    }
-
-    @Test
-    public void testConnectButton_clickConnectButTimeout_displayNotInRangeMessage() {
-        setUpForNotInRangeNetwork();
-        when(mMockWifiManager.isWifiEnabled()).thenReturn(true);
-        InOrder inOrder = inOrder(mMockButtonsPref);
-        setUpForToast();
-
-        displayAndResume();
-
-        // check connect button exist
-        verifyConnectBtnSetUpAsVisible(inOrder);
-
-        // click connect button
-        mController.connectNetwork();
-
-        // check display button as connecting
-        verify(mMockWifiManager, times(1)).connect(anyInt(), any(WifiManager.ActionListener.class));
-        verifyConnectBtnSetUpAsConnecting(inOrder);
-
-        // update as failed
-        mController.sTimer.onFinish();
-
-        // check connect button visible, be init as default and toast failed message
-        verifyConnectBtnBeInitAsDefault(inOrder);
-        inOrder.verify(mMockButtonsPref, times(1)).setButton3Visible(true);
-        assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
-                mContext.getString(R.string.wifi_not_in_range_message));
-    }
-
-    @Test
-    public void testConnectButton_clickConnectWhenWiFiDisabled_displaySuccessMessage() {
-        setUpForDisconnectedNetwork();
-        when(mMockWifiManager.isWifiEnabled()).thenReturn(false); // wifi disabled
-        InOrder inOrder = inOrder(mMockButtonsPref);
-        String label = "title";
-        when(mMockAccessPoint.getTitle()).thenReturn(label);
-        setUpForToast();
-
-        displayAndResume();
-
-        // check connect button exist
-        verifyConnectBtnSetUpAsVisible(inOrder);
-
-        // click connect button
-        mController.connectNetwork();
-
-        // check turn on Wi-Fi, display button as connecting and toast turn on Wi-Fi message
-        verify(mMockWifiManager, times(1)).setWifiEnabled(true);
-        verifyConnectBtnSetUpAsConnecting(inOrder);
-        assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
-                mContext.getString(R.string.wifi_turned_on_message));
-
-        // notify Wi-Fi enabled
-        mController.mWifiListener.onWifiStateChanged(WifiManager.WIFI_STATE_ENABLED);
-
-        // check had connect network and icon display as expected
-        verify(mMockWifiManager, times(1)).connect(anyInt(), any(WifiManager.ActionListener.class));
-        verifyConnectBtnSetUpAsConnecting(inOrder);
-
-        // update as connected
-        when(mMockAccessPoint.isActive()).thenReturn(true);
-        mController.updateAccessPoint();
-
-        // check connect button invisible, be init as default state and toast success message
-        verifyConnectBtnBeInitAsDefault(inOrder);
-        inOrder.verify(mMockButtonsPref, times(1)).setButton3Visible(false);
-        assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
-                mContext.getString(R.string.wifi_connected_to_message, label));
-    }
-
-    @Test
-    public void testConnectButton_clickConnectWhenWiFiDisabled_failedToConnectWiFi() {
-        setUpForDisconnectedNetwork();
-        when(mMockWifiManager.isWifiEnabled()).thenReturn(false); // wifi disabled
-        InOrder inOrder = inOrder(mMockButtonsPref);
-        setUpForToast();
-
-        displayAndResume();
-
-        // check connect button exist
-        verifyConnectBtnSetUpAsVisible(inOrder);
-
-        // click connect button
-        mController.connectNetwork();
-
-        // check turn on Wi-Fi, display button as connecting and toast turn on Wi-Fi message
-        verify(mMockWifiManager, times(1)).setWifiEnabled(true);
-        verifyConnectBtnSetUpAsConnecting(inOrder);
-        assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
-                mContext.getString(R.string.wifi_turned_on_message));
-
-        // notify Wi-Fi enabled
-        mController.mWifiListener.onWifiStateChanged(WifiManager.WIFI_STATE_ENABLED);
-
-        // check had connect network and icon display as expected
-        verify(mMockWifiManager, times(1)).connect(anyInt(), any(WifiManager.ActionListener.class));
-        verifyConnectBtnSetUpAsConnecting(inOrder);
-
-        // update as failed
-        mController.sTimer.onFinish();
-
-        // check connect button visible, be init as default and toast failed message
-        verifyConnectBtnBeInitAsDefault(inOrder);
-        inOrder.verify(mMockButtonsPref, times(1)).setButton3Visible(true);
-        assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
-                mContext.getString(R.string.wifi_failed_connect_message));
-    }
-
-    @Test
-    public void
-            testConnectButton_clickConnectWhenWiFiDisabled_failedToConnectWifiBecauseNotInRange() {
-        setUpForNotInRangeNetwork();
-        when(mMockWifiManager.isWifiEnabled()).thenReturn(false); // wifi disabled
-        InOrder inOrder = inOrder(mMockButtonsPref);
-        setUpForToast();
-
-        displayAndResume();
-
-        // check connect button exist
-        verifyConnectBtnSetUpAsVisible(inOrder);
-
-        // click connect button
-        mController.connectNetwork();
-
-        // check turn on Wi-Fi, display button as connecting and toast turn on Wi-Fi message
-        verify(mMockWifiManager, times(1)).setWifiEnabled(true);
-        verifyConnectBtnSetUpAsConnecting(inOrder);
-        assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
-                mContext.getString(R.string.wifi_turned_on_message));
-
-        // notify Wi-Fi enabled
-        mController.mWifiListener.onWifiStateChanged(WifiManager.WIFI_STATE_ENABLED);
-
-        // check had connect network and icon display as expected
-        verify(mMockWifiManager, times(1)).connect(anyInt(), any(WifiManager.ActionListener.class));
-        verifyConnectBtnSetUpAsConnecting(inOrder);
-
-        // update as failed
-        mController.sTimer.onFinish();
-
-        // check connect button visible, be init as default and toast failed message
-        verifyConnectBtnBeInitAsDefault(inOrder);
-        inOrder.verify(mMockButtonsPref, times(1)).setButton3Visible(true);
-        assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
-                mContext.getString(R.string.wifi_not_in_range_message));
-    }
-
-    @Test
-    public void testConnectButton_clickConnectWhenWiFiDisabled_failedToEnableWifi() {
-        setUpForDisconnectedNetwork();
-        when(mMockWifiManager.isWifiEnabled()).thenReturn(false); // wifi disabled
-        InOrder inOrder = inOrder(mMockButtonsPref);
-        setUpForToast();
-
-        displayAndResume();
-
-        // check connect button exist
-        verifyConnectBtnSetUpAsVisible(inOrder);
-
-        // click connect button
-        mController.connectNetwork();
-
-        // check turn on Wi-Fi, display button as connecting and toast turn on Wi-Fi message
-        verify(mMockWifiManager, times(1)).setWifiEnabled(true);
-        verifyConnectBtnSetUpAsConnecting(inOrder);
-        assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
-                mContext.getString(R.string.wifi_turned_on_message));
-
-        // notify turn on Wi-Fi failed
-        mController.sTimer.onFinish();
-
-        // check connect button visible, be init as default and toast failed message
-        verifyConnectBtnBeInitAsDefault(inOrder);
-        inOrder.verify(mMockButtonsPref, times(1)).setButton3Visible(true);
-        assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
-                mContext.getString(R.string.wifi_failed_connect_message));
-    }
-
-    @Test
-    public void testConnectButton_clickConnectAndBackKey_ignoreTimeoutEvent() {
-        setUpForDisconnectedNetwork();
-        when(mMockWifiManager.isWifiEnabled()).thenReturn(true);
-        InOrder inOrder = inOrder(mMockButtonsPref);
-        setUpForToast();
-
-        displayAndResume();
-
-        // check connect button exist
-        verifyConnectBtnSetUpAsVisible(inOrder);
-
-        // click connect button
-        mController.connectNetwork();
-
-        // check display button as connecting
-        verify(mMockWifiManager, times(1)).connect(anyInt(), any(WifiManager.ActionListener.class));
-        verifyConnectBtnSetUpAsConnecting(inOrder);
-
-        // leave detail page
-        when(mMockFragment.getActivity()).thenReturn(null);
-
-        // timeout happened
-        mController.sTimer.onFinish();
-
-        // check connect button visible, be init as default and toast failed message
-        inOrder.verify(mMockButtonsPref, never()).setButton3Text(R.string.wifi_connect);
-        inOrder.verify(mMockButtonsPref, never()).setButton3Icon(R.drawable.ic_settings_wireless);
-        inOrder.verify(mMockButtonsPref, never()).setButton3Enabled(true);
-        inOrder.verify(mMockButtonsPref, never()).setButton3Visible(true);
-        assertThat(ShadowToast.shownToastCount()).isEqualTo(0);
-    }
-
-    @Test
-    public void updateAccessPoint_returnFalseForNothingChanged() {
-        setUpForDisconnectedNetwork();
-
-        displayAndResume();
-        boolean changed = mController.updateAccessPoint();
-
-        assertThat(changed).isFalse();
-    }
-
-    @Test
-    public void updateAccessPoint_returnTrueForSignalLevelChanged() {
-        setUpForDisconnectedNetwork();
-
-        displayAndResume();
-
-        // Level changed
-        when(mMockAccessPoint.getLevel()).thenReturn(LEVEL + 1);
-        boolean changed = mController.updateAccessPoint();
-
-        assertThat(changed).isTrue();
-    }
-
-    @Test
-    public void updateAccessPoint_returnTrueForChangeAsNotInRange() {
-        setUpForDisconnectedNetwork();
-
-        displayAndResume();
-
-        // change as not in range
-        when(mMockAccessPoint.matches(any(AccessPoint.class))).thenReturn(false);
-        boolean changed = mController.updateAccessPoint();
-
-        assertThat(changed).isTrue();
-    }
-
-    @Test
-    public void updateAccessPoint_returnTrueForChangeAsInRange() {
-        setUpForNotInRangeNetwork();
-
-        displayAndResume();
-
-        // change as in range
-        when(mMockAccessPoint.matches(any(AccessPoint.class))).thenReturn(true);
-        boolean changed = mController.updateAccessPoint();
-
-        assertThat(changed).isTrue();
-    }
-
-    @Test
-    public void updateAccessPoint_returnTrueForChangeAsConnected() {
-        setUpForDisconnectedNetwork();
-
-        displayAndResume();
-
-        // change as connected
-        when(mMockAccessPoint.isActive()).thenReturn(true);
-        boolean changed = mController.updateAccessPoint();
-
-        assertThat(changed).isTrue();
-    }
-
-    @Test
-    public void updateAccessPoint_returnTrueForChangeAsDisconnected() {
-        setUpForConnectedNetwork();
-
-        displayAndResume();
-
-        // change as disconnected
-        when(mMockAccessPoint.isActive()).thenReturn(false);
-        boolean changed = mController.updateAccessPoint();
-
-        assertThat(changed).isTrue();
-    }
-
-    @Test
-    public void updateAccessPoint_returnTrueForAccessPointUpdated() {
-        setUpForConnectedNetwork();
-
-        displayAndResume();
-
-        // change as disconnected
-        when(mMockAccessPoint.update(mMockWifiConfig, mMockWifiInfo, mMockNetworkInfo))
-                .thenReturn(true);
-        boolean changed = mController.updateAccessPoint();
-
-        assertThat(changed).isTrue();
-    }
-
-    @Test
-    public void testRefreshRssiViews_shouldNotUpdateIfLevelIsSameForConnectedNetwork() {
+    public void testRefreshRssiViews_shouldOnUpdated() {
         setUpForConnectedNetwork();
         displayAndResume();
 
         mContext.sendBroadcast(new Intent(WifiManager.RSSI_CHANGED_ACTION));
 
-        verify(mMockAccessPoint, times(3)).getLevel();
-        verify(mMockIconInjector, times(1)).getIcon(anyInt());
-    }
-
-    @Test
-    public void testRefreshRssiViews_shouldUpdateOnLevelChangeForConnectedNetwork() {
-        setUpForConnectedNetwork();
-        displayAndResume();
-
-        when(mMockAccessPoint.getLevel()).thenReturn(0);
-        mContext.sendBroadcast(new Intent(WifiManager.RSSI_CHANGED_ACTION));
-
-        verify(mMockAccessPoint, times(4)).getLevel();
-        verify(mMockIconInjector, times(2)).getIcon(anyInt());
+        verify(mController).onUpdated();
     }
 
     @Test
     public void testRefreshRssiViews_shouldNotUpdateForNotInRangeNetwork() {
         setUpForNotInRangeNetwork();
-
         displayAndResume();
 
-        when(mMockAccessPoint.getLevel()).thenReturn(0);
+        when(mMockWifiEntry.getLevel()).thenReturn(0);
         mContext.sendBroadcast(new Intent(WifiManager.RSSI_CHANGED_ACTION));
 
         verify(mMockSignalStrengthPref, times(2)).setVisible(false);
@@ -1858,6 +1502,7 @@
         verify(mMockMacAddressPref).setTitle(R.string.wifi_advanced_device_mac_address_title);
     }
 
+    /* TODO(b/143326832): Support Passpoint test cases while WifiTracker2 supports it.
     @Test
     public void entityHeader_expiredPasspointR1_shouldHandleExpiration() {
         when(mMockAccessPoint.isPasspoint()).thenReturn(true);
@@ -1872,6 +1517,7 @@
         verify(mMockButtonsPref, atLeastOnce()).setButton3Visible(false);
         verify(mMockHeaderController).setSummary(expireSummary);
     }
+    */
 
     private ActionButtonsPreference createMock() {
         final ActionButtonsPreference pref = mock(ActionButtonsPreference.class);
diff --git a/tests/robotests/src/com/android/settings/wifi/details2/WifiMeteredPreferenceController2Test.java b/tests/robotests/src/com/android/settings/wifi/details2/WifiMeteredPreferenceController2Test.java
index 517c96a..c453db3 100644
--- a/tests/robotests/src/com/android/settings/wifi/details2/WifiMeteredPreferenceController2Test.java
+++ b/tests/robotests/src/com/android/settings/wifi/details2/WifiMeteredPreferenceController2Test.java
@@ -21,13 +21,14 @@
 import static org.mockito.Mockito.spy;
 
 import android.content.Context;
-import android.net.wifi.WifiConfiguration;
 
 import androidx.preference.DropDownPreference;
 
 import com.android.settings.R;
+import com.android.wifitrackerlib.WifiEntry;
 
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
@@ -42,7 +43,7 @@
     private static final int METERED_OVERRIDE_NOT_METERED = 2;
 
     @Mock
-    private WifiConfiguration mWifiConfiguration;
+    private WifiEntry mWifiEntry;
 
     private WifiMeteredPreferenceController2 mPreferenceController;
     private Context mContext;
@@ -53,7 +54,7 @@
         mContext = RuntimeEnvironment.application;
 
         mPreferenceController = spy(
-                new WifiMeteredPreferenceController2(mContext, mWifiConfiguration));
+                new WifiMeteredPreferenceController2(mContext, mWifiEntry));
         mDropDownPreference = new DropDownPreference(mContext);
         mDropDownPreference.setEntries(R.array.wifi_metered_entries);
         mDropDownPreference.setEntryValues(R.array.wifi_metered_values);
@@ -87,6 +88,7 @@
     }
 
     @Test
+    @Ignore
     public void testController_resilientToNullConfig() {
         mPreferenceController = spy(new WifiMeteredPreferenceController2(mContext, null));
 
diff --git a/tests/robotests/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2Test.java b/tests/robotests/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2Test.java
index 91cc01e..3403e0c 100644
--- a/tests/robotests/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2Test.java
+++ b/tests/robotests/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2Test.java
@@ -20,15 +20,17 @@
 
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
 
 import android.content.Context;
-import android.net.wifi.WifiConfiguration;
 
 import androidx.preference.DropDownPreference;
 
 import com.android.settings.R;
+import com.android.wifitrackerlib.WifiEntry;
 
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
@@ -36,13 +38,14 @@
 import org.robolectric.RuntimeEnvironment;
 
 @RunWith(RobolectricTestRunner.class)
+@Ignore
 public class WifiPrivacyPreferenceController2Test {
 
-    private static final int PRIVACY_RANDOMIZED = WifiConfiguration.RANDOMIZATION_PERSISTENT;
-    private static final int PRIVACY_TRUSTED = WifiConfiguration.RANDOMIZATION_NONE;
+    private static final int PRIVACY_RANDOMIZED = WifiEntry.PRIVACY_RANDOMIZED_MAC;
+    private static final int PRIVACY_TRUSTED = WifiEntry.PRIVACY_DEVICE_MAC;
 
     @Mock
-    private WifiConfiguration mWifiConfiguration;
+    private WifiEntry mWifiEntry;
 
     private WifiPrivacyPreferenceController2 mPreferenceController;
     private Context mContext;
@@ -55,7 +58,7 @@
 
         WifiPrivacyPreferenceController2 preferenceController =
                 new WifiPrivacyPreferenceController2(mContext);
-        preferenceController.setWifiConfiguration(mWifiConfiguration);
+        preferenceController.setWifiEntry(mWifiEntry);
         mPreferenceController = spy(preferenceController);
         mDropDownPreference = new DropDownPreference(mContext);
         mDropDownPreference.setEntries(R.array.wifi_privacy_entries);
@@ -89,38 +92,23 @@
     @Test
     public void testController_resilientToNullConfig() {
         mPreferenceController = spy(new WifiPrivacyPreferenceController2(mContext));
+        mPreferenceController.setWifiEntry(mWifiEntry);
 
         mPreferenceController.getRandomizationValue();
         mPreferenceController.onPreferenceChange(mDropDownPreference, "1");
     }
 
     @Test
-    public void testUpdateState_isNotEphemeralNetwork_shouldBeSelectable() {
-        mPreferenceController.setIsEphemeral(false);
+    public void testUpdateState_canSetPrivacy_shouldBeSelectable() {
+        when(mWifiEntry.canSetPrivacy()).thenReturn(true);
         mPreferenceController.updateState(mDropDownPreference);
 
         assertThat(mDropDownPreference.isSelectable()).isTrue();
     }
 
     @Test
-    public void testUpdateState_isEphemeralNetwork_shouldNotSelectable() {
-        mPreferenceController.setIsEphemeral(true);
-        mPreferenceController.updateState(mDropDownPreference);
-
-        assertThat(mDropDownPreference.isSelectable()).isFalse();
-    }
-
-    @Test
-    public void testUpdateState_isNotPasspointNetwork_shouldBeSelectable() {
-        mPreferenceController.setIsPasspoint(false);
-        mPreferenceController.updateState(mDropDownPreference);
-
-        assertThat(mDropDownPreference.isSelectable()).isTrue();
-    }
-
-    @Test
-    public void testUpdateState_isPasspointNetwork_shouldNotSelectable() {
-        mPreferenceController.setIsPasspoint(true);
+    public void testUpdateState_canNotSetPrivacy_shouldNotSelectable() {
+        when(mWifiEntry.canSetPrivacy()).thenReturn(false);
         mPreferenceController.updateState(mDropDownPreference);
 
         assertThat(mDropDownPreference.isSelectable()).isFalse();