Merge "Fix issues where the task was still touchable in overview" into sc-v2-dev
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 98e447c..7ed0bed 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -127,6 +127,7 @@
     })";
 static const char IMAGE_FRAG_DYNAMIC_COLORING_SHADER_SOURCE[] = R"(
     precision mediump float;
+    const float cWhiteMaskThreshold = 0.05f;
     uniform sampler2D uTexture;
     uniform float uFade;
     uniform float uColorProgress;
@@ -141,10 +142,20 @@
     varying highp vec2 vUv;
     void main() {
         vec4 mask = texture2D(uTexture, vUv);
-        vec4 color = mask.r * mix(uStartColor0, uEndColor0, uColorProgress)
-            + mask.g * mix(uStartColor1, uEndColor1, uColorProgress)
-            + mask.b * mix(uStartColor2, uEndColor2, uColorProgress)
-            + mask.a * mix(uStartColor3, uEndColor3, uColorProgress);
+        float r = mask.r;
+        float g = mask.g;
+        float b = mask.b;
+        float a = mask.a;
+        // If all channels have values, render pixel as a shade of white.
+        float useWhiteMask = step(cWhiteMaskThreshold, r)
+            * step(cWhiteMaskThreshold, g)
+            * step(cWhiteMaskThreshold, b)
+            * step(cWhiteMaskThreshold, a);
+        vec4 color = r * mix(uStartColor0, uEndColor0, uColorProgress)
+                + g * mix(uStartColor1, uEndColor1, uColorProgress)
+                + b * mix(uStartColor2, uEndColor2, uColorProgress)
+                + a * mix(uStartColor3, uEndColor3, uColorProgress);
+        color = mix(color, vec4(vec3((r + g + b + a) * 0.25f), 1.0), useWhiteMask);
         gl_FragColor = vec4(color.x, color.y, color.z, (1.0 - uFade)) * color.a;
     })";
 static const char IMAGE_FRAG_SHADER_SOURCE[] = R"(
@@ -1077,6 +1088,8 @@
         int pause = 0;
         int progress = 0;
         int framesToFadeCount = 0;
+        int colorTransitionStart = 0;
+        int colorTransitionEnd = 0;
         char path[ANIM_ENTRY_NAME_MAX];
         char color[7] = "000000"; // default to black if unspecified
         char clockPos1[TEXT_POS_LEN_MAX + 1] = "";
@@ -1102,14 +1115,17 @@
             } else {
               animation.progressEnabled = false;
             }
-        } else if (sscanf(l, "dynamic_colors %" STRTO(ANIM_PATH_MAX) "s #%6s #%6s #%6s #%6s",
+        } else if (sscanf(l, "dynamic_colors %" STRTO(ANIM_PATH_MAX) "s #%6s #%6s #%6s #%6s %d %d",
             dynamicColoringPartNameBuffer,
-            start_color_0, start_color_1, start_color_2, start_color_3)) {
+            start_color_0, start_color_1, start_color_2, start_color_3,
+            &colorTransitionStart, &colorTransitionEnd)) {
             animation.dynamicColoringEnabled = true;
             parseColor(start_color_0, animation.startColors[0]);
             parseColor(start_color_1, animation.startColors[1]);
             parseColor(start_color_2, animation.startColors[2]);
             parseColor(start_color_3, animation.startColors[3]);
+            animation.colorTransitionStart = colorTransitionStart;
+            animation.colorTransitionEnd = colorTransitionEnd;
             dynamicColoringPartName = std::string(dynamicColoringPartNameBuffer);
         } else if (sscanf(l, "%c %d %d %" STRTO(ANIM_PATH_MAX) "s%n",
                           &pathType, &count, &pause, path, &nextReadPos) >= 4) {
@@ -1461,11 +1477,16 @@
                 if (shouldStopPlayingPart(part, fadedFramesCount, lastDisplayedProgress)) break;
 
                 // Color progress is
-                // - the normalized animation progress between [0, 1] for the dynamic coloring part,
+                // - the animation progress, normalized from
+                //   [colorTransitionStart,colorTransitionEnd] to [0, 1] for the dynamic coloring
+                //   part.
                 // - 0 for parts that come before,
                 // - 1 for parts that come after.
                 float colorProgress = part.useDynamicColoring
-                    ? (float)j / fcount
+                    ? fmin(fmax(
+                        ((float)j - animation.colorTransitionStart) /
+                            fmax(animation.colorTransitionEnd -
+                                animation.colorTransitionStart, 1.0f), 0.0f), 1.0f)
                     : (part.postDynamicColoring ? 1 : 0);
 
                 processDisplayEvents();
diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h
index 0e29621..7a597da 100644
--- a/cmds/bootanimation/BootAnimation.h
+++ b/cmds/bootanimation/BootAnimation.h
@@ -111,6 +111,8 @@
         Font progressFont;
          // Controls if dynamic coloring is enabled for the whole animation.
         bool dynamicColoringEnabled = false;
+        int colorTransitionStart = 0; // Start frame of dynamic color transition.
+        int colorTransitionEnd = 0; // End frame of dynamic color transition.
         float startColors[4][3]; // Start colors of dynamic color transition.
         float endColors[4][3];   // End colors of dynamic color transition.
     };
diff --git a/core/res/res/values-sw600dp/config.xml b/core/res/res/values-sw600dp/config.xml
index 34b6a54..861e329 100644
--- a/core/res/res/values-sw600dp/config.xml
+++ b/core/res/res/values-sw600dp/config.xml
@@ -51,5 +51,10 @@
 
     <!-- If true, show multiuser switcher by default unless the user specifically disables it. -->
     <bool name="config_showUserSwitcherByDefault">true</bool>
+
+    <!-- Enable dynamic keyguard positioning for large-width screens. This will cause the keyguard
+         to be aligned to one side of the screen when in landscape mode. -->
+    <bool name="config_enableDynamicKeyguardPositioning">true</bool>
+
 </resources>
 
diff --git a/libs/WindowManager/Shell/res/color/split_divider_background.xml b/libs/WindowManager/Shell/res/color/split_divider_background.xml
new file mode 100644
index 0000000..84f4fdf
--- /dev/null
+++ b/libs/WindowManager/Shell/res/color/split_divider_background.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2021 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="@android:color/system_neutral2_500" android:lStar="35" />
+</selector>
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/layout/docked_stack_divider.xml b/libs/WindowManager/Shell/res/layout/docked_stack_divider.xml
index ed5d2e1..d732b01 100644
--- a/libs/WindowManager/Shell/res/layout/docked_stack_divider.xml
+++ b/libs/WindowManager/Shell/res/layout/docked_stack_divider.xml
@@ -22,7 +22,7 @@
     <View
         style="@style/DockedDividerBackground"
         android:id="@+id/docked_divider_background"
-        android:background="@color/docked_divider_background"/>
+        android:background="@color/split_divider_background"/>
 
     <com.android.wm.shell.legacysplitscreen.MinimizedDockShadow
         style="@style/DockedDividerMinimizedShadow"
diff --git a/libs/WindowManager/Shell/res/layout/split_divider.xml b/libs/WindowManager/Shell/res/layout/split_divider.xml
index 7f583f3..a1dba51 100644
--- a/libs/WindowManager/Shell/res/layout/split_divider.xml
+++ b/libs/WindowManager/Shell/res/layout/split_divider.xml
@@ -21,8 +21,7 @@
 
     <View
         style="@style/DockedDividerBackground"
-        android:id="@+id/docked_divider_background"
-        android:background="@color/docked_divider_background"/>
+        android:id="@+id/docked_divider_background"/>
 
     <com.android.wm.shell.common.split.DividerHandleView
         style="@style/DockedDividerHandle"
diff --git a/libs/WindowManager/Shell/res/values-land/dimens.xml b/libs/WindowManager/Shell/res/values-land/dimens.xml
index aafba58..a95323f 100644
--- a/libs/WindowManager/Shell/res/values-land/dimens.xml
+++ b/libs/WindowManager/Shell/res/values-land/dimens.xml
@@ -16,8 +16,12 @@
 */
 -->
 <resources>
+    <!-- Divider handle size for legacy split screen -->
     <dimen name="docked_divider_handle_width">2dp</dimen>
     <dimen name="docked_divider_handle_height">16dp</dimen>
+    <!-- Divider handle size for split screen -->
+    <dimen name="split_divider_handle_width">3dp</dimen>
+    <dimen name="split_divider_handle_height">72dp</dimen>
 
     <!-- Padding between status bar and bubbles when displayed in expanded state, smaller
      value in landscape since we have limited vertical space-->
diff --git a/libs/WindowManager/Shell/res/values-land/styles.xml b/libs/WindowManager/Shell/res/values-land/styles.xml
index 863bb69..9eddac4 100644
--- a/libs/WindowManager/Shell/res/values-land/styles.xml
+++ b/libs/WindowManager/Shell/res/values-land/styles.xml
@@ -19,6 +19,7 @@
         <item name="android:layout_width">10dp</item>
         <item name="android:layout_height">match_parent</item>
         <item name="android:layout_gravity">center_horizontal</item>
+        <item name="android:background">@color/split_divider_background</item>
     </style>
 
     <style name="DockedDividerHandle">
diff --git a/libs/WindowManager/Shell/res/values/colors.xml b/libs/WindowManager/Shell/res/values/colors.xml
index 350beaf..93c0352 100644
--- a/libs/WindowManager/Shell/res/values/colors.xml
+++ b/libs/WindowManager/Shell/res/values/colors.xml
@@ -17,7 +17,6 @@
  */
 -->
 <resources>
-    <color name="docked_divider_background">#ff000000</color>
     <color name="docked_divider_handle">#ffffff</color>
     <drawable name="forced_resizable_background">#59000000</drawable>
     <color name="minimize_dock_shadow_start">#60000000</color>
diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml
index 130f741..26c619d 100644
--- a/libs/WindowManager/Shell/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/res/values/dimen.xml
@@ -76,8 +76,12 @@
     <!-- How high we lift the divider when touching -->
     <dimen name="docked_stack_divider_lift_elevation">4dp</dimen>
 
+    <!-- Divider handle size for legacy split screen -->
     <dimen name="docked_divider_handle_width">16dp</dimen>
     <dimen name="docked_divider_handle_height">2dp</dimen>
+    <!-- Divider handle size for split screen -->
+    <dimen name="split_divider_handle_width">72dp</dimen>
+    <dimen name="split_divider_handle_height">3dp</dimen>
 
     <!-- One-Handed Mode -->
     <!-- Threshold for dragging distance to enable one-handed mode -->
diff --git a/libs/WindowManager/Shell/res/values/styles.xml b/libs/WindowManager/Shell/res/values/styles.xml
index fffcd33..3e4ca3a 100644
--- a/libs/WindowManager/Shell/res/values/styles.xml
+++ b/libs/WindowManager/Shell/res/values/styles.xml
@@ -34,6 +34,7 @@
         <item name="android:layout_width">match_parent</item>
         <item name="android:layout_height">10dp</item>
         <item name="android:layout_gravity">center_vertical</item>
+        <item name="android:background">@color/split_divider_background</item>
     </style>
 
     <style name="DockedDividerMinimizedShadow">
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerHandleView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerHandleView.java
index 218bf47..c76937d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerHandleView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerHandleView.java
@@ -70,7 +70,8 @@
     private final Paint mPaint = new Paint();
     private final int mWidth;
     private final int mHeight;
-    private final int mCircleDiameter;
+    private final int mTouchingWidth;
+    private final int mTouchingHeight;
     private int mCurrentWidth;
     private int mCurrentHeight;
     private AnimatorSet mAnimator;
@@ -80,11 +81,12 @@
         super(context, attrs);
         mPaint.setColor(getResources().getColor(R.color.docked_divider_handle, null));
         mPaint.setAntiAlias(true);
-        mWidth = getResources().getDimensionPixelSize(R.dimen.docked_divider_handle_width);
-        mHeight = getResources().getDimensionPixelSize(R.dimen.docked_divider_handle_height);
+        mWidth = getResources().getDimensionPixelSize(R.dimen.split_divider_handle_width);
+        mHeight = getResources().getDimensionPixelSize(R.dimen.split_divider_handle_height);
         mCurrentWidth = mWidth;
         mCurrentHeight = mHeight;
-        mCircleDiameter = (mWidth + mHeight) / 3;
+        mTouchingWidth = mWidth > mHeight ? mWidth / 2 : mWidth;
+        mTouchingHeight = mHeight > mWidth ? mHeight / 2 : mHeight;
     }
 
     /** Sets touching state for this handle view. */
@@ -98,16 +100,16 @@
         }
         if (!animate) {
             if (touching) {
-                mCurrentWidth = mCircleDiameter;
-                mCurrentHeight = mCircleDiameter;
+                mCurrentWidth = mTouchingWidth;
+                mCurrentHeight = mTouchingHeight;
             } else {
                 mCurrentWidth = mWidth;
                 mCurrentHeight = mHeight;
             }
             invalidate();
         } else {
-            animateToTarget(touching ? mCircleDiameter : mWidth,
-                    touching ? mCircleDiameter : mHeight, touching);
+            animateToTarget(touching ? mTouchingWidth : mWidth,
+                    touching ? mTouchingHeight : mHeight, touching);
         }
         mTouching = touching;
     }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt
index 050beb3..0861652 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt
@@ -27,13 +27,15 @@
 import com.android.server.wm.flicker.dsl.FlickerBuilder
 import com.android.server.wm.flicker.helpers.launchSplitScreen
 import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
-import com.android.wm.shell.flicker.helpers.ImeAppHelper
-import com.android.wm.shell.flicker.helpers.FixedAppHelper
 import com.android.server.wm.flicker.repetitions
 import com.android.server.wm.flicker.rules.RemoveAllTasksButHomeRule.Companion.removeAllTasksButHome
 import com.android.wm.shell.flicker.helpers.BaseAppHelper.Companion.isShellTransitionsEnabled
+import com.android.wm.shell.flicker.helpers.FixedAppHelper
+import com.android.wm.shell.flicker.helpers.ImeAppHelper
+import com.android.wm.shell.flicker.helpers.SplitScreenHelper
 import com.android.wm.shell.flicker.testapp.Components.PipActivity.EXTRA_ENTER_PIP
 import org.junit.Assume.assumeFalse
+import org.junit.Assume.assumeTrue
 import org.junit.Before
 import org.junit.FixMethodOrder
 import org.junit.Test
@@ -56,6 +58,8 @@
 
     @Before
     open fun setup() {
+        // Only run legacy split tests when the system is using legacy split screen.
+        assumeTrue(SplitScreenHelper.isUsingLegacySplit())
         // Legacy split is having some issue with Shell transition, and will be deprecated soon.
         assumeFalse(isShellTransitionsEnabled())
     }
diff --git a/packages/SystemUI/res/color/settingslib_state_off.xml b/packages/SystemUI/res/color/settingslib_state_off.xml
new file mode 100644
index 0000000..e821825
--- /dev/null
+++ b/packages/SystemUI/res/color/settingslib_state_off.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
+ <item android:color="?androidprv:attr/colorAccentSecondaryVariant"/>
+</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/color/settingslib_state_on.xml b/packages/SystemUI/res/color/settingslib_state_on.xml
new file mode 100644
index 0000000..6d2133c
--- /dev/null
+++ b/packages/SystemUI/res/color/settingslib_state_on.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
+ <item android:color="?androidprv:attr/colorAccentPrimary"/>
+</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/color/settingslib_track_off.xml b/packages/SystemUI/res/color/settingslib_track_off.xml
new file mode 100644
index 0000000..21d1dcc
--- /dev/null
+++ b/packages/SystemUI/res/color/settingslib_track_off.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
+ <item android:color="?androidprv:attr/colorAccentSecondary"/>
+</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/color/settingslib_track_on.xml b/packages/SystemUI/res/color/settingslib_track_on.xml
new file mode 100644
index 0000000..ba7848a
--- /dev/null
+++ b/packages/SystemUI/res/color/settingslib_track_on.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
+ <item android:color="?androidprv:attr/colorAccentPrimaryVariant"/>
+</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/global_screenshot_static.xml b/packages/SystemUI/res/layout/global_screenshot_static.xml
index e4a9694..6a9254c 100644
--- a/packages/SystemUI/res/layout/global_screenshot_static.xml
+++ b/packages/SystemUI/res/layout/global_screenshot_static.xml
@@ -36,7 +36,6 @@
         android:layout_width="0dp"
         android:layout_height="wrap_content"
         android:layout_marginEnd="@dimen/screenshot_action_container_margin_horizontal"
-        android:layout_marginBottom="@dimen/screenshot_action_container_offset_y"
         android:paddingEnd="@dimen/screenshot_action_container_padding_right"
         android:paddingVertical="@dimen/screenshot_action_container_padding_vertical"
         android:elevation="1dp"
diff --git a/packages/SystemUI/res/layout/internet_connectivity_dialog.xml b/packages/SystemUI/res/layout/internet_connectivity_dialog.xml
index 5b58fe8..b841419 100644
--- a/packages/SystemUI/res/layout/internet_connectivity_dialog.xml
+++ b/packages/SystemUI/res/layout/internet_connectivity_dialog.xml
@@ -30,7 +30,7 @@
         style="@style/Widget.SliceView.Panel"
         android:gravity="center_vertical|center_horizontal"
         android:layout_marginTop="24dp"
-        android:layout_marginBottom="16dp"
+        android:layout_marginBottom="@dimen/internet_dialog_network_layout_margin"
         android:orientation="vertical">
 
         <TextView
@@ -57,7 +57,7 @@
     <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_marginBottom="16dp"
+        android:layout_marginBottom="@dimen/internet_dialog_network_layout_margin"
         android:orientation="vertical">
 
         <View
@@ -101,8 +101,8 @@
                     android:background="?android:attr/selectableItemBackground"
                     android:layout_gravity="center_vertical|start"
                     android:orientation="horizontal"
-                    android:layout_marginEnd="@dimen/settingslib_switchbar_margin"
-                    android:layout_marginStart="@dimen/settingslib_switchbar_margin"
+                    android:layout_marginEnd="@dimen/internet_dialog_network_layout_margin"
+                    android:layout_marginStart="@dimen/internet_dialog_network_layout_margin"
                     android:paddingStart="22dp"
                     android:paddingEnd="22dp">
 
@@ -130,24 +130,24 @@
                         <TextView
                             android:id="@+id/mobile_title"
                             android:textDirection="locale"
-                            android:layout_marginStart="16dp"
+                            android:layout_marginStart="@dimen/internet_dialog_network_layout_margin"
+                            android:layout_marginEnd="7dp"
                             android:layout_width="wrap_content"
                             android:layout_height="wrap_content"
                             android:layout_gravity="center_vertical|start"
                             android:ellipsize="end"
-                            android:maxLines="1"
                             android:textColor="?android:attr/textColorPrimary"
                             android:textSize="16sp"
                             android:fontFamily="google-sans"/>
                         <TextView
                             android:id="@+id/mobile_summary"
                             android:textDirection="locale"
-                            android:layout_marginStart="16dp"
+                            android:layout_marginStart="@dimen/internet_dialog_network_layout_margin"
+                            android:layout_marginEnd="34dp"
                             android:layout_width="wrap_content"
                             android:layout_height="wrap_content"
                             android:layout_gravity="center_vertical|start"
                             android:ellipsize="end"
-                            android:maxLines="1"
                             android:textColor="?android:attr/textColorTertiary"
                             android:textSize="14sp"
                             android:fontFamily="google-sans"/>
@@ -179,8 +179,8 @@
                     android:background="?android:attr/selectableItemBackground"
                     android:gravity="center"
                     android:orientation="horizontal"
-                    android:layout_marginEnd="@dimen/settingslib_switchbar_margin"
-                    android:layout_marginStart="@dimen/settingslib_switchbar_margin"
+                    android:layout_marginEnd="@dimen/internet_dialog_network_layout_margin"
+                    android:layout_marginStart="@dimen/internet_dialog_network_layout_margin"
                     android:paddingStart="22dp"
                     android:paddingEnd="22dp">
 
@@ -191,6 +191,7 @@
                         android:layout_width="wrap_content"
                         android:layout_height="match_parent">
                         <TextView
+                            android:id="@+id/wifi_toggle_title"
                             android:text="@string/turn_on_wifi"
                             android:textDirection="locale"
                             android:layout_width="wrap_content"
@@ -229,10 +230,10 @@
                     android:visibility="gone"
                     android:background="?android:attr/selectableItemBackground"
                     android:orientation="horizontal"
-                    android:layout_marginEnd="@dimen/settingslib_switchbar_margin"
-                    android:layout_marginStart="@dimen/settingslib_switchbar_margin"
-                    android:paddingStart="22dp"
-                    android:paddingEnd="22dp">
+                    android:layout_marginStart="@dimen/internet_dialog_network_layout_margin"
+                    android:layout_marginEnd="@dimen/internet_dialog_network_layout_margin"
+                    android:paddingStart="20dp"
+                    android:paddingEnd="24dp">
 
                     <FrameLayout
                         android:layout_width="24dp"
@@ -247,12 +248,13 @@
                     </FrameLayout>
 
                     <LinearLayout
-                        android:layout_weight="3"
                         android:id="@+id/wifi_connected_list"
                         android:orientation="vertical"
                         android:clickable="false"
                         android:layout_width="wrap_content"
                         android:layout_height="72dp"
+                        android:layout_marginEnd="30dp"
+                        android:layout_weight="1"
                         android:gravity="start|center_vertical">
                         <TextView
                             android:id="@+id/wifi_connected_title"
@@ -260,9 +262,8 @@
                             android:layout_width="wrap_content"
                             android:layout_height="wrap_content"
                             android:layout_gravity="center_vertical|start"
-                            android:layout_marginStart="16dp"
+                            android:layout_marginStart="@dimen/internet_dialog_network_layout_margin"
                             android:ellipsize="end"
-                            android:maxLines="1"
                             android:textColor="?android:attr/textColorPrimary"
                             android:textSize="14sp"
                             android:fontFamily="google-sans"/>
@@ -272,9 +273,8 @@
                             android:layout_width="wrap_content"
                             android:layout_height="wrap_content"
                             android:layout_gravity="center_vertical|start"
-                            android:layout_marginStart="16dp"
+                            android:layout_marginStart="@dimen/internet_dialog_network_layout_margin"
                             android:ellipsize="end"
-                            android:maxLines="1"
                             android:textColor="?android:attr/textColorTertiary"
                             android:textSize="14sp"
                             android:fontFamily="google-sans"/>
@@ -283,14 +283,14 @@
                     <FrameLayout
                         android:layout_width="24dp"
                         android:layout_height="match_parent"
-                        android:layout_marginEnd="5dp"
                         android:clickable="false"
+                        android:layout_gravity="end|center_vertical"
                         android:gravity="center">
                         <ImageView
                             android:id="@+id/wifi_settings_icon"
                             android:src="@drawable/ic_settings_24dp"
                             android:layout_width="24dp"
-                            android:layout_gravity="center"
+                            android:layout_gravity="end|center_vertical"
                             android:layout_height="wrap_content"/>
                     </FrameLayout>
 
@@ -323,7 +323,7 @@
                     android:layout_height="24dp"
                     android:clickable="false"
                     android:layout_gravity="center_vertical|start"
-                    android:layout_marginStart="16dp">
+                    android:layout_marginStart="@dimen/internet_dialog_network_layout_margin">
                     <ImageView
                         android:id="@+id/arrow_forward"
                         android:src="@drawable/ic_arrow_forward"
@@ -337,7 +337,7 @@
                     android:clickable="false"
                     android:layout_width="match_parent"
                     android:layout_height="match_parent"
-                    android:layout_marginStart="16dp">
+                    android:layout_marginStart="@dimen/internet_dialog_network_layout_margin">
                     <TextView
                         android:text="@string/see_all_networks"
                         android:textDirection="locale"
diff --git a/packages/SystemUI/res/layout/internet_list_item.xml b/packages/SystemUI/res/layout/internet_list_item.xml
index 19b1ef9..b52933d 100644
--- a/packages/SystemUI/res/layout/internet_list_item.xml
+++ b/packages/SystemUI/res/layout/internet_list_item.xml
@@ -31,15 +31,14 @@
         android:focusable="true"
         android:background="?android:attr/selectableItemBackground"
         android:orientation="horizontal"
-        android:paddingStart="22dp"
-        android:paddingEnd="22dp">
-
+        android:paddingStart="20dp"
+        android:paddingEnd="40dp">
         <FrameLayout
             android:layout_width="24dp"
             android:layout_height="24dp"
             android:clickable="false"
             android:layout_gravity="center_vertical|start"
-            android:layout_marginStart="16dp">
+            android:layout_marginStart="@dimen/internet_dialog_network_layout_margin">
             <ImageView
                 android:id="@+id/wifi_icon"
                 android:layout_width="wrap_content"
@@ -48,52 +47,47 @@
         </FrameLayout>
 
         <LinearLayout
-            android:layout_weight="3"
             android:id="@+id/wifi_network_layout"
             android:orientation="vertical"
             android:clickable="false"
             android:layout_width="wrap_content"
-            android:layout_height="72dp">
+            android:layout_height="72dp"
+            android:layout_weight="1"
+            android:gravity="start|center_vertical"
+            android:layout_marginStart="@dimen/internet_dialog_network_layout_margin">
             <TextView
                 android:id="@+id/wifi_title"
                 android:textDirection="locale"
-                android:layout_weight="1"
                 android:layout_width="wrap_content"
-                android:layout_height="0dp"
-                android:layout_gravity="center_vertical|start"
+                android:layout_height="20dp"
                 android:gravity="start|center_vertical"
-                android:layout_marginStart="16dp"
                 android:ellipsize="end"
-                android:maxLines="1"
                 android:textColor="?android:attr/textColorPrimary"
                 android:textSize="14sp"
-                android:fontFamily="google-sans"/>
+                android:fontFamily="google-sans"
+                android:layout_marginEnd="18dp"/>
             <TextView
                 android:id="@+id/wifi_summary"
                 android:textDirection="locale"
-                android:layout_weight="1"
                 android:layout_width="wrap_content"
-                android:layout_height="0dp"
-                android:layout_gravity="center_vertical|start"
+                android:layout_height="20dp"
                 android:gravity="start|center_vertical"
-                android:layout_marginStart="16dp"
                 android:ellipsize="end"
-                android:maxLines="1"
                 android:textColor="?android:attr/textColorSecondary"
                 android:textSize="14sp"
-                android:fontFamily="google-sans"/>
+                android:fontFamily="google-sans"
+                android:layout_marginEnd="18dp"/>
         </LinearLayout>
 
         <FrameLayout
             android:layout_width="24dp"
             android:layout_height="match_parent"
-            android:layout_marginEnd="@dimen/settingslib_switchbar_padding_right"
             android:clickable="false"
-            android:gravity="center">
+            android:layout_gravity="end|center_vertical">
             <ImageView
                 android:id="@+id/wifi_locked_icon"
+                android:layout_gravity="end|center_vertical"
                 android:layout_width="wrap_content"
-                android:layout_gravity="center"
                 android:layout_height="wrap_content"/>
         </FrameLayout>
 
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index c2aad2d..d921d49 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -103,4 +103,7 @@
 
     <!-- When split shade is used, this panel should be aligned to the top -->
     <dimen name="qs_detail_margin_top">0dp</dimen>
+
+    <!-- Internet panel related dimensions -->
+    <dimen name="internet_dialog_list_max_width">624dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index b5ac0c6..d901267 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -286,13 +286,13 @@
 
     <!-- Internet Dialog -->
     <!-- Material next state on color-->
-    <color name="settingslib_state_on_color">?androidprv:attr/colorAccentPrimary</color>
+    <color name="settingslib_state_on_color">@color/settingslib_state_on</color>
     <!-- Material next state off color-->
-    <color name="settingslib_state_off_color">?androidprv:attr/colorAccentSecondary</color>
+    <color name="settingslib_state_off_color">@color/settingslib_state_off</color>
     <!-- Material next track on color-->
-    <color name="settingslib_track_on_color">?androidprv:attr/colorAccentPrimaryVariant</color>
+    <color name="settingslib_track_on_color">@color/settingslib_track_on</color>
     <!-- Material next track off color-->
-    <color name="settingslib_track_off_color">?androidprv:attr/colorAccentSecondaryVariant</color>
+    <color name="settingslib_track_off_color">@color/settingslib_track_off</color>
     <color name="connected_network_primary_color">#191C18</color>
     <color name="connected_network_secondary_color">#41493D</color>
 </resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 5699cd5..9d37acce 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -328,11 +328,10 @@
     <dimen name="global_screenshot_x_scale">80dp</dimen>
     <dimen name="screenshot_bg_protection_height">242dp</dimen>
     <dimen name="screenshot_preview_elevation">4dp</dimen>
-    <dimen name="screenshot_offset_y">24dp</dimen>
+    <dimen name="screenshot_offset_y">8dp</dimen>
     <dimen name="screenshot_offset_x">16dp</dimen>
     <dimen name="screenshot_dismiss_button_tappable_size">48dp</dimen>
     <dimen name="screenshot_dismiss_button_margin">8dp</dimen>
-    <dimen name="screenshot_action_container_offset_y">16dp</dimen>
     <dimen name="screenshot_action_container_corner_radius">18dp</dimen>
     <dimen name="screenshot_action_container_padding_vertical">4dp</dimen>
     <dimen name="screenshot_action_container_margin_horizontal">8dp</dimen>
@@ -1602,15 +1601,16 @@
     <!-- Internet panel related dimensions -->
     <dimen name="internet_dialog_list_margin">12dp</dimen>
     <dimen name="internet_dialog_list_max_height">646dp</dimen>
-    <dimen name="internet_dialog_list_max_width">412dp</dimen>
+    <dimen name="internet_dialog_list_max_width">@dimen/match_parent</dimen>
 
     <!-- Signal icon in internet dialog -->
     <dimen name="signal_strength_icon_size">24dp</dimen>
 
     <!-- Internet dialog related dimensions -->
     <dimen name="internet_dialog_corner_radius">24dp</dimen>
-
-    <!-- Size of internet dialog -->
+    <!-- End margin of network layout -->
+    <dimen name="internet_dialog_network_layout_margin">16dp</dimen>
+    <!-- Size of switch bar in internet dialog -->
     <dimen name="settingslib_switchbar_margin">16dp</dimen>
     <!-- Minimum width of switch -->
     <dimen name="settingslib_min_switch_width">52dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 4093726..d785a03 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2990,8 +2990,6 @@
     <!-- Content description for a chip in the status bar showing that the user is currently on a phone call. [CHAR LIMIT=NONE] -->
     <string name="ongoing_phone_call_content_description">Ongoing phone call</string>
 
-    <!-- Provider Model: Title of the airplane mode in the internet dialog. [CHAR LIMIT=50] -->
-    <string name="airplane_mode">Airplane mode</string>
     <!-- Provider Model: Default title of the mobile network in the mobile layout. [CHAR LIMIT=50] -->
     <string name="mobile_data_settings_title">Mobile data</string>
     <!-- Provider Model: Summary text separator for preferences including a short description
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index 840e8c8..26059068 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -317,7 +317,8 @@
             mRunningOneHandedAnimator = null;
         }
 
-        int targetTranslation = mIsSecurityViewLeftAligned ? 0 : (int) (getMeasuredWidth() / 2f);
+        int targetTranslation = mIsSecurityViewLeftAligned
+                ? 0 : (int) (getMeasuredWidth() - mSecurityViewFlipper.getWidth());
 
         if (animate) {
             mRunningOneHandedAnimator =
diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
index 47f0714..2a4022c 100644
--- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
@@ -501,8 +501,10 @@
                     if (!wasClickableOnDownEvent()) {
                         return;
                     }
+                    mDetectedLongPress = true;
 
-                    if (mVibrator != null) {
+                    if (onAffordanceClick() && mVibrator != null) {
+                        // only vibrate if the click went through and wasn't intercepted by falsing
                         mVibrator.vibrate(
                                 Process.myUid(),
                                 getContext().getOpPackageName(),
@@ -510,8 +512,6 @@
                                 "lockIcon-onLongPress",
                                 VIBRATION_SONIFICATION_ATTRIBUTES);
                     }
-                    mDetectedLongPress = true;
-                    onAffordanceClick();
                 }
 
                 public boolean onSingleTapUp(MotionEvent e) {
@@ -535,9 +535,14 @@
                     return mDownDetected;
                 }
 
-                private void onAffordanceClick() {
+                /**
+                 * Whether we tried to launch the affordance.
+                 *
+                 * If falsing intercepts the click, returns false.
+                 */
+                private boolean onAffordanceClick() {
                     if (mFalsingManager.isFalseTouch(LOCK_ICON)) {
-                        return;
+                        return false;
                     }
 
                     // pre-emptively set to true to hide view
@@ -547,6 +552,7 @@
                     }
                     updateVisibility();
                     mKeyguardViewController.showBouncer(/* scrim */ true);
+                    return true;
                 }
             });
 
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index c323bf7..e13ae4c 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -163,7 +163,8 @@
     public static final AudioAttributes VIBRATION_SONIFICATION_ATTRIBUTES =
             new AudioAttributes.Builder()
                     .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
-                    .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
+                    // vibration will bypass battery saver mode:
+                    .setUsage(AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY)
                     .build();
 
     public static final VibrationEffect EFFECT_CLICK =
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/ZigZagClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/ZigZagClassifier.java
index e1349f2..40c28fa 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/ZigZagClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/ZigZagClassifier.java
@@ -21,6 +21,7 @@
 import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_ZIGZAG_Y_PRIMARY_DEVIANCE;
 import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_ZIGZAG_Y_SECONDARY_DEVIANCE;
 import static com.android.systemui.classifier.Classifier.BRIGHTNESS_SLIDER;
+import static com.android.systemui.classifier.Classifier.LOCK_ICON;
 import static com.android.systemui.classifier.Classifier.SHADE_DRAG;
 
 import android.graphics.Point;
@@ -89,7 +90,9 @@
     Result calculateFalsingResult(
             @Classifier.InteractionType int interactionType,
             double historyBelief, double historyConfidence) {
-        if (interactionType == BRIGHTNESS_SLIDER || interactionType == SHADE_DRAG) {
+        if (interactionType == BRIGHTNESS_SLIDER
+                || interactionType == SHADE_DRAG
+                || interactionType == LOCK_ICON) {
             return Result.passed(0);
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java
index 2e771d6..b1cd03c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java
@@ -116,6 +116,9 @@
                     : icon.getInvisibleDrawable(mContext) : null;
             int padding = icon != null ? icon.getPadding() : 0;
             if (d != null) {
+                if (d.getConstantState() != null) {
+                    d = d.getConstantState().newDrawable();
+                }
                 d.setAutoMirrored(false);
                 d.setLayoutDirection(getLayoutDirection());
             }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java
index d0a4b62..cc9e748 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java
@@ -122,8 +122,9 @@
 
     @Override
     protected void handleClick(@Nullable View view) {
-        boolean canConfigMobileData = mAccessPointController.canConfigMobileData();
-        mHandler.post(() -> mInternetDialogFactory.create(true, canConfigMobileData));
+        mHandler.post(() -> mInternetDialogFactory.create(true,
+                mAccessPointController.canConfigMobileData(),
+                mAccessPointController.canConfigWifi()));
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetAdapter.java
index 91c81bc..4e897d9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetAdapter.java
@@ -24,7 +24,6 @@
 import android.graphics.drawable.Drawable;
 import android.text.Html;
 import android.text.TextUtils;
-import android.util.Log;
 import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -34,6 +33,7 @@
 import android.widget.TextView;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.recyclerview.widget.RecyclerView;
 
 import com.android.settingslib.Utils;
@@ -43,7 +43,6 @@
 
 import java.util.List;
 import java.util.concurrent.atomic.AtomicReference;
-import java.util.stream.Collectors;
 
 /**
  * Adapter for showing Wi-Fi networks.
@@ -54,9 +53,10 @@
     private static final String ACTION_WIFI_DIALOG = "com.android.settings.WIFI_DIALOG";
     private static final String EXTRA_CHOSEN_WIFI_ENTRY_KEY = "key_chosen_wifientry_key";
     private static final String EXTRA_CONNECT_FOR_CALLER = "connect_for_caller";
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     private final InternetDialogController mInternetDialogController;
+    private List<WifiEntry> mWifiEntries;
+    private int mWifiEntriesCount;
 
     protected View mHolderView;
     protected Context mContext;
@@ -76,54 +76,31 @@
 
     @Override
     public void onBindViewHolder(@NonNull InternetViewHolder viewHolder, int position) {
-        List<WifiEntry> wifiList = getWifiEntryList();
-        if (wifiList != null && wifiList.size() != 0) {
-            int count = getItemCount();
-            if (wifiList.size() > count) {
-                wifiList = getWifiEntryList().subList(0, count - 1);
-            }
-
-            if (position < wifiList.size()) {
-                viewHolder.onBind(wifiList.get(position));
-            }
-        } else if (DEBUG) {
-            Log.d(TAG, "onBindViewHolder, Wi-Fi entry list = null");
+        if (mWifiEntries == null || position >= mWifiEntriesCount) {
+            return;
         }
-    }
-
-    private List<WifiEntry> getWifiEntryList() {
-        if (mInternetDialogController.getWifiEntryList() == null) {
-            return null;
-        }
-
-        return mInternetDialogController.getWifiEntryList().stream()
-                .filter(wifiEntry -> (!wifiEntry.isDefaultNetwork()
-                        || !wifiEntry.hasInternetAccess()))
-                .limit(getItemCount())
-                .collect(Collectors.toList());
+        viewHolder.onBind(mWifiEntries.get(position));
     }
 
     /**
-     * The total number of networks (mobile network and entries of Wi-Fi) should be four in
-     * {@link InternetDialog}.
+     * Updates the Wi-Fi networks.
      *
-     * Airplane mode is ON (mobile network is gone):
-     *   Return four Wi-Fi's entries if no internet Wi-Fi.
-     *   Return three Wi-Fi's entries if one internet Wi-Fi.
-     * Airplane mode is OFF (mobile network is visible):
-     *   Return three Wi-Fi's entries if no internet Wi-Fi.
-     *   Return two Wi-Fi's entries if one internet Wi-Fi.
+     * @param wifiEntries the updated Wi-Fi entries.
+     * @param wifiEntriesCount the total number of Wi-Fi entries.
+     */
+    public void setWifiEntries(@Nullable List<WifiEntry> wifiEntries, int wifiEntriesCount) {
+        mWifiEntries = wifiEntries;
+        mWifiEntriesCount = wifiEntriesCount;
+    }
+
+    /**
+     * Gets the total number of Wi-Fi networks.
      *
-     * @return The total number of networks.
+     * @return The total number of Wi-Fi entries.
      */
     @Override
     public int getItemCount() {
-        final boolean hasInternetWifi = mInternetDialogController.getInternetWifiEntry() != null;
-        if (mInternetDialogController.isAirplaneModeEnabled()) {
-            return hasInternetWifi ? 3 : 4;
-        } else {
-            return hasInternetWifi ? 2 : 3;
-        }
+        return mWifiEntriesCount;
     }
 
     /**
@@ -198,18 +175,18 @@
             mWifiNetworkLayout.setVisibility(View.VISIBLE);
             mWifiTitleText.setText(title);
             if (TextUtils.isEmpty(summary)) {
-                mWifiTitleText.setGravity(Gravity.CENTER);
                 mWifiSummaryText.setVisibility(View.GONE);
                 return;
             } else {
-                mWifiTitleText.setGravity(Gravity.BOTTOM);
-                mWifiSummaryText.setGravity(Gravity.TOP);
                 mWifiSummaryText.setVisibility(View.VISIBLE);
             }
             mWifiSummaryText.setText(summary);
         }
 
         Drawable getWifiDrawable(@NonNull WifiEntry wifiEntry) throws Throwable {
+            if (wifiEntry.getLevel() == WifiEntry.WIFI_LEVEL_UNREACHABLE) {
+                return null;
+            }
             final Drawable drawable = mWifiIconInjector.getIcon(wifiEntry.shouldShowXLevelIcon(),
                     wifiEntry.getLevel());
             if (drawable == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
index e1e0ba7..4d0cbd1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
@@ -21,13 +21,11 @@
 
 import android.app.AlertDialog;
 import android.content.Context;
-import android.content.Intent;
 import android.graphics.Color;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.net.Network;
 import android.net.NetworkCapabilities;
-import android.net.wifi.ScanResult;
 import android.net.wifi.WifiManager;
 import android.os.Bundle;
 import android.os.Handler;
@@ -51,11 +49,12 @@
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.ProgressBar;
-import android.widget.Space;
 import android.widget.Switch;
 import android.widget.TextView;
 
+import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
+import androidx.annotation.WorkerThread;
 import androidx.recyclerview.widget.LinearLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
 
@@ -92,7 +91,7 @@
     @VisibleForTesting
     protected View mDialogView;
     @VisibleForTesting
-    protected WifiEntry mConnectedWifiEntry;
+    protected boolean mCanConfigWifi;
 
     private InternetDialogFactory mInternetDialogFactory;
     private SubscriptionManager mSubscriptionManager;
@@ -105,12 +104,14 @@
     private TextView mInternetDialogSubTitle;
     private View mDivider;
     private ProgressBar mProgressBar;
+    private LinearLayout mInternetDialogLayout;
     private LinearLayout mInternetListLayout;
     private LinearLayout mConnectedWifListLayout;
     private LinearLayout mConnectedWifList;
     private LinearLayout mMobileNetworkLayout;
     private LinearLayout mMobileNetworkList;
     private LinearLayout mTurnWifiOnLayout;
+    private TextView mWifiToggleTitleText;
     private LinearLayout mSeeAllLayout;
     private RecyclerView mWifiRecyclerView;
     private ImageView mConnectedWifiIcon;
@@ -125,10 +126,14 @@
     private Button mDoneButton;
     private Drawable mBackgroundOn;
     private int mListMaxHeight;
-    private int mListMaxWidth;
+    private int mLayoutWidth;
     private int mDefaultDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
     private boolean mCanConfigMobileData;
 
+    // Wi-Fi entries
+    protected WifiEntry mConnectedWifiEntry;
+    protected int mWifiEntriesCount;
+
     // Wi-Fi scanning progress bar
     protected boolean mIsProgressBarVisible;
     protected boolean mIsSearchingHidden;
@@ -142,16 +147,17 @@
 
     private final ViewTreeObserver.OnGlobalLayoutListener mInternetListLayoutListener = () -> {
         // Set max height for list
-        if (mInternetListLayout.getHeight() > mListMaxHeight) {
-            ViewGroup.LayoutParams params = mInternetListLayout.getLayoutParams();
+        if (mInternetDialogLayout.getHeight() > mListMaxHeight) {
+            ViewGroup.LayoutParams params = mInternetDialogLayout.getLayoutParams();
             params.height = mListMaxHeight;
-            mInternetListLayout.setLayoutParams(params);
+            mInternetDialogLayout.setLayoutParams(params);
         }
     };
 
     public InternetDialog(Context context, InternetDialogFactory internetDialogFactory,
             InternetDialogController internetDialogController, boolean canConfigMobileData,
-            boolean aboveStatusBar, UiEventLogger uiEventLogger, @Main Handler handler) {
+            boolean canConfigWifi, boolean aboveStatusBar, UiEventLogger uiEventLogger,
+            @Main Handler handler) {
         super(context, R.style.Theme_SystemUI_Dialog_Internet);
         if (DEBUG) {
             Log.d(TAG, "Init InternetDialog");
@@ -165,6 +171,7 @@
         mTelephonyManager = mInternetDialogController.getTelephonyManager();
         mWifiManager = mInternetDialogController.getWifiManager();
         mCanConfigMobileData = canConfigMobileData;
+        mCanConfigWifi = canConfigWifi;
 
         mLayoutManager = new LinearLayoutManager(mContext) {
             @Override
@@ -174,7 +181,7 @@
         };
         mListMaxHeight = context.getResources().getDimensionPixelSize(
                 R.dimen.internet_dialog_list_max_height);
-        mListMaxWidth = context.getResources().getDimensionPixelSize(
+        mLayoutWidth = context.getResources().getDimensionPixelSize(
                 R.dimen.internet_dialog_list_max_width);
         mUiEventLogger = uiEventLogger;
         mAdapter = new InternetAdapter(mInternetDialogController);
@@ -202,11 +209,14 @@
         layoutParams.setFitInsetsIgnoringVisibility(true);
         window.setAttributes(layoutParams);
         window.setContentView(mDialogView);
-        window.setLayout(mListMaxWidth, ViewGroup.LayoutParams.WRAP_CONTENT);
+        //Only fix the width for large screen or tablet.
+        window.setLayout(mContext.getResources().getDimensionPixelSize(
+                R.dimen.internet_dialog_list_max_width), ViewGroup.LayoutParams.WRAP_CONTENT);
         window.setWindowAnimations(R.style.Animation_InternetDialog);
         window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
         window.addFlags(FLAG_LAYOUT_NO_LIMITS);
 
+        mInternetDialogLayout = mDialogView.requireViewById(R.id.internet_connectivity_dialog);
         mInternetDialogTitle = mDialogView.requireViewById(R.id.internet_dialog_title);
         mInternetDialogSubTitle = mDialogView.requireViewById(R.id.internet_dialog_subtitle);
         mDivider = mDialogView.requireViewById(R.id.divider);
@@ -215,6 +225,7 @@
         mMobileNetworkLayout = mDialogView.requireViewById(R.id.mobile_network_layout);
         mMobileNetworkList = mDialogView.requireViewById(R.id.mobile_network_list);
         mTurnWifiOnLayout = mDialogView.requireViewById(R.id.turn_on_wifi_layout);
+        mWifiToggleTitleText = mDialogView.requireViewById(R.id.wifi_toggle_title);
         mConnectedWifListLayout = mDialogView.requireViewById(R.id.wifi_connected_layout);
         mConnectedWifList = mDialogView.requireViewById(R.id.wifi_connected_list);
         mConnectedWifiIcon = mDialogView.requireViewById(R.id.wifi_connected_icon);
@@ -230,7 +241,7 @@
         mMobileDataToggle = mDialogView.requireViewById(R.id.mobile_toggle);
         mWiFiToggle = mDialogView.requireViewById(R.id.wifi_toggle);
         mBackgroundOn = mContext.getDrawable(R.drawable.settingslib_switch_bar_bg_on);
-        mInternetListLayout.getViewTreeObserver().addOnGlobalLayoutListener(
+        mInternetDialogLayout.getViewTreeObserver().addOnGlobalLayoutListener(
                 mInternetListLayoutListener);
         mInternetDialogTitle.setText(getDialogTitleText());
         mInternetDialogTitle.setGravity(Gravity.START | Gravity.CENTER_VERTICAL);
@@ -247,7 +258,19 @@
         if (DEBUG) {
             Log.d(TAG, "onStart");
         }
-        mInternetDialogController.onStart(this);
+        mInternetDialogController.onStart(this, mCanConfigWifi);
+        if (!mCanConfigWifi) {
+            hideWifiViews();
+        }
+    }
+
+    @VisibleForTesting
+    void hideWifiViews() {
+        setProgressBarVisible(false);
+        mTurnWifiOnLayout.setVisibility(View.GONE);
+        mConnectedWifListLayout.setVisibility(View.GONE);
+        mWifiRecyclerView.setVisibility(View.GONE);
+        mSeeAllLayout.setVisibility(View.GONE);
     }
 
     @Override
@@ -286,23 +309,22 @@
         } else {
             mInternetDialogSubTitle.setText(getSubtitleText());
         }
-        showProgressBar();
         setMobileDataLayout(mInternetDialogController.activeNetworkIsCellular());
 
+        if (!mCanConfigWifi) {
+            return;
+        }
+
+        showProgressBar();
         final boolean isDeviceLocked = mInternetDialogController.isDeviceLocked();
         final boolean isWifiEnabled = mWifiManager.isWifiEnabled();
         updateWifiToggle(isWifiEnabled, isDeviceLocked);
         updateConnectedWifi(isWifiEnabled, isDeviceLocked);
 
-        List<WifiEntry> wifiEntryList = mInternetDialogController.getWifiEntryList();
-        final int wifiListVisibility =
-                (isDeviceLocked || wifiEntryList == null || wifiEntryList.size() <= 0)
-                        ? View.GONE : View.VISIBLE;
-        mWifiRecyclerView.setVisibility(wifiListVisibility);
-        if (wifiListVisibility == View.VISIBLE) {
-            mAdapter.notifyDataSetChanged();
-        }
-        mSeeAllLayout.setVisibility(wifiListVisibility);
+        final int visibility = (isDeviceLocked || !isWifiEnabled || mWifiEntriesCount <= 0)
+                ? View.GONE : View.VISIBLE;
+        mWifiRecyclerView.setVisibility(visibility);
+        mSeeAllLayout.setVisibility(visibility);
     }
 
     private void setOnClickListener() {
@@ -368,6 +390,12 @@
 
     private void updateWifiToggle(boolean isWifiEnabled, boolean isDeviceLocked) {
         mWiFiToggle.setChecked(isWifiEnabled);
+        if (isDeviceLocked && mInternetDialogController.isNightMode()) {
+            int titleColor = mConnectedWifiEntry != null ? mContext.getColor(
+                    R.color.connected_network_primary_color) : Utils.getColorAttrDefaultColor(
+                    mContext, android.R.attr.textColorPrimary);
+            mWifiToggleTitleText.setTextColor(titleColor);
+        }
         mTurnWifiOnLayout.setBackground(
                 (isDeviceLocked && mConnectedWifiEntry != null) ? mBackgroundOn : null);
     }
@@ -379,8 +407,8 @@
             return;
         }
         mConnectedWifListLayout.setVisibility(View.VISIBLE);
-        mConnectedWifiTitleText.setText(mInternetDialogController.getInternetWifiTitle());
-        mConnectedWifiSummaryText.setText(mInternetDialogController.getInternetWifiSummary());
+        mConnectedWifiTitleText.setText(mConnectedWifiEntry.getTitle());
+        mConnectedWifiSummaryText.setText(mConnectedWifiEntry.getSummary(false));
         mConnectedWifiIcon.setImageDrawable(
                 mInternetDialogController.getInternetWifiDrawable(mConnectedWifiEntry));
         if (mInternetDialogController.isNightMode()) {
@@ -430,8 +458,7 @@
             return;
         }
         setProgressBarVisible(true);
-        List<ScanResult> wifiScanResults = mWifiManager.getScanResults();
-        if (wifiScanResults != null && wifiScanResults.size() > 0) {
+        if (mConnectedWifiEntry != null || mWifiEntriesCount > 0) {
             mHandler.postDelayed(mHideProgressBarRunnable, PROGRESS_DELAY_MS);
         } else if (!mIsSearchingHidden) {
             mHandler.postDelayed(mHideSearchingRunnable, PROGRESS_DELAY_MS);
@@ -516,8 +543,8 @@
     }
 
     @Override
+    @WorkerThread
     public void onDataConnectionStateChanged(int state, int networkType) {
-        mAdapter.notifyDataSetChanged();
         mHandler.post(() -> updateDialog());
     }
 
@@ -532,10 +559,16 @@
     }
 
     @Override
-    public void onAccessPointsChanged(List<WifiEntry> wifiEntryList, WifiEntry connectedEntry) {
+    @WorkerThread
+    public void onAccessPointsChanged(@Nullable List<WifiEntry> wifiEntries,
+            @Nullable WifiEntry connectedEntry) {
         mConnectedWifiEntry = connectedEntry;
-        mAdapter.notifyDataSetChanged();
-        mHandler.post(() -> updateDialog());
+        mWifiEntriesCount = wifiEntries == null ? 0 : wifiEntries.size();
+        mAdapter.setWifiEntries(wifiEntries, mWifiEntriesCount);
+        mHandler.post(() -> {
+            mAdapter.notifyDataSetChanged();
+            updateDialog();
+        });
     }
 
     @Override
@@ -548,24 +581,6 @@
         }
     }
 
-    @Override
-    public void onWifiStateReceived(Context context, Intent intent) {
-        if (intent == null) {
-            return;
-        }
-
-        String action = intent.getAction();
-        if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
-            mInternetDialogController.scanWifiAccessPoints();
-            showProgressBar();
-            return;
-        }
-
-        if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
-            mHandler.post(() -> updateDialog());
-        }
-    }
-
     public enum InternetDialogEvent implements UiEventLogger.UiEventEnum {
         @UiEvent(doc = "The Internet dialog became visible on the screen.")
         INTERNET_DIALOG_SHOW(843);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
index ed32730..dfe78de8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
@@ -32,7 +32,6 @@
 import android.net.Network;
 import android.net.NetworkCapabilities;
 import android.net.NetworkRequest;
-import android.net.wifi.ScanResult;
 import android.net.wifi.WifiManager;
 import android.os.Handler;
 import android.provider.Settings;
@@ -53,6 +52,7 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
+import androidx.annotation.WorkerThread;
 
 import com.android.internal.logging.UiEventLogger;
 import com.android.keyguard.KeyguardUpdateMonitor;
@@ -108,6 +108,8 @@
             R.string.all_network_unavailable;
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
+    static final int MAX_WIFI_ENTRY_COUNT = 4;
+
     private WifiManager mWifiManager;
     private Context mContext;
     private SubscriptionManager mSubscriptionManager;
@@ -122,7 +124,8 @@
     private AccessPointController mAccessPointController;
     private IntentFilter mConnectionStateFilter;
     private InternetDialogCallback mCallback;
-    private List<WifiEntry> mWifiEntry;
+    private WifiEntry mConnectedEntry;
+    private int mWifiEntriesCount;
     private UiEventLogger mUiEventLogger;
     private BroadcastDispatcher mBroadcastDispatcher;
     private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
@@ -132,16 +135,15 @@
     @VisibleForTesting
     protected ActivityStarter mActivityStarter;
     @VisibleForTesting
-    protected WifiEntry mConnectedEntry;
-    @VisibleForTesting
     protected SubscriptionManager.OnSubscriptionsChangedListener mOnSubscriptionsChangedListener;
     @VisibleForTesting
     protected InternetTelephonyCallback mInternetTelephonyCallback;
     @VisibleForTesting
     protected WifiUtils.InternetIconInjector mWifiIconInjector;
-
     @VisibleForTesting
-    KeyguardStateController mKeyguardStateController;
+    protected boolean mCanConfigWifi;
+    @VisibleForTesting
+    protected KeyguardStateController mKeyguardStateController;
 
     private final KeyguardUpdateMonitorCallback mKeyguardUpdateCallback =
             new KeyguardUpdateMonitorCallback() {
@@ -183,8 +185,6 @@
         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
         mKeyguardStateController = keyguardStateController;
         mConnectionStateFilter = new IntentFilter();
-        mConnectionStateFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
-        mConnectionStateFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
         mConnectionStateFilter.addAction(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
         mUiEventLogger = uiEventLogger;
         mActivityStarter = starter;
@@ -193,7 +193,7 @@
         mWifiIconInjector = new WifiUtils.InternetIconInjector(mContext);
     }
 
-    void onStart(@NonNull InternetDialogCallback callback) {
+    void onStart(@NonNull InternetDialogCallback callback, boolean canConfigWifi) {
         if (DEBUG) {
             Log.d(TAG, "onStart");
         }
@@ -217,6 +217,7 @@
         mConnectivityManager.registerNetworkCallback(new NetworkRequest.Builder()
                 .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
                 .build(), new DataConnectivityListener(), mHandler);
+        mCanConfigWifi = canConfigWifi;
         scanWifiAccessPoints();
     }
 
@@ -270,7 +271,7 @@
             return null;
         }
 
-        if (!mWifiManager.isWifiEnabled()) {
+        if (mCanConfigWifi && !mWifiManager.isWifiEnabled()) {
             // When the airplane mode is off and Wi-Fi is disabled.
             //   Sub-Title: Wi-Fi is off
             if (DEBUG) {
@@ -288,12 +289,11 @@
             return mContext.getText(SUBTITLE_TEXT_UNLOCK_TO_VIEW_NETWORKS);
         }
 
-        final List<ScanResult> wifiList = mWifiManager.getScanResults();
-        if (wifiList != null && wifiList.size() != 0) {
-            return mContext.getText(SUBTITLE_TEXT_TAP_A_NETWORK_TO_CONNECT);
+        if (mConnectedEntry != null || mWifiEntriesCount > 0) {
+            return mCanConfigWifi ? mContext.getText(SUBTITLE_TEXT_TAP_A_NETWORK_TO_CONNECT) : null;
         }
 
-        if (isProgressBarVisible) {
+        if (mCanConfigWifi && isProgressBarVisible) {
             // When the Wi-Fi scan result callback is received
             //   Sub-Title: Searching for networks...
             return mContext.getText(SUBTITLE_TEXT_SEARCHING_FOR_NETWORKS);
@@ -317,7 +317,7 @@
             return mContext.getText(SUBTITLE_TEXT_ALL_CARRIER_NETWORK_UNAVAILABLE);
         }
 
-        if (!isMobileDataEnabled()) {
+        if (mCanConfigWifi && !isMobileDataEnabled()) {
             if (DEBUG) {
                 Log.d(TAG, "Mobile data off");
             }
@@ -331,7 +331,10 @@
             return mContext.getText(SUBTITLE_TEXT_ALL_CARRIER_NETWORK_UNAVAILABLE);
         }
 
-        return mContext.getText(SUBTITLE_TEXT_NON_CARRIER_NETWORK_UNAVAILABLE);
+        if (mCanConfigWifi) {
+            return mContext.getText(SUBTITLE_TEXT_NON_CARRIER_NETWORK_UNAVAILABLE);
+        }
+        return null;
     }
 
     Drawable getInternetWifiDrawable(@NonNull WifiEntry wifiEntry) {
@@ -549,26 +552,6 @@
         return summary;
     }
 
-    String getInternetWifiTitle() {
-        if (getInternetWifiEntry() == null) {
-            if (DEBUG) {
-                Log.d(TAG, "connected entry is null");
-            }
-            return "";
-        }
-        return getInternetWifiEntry().getTitle();
-    }
-
-    String getInternetWifiSummary() {
-        if (getInternetWifiEntry() == null) {
-            if (DEBUG) {
-                Log.d(TAG, "connected entry is null");
-            }
-            return "";
-        }
-        return getInternetWifiEntry().getSummary(false);
-    }
-
     void launchNetworkSetting() {
         mCallback.dismissDialog();
         mActivityStarter.postStartActivityDismissingKeyguard(getSettingsIntent(), 0);
@@ -590,18 +573,6 @@
         }
     }
 
-    List<WifiEntry> getWifiEntryList() {
-        return mWifiEntry;
-    }
-
-    WifiEntry getInternetWifiEntry() {
-        if (mConnectedEntry == null || !mConnectedEntry.isDefaultNetwork()
-                || !mConnectedEntry.hasInternetAccess()) {
-            return null;
-        }
-        return mConnectedEntry;
-    }
-
     WifiManager getWifiManager() {
         return mWifiManager;
     }
@@ -779,20 +750,33 @@
         }
     }
 
-    void scanWifiAccessPoints() {
-        mAccessPointController.scanForAccessPoints();
+    private void scanWifiAccessPoints() {
+        if (mCanConfigWifi) {
+            mAccessPointController.scanForAccessPoints();
+        }
     }
 
     @Override
+    @WorkerThread
     public void onAccessPointsChanged(List<WifiEntry> accessPoints) {
-        if (accessPoints == null) {
+        if (!mCanConfigWifi) {
+            return;
+        }
+
+        if (accessPoints == null || accessPoints.size() == 0) {
+            mConnectedEntry = null;
+            mWifiEntriesCount = 0;
+            if (mCallback != null) {
+                mCallback.onAccessPointsChanged(null /* wifiEntries */, null /* connectedEntry */);
+            }
             return;
         }
 
         boolean hasConnectedWifi = false;
-        mWifiEntry = accessPoints;
-        for (WifiEntry wifiEntry : accessPoints) {
-            if (wifiEntry.getConnectedState() == WifiEntry.CONNECTED_STATE_CONNECTED) {
+        final int accessPointSize = accessPoints.size();
+        for (int i = 0; i < accessPointSize; i++) {
+            WifiEntry wifiEntry = accessPoints.get(i);
+            if (wifiEntry.isDefaultNetwork() && wifiEntry.hasInternetAccess()) {
                 mConnectedEntry = wifiEntry;
                 hasConnectedWifi = true;
                 break;
@@ -802,7 +786,23 @@
             mConnectedEntry = null;
         }
 
-        mCallback.onAccessPointsChanged(mWifiEntry, getInternetWifiEntry());
+        int count = MAX_WIFI_ENTRY_COUNT;
+        if (hasCarrier()) {
+            count -= 1;
+        }
+        if (hasConnectedWifi) {
+            count -= 1;
+        }
+        final List<WifiEntry> wifiEntries = accessPoints.stream()
+                .filter(wifiEntry -> (!wifiEntry.isDefaultNetwork()
+                        || !wifiEntry.hasInternetAccess()))
+                .limit(count)
+                .collect(Collectors.toList());
+        mWifiEntriesCount = wifiEntries == null ? 0 : wifiEntries.size();
+
+        if (mCallback != null) {
+            mCallback.onAccessPointsChanged(wifiEntries, mConnectedEntry);
+        }
     }
 
     @Override
@@ -855,8 +855,17 @@
 
     private class DataConnectivityListener extends ConnectivityManager.NetworkCallback {
         @Override
+        @WorkerThread
         public void onCapabilitiesChanged(@NonNull Network network,
                 @NonNull NetworkCapabilities networkCapabilities) {
+            if (mCanConfigWifi) {
+                for (int transport : networkCapabilities.getTransportTypes()) {
+                    if (transport == NetworkCapabilities.TRANSPORT_WIFI) {
+                        scanWifiAccessPoints();
+                        break;
+                    }
+                }
+            }
             final Network activeNetwork = mConnectivityManager.getActiveNetwork();
             if (activeNetwork != null && activeNetwork.equals(network)) {
                 // update UI
@@ -869,11 +878,6 @@
         @Override
         public void onReceive(Context context, Intent intent) {
             final String action = intent.getAction();
-            if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)
-                    || action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
-                mCallback.onWifiStateReceived(context, intent);
-            }
-
             if (action.equals(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)) {
                 if (DEBUG) {
                     Log.d(TAG, "ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED");
@@ -929,8 +933,7 @@
 
         void dismissDialog();
 
-        void onAccessPointsChanged(List<WifiEntry> wifiEntryList, WifiEntry connectedEntry);
-
-        void onWifiStateReceived(Context context, Intent intent);
+        void onAccessPointsChanged(@Nullable List<WifiEntry> wifiEntries,
+                @Nullable WifiEntry connectedEntry);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogFactory.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogFactory.kt
index e82e89ef1..11c6980 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogFactory.kt
@@ -31,17 +31,17 @@
  */
 @SysUISingleton
 class InternetDialogFactory @Inject constructor(
-        @Main private val handler: Handler,
-        private val internetDialogController: InternetDialogController,
-        private val context: Context,
-        private val uiEventLogger: UiEventLogger
+    @Main private val handler: Handler,
+    private val internetDialogController: InternetDialogController,
+    private val context: Context,
+    private val uiEventLogger: UiEventLogger
 ) {
     companion object {
         var internetDialog: InternetDialog? = null
     }
 
     /** Creates a [InternetDialog]. */
-    fun create(aboveStatusBar: Boolean, canConfigMobileData: Boolean) {
+    fun create(aboveStatusBar: Boolean, canConfigMobileData: Boolean, canConfigWifi: Boolean) {
         if (internetDialog != null) {
             if (DEBUG) {
                 Log.d(TAG, "InternetDialog is showing, do not create it twice.")
@@ -49,7 +49,7 @@
             return
         } else {
             internetDialog = InternetDialog(context, this, internetDialogController,
-                    canConfigMobileData, aboveStatusBar, uiEventLogger, handler)
+                    canConfigMobileData, canConfigWifi, aboveStatusBar, uiEventLogger, handler)
             internetDialog?.show()
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
index cab2168..3fbdc23 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
@@ -559,8 +559,8 @@
             mScreenshotView.reset();
         }
 
-        mScreenshotView.updateOrientation(mWindowManager.getCurrentWindowMetrics()
-                .getWindowInsets().getDisplayCutout());
+        mScreenshotView.updateOrientation(
+                mWindowManager.getCurrentWindowMetrics().getWindowInsets());
 
         mScreenBitmap = screenshot;
 
@@ -594,9 +594,8 @@
                             // Delay scroll capture eval a bit to allow the underlying activity
                             // to set up in the new orientation.
                             mScreenshotHandler.postDelayed(this::requestScrollCapture, 150);
-                            mScreenshotView.updateDisplayCutoutMargins(
-                                    mWindowManager.getCurrentWindowMetrics().getWindowInsets()
-                                            .getDisplayCutout());
+                            mScreenshotView.updateInsets(
+                                    mWindowManager.getCurrentWindowMetrics().getWindowInsets());
                             // screenshot animation calculations won't be valid anymore, so just end
                             if (mScreenshotAnimation != null && mScreenshotAnimation.isRunning()) {
                                 mScreenshotAnimation.end();
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
index e5e690bcb..dfb39e3 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
@@ -118,8 +118,8 @@
     private static final long SCREENSHOT_TO_CORNER_SCALE_DURATION_MS = 234;
     private static final long SCREENSHOT_ACTIONS_EXPANSION_DURATION_MS = 400;
     private static final long SCREENSHOT_ACTIONS_ALPHA_DURATION_MS = 100;
-    private static final long SCREENSHOT_DISMISS_Y_DURATION_MS = 350;
-    private static final long SCREENSHOT_DISMISS_ALPHA_DURATION_MS = 183;
+    private static final long SCREENSHOT_DISMISS_X_DURATION_MS = 350;
+    private static final long SCREENSHOT_DISMISS_ALPHA_DURATION_MS = 350;
     private static final long SCREENSHOT_DISMISS_ALPHA_OFFSET_MS = 50; // delay before starting fade
     private static final float SCREENSHOT_ACTIONS_START_SCALE_X = .7f;
     private static final float ROUNDED_CORNER_RADIUS = .25f;
@@ -416,21 +416,30 @@
         mScreenshotPreview.setImageDrawable(createScreenDrawable(mResources, bitmap, screenInsets));
     }
 
-    void updateDisplayCutoutMargins(DisplayCutout cutout) {
+    void updateInsets(WindowInsets insets) {
         int orientation = mContext.getResources().getConfiguration().orientation;
         mOrientationPortrait = (orientation == ORIENTATION_PORTRAIT);
         FrameLayout.LayoutParams p =
                 (FrameLayout.LayoutParams) mScreenshotStatic.getLayoutParams();
+        DisplayCutout cutout = insets.getDisplayCutout();
+        Insets navBarInsets = insets.getInsets(WindowInsets.Type.navigationBars());
         if (cutout == null) {
-            p.setMargins(0, 0, 0, 0);
+            p.setMargins(0, 0, 0, navBarInsets.bottom);
         } else {
             Insets waterfall = cutout.getWaterfallInsets();
             if (mOrientationPortrait) {
-                p.setMargins(waterfall.left, Math.max(cutout.getSafeInsetTop(), waterfall.top),
-                        waterfall.right, Math.max(cutout.getSafeInsetBottom(), waterfall.bottom));
+                p.setMargins(
+                        waterfall.left,
+                        Math.max(cutout.getSafeInsetTop(), waterfall.top),
+                        waterfall.right,
+                        Math.max(cutout.getSafeInsetBottom(),
+                                Math.max(navBarInsets.bottom, waterfall.bottom)));
             } else {
-                p.setMargins(Math.max(cutout.getSafeInsetLeft(), waterfall.left), waterfall.top,
-                        Math.max(cutout.getSafeInsetRight(), waterfall.right), waterfall.bottom);
+                p.setMargins(
+                        Math.max(cutout.getSafeInsetLeft(), waterfall.left),
+                        waterfall.top,
+                        Math.max(cutout.getSafeInsetRight(), waterfall.right),
+                        Math.max(navBarInsets.bottom, waterfall.bottom));
             }
         }
         mStaticLeftMargin = p.leftMargin;
@@ -438,10 +447,10 @@
         mScreenshotStatic.requestLayout();
     }
 
-    void updateOrientation(DisplayCutout cutout) {
+    void updateOrientation(WindowInsets insets) {
         int orientation = mContext.getResources().getConfiguration().orientation;
         mOrientationPortrait = (orientation == ORIENTATION_PORTRAIT);
-        updateDisplayCutoutMargins(cutout);
+        updateInsets(insets);
         int screenshotFixedSize =
                 mContext.getResources().getDimensionPixelSize(R.dimen.global_screenshot_x_scale);
         ViewGroup.LayoutParams params = mScreenshotPreview.getLayoutParams();
@@ -980,7 +989,6 @@
         mScrollingScrim.setVisibility(View.GONE);
         mScrollablePreview.setVisibility(View.GONE);
         mScreenshotStatic.setTranslationX(0);
-        mScreenshotPreview.setTranslationY(0);
         mScreenshotPreview.setContentDescription(
                 mContext.getResources().getString(R.string.screenshot_preview_description));
         mScreenshotPreview.setOnClickListener(null);
@@ -996,9 +1004,6 @@
         mSmartChips.clear();
         mQuickShareChip = null;
         setAlpha(1);
-        mDismissButton.setTranslationY(0);
-        mActionsContainer.setTranslationY(0);
-        mActionsContainerBackground.setTranslationY(0);
         mScreenshotSelectorView.stop();
     }
 
@@ -1026,22 +1031,19 @@
             setAlpha(1 - animation.getAnimatedFraction());
         });
 
-        ValueAnimator yAnim = ValueAnimator.ofFloat(0, 1);
-        yAnim.setInterpolator(mAccelerateInterpolator);
-        yAnim.setDuration(SCREENSHOT_DISMISS_Y_DURATION_MS);
-        float screenshotStartY = mScreenshotPreview.getTranslationY();
-        float dismissStartY = mDismissButton.getTranslationY();
-        yAnim.addUpdateListener(animation -> {
-            float yDelta = MathUtils.lerp(0, mDismissDeltaY, animation.getAnimatedFraction());
-            mScreenshotPreview.setTranslationY(screenshotStartY + yDelta);
-            mScreenshotPreviewBorder.setTranslationY(screenshotStartY + yDelta);
-            mDismissButton.setTranslationY(dismissStartY + yDelta);
-            mActionsContainer.setTranslationY(yDelta);
-            mActionsContainerBackground.setTranslationY(yDelta);
+        ValueAnimator xAnim = ValueAnimator.ofFloat(0, 1);
+        xAnim.setInterpolator(mAccelerateInterpolator);
+        xAnim.setDuration(SCREENSHOT_DISMISS_X_DURATION_MS);
+        float deltaX = mDirectionLTR
+                    ? -1 * (mScreenshotPreviewBorder.getX() + mScreenshotPreviewBorder.getWidth())
+                    : (mDisplayMetrics.widthPixels - mScreenshotPreviewBorder.getX());
+        xAnim.addUpdateListener(animation -> {
+            float currXDelta = MathUtils.lerp(0, deltaX, animation.getAnimatedFraction());
+            mScreenshotStatic.setTranslationX(currXDelta);
         });
 
         AnimatorSet animSet = new AnimatorSet();
-        animSet.play(yAnim).with(alphaAnim);
+        animSet.play(xAnim).with(alphaAnim);
 
         return animSet;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 1431c9e..eb5f82c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -811,13 +811,8 @@
                 mStatusBarKeyguardViewManager.showBouncerMessage(message, mInitialTextColorState);
             }
         } else if (mKeyguardUpdateMonitor.isScreenOn()) {
-            if (mKeyguardUpdateMonitor.isUdfpsAvailable()) {
-                showTransientIndication(mContext.getString(R.string.keyguard_unlock_press),
-                        false /* isError */, true /* hideOnScreenOff */);
-            } else {
-                showTransientIndication(mContext.getString(R.string.keyguard_unlock),
-                        false /* isError */, true /* hideOnScreenOff */);
-            }
+            showTransientIndication(mContext.getString(R.string.keyguard_unlock),
+                    false /* isError */, true /* hideOnScreenOff */);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
index fefa994..af9d921 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar.phone;
 
+import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
 import static com.android.systemui.statusbar.events.SystemStatusAnimationSchedulerKt.ANIMATING_IN;
 import static com.android.systemui.statusbar.events.SystemStatusAnimationSchedulerKt.ANIMATING_OUT;
 
@@ -23,19 +24,26 @@
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ValueAnimator;
 import android.content.res.Resources;
+import android.hardware.biometrics.BiometricSourceType;
 import android.view.View;
 
 import androidx.annotation.NonNull;
 
 import com.android.keyguard.CarrierTextController;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.KeyguardUpdateMonitorCallback;
 import com.android.systemui.R;
 import com.android.systemui.animation.Interpolators;
 import com.android.systemui.battery.BatteryMeterViewController;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
 import com.android.systemui.statusbar.events.SystemStatusAnimationCallback;
 import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler;
 import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.statusbar.policy.UserInfoController;
 import com.android.systemui.util.ViewController;
 
@@ -58,6 +66,11 @@
     private final StatusBarIconController.TintedIconManager.Factory mTintedIconManagerFactory;
     private final BatteryMeterViewController mBatteryMeterViewController;
     private final ViewStateProvider mViewStateProvider;
+    private final KeyguardStateController mKeyguardStateController;
+    private final KeyguardBypassController mKeyguardBypassController;
+    private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+    private final BiometricUnlockController mBiometricUnlockController;
+    private final SysuiStatusBarStateController mStatusBarStateController;
 
     private final ConfigurationController.ConfigurationListener mConfigurationListener =
             new ConfigurationController.ConfigurationListener() {
@@ -115,12 +128,71 @@
                 updateViewState();
             };
 
+    private final KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback =
+            new KeyguardUpdateMonitorCallback() {
+                @Override
+                public void onBiometricAuthenticated(
+                        int userId,
+                        BiometricSourceType biometricSourceType,
+                        boolean isStrongBiometric) {
+                    if (mFirstBypassAttempt
+                            && mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
+                                    isStrongBiometric)) {
+                        mDelayShowingKeyguardStatusBar = true;
+                    }
+                }
+
+                @Override
+                public void onBiometricRunningStateChanged(
+                        boolean running,
+                        BiometricSourceType biometricSourceType) {
+                    boolean keyguardOrShadeLocked =
+                            mStatusBarState == KEYGUARD
+                                    || mStatusBarState == StatusBarState.SHADE_LOCKED;
+                    if (!running
+                            && mFirstBypassAttempt
+                            && keyguardOrShadeLocked
+                            && !mDozing
+                            && !mDelayShowingKeyguardStatusBar
+                            && !mBiometricUnlockController.isBiometricUnlock()) {
+                        mFirstBypassAttempt = false;
+                        animateKeyguardStatusBarIn();
+                    }
+                }
+
+                @Override
+                public void onFinishedGoingToSleep(int why) {
+                    mFirstBypassAttempt = mKeyguardBypassController.getBypassEnabled();
+                    mDelayShowingKeyguardStatusBar = false;
+                }
+            };
+
+    private final StatusBarStateController.StateListener mStatusBarStateListener =
+            new StatusBarStateController.StateListener() {
+                @Override
+                public void onStateChanged(int newState) {
+                    mStatusBarState = newState;
+                }
+            };
+
     private final List<String> mBlockedIcons;
 
     private boolean mBatteryListening;
     private StatusBarIconController.TintedIconManager mTintedIconManager;
 
     private float mKeyguardStatusBarAnimateAlpha = 1f;
+    /**
+     * If face auth with bypass is running for the first time after you turn on the screen.
+     * (From aod or screen off)
+     */
+    private boolean mFirstBypassAttempt;
+    /**
+     * If auth happens successfully during {@code mFirstBypassAttempt}, and we should wait until
+     * the keyguard is dismissed to show the status bar.
+     */
+    private boolean mDelayShowingKeyguardStatusBar;
+    private int mStatusBarState;
+    private boolean mDozing;
 
     @Inject
     public KeyguardStatusBarViewController(
@@ -133,7 +205,12 @@
             StatusBarIconController statusBarIconController,
             StatusBarIconController.TintedIconManager.Factory tintedIconManagerFactory,
             BatteryMeterViewController batteryMeterViewController,
-            ViewStateProvider viewStateProvider) {
+            ViewStateProvider viewStateProvider,
+            KeyguardStateController keyguardStateController,
+            KeyguardBypassController bypassController,
+            KeyguardUpdateMonitor keyguardUpdateMonitor,
+            BiometricUnlockController biometricUnlockController,
+            SysuiStatusBarStateController statusBarStateController) {
         super(view);
         mCarrierTextController = carrierTextController;
         mConfigurationController = configurationController;
@@ -144,6 +221,24 @@
         mTintedIconManagerFactory = tintedIconManagerFactory;
         mBatteryMeterViewController = batteryMeterViewController;
         mViewStateProvider = viewStateProvider;
+        mKeyguardStateController = keyguardStateController;
+        mKeyguardBypassController = bypassController;
+        mKeyguardUpdateMonitor = keyguardUpdateMonitor;
+        mBiometricUnlockController = biometricUnlockController;
+        mStatusBarStateController = statusBarStateController;
+
+        mFirstBypassAttempt = mKeyguardBypassController.getBypassEnabled();
+        mKeyguardStateController.addCallback(
+                new KeyguardStateController.Callback() {
+                    @Override
+                    public void onKeyguardFadingAwayChanged() {
+                        if (!mKeyguardStateController.isKeyguardFadingAway()) {
+                            mFirstBypassAttempt = false;
+                            mDelayShowingKeyguardStatusBar = false;
+                        }
+                    }
+                }
+        );
 
         Resources r = getResources();
         mBlockedIcons = Collections.unmodifiableList(Arrays.asList(
@@ -164,6 +259,8 @@
         mConfigurationController.addCallback(mConfigurationListener);
         mAnimationScheduler.addCallback(mAnimationCallback);
         mUserInfoController.addCallback(mOnUserInfoChangedListener);
+        mStatusBarStateController.addCallback(mStatusBarStateListener);
+        mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback);
         if (mTintedIconManager == null) {
             mTintedIconManager =
                     mTintedIconManagerFactory.create(mView.findViewById(R.id.statusIcons));
@@ -178,6 +275,8 @@
         mConfigurationController.removeCallback(mConfigurationListener);
         mAnimationScheduler.removeCallback(mAnimationCallback);
         mUserInfoController.removeCallback(mOnUserInfoChangedListener);
+        mStatusBarStateController.removeCallback(mStatusBarStateListener);
+        mKeyguardUpdateMonitor.removeCallback(mKeyguardUpdateMonitorCallback);
         if (mTintedIconManager != null) {
             mStatusBarIconController.removeIconGroup(mTintedIconManager);
         }
@@ -221,6 +320,11 @@
         mView.setTopClipping(notificationPanelTop - mView.getTop());
     }
 
+    /** Sets the dozing state. */
+    public void setDozing(boolean dozing) {
+        mDozing = dozing;
+    }
+
     /** Animate the keyguard status bar in. */
     public void animateKeyguardStatusBarIn() {
         mView.setVisibility(View.VISIBLE);
@@ -252,16 +356,23 @@
 
     /**
      * Updates the {@link KeyguardStatusBarView} state based on what the {@link ViewStateProvider}
-     * provides.
+     * and other controllers provide.
      */
     public void updateViewState() {
         ViewState newViewState = mViewStateProvider.provideViewState();
-        if (!newViewState.mShouldUpdate) {
+        if (!isKeyguardShowing()) {
             return;
         }
-        updateViewState(
-                newViewState.mAlpha * mKeyguardStatusBarAnimateAlpha,
-                newViewState.mVisibility);
+
+        float newAlpha = newViewState.mAlpha * mKeyguardStatusBarAnimateAlpha;
+
+        boolean hideForBypass =
+                mFirstBypassAttempt && mKeyguardUpdateMonitor.shouldListenForFace()
+                        || mDelayShowingKeyguardStatusBar;
+        int newVisibility = newAlpha != 0f && !mDozing && !hideForBypass
+                ? View.VISIBLE : View.INVISIBLE;
+
+        updateViewState(newAlpha, newVisibility);
     }
 
     /**
@@ -272,6 +383,10 @@
         mView.setVisibility(visibility);
     }
 
+    private boolean isKeyguardShowing() {
+        return mStatusBarState == KEYGUARD;
+    }
+
     /** */
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.println("KeyguardStatusBarView:");
@@ -287,14 +402,10 @@
 
     /** A POJO for the desired state of {@link KeyguardStatusBarView}. */
     static class ViewState {
-        final boolean mShouldUpdate;
         final float mAlpha;
-        final int mVisibility;
 
-        ViewState(boolean shouldUpdate, float alpha, int visibility) {
-            this.mShouldUpdate = shouldUpdate;
+        ViewState(float alpha) {
             this.mAlpha = alpha;
-            this.mVisibility = visibility;
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index 5f2dab8..e31871a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -55,7 +55,6 @@
 import android.graphics.Rect;
 import android.graphics.Region;
 import android.graphics.drawable.Drawable;
-import android.hardware.biometrics.BiometricSourceType;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.PowerManager;
@@ -91,7 +90,6 @@
 import com.android.keyguard.KeyguardStatusView;
 import com.android.keyguard.KeyguardStatusViewController;
 import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.keyguard.KeyguardUpdateMonitorCallback;
 import com.android.keyguard.LockIconViewController;
 import com.android.keyguard.dagger.KeyguardQsUserSwitchComponent;
 import com.android.keyguard.dagger.KeyguardStatusBarViewComponent;
@@ -232,7 +230,6 @@
 
     @VisibleForTesting final StatusBarStateListener mStatusBarStateListener =
             new StatusBarStateListener();
-    private final BiometricUnlockController mBiometricUnlockController;
     private final NotificationPanelView mView;
     private final VibratorHelper mVibratorHelper;
     private final MetricsLogger mMetricsLogger;
@@ -270,42 +267,6 @@
     private static final AnimationProperties
             KEYGUARD_HUN_PROPERTIES =
             new AnimationProperties().setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
-    @VisibleForTesting
-    final KeyguardUpdateMonitorCallback
-            mKeyguardUpdateCallback =
-            new KeyguardUpdateMonitorCallback() {
-
-                @Override
-                public void onBiometricAuthenticated(int userId,
-                        BiometricSourceType biometricSourceType,
-                        boolean isStrongBiometric) {
-                    if (mFirstBypassAttempt
-                            && mUpdateMonitor.isUnlockingWithBiometricAllowed(isStrongBiometric)) {
-                        mDelayShowingKeyguardStatusBar = true;
-                    }
-                }
-
-                @Override
-                public void onBiometricRunningStateChanged(boolean running,
-                        BiometricSourceType biometricSourceType) {
-                    boolean
-                            keyguardOrShadeLocked =
-                            mBarState == KEYGUARD
-                                    || mBarState == StatusBarState.SHADE_LOCKED;
-                    if (!running && mFirstBypassAttempt && keyguardOrShadeLocked && !mDozing
-                            && !mDelayShowingKeyguardStatusBar
-                            && !mBiometricUnlockController.isBiometricUnlock()) {
-                        mFirstBypassAttempt = false;
-                        mKeyguardStatusBarViewController.animateKeyguardStatusBarIn();
-                    }
-                }
-
-                @Override
-                public void onFinishedGoingToSleep(int why) {
-                    mFirstBypassAttempt = mKeyguardBypassController.getBypassEnabled();
-                    mDelayShowingKeyguardStatusBar = false;
-                }
-    };
 
     private final LayoutInflater mLayoutInflater;
     private final PowerManager mPowerManager;
@@ -587,17 +548,6 @@
      */
     private boolean mIsPanelCollapseOnQQS;
 
-    /**
-     * If face auth with bypass is running for the first time after you turn on the screen.
-     * (From aod or screen off)
-     */
-    private boolean mFirstBypassAttempt;
-    /**
-     * If auth happens successfully during {@code mFirstBypassAttempt}, and we should wait until
-     * the keyguard is dismissed to show the status bar.
-     */
-    private boolean mDelayShowingKeyguardStatusBar;
-
     private boolean mAnimatingQS;
 
     /**
@@ -689,17 +639,7 @@
                     float alphaQsExpansion = 1 - Math.min(1, computeQsExpansionFraction() * 2);
                     float newAlpha = Math.min(getKeyguardContentsAlpha(), alphaQsExpansion)
                             * (1.0f - mKeyguardHeadsUpShowingAmount);
-
-                    boolean hideForBypass =
-                            mFirstBypassAttempt && mUpdateMonitor.shouldListenForFace()
-                                    || mDelayShowingKeyguardStatusBar;
-                    int newVisibility = newAlpha != 0f && !mDozing && !hideForBypass
-                                    ? View.VISIBLE : View.INVISIBLE;
-
-                    return new KeyguardStatusBarViewController.ViewState(
-                            /* shouldAnimate= */ mKeyguardShowing,
-                            newAlpha,
-                            newVisibility);
+                    return new KeyguardStatusBarViewController.ViewState(newAlpha);
                 }
             };
 
@@ -726,7 +666,6 @@
             StatusBarTouchableRegionManager statusBarTouchableRegionManager,
             ConversationNotificationManager conversationNotificationManager,
             MediaHierarchyManager mediaHierarchyManager,
-            BiometricUnlockController biometricUnlockController,
             StatusBarKeyguardViewManager statusBarKeyguardViewManager,
             NotificationStackScrollLayoutController notificationStackScrollLayoutController,
             KeyguardStatusViewComponent.Factory keyguardStatusViewComponentFactory,
@@ -812,7 +751,6 @@
         mDisplayId = displayId;
         mPulseExpansionHandler = pulseExpansionHandler;
         mDozeParameters = dozeParameters;
-        mBiometricUnlockController = biometricUnlockController;
         mScrimController = scrimController;
         mScrimController.setClipsQsScrim(!mShouldUseSplitNotificationShade);
         mUserManager = userManager;
@@ -828,21 +766,8 @@
         mThemeResId = mView.getContext().getThemeResId();
         mKeyguardBypassController = bypassController;
         mUpdateMonitor = keyguardUpdateMonitor;
-        mFirstBypassAttempt = mKeyguardBypassController.getBypassEnabled();
-        KeyguardStateController.Callback
-                keyguardMonitorCallback =
-                new KeyguardStateController.Callback() {
-                    @Override
-                    public void onKeyguardFadingAwayChanged() {
-                        if (!mKeyguardStateController.isKeyguardFadingAway()) {
-                            mFirstBypassAttempt = false;
-                            mDelayShowingKeyguardStatusBar = false;
-                        }
-                    }
-                };
         mLockscreenShadeTransitionController = lockscreenShadeTransitionController;
         lockscreenShadeTransitionController.setNotificationPanelController(this);
-        mKeyguardStateController.addCallback(keyguardMonitorCallback);
         DynamicPrivacyControlListener
                 dynamicPrivacyControlListener =
                 new DynamicPrivacyControlListener();
@@ -1903,6 +1828,9 @@
 
 
     private boolean handleQsTouch(MotionEvent event) {
+        if (mShouldUseSplitNotificationShade && touchXOutsideOfQs(event.getX())) {
+            return false;
+        }
         final int action = event.getActionMasked();
         if (action == MotionEvent.ACTION_DOWN && getExpandedFraction() == 1f
                 && mBarState != KEYGUARD && !mQsExpanded && isQsExpansionEnabled()) {
@@ -1944,8 +1872,12 @@
         return false;
     }
 
+    private boolean touchXOutsideOfQs(float touchX) {
+        return touchX < mQsFrame.getX() || touchX > mQsFrame.getX() + mQsFrame.getWidth();
+    }
+
     private boolean isInQsArea(float x, float y) {
-        if (x < mQsFrame.getX() || x > mQsFrame.getX() + mQsFrame.getWidth()) {
+        if (touchXOutsideOfQs(x)) {
             return false;
         }
         // Let's reject anything at the very bottom around the home handle in gesture nav
@@ -3628,6 +3560,7 @@
         mDozing = dozing;
         mNotificationStackScrollLayoutController.setDozing(mDozing, animate, wakeUpTouchLocation);
         mKeyguardBottomArea.setDozing(mDozing, animate);
+        mKeyguardStatusBarViewController.setDozing(mDozing);
 
         if (dozing) {
             mBottomAreaShadeAlphaAnimator.cancel();
@@ -4094,9 +4027,7 @@
         @Override
         public void flingTopOverscroll(float velocity, boolean open) {
             // in split shade mode we want to expand/collapse QS only when touch happens within QS
-            if (mShouldUseSplitNotificationShade
-                    && (mInitialTouchX < mQsFrame.getX()
-                        || mInitialTouchX > mQsFrame.getX() + mQsFrame.getWidth())) {
+            if (mShouldUseSplitNotificationShade && touchXOutsideOfQs(mInitialTouchX)) {
                 return;
             }
             mLastOverscroll = 0f;
@@ -4508,7 +4439,6 @@
                             .addTagListener(QS.TAG, mFragmentListener);
             mStatusBarStateController.addCallback(mStatusBarStateListener);
             mConfigurationController.addCallback(mConfigurationListener);
-            mUpdateMonitor.registerCallback(mKeyguardUpdateCallback);
             // Theme might have changed between inflating this view and attaching it to the
             // window, so
             // force a call to onThemeChanged
@@ -4525,7 +4455,6 @@
                             .removeTagListener(QS.TAG, mFragmentListener);
             mStatusBarStateController.removeCallback(mStatusBarStateListener);
             mConfigurationController.removeCallback(mConfigurationListener);
-            mUpdateMonitor.removeCallback(mKeyguardUpdateCallback);
             mFalsingManager.removeTapListener(mFalsingTapListener);
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index c3f8853..156def5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -71,6 +71,7 @@
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.demomode.DemoMode;
 import com.android.systemui.demomode.DemoModeController;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.qs.tiles.dialog.InternetDialogFactory;
 import com.android.systemui.qs.tiles.dialog.InternetDialogUtil;
@@ -129,6 +130,7 @@
     private Config mConfig;
     private final CarrierConfigTracker mCarrierConfigTracker;
     private final FeatureFlags mFeatureFlags;
+    private final DumpManager mDumpManager;
 
     private TelephonyCallback.ActiveDataSubscriptionIdListener mPhoneStateListener;
     private int mActiveMobileDataSubscription = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@@ -225,7 +227,8 @@
             CarrierConfigTracker carrierConfigTracker,
             FeatureFlags featureFlags,
             @Main Handler handler,
-            InternetDialogFactory internetDialogFactory) {
+            InternetDialogFactory internetDialogFactory,
+            DumpManager dumpManager) {
         this(context, connectivityManager,
                 telephonyManager,
                 telephonyListenerManager,
@@ -243,7 +246,8 @@
                 broadcastDispatcher,
                 demoModeController,
                 carrierConfigTracker,
-                featureFlags);
+                featureFlags,
+                dumpManager);
         mReceiverHandler.post(mRegisterListeners);
         mMainHandler = handler;
         mInternetDialogFactory = internetDialogFactory;
@@ -265,7 +269,8 @@
             BroadcastDispatcher broadcastDispatcher,
             DemoModeController demoModeController,
             CarrierConfigTracker carrierConfigTracker,
-            FeatureFlags featureFlags
+            FeatureFlags featureFlags,
+            DumpManager dumpManager
     ) {
         mContext = context;
         mTelephonyListenerManager = telephonyListenerManager;
@@ -284,6 +289,7 @@
         mDemoModeController = demoModeController;
         mCarrierConfigTracker = carrierConfigTracker;
         mFeatureFlags = featureFlags;
+        mDumpManager = dumpManager;
 
         // telephony
         mPhone = telephonyManager;
@@ -434,6 +440,8 @@
         mDemoModeController.addCallback(this);
         mProviderModelBehavior = mFeatureFlags.isCombinedStatusBarSignalIconsEnabled();
         mProviderModelSetting = mFeatureFlags.isProviderModelSettingEnabled();
+
+        mDumpManager.registerDumpable(TAG, this);
     }
 
     private final Runnable mClearForceValidated = () -> {
@@ -793,8 +801,8 @@
                 mReceiverHandler.post(this::handleConfigurationChanged);
                 break;
             case Settings.Panel.ACTION_INTERNET_CONNECTIVITY:
-                boolean canConfigMobileData = mAccessPoints.canConfigMobileData();
-                mMainHandler.post(() -> mInternetDialogFactory.create(true, canConfigMobileData));
+                mMainHandler.post(() -> mInternetDialogFactory.create(true,
+                        mAccessPoints.canConfigMobileData(), mAccessPoints.canConfigWifi()));
                 break;
             default:
                 int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
index 0276323..2efd369 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
@@ -165,7 +165,8 @@
 
         mKeyguardSecurityContainer.setOneHandedModeLeftAligned(
                 /* leftAligned= */false, /* animate= */false);
-        verify(mSecurityViewFlipper).setTranslationX(SCREEN_WIDTH / 2.0f);
+        verify(mSecurityViewFlipper).setTranslationX(
+                mKeyguardSecurityContainer.getWidth() - mSecurityViewFlipper.getWidth());
 
         mKeyguardSecurityContainer.setOneHandedModeLeftAligned(
                 /* leftAligned= */true, /* animate= */false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintViewTest.java
index f91c029..b6d1e42 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintViewTest.java
@@ -47,6 +47,7 @@
 import com.android.systemui.SysuiTestCase;
 
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
@@ -165,6 +166,7 @@
     }
 
     @Test
+    @Ignore("flaky, b/189031816")
     public void testModeUpdated_onSoftError_whenSwitchToFingerprint() {
         mFaceToFpView.onDialogAnimatedIn();
         mFaceToFpView.onAuthenticationFailed(TYPE_FACE, "no face");
@@ -181,6 +183,7 @@
     }
 
     @Test
+    @Ignore("flaky, b/189031816")
     public void testModeUpdated_onHardError_whenSwitchToFingerprint() {
         mFaceToFpView.onDialogAnimatedIn();
         mFaceToFpView.onError(TYPE_FACE, "oh no!");
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricViewTest.java
index bd518ff..f8e38e4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricViewTest.java
@@ -45,6 +45,7 @@
 import com.android.systemui.SysuiTestCase;
 
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
@@ -199,6 +200,7 @@
     }
 
     @Test
+    @Ignore("flaky, b/189031816")
     public void testError_sendsActionError() {
         initDialog(mContext, false /* allowDeviceCredential */, mCallback, new MockInjector());
         final String testError = "testError";
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
index ae009bc..f5c6f98 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.biometrics;
 
+import static android.media.AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY;
+
 import static junit.framework.Assert.assertEquals;
 
 import static org.mockito.ArgumentMatchers.any;
@@ -563,5 +565,10 @@
                 eq(mUdfpsController.EFFECT_CLICK),
                 eq("udfps-onStart"),
                 eq(UdfpsController.VIBRATION_SONIFICATION_ATTRIBUTES));
+
+        // THEN make sure vibration attributes has so that it always will play the haptic,
+        // even in battery saver mode
+        assertEquals(USAGE_ASSISTANCE_ACCESSIBILITY,
+                UdfpsController.VIBRATION_SONIFICATION_ATTRIBUTES.getUsage());
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSIconViewImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSIconViewImplTest.java
index 63ebe92..23e5168 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSIconViewImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSIconViewImplTest.java
@@ -18,6 +18,7 @@
 import static org.junit.Assert.assertFalse;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
@@ -74,6 +75,24 @@
     }
 
     @Test
+    public void testMutateIconDrawable() {
+        SlashImageView iv = mock(SlashImageView.class);
+        Drawable originalDrawable = mock(Drawable.class);
+        Drawable otherDrawable = mock(Drawable.class);
+        State s = new State();
+        s.icon = mock(Icon.class);
+        when(s.icon.getInvisibleDrawable(eq(mContext))).thenReturn(originalDrawable);
+        when(s.icon.getDrawable(eq(mContext))).thenReturn(originalDrawable);
+        when(iv.isShown()).thenReturn(true);
+        when(originalDrawable.getConstantState()).thenReturn(fakeConstantState(otherDrawable));
+
+
+        mIconView.updateIcon(iv, s, /* allowAnimations= */true);
+
+        verify(iv).setState(any(), eq(otherDrawable));
+    }
+
+    @Test
     public void testNoFirstFade() {
         ImageView iv = mock(ImageView.class);
         State s = new State();
@@ -104,4 +123,18 @@
     public void testIconNotSet_toString() {
         assertFalse(mIconView.toString().contains("lastIcon"));
     }
+
+    private static Drawable.ConstantState fakeConstantState(Drawable otherDrawable) {
+        return new Drawable.ConstantState() {
+            @Override
+            public Drawable newDrawable() {
+                return otherDrawable;
+            }
+
+            @Override
+            public int getChangingConfigurations() {
+                return 1;
+            }
+        };
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetAdapterTest.java
index 2b9082d..fa5f70c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetAdapterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetAdapterTest.java
@@ -2,8 +2,11 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -24,6 +27,7 @@
 import org.mockito.MockitoAnnotations;
 
 import java.util.Arrays;
+import java.util.List;
 
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
@@ -35,6 +39,8 @@
     @Mock
     private WifiEntry mInternetWifiEntry;
     @Mock
+    private List<WifiEntry> mWifiEntries;
+    @Mock
     private WifiEntry mWifiEntry;
     @Mock
     private InternetDialogController mInternetDialogController;
@@ -56,43 +62,17 @@
 
         mInternetAdapter = new InternetAdapter(mInternetDialogController);
         mViewHolder = mInternetAdapter.onCreateViewHolder(new LinearLayout(mContext), 0);
-        when(mInternetDialogController.getInternetWifiEntry()).thenReturn(mInternetWifiEntry);
-        when(mInternetDialogController.getWifiEntryList()).thenReturn(Arrays.asList(mWifiEntry));
+        mInternetAdapter.setWifiEntries(Arrays.asList(mWifiEntry), 1 /* wifiEntriesCount */);
         mViewHolder.mWifiIconInjector = mWifiIconInjector;
     }
 
     @Test
-    public void getItemCount_withApmOnWifiOnNoInternetWifi_returnFour() {
-        // The preconditions WiFi ON is already in setUp()
-        when(mInternetDialogController.getInternetWifiEntry()).thenReturn(null);
-        when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(true);
+    public void getItemCount_returnWifiEntriesCount() {
+        for (int i = 0; i < InternetDialogController.MAX_WIFI_ENTRY_COUNT; i++) {
+            mInternetAdapter.setWifiEntries(mWifiEntries, i /* wifiEntriesCount */);
 
-        assertThat(mInternetAdapter.getItemCount()).isEqualTo(4);
-    }
-
-    @Test
-    public void getItemCount_withApmOnWifiOnHasInternetWifi_returnThree() {
-        // The preconditions WiFi ON and Internet WiFi are already in setUp()
-        when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(true);
-
-        assertThat(mInternetAdapter.getItemCount()).isEqualTo(3);
-    }
-
-    @Test
-    public void getItemCount_withApmOffWifiOnNoInternetWifi_returnThree() {
-        // The preconditions WiFi ON is already in setUp()
-        when(mInternetDialogController.getInternetWifiEntry()).thenReturn(null);
-        when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(false);
-
-        assertThat(mInternetAdapter.getItemCount()).isEqualTo(3);
-    }
-
-    @Test
-    public void getItemCount_withApmOffWifiOnHasInternetWifi_returnTwo() {
-        // The preconditions WiFi ON and Internet WiFi are already in setUp()
-        when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(false);
-
-        assertThat(mInternetAdapter.getItemCount()).isEqualTo(2);
+            assertThat(mInternetAdapter.getItemCount()).isEqualTo(i);
+        }
     }
 
     @Test
@@ -118,7 +98,17 @@
     }
 
     @Test
-    public void onBindViewHolder_bindDefaultWifiNetwork_getIconWithInternet() {
+    public void onBindViewHolder_wifiLevelUnreachable_shouldNotGetWifiIcon() {
+        reset(mWifiIconInjector);
+        when(mWifiEntry.getLevel()).thenReturn(WifiEntry.WIFI_LEVEL_UNREACHABLE);
+
+        mInternetAdapter.onBindViewHolder(mViewHolder, 0);
+
+        verify(mWifiIconInjector, never()).getIcon(anyBoolean(), anyInt());
+    }
+
+    @Test
+    public void onBindViewHolder_shouldNotShowXLevelIcon_getIconWithInternet() {
         when(mWifiEntry.shouldShowXLevelIcon()).thenReturn(false);
 
         mInternetAdapter.onBindViewHolder(mViewHolder, 0);
@@ -127,7 +117,7 @@
     }
 
     @Test
-    public void onBindViewHolder_bindNoDefaultWifiNetwork_getIconWithNoInternet() {
+    public void onBindViewHolder_shouldShowXLevelIcon_getIconWithNoInternet() {
         when(mWifiEntry.shouldShowXLevelIcon()).thenReturn(true);
 
         mInternetAdapter.onBindViewHolder(mViewHolder, 0);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java
index 830fe5a..cacc409 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java
@@ -10,6 +10,7 @@
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -17,7 +18,6 @@
 import android.content.Intent;
 import android.graphics.drawable.Drawable;
 import android.net.ConnectivityManager;
-import android.net.wifi.ScanResult;
 import android.net.wifi.WifiManager;
 import android.os.Handler;
 import android.telephony.ServiceState;
@@ -84,14 +84,26 @@
     @Mock
     private WifiEntry mConnectedEntry;
     @Mock
+    private WifiEntry mWifiEntry1;
+    @Mock
+    private WifiEntry mWifiEntry2;
+    @Mock
+    private WifiEntry mWifiEntry3;
+    @Mock
+    private WifiEntry mWifiEntry4;
+    @Mock
     private ServiceState mServiceState;
     @Mock
     private BroadcastDispatcher mBroadcastDispatcher;
     @Mock
     private WifiUtils.InternetIconInjector mWifiIconInjector;
+    @Mock
+    InternetDialogController.InternetDialogCallback mInternetDialogCallback;
 
     private MockInternetDialogController mInternetDialogController;
     private FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
+    private List<WifiEntry> mAccessPoints = new ArrayList<>();
+    private List<WifiEntry> mWifiEntries = new ArrayList<>();
 
     @Before
     public void setUp() {
@@ -100,6 +112,13 @@
         when(mKeyguardStateController.isUnlocked()).thenReturn(true);
         when(mConnectedEntry.isDefaultNetwork()).thenReturn(true);
         when(mConnectedEntry.hasInternetAccess()).thenReturn(true);
+        when(mWifiEntry1.getConnectedState()).thenReturn(WifiEntry.CONNECTED_STATE_DISCONNECTED);
+        when(mWifiEntry2.getConnectedState()).thenReturn(WifiEntry.CONNECTED_STATE_DISCONNECTED);
+        when(mWifiEntry3.getConnectedState()).thenReturn(WifiEntry.CONNECTED_STATE_DISCONNECTED);
+        when(mWifiEntry4.getConnectedState()).thenReturn(WifiEntry.CONNECTED_STATE_DISCONNECTED);
+        mAccessPoints.add(mConnectedEntry);
+        mAccessPoints.add(mWifiEntry1);
+        when(mSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(new int[]{SUB_ID});
 
         mInternetDialogController = new MockInternetDialogController(mContext,
                 mock(UiEventLogger.class), mock(ActivityStarter.class), mAccessPointController,
@@ -108,10 +127,9 @@
                 mock(KeyguardUpdateMonitor.class), mGlobalSettings, mKeyguardStateController);
         mSubscriptionManager.addOnSubscriptionsChangedListener(mExecutor,
                 mInternetDialogController.mOnSubscriptionsChangedListener);
-        mInternetDialogController.onStart(
-                mock(InternetDialogController.InternetDialogCallback.class));
+        mInternetDialogController.onStart(mInternetDialogCallback, true);
+        mInternetDialogController.onAccessPointsChanged(mAccessPoints);
         mInternetDialogController.mActivityStarter = mActivityStarter;
-        mInternetDialogController.mConnectedEntry = mConnectedEntry;
         mInternetDialogController.mWifiIconInjector = mWifiIconInjector;
     }
 
@@ -143,32 +161,46 @@
         mInternetDialogController.setAirplaneModeEnabled(false);
         when(mWifiManager.isWifiEnabled()).thenReturn(false);
 
-        assertTrue(TextUtils.equals(mInternetDialogController.getSubtitleText(false),
-                getResourcesString("wifi_is_off")));
+        assertThat(mInternetDialogController.getSubtitleText(false))
+                .isEqualTo(getResourcesString("wifi_is_off"));
+
+        // if the Wi-Fi disallow config, then don't return Wi-Fi related string.
+        mInternetDialogController.mCanConfigWifi = false;
+
+        assertThat(mInternetDialogController.getSubtitleText(false))
+                .isNotEqualTo(getResourcesString("wifi_is_off"));
     }
 
     @Test
     public void getSubtitleText_withNoWifiEntry_returnSearchWifi() {
         mInternetDialogController.setAirplaneModeEnabled(false);
         when(mWifiManager.isWifiEnabled()).thenReturn(true);
-        List<ScanResult> wifiScanResults = mock(ArrayList.class);
-        doReturn(0).when(wifiScanResults).size();
-        when(mWifiManager.getScanResults()).thenReturn(wifiScanResults);
+        mInternetDialogController.onAccessPointsChanged(null /* accessPoints */);
 
-        assertTrue(TextUtils.equals(mInternetDialogController.getSubtitleText(true),
-                getResourcesString("wifi_empty_list_wifi_on")));
+        assertThat(mInternetDialogController.getSubtitleText(true))
+                .isEqualTo(getResourcesString("wifi_empty_list_wifi_on"));
+
+        // if the Wi-Fi disallow config, then don't return Wi-Fi related string.
+        mInternetDialogController.mCanConfigWifi = false;
+
+        assertThat(mInternetDialogController.getSubtitleText(true))
+                .isNotEqualTo(getResourcesString("wifi_empty_list_wifi_on"));
     }
 
     @Test
     public void getSubtitleText_withWifiEntry_returnTapToConnect() {
+        // The preconditions WiFi Entries is already in setUp()
         mInternetDialogController.setAirplaneModeEnabled(false);
         when(mWifiManager.isWifiEnabled()).thenReturn(true);
-        List<ScanResult> wifiScanResults = mock(ArrayList.class);
-        doReturn(1).when(wifiScanResults).size();
-        when(mWifiManager.getScanResults()).thenReturn(wifiScanResults);
 
-        assertTrue(TextUtils.equals(mInternetDialogController.getSubtitleText(false),
-                getResourcesString("tap_a_network_to_connect")));
+        assertThat(mInternetDialogController.getSubtitleText(false))
+                .isEqualTo(getResourcesString("tap_a_network_to_connect"));
+
+        // if the Wi-Fi disallow config, then don't return Wi-Fi related string.
+        mInternetDialogController.mCanConfigWifi = false;
+
+        assertThat(mInternetDialogController.getSubtitleText(false))
+                .isNotEqualTo(getResourcesString("tap_a_network_to_connect"));
     }
 
     @Test
@@ -185,11 +217,7 @@
     public void getSubtitleText_withNoService_returnNoNetworksAvailable() {
         mInternetDialogController.setAirplaneModeEnabled(false);
         when(mWifiManager.isWifiEnabled()).thenReturn(true);
-        List<ScanResult> wifiScanResults = new ArrayList<>();
-        doReturn(wifiScanResults).when(mWifiManager).getScanResults();
-        when(mWifiManager.getScanResults()).thenReturn(wifiScanResults);
-        when(mSubscriptionManager.getActiveSubscriptionIdList())
-                .thenReturn(new int[] {SUB_ID});
+        mInternetDialogController.onAccessPointsChanged(null /* accessPoints */);
 
         doReturn(ServiceState.STATE_OUT_OF_SERVICE).when(mServiceState).getState();
         doReturn(mServiceState).when(mTelephonyManager).getServiceState();
@@ -203,83 +231,26 @@
     public void getSubtitleText_withMobileDataDisabled_returnNoOtherAvailable() {
         mInternetDialogController.setAirplaneModeEnabled(false);
         when(mWifiManager.isWifiEnabled()).thenReturn(true);
-        List<ScanResult> wifiScanResults = new ArrayList<>();
-        doReturn(wifiScanResults).when(mWifiManager).getScanResults();
-        when(mWifiManager.getScanResults()).thenReturn(wifiScanResults);
-        when(mSubscriptionManager.getActiveSubscriptionIdList())
-                .thenReturn(new int[] {SUB_ID});
+        mInternetDialogController.onAccessPointsChanged(null /* accessPoints */);
 
         doReturn(ServiceState.STATE_IN_SERVICE).when(mServiceState).getState();
         doReturn(mServiceState).when(mTelephonyManager).getServiceState();
 
         when(mTelephonyManager.isDataEnabled()).thenReturn(false);
 
-        assertTrue(TextUtils.equals(mInternetDialogController.getSubtitleText(false),
-                getResourcesString("non_carrier_network_unavailable")));
-    }
+        assertThat(mInternetDialogController.getSubtitleText(false))
+                .isEqualTo(getResourcesString("non_carrier_network_unavailable"));
 
-    @Test
-    public void getInternetWifiEntry_connectedEntryIsNull_returnNull() {
-        mInternetDialogController.mConnectedEntry = null;
+        // if the Wi-Fi disallow config, then don't return Wi-Fi related string.
+        mInternetDialogController.mCanConfigWifi = false;
 
-        assertThat(mInternetDialogController.getInternetWifiEntry()).isNull();
-    }
-
-    @Test
-    public void getInternetWifiEntry_connectedWifiIsNotDefaultNetwork_returnNull() {
-        when(mConnectedEntry.isDefaultNetwork()).thenReturn(false);
-
-        assertThat(mInternetDialogController.getInternetWifiEntry()).isNull();
-    }
-
-    @Test
-    public void getInternetWifiEntry_connectedWifiHasNotInternetAccess_returnNull() {
-        when(mConnectedEntry.hasInternetAccess()).thenReturn(false);
-
-        assertThat(mInternetDialogController.getInternetWifiEntry()).isNull();
-    }
-
-    @Test
-    public void getInternetWifiEntry_connectedEntryIsInternetWifi_returnConnectedEntry() {
-        // The preconditions have been set in setUp().
-        //   - The connected Wi-Fi entry have both default network and internet access conditions.
-
-        assertThat(mInternetDialogController.getInternetWifiEntry()).isEqualTo(mConnectedEntry);
-    }
-
-    @Test
-    public void getInternetWifiTitle_withNoConnectedWifiEntry_returnEmpty() {
-        mInternetDialogController.mConnectedEntry = null;
-
-        assertThat(mInternetDialogController.getInternetWifiTitle()).isEmpty();
-    }
-
-    @Test
-    public void getInternetWifiTitle_withInternetWifi_returnTitle() {
-        // The preconditions have been set in setUp().
-        //   - The connected Wi-Fi entry have both default network and internet access conditions.
-        when(mConnectedEntry.getTitle()).thenReturn(CONNECTED_TITLE);
-
-        assertThat(mInternetDialogController.getInternetWifiTitle()).isEqualTo(CONNECTED_TITLE);
-    }
-
-    @Test
-    public void getInternetWifiSummary_withNoConnectedWifiEntry_returnEmpty() {
-        mInternetDialogController.mConnectedEntry = null;
-
-        assertThat(mInternetDialogController.getInternetWifiSummary()).isEmpty();
-    }
-
-    @Test
-    public void getInternetWifiSummary_withInternetWifi_returnSummary() {
-        when(mConnectedEntry.getSummary(false)).thenReturn(CONNECTED_SUMMARY);
-
-        assertThat(mInternetDialogController.getInternetWifiSummary()).isEqualTo(CONNECTED_SUMMARY);
+        assertThat(mInternetDialogController.getSubtitleText(false))
+                .isNotEqualTo(getResourcesString("non_carrier_network_unavailable"));
     }
 
     @Test
     public void getWifiDetailsSettingsIntent_withNoConnectedEntry_returnNull() {
-        mInternetDialogController.mConnectedEntry = null;
+        mInternetDialogController.onAccessPointsChanged(null /* accessPoints */);
 
         assertThat(mInternetDialogController.getWifiDetailsSettingsIntent()).isNull();
     }
@@ -311,7 +282,7 @@
 
     @Test
     public void launchWifiNetworkDetailsSetting_withNoConnectedEntry_doNothing() {
-        mInternetDialogController.mConnectedEntry = null;
+        mInternetDialogController.onAccessPointsChanged(null /* accessPoints */);
 
         mInternetDialogController.launchWifiNetworkDetailsSetting();
 
@@ -342,6 +313,143 @@
         assertThat(mInternetDialogController.isDeviceLocked()).isTrue();
     }
 
+    @Test
+    public void onAccessPointsChanged_canNotConfigWifi_doNothing() {
+        reset(mInternetDialogCallback);
+        mInternetDialogController.mCanConfigWifi = false;
+
+        mInternetDialogController.onAccessPointsChanged(null /* accessPoints */);
+
+        verify(mInternetDialogCallback, never()).onAccessPointsChanged(any(), any());
+    }
+
+    @Test
+    public void onAccessPointsChanged_nullAccessPoints_callbackBothNull() {
+        reset(mInternetDialogCallback);
+
+        mInternetDialogController.onAccessPointsChanged(null /* accessPoints */);
+
+        verify(mInternetDialogCallback)
+                .onAccessPointsChanged(null /* wifiEntries */, null /* connectedEntry */);
+    }
+
+    @Test
+    public void onAccessPointsChanged_oneConnectedEntry_callbackConnectedEntryOnly() {
+        reset(mInternetDialogCallback);
+        mInternetDialogController.setAirplaneModeEnabled(true);
+        mAccessPoints.clear();
+        mAccessPoints.add(mConnectedEntry);
+
+        mInternetDialogController.onAccessPointsChanged(mAccessPoints);
+
+        mWifiEntries.clear();
+        verify(mInternetDialogCallback).onAccessPointsChanged(mWifiEntries, mConnectedEntry);
+    }
+
+    @Test
+    public void onAccessPointsChanged_noConnectedEntryAndOneOther_callbackWifiEntriesOnly() {
+        reset(mInternetDialogCallback);
+        mInternetDialogController.setAirplaneModeEnabled(true);
+        mAccessPoints.clear();
+        mAccessPoints.add(mWifiEntry1);
+
+        mInternetDialogController.onAccessPointsChanged(mAccessPoints);
+
+        mWifiEntries.clear();
+        mWifiEntries.add(mWifiEntry1);
+        verify(mInternetDialogCallback)
+                .onAccessPointsChanged(mWifiEntries, null /* connectedEntry */);
+    }
+
+    @Test
+    public void onAccessPointsChanged_oneConnectedEntryAndOneOther_callbackCorrectly() {
+        reset(mInternetDialogCallback);
+        mInternetDialogController.setAirplaneModeEnabled(true);
+        mAccessPoints.clear();
+        mAccessPoints.add(mConnectedEntry);
+        mAccessPoints.add(mWifiEntry1);
+
+        mInternetDialogController.onAccessPointsChanged(mAccessPoints);
+
+        mWifiEntries.clear();
+        mWifiEntries.add(mWifiEntry1);
+        verify(mInternetDialogCallback).onAccessPointsChanged(mWifiEntries, mConnectedEntry);
+    }
+
+    @Test
+    public void onAccessPointsChanged_oneConnectedEntryAndTwoOthers_callbackCorrectly() {
+        reset(mInternetDialogCallback);
+        mInternetDialogController.setAirplaneModeEnabled(true);
+        mAccessPoints.clear();
+        mAccessPoints.add(mConnectedEntry);
+        mAccessPoints.add(mWifiEntry1);
+        mAccessPoints.add(mWifiEntry2);
+
+        mInternetDialogController.onAccessPointsChanged(mAccessPoints);
+
+        mWifiEntries.clear();
+        mWifiEntries.add(mWifiEntry1);
+        mWifiEntries.add(mWifiEntry2);
+        verify(mInternetDialogCallback).onAccessPointsChanged(mWifiEntries, mConnectedEntry);
+    }
+
+    @Test
+    public void onAccessPointsChanged_oneConnectedEntryAndThreeOthers_callbackCutMore() {
+        reset(mInternetDialogCallback);
+        mInternetDialogController.setAirplaneModeEnabled(true);
+        mAccessPoints.clear();
+        mAccessPoints.add(mConnectedEntry);
+        mAccessPoints.add(mWifiEntry1);
+        mAccessPoints.add(mWifiEntry2);
+        mAccessPoints.add(mWifiEntry3);
+
+        mInternetDialogController.onAccessPointsChanged(mAccessPoints);
+
+        mWifiEntries.clear();
+        mWifiEntries.add(mWifiEntry1);
+        mWifiEntries.add(mWifiEntry2);
+        mWifiEntries.add(mWifiEntry3);
+        verify(mInternetDialogCallback).onAccessPointsChanged(mWifiEntries, mConnectedEntry);
+
+        // Turn off airplane mode to has carrier network, then Wi-Fi entries will cut last one.
+        reset(mInternetDialogCallback);
+        mInternetDialogController.setAirplaneModeEnabled(false);
+
+        mInternetDialogController.onAccessPointsChanged(mAccessPoints);
+
+        mWifiEntries.remove(mWifiEntry3);
+        verify(mInternetDialogCallback).onAccessPointsChanged(mWifiEntries, mConnectedEntry);
+    }
+
+    @Test
+    public void onAccessPointsChanged_oneConnectedEntryAndFourOthers_callbackCutMore() {
+        reset(mInternetDialogCallback);
+        mInternetDialogController.setAirplaneModeEnabled(true);
+        mAccessPoints.clear();
+        mAccessPoints.add(mConnectedEntry);
+        mAccessPoints.add(mWifiEntry1);
+        mAccessPoints.add(mWifiEntry2);
+        mAccessPoints.add(mWifiEntry3);
+        mAccessPoints.add(mWifiEntry4);
+
+        mInternetDialogController.onAccessPointsChanged(mAccessPoints);
+
+        mWifiEntries.clear();
+        mWifiEntries.add(mWifiEntry1);
+        mWifiEntries.add(mWifiEntry2);
+        mWifiEntries.add(mWifiEntry3);
+        verify(mInternetDialogCallback).onAccessPointsChanged(mWifiEntries, mConnectedEntry);
+
+        // Turn off airplane mode to has carrier network, then Wi-Fi entries will cut last one.
+        reset(mInternetDialogCallback);
+        mInternetDialogController.setAirplaneModeEnabled(false);
+
+        mInternetDialogController.onAccessPointsChanged(mAccessPoints);
+
+        mWifiEntries.remove(mWifiEntry3);
+        verify(mInternetDialogCallback).onAccessPointsChanged(mWifiEntries, mConnectedEntry);
+    }
+
     private String getResourcesString(String name) {
         return mContext.getResources().getString(getResourcesId(name));
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java
index 5a018f4..fa9c053 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java
@@ -12,7 +12,6 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import android.net.wifi.ScanResult;
 import android.net.wifi.WifiManager;
 import android.os.Handler;
 import android.telephony.TelephonyManager;
@@ -20,7 +19,6 @@
 import android.testing.TestableLooper;
 import android.view.View;
 import android.widget.LinearLayout;
-import android.widget.TextView;
 
 import androidx.recyclerview.widget.RecyclerView;
 import androidx.test.filters.SmallTest;
@@ -39,8 +37,6 @@
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 
-import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 
 @SmallTest
@@ -62,13 +58,16 @@
     @Mock
     private WifiEntry mInternetWifiEntry;
     @Mock
-    private WifiEntry mWifiEntry;
+    private List<WifiEntry> mWifiEntries;
     @Mock
     private InternetAdapter mInternetAdapter;
     @Mock
     private InternetDialogController mInternetDialogController;
 
     private InternetDialog mInternetDialog;
+    private View mDialogView;
+    private View mSubTitle;
+    private LinearLayout mMobileDataToggle;
     private LinearLayout mWifiToggle;
     private LinearLayout mConnectedWifi;
     private RecyclerView mWifiList;
@@ -83,26 +82,26 @@
         when(mInternetWifiEntry.getSummary(false)).thenReturn(WIFI_SUMMARY);
         when(mInternetWifiEntry.isDefaultNetwork()).thenReturn(true);
         when(mInternetWifiEntry.hasInternetAccess()).thenReturn(true);
-        when(mWifiEntry.getTitle()).thenReturn(WIFI_TITLE);
-        when(mWifiEntry.getSummary(false)).thenReturn(WIFI_SUMMARY);
+        when(mWifiEntries.size()).thenReturn(1);
 
         when(mInternetDialogController.getMobileNetworkTitle()).thenReturn(MOBILE_NETWORK_TITLE);
         when(mInternetDialogController.getMobileNetworkSummary())
                 .thenReturn(MOBILE_NETWORK_SUMMARY);
         when(mInternetDialogController.getWifiManager()).thenReturn(mWifiManager);
-        when(mInternetDialogController.getInternetWifiEntry()).thenReturn(mInternetWifiEntry);
-        when(mInternetDialogController.getWifiEntryList()).thenReturn(Arrays.asList(mWifiEntry));
 
         mInternetDialog = new InternetDialog(mContext, mock(InternetDialogFactory.class),
-                mInternetDialogController, true, true, mock(UiEventLogger.class), mHandler);
+                mInternetDialogController, true, true, true, mock(UiEventLogger.class), mHandler);
         mInternetDialog.mAdapter = mInternetAdapter;
-        mInternetDialog.mConnectedWifiEntry = mInternetWifiEntry;
+        mInternetDialog.onAccessPointsChanged(mWifiEntries, mInternetWifiEntry);
         mInternetDialog.show();
 
-        mWifiToggle = mInternetDialog.mDialogView.requireViewById(R.id.turn_on_wifi_layout);
-        mConnectedWifi = mInternetDialog.mDialogView.requireViewById(R.id.wifi_connected_layout);
-        mWifiList = mInternetDialog.mDialogView.requireViewById(R.id.wifi_list_layout);
-        mSeeAll = mInternetDialog.mDialogView.requireViewById(R.id.see_all_layout);
+        mDialogView = mInternetDialog.mDialogView;
+        mSubTitle = mDialogView.requireViewById(R.id.internet_dialog_subtitle);
+        mMobileDataToggle = mDialogView.requireViewById(R.id.mobile_network_layout);
+        mWifiToggle = mDialogView.requireViewById(R.id.turn_on_wifi_layout);
+        mConnectedWifi = mDialogView.requireViewById(R.id.wifi_connected_layout);
+        mWifiList = mDialogView.requireViewById(R.id.wifi_list_layout);
+        mSeeAll = mDialogView.requireViewById(R.id.see_all_layout);
     }
 
     @After
@@ -111,33 +110,41 @@
     }
 
     @Test
+    public void hideWifiViews_WifiViewsGone() {
+        mInternetDialog.hideWifiViews();
+
+        assertThat(mInternetDialog.mIsProgressBarVisible).isFalse();
+        assertThat(mWifiToggle.getVisibility()).isEqualTo(View.GONE);
+        assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE);
+        assertThat(mWifiList.getVisibility()).isEqualTo(View.GONE);
+        assertThat(mSeeAll.getVisibility()).isEqualTo(View.GONE);
+    }
+
+    @Test
     public void updateDialog_withApmOn_internetDialogSubTitleGone() {
         when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(true);
-        mInternetDialog.updateDialog();
-        final TextView view = mInternetDialog.mDialogView.requireViewById(
-                R.id.internet_dialog_subtitle);
 
-        assertThat(view.getVisibility()).isEqualTo(View.GONE);
+        mInternetDialog.updateDialog();
+
+        assertThat(mSubTitle.getVisibility()).isEqualTo(View.GONE);
     }
 
     @Test
     public void updateDialog_withApmOff_internetDialogSubTitleVisible() {
         when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(false);
-        mInternetDialog.updateDialog();
-        final TextView view = mInternetDialog.mDialogView.requireViewById(
-                R.id.internet_dialog_subtitle);
 
-        assertThat(view.getVisibility()).isEqualTo(View.VISIBLE);
+        mInternetDialog.updateDialog();
+
+        assertThat(mSubTitle.getVisibility()).isEqualTo(View.VISIBLE);
     }
 
     @Test
     public void updateDialog_withApmOn_mobileDataLayoutGone() {
         when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(true);
-        mInternetDialog.updateDialog();
-        final LinearLayout linearLayout = mInternetDialog.mDialogView.requireViewById(
-                R.id.mobile_network_layout);
 
-        assertThat(linearLayout.getVisibility()).isEqualTo(View.GONE);
+        mInternetDialog.updateDialog();
+
+        assertThat(mMobileDataToggle.getVisibility()).isEqualTo(View.GONE);
     }
 
     @Test
@@ -152,7 +159,8 @@
 
     @Test
     public void updateDialog_wifiOnAndNoConnectedWifi_hideConnectedWifi() {
-        mInternetDialog.mConnectedWifiEntry = null;
+        // The precondition WiFi ON is already in setUp()
+        mInternetDialog.onAccessPointsChanged(mWifiEntries, null /* connectedEntry*/);
         doReturn(false).when(mInternetDialogController).activeNetworkIsCellular();
 
         mInternetDialog.updateDialog();
@@ -162,7 +170,8 @@
 
     @Test
     public void updateDialog_wifiOnAndNoWifiList_hideWifiListAndSeeAll() {
-        when(mInternetDialogController.getWifiEntryList()).thenReturn(null);
+        // The precondition WiFi ON is already in setUp()
+        mInternetDialog.onAccessPointsChanged(null /* wifiEntries */, mInternetWifiEntry);
 
         mInternetDialog.updateDialog();
 
@@ -245,9 +254,6 @@
     public void showProgressBar_wifiEnabledWithWifiEntry_showProgressBarThenHide() {
         Mockito.reset(mHandler);
         when(mWifiManager.isWifiEnabled()).thenReturn(true);
-        List<ScanResult> wifiScanResults = mock(ArrayList.class);
-        when(wifiScanResults.size()).thenReturn(1);
-        when(mWifiManager.getScanResults()).thenReturn(wifiScanResults);
 
         mInternetDialog.showProgressBar();
 
@@ -264,12 +270,10 @@
     }
 
     @Test
-    public void showProgressBar_wifiEnabledWithoutWifiScanResults_showProgressBarThenHideSearch() {
+    public void showProgressBar_wifiEnabledWithoutWifiEntries_showProgressBarThenHideSearch() {
         Mockito.reset(mHandler);
         when(mWifiManager.isWifiEnabled()).thenReturn(true);
-        List<ScanResult> wifiScanResults = mock(ArrayList.class);
-        when(wifiScanResults.size()).thenReturn(0);
-        when(mWifiManager.getScanResults()).thenReturn(wifiScanResults);
+        mInternetDialog.onAccessPointsChanged(null /* wifiEntries */, null /* connectedEntry*/);
 
         mInternetDialog.showProgressBar();
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java
index aa73152..f9e3707 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java
@@ -17,10 +17,14 @@
 package com.android.systemui.statusbar.phone;
 
 
+import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
+import static com.android.systemui.statusbar.StatusBarState.SHADE;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
@@ -30,18 +34,24 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.keyguard.CarrierTextController;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.KeyguardUpdateMonitorCallback;
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.battery.BatteryMeterViewController;
 import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
 import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler;
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.statusbar.policy.UserInfoController;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
@@ -66,11 +76,23 @@
     @Mock
     private BatteryMeterViewController mBatteryMeterViewController;
     @Mock
-    private KeyguardStatusBarViewController.ViewStateProvider mViewStateProvider;
+    private KeyguardStateController mKeyguardStateController;
+    @Mock
+    private KeyguardBypassController mKeyguardBypassController;
+    @Mock
+    private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+    @Mock
+    private BiometricUnlockController mBiometricUnlockController;
+    @Mock
+    private SysuiStatusBarStateController mStatusBarStateController;
 
     private KeyguardStatusBarView mKeyguardStatusBarView;
     private KeyguardStatusBarViewController mController;
 
+    private float mAlpha = 0.5f;
+    private final KeyguardStatusBarViewController.ViewStateProvider mViewStateProvider =
+            () -> new KeyguardStatusBarViewController.ViewState(mAlpha);
+
     @Before
     public void setup() throws Exception {
         MockitoAnnotations.initMocks(this);
@@ -92,7 +114,12 @@
                 mStatusBarIconController,
                 new StatusBarIconController.TintedIconManager.Factory(mFeatureFlags),
                 mBatteryMeterViewController,
-                mViewStateProvider
+                mViewStateProvider,
+                mKeyguardStateController,
+                mKeyguardBypassController,
+                mKeyguardUpdateMonitor,
+                mBiometricUnlockController,
+                mStatusBarStateController
         );
     }
 
@@ -180,4 +207,92 @@
         assertThat(mKeyguardStatusBarView.getAlpha()).isEqualTo(newAlpha);
         assertThat(mKeyguardStatusBarView.getVisibility()).isEqualTo(newVisibility);
     }
+
+    @Test
+    public void updateViewState_notKeyguardState_nothingUpdated() {
+        mAlpha = 0.255f;
+        mController.onViewAttached();
+        updateStateToNotKeyguard();
+
+        float oldAlpha = mKeyguardStatusBarView.getAlpha();
+
+        mController.updateViewState();
+
+        assertThat(mKeyguardStatusBarView.getAlpha()).isEqualTo(oldAlpha);
+    }
+
+    @Test
+    public void updateViewState_bypassEnabledAndShouldListenForFace_viewHidden() {
+        mController.onViewAttached();
+        updateStateToKeyguard();
+        assertThat(mKeyguardStatusBarView.getVisibility()).isEqualTo(View.VISIBLE);
+
+        when(mKeyguardUpdateMonitor.shouldListenForFace()).thenReturn(true);
+        when(mKeyguardBypassController.getBypassEnabled()).thenReturn(true);
+        onFinishedGoingToSleep();
+
+        mController.updateViewState();
+
+        assertThat(mKeyguardStatusBarView.getVisibility()).isEqualTo(View.INVISIBLE);
+    }
+
+    @Test
+    public void updateViewState_bypassNotEnabled_viewShown() {
+        mController.onViewAttached();
+        updateStateToKeyguard();
+
+        when(mKeyguardUpdateMonitor.shouldListenForFace()).thenReturn(true);
+        when(mKeyguardBypassController.getBypassEnabled()).thenReturn(false);
+        onFinishedGoingToSleep();
+
+        mController.updateViewState();
+
+        assertThat(mKeyguardStatusBarView.getVisibility()).isEqualTo(View.VISIBLE);
+    }
+
+    @Test
+    public void updateViewState_shouldNotListenForFace_viewShown() {
+        mController.onViewAttached();
+        updateStateToKeyguard();
+
+        when(mKeyguardUpdateMonitor.shouldListenForFace()).thenReturn(false);
+        when(mKeyguardBypassController.getBypassEnabled()).thenReturn(true);
+        onFinishedGoingToSleep();
+
+        mController.updateViewState();
+
+        assertThat(mKeyguardStatusBarView.getVisibility()).isEqualTo(View.VISIBLE);
+    }
+
+    // TODO(b/195442899): Add more tests for #updateViewState once CLs are finalized.
+
+    private void updateStateToNotKeyguard() {
+        updateStatusBarState(SHADE);
+    }
+
+    private void updateStateToKeyguard() {
+        updateStatusBarState(KEYGUARD);
+    }
+
+    private void updateStatusBarState(int state) {
+        ArgumentCaptor<StatusBarStateController.StateListener> statusBarStateListenerCaptor =
+                ArgumentCaptor.forClass(StatusBarStateController.StateListener.class);
+        verify(mStatusBarStateController).addCallback(statusBarStateListenerCaptor.capture());
+        StatusBarStateController.StateListener callback = statusBarStateListenerCaptor.getValue();
+
+        callback.onStateChanged(state);
+    }
+
+    /**
+     * Calls {@link com.android.keyguard.KeyguardUpdateMonitorCallback#onFinishedGoingToSleep(int)}
+     * to ensure values are updated properly.
+     */
+    private void onFinishedGoingToSleep() {
+        ArgumentCaptor<KeyguardUpdateMonitorCallback> keyguardUpdateCallbackCaptor =
+                ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback.class);
+        verify(mKeyguardUpdateMonitor).registerCallback(keyguardUpdateCallbackCaptor.capture());
+        KeyguardUpdateMonitorCallback callback = keyguardUpdateCallbackCaptor.getValue();
+
+        callback.onFinishedGoingToSleep(0);
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
index 1dc6fa2..bef10ce 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
@@ -47,7 +47,6 @@
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.database.ContentObserver;
-import android.hardware.biometrics.BiometricSourceType;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.PowerManager;
@@ -229,8 +228,6 @@
     @Mock
     private ConversationNotificationManager mConversationNotificationManager;
     @Mock
-    private BiometricUnlockController mBiometricUnlockController;
-    @Mock
     private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
     @Mock
     private KeyguardStatusViewComponent.Factory mKeyguardStatusViewComponentFactory;
@@ -416,7 +413,7 @@
                 mMetricsLogger, mActivityManager, mConfigurationController,
                 () -> flingAnimationUtilsBuilder, mStatusBarTouchableRegionManager,
                 mConversationNotificationManager, mMediaHiearchyManager,
-                mBiometricUnlockController, mStatusBarKeyguardViewManager,
+                mStatusBarKeyguardViewManager,
                 mNotificationStackScrollLayoutController,
                 mKeyguardStatusViewComponentFactory,
                 mKeyguardQsUserSwitchComponentFactory,
@@ -512,20 +509,6 @@
     }
 
     @Test
-    public void testKeyguardStatusBarVisibility_hiddenForBypass() {
-        when(mUpdateMonitor.shouldListenForFace()).thenReturn(true);
-        mNotificationPanelViewController.mKeyguardUpdateCallback.onBiometricRunningStateChanged(
-                true, BiometricSourceType.FACE);
-        verify(mKeyguardStatusBar, never()).setVisibility(View.VISIBLE);
-
-        when(mKeyguardBypassController.getBypassEnabled()).thenReturn(true);
-        mNotificationPanelViewController.mKeyguardUpdateCallback.onFinishedGoingToSleep(0);
-        mNotificationPanelViewController.mKeyguardUpdateCallback.onBiometricRunningStateChanged(
-                true, BiometricSourceType.FACE);
-        verify(mKeyguardStatusBar, never()).setVisibility(View.VISIBLE);
-    }
-
-    @Test
     public void testA11y_initializeNode() {
         AccessibilityNodeInfo nodeInfo = new AccessibilityNodeInfo();
         mAccessibiltyDelegate.onInitializeAccessibilityNodeInfo(mView, nodeInfo);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index 21c4a17..c488ee9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -70,6 +70,7 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.demomode.DemoModeController;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
@@ -241,7 +242,9 @@
                 mMockBd,
                 mDemoModeController,
                 mCarrierConfigTracker,
-                mFeatureFlags);
+                mFeatureFlags,
+                mock(DumpManager.class)
+        );
         setupNetworkController();
 
         // Trigger blank callbacks to always get the current state (some tests don't trigger
@@ -309,7 +312,8 @@
                         mock(AccessPointControllerImpl.class),
                         mock(DataUsageController.class), mMockSubDefaults,
                         mock(DeviceProvisionedController.class), mMockBd, mDemoModeController,
-                        mCarrierConfigTracker, mFeatureFlags);
+                        mCarrierConfigTracker, mFeatureFlags,
+                        mock(DumpManager.class));
 
         setupNetworkController();
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
index bc4c2b6..3433a14 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
@@ -21,6 +21,7 @@
 
 import com.android.settingslib.mobile.TelephonyIcons;
 import com.android.settingslib.net.DataUsageController;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.util.CarrierConfigTracker;
 
 import org.junit.Test;
@@ -113,7 +114,7 @@
                 mock(AccessPointControllerImpl.class),
                 mock(DataUsageController.class), mMockSubDefaults,
                 mock(DeviceProvisionedController.class), mMockBd, mDemoModeController,
-                mock(CarrierConfigTracker.class), mFeatureFlags);
+                mock(CarrierConfigTracker.class), mFeatureFlags, mock(DumpManager.class));
         setupNetworkController();
 
         setupDefaultSignal();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
index 5090b0d..4ff1301 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
@@ -41,6 +41,7 @@
 import com.android.settingslib.mobile.TelephonyIcons;
 import com.android.settingslib.net.DataUsageController;
 import com.android.systemui.R;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.util.CarrierConfigTracker;
 
 import org.junit.Test;
@@ -67,7 +68,8 @@
                 Looper.getMainLooper(), mFakeExecutor, mCallbackHandler,
                 mock(AccessPointControllerImpl.class), mock(DataUsageController.class),
                 mMockSubDefaults, mock(DeviceProvisionedController.class), mMockBd,
-                mDemoModeController, mock(CarrierConfigTracker.class), mFeatureFlags);
+                mDemoModeController, mock(CarrierConfigTracker.class), mFeatureFlags,
+                mock(DumpManager.class));
         setupNetworkController();
 
         verifyLastMobileDataIndicators(false, -1, 0);
@@ -87,7 +89,8 @@
                 Looper.getMainLooper(), mFakeExecutor, mCallbackHandler,
                 mock(AccessPointControllerImpl.class), mock(DataUsageController.class),
                 mMockSubDefaults, mock(DeviceProvisionedController.class), mMockBd,
-                mDemoModeController, mock(CarrierConfigTracker.class), mFeatureFlags);
+                mDemoModeController, mock(CarrierConfigTracker.class), mFeatureFlags,
+                mock(DumpManager.class));
         mNetworkController.registerListeners();
 
         // Wait for the main looper to execute the previous command
@@ -155,7 +158,8 @@
                 Looper.getMainLooper(), mFakeExecutor, mCallbackHandler,
                 mock(AccessPointControllerImpl.class), mock(DataUsageController.class),
                 mMockSubDefaults, mock(DeviceProvisionedController.class), mMockBd,
-                mDemoModeController, mock(CarrierConfigTracker.class), mFeatureFlags);
+                mDemoModeController, mock(CarrierConfigTracker.class), mFeatureFlags,
+                mock(DumpManager.class));
         setupNetworkController();
 
         // No Subscriptions.
diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
index 4c9d0f2..2ae5cbb 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
@@ -590,7 +590,7 @@
             newIndex = i - newStart;
             final float newBacklightVal;
             final float newNitsVal;
-            isLastValue = mRawBacklight[i] > mBacklightMaximum
+            isLastValue = mRawBacklight[i] >= mBacklightMaximum
                     || i >= mRawBacklight.length - 1;
             // Clamp beginning and end to valid backlight values.
             if (newIndex == 0) {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 207baf5..78c909d 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -7449,15 +7449,21 @@
                         sentAccessibilityEvent = true;
                     }
                     if (DBG) Slog.v(TAG, "Interrupting!");
+                    boolean isInsistentUpdate = isInsistentUpdate(record);
                     if (hasValidSound) {
-                        if (isInCall()) {
-                            playInCallNotification();
+                        if (isInsistentUpdate) {
+                            // don't reset insistent sound, it's jarring
                             beep = true;
                         } else {
-                            beep = playSound(record, soundUri);
-                        }
-                        if(beep) {
-                            mSoundNotificationKey = key;
+                            if (isInCall()) {
+                                playInCallNotification();
+                                beep = true;
+                            } else {
+                                beep = playSound(record, soundUri);
+                            }
+                            if (beep) {
+                                mSoundNotificationKey = key;
+                            }
                         }
                     }
 
@@ -7465,9 +7471,13 @@
                             mAudioManager.getRingerModeInternal()
                                     == AudioManager.RINGER_MODE_SILENT;
                     if (!isInCall() && hasValidVibrate && !ringerModeSilent) {
-                        buzz = playVibration(record, vibration, hasValidSound);
-                        if(buzz) {
-                            mVibrateNotificationKey = key;
+                        if (isInsistentUpdate) {
+                            buzz = true;
+                        } else {
+                            buzz = playVibration(record, vibration, hasValidSound);
+                            if (buzz) {
+                                mVibrateNotificationKey = key;
+                            }
                         }
                     }
                 } else if ((record.getFlags() & Notification.FLAG_INSISTENT) != 0) {
@@ -7571,6 +7581,19 @@
     }
 
     @GuardedBy("mNotificationLock")
+    boolean isInsistentUpdate(final NotificationRecord record) {
+        return (Objects.equals(record.getKey(), mSoundNotificationKey)
+                || Objects.equals(record.getKey(), mVibrateNotificationKey))
+                && isCurrentlyInsistent();
+    }
+
+    @GuardedBy("mNotificationLock")
+    boolean isCurrentlyInsistent() {
+        return isLoopingRingtoneNotification(mNotificationsByKey.get(mSoundNotificationKey))
+                || isLoopingRingtoneNotification(mNotificationsByKey.get(mVibrateNotificationKey));
+    }
+
+    @GuardedBy("mNotificationLock")
     boolean shouldMuteNotificationLocked(final NotificationRecord record) {
         // Suppressed because it's a silent update
         final Notification notification = record.getNotification();
@@ -7609,10 +7632,8 @@
             return true;
         }
 
-        // A looping ringtone, such as an incoming call is playing
-        if (isLoopingRingtoneNotification(mNotificationsByKey.get(mSoundNotificationKey))
-                || isLoopingRingtoneNotification(
-                        mNotificationsByKey.get(mVibrateNotificationKey))) {
+        // A different looping ringtone, such as an incoming call is playing
+        if (isCurrentlyInsistent() && !isInsistentUpdate(record)) {
             return true;
         }
 
@@ -8756,10 +8777,22 @@
 
     void snoozeNotificationInt(String key, long duration, String snoozeCriterionId,
             ManagedServiceInfo listener) {
-        String listenerName = listener == null ? null : listener.component.toShortString();
+        if (listener == null) {
+            return;
+        }
+        String listenerName = listener.component.toShortString();
         if ((duration <= 0 && snoozeCriterionId == null) || key == null) {
             return;
         }
+        synchronized (mNotificationLock) {
+            final NotificationRecord r = findInCurrentAndSnoozedNotificationByKeyLocked(key);
+            if (r == null) {
+                return;
+            }
+            if (!listener.enabledAndUserMatches(r.getSbn().getNormalizedUserId())){
+                return;
+            }
+        }
 
         if (DBG) {
             Slog.d(TAG, String.format("snooze event(%s, %d, %s, %s)", key, duration,
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index f37be64..1265744 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -8117,9 +8117,15 @@
             // This could prevent if there is no container animation, we still have to apply the
             // pending transaction and exit waiting.
             mAnimator.mNotifyWhenNoAnimation = true;
+            boolean animateStarting = false;
             while (timeoutRemaining > 0) {
+                // Waiting until all starting windows has finished animating.
+                animateStarting = mRoot.forAllActivities(a -> {
+                    return a.hasStartingWindow();
+                });
                 boolean isAnimating = mAnimator.isAnimationScheduled()
-                        || mRoot.isAnimating(TRANSITION | CHILDREN, ANIMATION_TYPE_ALL);
+                        || mRoot.isAnimating(TRANSITION | CHILDREN, ANIMATION_TYPE_ALL)
+                        || animateStarting;
                 if (!isAnimating) {
                     // isAnimating is a legacy transition query and will be removed, so also add
                     // a check for whether this is in a shell-transition when not using legacy.
@@ -8139,13 +8145,14 @@
             WindowContainer animatingContainer;
             animatingContainer = mRoot.getAnimatingContainer(TRANSITION | CHILDREN,
                     ANIMATION_TYPE_ALL);
-            if (mAnimator.isAnimationScheduled() || animatingContainer != null) {
+            if (mAnimator.isAnimationScheduled() || animatingContainer != null || animateStarting) {
                 Slog.w(TAG, "Timed out waiting for animations to complete,"
                         + " animatingContainer=" + animatingContainer
                         + " animationType=" + SurfaceAnimator.animationTypeToString(
                         animatingContainer != null
                                 ? animatingContainer.mSurfaceAnimator.getAnimationType()
-                                : SurfaceAnimator.ANIMATION_TYPE_NONE));
+                                : SurfaceAnimator.ANIMATION_TYPE_NONE)
+                        + " animateStarting=" + animateStarting);
             }
         }
     }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
index 71c05b5..ea46eab 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -32,6 +32,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyBoolean;
 import static org.mockito.Matchers.anyInt;
@@ -72,6 +73,7 @@
 import android.service.notification.NotificationListenerService;
 import android.service.notification.StatusBarNotification;
 import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Slog;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.IAccessibilityManager;
@@ -1182,6 +1184,7 @@
         when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
 
         mService.buzzBeepBlinkLocked(r);
+        verifyDelayedVibrate(mService.getVibratorHelper().createFallbackVibration(false));
 
         // quiet update should stop making noise
         mService.buzzBeepBlinkLocked(s);
@@ -1564,6 +1567,32 @@
     }
 
     @Test
+    public void testRingtoneInsistentBeep_canUpdate() throws Exception {
+        NotificationChannel ringtoneChannel =
+                new NotificationChannel("ringtone", "", IMPORTANCE_HIGH);
+        ringtoneChannel.setSound(Uri.fromParts("a", "b", "c"),
+                new AudioAttributes.Builder().setUsage(USAGE_NOTIFICATION_RINGTONE).build());
+        ringtoneChannel.enableVibration(true);
+        NotificationRecord ringtoneNotification = getCallRecord(1, ringtoneChannel, true);
+        mService.addNotification(ringtoneNotification);
+        assertFalse(mService.shouldMuteNotificationLocked(ringtoneNotification));
+        mService.buzzBeepBlinkLocked(ringtoneNotification);
+        verifyBeepLooped();
+        verifyDelayedVibrateLooped();
+        Mockito.reset(mVibrator);
+        Mockito.reset(mRingtonePlayer);
+
+        assertFalse(mService.shouldMuteNotificationLocked(ringtoneNotification));
+        mService.buzzBeepBlinkLocked(ringtoneNotification);
+
+        // beep wasn't reset
+        verifyNeverBeep();
+        verifyNeverVibrate();
+        verify(mRingtonePlayer, never()).stopAsync();
+        verify(mVibrator, never()).cancel();
+    }
+
+    @Test
     public void testCannotInterruptRingtoneInsistentBuzz() {
         NotificationChannel ringtoneChannel =
                 new NotificationChannel("ringtone", "", IMPORTANCE_HIGH);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 7bbf3e6..f660af0 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -516,7 +516,7 @@
 
         when(mAssistants.isAdjustmentAllowed(anyString())).thenReturn(true);
 
-        mWorkerHandler = mService.new WorkerHandler(mTestableLooper.getLooper());
+        mWorkerHandler = spy(mService.new WorkerHandler(mTestableLooper.getLooper()));
         mService.init(mWorkerHandler, mRankingHandler, mPackageManager, mPackageManagerClient,
                 mockLightsManager, mListeners, mAssistants, mConditionProviders, mCompanionMgr,
                 mSnoozeHelper, mUsageStats, mPolicyFile, mActivityManager, mGroupHelper, mAm, mAtm,
@@ -2703,6 +2703,42 @@
     }
 
     @Test
+    public void testCrossUserSnooze() {
+        NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 10);
+        mService.addNotification(r);
+        NotificationRecord r2 = generateNotificationRecord(mTestNotificationChannel, 0);
+        mService.addNotification(r2);
+
+        mListener = mock(ManagedServices.ManagedServiceInfo.class);
+        mListener.component = new ComponentName(PKG, PKG);
+        when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
+        when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
+
+        mService.snoozeNotificationInt(r.getKey(), 1000, null, mListener);
+
+        verify(mWorkerHandler, never()).post(
+                any(NotificationManagerService.SnoozeNotificationRunnable.class));
+    }
+
+    @Test
+    public void testSameUserSnooze() {
+        NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 10);
+        mService.addNotification(r);
+        NotificationRecord r2 = generateNotificationRecord(mTestNotificationChannel, 0);
+        mService.addNotification(r2);
+
+        mListener = mock(ManagedServices.ManagedServiceInfo.class);
+        mListener.component = new ComponentName(PKG, PKG);
+        when(mListener.enabledAndUserMatches(anyInt())).thenReturn(true);
+        when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
+
+        mService.snoozeNotificationInt(r2.getKey(), 1000, null, mListener);
+
+        verify(mWorkerHandler).post(
+                any(NotificationManagerService.SnoozeNotificationRunnable.class));
+    }
+
+    @Test
     public void testSnoozeRunnable_reSnoozeASingleSnoozedNotification() throws Exception {
         final NotificationRecord notification = generateNotificationRecord(
                 mTestNotificationChannel, 1, null, true);
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 759afd7..f2f1645 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -775,6 +775,21 @@
             "android.telecom.extra.REMOTE_PHONE_ACCOUNT_HANDLE";
 
     /**
+     * The Telecom call ID of the conference an existing connection should be added to.  This is
+     * required when {@link com.android.services.telephony.TelephonyConnectionService} adds a
+     * {@link Conference} to Telecom using the
+     * {@link ConnectionService#addExistingConnection(PhoneAccountHandle, Connection, Conference)}
+     * API.  That API specifies a parent conference associated with the new existing connection
+     * being added, and there is no equivalent as part of the {@link RemoteConnectionService} API.
+     * This extra key is used to stack the ID of the conference to which the existing connection
+     * will be added so that Telecom can link it up correctly when the {@link RemoteConference}
+     * is added to Telecom by the connection manager.
+     * @hide
+     */
+    public static final String EXTRA_ADD_TO_CONFERENCE_ID =
+            "android.telecom.extra.ADD_TO_CONFERENCE_ID";
+
+    /**
      * Extra key set from a {@link ConnectionService} when using the remote connection APIs
      * (e.g. {@link RemoteConnectionService#createRemoteConnection(PhoneAccountHandle,
      * ConnectionRequest, boolean)}) to create a remote connection.  Provides the receiving
diff --git a/telecomm/java/android/telecom/RemoteConnectionService.java b/telecomm/java/android/telecom/RemoteConnectionService.java
index bf6a6ef7..efe35d2 100644
--- a/telecomm/java/android/telecom/RemoteConnectionService.java
+++ b/telecomm/java/android/telecom/RemoteConnectionService.java
@@ -239,13 +239,9 @@
                     conference.addConnection(c);
                 }
             }
-            if (conference.getConnections().size() == 0) {
-                // A conference was created, but none of its connections are ones that have been
-                // created by, and therefore being tracked by, this remote connection service. It
-                // is of no interest to us.
-                Log.d(this, "addConferenceCall - skipping");
-                return;
-            }
+            // We used to skip adding empty conferences; however in the world of IMS conference
+            // calls we need to add them to the remote connection service because they will always
+            // start with no participants.
 
             conference.setState(parcel.getState());
             conference.setConnectionCapabilities(parcel.getConnectionCapabilities());
@@ -379,6 +375,8 @@
         @Override
         public void addExistingConnection(String callId, ParcelableConnection connection,
                 Session.Info sessionInfo) {
+            Log.i(RemoteConnectionService.this, "addExistingConnection: callId=%s, conn=%s", callId,
+                    connection);
             String callingPackage = mOurConnectionServiceImpl.getApplicationContext().
                     getOpPackageName();
             int callingTargetSdkVersion = mOurConnectionServiceImpl.getApplicationInfo()
@@ -390,6 +388,20 @@
             Bundle newExtras = new Bundle();
             newExtras.putParcelable(Connection.EXTRA_REMOTE_PHONE_ACCOUNT_HANDLE,
                     connection.getPhoneAccount());
+            if (connection.getParentCallId() != null) {
+                RemoteConference parentConf = mConferenceById.get(connection.getParentCallId());
+                // If there is a parent being set, we need to stash the conference ID here.
+                // Telephony can add an existing connection while specifying a parent conference.
+                // There is no equivalent version of that operation as part of the remote connection
+                // API, so we will stash the pre-defined parent's ID in the extras.  When the
+                // connectionmanager copies over the extras from the remote connection to the
+                // actual one, it'll get passed to Telecom so that it can make the association.
+                if (parentConf != null) {
+                    newExtras.putString(Connection.EXTRA_ADD_TO_CONFERENCE_ID, parentConf.getId());
+                    Log.i(this, "addExistingConnection: stash parent of %s as %s",
+                            connection.getParentCallId(), parentConf.getId());
+                }
+            }
             remoteConnection.putExtras(newExtras);
             mConnectionById.put(callId, remoteConnection);
             remoteConnection.registerCallback(new RemoteConnection.Callback() {