Merge "AmbientContextManager API changes to support quick-tap detection" into tm-qpr-dev
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index c10c380..41a784a 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -26,7 +26,7 @@
 
 hidden_api_txt_exclude_hook = ${REPO_ROOT}/frameworks/base/tools/hiddenapi/exclude.sh ${PREUPLOAD_COMMIT} ${REPO_ROOT}
 
-ktfmt_hook = ${REPO_ROOT}/external/ktfmt/ktfmt.py --check -i ${REPO_ROOT}/frameworks/base/ktfmt_includes.txt ${PREUPLOAD_FILES}
+ktfmt_hook = ${REPO_ROOT}/external/ktfmt/ktfmt.py --check -i ${REPO_ROOT}/frameworks/base/packages/SystemUI/ktfmt_includes.txt ${PREUPLOAD_FILES}
 
 ktlint_hook = ${REPO_ROOT}/prebuilts/ktlint/ktlint.py -f ${PREUPLOAD_FILES}
 
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index fbc2148..aad32b1 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1740,7 +1740,7 @@
     <!-- Generic error message shown when the fingerprint operation fails because too many attempts have been made. -->
     <string name="fingerprint_error_lockout">Too many attempts. Try again later.</string>
     <!-- Generic error message shown when the fingerprint operation fails because strong authentication is required -->
-    <string name="fingerprint_error_lockout_permanent">Too many attempts. Fingerprint sensor disabled.</string>
+    <string name="fingerprint_error_lockout_permanent">Too many attempts. Use screen lock instead.</string>
     <!-- Generic error message shown when the fingerprint hardware can't recognize the fingerprint -->
     <string name="fingerprint_error_unable_to_process">Try again.</string>
     <!-- Generic error message shown when the user has no enrolled fingerprints -->
diff --git a/ktfmt_includes.txt b/ktfmt_includes.txt
deleted file mode 100644
index c7062e0..0000000
--- a/ktfmt_includes.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-packages/SystemUI/compose/
-packages/SystemUI/screenshot/
-packages/SystemUI/src/com/android/systemui/people/data
-packages/SystemUI/src/com/android/systemui/people/ui
-packages/SystemUI/src/com/android/systemui/keyguard/data
-packages/SystemUI/src/com/android/systemui/keyguard/dagger
-packages/SystemUI/src/com/android/systemui/keyguard/domain
-packages/SystemUI/src/com/android/systemui/keyguard/shared
-packages/SystemUI/src/com/android/systemui/keyguard/ui
-packages/SystemUI/src/com/android/systemui/qs/footer
-packages/SystemUI/src/com/android/systemui/security
-packages/SystemUI/src/com/android/systemui/common/
-packages/SystemUI/tests/utils/src/com/android/systemui/qs/
-packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeSecurityController.kt
-packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeUserInfoController.kt
-packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/MockUserSwitcherControllerWrapper.kt
-packages/SystemUI/tests/src/com/android/systemui/qs/footer/
\ No newline at end of file
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
index 02af916..4102732 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -792,6 +792,9 @@
      * Checks if there is a rule to split the two activities. If there is one, puts them into split
      * and returns {@code true}. Otherwise, returns {@code false}.
      */
+    // Suppress GuardedBy warning because lint ask to mark this method as
+    // @GuardedBy(mPresenter.mController.mLock), which is mLock itself
+    @SuppressWarnings("GuardedBy")
     @GuardedBy("mLock")
     private boolean putActivitiesIntoSplitIfNecessary(@NonNull WindowContainerTransaction wct,
             @NonNull Activity primaryActivity, @NonNull Activity secondaryActivity) {
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
index 2b069d7..2ef8e4c 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
@@ -38,6 +38,7 @@
 import android.view.WindowMetrics;
 import android.window.WindowContainerTransaction;
 
+import androidx.annotation.GuardedBy;
 import androidx.annotation.IntDef;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
@@ -171,6 +172,7 @@
      *                          created and the activity will be re-parented to it.
      * @param rule The split rule to be applied to the container.
      */
+    @GuardedBy("mController.mLock")
     void createNewSplitContainer(@NonNull WindowContainerTransaction wct,
             @NonNull Activity primaryActivity, @NonNull Activity secondaryActivity,
             @NonNull SplitPairRule rule) {
@@ -187,8 +189,10 @@
         final TaskFragmentContainer curSecondaryContainer = mController.getContainerWithActivity(
                 secondaryActivity);
         TaskFragmentContainer containerToAvoid = primaryContainer;
-        if (rule.shouldClearTop() && curSecondaryContainer != null) {
-            // Do not reuse the current TaskFragment if the rule is to clear top.
+        if (curSecondaryContainer != null
+                && (rule.shouldClearTop() || primaryContainer.isAbove(curSecondaryContainer))) {
+            // Do not reuse the current TaskFragment if the rule is to clear top, or if it is below
+            // the primary TaskFragment.
             containerToAvoid = curSecondaryContainer;
         }
         final TaskFragmentContainer secondaryContainer = prepareContainerForActivity(wct,
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
index 77e26c0..45645b2 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
@@ -162,4 +162,8 @@
         }
         return null;
     }
+
+    int indexOf(@NonNull TaskFragmentContainer child) {
+        return mContainers.indexOf(child);
+    }
 }
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
index 11c0db3..344ffc7 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
@@ -501,6 +501,18 @@
         return new Size(maxMinWidth, maxMinHeight);
     }
 
+    /** Whether the current TaskFragment is above the {@code other} TaskFragment. */
+    boolean isAbove(@NonNull TaskFragmentContainer other) {
+        if (mTaskContainer != other.mTaskContainer) {
+            throw new IllegalArgumentException(
+                    "Trying to compare two TaskFragments in different Task.");
+        }
+        if (this == other) {
+            throw new IllegalArgumentException("Trying to compare a TaskFragment with itself.");
+        }
+        return mTaskContainer.indexOf(this) > mTaskContainer.indexOf(other);
+    }
+
     @Override
     public String toString() {
         return toString(true /* includeContainersToFinishOnExit */);
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java
index da724d9..25f0e25 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java
@@ -39,6 +39,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
@@ -247,6 +248,26 @@
         verify(mPresenter).expandTaskFragment(mTransaction, secondaryTf.getTaskFragmentToken());
     }
 
+    @Test
+    public void testCreateNewSplitContainer_secondaryAbovePrimary() {
+        final Activity secondaryActivity = createMockActivity();
+        final TaskFragmentContainer bottomTf = mController.newContainer(secondaryActivity, TASK_ID);
+        final TaskFragmentContainer primaryTf = mController.newContainer(mActivity, TASK_ID);
+        final SplitPairRule rule = new SplitPairRule.Builder(pair ->
+                pair.first == mActivity && pair.second == secondaryActivity, pair -> false,
+                metrics -> true)
+                .setShouldClearTop(false)
+                .build();
+
+        mPresenter.createNewSplitContainer(mTransaction, mActivity, secondaryActivity, rule);
+
+        assertEquals(primaryTf, mController.getContainerWithActivity(mActivity));
+        final TaskFragmentContainer secondaryTf = mController.getContainerWithActivity(
+                secondaryActivity);
+        assertNotEquals(bottomTf, secondaryTf);
+        assertTrue(secondaryTf.isAbove(primaryTf));
+    }
+
     private Activity createMockActivity() {
         final Activity activity = mock(Activity.class);
         final Configuration activityConfig = new Configuration();
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java
index 6cbecff..1bc81ee 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java
@@ -288,6 +288,18 @@
     }
 
     @Test
+    public void testIsAbove() {
+        final TaskContainer taskContainer = new TaskContainer(TASK_ID);
+        final TaskFragmentContainer container0 = new TaskFragmentContainer(null /* activity */,
+                mIntent, taskContainer, mController);
+        final TaskFragmentContainer container1 = new TaskFragmentContainer(null /* activity */,
+                mIntent, taskContainer, mController);
+
+        assertTrue(container1.isAbove(container0));
+        assertFalse(container0.isAbove(container1));
+    }
+
+    @Test
     public void testGetBottomMostActivity() {
         final TaskContainer taskContainer = new TaskContainer(TASK_ID);
         final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_letterboxed_app.xml b/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_letterboxed_app.xml
deleted file mode 100644
index 6fcd1de..0000000
--- a/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_letterboxed_app.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2022 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="@dimen/letterbox_education_dialog_icon_size"
-        android:height="@dimen/letterbox_education_dialog_icon_size"
-        android:viewportWidth="48"
-        android:viewportHeight="48">
-    <path
-        android:fillColor="@color/letterbox_education_accent_primary"
-        android:fillType="evenOdd"
-        android:pathData="M2 8C0.895431 8 0 8.89543 0 10V38C0 39.1046 0.895431 40 2 40H46C47.1046 40 48 39.1046 48 38V10C48 8.89543 47.1046 8 46 8H2ZM44 12H4V36H44V12Z" />
-    <path
-        android:fillColor="@color/letterbox_education_accent_primary"
-        android:pathData="M 17 14 L 31 14 Q 32 14 32 15 L 32 33 Q 32 34 31 34 L 17 34 Q 16 34 16 33 L 16 15 Q 16 14 17 14 Z" />
-</vector>
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_light_bulb.xml b/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_light_bulb.xml
new file mode 100644
index 0000000..ddfb5c2
--- /dev/null
+++ b/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_light_bulb.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="@dimen/letterbox_education_dialog_title_icon_width"
+        android:height="@dimen/letterbox_education_dialog_title_icon_height"
+        android:viewportWidth="45"
+        android:viewportHeight="44">
+
+    <path
+        android:fillColor="@color/letterbox_education_accent_primary"
+        android:pathData="M11 40H19C19 42.2 17.2 44 15 44C12.8 44 11 42.2 11 40ZM7 38L23 38V34L7 34L7 38ZM30 19C30 26.64 24.68 30.72 22.46 32L7.54 32C5.32 30.72 0 26.64 0 19C0 10.72 6.72 4 15 4C23.28 4 30 10.72 30 19ZM26 19C26 12.94 21.06 8 15 8C8.94 8 4 12.94 4 19C4 23.94 6.98 26.78 8.7 28L21.3 28C23.02 26.78 26 23.94 26 19ZM39.74 14.74L37 16L39.74 17.26L41 20L42.26 17.26L45 16L42.26 14.74L41 12L39.74 14.74ZM35 12L36.88 7.88L41 6L36.88 4.12L35 0L33.12 4.12L29 6L33.12 7.88L35 12Z" />
+</vector>
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_reposition.xml b/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_reposition.xml
index cbfcfd0..22a8f39 100644
--- a/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_reposition.xml
+++ b/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_reposition.xml
@@ -15,18 +15,16 @@
   ~ limitations under the License.
   -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="@dimen/letterbox_education_dialog_icon_size"
-        android:height="@dimen/letterbox_education_dialog_icon_size"
-        android:viewportWidth="48"
-        android:viewportHeight="48">
+        android:width="@dimen/letterbox_education_dialog_icon_width"
+        android:height="@dimen/letterbox_education_dialog_icon_height"
+        android:viewportWidth="40"
+        android:viewportHeight="32">
+
     <path
         android:fillColor="@color/letterbox_education_text_secondary"
         android:fillType="evenOdd"
-        android:pathData="M2 8C0.895431 8 0 8.89543 0 10V38C0 39.1046 0.895431 40 2 40H46C47.1046 40 48 39.1046 48 38V10C48 8.89543 47.1046 8 46 8H2ZM44 12H4V36H44V12Z" />
+        android:pathData="M4 0C1.79086 0 0 1.79086 0 4V28C0 30.2091 1.79086 32 4 32H36C38.2091 32 40 30.2091 40 28V4C40 1.79086 38.2091 0 36 0H4ZM36 4H4V28H36V4Z" />
     <path
         android:fillColor="@color/letterbox_education_text_secondary"
-        android:pathData="M 14 22 H 30 V 26 H 14 V 22 Z" />
-    <path
-        android:fillColor="@color/letterbox_education_text_secondary"
-        android:pathData="M26 16L34 24L26 32V16Z" />
+        android:pathData="M19.98 8L17.16 10.82L20.32 14L12 14V18H20.32L17.14 21.18L19.98 24L28 16.02L19.98 8Z" />
 </vector>
diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_screen_rotation.xml b/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_screen_rotation.xml
deleted file mode 100644
index 469eb1e..0000000
--- a/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_screen_rotation.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2022 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="@dimen/letterbox_education_dialog_icon_size"
-        android:height="@dimen/letterbox_education_dialog_icon_size"
-        android:viewportWidth="48"
-        android:viewportHeight="48">
-    <path
-        android:fillColor="@color/letterbox_education_text_secondary"
-        android:fillType="evenOdd"
-        android:pathData="M22.56 2H26C37.02 2 46 10.98 46 22H42C42 14.44 36.74 8.1 29.7 6.42L31.74 10L28.26 12L22.56 2ZM22 46H25.44L19.74 36L16.26 38L18.3 41.58C11.26 39.9 6 33.56 6 26H2C2 37.02 10.98 46 22 46ZM20.46 12L36 27.52L27.54 36L12 20.48L20.46 12ZM17.64 9.18C18.42 8.4 19.44 8 20.46 8C21.5 8 22.52 8.4 23.3 9.16L38.84 24.7C40.4 26.26 40.4 28.78 38.84 30.34L30.36 38.82C29.58 39.6 28.56 40 27.54 40C26.52 40 25.5 39.6 24.72 38.82L9.18 23.28C7.62 21.72 7.62 19.2 9.18 17.64L17.64 9.18Z" />
-</vector>
diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_split_screen.xml b/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_split_screen.xml
index dcb8aed..15e65f7 100644
--- a/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_split_screen.xml
+++ b/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_split_screen.xml
@@ -15,18 +15,12 @@
   ~ limitations under the License.
   -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="@dimen/letterbox_education_dialog_icon_size"
-        android:height="@dimen/letterbox_education_dialog_icon_size"
-        android:viewportWidth="48"
-        android:viewportHeight="48">
+        android:width="@dimen/letterbox_education_dialog_icon_width"
+        android:height="@dimen/letterbox_education_dialog_icon_height"
+        android:viewportWidth="40"
+        android:viewportHeight="32">
+
     <path
         android:fillColor="@color/letterbox_education_text_secondary"
-        android:fillType="evenOdd"
-        android:pathData="M2 8C0.895431 8 0 8.89543 0 10V38C0 39.1046 0.895431 40 2 40H46C47.1046 40 48 39.1046 48 38V10C48 8.89543 47.1046 8 46 8H2ZM44 12H4V36H44V12Z" />
-    <path
-        android:fillColor="@color/letterbox_education_text_secondary"
-        android:pathData="M6 16C6 14.8954 6.89543 14 8 14H21C22.1046 14 23 14.8954 23 16V32C23 33.1046 22.1046 34 21 34H8C6.89543 34 6 33.1046 6 32V16Z" />
-    <path
-        android:fillColor="@color/letterbox_education_text_secondary"
-        android:pathData="M25 16C25 14.8954 25.8954 14 27 14H40C41.1046 14 42 14.8954 42 16V32C42 33.1046 41.1046 34 40 34H27C25.8954 34 25 33.1046 25 32V16Z" />
+        android:pathData="M40 28L40 4C40 1.8 38.2 -7.86805e-08 36 -1.74846e-07L26 -6.11959e-07C23.8 -7.08124e-07 22 1.8 22 4L22 28C22 30.2 23.8 32 26 32L36 32C38.2 32 40 30.2 40 28ZM14 28L4 28L4 4L14 4L14 28ZM18 28L18 4C18 1.8 16.2 -1.04033e-06 14 -1.1365e-06L4 -1.57361e-06C1.8 -1.66978e-06 -7.86805e-08 1.8 -1.74846e-07 4L-1.22392e-06 28C-1.32008e-06 30.2 1.8 32 4 32L14 32C16.2 32 18 30.2 18 28Z" />
 </vector>
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_action_layout.xml b/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_action_layout.xml
index cd1d99a..c65f24d 100644
--- a/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_action_layout.xml
+++ b/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_action_layout.xml
@@ -26,7 +26,7 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_gravity="center"
-        android:layout_marginBottom="12dp"/>
+        android:layout_marginBottom="20dp"/>
 
     <TextView
         android:id="@+id/letterbox_education_dialog_action_text"
diff --git a/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml b/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml
index 9592376..3a44eb9 100644
--- a/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml
+++ b/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml
@@ -50,13 +50,16 @@
                 android:layout_height="wrap_content"
                 android:gravity="center_horizontal"
                 android:orientation="vertical"
-                android:padding="24dp">
+                android:paddingTop="32dp"
+                android:paddingBottom="32dp"
+                android:paddingLeft="56dp"
+                android:paddingRight="56dp">
 
                 <ImageView
-                    android:layout_width="@dimen/letterbox_education_dialog_icon_size"
-                    android:layout_height="@dimen/letterbox_education_dialog_icon_size"
-                    android:layout_marginBottom="12dp"
-                    android:src="@drawable/letterbox_education_ic_letterboxed_app"/>
+                    android:layout_width="@dimen/letterbox_education_dialog_title_icon_width"
+                    android:layout_height="@dimen/letterbox_education_dialog_title_icon_height"
+                    android:layout_marginBottom="17dp"
+                    android:src="@drawable/letterbox_education_ic_light_bulb"/>
 
                 <TextView
                     android:id="@+id/letterbox_education_dialog_title"
@@ -68,16 +71,6 @@
                     android:textColor="@color/compat_controls_text"
                     android:textSize="24sp"/>
 
-                <TextView
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:layout_marginTop="8dp"
-                    android:lineSpacingExtra="4sp"
-                    android:text="@string/letterbox_education_dialog_subtext"
-                    android:textAlignment="center"
-                    android:textColor="@color/letterbox_education_text_secondary"
-                    android:textSize="14sp"/>
-
                 <LinearLayout
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
@@ -88,16 +81,16 @@
                     <com.android.wm.shell.compatui.letterboxedu.LetterboxEduDialogActionLayout
                         android:layout_width="wrap_content"
                         android:layout_height="wrap_content"
-                        app:icon="@drawable/letterbox_education_ic_screen_rotation"
-                        app:text="@string/letterbox_education_screen_rotation_text"/>
+                        app:icon="@drawable/letterbox_education_ic_reposition"
+                        app:text="@string/letterbox_education_reposition_text"/>
 
                     <com.android.wm.shell.compatui.letterboxedu.LetterboxEduDialogActionLayout
                         android:layout_width="wrap_content"
                         android:layout_height="wrap_content"
                         android:layout_marginStart=
                             "@dimen/letterbox_education_dialog_space_between_actions"
-                        app:icon="@drawable/letterbox_education_ic_reposition"
-                        app:text="@string/letterbox_education_reposition_text"/>
+                        app:icon="@drawable/letterbox_education_ic_split_screen"
+                        app:text="@string/letterbox_education_split_screen_text"/>
 
                 </LinearLayout>
 
@@ -105,7 +98,7 @@
                     android:id="@+id/letterbox_education_dialog_dismiss_button"
                     android:layout_width="match_parent"
                     android:layout_height="56dp"
-                    android:layout_marginTop="48dp"
+                    android:layout_marginTop="40dp"
                     android:background=
                         "@drawable/letterbox_education_dismiss_button_background_ripple"
                     android:text="@string/letterbox_education_got_it"
diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml
index 1dac9ca..d2dd8d6b 100644
--- a/libs/WindowManager/Shell/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/res/values/dimen.xml
@@ -246,8 +246,17 @@
     <!-- The corner radius of the letterbox education dialog. -->
     <dimen name="letterbox_education_dialog_corner_radius">28dp</dimen>
 
-    <!-- The size of an icon in the letterbox education dialog. -->
-    <dimen name="letterbox_education_dialog_icon_size">48dp</dimen>
+    <!-- The width of the top icon in the letterbox education dialog. -->
+    <dimen name="letterbox_education_dialog_title_icon_width">45dp</dimen>
+
+    <!-- The height of the top icon in the letterbox education dialog. -->
+    <dimen name="letterbox_education_dialog_title_icon_height">44dp</dimen>
+
+    <!-- The width of an icon in the letterbox education dialog. -->
+    <dimen name="letterbox_education_dialog_icon_width">40dp</dimen>
+
+    <!-- The height of an icon in the letterbox education dialog. -->
+    <dimen name="letterbox_education_dialog_icon_height">32dp</dimen>
 
     <!-- The fixed width of the dialog if there is enough space in the parent. -->
     <dimen name="letterbox_education_dialog_width">472dp</dimen>
diff --git a/libs/WindowManager/Shell/res/values/strings.xml b/libs/WindowManager/Shell/res/values/strings.xml
index 96778a9..1d1162d 100644
--- a/libs/WindowManager/Shell/res/values/strings.xml
+++ b/libs/WindowManager/Shell/res/values/strings.xml
@@ -172,16 +172,13 @@
     <string name="camera_compat_dismiss_button_description">No camera issues? Tap to dismiss.</string>
 
     <!-- The title of the letterbox education dialog. [CHAR LIMIT=NONE] -->
-    <string name="letterbox_education_dialog_title">Some apps work best in portrait</string>
+    <string name="letterbox_education_dialog_title">See and do more</string>
 
-    <!-- The subtext of the letterbox education dialog. [CHAR LIMIT=NONE] -->
-    <string name="letterbox_education_dialog_subtext">Try one of these options to make the most of your space</string>
-
-    <!-- Description of the rotate screen action. [CHAR LIMIT=NONE] -->
-    <string name="letterbox_education_screen_rotation_text">Rotate your device to go full screen</string>
+    <!-- Description of the split screen action. [CHAR LIMIT=NONE] -->
+    <string name="letterbox_education_split_screen_text">Drag in another app for split-screen</string>
 
     <!-- Description of the reposition app action. [CHAR LIMIT=NONE] -->
-    <string name="letterbox_education_reposition_text">Double-tap next to an app to reposition it</string>
+    <string name="letterbox_education_reposition_text">Double-tap outside an app to reposition it</string>
 
     <!-- Button text for dismissing the letterbox education dialog. [CHAR LIMIT=20] -->
     <string name="letterbox_education_got_it">Got it</string>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index b7959eb..4c85d20 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -80,7 +80,10 @@
     public static final int PARALLAX_DISMISSING = 1;
     public static final int PARALLAX_ALIGN_CENTER = 2;
 
-    private static final int FLING_ANIMATION_DURATION = 250;
+    private static final int FLING_RESIZE_DURATION = 250;
+    private static final int FLING_SWITCH_DURATION = 350;
+    private static final int FLING_ENTER_DURATION = 350;
+    private static final int FLING_EXIT_DURATION = 350;
 
     private final int mDividerWindowWidth;
     private final int mDividerInsets;
@@ -93,6 +96,9 @@
     private final Rect mBounds1 = new Rect();
     // Bounds2 final position should be always at bottom or right
     private final Rect mBounds2 = new Rect();
+    // The temp bounds outside of display bounds for side stage when split screen inactive to avoid
+    // flicker next time active split screen.
+    private final Rect mInvisibleBounds = new Rect();
     private final Rect mWinBounds1 = new Rect();
     private final Rect mWinBounds2 = new Rect();
     private final SplitLayoutHandler mSplitLayoutHandler;
@@ -141,6 +147,8 @@
         resetDividerPosition();
 
         mDimNonImeSide = resources.getBoolean(R.bool.config_dimNonImeAttachedSide);
+
+        updateInvisibleRect();
     }
 
     private int getDividerInsets(Resources resources, Display display) {
@@ -239,6 +247,12 @@
         rect.offset(-mRootBounds.left, -mRootBounds.top);
     }
 
+    /** Gets bounds size equal to root bounds but outside of screen, used for position side stage
+     * when split inactive to avoid flicker when next time active. */
+    public void getInvisibleBounds(Rect rect) {
+        rect.set(mInvisibleBounds);
+    }
+
     /** Returns leash of the current divider bar. */
     @Nullable
     public SurfaceControl getDividerLeash() {
@@ -258,6 +272,14 @@
                 : (float) ((mBounds1.bottom + mBounds2.top) / 2f) / mBounds2.bottom));
     }
 
+    private void updateInvisibleRect() {
+        mInvisibleBounds.set(mRootBounds.left, mRootBounds.top,
+                isLandscape() ? mRootBounds.right / 2 : mRootBounds.right,
+                isLandscape() ? mRootBounds.bottom : mRootBounds.bottom / 2);
+        mInvisibleBounds.offset(isLandscape() ? mRootBounds.right : 0,
+                isLandscape() ? 0 : mRootBounds.bottom);
+    }
+
     /** Applies new configuration, returns {@code false} if there's no effect to the layout. */
     public boolean updateConfiguration(Configuration configuration) {
         // Update the split bounds when necessary. Besides root bounds changed, split bounds need to
@@ -283,6 +305,7 @@
         mRotation = rotation;
         mDividerSnapAlgorithm = getSnapAlgorithm(mContext, mRootBounds, null);
         initDividerPosition(mTempRect);
+        updateInvisibleRect();
 
         return true;
     }
@@ -405,6 +428,13 @@
         mFreezeDividerWindow = freezeDividerWindow;
     }
 
+    /** Update current layout as divider put on start or end position. */
+    public void setDividerAtBorder(boolean start) {
+        final int pos = start ? mDividerSnapAlgorithm.getDismissStartTarget().position
+                : mDividerSnapAlgorithm.getDismissEndTarget().position;
+        setDividePosition(pos, false /* applyLayoutChange */);
+    }
+
     /**
      * Updates bounds with the passing position. Usually used to update recording bounds while
      * performing animation or dragging divider bar to resize the splits.
@@ -449,17 +479,17 @@
     public void snapToTarget(int currentPosition, DividerSnapAlgorithm.SnapTarget snapTarget) {
         switch (snapTarget.flag) {
             case FLAG_DISMISS_START:
-                flingDividePosition(currentPosition, snapTarget.position,
+                flingDividePosition(currentPosition, snapTarget.position, FLING_RESIZE_DURATION,
                         () -> mSplitLayoutHandler.onSnappedToDismiss(false /* bottomOrRight */,
                                 EXIT_REASON_DRAG_DIVIDER));
                 break;
             case FLAG_DISMISS_END:
-                flingDividePosition(currentPosition, snapTarget.position,
+                flingDividePosition(currentPosition, snapTarget.position, FLING_RESIZE_DURATION,
                         () -> mSplitLayoutHandler.onSnappedToDismiss(true /* bottomOrRight */,
                                 EXIT_REASON_DRAG_DIVIDER));
                 break;
             default:
-                flingDividePosition(currentPosition, snapTarget.position,
+                flingDividePosition(currentPosition, snapTarget.position, FLING_RESIZE_DURATION,
                         () -> setDividePosition(snapTarget.position, true /* applyLayoutChange */));
                 break;
         }
@@ -514,12 +544,20 @@
     public void flingDividerToDismiss(boolean toEnd, int reason) {
         final int target = toEnd ? mDividerSnapAlgorithm.getDismissEndTarget().position
                 : mDividerSnapAlgorithm.getDismissStartTarget().position;
-        flingDividePosition(getDividePosition(), target,
+        flingDividePosition(getDividePosition(), target, FLING_EXIT_DURATION,
                 () -> mSplitLayoutHandler.onSnappedToDismiss(toEnd, reason));
     }
 
+    /** Fling divider from current position to center position. */
+    public void flingDividerToCenter() {
+        final int pos = mDividerSnapAlgorithm.getMiddleTarget().position;
+        flingDividePosition(getDividePosition(), pos, FLING_ENTER_DURATION,
+                () -> setDividePosition(pos, true /* applyLayoutChange */));
+    }
+
     @VisibleForTesting
-    void flingDividePosition(int from, int to, @Nullable Runnable flingFinishedCallback) {
+    void flingDividePosition(int from, int to, int duration,
+            @Nullable Runnable flingFinishedCallback) {
         if (from == to) {
             // No animation run, still callback to stop resizing.
             mSplitLayoutHandler.onLayoutSizeChanged(this);
@@ -529,7 +567,7 @@
         }
         ValueAnimator animator = ValueAnimator
                 .ofInt(from, to)
-                .setDuration(FLING_ANIMATION_DURATION);
+                .setDuration(duration);
         animator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
         animator.addUpdateListener(
                 animation -> updateDivideBounds((int) animation.getAnimatedValue()));
@@ -586,7 +624,7 @@
 
         AnimatorSet set = new AnimatorSet();
         set.playTogether(animator1, animator2, animator3);
-        set.setDuration(FLING_ANIMATION_DURATION);
+        set.setDuration(FLING_SWITCH_DURATION);
         set.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationEnd(Animator animation) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 7e83d2f..c08aa5a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -25,6 +25,7 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
+import static android.content.res.Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.RemoteAnimationTarget.MODE_OPENING;
 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
@@ -488,13 +489,6 @@
         final WindowContainerTransaction wct = new WindowContainerTransaction();
         options = resolveStartStage(STAGE_TYPE_UNDEFINED, position, options, wct);
 
-        // If split still not active, apply windows bounds first to avoid surface reset to
-        // wrong pos by SurfaceAnimator from wms.
-        // TODO(b/223325631): check  is it still necessary after improve enter transition done.
-        if (!mMainStage.isActive()) {
-            updateWindowBounds(mSplitLayout, wct);
-        }
-
         wct.sendPendingIntent(intent, fillInIntent, options);
         mSyncQueue.queue(transition, WindowManager.TRANSIT_OPEN, wct);
     }
@@ -519,6 +513,7 @@
         mSplitLayout.setDivideRatio(splitRatio);
         updateWindowBounds(mSplitLayout, wct);
         wct.reorder(mRootTaskInfo.token, true);
+        wct.setForceTranslucent(mRootTaskInfo.token, false);
 
         // Make sure the launch options will put tasks in the corresponding split roots
         addActivityOptions(mainOptions, mMainStage);
@@ -628,6 +623,7 @@
         }
         updateWindowBounds(mSplitLayout, wct);
         wct.reorder(mRootTaskInfo.token, true);
+        wct.setForceTranslucent(mRootTaskInfo.token, false);
 
         // Make sure the launch options will put tasks in the corresponding split roots
         addActivityOptions(mainOptions, mMainStage);
@@ -640,8 +636,8 @@
         } else {
             wct.startTask(sideTaskId, sideOptions);
         }
-        // Using legacy transitions, so we can't use blast sync since it conflicts.
-        mTaskOrganizer.applyTransaction(wct);
+
+        mSyncQueue.queue(wct);
         mSyncQueue.runInSync(t -> {
             setDividerVisibility(true, t);
             updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */);
@@ -893,10 +889,13 @@
         mShouldUpdateRecents = false;
         mIsDividerRemoteAnimating = false;
 
+        mSplitLayout.getInvisibleBounds(mTempRect1);
         if (childrenToTop == null) {
             mSideStage.removeAllTasks(wct, false /* toTop */);
             mMainStage.deactivate(wct, false /* toTop */);
             wct.reorder(mRootTaskInfo.token, false /* onTop */);
+            wct.setForceTranslucent(mRootTaskInfo.token, true);
+            wct.setBounds(mSideStage.mRootTaskInfo.token, mTempRect1);
             onTransitionAnimationComplete();
         } else {
             // Expand to top side split as full screen for fading out decor animation and dismiss
@@ -907,27 +906,32 @@
                     ? mSideStage : mMainStage;
             tempFullStage.resetBounds(wct);
             wct.setSmallestScreenWidthDp(tempFullStage.mRootTaskInfo.token,
-                    mRootTaskInfo.configuration.smallestScreenWidthDp);
+                    SMALLEST_SCREEN_WIDTH_DP_UNDEFINED);
             dismissStage.dismiss(wct, false /* toTop */);
         }
         mSyncQueue.queue(wct);
         mSyncQueue.runInSync(t -> {
             t.setWindowCrop(mMainStage.mRootLeash, null)
                     .setWindowCrop(mSideStage.mRootLeash, null);
-            t.setPosition(mMainStage.mRootLeash, 0, 0)
-                    .setPosition(mSideStage.mRootLeash, 0, 0);
             t.hide(mMainStage.mDimLayer).hide(mSideStage.mDimLayer);
             setDividerVisibility(false, t);
 
-            // In this case, exit still under progress, fade out the split decor after first WCT
-            // done and do remaining WCT after animation finished.
-            if (childrenToTop != null) {
+            if (childrenToTop == null) {
+                t.setPosition(mSideStage.mRootLeash, mTempRect1.left, mTempRect1.right);
+            } else {
+                // In this case, exit still under progress, fade out the split decor after first WCT
+                // done and do remaining WCT after animation finished.
                 childrenToTop.fadeOutDecor(() -> {
                     WindowContainerTransaction finishedWCT = new WindowContainerTransaction();
                     mIsExiting = false;
                     childrenToTop.dismiss(finishedWCT, true /* toTop */);
                     finishedWCT.reorder(mRootTaskInfo.token, false /* toTop */);
-                    mTaskOrganizer.applyTransaction(finishedWCT);
+                    finishedWCT.setForceTranslucent(mRootTaskInfo.token, true);
+                    finishedWCT.setBounds(mSideStage.mRootTaskInfo.token, mTempRect1);
+                    mSyncQueue.queue(finishedWCT);
+                    mSyncQueue.runInSync(at -> {
+                        at.setPosition(mSideStage.mRootLeash, mTempRect1.left, mTempRect1.right);
+                    });
                     onTransitionAnimationComplete();
                 });
             }
@@ -996,6 +1000,7 @@
         mMainStage.activate(wct, true /* includingTopTask */);
         updateWindowBounds(mSplitLayout, wct);
         wct.reorder(mRootTaskInfo.token, true);
+        wct.setForceTranslucent(mRootTaskInfo.token, false);
     }
 
     void finishEnterSplitScreen(SurfaceControl.Transaction t) {
@@ -1221,7 +1226,13 @@
         // Make the stages adjacent to each other so they occlude what's behind them.
         wct.setAdjacentRoots(mMainStage.mRootTaskInfo.token, mSideStage.mRootTaskInfo.token);
         wct.setLaunchAdjacentFlagRoot(mSideStage.mRootTaskInfo.token);
-        mTaskOrganizer.applyTransaction(wct);
+        wct.setForceTranslucent(mRootTaskInfo.token, true);
+        mSplitLayout.getInvisibleBounds(mTempRect1);
+        wct.setBounds(mSideStage.mRootTaskInfo.token, mTempRect1);
+        mSyncQueue.queue(wct);
+        mSyncQueue.runInSync(t -> {
+            t.setPosition(mSideStage.mRootLeash, mTempRect1.left, mTempRect1.top);
+        });
     }
 
     private void onRootTaskVanished() {
@@ -1377,10 +1388,15 @@
             // TODO (b/238697912) : Add the validation to prevent entering non-recovered status
             final WindowContainerTransaction wct = new WindowContainerTransaction();
             mSplitLayout.init();
-            prepareEnterSplitScreen(wct);
+            mSplitLayout.setDividerAtBorder(mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT);
+            mMainStage.activate(wct, true /* includingTopTask */);
+            updateWindowBounds(mSplitLayout, wct);
+            wct.reorder(mRootTaskInfo.token, true);
+            wct.setForceTranslucent(mRootTaskInfo.token, false);
             mSyncQueue.queue(wct);
-            mSyncQueue.runInSync(t ->
-                    updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */));
+            mSyncQueue.runInSync(t -> {
+                mSplitLayout.flingDividerToCenter();
+            });
         }
         if (mMainStageListener.mHasChildren && mSideStageListener.mHasChildren) {
             mShouldUpdateRecents = true;
@@ -1822,6 +1838,7 @@
             // properly for the animation itself.
             mSplitLayout.release();
             mSplitLayout.resetDividerPosition();
+            mSideStagePosition = SPLIT_POSITION_BOTTOM_OR_RIGHT;
             mTopStageAfterFoldDismiss = STAGE_TYPE_UNDEFINED;
         }
     }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
index 95725bb..695550d 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
@@ -159,7 +159,8 @@
     }
 
     private void waitDividerFlingFinished() {
-        verify(mSplitLayout).flingDividePosition(anyInt(), anyInt(), mRunnableCaptor.capture());
+        verify(mSplitLayout).flingDividePosition(anyInt(), anyInt(), anyInt(),
+                mRunnableCaptor.capture());
         mRunnableCaptor.getValue().run();
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
index 62c83cf..51812f0 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
@@ -367,8 +367,14 @@
             if (bondState == BluetoothDevice.BOND_NONE) {
                 // Check if we need to remove other Coordinated set member devices / Hearing Aid
                 // devices
+                if (DEBUG) {
+                    Log.d(TAG, "BondStateChangedHandler: cachedDevice.getGroupId() = "
+                            + cachedDevice.getGroupId() + ", cachedDevice.getHiSyncId()= "
+                            + cachedDevice.getHiSyncId());
+                }
                 if (cachedDevice.getGroupId() != BluetoothCsipSetCoordinator.GROUP_ID_INVALID
                         || cachedDevice.getHiSyncId() != BluetoothHearingAid.HI_SYNC_ID_INVALID) {
+                    Log.d(TAG, "BondStateChangedHandler: Start onDeviceUnpaired");
                     mDeviceManager.onDeviceUnpaired(cachedDevice);
                 }
                 int reason = intent.getIntExtra(BluetoothDevice.EXTRA_UNBOND_REASON,
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 32d5b78..3ca94db 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -1431,11 +1431,10 @@
      * first connected device in the coordinated set, and then switch the content of the main
      * device and member devices.
      *
-     * @param prevMainDevice the previous Main device, it will be added into the member device set.
-     * @param newMainDevice the new Main device, it will be removed from the member device set.
+     * @param newMainDevice the new Main device which is from the previous main device's member
+     *                      list.
      */
-    public void switchMemberDeviceContent(CachedBluetoothDevice prevMainDevice,
-            CachedBluetoothDevice newMainDevice) {
+    public void switchMemberDeviceContent(CachedBluetoothDevice newMainDevice) {
         // Backup from main device
         final BluetoothDevice tmpDevice = mDevice;
         final short tmpRssi = mRssi;
@@ -1444,8 +1443,7 @@
         mDevice = newMainDevice.mDevice;
         mRssi = newMainDevice.mRssi;
         mJustDiscovered = newMainDevice.mJustDiscovered;
-        addMemberDevice(prevMainDevice);
-        mMemberDevices.remove(newMainDevice);
+
         // Set sub device from backup
         newMainDevice.mDevice = tmpDevice;
         newMainDevice.mRssi = tmpRssi;
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
index cd3242a..26a2080 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
@@ -17,6 +17,7 @@
 package com.android.settingslib.bluetooth;
 
 import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothCsipSetCoordinator;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothProfile;
 import android.content.Context;
@@ -317,12 +318,14 @@
     }
 
     public synchronized void onDeviceUnpaired(CachedBluetoothDevice device) {
+        device.setGroupId(BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
         CachedBluetoothDevice mainDevice = mCsipDeviceManager.findMainDevice(device);
         final Set<CachedBluetoothDevice> memberDevices = device.getMemberDevice();
         if (!memberDevices.isEmpty()) {
             // Main device is unpaired, to unpair the member device
             for (CachedBluetoothDevice memberDevice : memberDevices) {
                 memberDevice.unpair();
+                memberDevice.setGroupId(BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
                 device.removeMemberDevice(memberDevice);
             }
         } else if (mainDevice != null) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java
index fc70ba4..9b38238 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java
@@ -231,7 +231,7 @@
                         // When both LE Audio devices are disconnected, receiving member device
                         // connection. To switch content and dispatch to notify UI change
                         mBtManager.getEventManager().dispatchDeviceRemoved(mainDevice);
-                        mainDevice.switchMemberDeviceContent(mainDevice, cachedDevice);
+                        mainDevice.switchMemberDeviceContent(cachedDevice);
                         mainDevice.refresh();
                         // It is necessary to do remove and add for updating the mapping on
                         // preference and device
@@ -255,10 +255,11 @@
 
                 for (CachedBluetoothDevice device: memberSet) {
                     if (device.isConnected()) {
+                        log("set device: " + device + " as the main device");
                         // Main device is disconnected and sub device is connected
                         // To copy data from sub device to main device
                         mBtManager.getEventManager().dispatchDeviceRemoved(cachedDevice);
-                        cachedDevice.switchMemberDeviceContent(device, cachedDevice);
+                        cachedDevice.switchMemberDeviceContent(device);
                         cachedDevice.refresh();
                         // It is necessary to do remove and add for updating the mapping on
                         // preference and device
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
index bef1d9c..62552f91 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
@@ -25,6 +25,7 @@
 import static org.mockito.Mockito.when;
 
 import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothCsipSetCoordinator;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothUuid;
 import android.content.Context;
@@ -518,7 +519,8 @@
      */
     @Test
     public void onDeviceUnpaired_unpairCsipMainDevice() {
-        when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+        when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_NONE);
+        when(mDevice2.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
         CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
         CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
         cachedDevice1.setGroupId(1);
@@ -527,7 +529,12 @@
 
         // Call onDeviceUnpaired for the one in mCachedDevices.
         mCachedDeviceManager.onDeviceUnpaired(cachedDevice1);
+
         verify(mDevice2).removeBond();
+        assertThat(cachedDevice1.getGroupId()).isEqualTo(
+                BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
+        assertThat(cachedDevice2.getGroupId()).isEqualTo(
+                BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
     }
 
     /**
@@ -536,6 +543,7 @@
     @Test
     public void onDeviceUnpaired_unpairCsipSubDevice() {
         when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+        when(mDevice2.getBondState()).thenReturn(BluetoothDevice.BOND_NONE);
         CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
         CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
         cachedDevice1.setGroupId(1);
@@ -544,7 +552,10 @@
 
         // Call onDeviceUnpaired for the one in mCachedDevices.
         mCachedDeviceManager.onDeviceUnpaired(cachedDevice2);
+
         verify(mDevice1).removeBond();
+        assertThat(cachedDevice2.getGroupId()).isEqualTo(
+                BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
     }
 
     /**
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
index 76c066c..79e9938 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
@@ -1050,4 +1050,23 @@
 
         assertThat(mCachedDevice.mDrawableCache.size()).isEqualTo(0);
     }
+
+    @Test
+    public void switchMemberDeviceContent_switchMainDevice_switchesSuccessful() {
+        mCachedDevice.mRssi = RSSI_1;
+        mCachedDevice.mJustDiscovered = JUSTDISCOVERED_1;
+        mSubCachedDevice.mRssi = RSSI_2;
+        mSubCachedDevice.mJustDiscovered = JUSTDISCOVERED_2;
+        mCachedDevice.addMemberDevice(mSubCachedDevice);
+
+        mCachedDevice.switchMemberDeviceContent(mSubCachedDevice);
+
+        assertThat(mCachedDevice.mRssi).isEqualTo(RSSI_2);
+        assertThat(mCachedDevice.mJustDiscovered).isEqualTo(JUSTDISCOVERED_2);
+        assertThat(mCachedDevice.mDevice).isEqualTo(mSubDevice);
+        assertThat(mSubCachedDevice.mRssi).isEqualTo(RSSI_1);
+        assertThat(mSubCachedDevice.mJustDiscovered).isEqualTo(JUSTDISCOVERED_1);
+        assertThat(mSubCachedDevice.mDevice).isEqualTo(mDevice);
+        assertThat(mCachedDevice.getMemberDevice().contains(mSubCachedDevice)).isTrue();
+    }
 }
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index abcd65b..7649de6 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -94,6 +94,7 @@
     <uses-permission android:name="android.permission.VIBRATE" />
     <uses-permission android:name="android.permission.MANAGE_SENSOR_PRIVACY" />
     <uses-permission android:name="android.permission.OBSERVE_SENSOR_PRIVACY" />
+    <uses-permission android:name="android.permission.ACCESS_AMBIENT_CONTEXT_EVENT" />
 
     <!-- ActivityManager -->
     <uses-permission android:name="android.permission.REAL_GET_TASKS" />
diff --git a/packages/SystemUI/ktfmt_includes.txt b/packages/SystemUI/ktfmt_includes.txt
new file mode 100644
index 0000000..3ca8dfe
--- /dev/null
+++ b/packages/SystemUI/ktfmt_includes.txt
@@ -0,0 +1,870 @@
++packages/SystemUI
+-packages/SystemUI/animation/src/com/android/systemui/animation/FontInterpolator.kt
+-packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewLaunchAnimatorController.kt
+-packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt
+-packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt
+-packages/SystemUI/animation/src/com/android/systemui/animation/ViewHierarchyAnimator.kt
+-packages/SystemUI/checks/src/com/android/internal/systemui/lint/BindServiceViaContextDetector.kt
+-packages/SystemUI/checks/src/com/android/internal/systemui/lint/BroadcastSentViaContextDetector.kt
+-packages/SystemUI/checks/src/com/android/internal/systemui/lint/GetMainLooperViaContextDetector.kt
+-packages/SystemUI/checks/src/com/android/internal/systemui/lint/RegisterReceiverViaContextDetector.kt
+-packages/SystemUI/checks/src/com/android/internal/systemui/lint/SoftwareBitmapDetector.kt
+-packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt
+-packages/SystemUI/checks/tests/com/android/systemui/lint/BindServiceViaContextDetectorTest.kt
+-packages/SystemUI/checks/tests/com/android/systemui/lint/BroadcastSentViaContextDetectorTest.kt
+-packages/SystemUI/checks/tests/com/android/systemui/lint/GetMainLooperViaContextDetectorTest.kt
+-packages/SystemUI/checks/tests/com/android/systemui/lint/RegisterReceiverViaContextDetectorTest.kt
+-packages/SystemUI/checks/tests/com/android/systemui/lint/SoftwareBitmapDetectorTest.kt
+-packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt
+-packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
+-packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSContainerController.kt
+-packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt
+-packages/SystemUI/shared/src/com/android/systemui/flags/FlagListenable.kt
+-packages/SystemUI/shared/src/com/android/systemui/flags/FlagManager.kt
+-packages/SystemUI/shared/src/com/android/systemui/flags/FlagSerializer.kt
+-packages/SystemUI/shared/src/com/android/systemui/flags/FlagSettingsHelper.kt
+-packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimator.kt
+-packages/SystemUI/shared/src/com/android/systemui/shared/clocks/AnimatableClockView.kt
+-packages/SystemUI/shared/src/com/android/systemui/shared/clocks/ClockRegistry.kt
+-packages/SystemUI/shared/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
+-packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionDarkness.kt
+-packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionSamplingInstance.kt
+-packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButtonPositionCalculator.kt
+-packages/SystemUI/shared/src/com/android/systemui/shared/system/UncaughtExceptionPreHandlerManager.kt
+-packages/SystemUI/shared/src/com/android/systemui/shared/system/smartspace/SmartspaceState.kt
+-packages/SystemUI/shared/src/com/android/systemui/unfold/system/ActivityManagerActivityTypeProvider.kt
+-packages/SystemUI/shared/src/com/android/systemui/unfold/system/DeviceStateManagerFoldProvider.kt
+-packages/SystemUI/shared/src/com/android/systemui/unfold/system/SystemUnfoldSharedModule.kt
+-packages/SystemUI/src-debug/com/android/systemui/flags/FlagsModule.kt
+-packages/SystemUI/src-release/com/android/systemui/flags/FlagsModule.kt
+-packages/SystemUI/src/com/android/keyguard/ActiveUnlockConfig.kt
+-packages/SystemUI/src/com/android/keyguard/BouncerPanelExpansionCalculator.kt
+-packages/SystemUI/src/com/android/keyguard/KeyguardBiometricLockoutLogger.kt
+-packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt
+-packages/SystemUI/src/com/android/keyguard/KeyguardListenQueue.kt
+-packages/SystemUI/src/com/android/keyguard/KeyguardUnfoldTransition.kt
+-packages/SystemUI/src/com/android/keyguard/KeyguardUserSwitcherAnchor.kt
+-packages/SystemUI/src/com/android/keyguard/clock/ClockPalette.kt
+-packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
+-packages/SystemUI/src/com/android/keyguard/mediator/ScreenOnCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/BootCompleteCache.kt
+-packages/SystemUI/src/com/android/systemui/BootCompleteCacheImpl.kt
+-packages/SystemUI/src/com/android/systemui/CameraAvailabilityListener.kt
+-packages/SystemUI/src/com/android/systemui/ChooserSelector.kt
+-packages/SystemUI/src/com/android/systemui/DarkReceiverImpl.kt
+-packages/SystemUI/src/com/android/systemui/DisplayCutoutBaseView.kt
+-packages/SystemUI/src/com/android/systemui/DualToneHandler.kt
+-packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt
+-packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt
+-packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactoryBase.kt
+-packages/SystemUI/src/com/android/systemui/SystemUIInitializerFactory.kt
+-packages/SystemUI/src/com/android/systemui/SystemUIInitializerImpl.kt
+-packages/SystemUI/src/com/android/systemui/assist/AssistLogger.kt
+-packages/SystemUI/src/com/android/systemui/assist/AssistantInvocationEvent.kt
+-packages/SystemUI/src/com/android/systemui/assist/AssistantSessionEvent.kt
+-packages/SystemUI/src/com/android/systemui/backup/BackupHelper.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/AlternateUdfpsTouchProvider.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFaceIconController.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFaceView.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceIconController.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceView.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintView.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricIconController.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/BiometricDisplayListener.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/DwellRippleShader.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationViewController.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsBpView.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsBpViewController.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsDrawable.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsFpDrawable.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsFpmOtherView.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsFpmOtherViewController.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsHapticsSimulator.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsOverlayParams.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsShell.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/Utils.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/dagger/BiometricsModule.kt
+-packages/SystemUI/src/com/android/systemui/broadcast/ActionReceiver.kt
+-packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt
+-packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcherStartable.kt
+-packages/SystemUI/src/com/android/systemui/broadcast/BroadcastSender.kt
+-packages/SystemUI/src/com/android/systemui/broadcast/PendingRemovalStore.kt
+-packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt
+-packages/SystemUI/src/com/android/systemui/broadcast/logging/BroadcastDispatcherLogger.kt
+-packages/SystemUI/src/com/android/systemui/camera/CameraGestureHelper.kt
+-packages/SystemUI/src/com/android/systemui/camera/CameraIntents.kt
+-packages/SystemUI/src/com/android/systemui/camera/CameraIntentsWrapper.kt
+-packages/SystemUI/src/com/android/systemui/charging/WiredChargingRippleController.kt
+-packages/SystemUI/src/com/android/systemui/controls/ControlStatus.kt
+-packages/SystemUI/src/com/android/systemui/controls/ControlsMetricsLogger.kt
+-packages/SystemUI/src/com/android/systemui/controls/ControlsMetricsLoggerImpl.kt
+-packages/SystemUI/src/com/android/systemui/controls/ControlsServiceInfo.kt
+-packages/SystemUI/src/com/android/systemui/controls/CustomIconCache.kt
+-packages/SystemUI/src/com/android/systemui/controls/TooltipManager.kt
+-packages/SystemUI/src/com/android/systemui/controls/controller/AuxiliaryPersistenceWrapper.kt
+-packages/SystemUI/src/com/android/systemui/controls/controller/ControlInfo.kt
+-packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingController.kt
+-packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt
+-packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt
+-packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
+-packages/SystemUI/src/com/android/systemui/controls/controller/ControlsFavoritePersistenceWrapper.kt
+-packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
+-packages/SystemUI/src/com/android/systemui/controls/controller/ControlsTileResourceConfiguration.kt
+-packages/SystemUI/src/com/android/systemui/controls/controller/ControlsTileResourceConfigurationImpl.kt
+-packages/SystemUI/src/com/android/systemui/controls/controller/ServiceWrapper.kt
+-packages/SystemUI/src/com/android/systemui/controls/controller/StatefulControlSubscriber.kt
+-packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt
+-packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsFeatureEnabled.kt
+-packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/AllModel.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/AppAdapter.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/ControlsAnimations.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/ControlsEditingActivity.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingController.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingControllerImpl.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/ControlsModel.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/ControlsRequestDialog.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/ControlsRequestReceiver.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/FavoritesModel.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/ManagementPageIndicator.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/StructureAdapter.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/Behavior.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/ChallengeDialogs.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/ControlWithState.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/CornerDrawable.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/StatusBehavior.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/TemperatureControlBehavior.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/ThumbnailBehavior.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/ToggleBehavior.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/TouchBehavior.kt
+-packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
+-packages/SystemUI/src/com/android/systemui/decor/DecorProvider.kt
+-packages/SystemUI/src/com/android/systemui/decor/DecorProviderFactory.kt
+-packages/SystemUI/src/com/android/systemui/decor/FaceScanningProviderFactory.kt
+-packages/SystemUI/src/com/android/systemui/decor/OverlayWindow.kt
+-packages/SystemUI/src/com/android/systemui/decor/PrivacyDotDecorProviderFactory.kt
+-packages/SystemUI/src/com/android/systemui/decor/RoundedCornerDecorProviderFactory.kt
+-packages/SystemUI/src/com/android/systemui/decor/RoundedCornerDecorProviderImpl.kt
+-packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt
+-packages/SystemUI/src/com/android/systemui/demomode/DemoModeAvailabilityTracker.kt
+-packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt
+-packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt
+-packages/SystemUI/src/com/android/systemui/doze/util/BurnInHelper.kt
+-packages/SystemUI/src/com/android/systemui/dreams/smartspace/DreamSmartspaceController.kt
+-packages/SystemUI/src/com/android/systemui/dump/DumpHandler.kt
+-packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt
+-packages/SystemUI/src/com/android/systemui/dump/DumpsysTableLogger.kt
+-packages/SystemUI/src/com/android/systemui/dump/LogBufferEulogizer.kt
+-packages/SystemUI/src/com/android/systemui/dump/LogBufferFreezer.kt
+-packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.kt
+-packages/SystemUI/src/com/android/systemui/flags/ServerFlagReader.kt
+-packages/SystemUI/src/com/android/systemui/flags/SystemPropertiesHelper.kt
+-packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
+-packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt
+-packages/SystemUI/src/com/android/systemui/log/LogBufferFactory.kt
+-packages/SystemUI/src/com/android/systemui/log/LogLevel.kt
+-packages/SystemUI/src/com/android/systemui/log/LogMessage.kt
+-packages/SystemUI/src/com/android/systemui/log/LogMessageImpl.kt
+-packages/SystemUI/src/com/android/systemui/log/LogcatEchoTracker.kt
+-packages/SystemUI/src/com/android/systemui/log/LogcatEchoTrackerDebug.kt
+-packages/SystemUI/src/com/android/systemui/log/LogcatEchoTrackerProd.kt
+-packages/SystemUI/src/com/android/systemui/media/AnimationBindHandler.kt
+-packages/SystemUI/src/com/android/systemui/media/ColorSchemeTransition.kt
+-packages/SystemUI/src/com/android/systemui/media/GutsViewHolder.kt
+-packages/SystemUI/src/com/android/systemui/media/IlluminationDrawable.kt
+-packages/SystemUI/src/com/android/systemui/media/KeyguardMediaController.kt
+-packages/SystemUI/src/com/android/systemui/media/LightSourceDrawable.kt
+-packages/SystemUI/src/com/android/systemui/media/LocalMediaManagerFactory.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaCarouselControllerLogger.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaCarouselScrollHandler.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaData.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaDataCombineLatest.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaFeatureFlag.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaFlags.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaHost.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaHostStatesManager.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaProjectionCaptureTarget.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaScrollView.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaSessionBasedFilter.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaTimeoutLogger.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaUiEventLogger.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaViewController.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaViewHolder.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaViewLogger.kt
+-packages/SystemUI/src/com/android/systemui/media/MetadataAnimationHandler.kt
+-packages/SystemUI/src/com/android/systemui/media/RecommendationViewHolder.kt
+-packages/SystemUI/src/com/android/systemui/media/ResumeMediaBrowserLogger.kt
+-packages/SystemUI/src/com/android/systemui/media/SeekBarObserver.kt
+-packages/SystemUI/src/com/android/systemui/media/SeekBarViewModel.kt
+-packages/SystemUI/src/com/android/systemui/media/SmartspaceMediaData.kt
+-packages/SystemUI/src/com/android/systemui/media/SmartspaceMediaDataProvider.kt
+-packages/SystemUI/src/com/android/systemui/media/SquigglyProgress.kt
+-packages/SystemUI/src/com/android/systemui/media/dagger/MediaProjectionModule.kt
+-packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogFactory.kt
+-packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt
+-packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogReceiver.kt
+-packages/SystemUI/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionCli.kt
+-packages/SystemUI/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionManager.kt
+-packages/SystemUI/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionManagerFactory.kt
+-packages/SystemUI/src/com/android/systemui/media/muteawait/MediaMuteAwaitLogger.kt
+-packages/SystemUI/src/com/android/systemui/media/nearby/NearbyMediaDevicesLogger.kt
+-packages/SystemUI/src/com/android/systemui/media/nearby/NearbyMediaDevicesManager.kt
+-packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelper.kt
+-packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttFlags.kt
+-packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/ChipInfoCommon.kt
+-packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt
+-packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttLogger.kt
+-packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ChipStateReceiver.kt
+-packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt
+-packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttReceiverLogger.kt
+-packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ReceiverChipRippleView.kt
+-packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt
+-packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt
+-packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderLogger.kt
+-packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderUiEventLogger.kt
+-packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanel.kt
+-packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt
+-packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgePanelParams.kt
+-packages/SystemUI/src/com/android/systemui/power/BatteryStateSnapshot.kt
+-packages/SystemUI/src/com/android/systemui/privacy/AppOpsPrivacyItemMonitor.kt
+-packages/SystemUI/src/com/android/systemui/privacy/MediaProjectionPrivacyItemMonitor.kt
+-packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt
+-packages/SystemUI/src/com/android/systemui/privacy/PrivacyChipBuilder.kt
+-packages/SystemUI/src/com/android/systemui/privacy/PrivacyChipEvent.kt
+-packages/SystemUI/src/com/android/systemui/privacy/PrivacyConfig.kt
+-packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialog.kt
+-packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogController.kt
+-packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogEvent.kt
+-packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt
+-packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
+-packages/SystemUI/src/com/android/systemui/privacy/logging/PrivacyLogger.kt
+-packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.kt
+-packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt
+-packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt
+-packages/SystemUI/src/com/android/systemui/qs/FooterActionsView.kt
+-packages/SystemUI/src/com/android/systemui/qs/HeaderPrivacyIconsController.kt
+-packages/SystemUI/src/com/android/systemui/qs/QSEvents.kt
+-packages/SystemUI/src/com/android/systemui/qs/QSExpansionPathInterpolator.kt
+-packages/SystemUI/src/com/android/systemui/qs/QSFragmentDisableFlagsLogger.kt
+-packages/SystemUI/src/com/android/systemui/qs/QSSquishinessController.kt
+-packages/SystemUI/src/com/android/systemui/qs/QSUtils.kt
+-packages/SystemUI/src/com/android/systemui/qs/SideLabelTileLayout.kt
+-packages/SystemUI/src/com/android/systemui/qs/VisibilityChangedDispatcher.kt
+-packages/SystemUI/src/com/android/systemui/qs/carrier/CellSignalState.kt
+-packages/SystemUI/src/com/android/systemui/qs/customize/CustomizeTileView.kt
+-packages/SystemUI/src/com/android/systemui/qs/external/CustomTileStatePersister.kt
+-packages/SystemUI/src/com/android/systemui/qs/external/QSExternalModule.kt
+-packages/SystemUI/src/com/android/systemui/qs/external/TileRequestDialog.kt
+-packages/SystemUI/src/com/android/systemui/qs/external/TileRequestDialogEventLogger.kt
+-packages/SystemUI/src/com/android/systemui/qs/external/TileServiceRequestController.kt
+-packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt
+-packages/SystemUI/src/com/android/systemui/qs/tileimpl/HeightOverrideable.kt
+-packages/SystemUI/src/com/android/systemui/qs/tileimpl/IgnorableChildLinearLayout.kt
+-packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
+-packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.kt
+-packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt
+-packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogFactory.kt
+-packages/SystemUI/src/com/android/systemui/qs/user/UserSwitchDialogController.kt
+-packages/SystemUI/src/com/android/systemui/ripple/RippleShader.kt
+-packages/SystemUI/src/com/android/systemui/ripple/RippleShaderUtilLibrary.kt
+-packages/SystemUI/src/com/android/systemui/ripple/RippleView.kt
+-packages/SystemUI/src/com/android/systemui/ripple/SdfShaderLibrary.kt
+-packages/SystemUI/src/com/android/systemui/screenshot/ImageCaptureImpl.kt
+-packages/SystemUI/src/com/android/systemui/screenshot/RequestProcessor.kt
+-packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotPolicy.kt
+-packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotPolicyImpl.kt
+-packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotProxyService.kt
+-packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseDialog.kt
+-packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt
+-packages/SystemUI/src/com/android/systemui/settings/UserContentResolverProvider.kt
+-packages/SystemUI/src/com/android/systemui/settings/UserContextProvider.kt
+-packages/SystemUI/src/com/android/systemui/settings/UserFileManager.kt
+-packages/SystemUI/src/com/android/systemui/settings/UserFileManagerImpl.kt
+-packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt
+-packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
+-packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessMirrorHandler.kt
+-packages/SystemUI/src/com/android/systemui/settings/brightness/MirroredBrightnessController.kt
+-packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManager.kt
+-packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManagerImpl.kt
+-packages/SystemUI/src/com/android/systemui/shade/LargeScreenShadeHeaderController.kt
+-packages/SystemUI/src/com/android/systemui/shade/NPVCDownEventState.kt
+-packages/SystemUI/src/com/android/systemui/shade/NotifPanelEvents.kt
+-packages/SystemUI/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationController.kt
+-packages/SystemUI/src/com/android/systemui/shade/NotificationsQSContainerController.kt
+-packages/SystemUI/src/com/android/systemui/shade/PulsingGestureListener.kt
+-packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt
+-packages/SystemUI/src/com/android/systemui/shade/transition/ScrimShadeTransitionController.kt
+-packages/SystemUI/src/com/android/systemui/shade/transition/ShadeTransitionController.kt
+-packages/SystemUI/src/com/android/systemui/shade/transition/SplitShadeOverScroller.kt
+-packages/SystemUI/src/com/android/systemui/smartspace/SmartspacePrecondition.kt
+-packages/SystemUI/src/com/android/systemui/smartspace/SmartspaceTargetFilter.kt
+-packages/SystemUI/src/com/android/systemui/smartspace/dagger/SmartspaceModule.kt
+-packages/SystemUI/src/com/android/systemui/smartspace/dagger/SmartspaceViewComponent.kt
+-packages/SystemUI/src/com/android/systemui/smartspace/filters/LockscreenAndDreamTargetFilter.kt
+-packages/SystemUI/src/com/android/systemui/smartspace/preconditions/LockscreenPrecondition.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/AbstractLockscreenShadeTransitionController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/ActionClickLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBarWifiView.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/DisableFlagsLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/LockScreenShadeOverScroller.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeKeyguardTransitionController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeScrimTransitionController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/MediaArtworkProcessor.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/NotificationClickNotifier.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/NotificationInteractionTracker.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/SingleShadeLockScreenOverScroller.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/SplitShadeLockScreenOverScroller.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/commandline/CommandRegistry.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/connectivity/AccessPointController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ConnectivityState.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalControllerFactory.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileState.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileStatusTrackerFactory.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/connectivity/SignalCallback.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiState.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiStatusTrackerFactory.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/core/StatusBarInitializer.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/dagger/StartCentralSurfacesModule.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/events/StatusEvent.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/gesture/GenericGestureDetector.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeStatusBarAwayGestureHandler.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeStatusBarAwayGestureLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/gesture/TapGestureDetector.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/FeedbackIcon.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/LaunchAnimationParameters.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClickerLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManagerLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/ViewGroupFadeHelper.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListAttachState.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataStoreImpl.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipeline.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipelineChoreographer.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/PipelineDumper.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/SuppressedAttachState.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/TargetSdkResolver.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescerLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DataStoreCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DebugModeCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupCountCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GutsCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GutsCoordinatorLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RemoteInputCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ShadeEventCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ShadeEventCoordinatorLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SmartspaceDedupingCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ViewConfigCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/dagger/CoordinatorsModule.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/BindEventManager.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/BindEventManagerImpl.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifInflater.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustment.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProvider.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/NotifSection.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifStabilityManager.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionInconsistencyTracker.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifEvent.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/SelfTrackingLifetimeExtender.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/DebugModeFilterProvider.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/NotificationVisibilityProviderImpl.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/SectionHeaderVisibilityProvider.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/SectionStyleProvider.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/MediaContainerController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilder.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilderLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifGroupController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifGutsViewListener.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifGutsViewManager.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifRowController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifShadeEventSource.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifStackController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewBarn.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewRenderer.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotificationVisibilityProvider.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/RenderExtensions.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManager.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/RootNodeController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/SectionHeaderController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDiffer.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDifferLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationSectionHeadersModule.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconBuilder.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerStub.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/HeadsUpViewBinderLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/people/NotificationPersonExtractor.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/people/ViewPipeline.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorListView.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifBindPipelineLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindStageLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/RemoteInputViewModule.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCallTemplateViewWrapper.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationConversationTemplateViewWrapper.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MediaContainerView.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationPriorityBucket.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaViewController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/LSShadeTransitionLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/LetterboxAppearanceCalculator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/LetterboxBackgroundProvider.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/ScreenOffAnimationController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProvider.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHideIconsForBouncerManager.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarLaunchAnimatorController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarLocationPublisher.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarMoveFromCenterAnimationController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemBarAttributesListener.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarIconBlocklist.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarSystemEventAnimator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallChronometer.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallFlags.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/panelstate/PanelExpansionStateManager.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/panelstate/PanelStateListener.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserInfoTracker.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherContainer.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherFeatureController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/pipeline/ConnectivityInfoProcessor.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/model/WifiActivityModel.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/model/WifiNetworkModel.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractor.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/WifiConstants.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiView.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateNotifier.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceControlsController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceControlsControllerImpl.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManagerLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplyState.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplyViewHolder.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisabler.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputViewController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyStateInflater.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/VariableDateView.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/VariableDateViewController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/WalletController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/WalletControllerImpl.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/RemoteInput.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/SmartRepliesInflationModule.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/tv/VpnStatusObserver.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowModule.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowStateController.kt
+-packages/SystemUI/src/com/android/systemui/toast/ToastDefaultAnimation.kt
+-packages/SystemUI/src/com/android/systemui/toast/ToastLogger.kt
+-packages/SystemUI/src/com/android/systemui/tv/TVSystemUICoreStartableModule.kt
+-packages/SystemUI/src/com/android/systemui/unfold/FoldStateLogger.kt
+-packages/SystemUI/src/com/android/systemui/unfold/SysUIUnfoldModule.kt
+-packages/SystemUI/src/com/android/systemui/unfold/UnfoldLatencyTracker.kt
+-packages/SystemUI/src/com/android/systemui/unfold/UnfoldLightRevealOverlayAnimation.kt
+-packages/SystemUI/src/com/android/systemui/unfold/UnfoldProgressProvider.kt
+-packages/SystemUI/src/com/android/systemui/user/UserCreator.kt
+-packages/SystemUI/src/com/android/systemui/user/UserSwitcherActivity.kt
+-packages/SystemUI/src/com/android/systemui/user/UserSwitcherPopupMenu.kt
+-packages/SystemUI/src/com/android/systemui/user/UserSwitcherRootView.kt
+-packages/SystemUI/src/com/android/systemui/util/AsyncActivityLauncher.kt
+-packages/SystemUI/src/com/android/systemui/util/ColorUtil.kt
+-packages/SystemUI/src/com/android/systemui/util/ConvenienceExtensions.kt
+-packages/SystemUI/src/com/android/systemui/util/DelayableMarqueeTextView.kt
+-packages/SystemUI/src/com/android/systemui/util/DumpUtils.kt
+-packages/SystemUI/src/com/android/systemui/util/InitializationChecker.kt
+-packages/SystemUI/src/com/android/systemui/util/LargeScreenUtils.kt
+-packages/SystemUI/src/com/android/systemui/util/ListenerSet.kt
+-packages/SystemUI/src/com/android/systemui/util/NeverExactlyLinearLayout.kt
+-packages/SystemUI/src/com/android/systemui/util/NoRemeasureMotionLayout.kt
+-packages/SystemUI/src/com/android/systemui/util/PluralMessageFormater.kt
+-packages/SystemUI/src/com/android/systemui/util/RingerModeTracker.kt
+-packages/SystemUI/src/com/android/systemui/util/RingerModeTrackerImpl.kt
+-packages/SystemUI/src/com/android/systemui/util/RoundedCornerProgressDrawable.kt
+-packages/SystemUI/src/com/android/systemui/util/SafeMarqueeTextView.kt
+-packages/SystemUI/src/com/android/systemui/util/SparseArrayUtils.kt
+-packages/SystemUI/src/com/android/systemui/util/TraceUtils.kt
+-packages/SystemUI/src/com/android/systemui/util/UserAwareController.kt
+-packages/SystemUI/src/com/android/systemui/util/WallpaperController.kt
+-packages/SystemUI/src/com/android/systemui/util/animation/AnimationUtil.kt
+-packages/SystemUI/src/com/android/systemui/util/animation/MeasurementInput.kt
+-packages/SystemUI/src/com/android/systemui/util/animation/TransitionLayout.kt
+-packages/SystemUI/src/com/android/systemui/util/animation/TransitionLayoutController.kt
+-packages/SystemUI/src/com/android/systemui/util/animation/UniqueObjectHostView.kt
+-packages/SystemUI/src/com/android/systemui/util/collection/RingBuffer.kt
+-packages/SystemUI/src/com/android/systemui/util/concurrency/Execution.kt
+-packages/SystemUI/src/com/android/systemui/util/concurrency/PendingTasksContainer.kt
+-packages/SystemUI/src/com/android/systemui/util/drawable/DrawableSize.kt
+-packages/SystemUI/src/com/android/systemui/util/kotlin/CoroutinesModule.kt
+-packages/SystemUI/src/com/android/systemui/util/kotlin/Flow.kt
+-packages/SystemUI/src/com/android/systemui/util/kotlin/IpcSerializer.kt
+-packages/SystemUI/src/com/android/systemui/util/kotlin/nullability.kt
+-packages/SystemUI/src/com/android/systemui/util/view/ViewUtil.kt
+-packages/SystemUI/src/com/android/systemui/util/wrapper/RotationPolicyWrapper.kt
+-packages/SystemUI/src/com/android/systemui/volume/VolumePanelDialogReceiver.kt
+-packages/SystemUI/src/com/android/systemui/volume/VolumePanelFactory.kt
+-packages/SystemUI/tests/src/com/android/keyguard/ActiveUnlockConfigTest.kt
+-packages/SystemUI/tests/src/com/android/keyguard/BouncerPanelExpansionCalculatorTest.kt
+-packages/SystemUI/tests/src/com/android/keyguard/KeyguardBiometricLockoutLoggerTest.kt
+-packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt
+-packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt
+-packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt
+-packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.kt
+-packages/SystemUI/tests/src/com/android/keyguard/KeyguardUserSwitcherAnchorTest.kt
+-packages/SystemUI/tests/src/com/android/keyguard/clock/ClockPaletteTest.kt
+-packages/SystemUI/tests/src/com/android/keyguard/clock/ViewPreviewerTest.kt
+-packages/SystemUI/tests/src/com/android/keyguard/mediator/ScreenOnCoordinatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/BootCompleteCacheTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/ChooserSelectorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/DisplayCutoutBaseViewTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/InstanceIdSequenceFake.kt
+-packages/SystemUI/tests/src/com/android/systemui/ScreenDecorHwcLayerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/animation/DialogLaunchAnimatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/animation/FontInterpolatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/animation/GhostedViewLaunchAnimatorControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/animation/TextAnimatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/animation/TextInterpolatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/animation/ViewHierarchyAnimatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/battery/BatteryMeterViewTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceViewTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintViewTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricTestExtensions.kt
+-packages/SystemUI/tests/src/com/android/systemui/biometrics/SidefpsControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsViewTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/broadcast/ActionReceiverTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastSenderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/broadcast/PendingRemovalStoreTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/broadcast/UserBroadcastDispatcherTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/camera/CameraGestureHelperTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/camera/CameraIntentsTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/charging/WiredChargingRippleControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/CustomIconCacheTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/controller/AuxiliaryPersistenceWrapperTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlActionCoordinatorImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsBindingControllerImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsFavoritePersistenceWrapperTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsTileResourceConfigurationImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/controller/DeletionJobServiceTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/controller/ServiceWrapperTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/controller/StatefulControlSubscriberTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/dagger/ControlsComponentTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/management/AllModelTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/management/AppAdapterTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsListingControllerImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsRequestDialogTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsRequestReceiverTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/management/FavoritesModelTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/management/TestControlsRequestDialog.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlViewHolderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/decor/OverlayWindowTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/decor/PrivacyDotDecorProviderFactoryTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerDecorProviderFactoryTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerResDelegateTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/dump/DumpHandlerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/dump/DumpsysTableLoggerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/dump/LogBufferFreezerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/dump/LogBufferHelper.kt
+-packages/SystemUI/tests/src/com/android/systemui/dump/LogEulogizerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsReleaseTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/flags/FlagManagerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/lifecycle/InstantTaskExecutorRule.kt
+-packages/SystemUI/tests/src/com/android/systemui/log/LogBufferTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/AnimationBindHandlerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/ColorSchemeTransitionTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/KeyguardMediaControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/MediaPlayerDataTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/MediaResumeListenerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/MediaSessionBasedFilterTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/MediaTestUtils.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/MediaTimeoutListenerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/MetadataAnimationHandlerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/ResumeMediaBrowserTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/SeekBarObserverTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/SeekBarViewModelTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/SmartspaceMediaDataTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/SquigglyProgressTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionManagerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/nearby/NearbyMediaDevicesManagerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelperTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommonTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttLoggerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSenderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderUiEventLoggerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/navigationbar/gestural/FloatingRotationButtonPositionCalculatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/privacy/AppOpsPrivacyItemMonitorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyChipBuilderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyConfigFlagsTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/FooterActionsControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/HeaderPrivacyIconsControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/QSContainerImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentDisableFlagsLoggerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelSwitchToParentTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/QSSquishinessControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/SettingObserverTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/carrier/CellSignalStateTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileStatePersisterTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/external/TileRequestDialogEventLoggerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/external/TileRequestDialogTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceRequestControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSFactoryImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileViewImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/ResourceIconTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/TilesStatesTextTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AirplaneModeTileTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AlarmTileTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BluetoothTileTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CameraToggleTileTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tiles/LocationTileTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tiles/MicrophoneToggleTileTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/user/UserSwitchDialogControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/ripple/RippleViewTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/screenrecord/ScreenRecordDialogTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/screenshot/ImageCaptureImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/screenshot/RequestProcessorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotServiceTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/settings/UserFileManagerImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shade/CombinedShadeHeaderConstraintsTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerCombinedTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shade/NotificationQSContainerControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shade/transition/ScrimShadeTransitionControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shade/transition/ShadeTransitionControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shade/transition/SplitShadeOverScrollerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shared/navigationbar/RegionSamplingHelperTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shared/regionsampling/RegionSamplingInstanceTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shared/rotation/RotationButtonControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shared/system/UncaughtExceptionPreHandlerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/smartspace/DreamSmartspaceControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenAndDreamTargetFilterTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenPreconditionTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/BlurUtilsTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/DisableFlagsLoggerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/LSShadeTransitionLoggerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/LightRevealScrimTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/MediaArtworkProcessorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/SingleShadeLockScreenOverScrollerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/SplitShadeLockScreenOverScrollerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateEventTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/VibratorHelperTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/commandline/CommandRegistryTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/AccessPointControllerImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/gesture/GenericGestureDetectorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManagerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataStoreImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifPipelineChoreographerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/TargetSdkResolverTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/DataStoreCoordinatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupCountCoordinatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RemoteInputCoordinatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ShadeEventCoordinatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SmartspaceDedupingCoordinatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ViewConfigCoordinatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProviderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionInconsistencyTrackerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/notifcollection/SelfTrackingLifetimeExtenderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/provider/VisualStabilityProviderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManagerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/IconManagerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationViewTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/MediaContainerViewTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationShelfTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ConfigurationControllerImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/FoldStateListenerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LetterboxAppearanceCalculatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LetterboxBackgroundProviderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconContainerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProviderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarMoveFromCenterAnimationControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/SystemBarAttributesListenerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentLoggerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallChronometerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallLoggerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/panelstate/PanelExpansionStateManagerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLoggerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositoryImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryStateNotifierTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ClockTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceControlsControllerImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/FlashlightControllerImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherAdapterTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisablerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SafetyControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/VariableDateViewControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/WalletControllerImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/window/StatusBarWindowStateControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/unfold/FoldStateLoggingProviderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldLatencyTrackerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldTransitionWallpaperControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfigTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/unfold/util/FoldableTestUtils.kt
+-packages/SystemUI/tests/src/com/android/systemui/unfold/util/NaturalRotationUnfoldProgressProviderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/unfold/util/ScaleAwareUnfoldProgressProviderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/unfold/util/TestFoldStateProvider.kt
+-packages/SystemUI/tests/src/com/android/systemui/usb/UsbPermissionActivityTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/user/UserCreatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/user/UserSwitcherActivityTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/util/FakeSharedPreferencesTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/util/FloatingContentCoordinatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/util/ListenerSetTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/util/RingerModeLiveDataTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/util/WallpaperControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/util/animation/AnimationUtilTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/util/collection/RingBufferTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/util/drawable/DrawableSizeTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/util/kotlin/FlowUtilTests.kt
+-packages/SystemUI/tests/src/com/android/systemui/util/kotlin/IpcSerializerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/util/view/ViewUtilTest.kt
+-packages/SystemUI/tests/utils/src/com/android/systemui/broadcast/FakeBroadcastDispatcher.kt
+-packages/SystemUI/tests/utils/src/com/android/systemui/flags/FakeFeatureFlags.kt
+-packages/SystemUI/tests/utils/src/com/android/systemui/util/FakeSharedPreferences.kt
+-packages/SystemUI/tests/utils/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldSharedModule.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldTransitionFactory.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/compat/ScreenSizeFoldProvider.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/compat/SizeScreenStatusProvider.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfig.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/dagger/UnfoldBackground.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/dagger/UnfoldMain.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/FoldStateProvider.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/hinge/HingeSensorAngleProvider.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/screen/ScreenStatusProvider.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScaleAwareTransitionProgressProvider.kt
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index dca5ea8..f88f46f 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -131,7 +131,11 @@
     <!-- For StatusIconContainer to tag its icon views -->
     <item type="id" name="status_bar_view_state_tag" />
 
+    <!-- Default display cutout on the physical top of screen -->
     <item type="id" name="display_cutout" />
+    <item type="id" name="display_cutout_left" />
+    <item type="id" name="display_cutout_right" />
+    <item type="id" name="display_cutout_bottom" />
 
     <item type="id" name="row_tag_for_content_view" />
 
diff --git a/packages/SystemUI/src/com/android/systemui/DisplayCutoutBaseView.kt b/packages/SystemUI/src/com/android/systemui/DisplayCutoutBaseView.kt
index d2c229b..a3351e1 100644
--- a/packages/SystemUI/src/com/android/systemui/DisplayCutoutBaseView.kt
+++ b/packages/SystemUI/src/com/android/systemui/DisplayCutoutBaseView.kt
@@ -47,7 +47,8 @@
 open class DisplayCutoutBaseView : View, RegionInterceptableView {
 
     private var shouldDrawCutout: Boolean = DisplayCutout.getFillBuiltInDisplayCutout(
-            context.resources, context.display?.uniqueId)
+        context.resources, context.display?.uniqueId
+    )
     private var displayUniqueId: String? = null
     private var displayMode: Display.Mode? = null
     protected val location = IntArray(2)
@@ -74,8 +75,8 @@
 
     constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
 
-    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int)
-            : super(context, attrs, defStyleAttr)
+    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) :
+        super(context, attrs, defStyleAttr)
 
     override fun onAttachedToWindow() {
         super.onAttachedToWindow()
@@ -85,7 +86,7 @@
         onUpdate()
     }
 
-    fun onDisplayChanged(displayId: Int) {
+    fun onDisplayChanged(newDisplayUniqueId: String?) {
         val oldMode: Display.Mode? = displayMode
         val display: Display? = context.display
         displayMode = display?.mode
@@ -93,7 +94,8 @@
         if (displayUniqueId != display?.uniqueId) {
             displayUniqueId = display?.uniqueId
             shouldDrawCutout = DisplayCutout.getFillBuiltInDisplayCutout(
-                    context.resources, displayUniqueId)
+                context.resources, displayUniqueId
+            )
         }
 
         // Skip if display mode or cutout hasn't changed.
@@ -101,7 +103,7 @@
                 display?.cutout == displayInfo.displayCutout) {
             return
         }
-        if (displayId == display?.displayId) {
+        if (newDisplayUniqueId == display?.uniqueId) {
             updateCutout()
             updateProtectionBoundingPath()
             onUpdate()
@@ -147,8 +149,9 @@
         cutoutBounds.translate(-location[0], -location[1])
 
         // Intersect with window's frame
-        cutoutBounds.op(rootView.left, rootView.top, rootView.right, rootView.bottom,
-                Region.Op.INTERSECT)
+        cutoutBounds.op(
+            rootView.left, rootView.top, rootView.right, rootView.bottom, Region.Op.INTERSECT
+        )
         return cutoutBounds
     }
 
@@ -171,9 +174,12 @@
 
     protected open fun drawCutoutProtection(canvas: Canvas) {
         if (cameraProtectionProgress > HIDDEN_CAMERA_PROTECTION_SCALE &&
-                !protectionRect.isEmpty) {
-            canvas.scale(cameraProtectionProgress, cameraProtectionProgress,
-                    protectionRect.centerX(), protectionRect.centerY())
+            !protectionRect.isEmpty
+        ) {
+            canvas.scale(
+                cameraProtectionProgress, cameraProtectionProgress, protectionRect.centerX(),
+                protectionRect.centerY()
+            )
             canvas.drawPath(protectionPath, paint)
         }
     }
@@ -205,14 +211,17 @@
             requestLayout()
         }
         cameraProtectionAnimator?.cancel()
-        cameraProtectionAnimator = ValueAnimator.ofFloat(cameraProtectionProgress,
-                if (showProtection) 1.0f else HIDDEN_CAMERA_PROTECTION_SCALE).setDuration(750)
+        cameraProtectionAnimator = ValueAnimator.ofFloat(
+            cameraProtectionProgress,
+            if (showProtection) 1.0f else HIDDEN_CAMERA_PROTECTION_SCALE
+        ).setDuration(750)
         cameraProtectionAnimator?.interpolator = Interpolators.DECELERATE_QUINT
-        cameraProtectionAnimator?.addUpdateListener(ValueAnimator.AnimatorUpdateListener {
-            animation: ValueAnimator ->
-            cameraProtectionProgress = animation.animatedValue as Float
-            invalidate()
-        })
+        cameraProtectionAnimator?.addUpdateListener(
+            ValueAnimator.AnimatorUpdateListener { animation: ValueAnimator ->
+                cameraProtectionProgress = animation.animatedValue as Float
+                invalidate()
+            }
+        )
         cameraProtectionAnimator?.addListener(object : AnimatorListenerAdapter() {
             override fun onAnimationEnd(animation: Animator) {
                 cameraProtectionAnimator = null
@@ -245,8 +254,10 @@
         // Apply rotation.
         val lw: Int = displayInfo.logicalWidth
         val lh: Int = displayInfo.logicalHeight
-        val flipped = (displayInfo.rotation == Surface.ROTATION_90 ||
-                displayInfo.rotation == Surface.ROTATION_270)
+        val flipped = (
+            displayInfo.rotation == Surface.ROTATION_90 ||
+                displayInfo.rotation == Surface.ROTATION_270
+            )
         val dw = if (flipped) lh else lw
         val dh = if (flipped) lw else lh
         transformPhysicalToLogicalCoordinates(displayInfo.rotation, dw, dh, m)
@@ -275,7 +286,7 @@
         // We purposely ignore refresh rate and id changes here, because we don't need to
         // invalidate for those, and they can trigger the refresh rate to increase
         return oldMode?.physicalHeight != newMode?.physicalHeight ||
-                oldMode?.physicalWidth != newMode?.physicalWidth
+            oldMode?.physicalWidth != newMode?.physicalWidth
     }
 
     companion object {
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index edcaf49..2e13903 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -32,7 +32,6 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.ActivityInfo;
-import android.content.res.ColorStateList;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.Color;
@@ -73,6 +72,7 @@
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.decor.CutoutDecorProviderFactory;
 import com.android.systemui.decor.DecorProvider;
 import com.android.systemui.decor.DecorProviderFactory;
 import com.android.systemui.decor.DecorProviderKt;
@@ -92,10 +92,8 @@
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Objects;
-import java.util.Set;
 import java.util.concurrent.Executor;
 
 import javax.inject.Inject;
@@ -121,6 +119,13 @@
     private static final boolean VERBOSE = false;
     static final boolean DEBUG_COLOR = DEBUG_SCREENSHOT_ROUNDED_CORNERS;
 
+    private static final int[] DISPLAY_CUTOUT_IDS = {
+            R.id.display_cutout,
+            R.id.display_cutout_left,
+            R.id.display_cutout_right,
+            R.id.display_cutout_bottom
+    };
+
     private DisplayManager mDisplayManager;
     @VisibleForTesting
     protected boolean mIsRegistered;
@@ -142,13 +147,11 @@
     protected RoundedCornerResDelegate mRoundedCornerResDelegate;
     @VisibleForTesting
     protected DecorProviderFactory mRoundedCornerFactory;
+    private CutoutDecorProviderFactory mCutoutFactory;
     private int mProviderRefreshToken = 0;
     @VisibleForTesting
     protected OverlayWindow[] mOverlays = null;
     @VisibleForTesting
-    @Nullable
-    DisplayCutoutView[] mCutoutViews;
-    @VisibleForTesting
     ViewGroup mScreenDecorHwcWindow;
     @VisibleForTesting
     ScreenDecorHwcLayer mScreenDecorHwcLayer;
@@ -190,18 +193,19 @@
             return;
         }
 
-        if (mCutoutViews == null) {
-            Log.w(TAG, "DisplayCutoutView not initialized onApplyCameraProtection");
-            return;
-        }
-
-        // Show the extra protection around the front facing camera if necessary
-        for (DisplayCutoutView dcv : mCutoutViews) {
-            // Check Null since not all mCutoutViews[pos] be inflated at the meanwhile
-            if (dcv != null) {
-                dcv.setProtection(protectionPath, bounds);
-                dcv.enableShowProtection(true);
+        int setProtectionCnt = 0;
+        for (int id: DISPLAY_CUTOUT_IDS) {
+            final View view = getOverlayView(id);
+            if (!(view instanceof DisplayCutoutView)) {
+                continue;
             }
+            ++setProtectionCnt;
+            final DisplayCutoutView dcv = (DisplayCutoutView) view;
+            dcv.setProtection(protectionPath, bounds);
+            dcv.enableShowProtection(true);
+        }
+        if (setProtectionCnt == 0) {
+            Log.e(TAG, "CutoutView not initialized showCameraProtection");
         }
     }
 
@@ -222,16 +226,17 @@
             return;
         }
 
-        if (mCutoutViews == null) {
-            Log.w(TAG, "DisplayCutoutView not initialized onHideCameraProtection");
-            return;
-        }
-        // Go back to the regular anti-aliasing
-        for (DisplayCutoutView dcv : mCutoutViews) {
-            // Check Null since not all mCutoutViews[pos] be inflated at the meanwhile
-            if (dcv != null) {
-                dcv.enableShowProtection(false);
+        int setProtectionCnt = 0;
+        for (int id: DISPLAY_CUTOUT_IDS) {
+            final View view = getOverlayView(id);
+            if (!(view instanceof DisplayCutoutView)) {
+                continue;
             }
+            ++setProtectionCnt;
+            ((DisplayCutoutView) view).enableShowProtection(false);
+        }
+        if (setProtectionCnt == 0) {
+            Log.e(TAG, "CutoutView not initialized hideCameraProtection");
         }
     }
 
@@ -338,6 +343,7 @@
         decorProviders.addAll(mFaceScanningFactory.getProviders());
         if (!hasHwLayer) {
             decorProviders.addAll(mRoundedCornerFactory.getProviders());
+            decorProviders.addAll(mCutoutFactory.getProviders());
         }
         return decorProviders;
     }
@@ -382,6 +388,7 @@
         mRoundedCornerResDelegate.setPhysicalPixelDisplaySizeRatio(
                 getPhysicalPixelDisplaySizeRatio());
         mRoundedCornerFactory = new RoundedCornerDecorProviderFactory(mRoundedCornerResDelegate);
+        mCutoutFactory = getCutoutFactory();
         mHwcScreenDecorationSupport = mContext.getDisplay().getDisplayDecorationSupport();
         updateHwLayerRoundedCornerDrawable();
         setupDecorations();
@@ -448,6 +455,7 @@
                     }
                 }
 
+                boolean needToUpdateProviderViews = false;
                 final String newUniqueId = mDisplayInfo.uniqueId;
                 if (!Objects.equals(newUniqueId, mDisplayUniqueId)) {
                     mDisplayUniqueId = newUniqueId;
@@ -470,8 +478,7 @@
                         updateHwLayerRoundedCornerDrawable();
                         updateHwLayerRoundedCornerExistAndSize();
                     }
-
-                    updateOverlayProviderViews();
+                    needToUpdateProviderViews = true;
                 }
 
                 final float newRatio = getPhysicalPixelDisplaySizeRatio();
@@ -480,28 +487,23 @@
                     if (mScreenDecorHwcLayer != null) {
                         updateHwLayerRoundedCornerExistAndSize();
                     }
-                    updateOverlayProviderViews();
+                    needToUpdateProviderViews = true;
                 }
 
-                if (mCutoutViews != null) {
-                    final int size = mCutoutViews.length;
-                    for (int i = 0; i < size; i++) {
-                        final DisplayCutoutView cutoutView = mCutoutViews[i];
-                        if (cutoutView == null) {
-                            continue;
-                        }
-                        cutoutView.onDisplayChanged(displayId);
-                    }
-                }
-
-                DisplayCutoutView overlay = (DisplayCutoutView) getOverlayView(mFaceScanningViewId);
-                if (overlay != null) {
-                    // handle display resolution changes
-                    overlay.onDisplayChanged(displayId);
+                if (needToUpdateProviderViews) {
+                    updateOverlayProviderViews(null);
+                } else {
+                    updateOverlayProviderViews(new Integer[] {
+                            mFaceScanningViewId,
+                            R.id.display_cutout,
+                            R.id.display_cutout_left,
+                            R.id.display_cutout_right,
+                            R.id.display_cutout_bottom,
+                    });
                 }
 
                 if (mScreenDecorHwcLayer != null) {
-                    mScreenDecorHwcLayer.onDisplayChanged(displayId);
+                    mScreenDecorHwcLayer.onDisplayChanged(newUniqueId);
                 }
             }
         };
@@ -510,8 +512,9 @@
         updateConfiguration();
     }
 
+    @VisibleForTesting
     @Nullable
-    private View getOverlayView(@IdRes int id) {
+    View getOverlayView(@IdRes int id) {
         if (mOverlays == null) {
             return null;
         }
@@ -568,18 +571,18 @@
                 removeHwcOverlay();
             }
 
-            final DisplayCutout cutout = getCutout();
+            boolean[] hasCreatedOverlay = new boolean[BOUNDS_POSITION_LENGTH];
             final boolean shouldOptimizeVisibility = shouldOptimizeVisibility();
+            Integer bound;
+            while ((bound = DecorProviderKt.getProperBound(decorProviders)) != null) {
+                hasCreatedOverlay[bound] = true;
+                Pair<List<DecorProvider>, List<DecorProvider>> pair =
+                        DecorProviderKt.partitionAlignedBound(decorProviders, bound);
+                decorProviders = pair.getSecond();
+                createOverlay(bound, pair.getFirst(), shouldOptimizeVisibility);
+            }
             for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) {
-                if (shouldShowSwLayerCutout(i, cutout)
-                        || shouldShowSwLayerFaceScan(i, cutout)
-                        || shouldShowSwLayerRoundedCorner(i, cutout)
-                        || shouldShowSwLayerPrivacyDot(i, cutout)) {
-                    Pair<List<DecorProvider>, List<DecorProvider>> pair =
-                            DecorProviderKt.partitionAlignedBound(decorProviders, i);
-                    decorProviders = pair.getSecond();
-                    createOverlay(i, pair.getFirst(), shouldOptimizeVisibility);
-                } else {
+                if (!hasCreatedOverlay[i]) {
                     removeOverlay(i);
                 }
             }
@@ -642,9 +645,10 @@
         }
     }
 
-    @VisibleForTesting
-    DisplayCutout getCutout() {
-        return mContext.getDisplay().getCutout();
+    // For unit test to override
+    protected CutoutDecorProviderFactory getCutoutFactory() {
+        return new CutoutDecorProviderFactory(mContext.getResources(),
+                mContext.getDisplay());
     }
 
     @VisibleForTesting
@@ -734,16 +738,6 @@
         overlayView.setAlpha(0);
         overlayView.setForceDarkAllowed(false);
 
-        // Only show cutout in mOverlays when hwc doesn't support screen decoration
-        if (mHwcScreenDecorationSupport == null) {
-            if (mCutoutViews == null) {
-                mCutoutViews = new DisplayCutoutView[BOUNDS_POSITION_LENGTH];
-            }
-            mCutoutViews[pos] = new DisplayCutoutView(mContext, pos);
-            overlayView.addView(mCutoutViews[pos]);
-            mCutoutViews[pos].updateRotation(mRotation);
-        }
-
         mWindowManager.addView(overlayView, getWindowLayoutParams(pos));
 
         overlayView.addOnLayoutChangeListener(new OnLayoutChangeListener() {
@@ -804,7 +798,7 @@
                     return;
                 }
                 removeOverlayView(provider.getViewId());
-                overlay.addDecorProvider(provider, mRotation);
+                overlay.addDecorProvider(provider, mRotation, mTintColor);
             });
         }
         // Use visibility of privacy dot views & face scanning view to determine the overlay's
@@ -923,6 +917,7 @@
     }
 
     private void setupCameraListener() {
+        // TODO(b/238143614) Support dual screen camera protection
         Resources res = mContext.getResources();
         boolean enabled = res.getBoolean(R.bool.config_enableDisplayCutoutProtection);
         if (enabled) {
@@ -951,45 +946,17 @@
             mTintColor = Color.RED;
         }
 
-        if (mOverlays == null) {
-            return;
-        }
-
-        // When the hwc supports screen decorations, the layer will use the A8 color mode which
-        // won't be affected by the color inversion. If the composition goes the client composition
-        // route, the color inversion will be handled by the RenderEngine.
-        final Set<Integer> viewsMayNeedColorUpdate = new HashSet<>();
-        if (mHwcScreenDecorationSupport == null) {
-            ColorStateList tintList = ColorStateList.valueOf(mTintColor);
-            mRoundedCornerResDelegate.setColorTintList(tintList);
-            viewsMayNeedColorUpdate.add(R.id.rounded_corner_top_left);
-            viewsMayNeedColorUpdate.add(R.id.rounded_corner_top_right);
-            viewsMayNeedColorUpdate.add(R.id.rounded_corner_bottom_left);
-            viewsMayNeedColorUpdate.add(R.id.rounded_corner_bottom_right);
-            viewsMayNeedColorUpdate.add(R.id.display_cutout);
-        }
-        if (getOverlayView(mFaceScanningViewId) != null) {
-            viewsMayNeedColorUpdate.add(mFaceScanningViewId);
-        }
-        final Integer[] views = new Integer[viewsMayNeedColorUpdate.size()];
-        viewsMayNeedColorUpdate.toArray(views);
-        for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) {
-            if (mOverlays[i] == null) {
-                continue;
-            }
-            final ViewGroup overlayView = mOverlays[i].getRootView();
-            final int size = overlayView.getChildCount();
-            View child;
-            for (int j = 0; j < size; j++) {
-                child = overlayView.getChildAt(j);
-                if (viewsMayNeedColorUpdate.contains(child.getId())
-                        && child instanceof DisplayCutoutView) {
-                    ((DisplayCutoutView) child).setColor(mTintColor);
-                }
-            }
-            mOverlays[i].onReloadResAndMeasure(views, mProviderRefreshToken,
-                    mRotation, mDisplayUniqueId);
-        }
+        updateOverlayProviderViews(new Integer[] {
+                mFaceScanningViewId,
+                R.id.display_cutout,
+                R.id.display_cutout_left,
+                R.id.display_cutout_right,
+                R.id.display_cutout_bottom,
+                R.id.rounded_corner_top_left,
+                R.id.rounded_corner_top_right,
+                R.id.rounded_corner_bottom_left,
+                R.id.rounded_corner_bottom_right
+        });
     }
 
     @VisibleForTesting
@@ -1109,18 +1076,9 @@
                 updateHwLayerRoundedCornerDrawable();
             }
             updateLayoutParams();
-            // update cutout view rotation
-            if (mCutoutViews != null) {
-                for (final DisplayCutoutView cutoutView: mCutoutViews) {
-                    if (cutoutView == null) {
-                        continue;
-                    }
-                    cutoutView.updateRotation(mRotation);
-                }
-            }
 
             // update all provider views inside overlay
-            updateOverlayProviderViews();
+            updateOverlayProviderViews(null);
         }
 
         FaceScanningOverlay faceScanningOverlay =
@@ -1136,46 +1094,6 @@
         return mRoundedCornerFactory.getHasProviders();
     }
 
-    private boolean isDefaultShownOverlayPos(@BoundsPosition int pos,
-            @Nullable DisplayCutout cutout) {
-        // for cutout is null or cutout with only waterfall.
-        final boolean emptyBoundsOrWaterfall = cutout == null || cutout.isBoundsEmpty();
-        // Shows rounded corner on left and right overlays only when there is no top or bottom
-        // cutout.
-        final int rotatedTop = getBoundPositionFromRotation(BOUNDS_POSITION_TOP, mRotation);
-        final int rotatedBottom = getBoundPositionFromRotation(BOUNDS_POSITION_BOTTOM, mRotation);
-        if (emptyBoundsOrWaterfall || !cutout.getBoundingRectsAll()[rotatedTop].isEmpty()
-                || !cutout.getBoundingRectsAll()[rotatedBottom].isEmpty()) {
-            return pos == BOUNDS_POSITION_TOP || pos == BOUNDS_POSITION_BOTTOM;
-        } else {
-            return pos == BOUNDS_POSITION_LEFT || pos == BOUNDS_POSITION_RIGHT;
-        }
-    }
-
-    private boolean shouldShowSwLayerRoundedCorner(@BoundsPosition int pos,
-            @Nullable DisplayCutout cutout) {
-        return hasRoundedCorners() && isDefaultShownOverlayPos(pos, cutout)
-                && mHwcScreenDecorationSupport == null;
-    }
-
-    private boolean shouldShowSwLayerPrivacyDot(@BoundsPosition int pos,
-            @Nullable DisplayCutout cutout) {
-        return isPrivacyDotEnabled() && isDefaultShownOverlayPos(pos, cutout);
-    }
-
-    private boolean shouldShowSwLayerFaceScan(@BoundsPosition int pos,
-            @Nullable DisplayCutout cutout) {
-        return mFaceScanningFactory.getHasProviders() && isDefaultShownOverlayPos(pos, cutout);
-    }
-
-    private boolean shouldShowSwLayerCutout(@BoundsPosition int pos,
-            @Nullable DisplayCutout cutout) {
-        final Rect[] bounds = cutout == null ? null : cutout.getBoundingRectsAll();
-        final int rotatedPos = getBoundPositionFromRotation(pos, mRotation);
-        return (bounds != null && !bounds[rotatedPos].isEmpty()
-                && mHwcScreenDecorationSupport == null);
-    }
-
     private boolean shouldOptimizeVisibility() {
         return (isPrivacyDotEnabled() || mFaceScanningFactory.getHasProviders())
                 && (mHwcScreenDecorationSupport != null
@@ -1184,7 +1102,7 @@
     }
 
     private boolean shouldDrawCutout() {
-        return shouldDrawCutout(mContext);
+        return mCutoutFactory.getHasProviders();
     }
 
     static boolean shouldDrawCutout(Context context) {
@@ -1192,7 +1110,7 @@
                 context.getResources(), context.getDisplay().getUniqueId());
     }
 
-    private void updateOverlayProviderViews() {
+    private void updateOverlayProviderViews(@Nullable Integer[] filterIds) {
         if (mOverlays == null) {
             return;
         }
@@ -1201,7 +1119,8 @@
             if (overlay == null) {
                 continue;
             }
-            overlay.onReloadResAndMeasure(null, mProviderRefreshToken, mRotation, mDisplayUniqueId);
+            overlay.onReloadResAndMeasure(filterIds, mProviderRefreshToken, mRotation, mTintColor,
+                    mDisplayUniqueId);
         }
     }
 
@@ -1240,19 +1159,12 @@
             } catch (NumberFormatException e) {
                 mRoundedCornerResDelegate.setTuningSizeFactor(null);
             }
-            Integer[] filterIds = {
+            updateOverlayProviderViews(new Integer[] {
                     R.id.rounded_corner_top_left,
                     R.id.rounded_corner_top_right,
                     R.id.rounded_corner_bottom_left,
                     R.id.rounded_corner_bottom_right
-            };
-            for (final OverlayWindow overlay: mOverlays) {
-                if (overlay == null) {
-                    continue;
-                }
-                overlay.onReloadResAndMeasure(filterIds, mProviderRefreshToken, mRotation,
-                        mDisplayUniqueId);
-            }
+            });
             updateHwLayerRoundedCornerExistAndSize();
         });
     }
@@ -1306,7 +1218,6 @@
 
             paint.setColor(mColor);
             paint.setStyle(Paint.Style.FILL);
-            setId(R.id.display_cutout);
             if (DEBUG) {
                 getViewTreeObserver().addOnDrawListener(() -> Log.i(TAG,
                         getWindowTitleByPos(pos) + " drawn in rot " + mRotation));
@@ -1314,6 +1225,9 @@
         }
 
         public void setColor(int color) {
+            if (color == mColor) {
+                return;
+            }
             mColor = color;
             paint.setColor(mColor);
             invalidate();
@@ -1321,6 +1235,12 @@
 
         @Override
         public void updateRotation(int rotation) {
+            // updateRotation() is called inside CutoutDecorProviderImpl::onReloadResAndMeasure()
+            // during onDisplayChanged. In order to prevent reloading cutout info in super class,
+            // check mRotation at first
+            if (rotation == mRotation) {
+                return;
+            }
             mRotation = rotation;
             super.updateRotation(rotation);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
index 84e1c3d..86837366 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
@@ -129,6 +129,8 @@
     private final Set<Integer> mFailedModalities = new HashSet<Integer>();
 
     private final @Background DelayableExecutor mBackgroundExecutor;
+    private int mOrientation;
+    private boolean mSkipFirstLostFocus = false;
 
     // Non-null only if the dialog is in the act of dismissing and has not sent the reason yet.
     @Nullable @AuthDialogCallback.DismissedReason private Integer mPendingCallbackReason;
@@ -441,6 +443,12 @@
     public void onWindowFocusChanged(boolean hasWindowFocus) {
         super.onWindowFocusChanged(hasWindowFocus);
         if (!hasWindowFocus) {
+            //it's a workaround to avoid closing BP incorrectly
+            //BP gets a onWindowFocusChanged(false) and then gets a onWindowFocusChanged(true)
+            if (mSkipFirstLostFocus) {
+                mSkipFirstLostFocus = false;
+                return;
+            }
             Log.v(TAG, "Lost window focus, dismissing the dialog");
             animateAway(AuthDialogCallback.DISMISSED_USER_CANCELED);
         }
@@ -450,6 +458,9 @@
     public void onAttachedToWindow() {
         super.onAttachedToWindow();
 
+        //save the first orientation
+        mOrientation = getResources().getConfiguration().orientation;
+
         mWakefulnessLifecycle.addObserver(this);
 
         if (Utils.isBiometricAllowed(mConfig.mPromptInfo)) {
@@ -621,6 +632,12 @@
         if (mBiometricView != null) {
             mBiometricView.restoreState(savedState);
         }
+
+        if (savedState != null) {
+            mSkipFirstLostFocus = savedState.getBoolean(
+                    AuthDialog.KEY_BIOMETRIC_ORIENTATION_CHANGED);
+        }
+
         wm.addView(this, getLayoutParams(mWindowToken, mConfig.mPromptInfo.getTitle()));
     }
 
@@ -677,6 +694,10 @@
                 mBiometricView != null && mCredentialView == null);
         outState.putBoolean(AuthDialog.KEY_CREDENTIAL_SHOWING, mCredentialView != null);
 
+        if (mOrientation != getResources().getConfiguration().orientation) {
+            outState.putBoolean(AuthDialog.KEY_BIOMETRIC_ORIENTATION_CHANGED, true);
+        }
+
         if (mBiometricView != null) {
             mBiometricView.onSaveState(outState);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java
index 51f39b3..cd0fc37 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java
@@ -48,6 +48,8 @@
     String KEY_BIOMETRIC_SENSOR_TYPE = "sensor_type";
     String KEY_BIOMETRIC_SENSOR_PROPS = "sensor_props";
 
+    String KEY_BIOMETRIC_ORIENTATION_CHANGED = "orientation_changed";
+
     int SIZE_UNKNOWN = 0;
     /**
      * Minimal UI, showing only biometric icon.
diff --git a/packages/SystemUI/src/com/android/systemui/camera/CameraGestureHelper.kt b/packages/SystemUI/src/com/android/systemui/camera/CameraGestureHelper.kt
index 4fe2dd8..e2ef247 100644
--- a/packages/SystemUI/src/com/android/systemui/camera/CameraGestureHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/camera/CameraGestureHelper.kt
@@ -33,7 +33,6 @@
 import com.android.systemui.ActivityIntentHelper
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.plugins.ActivityStarter
-import com.android.systemui.shade.NotificationPanelViewController
 import com.android.systemui.shared.system.ActivityManagerKt.isInForeground
 import com.android.systemui.statusbar.StatusBarState
 import com.android.systemui.statusbar.phone.CentralSurfaces
@@ -117,7 +116,7 @@
                     )
                 } catch (e: RemoteException) {
                     Log.w(
-                        NotificationPanelViewController.TAG,
+                        "CameraGestureHelper",
                         "Unable to start camera activity",
                         e
                     )
diff --git a/packages/SystemUI/src/com/android/systemui/decor/CutoutDecorProviderFactory.kt b/packages/SystemUI/src/com/android/systemui/decor/CutoutDecorProviderFactory.kt
new file mode 100644
index 0000000..cbed21c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/decor/CutoutDecorProviderFactory.kt
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.decor
+
+import android.content.res.Resources
+import android.util.Log
+import android.view.Display
+import android.view.DisplayCutout
+import android.view.DisplayInfo
+
+class CutoutDecorProviderFactory constructor(
+    private val res: Resources,
+    private val display: Display?,
+) : DecorProviderFactory() {
+
+    val displayInfo = DisplayInfo()
+
+    override val hasProviders: Boolean
+        get() {
+            display?.getDisplayInfo(displayInfo) ?: run {
+                Log.w(TAG, "display is null, can't update displayInfo")
+            }
+            return DisplayCutout.getFillBuiltInDisplayCutout(res, displayInfo.uniqueId)
+        }
+
+    override val providers: List<DecorProvider>
+        get() {
+            if (!hasProviders) {
+                return emptyList()
+            }
+
+            return ArrayList<DecorProvider>().also { list ->
+                // We need to update displayInfo before using it, but it has already updated during
+                // accessing hasProviders field
+                displayInfo.displayCutout?.getBoundBaseOnCurrentRotation()?.let { bounds ->
+                    for (bound in bounds) {
+                        list.add(
+                            CutoutDecorProviderImpl(bound.baseOnRotation0(displayInfo.rotation))
+                        )
+                    }
+                }
+            }
+        }
+}
+
+private const val TAG = "CutoutDecorProviderFactory"
diff --git a/packages/SystemUI/src/com/android/systemui/decor/CutoutDecorProviderImpl.kt b/packages/SystemUI/src/com/android/systemui/decor/CutoutDecorProviderImpl.kt
new file mode 100644
index 0000000..991b54e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/decor/CutoutDecorProviderImpl.kt
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.decor
+
+import android.content.Context
+import android.view.DisplayCutout
+import android.view.Surface
+import android.view.View
+import android.view.ViewGroup
+import com.android.systemui.R
+import com.android.systemui.ScreenDecorations.DisplayCutoutView
+
+class CutoutDecorProviderImpl(
+    @DisplayCutout.BoundsPosition override val alignedBound: Int
+) : BoundDecorProvider() {
+
+    override val viewId: Int = when (alignedBound) {
+        DisplayCutout.BOUNDS_POSITION_TOP -> R.id.display_cutout
+        DisplayCutout.BOUNDS_POSITION_LEFT -> R.id.display_cutout_left
+        DisplayCutout.BOUNDS_POSITION_RIGHT -> R.id.display_cutout_right
+        else -> R.id.display_cutout_bottom
+    }
+
+    override fun inflateView(
+        context: Context,
+        parent: ViewGroup,
+        @Surface.Rotation rotation: Int,
+        tintColor: Int
+    ): View {
+        return DisplayCutoutView(context, alignedBound).also { view ->
+            view.id = viewId
+            view.setColor(tintColor)
+            parent.addView(view)
+            view.updateRotation(rotation)
+        }
+    }
+
+    override fun onReloadResAndMeasure(
+        view: View,
+        reloadToken: Int,
+        @Surface.Rotation rotation: Int,
+        tintColor: Int,
+        displayUniqueId: String?
+    ) {
+        (view as? DisplayCutoutView)?.let { cutoutView ->
+            cutoutView.setColor(tintColor)
+            cutoutView.updateRotation(rotation)
+            cutoutView.onDisplayChanged(displayUniqueId)
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/decor/DecorProvider.kt b/packages/SystemUI/src/com/android/systemui/decor/DecorProvider.kt
index 169b50e..0681f50 100644
--- a/packages/SystemUI/src/com/android/systemui/decor/DecorProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/decor/DecorProvider.kt
@@ -32,8 +32,8 @@
     abstract val viewId: Int
 
     /** The number of total aligned bounds */
-    val numOfAlignedEdge: Int
-    get() = alignedBounds.size
+    val numOfAlignedBound: Int
+        get() = alignedBounds.size
 
     /** The aligned bounds for the view which is created through inflateView() */
     abstract val alignedBounds: List<Int>
@@ -46,25 +46,19 @@
         view: View,
         reloadToken: Int,
         @Surface.Rotation rotation: Int,
-        displayUniqueId: String? = null
+        tintColor: Int,
+        displayUniqueId: String?
     )
 
     /** Inflate view into parent as current rotation */
     abstract fun inflateView(
         context: Context,
         parent: ViewGroup,
-        @Surface.Rotation rotation: Int
+        @Surface.Rotation rotation: Int,
+        tintColor: Int
     ): View
-}
 
-/**
- * Split list to 2 list, and return it back as Pair<>. The providers on the first list contains this
- * alignedBound element. The providers on the second list do not contain this alignedBound element
- */
-fun List<DecorProvider>.partitionAlignedBound(
-    @DisplayCutout.BoundsPosition alignedBound: Int
-): Pair<List<DecorProvider>, List<DecorProvider>> {
-    return partition { it.alignedBounds.contains(alignedBound) }
+    override fun toString() = "${javaClass.simpleName}{alignedBounds=$alignedBounds}"
 }
 
 /**
@@ -92,3 +86,61 @@
         listOf(alignedBound)
     }
 }
+
+/**
+ * Split list to 2 sub-lists, and return it back as Pair<>. The providers on the first list contains
+ * this alignedBound element. The providers on the second list do not contain this alignedBound
+ * element.
+ */
+fun List<DecorProvider>.partitionAlignedBound(
+    @DisplayCutout.BoundsPosition alignedBound: Int
+): Pair<List<DecorProvider>, List<DecorProvider>> {
+    return partition { it.alignedBounds.contains(alignedBound) }
+}
+
+/**
+ * Get the proper bound from DecorProvider list
+ * Time complexity: O(N), N is the number of providers
+ *
+ * Choose order
+ * 1. Return null if list is empty
+ * 2. If list contains BoundDecorProvider, return its alignedBound[0] because it is a must-have
+ *    bound
+ * 3. Return the bound with most DecorProviders
+ */
+fun List<DecorProvider>.getProperBound(): Int? {
+    // Return null if list is empty
+    if (isEmpty()) {
+        return null
+    }
+
+    // Choose alignedBounds[0] of BoundDecorProvider if any
+    val singleBoundProvider = firstOrNull { it.numOfAlignedBound == 1 }
+    if (singleBoundProvider != null) {
+        return singleBoundProvider.alignedBounds[0]
+    }
+
+    // Return the bound with most DecorProviders
+    val boundCount = intArrayOf(0, 0, 0, 0)
+    for (provider in this) {
+        for (bound in provider.alignedBounds) {
+            boundCount[bound]++
+        }
+    }
+    var maxCount = 0
+    var maxCountBound: Int? = null
+    val bounds = arrayOf(
+        // Put top and bottom at first to get the highest priority to be chosen
+        DisplayCutout.BOUNDS_POSITION_TOP,
+        DisplayCutout.BOUNDS_POSITION_BOTTOM,
+        DisplayCutout.BOUNDS_POSITION_LEFT,
+        DisplayCutout.BOUNDS_POSITION_RIGHT
+    )
+    for (bound in bounds) {
+        if (boundCount[bound] > maxCount) {
+            maxCountBound = bound
+            maxCount = boundCount[bound]
+        }
+    }
+    return maxCountBound
+}
diff --git a/packages/SystemUI/src/com/android/systemui/decor/FaceScanningProviderFactory.kt b/packages/SystemUI/src/com/android/systemui/decor/FaceScanningProviderFactory.kt
index 81d3d6c..5925c57 100644
--- a/packages/SystemUI/src/com/android/systemui/decor/FaceScanningProviderFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/decor/FaceScanningProviderFactory.kt
@@ -115,19 +115,25 @@
     override fun onReloadResAndMeasure(
         view: View,
         reloadToken: Int,
-        rotation: Int,
+        @Surface.Rotation rotation: Int,
+        tintColor: Int,
         displayUniqueId: String?
     ) {
         (view.layoutParams as FrameLayout.LayoutParams).let {
             updateLayoutParams(it, rotation)
             view.layoutParams = it
+            (view as? FaceScanningOverlay)?.let { overlay ->
+                overlay.setColor(tintColor)
+                overlay.onDisplayChanged(displayUniqueId)
+            }
         }
     }
 
     override fun inflateView(
         context: Context,
         parent: ViewGroup,
-        @Surface.Rotation rotation: Int
+        @Surface.Rotation rotation: Int,
+        tintColor: Int
     ): View {
         val view = FaceScanningOverlay(
                 context,
@@ -137,6 +143,7 @@
                 mainExecutor
         )
         view.id = viewId
+        view.setColor(tintColor)
         FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                 ViewGroup.LayoutParams.MATCH_PARENT).let {
             updateLayoutParams(it, rotation)
diff --git a/packages/SystemUI/src/com/android/systemui/decor/OverlayWindow.kt b/packages/SystemUI/src/com/android/systemui/decor/OverlayWindow.kt
index 3c0748e..45b8a08 100644
--- a/packages/SystemUI/src/com/android/systemui/decor/OverlayWindow.kt
+++ b/packages/SystemUI/src/com/android/systemui/decor/OverlayWindow.kt
@@ -34,9 +34,10 @@
 
     fun addDecorProvider(
         decorProvider: DecorProvider,
-        @Surface.Rotation rotation: Int
+        @Surface.Rotation rotation: Int,
+        tintColor: Int
     ) {
-        val view = decorProvider.inflateView(context, rootView, rotation)
+        val view = decorProvider.inflateView(context, rootView, rotation, tintColor)
         viewProviderMap[decorProvider.viewId] = Pair(view, decorProvider)
     }
 
@@ -69,7 +70,7 @@
      */
     fun hasSameProviders(newProviders: List<DecorProvider>): Boolean {
         return (newProviders.size == viewProviderMap.size) &&
-                newProviders.all { getView(it.viewId) != null }
+            newProviders.all { getView(it.viewId) != null }
     }
 
     /**
@@ -82,23 +83,28 @@
         filterIds: Array<Int>? = null,
         reloadToken: Int,
         @Surface.Rotation rotation: Int,
+        tintColor: Int,
         displayUniqueId: String? = null
     ) {
         filterIds?.forEach { id ->
             viewProviderMap[id]?.let {
                 it.second.onReloadResAndMeasure(
-                        view = it.first,
-                        reloadToken = reloadToken,
-                        displayUniqueId = displayUniqueId,
-                        rotation = rotation)
+                    view = it.first,
+                    reloadToken = reloadToken,
+                    rotation = rotation,
+                    tintColor = tintColor,
+                    displayUniqueId = displayUniqueId
+                )
             }
         } ?: run {
             viewProviderMap.values.forEach {
                 it.second.onReloadResAndMeasure(
-                        view = it.first,
-                        reloadToken = reloadToken,
-                        displayUniqueId = displayUniqueId,
-                        rotation = rotation)
+                    view = it.first,
+                    reloadToken = reloadToken,
+                    rotation = rotation,
+                    tintColor = tintColor,
+                    displayUniqueId = displayUniqueId
+                )
             }
         }
     }
@@ -108,7 +114,8 @@
         pw.println("    rootView=$rootView")
         for (i in 0 until rootView.childCount) {
             val child = rootView.getChildAt(i)
-            pw.println("    child[$i]=$child")
+            val provider = viewProviderMap[child.id]?.second
+            pw.println("    child[$i]=$child $provider")
         }
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/decor/PrivacyDotDecorProviderFactory.kt b/packages/SystemUI/src/com/android/systemui/decor/PrivacyDotDecorProviderFactory.kt
index 9f624b3..e18c0e1 100644
--- a/packages/SystemUI/src/com/android/systemui/decor/PrivacyDotDecorProviderFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/decor/PrivacyDotDecorProviderFactory.kt
@@ -20,9 +20,9 @@
 import android.content.res.Resources
 import android.view.DisplayCutout
 import android.view.LayoutInflater
+import android.view.Surface
 import android.view.View
 import android.view.ViewGroup
-import android.view.Surface
 import com.android.systemui.R
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Main
@@ -85,6 +85,7 @@
         view: View,
         reloadToken: Int,
         rotation: Int,
+        tintColor: Int,
         displayUniqueId: String?
     ) {
         // Do nothing here because it is handled inside PrivacyDotViewController
@@ -93,7 +94,8 @@
     override fun inflateView(
         context: Context,
         parent: ViewGroup,
-        @Surface.Rotation rotation: Int
+        @Surface.Rotation rotation: Int,
+        tintColor: Int
     ): View {
         LayoutInflater.from(context).inflate(layoutId, parent, true)
         return parent.getChildAt(parent.childCount - 1 /* latest new added child */)
diff --git a/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerDecorProviderImpl.kt b/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerDecorProviderImpl.kt
index e316722..8156797 100644
--- a/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerDecorProviderImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerDecorProviderImpl.kt
@@ -17,6 +17,7 @@
 package com.android.systemui.decor
 
 import android.content.Context
+import android.content.res.ColorStateList
 import android.view.DisplayCutout
 import android.view.Gravity
 import android.view.Surface
@@ -38,12 +39,13 @@
     override fun inflateView(
         context: Context,
         parent: ViewGroup,
-        @Surface.Rotation rotation: Int
+        @Surface.Rotation rotation: Int,
+        tintColor: Int
     ): View {
         return ImageView(context).also { view ->
             // View
             view.id = viewId
-            initView(view, rotation)
+            initView(view, rotation, tintColor)
 
             // LayoutParams
             val layoutSize = if (isTop) {
@@ -52,31 +54,36 @@
                 roundedCornerResDelegate.bottomRoundedSize
             }
             val params = FrameLayout.LayoutParams(
-                    layoutSize.width,
-                    layoutSize.height,
-                    alignedBound1.toLayoutGravity(rotation) or
-                            alignedBound2.toLayoutGravity(rotation))
+                layoutSize.width,
+                layoutSize.height,
+                alignedBound1.toLayoutGravity(rotation) or alignedBound2.toLayoutGravity(rotation)
+            )
 
             // AddView
             parent.addView(view, params)
         }
     }
 
-    private fun initView(view: ImageView, @Surface.Rotation rotation: Int) {
+    private fun initView(
+        view: ImageView,
+        @Surface.Rotation rotation: Int,
+        tintColor: Int
+    ) {
         view.setRoundedCornerImage(roundedCornerResDelegate, isTop)
         view.adjustRotation(alignedBounds, rotation)
-        view.imageTintList = roundedCornerResDelegate.colorTintList
+        view.imageTintList = ColorStateList.valueOf(tintColor)
     }
 
     override fun onReloadResAndMeasure(
         view: View,
         reloadToken: Int,
         @Surface.Rotation rotation: Int,
+        tintColor: Int,
         displayUniqueId: String?
     ) {
         roundedCornerResDelegate.updateDisplayUniqueId(displayUniqueId, reloadToken)
 
-        initView((view as ImageView), rotation)
+        initView((view as ImageView), rotation, tintColor)
 
         val layoutSize = if (isTop) {
             roundedCornerResDelegate.topRoundedSize
@@ -87,7 +94,7 @@
             it.width = layoutSize.width
             it.height = layoutSize.height
             it.gravity = alignedBound1.toLayoutGravity(rotation) or
-                    alignedBound2.toLayoutGravity(rotation)
+                alignedBound2.toLayoutGravity(rotation)
             view.setLayoutParams(it)
         }
     }
@@ -134,10 +141,10 @@
         setImageDrawable(drawable)
     } else {
         setImageResource(
-                if (isTop)
-                    R.drawable.rounded_corner_top
-                else
-                    R.drawable.rounded_corner_bottom
+            if (isTop)
+                R.drawable.rounded_corner_top
+            else
+                R.drawable.rounded_corner_bottom
         )
     }
 }
@@ -187,4 +194,4 @@
     this.rotation = newRotation
     this.scaleX = newScaleX
     this.scaleY = newScaleY
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt b/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt
index b5a0cfc..a252864 100644
--- a/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt
+++ b/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt
@@ -18,9 +18,7 @@
 
 import android.annotation.ArrayRes
 import android.annotation.DrawableRes
-import android.content.res.ColorStateList
 import android.content.res.Resources
-import android.graphics.Color
 import android.graphics.drawable.Drawable
 import android.util.DisplayUtils
 import android.util.Size
@@ -57,8 +55,6 @@
     var bottomRoundedSize = Size(0, 0)
         private set
 
-    var colorTintList = ColorStateList.valueOf(Color.BLACK)
-
     var tuningSizeFactor: Int? = null
         set(value) {
             if (field == value) {
@@ -107,19 +103,19 @@
 
         val hasDefaultRadius = RoundedCorners.getRoundedCornerRadius(res, displayUniqueId) > 0
         hasTop = hasDefaultRadius ||
-                (RoundedCorners.getRoundedCornerTopRadius(res, displayUniqueId) > 0)
+            (RoundedCorners.getRoundedCornerTopRadius(res, displayUniqueId) > 0)
         hasBottom = hasDefaultRadius ||
-                (RoundedCorners.getRoundedCornerBottomRadius(res, displayUniqueId) > 0)
+            (RoundedCorners.getRoundedCornerBottomRadius(res, displayUniqueId) > 0)
 
         topRoundedDrawable = getDrawable(
-                displayConfigIndex = configIdx,
-                arrayResId = R.array.config_roundedCornerTopDrawableArray,
-                backupDrawableId = R.drawable.rounded_corner_top
+            displayConfigIndex = configIdx,
+            arrayResId = R.array.config_roundedCornerTopDrawableArray,
+            backupDrawableId = R.drawable.rounded_corner_top
         )
         bottomRoundedDrawable = getDrawable(
-                displayConfigIndex = configIdx,
-                arrayResId = R.array.config_roundedCornerBottomDrawableArray,
-                backupDrawableId = R.drawable.rounded_corner_bottom
+            displayConfigIndex = configIdx,
+            arrayResId = R.array.config_roundedCornerBottomDrawableArray,
+            backupDrawableId = R.drawable.rounded_corner_bottom
         )
     }
 
@@ -147,13 +143,15 @@
         if (physicalPixelDisplaySizeRatio != 1f) {
             if (topRoundedSize.width != 0) {
                 topRoundedSize = Size(
-                        (physicalPixelDisplaySizeRatio * topRoundedSize.width + 0.5f).toInt(),
-                        (physicalPixelDisplaySizeRatio * topRoundedSize.height + 0.5f).toInt())
+                    (physicalPixelDisplaySizeRatio * topRoundedSize.width + 0.5f).toInt(),
+                    (physicalPixelDisplaySizeRatio * topRoundedSize.height + 0.5f).toInt()
+                )
             }
             if (bottomRoundedSize.width != 0) {
                 bottomRoundedSize = Size(
-                        (physicalPixelDisplaySizeRatio * bottomRoundedSize.width + 0.5f).toInt(),
-                        (physicalPixelDisplaySizeRatio * bottomRoundedSize.height + 0.5f).toInt())
+                    (physicalPixelDisplaySizeRatio * bottomRoundedSize.width + 0.5f).toInt(),
+                    (physicalPixelDisplaySizeRatio * bottomRoundedSize.height + 0.5f).toInt()
+                )
             }
         }
     }
@@ -180,8 +178,9 @@
         pw.println("  hasTop=$hasTop")
         pw.println("  hasBottom=$hasBottom")
         pw.println("  topRoundedSize(w,h)=(${topRoundedSize.width},${topRoundedSize.height})")
-        pw.println("  bottomRoundedSize(w,h)=(${bottomRoundedSize.width}," +
-                "${bottomRoundedSize.height})")
+        pw.println(
+            "  bottomRoundedSize(w,h)=(${bottomRoundedSize.width},${bottomRoundedSize.height})"
+        )
         pw.println("  physicalPixelDisplaySizeRatio=$physicalPixelDisplaySizeRatio")
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/SmartSpaceComplication.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/SmartSpaceComplication.java
index 567bdbc..a981f25 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/SmartSpaceComplication.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/SmartSpaceComplication.java
@@ -70,11 +70,7 @@
                 new BcSmartspaceDataPlugin.SmartspaceTargetListener() {
             @Override
             public void onSmartspaceTargetsUpdated(List<? extends Parcelable> targets) {
-                if (!targets.isEmpty()) {
-                    mDreamOverlayStateController.addComplication(mComplication);
-                } else {
-                    mDreamOverlayStateController.removeComplication(mComplication);
-                }
+                mDreamOverlayStateController.addComplication(mComplication);
             }
         };
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
index 9e2b7c7..a3dc779 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
@@ -50,7 +50,6 @@
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
 import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
 import com.android.systemui.CoreStartable;
-import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.dagger.SysUISingleton;
 
@@ -61,6 +60,7 @@
 import java.util.Set;
 
 import javax.inject.Inject;
+import javax.inject.Provider;
 
 /** */
 @SysUISingleton
@@ -106,6 +106,8 @@
 
     protected volatile Context mContext;
 
+    private final Provider<LocalBluetoothManager> mBluetoothManagerProvider;
+
     private boolean mEnabled;
     private String mKeyboardName;
     private CachedBluetoothDeviceManager mCachedDeviceManager;
@@ -122,8 +124,9 @@
     private int mState;
 
     @Inject
-    public KeyboardUI(Context context) {
+    public KeyboardUI(Context context, Provider<LocalBluetoothManager> bluetoothManagerProvider) {
         super(context);
+        this.mBluetoothManagerProvider = bluetoothManagerProvider;
     }
 
     @Override
@@ -181,7 +184,7 @@
             return;
         }
 
-        LocalBluetoothManager bluetoothManager = Dependency.get(LocalBluetoothManager.class);
+        LocalBluetoothManager bluetoothManager = mBluetoothManagerProvider.get();
         if (bluetoothManager == null)  {
             if (DEBUG) {
                 Slog.e(TAG, "Failed to retrieve LocalBluetoothManager instance");
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
index bec130b..e08e338 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
@@ -356,15 +356,6 @@
             mHeaderSubtitle.setText(subTitle);
             mHeaderTitle.setGravity(Gravity.NO_GRAVITY);
         }
-        if (!mAdapter.isDragging()) {
-            int currentActivePosition = mAdapter.getCurrentActivePosition();
-            if (!colorSetUpdated && !deviceSetChanged && currentActivePosition >= 0
-                    && currentActivePosition < mAdapter.getItemCount()) {
-                mAdapter.notifyItemChanged(currentActivePosition);
-            } else {
-                mAdapter.notifyDataSetChanged();
-            }
-        }
         // Show when remote media session is available or
         //      when the device supports BT LE audio + media is playing
         mStopButton.setVisibility(getStopButtonVisibility());
@@ -374,6 +365,18 @@
 
         mBroadcastIcon.setVisibility(getBroadcastIconVisibility());
         mBroadcastIcon.setOnClickListener(v -> onBroadcastIconClick());
+        if (!mAdapter.isDragging()) {
+            int currentActivePosition = mAdapter.getCurrentActivePosition();
+            if (!colorSetUpdated && !deviceSetChanged && currentActivePosition >= 0
+                    && currentActivePosition < mAdapter.getItemCount()) {
+                mAdapter.notifyItemChanged(currentActivePosition);
+            } else {
+                mAdapter.notifyDataSetChanged();
+            }
+        } else {
+            mMediaOutputController.setRefreshing(false);
+            mMediaOutputController.refreshDataSetIfNeeded();
+        }
     }
 
     private void updateButtonBackgroundColorFilter() {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelView.java
index 9818af3..1cdacb9 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelView.java
@@ -17,32 +17,30 @@
 package com.android.systemui.shade;
 
 import android.content.Context;
+import android.content.res.Configuration;
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Paint;
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffXfermode;
 import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.widget.FrameLayout;
 
 import com.android.systemui.R;
 import com.android.systemui.statusbar.phone.TapAgainView;
 
-public class NotificationPanelView extends PanelView {
+/** The shade view. */
+public final class NotificationPanelView extends FrameLayout {
+    static final boolean DEBUG = false;
 
-    private static final boolean DEBUG = false;
-
-    /**
-     * Fling expanding QS.
-     */
-    public static final int FLING_EXPAND = 0;
-
-    public static final String COUNTER_PANEL_OPEN = "panel_open";
-    public static final String COUNTER_PANEL_OPEN_QS = "panel_open_qs";
+    private final Paint mAlphaPaint = new Paint();
 
     private int mCurrentPanelAlpha;
-    private final Paint mAlphaPaint = new Paint();
     private boolean mDozing;
     private RtlChangeListener mRtlChangeListener;
+    private NotificationPanelViewController.TouchHandler mTouchHandler;
+    private OnConfigurationChangedListener mOnConfigurationChangedListener;
 
     public NotificationPanelView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -99,7 +97,36 @@
         return findViewById(R.id.shade_falsing_tap_again);
     }
 
+    /** Sets the touch handler for this view. */
+    public void setOnTouchListener(NotificationPanelViewController.TouchHandler touchHandler) {
+        super.setOnTouchListener(touchHandler);
+        mTouchHandler = touchHandler;
+    }
+
+    void setOnConfigurationChangedListener(OnConfigurationChangedListener listener) {
+        mOnConfigurationChangedListener = listener;
+    }
+
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent event) {
+        return mTouchHandler.onInterceptTouchEvent(event);
+    }
+
+    @Override
+    public void dispatchConfigurationChanged(Configuration newConfig) {
+        super.dispatchConfigurationChanged(newConfig);
+        mOnConfigurationChangedListener.onConfigurationChanged(newConfig);
+    }
+
+    /** Callback for right-to-left setting changes. */
     interface RtlChangeListener {
+        /** Called when right-to-left setting changes. */
         void onRtlPropertielsChanged(int layoutDirection);
     }
+
+    /** Callback for config changes. */
+    interface OnConfigurationChangedListener {
+        /** Called when configuration changes. */
+        void onConfigurationChanged(Configuration newConfig);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index 3b7c7ce..efdeba5 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -33,7 +33,7 @@
 import static com.android.systemui.classifier.Classifier.QS_COLLAPSE;
 import static com.android.systemui.classifier.Classifier.QUICK_SETTINGS;
 import static com.android.systemui.classifier.Classifier.UNLOCK;
-import static com.android.systemui.shade.PanelView.DEBUG;
+import static com.android.systemui.shade.NotificationPanelView.DEBUG;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
 import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
@@ -248,7 +248,7 @@
 
 @CentralSurfacesComponent.CentralSurfacesScope
 public final class NotificationPanelViewController {
-    public static final String TAG = PanelView.class.getSimpleName();
+    public static final String TAG = "PanelView";
     public static final float FLING_MAX_LENGTH_SECONDS = 0.6f;
     public static final float FLING_SPEED_UP_FACTOR = 0.6f;
     public static final float FLING_CLOSING_MAX_LENGTH_SECONDS = 0.6f;
@@ -274,7 +274,7 @@
     /**
      * Fling expanding QS.
      */
-    private static final int FLING_EXPAND = 0;
+    public static final int FLING_EXPAND = 0;
 
     /**
      * Fling collapsing QS, potentially stopping when QS becomes QQS.
@@ -435,7 +435,8 @@
     private boolean mQsTracking;
 
     /**
-     * If set, the ongoing touch gesture might both trigger the expansion in {@link PanelView} and
+     * If set, the ongoing touch gesture might both trigger the expansion in {@link
+     * NotificationPanelView} and
      * the expansion for quick settings.
      */
     private boolean mConflictingQsExpansionGesture;
@@ -5417,13 +5418,13 @@
         return animator;
     }
 
-    /** Update the visibility of {@link PanelView} if necessary. */
+    /** Update the visibility of {@link NotificationPanelView} if necessary. */
     public void updateVisibility() {
         mView.setVisibility(shouldPanelBeVisible() ? VISIBLE : INVISIBLE);
     }
 
     /**
-     * Updates the panel expansion and {@link PanelView} visibility if necessary.
+     * Updates the panel expansion and {@link NotificationPanelView} visibility if necessary.
      *
      * TODO(b/200063118): Could public calls to this method be replaced with calls to
      *   {@link #updateVisibility()}? That would allow us to make this method private.
@@ -6186,7 +6187,7 @@
     }
 
     public class OnConfigurationChangedListener implements
-            PanelView.OnConfigurationChangedListener {
+            NotificationPanelView.OnConfigurationChangedListener {
         @Override
         public void onConfigurationChanged(Configuration newConfig) {
             loadDimens();
diff --git a/packages/SystemUI/src/com/android/systemui/shade/PanelView.java b/packages/SystemUI/src/com/android/systemui/shade/PanelView.java
deleted file mode 100644
index 4349d81..0000000
--- a/packages/SystemUI/src/com/android/systemui/shade/PanelView.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.shade;
-
-import android.content.Context;
-import android.content.res.Configuration;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-import android.widget.FrameLayout;
-
-import com.android.systemui.statusbar.phone.CentralSurfaces;
-import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
-import com.android.systemui.statusbar.phone.KeyguardBottomAreaView;
-
-public abstract class PanelView extends FrameLayout {
-    public static final boolean DEBUG = false;
-    public static final String TAG = PanelView.class.getSimpleName();
-    private NotificationPanelViewController.TouchHandler mTouchHandler;
-
-    protected CentralSurfaces mCentralSurfaces;
-    protected HeadsUpManagerPhone mHeadsUpManager;
-
-    protected KeyguardBottomAreaView mKeyguardBottomArea;
-    private OnConfigurationChangedListener mOnConfigurationChangedListener;
-
-    public PanelView(Context context) {
-        super(context);
-    }
-
-    public PanelView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    public PanelView(Context context, AttributeSet attrs, int defStyleAttr) {
-        super(context, attrs, defStyleAttr);
-    }
-
-    public void setOnTouchListener(NotificationPanelViewController.TouchHandler touchHandler) {
-        super.setOnTouchListener(touchHandler);
-        mTouchHandler = touchHandler;
-    }
-
-    public void setOnConfigurationChangedListener(OnConfigurationChangedListener listener) {
-        mOnConfigurationChangedListener = listener;
-    }
-
-    @Override
-    public boolean onInterceptTouchEvent(MotionEvent event) {
-        return mTouchHandler.onInterceptTouchEvent(event);
-    }
-
-    @Override
-    public void dispatchConfigurationChanged(Configuration newConfig) {
-        super.dispatchConfigurationChanged(newConfig);
-        mOnConfigurationChangedListener.onConfigurationChanged(newConfig);
-    }
-
-    interface OnConfigurationChangedListener {
-        void onConfigurationChanged(Configuration newConfig);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/EmptyShadeView.java b/packages/SystemUI/src/com/android/systemui/statusbar/EmptyShadeView.java
index b9684fc..3d161d9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/EmptyShadeView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/EmptyShadeView.java
@@ -24,6 +24,8 @@
 import android.view.View;
 import android.widget.TextView;
 
+import androidx.annotation.NonNull;
+
 import com.android.systemui.R;
 import com.android.systemui.statusbar.notification.row.StackScrollerDecorView;
 import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
@@ -73,6 +75,7 @@
     }
 
     @Override
+    @NonNull
     public ExpandableViewState createExpandableViewState() {
         return new EmptyShadeViewState();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInteractionTracker.kt b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInteractionTracker.kt
index 2ca1beb..7b49ecd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInteractionTracker.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInteractionTracker.kt
@@ -1,7 +1,6 @@
 package com.android.systemui.statusbar
 
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.statusbar.notification.NotificationEntryManager
 import com.android.systemui.statusbar.notification.collection.NotificationEntry
 import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
 import javax.inject.Inject
@@ -12,14 +11,12 @@
  */
 @SysUISingleton
 class NotificationInteractionTracker @Inject constructor(
-    private val clicker: NotificationClickNotifier,
-    private val entryManager: NotificationEntryManager
+    clicker: NotificationClickNotifier,
 ) : NotifCollectionListener, NotificationInteractionListener {
     private val interactions = mutableMapOf<String, Boolean>()
 
     init {
         clicker.addNotificationInteractionListener(this)
-        entryManager.addCollectionListener(this)
     }
 
     fun hasUserInteractedWith(key: String): Boolean {
@@ -38,5 +35,3 @@
         interactions[key] = true
     }
 }
-
-private const val TAG = "NotificationInteractionTracker"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 2214287..cea3deb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -29,6 +29,8 @@
 import android.view.animation.Interpolator;
 import android.view.animation.PathInterpolator;
 
+import androidx.annotation.NonNull;
+
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.policy.SystemBarUtils;
 import com.android.systemui.R;
@@ -153,6 +155,7 @@
     }
 
     @Override
+    @NonNull
     public ExpandableViewState createExpandableViewState() {
         return new ShelfState();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
index 8cb18a0..59022c0f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
@@ -50,7 +50,6 @@
 import com.android.internal.messages.nano.SystemMessageProto;
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
 import com.android.systemui.CoreStartable;
-import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.UiBackground;
@@ -76,20 +75,22 @@
     private final Executor mUiBgExecutor;
     private final ArraySet<Pair<String, Integer>> mCurrentNotifs = new ArraySet<>();
     private final CommandQueue mCommandQueue;
-    private KeyguardStateController mKeyguardStateController;
+    private final KeyguardStateController mKeyguardStateController;
 
     @Inject
-    public InstantAppNotifier(Context context, CommandQueue commandQueue,
-            @UiBackground Executor uiBgExecutor) {
+    public InstantAppNotifier(
+            Context context,
+            CommandQueue commandQueue,
+            @UiBackground Executor uiBgExecutor,
+            KeyguardStateController keyguardStateController) {
         super(context);
         mCommandQueue = commandQueue;
         mUiBgExecutor = uiBgExecutor;
+        mKeyguardStateController = keyguardStateController;
     }
 
     @Override
     public void start() {
-        mKeyguardStateController = Dependency.get(KeyguardStateController.class);
-
         // listen for user / profile change.
         try {
             ActivityManager.getService().registerUserSwitchObserver(mUserSwitchListener, TAG);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java
deleted file mode 100644
index c9c6f28..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.notification;
-
-import com.android.internal.statusbar.NotificationVisibility;
-import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
-
-import java.util.Objects;
-
-/**
- * Root controller for the list of notifications in the shade.
- *
- * TODO: Much of the code in NotificationPresenter should eventually move in here. It will proxy
- * domain-specific behavior (ARC, etc) to subcontrollers.
- */
-public class NotificationListController {
-    private final NotificationEntryManager mEntryManager;
-    private final NotificationListContainer mListContainer;
-    private final DeviceProvisionedController mDeviceProvisionedController;
-
-    public NotificationListController(
-            NotificationEntryManager entryManager,
-            NotificationListContainer listContainer,
-            DeviceProvisionedController deviceProvisionedController) {
-        mEntryManager = Objects.requireNonNull(entryManager);
-        mListContainer = Objects.requireNonNull(listContainer);
-        mDeviceProvisionedController = Objects.requireNonNull(deviceProvisionedController);
-    }
-
-    /**
-     * Causes the controller to register listeners on its dependencies. This method must be called
-     * before the controller is ready to perform its duties.
-     */
-    public void bind() {
-        mEntryManager.addNotificationEntryListener(mEntryListener);
-        mDeviceProvisionedController.addCallback(mDeviceProvisionedListener);
-    }
-
-    @SuppressWarnings("FieldCanBeLocal")
-    private final NotificationEntryListener mEntryListener = new NotificationEntryListener() {
-        @Override
-        public void onEntryRemoved(
-                NotificationEntry entry,
-                NotificationVisibility visibility,
-                boolean removedByUser,
-                int reason) {
-            mListContainer.cleanUpViewStateForEntry(entry);
-        }
-    };
-
-    // TODO: (b/145659174) remove after moving to NewNotifPipeline. Replaced by
-    //  DeviceProvisionedCoordinator
-    private final DeviceProvisionedListener mDeviceProvisionedListener =
-            new DeviceProvisionedListener() {
-                @Override
-                public void onDeviceProvisionedChanged() {
-                    mEntryManager.updateNotifications("device provisioned changed");
-                }
-            };
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
index dbf4810..126a986 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
@@ -18,10 +18,8 @@
 
 import android.animation.ObjectAnimator
 import android.util.FloatProperty
-import com.android.systemui.Dumpable
 import com.android.systemui.animation.Interpolators
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dump.DumpManager
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.statusbar.StatusBarState
 import com.android.systemui.statusbar.notification.collection.NotificationEntry
@@ -34,20 +32,17 @@
 import com.android.systemui.statusbar.phone.panelstate.PanelExpansionListener
 import com.android.systemui.statusbar.policy.HeadsUpManager
 import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener
-import java.io.PrintWriter
 import javax.inject.Inject
 import kotlin.math.min
 
 @SysUISingleton
 class NotificationWakeUpCoordinator @Inject constructor(
-    dumpManager: DumpManager,
     private val mHeadsUpManager: HeadsUpManager,
     private val statusBarStateController: StatusBarStateController,
     private val bypassController: KeyguardBypassController,
     private val dozeParameters: DozeParameters,
     private val screenOffAnimationController: ScreenOffAnimationController
-) : OnHeadsUpChangedListener, StatusBarStateController.StateListener, PanelExpansionListener,
-    Dumpable {
+) : OnHeadsUpChangedListener, StatusBarStateController.StateListener, PanelExpansionListener {
 
     private val mNotificationVisibility = object : FloatProperty<NotificationWakeUpCoordinator>(
         "notificationVisibility") {
@@ -65,7 +60,6 @@
 
     private var mLinearDozeAmount: Float = 0.0f
     private var mDozeAmount: Float = 0.0f
-    private var mDozeAmountSource: String = "init"
     private var mNotificationVisibleAmount = 0.0f
     private var mNotificationsVisible = false
     private var mNotificationsVisibleForExpansion = false
@@ -148,7 +142,6 @@
         }
 
     init {
-        dumpManager.registerDumpable(this)
         mHeadsUpManager.addListener(this)
         statusBarStateController.addCallback(this)
         addListener(object : WakeUpListener {
@@ -255,14 +248,13 @@
             // Let's notify the scroller that an animation started
             notifyAnimationStart(mLinearDozeAmount == 1.0f)
         }
-        setDozeAmount(linear, eased, source = "StatusBar")
+        setDozeAmount(linear, eased)
     }
 
-    fun setDozeAmount(linear: Float, eased: Float, source: String) {
+    fun setDozeAmount(linear: Float, eased: Float) {
         val changed = linear != mLinearDozeAmount
         mLinearDozeAmount = linear
         mDozeAmount = eased
-        mDozeAmountSource = source
         mStackScrollerController.setDozeAmount(mDozeAmount)
         updateHideAmount()
         if (changed && linear == 0.0f) {
@@ -279,7 +271,7 @@
             // undefined state, so it's an indication that we should do state cleanup. We override
             // the doze amount to 0f (not dozing) so that the notifications are no longer hidden.
             // See: UnlockedScreenOffAnimationController.onFinishedWakingUp()
-            setDozeAmount(0f, 0f, source = "Override: Shade->Shade (lock cancelled by unlock)")
+            setDozeAmount(0f, 0f)
         }
 
         if (overrideDozeAmountIfAnimatingScreenOff(mLinearDozeAmount)) {
@@ -319,11 +311,12 @@
      */
     private fun overrideDozeAmountIfBypass(): Boolean {
         if (bypassController.bypassEnabled) {
-            if (statusBarStateController.state == StatusBarState.KEYGUARD) {
-                setDozeAmount(1f, 1f, source = "Override: bypass (keyguard)")
-            } else {
-                setDozeAmount(0f, 0f, source = "Override: bypass (shade)")
+            var amount = 1.0f
+            if (statusBarStateController.state == StatusBarState.SHADE ||
+                statusBarStateController.state == StatusBarState.SHADE_LOCKED) {
+                amount = 0.0f
             }
+            setDozeAmount(amount, amount)
             return true
         }
         return false
@@ -339,7 +332,7 @@
      */
     private fun overrideDozeAmountIfAnimatingScreenOff(linearDozeAmount: Float): Boolean {
         if (screenOffAnimationController.overrideNotificationsFullyDozingOnKeyguard()) {
-            setDozeAmount(1f, 1f, source = "Override: animating screen off")
+            setDozeAmount(1f, 1f)
             return true
         }
 
@@ -433,24 +426,4 @@
          */
         @JvmDefault fun onPulseExpansionChanged(expandingChanged: Boolean) {}
     }
-
-    override fun dump(pw: PrintWriter, args: Array<out String>) {
-        pw.println("mLinearDozeAmount: $mLinearDozeAmount")
-        pw.println("mDozeAmount: $mDozeAmount")
-        pw.println("mDozeAmountSource: $mDozeAmountSource")
-        pw.println("mNotificationVisibleAmount: $mNotificationVisibleAmount")
-        pw.println("mNotificationsVisible: $mNotificationsVisible")
-        pw.println("mNotificationsVisibleForExpansion: $mNotificationsVisibleForExpansion")
-        pw.println("mVisibilityAmount: $mVisibilityAmount")
-        pw.println("mLinearVisibilityAmount: $mLinearVisibilityAmount")
-        pw.println("pulseExpanding: $pulseExpanding")
-        pw.println("state: ${StatusBarState.toString(state)}")
-        pw.println("fullyAwake: $fullyAwake")
-        pw.println("wakingUp: $wakingUp")
-        pw.println("willWakeUp: $willWakeUp")
-        pw.println("collapsedEnoughToHide: $collapsedEnoughToHide")
-        pw.println("pulsing: $pulsing")
-        pw.println("notificationsFullyHidden: $notificationsFullyHidden")
-        pw.println("canShowPulsingHuns: $canShowPulsingHuns")
-    }
-}
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
index 0e9f1cd..d38b6f9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
@@ -26,19 +26,19 @@
 import com.android.systemui.statusbar.notification.NotificationActivityStarter
 import com.android.systemui.statusbar.notification.NotificationClicker
 import com.android.systemui.statusbar.notification.NotificationEntryManager
-import com.android.systemui.statusbar.notification.NotificationListController
 import com.android.systemui.statusbar.notification.collection.NotifLiveDataStore
 import com.android.systemui.statusbar.notification.collection.NotifPipeline
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
 import com.android.systemui.statusbar.notification.collection.TargetSdkResolver
 import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl
 import com.android.systemui.statusbar.notification.collection.init.NotifPipelineInitializer
 import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
 import com.android.systemui.statusbar.notification.collection.render.NotifStackController
 import com.android.systemui.statusbar.notification.interruption.HeadsUpViewBinder
 import com.android.systemui.statusbar.notification.row.NotifBindPipelineInitializer
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer
 import com.android.systemui.statusbar.phone.CentralSurfaces
-import com.android.systemui.statusbar.policy.DeviceProvisionedController
 import com.android.wm.shell.bubbles.Bubbles
 import dagger.Lazy
 import java.io.PrintWriter
@@ -63,7 +63,6 @@
     private val targetSdkResolver: TargetSdkResolver,
     private val notifPipelineInitializer: Lazy<NotifPipelineInitializer>,
     private val notifBindPipelineInitializer: NotifBindPipelineInitializer,
-    private val deviceProvisionedController: DeviceProvisionedController,
     private val notificationRowBinder: NotificationRowBinderImpl,
     private val headsUpViewBinder: HeadsUpViewBinder,
     private val clickerBuilder: NotificationClicker.Builder,
@@ -81,12 +80,11 @@
     ) {
         notificationListener.registerAsSystemService()
 
-        val listController =
-                NotificationListController(
-                        entryManager,
-                        listContainer,
-                        deviceProvisionedController)
-        listController.bind()
+        notifPipeline.get().addCollectionListener(object : NotifCollectionListener {
+            override fun onEntryRemoved(entry: NotificationEntry, reason: Int) {
+                listContainer.cleanUpViewStateForEntry(entry)
+            }
+        })
 
         notificationRowBinder.setNotificationClicker(
                 clickerBuilder.build(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 855390d..8574f87 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -25,8 +25,6 @@
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator.AnimatorUpdateListener;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.app.INotificationManager;
 import android.app.Notification;
 import android.app.NotificationChannel;
@@ -68,6 +66,9 @@
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -3247,6 +3248,7 @@
     }
 
     @Override
+    @NonNull
     public ExpandableViewState createExpandableViewState() {
         return new NotificationViewState();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
index 8f73b80..1e09b8a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
@@ -29,6 +29,7 @@
 import android.view.ViewParent;
 import android.widget.FrameLayout;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
 import com.android.systemui.Dumpable;
@@ -66,7 +67,7 @@
     protected float mContentTransformationAmount;
     protected boolean mIsLastChild;
     protected int mContentShift;
-    private final ExpandableViewState mViewState;
+    @NonNull private final ExpandableViewState mViewState;
     private float mContentTranslation;
     protected boolean mLastInSection;
     protected boolean mFirstInSection;
@@ -610,6 +611,7 @@
 
     public void setActualHeightAnimating(boolean animating) {}
 
+    @NonNull
     protected ExpandableViewState createExpandableViewState() {
         return new ExpandableViewState();
     }
@@ -642,7 +644,12 @@
         return mViewState;
     }
 
-    @Nullable public ExpandableViewState getViewState() {
+    /**
+     * Get the {@link ExpandableViewState} associated with the view.
+     *
+     * @return the ExpandableView's view state.
+     */
+    @NonNull public ExpandableViewState getViewState() {
         return mViewState;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java
index e43ecf7..49dc655 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java
@@ -23,6 +23,8 @@
 import android.util.IndentingPrintWriter;
 import android.view.View;
 
+import androidx.annotation.NonNull;
+
 import com.android.systemui.R;
 import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
 import com.android.systemui.statusbar.notification.stack.ViewState;
@@ -142,6 +144,7 @@
     }
 
     @Override
+    @NonNull
     public ExpandableViewState createExpandableViewState() {
         return new FooterViewState();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java
deleted file mode 100644
index 6abfee9..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar.notification.row;
-
-import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
-
-import android.content.Context;
-import android.metrics.LogMaker;
-import android.util.Log;
-
-import androidx.annotation.VisibleForTesting;
-
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
-import com.android.systemui.statusbar.notification.dagger.NotificationsModule;
-import com.android.systemui.statusbar.notification.logging.NotificationCounters;
-import com.android.systemui.util.Compile;
-
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * Manager for the notification blocking helper - tracks and helps create the blocking helper
- * affordance.
- */
-public class NotificationBlockingHelperManager {
-    /** Enables debug logging and always makes the blocking helper show up after a dismiss. */
-    private static final String TAG = "BlockingHelper";
-    private static final boolean DEBUG = Compile.IS_DEBUG && Log.isLoggable(TAG, Log.DEBUG);
-    private static final boolean DEBUG_ALWAYS_SHOW = false;
-
-    private final Context mContext;
-    private final NotificationGutsManager mNotificationGutsManager;
-    private final NotificationEntryManager mNotificationEntryManager;
-    private final MetricsLogger mMetricsLogger;
-    private final GroupMembershipManager mGroupMembershipManager;
-    /** Row that the blocking helper will be shown in (via {@link NotificationGuts}. */
-    private ExpandableNotificationRow mBlockingHelperRow;
-    private Set<String> mNonBlockablePkgs;
-
-    /**
-     * Whether the notification shade/stack is expanded - used to determine blocking helper
-     * eligibility.
-     */
-    private boolean mIsShadeExpanded;
-
-    /**
-     * Injected constructor. See {@link NotificationsModule}.
-     */
-    public NotificationBlockingHelperManager(
-            Context context,
-            NotificationGutsManager notificationGutsManager,
-            NotificationEntryManager notificationEntryManager,
-            MetricsLogger metricsLogger,
-            GroupMembershipManager groupMembershipManager) {
-        mContext = context;
-        mNotificationGutsManager = notificationGutsManager;
-        mNotificationEntryManager = notificationEntryManager;
-        mMetricsLogger = metricsLogger;
-        mNonBlockablePkgs = new HashSet<>();
-        Collections.addAll(mNonBlockablePkgs, mContext.getResources().getStringArray(
-                com.android.internal.R.array.config_nonBlockableNotificationPackages));
-        mGroupMembershipManager = groupMembershipManager;
-    }
-
-    /**
-     * Potentially shows the blocking helper, represented via the {@link NotificationInfo} menu
-     * item, in the current row if user sentiment is negative.
-     *
-     * @param row row to render the blocking helper in
-     * @param menuRow menu used to generate the {@link NotificationInfo} view that houses the
-     *                blocking helper UI
-     * @return whether we're showing a blocking helper in the given notification row
-     */
-    boolean perhapsShowBlockingHelper(
-            ExpandableNotificationRow row, NotificationMenuRowPlugin menuRow) {
-        // We only show the blocking helper if:
-        // - User sentiment is negative (DEBUG flag can bypass)
-        // - The notification shade is fully expanded (guarantees we're not touching a HUN).
-        // - The row is blockable (i.e. not non-blockable)
-        // - The dismissed row is a valid group (>1 or 0 children from the same channel)
-        // or the only child in the group
-        final NotificationEntry entry = row.getEntry();
-        if ((entry.getUserSentiment() == USER_SENTIMENT_NEGATIVE || DEBUG_ALWAYS_SHOW)
-                && mIsShadeExpanded
-                && !row.getIsNonblockable()
-                && ((!row.isChildInGroup() || mGroupMembershipManager.isOnlyChildInGroup(entry))
-                    && row.getNumUniqueChannels() <= 1)) {
-            // Dismiss any current blocking helper before continuing forward (only one can be shown
-            // at a given time).
-            dismissCurrentBlockingHelper();
-
-            if (DEBUG) {
-                Log.d(TAG, "Manager.perhapsShowBlockingHelper: Showing new blocking helper");
-            }
-
-            // Enable blocking helper on the row before moving forward so everything in the guts is
-            // correctly prepped.
-            mBlockingHelperRow = row;
-            mBlockingHelperRow.setBlockingHelperShowing(true);
-
-            // Log triggering of blocking helper by the system. This log line
-            // should be emitted before the "display" log line.
-            mMetricsLogger.write(
-                    getLogMaker().setSubtype(MetricsEvent.BLOCKING_HELPER_TRIGGERED_BY_SYSTEM));
-
-            // We don't care about the touch origin (x, y) since we're opening guts without any
-            // explicit user interaction.
-            mNotificationGutsManager.openGuts(
-                    mBlockingHelperRow, 0, 0, menuRow.getLongpressMenuItem(mContext));
-
-            mMetricsLogger.count(NotificationCounters.BLOCKING_HELPER_SHOWN, 1);
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Dismiss the currently showing blocking helper, if any, through a notification update.
-     *
-     * @return whether the blocking helper was dismissed
-     */
-    boolean dismissCurrentBlockingHelper() {
-        if (!isBlockingHelperRowNull()) {
-            if (DEBUG) {
-                Log.d(TAG, "Manager.dismissCurrentBlockingHelper: Dismissing current helper");
-            }
-            if (!mBlockingHelperRow.isBlockingHelperShowing()) {
-                Log.e(TAG, "Manager.dismissCurrentBlockingHelper: "
-                        + "Non-null row is not showing a blocking helper");
-            }
-
-            mBlockingHelperRow.setBlockingHelperShowing(false);
-            if (mBlockingHelperRow.isAttachedToWindow()) {
-                mNotificationEntryManager.updateNotifications("dismissCurrentBlockingHelper");
-            }
-            mBlockingHelperRow = null;
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Update the expansion status of the notification shade/stack.
-     *
-     * @param expandedHeight how much the shade is expanded ({code 0} indicating it's collapsed)
-     */
-    public void setNotificationShadeExpanded(float expandedHeight) {
-        mIsShadeExpanded = expandedHeight > 0.0f;
-    }
-
-    /**
-     * Returns whether the given package name is in the list of non-blockable packages.
-     */
-    public boolean isNonblockable(String packageName, String channelName) {
-        return mNonBlockablePkgs.contains(packageName)
-                || mNonBlockablePkgs.contains(makeChannelKey(packageName, channelName));
-    }
-
-    private LogMaker getLogMaker() {
-        return mBlockingHelperRow.getEntry().getSbn()
-            .getLogMaker()
-            .setCategory(MetricsEvent.NOTIFICATION_BLOCKING_HELPER);
-    }
-
-    // Format must stay in sync with frameworks/base/core/res/res/values/config.xml
-    // config_nonBlockableNotificationPackages
-    private String makeChannelKey(String pkg, String channel) {
-        return pkg + ":" + channel;
-    }
-
-    @VisibleForTesting
-    boolean isBlockingHelperRowNull() {
-        return mBlockingHelperRow == null;
-    }
-
-    @VisibleForTesting
-    void setBlockingHelperRowForTest(ExpandableNotificationRow blockingHelperRowForTest) {
-        mBlockingHelperRow = blockingHelperRowForTest;
-    }
-
-    @VisibleForTesting
-    void setNonBlockablePkgs(String[] pkgsAndChannels) {
-        mNonBlockablePkgs = new HashSet<>();
-        Collections.addAll(mNonBlockablePkgs, pkgsAndChannels);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index cc87499..1fb265f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -4460,8 +4460,7 @@
     }
 
     private void updateVisibility() {
-        boolean shouldShow = !mAmbientState.isFullyHidden() || !onKeyguard();
-        setVisibility(shouldShow ? View.VISIBLE : View.INVISIBLE);
+        mController.updateVisibility(!mAmbientState.isFullyHidden() || !onKeyguard());
     }
 
     @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
@@ -4526,17 +4525,21 @@
     }
 
     @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
-    void updateEmptyShadeView(boolean visible, boolean notifVisibleInShade) {
+    void updateEmptyShadeView(boolean visible, boolean areNotificationsHiddenInShade) {
         mEmptyShadeView.setVisible(visible, mIsExpanded && mAnimationsEnabled);
 
         int oldTextRes = mEmptyShadeView.getTextResource();
-        int newTextRes = notifVisibleInShade
+        int newTextRes = areNotificationsHiddenInShade
                 ? R.string.dnd_suppressing_shade_text : R.string.empty_shade_text;
         if (oldTextRes != newTextRes) {
             mEmptyShadeView.setText(newTextRes);
         }
     }
 
+    public boolean isEmptyShadeViewVisible() {
+        return mEmptyShadeView.isVisible();
+    }
+
     @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void updateFooterView(boolean visible, boolean showDismissView, boolean showHistory) {
         if (mFooterView == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index e6eceb5..ec1e620 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -177,7 +177,6 @@
     private NotificationStackScrollLayout mView;
     private boolean mFadeNotificationsOnDismiss;
     private NotificationSwipeHelper mSwipeHelper;
-    private boolean mShowEmptyShadeView;
     @Nullable private Boolean mHistoryEnabled;
     private int mBarState;
     private HeadsUpAppearanceController mHeadsUpAppearanceController;
@@ -1173,8 +1172,21 @@
     }
 
     /**
-     * Update whether we should show the empty shade view (no notifications in the shade).
-     * If so, send the update to our view.
+     * Set the visibility of the view, and propagate it to specific children.
+     *
+     * @param visible either the view is visible or not.
+     */
+    public void updateVisibility(boolean visible) {
+        mView.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
+
+        if (mView.getVisibility() == View.VISIBLE) {
+            // Synchronize EmptyShadeView visibility with the parent container.
+            updateShowEmptyShadeView();
+        }
+    }
+
+    /**
+     * Update whether we should show the empty shade view ("no notifications" in the shade).
      *
      * When in split mode, notifications are always visible regardless of the state of the
      * QuickSettings panel. That being the case, empty view is always shown if the other conditions
@@ -1182,18 +1194,31 @@
      */
     public void updateShowEmptyShadeView() {
         Trace.beginSection("NSSLC.updateShowEmptyShadeView");
-        mShowEmptyShadeView = mStatusBarStateController.getCurrentOrUpcomingState() != KEYGUARD
-                && !mView.isQsFullScreen()
-                && getVisibleNotificationCount() == 0;
 
-        mView.updateEmptyShadeView(
-                mShowEmptyShadeView,
-                mZenModeController.areNotificationsHiddenInShade());
+        final boolean shouldShow = getVisibleNotificationCount() == 0
+                && !mView.isQsFullScreen()
+                // Hide empty shade view when in transition to Keyguard.
+                // That avoids "No Notifications" to blink when transitioning to AOD.
+                // For more details, see: b/228790482
+                && !isInTransitionToKeyguard();
+
+        mView.updateEmptyShadeView(shouldShow, mZenModeController.areNotificationsHiddenInShade());
+
         Trace.endSection();
     }
 
+    /**
+     * @return true if {@link StatusBarStateController} is in transition to the KEYGUARD
+     *         and false otherwise.
+     */
+    private boolean isInTransitionToKeyguard() {
+        final int currentState = mStatusBarStateController.getState();
+        final int upcomingState = mStatusBarStateController.getCurrentOrUpcomingState();
+        return (currentState != upcomingState && upcomingState == KEYGUARD);
+    }
+
     public boolean isShowingEmptyShadeView() {
-        return mShowEmptyShadeView;
+        return mView.isEmptyShadeViewVisible();
     }
 
     public void setHeadsUpAnimatingAway(boolean headsUpAnimatingAway) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index 6d513d0da..353355b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -120,11 +120,64 @@
         updateClipping(algorithmState, ambientState);
         updateSpeedBumpState(algorithmState, speedBumpIndex);
         updateShelfState(algorithmState, ambientState);
+        updateAlphaState(algorithmState, ambientState);
         getNotificationChildrenStates(algorithmState, ambientState);
     }
 
+    private void updateAlphaState(StackScrollAlgorithmState algorithmState,
+            AmbientState ambientState) {
+        for (ExpandableView view : algorithmState.visibleChildren) {
+            final ViewState viewState = view.getViewState();
+
+            final boolean isHunGoingToShade = ambientState.isShadeExpanded()
+                    && view == ambientState.getTrackedHeadsUpRow();
+
+            if (isHunGoingToShade) {
+                // Keep 100% opacity for heads up notification going to shade.
+                viewState.alpha = 1f;
+            } else if (ambientState.isOnKeyguard()) {
+                // Adjust alpha for wakeup to lockscreen.
+                viewState.alpha = 1f - ambientState.getHideAmount();
+            } else if (ambientState.isExpansionChanging()) {
+                // Adjust alpha for shade open & close.
+                float expansion = ambientState.getExpansionFraction();
+                viewState.alpha = ambientState.isBouncerInTransit()
+                        ? BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(expansion)
+                        : ShadeInterpolation.getContentAlpha(expansion);
+            }
+
+            // For EmptyShadeView if on keyguard, we need to control the alpha to create
+            // a nice transition when the user is dragging down the notification panel.
+            if (view instanceof EmptyShadeView && ambientState.isOnKeyguard()) {
+                final float fractionToShade = ambientState.getFractionToShade();
+                viewState.alpha = ShadeInterpolation.getContentAlpha(fractionToShade);
+            }
+
+            NotificationShelf shelf = ambientState.getShelf();
+            if (shelf != null) {
+                final ViewState shelfState = shelf.getViewState();
+
+                // After the shelf has updated its yTranslation, explicitly set alpha=0 for view
+                // below shelf to skip rendering them in the hardware layer. We do not set them
+                // invisible because that runs invalidate & onDraw when these views return onscreen,
+                // which is more expensive.
+                if (shelfState.hidden) {
+                    // When the shelf is hidden, it won't clip views, so we don't hide rows
+                    return;
+                }
+
+                final float shelfTop = shelfState.yTranslation;
+                final float viewTop = viewState.yTranslation;
+                if (viewTop >= shelfTop) {
+                    viewState.alpha = 0;
+                }
+            }
+        }
+    }
+
     /**
      * How expanded or collapsed notifications are when pulling down the shade.
+     *
      * @param ambientState Current ambient state.
      * @return 0 when fully collapsed, 1 when expanded.
      */
@@ -208,22 +261,6 @@
         }
 
         shelf.updateState(algorithmState, ambientState);
-
-        // After the shelf has updated its yTranslation, explicitly set alpha=0 for view below shelf
-        // to skip rendering them in the hardware layer. We do not set them invisible because that
-        // runs invalidate & onDraw when these views return onscreen, which is more expensive.
-        if (shelf.getViewState().hidden) {
-            // When the shelf is hidden, it won't clip views, so we don't hide rows
-            return;
-        }
-        final float shelfTop = shelf.getViewState().yTranslation;
-
-        for (ExpandableView view : algorithmState.visibleChildren) {
-            final float viewTop = view.getViewState().yTranslation;
-            if (viewTop >= shelfTop) {
-                view.getViewState().alpha = 0;
-            }
-        }
     }
 
     private void updateClipping(StackScrollAlgorithmState algorithmState,
@@ -473,21 +510,6 @@
         ExpandableViewState viewState = view.getViewState();
         viewState.location = ExpandableViewState.LOCATION_UNKNOWN;
 
-        final boolean isHunGoingToShade = ambientState.isShadeExpanded()
-                && view == ambientState.getTrackedHeadsUpRow();
-        if (isHunGoingToShade) {
-            // Keep 100% opacity for heads up notification going to shade.
-        } else if (ambientState.isOnKeyguard()) {
-            // Adjust alpha for wakeup to lockscreen.
-            viewState.alpha = 1f - ambientState.getHideAmount();
-        } else if (ambientState.isExpansionChanging()) {
-            // Adjust alpha for shade open & close.
-            float expansion = ambientState.getExpansionFraction();
-            viewState.alpha = ambientState.isBouncerInTransit()
-                    ? BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(expansion)
-                    : ShadeInterpolation.getContentAlpha(expansion);
-        }
-
         final float expansionFraction = getExpansionFractionWithoutShelf(
                 algorithmState, ambientState);
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java
index 747c4de..52a45d6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java
@@ -55,7 +55,6 @@
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
 import com.android.systemui.qs.QSPanelController;
-import com.android.systemui.shade.NotificationPanelView;
 import com.android.systemui.shade.NotificationPanelViewController;
 import com.android.systemui.shade.ShadeController;
 import com.android.systemui.statusbar.CommandQueue;
@@ -326,12 +325,12 @@
                 mNotificationPanelViewController.expand(true /* animate */);
                 mNotificationStackScrollLayoutController.setWillExpand(true);
                 mHeadsUpManager.unpinAll(true /* userUnpinned */);
-                mMetricsLogger.count(NotificationPanelView.COUNTER_PANEL_OPEN, 1);
+                mMetricsLogger.count("panel_open", 1);
             } else if (!mNotificationPanelViewController.isInSettings()
                     && !mNotificationPanelViewController.isExpanding()) {
                 mNotificationPanelViewController.flingSettings(0 /* velocity */,
-                        NotificationPanelView.FLING_EXPAND);
-                mMetricsLogger.count(NotificationPanelView.COUNTER_PANEL_OPEN_QS, 1);
+                        NotificationPanelViewController.FLING_EXPAND);
+                mMetricsLogger.count("panel_open_qs", 1);
             }
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
index ed186ab..8273d57 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -33,7 +33,6 @@
 import androidx.annotation.VisibleForTesting;
 
 import com.android.internal.statusbar.StatusBarIcon;
-import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.demomode.DemoModeCommandReceiver;
@@ -137,11 +136,12 @@
                 LinearLayout linearLayout,
                 FeatureFlags featureFlags,
                 StatusBarPipelineFlags statusBarPipelineFlags,
-                Provider<WifiViewModel> wifiViewModelProvider) {
+                Provider<WifiViewModel> wifiViewModelProvider,
+                DarkIconDispatcher darkIconDispatcher) {
             super(linearLayout, featureFlags, statusBarPipelineFlags, wifiViewModelProvider);
             mIconHPadding = mContext.getResources().getDimensionPixelSize(
                     R.dimen.status_bar_icon_padding);
-            mDarkIconDispatcher = Dependency.get(DarkIconDispatcher.class);
+            mDarkIconDispatcher = darkIconDispatcher;
         }
 
         @Override
@@ -198,20 +198,24 @@
             private final FeatureFlags mFeatureFlags;
             private final StatusBarPipelineFlags mStatusBarPipelineFlags;
             private final Provider<WifiViewModel> mWifiViewModelProvider;
+            private final DarkIconDispatcher mDarkIconDispatcher;
 
             @Inject
             public Factory(
                     FeatureFlags featureFlags,
                     StatusBarPipelineFlags statusBarPipelineFlags,
-                    Provider<WifiViewModel> wifiViewModelProvider) {
+                    Provider<WifiViewModel> wifiViewModelProvider,
+                    DarkIconDispatcher darkIconDispatcher) {
                 mFeatureFlags = featureFlags;
                 mStatusBarPipelineFlags = statusBarPipelineFlags;
                 mWifiViewModelProvider = wifiViewModelProvider;
+                mDarkIconDispatcher = darkIconDispatcher;
             }
 
             public DarkIconManager create(LinearLayout group) {
                 return new DarkIconManager(
-                        group, mFeatureFlags, mStatusBarPipelineFlags, mWifiViewModelProvider);
+                        group, mFeatureFlags, mStatusBarPipelineFlags, mWifiViewModelProvider,
+                        mDarkIconDispatcher);
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt
index 7765427..103f3fc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt
@@ -46,7 +46,7 @@
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.flowOf
-import kotlinx.coroutines.flow.shareIn
+import kotlinx.coroutines.flow.stateIn
 
 /**
  * Provides data related to the wifi state.
@@ -118,12 +118,19 @@
             }
         }
 
-        trySend(WIFI_NETWORK_DEFAULT)
         connectivityManager.registerNetworkCallback(WIFI_NETWORK_CALLBACK_REQUEST, callback)
 
         awaitClose { connectivityManager.unregisterNetworkCallback(callback) }
     }
-        .shareIn(scope, started = SharingStarted.WhileSubscribed())
+        // There will be multiple wifi icons in different places that will frequently
+        // subscribe/unsubscribe to flows as the views attach/detach. Using [stateIn] ensures that
+        // new subscribes will get the latest value immediately upon subscription. Otherwise, the
+        // views could show stale data. See b/244173280.
+        .stateIn(
+            scope,
+            started = SharingStarted.WhileSubscribed(),
+            initialValue = WIFI_NETWORK_DEFAULT
+        )
 
     override val wifiActivity: Flow<WifiActivityModel> =
             if (wifiManager == null) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
index 90609fa..df10dfe 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
@@ -16,7 +16,6 @@
 
 import static android.view.DisplayCutout.BOUNDS_POSITION_BOTTOM;
 import static android.view.DisplayCutout.BOUNDS_POSITION_LEFT;
-import static android.view.DisplayCutout.BOUNDS_POSITION_LENGTH;
 import static android.view.DisplayCutout.BOUNDS_POSITION_RIGHT;
 import static android.view.DisplayCutout.BOUNDS_POSITION_TOP;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY;
@@ -36,6 +35,7 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.isA;
+import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
@@ -49,7 +49,6 @@
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.content.res.TypedArray;
-import android.graphics.Insets;
 import android.graphics.Path;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
@@ -60,7 +59,6 @@
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
-import android.util.RotationUtils;
 import android.util.Size;
 import android.view.Display;
 import android.view.DisplayCutout;
@@ -80,6 +78,8 @@
 import com.android.systemui.biometrics.AuthController;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.decor.CornerDecorProvider;
+import com.android.systemui.decor.CutoutDecorProviderFactory;
+import com.android.systemui.decor.CutoutDecorProviderImpl;
 import com.android.systemui.decor.DecorProvider;
 import com.android.systemui.decor.DecorProviderFactory;
 import com.android.systemui.decor.FaceScanningOverlayProviderImpl;
@@ -157,6 +157,9 @@
     @Mock
     private DisplayInfo mDisplayInfo;
     private PrivacyDotViewController.ShowingListener mPrivacyDotShowingListener;
+    @Mock
+    private CutoutDecorProviderFactory mCutoutFactory;
+    private List<DecorProvider> mMockCutoutList;
 
     @Before
     public void setup() {
@@ -206,6 +209,11 @@
                 DisplayCutout.BOUNDS_POSITION_RIGHT,
                 R.layout.privacy_dot_bottom_right));
 
+        // Default no cutout
+        mMockCutoutList = new ArrayList<>();
+        doAnswer(it -> !(mMockCutoutList.isEmpty())).when(mCutoutFactory).getHasProviders();
+        doReturn(mMockCutoutList).when(mCutoutFactory).getProviders();
+
         mFaceScanningDecorProvider = spy(new FaceScanningOverlayProviderImpl(
                 BOUNDS_POSITION_TOP,
                 mAuthController,
@@ -239,6 +247,11 @@
                 super.updateOverlayWindowVisibilityIfViewExists(view);
                 mExecutor.runAllReady();
             }
+
+            @Override
+            protected CutoutDecorProviderFactory getCutoutFactory() {
+                return ScreenDecorationsTest.this.mCutoutFactory;
+            }
         });
         mScreenDecorations.mDisplayInfo = mDisplayInfo;
         doReturn(1f).when(mScreenDecorations).getPhysicalPixelDisplaySizeRatio();
@@ -429,11 +442,9 @@
     public void testNoRounding_NoCutout_NoPrivacyDot_NoFaceScanning() {
         setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
                 null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
-                0 /* roundedPadding */, false /* fillCutout */, false /* privacyDot */,
-                false /* faceScanning */);
+                0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
 
-        // no cutout
-        doReturn(null).when(mScreenDecorations).getCutout();
+        // no cutout (default)
 
         mScreenDecorations.start();
         // No views added.
@@ -448,11 +459,9 @@
     public void testNoRounding_NoCutout_PrivacyDot_NoFaceScanning() {
         setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
                 null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
-                0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
-                false /* faceScanning */);
+                0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
 
-        // no cutout
-        doReturn(null).when(mScreenDecorations).getCutout();
+        // no cutout (default)
 
         mScreenDecorations.start();
 
@@ -484,11 +493,9 @@
     public void testRounding_NoCutout_NoPrivacyDot_NoFaceScanning() {
         setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
                 null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
-                20 /* roundedPadding */, false /* fillCutout */, false /* privacyDot */,
-                false /* faceScanning */);
+                20 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
 
-        // no cutout
-        doReturn(null).when(mScreenDecorations).getCutout();
+        // no cutout (default)
 
         mScreenDecorations.start();
 
@@ -516,11 +523,9 @@
     public void testRounding_NoCutout_PrivacyDot_NoFaceScanning() {
         setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
                 null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
-                20 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
-                false /* faceScanning */);
+                20 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
 
-        // no cutout
-        doReturn(null).when(mScreenDecorations).getCutout();
+        // no cutout (default)
 
         mScreenDecorations.start();
 
@@ -555,10 +560,9 @@
                 /* roundedTopDrawable */,
                 getTestsDrawable(com.android.systemui.tests.R.drawable.rounded3px)
                 /* roundedBottomDrawable */,
-                0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
-                false /* faceScanning */);
-        // no cutout
-        doReturn(null).when(mScreenDecorations).getCutout();
+                0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
+
+        // no cutout (default)
 
         mScreenDecorations.start();
         // Size of corner view should same as rounded_corner_radius{_top|_bottom}
@@ -574,11 +578,9 @@
                 /* roundedTopDrawable */,
                 getTestsDrawable(com.android.systemui.tests.R.drawable.rounded3px)
                 /* roundedBottomDrawable */,
-                0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
-                false /* faceScanning */);
+                0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
 
-        // no cutout
-        doReturn(null).when(mScreenDecorations).getCutout();
+        // no cutout (default)
 
         mScreenDecorations.start();
         View leftRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_TOP].getRootView()
@@ -611,13 +613,10 @@
                 /* roundedTopDrawable */,
                 getTestsDrawable(com.android.systemui.tests.R.drawable.rounded5px)
                 /* roundedBottomDrawable */,
-                0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
-                false /* faceScanning */);
+                0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
 
         // left cutout
-        final Rect[] bounds = {new Rect(0, 50, 1, 60), null, null, null};
-        doReturn(getDisplayCutoutForRotation(Insets.of(1, 0, 0, 0), bounds))
-                .when(mScreenDecorations).getCutout();
+        mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
 
         mScreenDecorations.start();
         View topRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_LEFT].getRootView()
@@ -647,13 +646,10 @@
     public void testNoRounding_CutoutShortEdge_NoPrivacyDot() {
         setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
                 null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
-                0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
-                false /* faceScanning */);
+                0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
 
         // top cutout
-        final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
-        doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
-                .when(mScreenDecorations).getCutout();
+        mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
 
         mScreenDecorations.start();
         // Top window is created for top cutout.
@@ -671,13 +667,10 @@
     public void testNoRounding_CutoutShortEdge_PrivacyDot() {
         setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
                 null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
-                0 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
-                false /* faceScanning */);
+                0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
 
         // top cutout
-        final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
-        doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
-                .when(mScreenDecorations).getCutout();
+        mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
 
         mScreenDecorations.start();
         // Top window is created for top cutout.
@@ -706,13 +699,10 @@
     public void testNoRounding_CutoutLongEdge_NoPrivacyDot() {
         setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
                 null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
-                0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
-                false /* faceScanning */);
+                0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
 
         // left cutout
-        final Rect[] bounds = {new Rect(0, 50, 1, 60), null, null, null};
-        doReturn(getDisplayCutoutForRotation(Insets.of(1, 0, 0, 0), bounds))
-                .when(mScreenDecorations).getCutout();
+        mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
 
         mScreenDecorations.start();
         // Left window is created for left cutout.
@@ -734,13 +724,10 @@
     public void testNoRounding_CutoutLongEdge_PrivacyDot() {
         setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
                 null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
-                0 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
-                false /* faceScanning */);
+                0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
 
         // left cutout
-        final Rect[] bounds = {new Rect(0, 50, 1, 60), null, null, null};
-        doReturn(getDisplayCutoutForRotation(Insets.of(1, 0, 0, 0), bounds))
-                .when(mScreenDecorations).getCutout();
+        mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
 
         mScreenDecorations.start();
         // Left window is created for left cutout.
@@ -762,13 +749,10 @@
     public void testRounding_CutoutShortEdge_NoPrivacyDot() {
         setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
                 null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
-                20 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
-                false /* faceScanning */);
+                20 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
 
         // top cutout
-        final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
-        doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
-                .when(mScreenDecorations).getCutout();
+        mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
 
         mScreenDecorations.start();
         // Top window is created for rounded corner and top cutout.
@@ -791,13 +775,10 @@
     public void testRounding_CutoutShortEdge_PrivacyDot() {
         setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
                 null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
-                20 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
-                false /* faceScanning */);
+                20 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
 
         // top cutout
-        final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
-        doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
-                .when(mScreenDecorations).getCutout();
+        mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
 
         mScreenDecorations.start();
         // Top window is created for rounded corner and top cutout.
@@ -823,13 +804,10 @@
     public void testRounding_CutoutLongEdge_NoPrivacyDot() {
         setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
                 null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
-                20 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
-                false /* faceScanning */);
+                20 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
 
         // left cutout
-        final Rect[] bounds = {new Rect(0, 50, 1, 60), null, null, null};
-        doReturn(getDisplayCutoutForRotation(Insets.of(1, 0, 0, 0), bounds))
-                .when(mScreenDecorations).getCutout();
+        mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
 
         mScreenDecorations.start();
         // Left window is created for rounded corner and left cutout.
@@ -842,13 +820,10 @@
     public void testRounding_CutoutLongEdge_PrivacyDot() {
         setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
                 null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
-                20 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
-                false /* faceScanning */);
+                20 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
 
         // left cutout
-        final Rect[] bounds = {new Rect(0, 50, 1, 60), null, null, null};
-        doReturn(getDisplayCutoutForRotation(Insets.of(1, 0, 0, 0), bounds))
-                .when(mScreenDecorations).getCutout();
+        mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
 
         mScreenDecorations.start();
         // Left window is created for rounded corner, left cutout, and privacy.
@@ -863,13 +838,11 @@
     public void testRounding_CutoutShortAndLongEdge_NoPrivacyDot() {
         setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
                 null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
-                20 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
-                false /* faceScanning */);
+                20 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
 
         // top and left cutout
-        final Rect[] bounds = {new Rect(0, 50, 1, 60), new Rect(9, 0, 10, 1), null, null};
-        doReturn(getDisplayCutoutForRotation(Insets.of(1, 1, 0, 0), bounds))
-                .when(mScreenDecorations).getCutout();
+        mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
+        mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
 
         mScreenDecorations.start();
         // Top window is created for rounded corner and top cutout.
@@ -883,13 +856,11 @@
     public void testRounding_CutoutShortAndLongEdge_PrivacyDot() {
         setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
                 null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
-                20 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
-                false /* faceScanning */);
+                20 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
 
         // top and left cutout
-        final Rect[] bounds = {new Rect(0, 50, 1, 60), new Rect(9, 0, 10, 1), null, null};
-        doReturn(getDisplayCutoutForRotation(Insets.of(1, 1, 0, 0), bounds))
-                .when(mScreenDecorations).getCutout();
+        mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
+        mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
 
         mScreenDecorations.start();
         // Top window is created for rounded corner and top cutout.
@@ -905,21 +876,16 @@
     public void testNoRounding_SwitchFrom_ShortEdgeCutout_To_LongCutout_NoPrivacyDot() {
         setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
                 null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
-                0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
-                false /* faceScanning */);
+                0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
 
         // Set to short edge cutout(top).
-        final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
-        doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
-                .when(mScreenDecorations).getCutout();
+        mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
 
         mScreenDecorations.start();
         verifyOverlaysExistAndAdded(false, true, false, false, View.VISIBLE);
 
         // Switch to long edge cutout(left).
-        final Rect[] newBounds = {new Rect(0, 50, 1, 60), null, null, null};
-        doReturn(getDisplayCutoutForRotation(Insets.of(1, 0, 0, 0), newBounds))
-                .when(mScreenDecorations).getCutout();
+        mMockCutoutList.set(0, new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
 
         mScreenDecorations.onConfigurationChanged(new Configuration());
         verifyOverlaysExistAndAdded(true, false, false, false, View.VISIBLE);
@@ -929,13 +895,10 @@
     public void testNoRounding_SwitchFrom_ShortEdgeCutout_To_LongCutout_PrivacyDot() {
         setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
                 null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
-                0 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
-                false /* faceScanning */);
+                0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
 
         // Set to short edge cutout(top).
-        final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
-        doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
-                .when(mScreenDecorations).getCutout();
+        mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
 
         mScreenDecorations.start();
         verifyOverlaysExistAndAdded(false, true, false, true, View.VISIBLE);
@@ -943,9 +906,7 @@
         verify(mDotViewController, times(1)).setShowingListener(null);
 
         // Switch to long edge cutout(left).
-        final Rect[] newBounds = {new Rect(0, 50, 1, 60), null, null, null};
-        doReturn(getDisplayCutoutForRotation(Insets.of(1, 0, 0, 0), newBounds))
-                .when(mScreenDecorations).getCutout();
+        mMockCutoutList.set(0, new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
 
         mScreenDecorations.onConfigurationChanged(new Configuration());
         verifyOverlaysExistAndAdded(true, false, true, false, View.VISIBLE);
@@ -973,20 +934,16 @@
     public void testDelayedCutout_NoPrivacyDot() {
         setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
                 null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
-                0 /* roundedPadding */, false /* fillCutout */, false /* privacyDot */,
-                false /* faceScanning */);
+                0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
 
-        // top cutout
-        final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
-        doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
-                .when(mScreenDecorations).getCutout();
+        // No cutout (default)
 
         mScreenDecorations.start();
         verifyOverlaysExistAndAdded(false, false, false, false, null);
 
-        when(mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout))
-                .thenReturn(true);
+        // top cutout
+        mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
+
         mScreenDecorations.onConfigurationChanged(new Configuration());
 
         // Only top windows should be added.
@@ -997,13 +954,9 @@
     public void testDelayedCutout_PrivacyDot() {
         setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
                 null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
-                0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
-                false /* faceScanning */);
+                0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
 
-        // top cutout
-        final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
-        doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
-                .when(mScreenDecorations).getCutout();
+        // no cutout (default)
 
         mScreenDecorations.start();
         // Both top and bottom windows should be added with INVISIBLE because of only privacy dot,
@@ -1015,9 +968,9 @@
         verify(mDotViewController, times(1)).setShowingListener(
                 mScreenDecorations.mPrivacyDotShowingListener);
 
-        when(mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout))
-                .thenReturn(true);
+        // top cutout
+        mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
+
         mScreenDecorations.onConfigurationChanged(new Configuration());
 
         // Both top and bottom windows should be added with VISIBLE because of privacy dot and
@@ -1043,8 +996,7 @@
                 /* roundedTopDrawable */,
                 getTestsDrawable(com.android.systemui.tests.R.drawable.rounded4px)
                 /* roundedBottomDrawable */,
-                0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
-                false /* faceScanning*/);
+                0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning*/);
         mDisplayInfo.rotation = Surface.ROTATION_0;
 
         mScreenDecorations.start();
@@ -1058,8 +1010,7 @@
                 /* roundedTopDrawable */,
                 getTestsDrawable(com.android.systemui.tests.R.drawable.rounded5px)
                 /* roundedBottomDrawable */,
-                0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
-                false /* faceScanning*/);
+                0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning*/);
         mDisplayInfo.rotation = Surface.ROTATION_270;
 
         mScreenDecorations.onConfigurationChanged(null);
@@ -1072,8 +1023,7 @@
     public void testOnlyRoundedCornerRadiusTop() {
         setupResources(0 /* radius */, 10 /* radiusTop */, 0 /* radiusBottom */,
                 null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
-                0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
-                false /* faceScanning */);
+                0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
 
         mScreenDecorations.start();
 
@@ -1094,8 +1044,7 @@
     public void testOnlyRoundedCornerRadiusBottom() {
         setupResources(0 /* radius */, 0 /* radiusTop */, 20 /* radiusBottom */,
                 null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
-                0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
-                false /* faceScanning */);
+                0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
 
         mScreenDecorations.start();
 
@@ -1166,13 +1115,10 @@
     public void testSupportHwcLayer_SwitchFrom_NotSupport() {
         setupResources(0 /* radius */, 10 /* radiusTop */, 20 /* radiusBottom */,
                 null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
-                0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
-                false /* faceScanning */);
+                0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
 
         // top cutout
-        final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
-        doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
-                .when(mScreenDecorations).getCutout();
+        mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
 
         mScreenDecorations.start();
         // should only inflate mOverlays when the hwc doesn't support screen decoration
@@ -1195,16 +1141,13 @@
     public void testNotSupportHwcLayer_SwitchFrom_Support() {
         setupResources(0 /* radius */, 10 /* radiusTop */, 20 /* radiusBottom */,
                 null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
-                0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
-                false /* faceScanning */);
+                0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
         final DisplayDecorationSupport decorationSupport = new DisplayDecorationSupport();
         decorationSupport.format = PixelFormat.R_8;
         doReturn(decorationSupport).when(mDisplay).getDisplayDecorationSupport();
 
         // top cutout
-        final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
-        doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
-                .when(mScreenDecorations).getCutout();
+        mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
 
         mScreenDecorations.start();
         // should only inflate hwc layer when the hwc supports screen decoration
@@ -1234,16 +1177,13 @@
                 /* roundedTopDrawable */,
                 getTestsDrawable(com.android.systemui.tests.R.drawable.rounded4px)
                 /* roundedBottomDrawable */,
-                0 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
-                true /* faceScanning */);
+                0 /* roundedPadding */, true /* privacyDot */, true /* faceScanning */);
         final DisplayDecorationSupport decorationSupport = new DisplayDecorationSupport();
         decorationSupport.format = PixelFormat.R_8;
         doReturn(decorationSupport).when(mDisplay).getDisplayDecorationSupport();
 
         // top cutout
-        final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
-        doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
-                .when(mScreenDecorations).getCutout();
+        mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
 
         mScreenDecorations.start();
         // Inflate top and bottom overlay with INVISIBLE because of only privacy dots on sw layer
@@ -1277,11 +1217,9 @@
     public void testAutoShowHideOverlayWindowWhenNoRoundedAndNoCutout() {
         setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
                 null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
-                0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
-                true /* faceScanning */);
+                0 /* roundedPadding */, true /* privacyDot */, true /* faceScanning */);
 
-        // no cutout
-        doReturn(null).when(mScreenDecorations).getCutout();
+        // no cutout (default)
 
         mScreenDecorations.start();
         // Inflate top and bottom overlay with INVISIBLE because of only privacy dots on sw layer
@@ -1315,16 +1253,13 @@
     public void testHwcLayer_noPrivacyDot_noFaceScanning() {
         setupResources(0 /* radius */, 10 /* radiusTop */, 20 /* radiusBottom */,
                 null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
-                0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
-                false /* faceScanning */);
+                0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
         final DisplayDecorationSupport decorationSupport = new DisplayDecorationSupport();
         decorationSupport.format = PixelFormat.R_8;
         doReturn(decorationSupport).when(mDisplay).getDisplayDecorationSupport();
 
         // top cutout
-        final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
-        doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
-                .when(mScreenDecorations).getCutout();
+        mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
 
         mScreenDecorations.start();
 
@@ -1337,16 +1272,13 @@
     public void testHwcLayer_PrivacyDot_FaceScanning() {
         setupResources(0 /* radius */, 10 /* radiusTop */, 20 /* radiusBottom */,
                 null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
-                0 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
-                true /* faceScanning */);
+                0 /* roundedPadding */, true /* privacyDot */, true /* faceScanning */);
         final DisplayDecorationSupport decorationSupport = new DisplayDecorationSupport();
         decorationSupport.format = PixelFormat.R_8;
         doReturn(decorationSupport).when(mDisplay).getDisplayDecorationSupport();
 
         // top cutout
-        final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
-        doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
-                .when(mScreenDecorations).getCutout();
+        mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
 
         mScreenDecorations.start();
 
@@ -1364,16 +1296,13 @@
     public void testOnDisplayChanged_hwcLayer() {
         setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
                 null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
-                0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
-                false /* faceScanning */);
+                0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
         final DisplayDecorationSupport decorationSupport = new DisplayDecorationSupport();
         decorationSupport.format = PixelFormat.R_8;
         doReturn(decorationSupport).when(mDisplay).getDisplayDecorationSupport();
 
         // top cutout
-        final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
-        doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
-                .when(mScreenDecorations).getCutout();
+        mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
 
         mScreenDecorations.start();
 
@@ -1383,39 +1312,36 @@
 
         mScreenDecorations.mDisplayListener.onDisplayChanged(1);
 
-        verify(hwcLayer, times(1)).onDisplayChanged(1);
+        verify(hwcLayer, times(1)).onDisplayChanged(any());
     }
 
     @Test
     public void testOnDisplayChanged_nonHwcLayer() {
         setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
                 null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
-                0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
-                false /* faceScanning */);
+                0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
 
         // top cutout
-        final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
-        doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
-                .when(mScreenDecorations).getCutout();
+        mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
 
         mScreenDecorations.start();
 
-        final ScreenDecorations.DisplayCutoutView cutoutView =
-                mScreenDecorations.mCutoutViews[BOUNDS_POSITION_TOP];
+        final ScreenDecorations.DisplayCutoutView cutoutView = (ScreenDecorations.DisplayCutoutView)
+                mScreenDecorations.getOverlayView(R.id.display_cutout);
+        assertNotNull(cutoutView);
         spyOn(cutoutView);
         doReturn(mDisplay).when(cutoutView).getDisplay();
 
         mScreenDecorations.mDisplayListener.onDisplayChanged(1);
 
-        verify(cutoutView, times(1)).onDisplayChanged(1);
+        verify(cutoutView, times(1)).onDisplayChanged(any());
     }
 
     @Test
     public void testHasSameProvidersWithNullOverlays() {
         setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
                 null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
-                0 /* roundedPadding */, false /* fillCutout */, false /* privacyDot */,
-                false /* faceScanning */);
+                0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
 
         mScreenDecorations.start();
 
@@ -1433,8 +1359,7 @@
     public void testHasSameProvidersWithPrivacyDots() {
         setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
                 null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
-                0 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
-                false /* faceScanning */);
+                0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
 
         mScreenDecorations.start();
 
@@ -1471,7 +1396,7 @@
 
     private void setupResources(int radius, int radiusTop, int radiusBottom,
             @Nullable Drawable roundedTopDrawable, @Nullable Drawable roundedBottomDrawable,
-            int roundedPadding, boolean fillCutout, boolean privacyDot, boolean faceScanning) {
+            int roundedPadding, boolean privacyDot, boolean faceScanning) {
         mContext.getOrCreateTestableResources().addOverride(
                 com.android.internal.R.array.config_displayUniqueIdArray,
                 new String[]{});
@@ -1511,8 +1436,6 @@
         }
         mContext.getOrCreateTestableResources().addOverride(
                 R.dimen.rounded_corner_content_padding, roundedPadding);
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, fillCutout);
 
         mPrivacyDecorProviders = new ArrayList<>();
         if (privacyDot) {
@@ -1531,19 +1454,4 @@
         when(mFaceScanningProviderFactory.getProviders()).thenReturn(mFaceScanningProviders);
         when(mFaceScanningProviderFactory.getHasProviders()).thenReturn(faceScanning);
     }
-
-    private DisplayCutout getDisplayCutoutForRotation(Insets safeInsets, Rect[] cutoutBounds) {
-        final int rotation = mContext.getDisplay().getRotation();
-        final Insets insets = RotationUtils.rotateInsets(safeInsets, rotation);
-        final Rect[] sorted = new Rect[BOUNDS_POSITION_LENGTH];
-        for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) {
-            final int rotatedPos = ScreenDecorations.getBoundPositionFromRotation(i, rotation);
-            if (cutoutBounds[i] != null) {
-                RotationUtils.rotateBounds(cutoutBounds[i], new Rect(0, 0, 100, 200), rotation);
-            }
-            sorted[rotatedPos] = cutoutBounds[i];
-        }
-        return new DisplayCutout(insets, sorted[BOUNDS_POSITION_LEFT], sorted[BOUNDS_POSITION_TOP],
-                sorted[BOUNDS_POSITION_RIGHT], sorted[BOUNDS_POSITION_BOTTOM]);
-    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/decor/CutoutDecorProviderFactoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/decor/CutoutDecorProviderFactoryTest.kt
new file mode 100644
index 0000000..1040ec4
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/decor/CutoutDecorProviderFactoryTest.kt
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.decor
+
+import android.graphics.Insets
+import android.graphics.Rect
+import android.testing.AndroidTestingRunner
+import android.testing.TestableResources
+import android.util.RotationUtils
+import android.util.Size
+import android.view.Display
+import android.view.DisplayCutout
+import android.view.DisplayCutout.BOUNDS_POSITION_LENGTH
+import android.view.DisplayInfo
+import android.view.Surface
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.mockito.any
+import org.junit.Assert
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.doAnswer
+import org.mockito.MockitoAnnotations
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class CutoutDecorProviderFactoryTest : SysuiTestCase() {
+
+    @Mock private lateinit var display: Display
+    private var testableRes: TestableResources? = null
+    private lateinit var factory: CutoutDecorProviderFactory
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+        testableRes = mContext.orCreateTestableResources
+        factory = CutoutDecorProviderFactory(testableRes!!.resources, display)
+    }
+
+    private fun setupFillCutout(fillCutout: Boolean) {
+        testableRes!!.addOverride(
+            com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, fillCutout
+        )
+    }
+
+    private fun setupDisplayInfo(
+        displayCutout: DisplayCutout? = null,
+        @Surface.Rotation rotation: Int = Surface.ROTATION_0,
+        displayId: Int = -1
+    ) {
+        doAnswer {
+            it.getArgument<DisplayInfo>(0).let { info ->
+                info.displayCutout = displayCutout
+                info.rotation = rotation
+                info.displayId = displayId
+            }
+            true
+        }.`when`(display).getDisplayInfo(any<DisplayInfo>())
+    }
+
+    private fun getCutout(
+        safeInsets: Insets,
+        cutoutBounds: Array<Rect?>,
+        @Surface.Rotation rotation: Int = Surface.ROTATION_0,
+        cutoutParentSizeForRotate: Size = Size(100, 200)
+    ): DisplayCutout {
+        val insets = RotationUtils.rotateInsets(safeInsets, rotation)
+        val sorted = arrayOfNulls<Rect>(BOUNDS_POSITION_LENGTH)
+        for (pos in 0 until BOUNDS_POSITION_LENGTH) {
+            val rotatedPos = (pos - rotation + BOUNDS_POSITION_LENGTH) % BOUNDS_POSITION_LENGTH
+            if (cutoutBounds[pos] != null) {
+                RotationUtils.rotateBounds(
+                    cutoutBounds[pos],
+                    cutoutParentSizeForRotate.width,
+                    cutoutParentSizeForRotate.height,
+                    rotation
+                )
+            }
+            sorted[rotatedPos] = cutoutBounds[pos]
+        }
+        return DisplayCutout(
+            insets,
+            sorted[DisplayCutout.BOUNDS_POSITION_LEFT],
+            sorted[DisplayCutout.BOUNDS_POSITION_TOP],
+            sorted[DisplayCutout.BOUNDS_POSITION_RIGHT],
+            sorted[DisplayCutout.BOUNDS_POSITION_BOTTOM]
+        )
+    }
+
+    @Test
+    fun testGetNothingIfNoCutout() {
+        setupFillCutout(false)
+
+        Assert.assertFalse(factory.hasProviders)
+        Assert.assertEquals(0, factory.providers.size)
+    }
+
+    @Test
+    fun testGetTopCutoutProvider() {
+        setupFillCutout(true)
+        setupDisplayInfo(
+            getCutout(
+                safeInsets = Insets.of(0, 1, 0, 0),
+                cutoutBounds = arrayOf(null, Rect(9, 0, 10, 1), null, null)
+            )
+        )
+
+        Assert.assertTrue(factory.hasProviders)
+
+        val providers = factory.providers
+        Assert.assertEquals(1, providers.size)
+        Assert.assertEquals(1, providers[0].numOfAlignedBound)
+        Assert.assertEquals(DisplayCutout.BOUNDS_POSITION_TOP, providers[0].alignedBounds[0])
+    }
+
+    @Test
+    fun testGetBottomCutoutProviderOnLandscape() {
+        setupFillCutout(true)
+        setupDisplayInfo(
+            getCutout(
+                safeInsets = Insets.of(0, 0, 0, 1),
+                cutoutBounds = arrayOf(null, null, null, Rect(45, 199, 55, 200)),
+                rotation = Surface.ROTATION_90
+            ),
+            Surface.ROTATION_90
+        )
+
+        Assert.assertTrue(factory.hasProviders)
+
+        val providers = factory.providers
+        Assert.assertEquals(1, providers.size)
+        Assert.assertEquals(1, providers[0].numOfAlignedBound)
+        Assert.assertEquals(DisplayCutout.BOUNDS_POSITION_BOTTOM, providers[0].alignedBounds[0])
+    }
+
+    @Test
+    fun testGetLeftCutoutProviderOnSeascape() {
+        setupFillCutout(true)
+        setupDisplayInfo(
+            getCutout(
+                safeInsets = Insets.of(1, 0, 0, 0),
+                cutoutBounds = arrayOf(Rect(0, 20, 1, 40), null, null, null),
+                rotation = Surface.ROTATION_270
+            ),
+            Surface.ROTATION_270
+        )
+
+        Assert.assertTrue(factory.hasProviders)
+
+        val providers = factory.providers
+        Assert.assertEquals(1, providers.size)
+        Assert.assertEquals(1, providers[0].numOfAlignedBound)
+        Assert.assertEquals(DisplayCutout.BOUNDS_POSITION_LEFT, providers[0].alignedBounds[0])
+    }
+
+    @Test
+    fun testGetTopRightCutoutProviderOnReverse() {
+        setupFillCutout(true)
+        setupDisplayInfo(
+            getCutout(
+                safeInsets = Insets.of(0, 1, 1, 0),
+                cutoutBounds = arrayOf(
+                    null,
+                    Rect(9, 0, 10, 1),
+                    Rect(99, 40, 100, 60),
+                    null
+                ),
+                rotation = Surface.ROTATION_180
+            ),
+            Surface.ROTATION_180
+        )
+
+        Assert.assertTrue(factory.hasProviders)
+
+        val providers = factory.providers
+        Assert.assertEquals(2, providers.size)
+        Assert.assertEquals(1, providers[0].numOfAlignedBound)
+        Assert.assertEquals(1, providers[1].numOfAlignedBound)
+        providers.sortedBy { it.alignedBounds[0] }.let {
+            Assert.assertEquals(DisplayCutout.BOUNDS_POSITION_TOP, it[0].alignedBounds[0])
+            Assert.assertEquals(DisplayCutout.BOUNDS_POSITION_RIGHT, it[1].alignedBounds[0])
+        }
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/decor/OverlayWindowTest.kt b/packages/SystemUI/tests/src/com/android/systemui/decor/OverlayWindowTest.kt
index 69366fa..8bf17d7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/decor/OverlayWindowTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/decor/OverlayWindowTest.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.decor
 
+import android.graphics.Color
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper.RunWithLooper
 import android.view.DisplayCutout
@@ -51,35 +52,45 @@
 
     @Before
     fun setUp() {
-        decorProvider1 = spy(PrivacyDotCornerDecorProviderImpl(
+        decorProvider1 = spy(
+            PrivacyDotCornerDecorProviderImpl(
                 viewId = TEST_DECOR_VIEW_ID_1,
                 alignedBound1 = DisplayCutout.BOUNDS_POSITION_TOP,
                 alignedBound2 = DisplayCutout.BOUNDS_POSITION_LEFT,
-                layoutId = R.layout.privacy_dot_top_left))
-        decorProvider2 = spy(PrivacyDotCornerDecorProviderImpl(
+                layoutId = R.layout.privacy_dot_top_left
+            )
+        )
+        decorProvider2 = spy(
+            PrivacyDotCornerDecorProviderImpl(
                 viewId = TEST_DECOR_VIEW_ID_2,
                 alignedBound1 = DisplayCutout.BOUNDS_POSITION_BOTTOM,
                 alignedBound2 = DisplayCutout.BOUNDS_POSITION_LEFT,
-                layoutId = R.layout.privacy_dot_bottom_left))
-        decorProvider3 = spy(PrivacyDotCornerDecorProviderImpl(
+                layoutId = R.layout.privacy_dot_bottom_left
+            )
+        )
+        decorProvider3 = spy(
+            PrivacyDotCornerDecorProviderImpl(
                 viewId = TEST_DECOR_VIEW_ID_3,
                 alignedBound1 = DisplayCutout.BOUNDS_POSITION_BOTTOM,
                 alignedBound2 = DisplayCutout.BOUNDS_POSITION_RIGHT,
-                layoutId = R.layout.privacy_dot_bottom_right))
-
+                layoutId = R.layout.privacy_dot_bottom_right
+            )
+        )
         overlay = OverlayWindow(mContext)
     }
 
     @Test
     fun testAddProvider() {
         @Surface.Rotation val rotation = Surface.ROTATION_270
-        overlay.addDecorProvider(decorProvider1, rotation)
-        overlay.addDecorProvider(decorProvider2, rotation)
+        overlay.addDecorProvider(decorProvider1, rotation, Color.BLACK)
+        overlay.addDecorProvider(decorProvider2, rotation, Color.YELLOW)
 
         verify(decorProvider1, times(1)).inflateView(
-                mContext, overlay.rootView, rotation)
+                mContext, overlay.rootView, rotation, Color.BLACK
+        )
         verify(decorProvider2, times(1)).inflateView(
-                mContext, overlay.rootView, rotation)
+                mContext, overlay.rootView, rotation, Color.YELLOW
+        )
 
         val view1FoundFromRootView = overlay.rootView.findViewById<View>(TEST_DECOR_VIEW_ID_1)
         Assert.assertNotNull(view1FoundFromRootView)
@@ -91,8 +102,8 @@
 
     @Test
     fun testRemoveView() {
-        overlay.addDecorProvider(decorProvider1, Surface.ROTATION_270)
-        overlay.addDecorProvider(decorProvider2, Surface.ROTATION_270)
+        overlay.addDecorProvider(decorProvider1, Surface.ROTATION_270, Color.BLACK)
+        overlay.addDecorProvider(decorProvider2, Surface.ROTATION_270, Color.BLACK)
         overlay.removeView(TEST_DECOR_VIEW_ID_1)
 
         val viewFoundFromRootView = overlay.rootView.findViewById<View>(TEST_DECOR_VIEW_ID_1)
@@ -102,39 +113,47 @@
 
     @Test
     fun testOnReloadResAndMeasureWithoutIds() {
-        overlay.addDecorProvider(decorProvider1, Surface.ROTATION_0)
-        overlay.addDecorProvider(decorProvider2, Surface.ROTATION_0)
+        overlay.addDecorProvider(decorProvider1, Surface.ROTATION_0, Color.BLACK)
+        overlay.addDecorProvider(decorProvider2, Surface.ROTATION_0, Color.BLACK)
 
         overlay.onReloadResAndMeasure(
-                reloadToken = 1,
-                rotation = Surface.ROTATION_90,
-                displayUniqueId = null)
+            reloadToken = 1,
+            rotation = Surface.ROTATION_90,
+            tintColor = Color.BLACK,
+            displayUniqueId = null
+        )
         verify(decorProvider1, times(1)).onReloadResAndMeasure(
-                overlay.getView(TEST_DECOR_VIEW_ID_1)!!, 1, Surface.ROTATION_90, null)
+                overlay.getView(TEST_DECOR_VIEW_ID_1)!!, 1, Surface.ROTATION_90, Color.BLACK, null
+        )
         verify(decorProvider2, times(1)).onReloadResAndMeasure(
-                overlay.getView(TEST_DECOR_VIEW_ID_2)!!, 1, Surface.ROTATION_90, null)
+                overlay.getView(TEST_DECOR_VIEW_ID_2)!!, 1, Surface.ROTATION_90, Color.BLACK, null
+        )
     }
 
     @Test
     fun testOnReloadResAndMeasureWithIds() {
-        overlay.addDecorProvider(decorProvider1, Surface.ROTATION_0)
-        overlay.addDecorProvider(decorProvider2, Surface.ROTATION_0)
+        overlay.addDecorProvider(decorProvider1, Surface.ROTATION_0, Color.BLACK)
+        overlay.addDecorProvider(decorProvider2, Surface.ROTATION_0, Color.BLACK)
 
         overlay.onReloadResAndMeasure(
-                filterIds = arrayOf(TEST_DECOR_VIEW_ID_2),
-                reloadToken = 1,
-                rotation = Surface.ROTATION_90,
-                displayUniqueId = null)
+            filterIds = arrayOf(TEST_DECOR_VIEW_ID_2),
+            reloadToken = 1,
+            rotation = Surface.ROTATION_90,
+            tintColor = Color.BLACK,
+            displayUniqueId = null
+        )
         verify(decorProvider1, never()).onReloadResAndMeasure(
-                overlay.getView(TEST_DECOR_VIEW_ID_1)!!, 1, Surface.ROTATION_90, null)
+                overlay.getView(TEST_DECOR_VIEW_ID_1)!!, 1, Surface.ROTATION_90, Color.BLACK, null
+        )
         verify(decorProvider2, times(1)).onReloadResAndMeasure(
-                overlay.getView(TEST_DECOR_VIEW_ID_2)!!, 1, Surface.ROTATION_90, null)
+                overlay.getView(TEST_DECOR_VIEW_ID_2)!!, 1, Surface.ROTATION_90, Color.BLACK, null
+        )
     }
 
     @Test
     fun testRemoveRedundantViewsWithNullParameter() {
-        overlay.addDecorProvider(decorProvider1, Surface.ROTATION_270)
-        overlay.addDecorProvider(decorProvider2, Surface.ROTATION_270)
+        overlay.addDecorProvider(decorProvider1, Surface.ROTATION_270, Color.BLACK)
+        overlay.addDecorProvider(decorProvider2, Surface.ROTATION_270, Color.BLACK)
 
         overlay.removeRedundantViews(null)
 
@@ -146,13 +165,15 @@
 
     @Test
     fun testRemoveRedundantViewsWith2Providers() {
-        overlay.addDecorProvider(decorProvider1, Surface.ROTATION_270)
-        overlay.addDecorProvider(decorProvider2, Surface.ROTATION_270)
+        overlay.addDecorProvider(decorProvider1, Surface.ROTATION_270, Color.BLACK)
+        overlay.addDecorProvider(decorProvider2, Surface.ROTATION_270, Color.BLACK)
 
-        overlay.removeRedundantViews(IntArray(2).apply {
-            this[0] = TEST_DECOR_VIEW_ID_3
-            this[1] = TEST_DECOR_VIEW_ID_1
-        })
+        overlay.removeRedundantViews(
+            IntArray(2).apply {
+                this[0] = TEST_DECOR_VIEW_ID_3
+                this[1] = TEST_DECOR_VIEW_ID_1
+            }
+        )
 
         Assert.assertNotNull(overlay.getView(TEST_DECOR_VIEW_ID_1))
         Assert.assertNotNull(overlay.rootView.findViewById(TEST_DECOR_VIEW_ID_1))
@@ -167,16 +188,16 @@
         Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider2)))
         Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider2, decorProvider1)))
 
-        overlay.addDecorProvider(decorProvider1, Surface.ROTATION_0)
+        overlay.addDecorProvider(decorProvider1, Surface.ROTATION_0, Color.BLACK)
         Assert.assertFalse(overlay.hasSameProviders(emptyList()))
         Assert.assertTrue(overlay.hasSameProviders(listOf(decorProvider1)))
         Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider2)))
         Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider2, decorProvider1)))
 
-        overlay.addDecorProvider(decorProvider2, Surface.ROTATION_0)
+        overlay.addDecorProvider(decorProvider2, Surface.ROTATION_0, Color.BLACK)
         Assert.assertFalse(overlay.hasSameProviders(emptyList()))
         Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider1)))
         Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider2)))
         Assert.assertTrue(overlay.hasSameProviders(listOf(decorProvider2, decorProvider1)))
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/SmartSpaceComplicationTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/SmartSpaceComplicationTest.java
index 7d54758..fa8f88a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/SmartSpaceComplicationTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/SmartSpaceComplicationTest.java
@@ -43,7 +43,7 @@
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 
-import java.util.Arrays;
+import java.util.Collections;
 
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
@@ -61,9 +61,6 @@
     private SmartSpaceComplication mComplication;
 
     @Mock
-    private ComplicationViewModel mComplicationViewModel;
-
-    @Mock
     private View mBcSmartspaceView;
 
     @Before
@@ -125,12 +122,12 @@
 
         // Test
         final SmartspaceTarget target = Mockito.mock(SmartspaceTarget.class);
-        listenerCaptor.getValue().onSmartspaceTargetsUpdated(Arrays.asList(target));
+        listenerCaptor.getValue().onSmartspaceTargetsUpdated(Collections.singletonList(target));
         verify(mDreamOverlayStateController).addComplication(eq(mComplication));
     }
 
     @Test
-    public void testOverlayActive_targetsEmpty_removesComplication() {
+    public void testOverlayActive_targetsEmpty_addsComplication() {
         final SmartSpaceComplication.Registrant registrant = getRegistrant();
         registrant.start();
 
@@ -145,13 +142,9 @@
                 ArgumentCaptor.forClass(BcSmartspaceDataPlugin.SmartspaceTargetListener.class);
         verify(mSmartspaceController).addListener(listenerCaptor.capture());
 
-        final SmartspaceTarget target = Mockito.mock(SmartspaceTarget.class);
-        listenerCaptor.getValue().onSmartspaceTargetsUpdated(Arrays.asList(target));
-        verify(mDreamOverlayStateController).addComplication(eq(mComplication));
-
         // Test
-        listenerCaptor.getValue().onSmartspaceTargetsUpdated(Arrays.asList());
-        verify(mDreamOverlayStateController).removeComplication(eq(mComplication));
+        listenerCaptor.getValue().onSmartspaceTargetsUpdated(Collections.emptyList());
+        verify(mDreamOverlayStateController).addComplication(eq(mComplication));
     }
 
     @Test
@@ -170,8 +163,7 @@
                 ArgumentCaptor.forClass(BcSmartspaceDataPlugin.SmartspaceTargetListener.class);
         verify(mSmartspaceController).addListener(listenerCaptor.capture());
 
-        final SmartspaceTarget target = Mockito.mock(SmartspaceTarget.class);
-        listenerCaptor.getValue().onSmartspaceTargetsUpdated(Arrays.asList(target));
+        listenerCaptor.getValue().onSmartspaceTargetsUpdated(Collections.emptyList());
         verify(mDreamOverlayStateController).addComplication(eq(mComplication));
 
         // Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
index 1131a7e..eb8ecae 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
@@ -224,6 +224,14 @@
     }
 
     @Test
+    public void refresh_inDragging_directSetRefreshingToFalse() {
+        when(mMediaOutputBaseAdapter.isDragging()).thenReturn(true);
+        mMediaOutputBaseDialogImpl.refresh();
+
+        assertThat(mMediaOutputController.isRefreshing()).isFalse();
+    }
+
+    @Test
     public void refresh_notInDragging_verifyUpdateAdapter() {
         when(mMediaOutputBaseAdapter.getCurrentActivePosition()).thenReturn(-1);
         when(mMediaOutputBaseAdapter.isDragging()).thenReturn(false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
index 98389c2..e2ce939 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
@@ -458,7 +458,6 @@
 
         NotificationWakeUpCoordinator coordinator =
                 new NotificationWakeUpCoordinator(
-                        mDumpManager,
                         mock(HeadsUpManagerPhone.class),
                         new StatusBarStateControllerImpl(new UiEventLoggerFake(), mDumpManager,
                                 mInteractionJankMonitor),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java
deleted file mode 100644
index 19dd027..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.notification;
-
-import static com.android.systemui.statusbar.notification.NotificationEntryManager.UNDEFINED_DISMISS_REASON;
-
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.verify;
-
-import android.app.ActivityManager;
-import android.app.Notification;
-import android.os.UserHandle;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.internal.statusbar.NotificationVisibility;
-import com.android.systemui.R;
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.NotificationLockscreenUserManager;
-import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
-import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
-public class NotificationListControllerTest extends SysuiTestCase {
-    private NotificationListController mController;
-
-    @Mock private NotificationEntryManager mEntryManager;
-    @Mock private NotificationListContainer mListContainer;
-    @Mock private DeviceProvisionedController mDeviceProvisionedController;
-
-    @Captor private ArgumentCaptor<NotificationEntryListener> mEntryListenerCaptor;
-    @Captor private ArgumentCaptor<DeviceProvisionedListener> mProvisionedCaptor;
-
-    private NotificationEntryListener mEntryListener;
-    private DeviceProvisionedListener mProvisionedListener;
-
-    private int mNextNotifId = 0;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mDependency.injectMockDependency(NotificationLockscreenUserManager.class);
-
-        mController = new NotificationListController(
-                mEntryManager,
-                mListContainer,
-                mDeviceProvisionedController);
-        mController.bind();
-
-        // Capture callbacks passed to mocks
-        verify(mEntryManager).addNotificationEntryListener(mEntryListenerCaptor.capture());
-        mEntryListener = mEntryListenerCaptor.getValue();
-        verify(mDeviceProvisionedController).addCallback(mProvisionedCaptor.capture());
-        mProvisionedListener = mProvisionedCaptor.getValue();
-    }
-
-    @Test
-    public void testCleanUpViewStateOnEntryRemoved() {
-        final NotificationEntry entry = buildEntry();
-        mEntryListener.onEntryRemoved(
-                entry,
-                NotificationVisibility.obtain(entry.getKey(), 0, 0, true),
-                false,
-                UNDEFINED_DISMISS_REASON);
-        verify(mListContainer).cleanUpViewStateForEntry(entry);
-    }
-
-    @Test
-    public void testCallUpdateNotificationsOnDeviceProvisionedChange() {
-        mProvisionedListener.onDeviceProvisionedChanged();
-        verify(mEntryManager).updateNotifications(anyString());
-    }
-
-    private NotificationEntry buildEntry() {
-        mNextNotifId++;
-
-        Notification.Builder n = new Notification.Builder(mContext, "")
-                .setSmallIcon(R.drawable.ic_person)
-                .setContentTitle("Title")
-                .setContentText("Text");
-
-        return new NotificationEntryBuilder()
-                .setPkg(TEST_PACKAGE_NAME)
-                .setOpPkg(TEST_PACKAGE_NAME)
-                .setId(mNextNotifId)
-                .setUid(TEST_UID)
-                .setNotification(n.build())
-                .setUser(new UserHandle(ActivityManager.getCurrentUser()))
-                .build();
-    }
-
-    private static final String TEST_PACKAGE_NAME = "test";
-    private static final int TEST_UID = 0;
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java
deleted file mode 100644
index b20f95c..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar.notification.row;
-
-import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
-import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
-import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL;
-import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_POSITIVE;
-
-import static com.android.systemui.statusbar.NotificationEntryHelper.modifyRanking;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.app.NotificationChannel;
-import android.content.Context;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-import android.view.View;
-
-import androidx.test.filters.FlakyTest;
-import androidx.test.filters.SmallTest;
-
-import com.android.internal.logging.MetricsLogger;
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-/**
- * Tests for {@link NotificationBlockingHelperManager}.
- */
-@SmallTest
-@FlakyTest
-@org.junit.runner.RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
-public class NotificationBlockingHelperManagerTest extends SysuiTestCase {
-    private NotificationBlockingHelperManager mBlockingHelperManager;
-
-    private NotificationTestHelper mHelper;
-
-    @Mock private NotificationGutsManager mGutsManager;
-    @Mock private NotificationEntryManager mEntryManager;
-    @Mock private NotificationMenuRow mMenuRow;
-    @Mock private NotificationMenuRowPlugin.MenuItem mMenuItem;
-    @Mock private GroupMembershipManager mGroupMembershipManager;
-
-    @Before
-    public void setUp() {
-        allowTestableLooperAsMainThread();
-        MockitoAnnotations.initMocks(this);
-        when(mGutsManager.openGuts(
-                any(View.class),
-                anyInt(),
-                anyInt(),
-                any(NotificationMenuRowPlugin.MenuItem.class)))
-                .thenReturn(true);
-        when(mMenuRow.getLongpressMenuItem(any(Context.class))).thenReturn(mMenuItem);
-
-        mHelper = new NotificationTestHelper(mContext, mDependency, TestableLooper.get(this));
-
-        mBlockingHelperManager = new NotificationBlockingHelperManager(
-                mContext, mGutsManager, mEntryManager, mock(MetricsLogger.class),
-                mGroupMembershipManager);
-        // By default, have the shade visible/expanded.
-        mBlockingHelperManager.setNotificationShadeExpanded(1f);
-    }
-
-    @Test
-    public void testDismissCurrentBlockingHelper_nullBlockingHelperRow() {
-        // By default, this shouldn't dismiss (no pointers/vars set up!)
-        assertFalse(mBlockingHelperManager.dismissCurrentBlockingHelper());
-        assertTrue(mBlockingHelperManager.isBlockingHelperRowNull());
-    }
-
-    @Test
-    public void testDismissCurrentBlockingHelper_withDetachedBlockingHelperRow() throws Exception {
-        ExpandableNotificationRow row = createBlockableRowSpy();
-        row.setBlockingHelperShowing(true);
-        when(row.isAttachedToWindow()).thenReturn(false);
-        mBlockingHelperManager.setBlockingHelperRowForTest(row);
-
-        assertTrue(mBlockingHelperManager.dismissCurrentBlockingHelper());
-        assertTrue(mBlockingHelperManager.isBlockingHelperRowNull());
-
-        verify(mEntryManager, times(0)).updateNotifications(anyString());
-    }
-
-    @Test
-    public void testDismissCurrentBlockingHelper_withAttachedBlockingHelperRow() throws Exception {
-        ExpandableNotificationRow row = createBlockableRowSpy();
-        row.setBlockingHelperShowing(true);
-        when(row.isAttachedToWindow()).thenReturn(true);
-        mBlockingHelperManager.setBlockingHelperRowForTest(row);
-
-        assertTrue(mBlockingHelperManager.dismissCurrentBlockingHelper());
-        assertTrue(mBlockingHelperManager.isBlockingHelperRowNull());
-
-        verify(mEntryManager).updateNotifications(anyString());
-    }
-
-    @Test
-    public void testPerhapsShowBlockingHelper_shown() throws Exception {
-        ExpandableNotificationRow row = createBlockableRowSpy();
-        modifyRanking(row.getEntry())
-                .setUserSentiment(USER_SENTIMENT_NEGATIVE)
-                .build();
-
-        assertTrue(mBlockingHelperManager.perhapsShowBlockingHelper(row, mMenuRow));
-
-        verify(mGutsManager).openGuts(row, 0, 0, mMenuItem);
-    }
-
-    @Test
-    public void testPerhapsShowBlockingHelper_notShownForMultiChannelGroup() throws Exception {
-        ExpandableNotificationRow groupRow = createBlockableGroupRowSpy(10);
-        int i = 0;
-        for (ExpandableNotificationRow childRow : groupRow.getAttachedChildren()) {
-            modifyRanking(childRow.getEntry())
-                    .setChannel(
-                            new NotificationChannel(
-                                    Integer.toString(i++), "", IMPORTANCE_DEFAULT))
-                    .build();
-        }
-
-        modifyRanking(groupRow.getEntry())
-                .setUserSentiment(USER_SENTIMENT_NEGATIVE)
-                .build();
-
-        assertFalse(mBlockingHelperManager.perhapsShowBlockingHelper(groupRow, mMenuRow));
-
-        verify(mGutsManager, never()).openGuts(groupRow, 0, 0, mMenuItem);
-    }
-
-    @Test
-    public void testPerhapsShowBlockingHelper_shownForLargeGroup() throws Exception {
-        ExpandableNotificationRow groupRow = createBlockableGroupRowSpy(10);
-        modifyRanking(groupRow.getEntry())
-                .setUserSentiment(USER_SENTIMENT_NEGATIVE)
-                .build();
-
-        assertTrue(mBlockingHelperManager.perhapsShowBlockingHelper(groupRow, mMenuRow));
-
-        verify(mGutsManager).openGuts(groupRow, 0, 0, mMenuItem);
-    }
-
-    @Test
-    public void testPerhapsShowBlockingHelper_shownForOnlyChildNotification()
-            throws Exception {
-        ExpandableNotificationRow groupRow = createBlockableGroupRowSpy(1);
-        // Explicitly get the children container & call getViewAtPosition on it instead of the row
-        // as other factors such as view expansion may cause us to get the parent row back instead
-        // of the child row.
-        ExpandableNotificationRow childRow = groupRow.getChildrenContainer().getViewAtPosition(0);
-        modifyRanking(childRow.getEntry())
-                .setUserSentiment(USER_SENTIMENT_NEGATIVE)
-                .build();
-        assertFalse(childRow.getIsNonblockable());
-
-        when(mGroupMembershipManager.isOnlyChildInGroup(childRow.getEntry())).thenReturn(true);
-        assertTrue(mBlockingHelperManager.perhapsShowBlockingHelper(childRow, mMenuRow));
-
-        verify(mGutsManager).openGuts(childRow, 0, 0, mMenuItem);
-    }
-
-    @Test
-    public void testPerhapsShowBlockingHelper_notShownDueToNeutralUserSentiment() throws Exception {
-        ExpandableNotificationRow row = createBlockableRowSpy();
-        modifyRanking(row.getEntry())
-                .setUserSentiment(USER_SENTIMENT_NEUTRAL)
-                .build();
-
-        assertFalse(mBlockingHelperManager.perhapsShowBlockingHelper(row, mMenuRow));
-    }
-
-    @Test
-    public void testPerhapsShowBlockingHelper_notShownDueToPositiveUserSentiment()
-            throws Exception {
-        ExpandableNotificationRow row = createBlockableRowSpy();
-        modifyRanking(row.getEntry())
-                .setUserSentiment(USER_SENTIMENT_POSITIVE)
-                .build();
-
-        assertFalse(mBlockingHelperManager.perhapsShowBlockingHelper(row, mMenuRow));
-    }
-
-    @Test
-    public void testPerhapsShowBlockingHelper_notShownDueToShadeVisibility() throws Exception {
-        ExpandableNotificationRow row = createBlockableRowSpy();
-        modifyRanking(row.getEntry())
-                .setUserSentiment(USER_SENTIMENT_NEGATIVE)
-                .build();
-        // Hide the shade
-        mBlockingHelperManager.setNotificationShadeExpanded(0f);
-
-        assertFalse(mBlockingHelperManager.perhapsShowBlockingHelper(row, mMenuRow));
-    }
-
-    @Test
-    public void testPerhapsShowBlockingHelper_notShownDueToNonblockability() throws Exception {
-        ExpandableNotificationRow row = createBlockableRowSpy();
-        when(row.getIsNonblockable()).thenReturn(true);
-        modifyRanking(row.getEntry())
-                .setUserSentiment(USER_SENTIMENT_NEGATIVE)
-                .build();
-
-        assertFalse(mBlockingHelperManager.perhapsShowBlockingHelper(row, mMenuRow));
-    }
-
-    @Test
-    public void testPerhapsShowBlockingHelper_notShownAsNotificationIsInMultipleChildGroup()
-            throws Exception {
-        ExpandableNotificationRow groupRow = createBlockableGroupRowSpy(2);
-        // Explicitly get the children container & call getViewAtPosition on it instead of the row
-        // as other factors such as view expansion may cause us to get the parent row back instead
-        // of the child row.
-        ExpandableNotificationRow childRow = groupRow.getChildrenContainer().getViewAtPosition(0);
-        modifyRanking(childRow.getEntry())
-                .setUserSentiment(USER_SENTIMENT_NEGATIVE)
-                .build();
-
-        assertFalse(mBlockingHelperManager.perhapsShowBlockingHelper(childRow, mMenuRow));
-    }
-
-    @Test
-    public void testBlockingHelperShowAndDismiss() throws Exception{
-        ExpandableNotificationRow row = createBlockableRowSpy();
-        modifyRanking(row.getEntry())
-                .setUserSentiment(USER_SENTIMENT_NEGATIVE)
-                .build();
-        when(row.isAttachedToWindow()).thenReturn(true);
-
-        // Show check
-        assertTrue(mBlockingHelperManager.perhapsShowBlockingHelper(row, mMenuRow));
-
-        verify(mGutsManager).openGuts(row, 0, 0, mMenuItem);
-
-        // Dismiss check
-        assertTrue(mBlockingHelperManager.dismissCurrentBlockingHelper());
-        assertTrue(mBlockingHelperManager.isBlockingHelperRowNull());
-
-        verify(mEntryManager).updateNotifications(anyString());
-    }
-
-    @Test
-    public void testNonBlockable_package() {
-        mBlockingHelperManager.setNonBlockablePkgs(new String[] {"banana", "strawberry:pie"});
-
-        assertFalse(mBlockingHelperManager.isNonblockable("orange", "pie"));
-
-        assertTrue(mBlockingHelperManager.isNonblockable("banana", "pie"));
-    }
-
-    @Test
-    public void testNonBlockable_channel() {
-        mBlockingHelperManager.setNonBlockablePkgs(new String[] {"banana", "strawberry:pie"});
-
-        assertFalse(mBlockingHelperManager.isNonblockable("strawberry", "shortcake"));
-
-        assertTrue(mBlockingHelperManager.isNonblockable("strawberry", "pie"));
-    }
-
-    private ExpandableNotificationRow createBlockableRowSpy() throws Exception {
-        ExpandableNotificationRow row = spy(mHelper.createRow());
-        when(row.getIsNonblockable()).thenReturn(false);
-        return row;
-    }
-
-    private ExpandableNotificationRow createBlockableGroupRowSpy(int numChildren) throws Exception {
-        ExpandableNotificationRow row = spy(mHelper.createGroup(numChildren));
-        when(row.getIsNonblockable()).thenReturn(false);
-        return row;
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
index 8fd6842..35d2363b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
@@ -3,19 +3,21 @@
 import android.annotation.DimenRes
 import android.widget.FrameLayout
 import androidx.test.filters.SmallTest
+import com.android.keyguard.BouncerPanelExpansionCalculator.aboutToShowBouncerProgress
 import com.android.systemui.R
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.animation.ShadeInterpolation.getContentAlpha
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.statusbar.EmptyShadeView
+import com.android.systemui.statusbar.NotificationShelf
+import com.android.systemui.statusbar.StatusBarState
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
 import com.android.systemui.statusbar.notification.row.ExpandableView
-import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm.BypassController
-import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm.SectionProvider
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
 import com.google.common.truth.Truth.assertThat
+import junit.framework.Assert.assertEquals
 import junit.framework.Assert.assertFalse
 import junit.framework.Assert.assertTrue
-import junit.framework.Assert.assertEquals
 import org.junit.Before
 import org.junit.Test
 import org.mockito.Mockito.mock
@@ -26,17 +28,20 @@
 
     private val hostView = FrameLayout(context)
     private val stackScrollAlgorithm = StackScrollAlgorithm(context, hostView)
-    private val expandableViewState = ExpandableViewState()
     private val notificationRow = mock(ExpandableNotificationRow::class.java)
     private val dumpManager = mock(DumpManager::class.java)
     private val mStatusBarKeyguardViewManager = mock(StatusBarKeyguardViewManager::class.java)
+    private val notificationShelf = mock(NotificationShelf::class.java)
+    private val emptyShadeView = EmptyShadeView(context, /* attrs= */ null).apply {
+        layout(/* l= */ 0, /* t= */ 0, /* r= */ 100, /* b= */ 100)
+    }
 
     private val ambientState = AmbientState(
-        context,
-        dumpManager,
-        SectionProvider { _, _ -> false },
-        BypassController { false },
-        mStatusBarKeyguardViewManager
+            context,
+            dumpManager,
+            /* sectionProvider */ { _, _ -> false },
+            /* bypassController */ { false },
+            mStatusBarKeyguardViewManager
     )
 
     private val testableResources = mContext.orCreateTestableResources
@@ -49,7 +54,9 @@
 
     @Before
     fun setUp() {
-        whenever(notificationRow.viewState).thenReturn(expandableViewState)
+        whenever(notificationShelf.viewState).thenReturn(ExpandableViewState())
+        whenever(notificationRow.viewState).thenReturn(ExpandableViewState())
+
         hostView.addView(notificationRow)
     }
 
@@ -60,7 +67,8 @@
 
         stackScrollAlgorithm.resetViewStates(ambientState, 0)
 
-        assertThat(expandableViewState.yTranslation).isEqualTo(stackScrollAlgorithm.mHeadsUpInset)
+        assertThat(notificationRow.viewState.yTranslation)
+                .isEqualTo(stackScrollAlgorithm.mHeadsUpInset)
     }
 
     @Test
@@ -75,15 +83,12 @@
         stackScrollAlgorithm.resetViewStates(ambientState, 0)
 
         // top margin presence should decrease heads up translation up to minHeadsUpTranslation
-        assertThat(expandableViewState.yTranslation).isEqualTo(minHeadsUpTranslation)
+        assertThat(notificationRow.viewState.yTranslation).isEqualTo(minHeadsUpTranslation)
     }
 
     @Test
     fun resetViewStates_emptyShadeView_isCenteredVertically() {
         stackScrollAlgorithm.initView(context)
-        val emptyShadeView = EmptyShadeView(context, /* attrs= */ null).apply {
-            layout(/* l= */ 0, /* t= */ 0, /* r= */ 100, /* b= */ 100)
-        }
         hostView.removeAllViews()
         hostView.addView(emptyShadeView)
         ambientState.layoutMaxHeight = 1280
@@ -98,6 +103,121 @@
     }
 
     @Test
+    fun resetViewStates_hunGoingToShade_viewBecomesOpaque() {
+        whenever(notificationRow.isAboveShelf).thenReturn(true)
+        ambientState.isShadeExpanded = true
+        ambientState.trackedHeadsUpRow = notificationRow
+        stackScrollAlgorithm.initView(context)
+
+        stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
+
+        assertThat(notificationRow.viewState.alpha).isEqualTo(1f)
+    }
+
+    @Test
+    fun resetViewStates_isExpansionChanging_viewBecomesTransparent() {
+        whenever(mStatusBarKeyguardViewManager.isBouncerInTransit).thenReturn(false)
+        ambientState.isExpansionChanging = true
+        ambientState.expansionFraction = 0.25f
+        stackScrollAlgorithm.initView(context)
+
+        stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
+
+        val expected = getContentAlpha(0.25f)
+        assertThat(notificationRow.viewState.alpha).isEqualTo(expected)
+    }
+
+    @Test
+    fun resetViewStates_isExpansionChangingWhileBouncerInTransit_viewBecomesTransparent() {
+        whenever(mStatusBarKeyguardViewManager.isBouncerInTransit).thenReturn(true)
+        ambientState.isExpansionChanging = true
+        ambientState.expansionFraction = 0.25f
+        stackScrollAlgorithm.initView(context)
+
+        stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
+
+        val expected = aboutToShowBouncerProgress(0.25f)
+        assertThat(notificationRow.viewState.alpha).isEqualTo(expected)
+    }
+
+    @Test
+    fun resetViewStates_isOnKeyguard_viewBecomesTransparent() {
+        ambientState.setStatusBarState(StatusBarState.KEYGUARD)
+        ambientState.hideAmount = 0.25f
+        stackScrollAlgorithm.initView(context)
+
+        stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
+
+        assertThat(notificationRow.viewState.alpha).isEqualTo(1f - ambientState.hideAmount)
+    }
+
+    @Test
+    fun resetViewStates_isOnKeyguard_emptyShadeViewBecomesTransparent() {
+        ambientState.setStatusBarState(StatusBarState.KEYGUARD)
+        ambientState.fractionToShade = 0.25f
+        stackScrollAlgorithm.initView(context)
+        hostView.removeAllViews()
+        hostView.addView(emptyShadeView)
+
+        stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
+
+        val expected = getContentAlpha(ambientState.fractionToShade)
+        assertThat(emptyShadeView.viewState.alpha).isEqualTo(expected)
+    }
+
+    @Test
+    fun resetViewStates_isOnKeyguard_emptyShadeViewBecomesOpaque() {
+        ambientState.setStatusBarState(StatusBarState.SHADE)
+        ambientState.fractionToShade = 0.25f
+        stackScrollAlgorithm.initView(context)
+        hostView.removeAllViews()
+        hostView.addView(emptyShadeView)
+
+        stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
+
+        assertThat(emptyShadeView.viewState.alpha).isEqualTo(1f)
+    }
+
+    @Test
+    fun resetViewStates_hiddenShelf_viewAlphaDoesNotChange() {
+        val expected = notificationShelf.viewState.alpha
+        notificationShelf.viewState.hidden = true
+        ambientState.shelf = notificationShelf
+        stackScrollAlgorithm.initView(context)
+
+        stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
+
+        assertThat(notificationShelf.viewState.alpha).isEqualTo(expected)
+    }
+
+    @Test
+    fun resetViewStates_shelfTopLessThanViewTop_hidesView() {
+        notificationRow.viewState.yTranslation = 10f
+        notificationShelf.viewState.yTranslation = 0.9f
+        notificationShelf.viewState.hidden = false
+        ambientState.shelf = notificationShelf
+        stackScrollAlgorithm.initView(context)
+
+        stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
+
+        assertThat(notificationRow.viewState.alpha).isEqualTo(0f)
+    }
+
+    @Test
+    fun resetViewStates_shelfTopGreaterOrEqualThanViewTop_viewAlphaDoesNotChange() {
+        val expected = notificationRow.viewState.alpha
+        notificationRow.viewState.yTranslation = 10f
+        notificationShelf.viewState.yTranslation = 10f
+        notificationShelf.viewState.hidden = false
+        ambientState.shelf = notificationShelf
+        stackScrollAlgorithm.initView(context)
+
+        stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
+
+        assertThat(notificationRow.viewState.alpha).isEqualTo(expected)
+    }
+
+    @Test
     fun getGapForLocation_onLockscreen_returnsSmallGap() {
         val gap = stackScrollAlgorithm.getGapForLocation(
                 /* fractionToShade= */ 0f, /* onKeyguard= */ true)
@@ -267,7 +387,6 @@
         assertEquals(10f, expandableViewState.yTranslation)
     }
 
-
     @Test
     fun clampHunToTop_viewYFarAboveVisibleStack_heightCollapsed() {
         val expandableViewState = ExpandableViewState()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java
index a6b7e51..ca98143 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java
@@ -58,7 +58,6 @@
     @Before
     public void setup() {
         injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
-        mDependency.injectMockDependency(DarkIconDispatcher.class);
     }
 
     @Test
@@ -75,7 +74,8 @@
                 layout,
                 mock(FeatureFlags.class),
                 mock(StatusBarPipelineFlags.class),
-                () -> mock(WifiViewModel.class));
+                () -> mock(WifiViewModel.class),
+                mock(DarkIconDispatcher.class));
         testCallOnAdd_forManager(manager);
     }
 
@@ -116,8 +116,10 @@
                 LinearLayout group,
                 FeatureFlags featureFlags,
                 StatusBarPipelineFlags statusBarPipelineFlags,
-                Provider<WifiViewModel> wifiViewModelProvider) {
-            super(group, featureFlags, statusBarPipelineFlags, wifiViewModelProvider);
+                Provider<WifiViewModel> wifiViewModelProvider,
+                DarkIconDispatcher darkIconDispatcher) {
+            super(group, featureFlags, statusBarPipelineFlags, wifiViewModelProvider,
+                    darkIconDispatcher);
         }
 
         @Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositoryImplTest.kt
index 9829271..d070ba0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositoryImplTest.kt
@@ -473,6 +473,40 @@
         job.cancel()
     }
 
+    /** Regression test for b/244173280. */
+    @Test
+    fun wifiNetwork_multipleSubscribers_newSubscribersGetCurrentValue() = runBlocking(IMMEDIATE) {
+        var latest1: WifiNetworkModel? = null
+        val job1 = underTest
+            .wifiNetwork
+            .onEach { latest1 = it }
+            .launchIn(this)
+
+        getNetworkCallback()
+            .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(PRIMARY_WIFI_INFO))
+
+        assertThat(latest1 is WifiNetworkModel.Active).isTrue()
+        val latest1Active = latest1 as WifiNetworkModel.Active
+        assertThat(latest1Active.networkId).isEqualTo(NETWORK_ID)
+        assertThat(latest1Active.ssid).isEqualTo(SSID)
+
+        // WHEN we add a second subscriber after having already emitted a value
+        var latest2: WifiNetworkModel? = null
+        val job2 = underTest
+            .wifiNetwork
+            .onEach { latest2 = it }
+            .launchIn(this)
+
+        // THEN the second subscribe receives the already-emitted value
+        assertThat(latest2 is WifiNetworkModel.Active).isTrue()
+        val latest2Active = latest2 as WifiNetworkModel.Active
+        assertThat(latest2Active.networkId).isEqualTo(NETWORK_ID)
+        assertThat(latest2Active.ssid).isEqualTo(SSID)
+
+        job1.cancel()
+        job2.cancel()
+    }
+
     @Test
     fun wifiActivity_nullWifiManager_receivesDefault() = runBlocking(IMMEDIATE) {
         underTest = WifiRepositoryImpl(
diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
index cdddc1d..2b644fe 100644
--- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
@@ -41,6 +41,7 @@
 import android.os.Parcel;
 import android.os.RemoteException;
 import android.os.UserHandle;
+import android.util.ArraySet;
 import android.util.ExceptionUtils;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -87,6 +88,12 @@
     private final SparseArray<VirtualDeviceImpl> mVirtualDevices = new SparseArray<>();
 
     /**
+     * Mapping from CDM association IDs to app UIDs running on the corresponding virtual device.
+     */
+    @GuardedBy("mVirtualDeviceManagerLock")
+    private final SparseArray<ArraySet<Integer>> mAppsOnVirtualDevices = new SparseArray<>();
+
+    /**
      * Mapping from user ID to CDM associations. The associations come from
      * {@link CompanionDeviceManager#getAllAssociations()}, which contains associations across all
      * packages.
@@ -213,6 +220,14 @@
         return mLocalService;
     }
 
+    @VisibleForTesting
+    void notifyRunningAppsChanged(int associationId, ArraySet<Integer> uids) {
+        synchronized (mVirtualDeviceManagerLock) {
+            mAppsOnVirtualDevices.put(associationId, uids);
+        }
+        mLocalService.onAppsOnVirtualDeviceChanged();
+    }
+
     class VirtualDeviceManagerImpl extends IVirtualDeviceManager.Stub implements
             VirtualDeviceImpl.PendingTrampolineCallback {
 
@@ -252,6 +267,7 @@
                             public void onClose(int associationId) {
                                 synchronized (mVirtualDeviceManagerLock) {
                                     mVirtualDevices.remove(associationId);
+                                    mAppsOnVirtualDevices.remove(associationId);
                                     if (cameraAccessController != null) {
                                         cameraAccessController.stopObservingIfNeeded();
                                     } else {
@@ -262,8 +278,10 @@
                             }
                         },
                         this, activityListener,
-                        runningUids -> cameraAccessController.blockCameraAccessIfNeeded(
-                                runningUids),
+                        runningUids -> {
+                            cameraAccessController.blockCameraAccessIfNeeded(runningUids);
+                            notifyRunningAppsChanged(associationInfo.getId(), runningUids);
+                        },
                         params);
                 if (cameraAccessController != null) {
                     cameraAccessController.startObservingIfNeeded();
@@ -385,8 +403,13 @@
 
     private final class LocalService extends VirtualDeviceManagerInternal {
         @GuardedBy("mVirtualDeviceManagerLock")
-        private final ArrayList<VirtualDeviceManagerInternal.VirtualDisplayListener>
+        private final ArrayList<VirtualDisplayListener>
                 mVirtualDisplayListeners = new ArrayList<>();
+        @GuardedBy("mVirtualDeviceManagerLock")
+        private final ArrayList<AppsOnVirtualDeviceListener>
+                mAppsOnVirtualDeviceListeners = new ArrayList<>();
+        @GuardedBy("mVirtualDeviceManagerLock")
+        private final ArraySet<Integer> mAllUidsOnVirtualDevice = new ArraySet<>();
 
         @Override
         public boolean isValidVirtualDevice(IVirtualDevice virtualDevice) {
@@ -423,6 +446,34 @@
         }
 
         @Override
+        public void onAppsOnVirtualDeviceChanged() {
+            ArraySet<Integer> latestRunningUids = new ArraySet<>();
+            final AppsOnVirtualDeviceListener[] listeners;
+            synchronized (mVirtualDeviceManagerLock) {
+                int size = mAppsOnVirtualDevices.size();
+                for (int i = 0; i < size; i++) {
+                    latestRunningUids.addAll(mAppsOnVirtualDevices.valueAt(i));
+                }
+                if (!mAllUidsOnVirtualDevice.equals(latestRunningUids)) {
+                    mAllUidsOnVirtualDevice.clear();
+                    mAllUidsOnVirtualDevice.addAll(latestRunningUids);
+                    listeners =
+                            mAppsOnVirtualDeviceListeners.toArray(
+                                    new AppsOnVirtualDeviceListener[0]);
+                } else {
+                    listeners = null;
+                }
+            }
+            if (listeners != null) {
+                mHandler.post(() -> {
+                    for (AppsOnVirtualDeviceListener listener : listeners) {
+                        listener.onAppsOnAnyVirtualDeviceChanged(latestRunningUids);
+                    }
+                });
+            }
+        }
+
+        @Override
         public int getBaseVirtualDisplayFlags(IVirtualDevice virtualDevice) {
             return ((VirtualDeviceImpl) virtualDevice).getBaseVirtualDisplayFlags();
         }
@@ -481,6 +532,22 @@
                 mVirtualDisplayListeners.remove(listener);
             }
         }
+
+        @Override
+        public void registerAppsOnVirtualDeviceListener(
+                @NonNull AppsOnVirtualDeviceListener listener) {
+            synchronized (mVirtualDeviceManagerLock) {
+                mAppsOnVirtualDeviceListeners.add(listener);
+            }
+        }
+
+        @Override
+        public void unregisterAppsOnVirtualDeviceListener(
+                @NonNull AppsOnVirtualDeviceListener listener) {
+            synchronized (mVirtualDeviceManagerLock) {
+                mAppsOnVirtualDeviceListeners.remove(listener);
+            }
+        }
     }
 
     private static final class PendingTrampolineMap {
diff --git a/services/core/java/com/android/server/companion/virtual/VirtualDeviceManagerInternal.java b/services/core/java/com/android/server/companion/virtual/VirtualDeviceManagerInternal.java
index 230bfc5..81b56a3 100644
--- a/services/core/java/com/android/server/companion/virtual/VirtualDeviceManagerInternal.java
+++ b/services/core/java/com/android/server/companion/virtual/VirtualDeviceManagerInternal.java
@@ -19,6 +19,8 @@
 import android.annotation.NonNull;
 import android.companion.virtual.IVirtualDevice;
 
+import java.util.Set;
+
 /**
  * Virtual device manager local service interface.
  * Only for use within system server.
@@ -34,14 +36,35 @@
         void onVirtualDisplayRemoved(int displayId);
     }
 
+
+    /** Interface to listen to the changes on the list of app UIDs running on any virtual device. */
+    public interface AppsOnVirtualDeviceListener {
+        /** Notifies that running apps on any virtual device has changed */
+        void onAppsOnAnyVirtualDeviceChanged(Set<Integer> allRunningUids);
+    }
+
     /** Register a listener for the creation and destruction of virtual displays. */
     public abstract void registerVirtualDisplayListener(
             @NonNull VirtualDisplayListener listener);
 
-    /** Unregister a listener for the creation and  destruction of virtual displays. */
+    /** Unregister a listener for the creation and destruction of virtual displays. */
     public abstract void unregisterVirtualDisplayListener(
             @NonNull VirtualDisplayListener listener);
 
+    /** Register a listener for changes of running app UIDs on any virtual device. */
+    public abstract void registerAppsOnVirtualDeviceListener(
+            @NonNull AppsOnVirtualDeviceListener listener);
+
+    /** Unregister a listener for changes of running app UIDs on any virtual device. */
+    public abstract void unregisterAppsOnVirtualDeviceListener(
+            @NonNull AppsOnVirtualDeviceListener listener);
+
+    /**
+     * Notifies that the set of apps running on virtual devices has changed.
+     * This method only notifies the listeners when the union of running UIDs on all virtual devices
+     * has changed.
+     */
+    public abstract void onAppsOnVirtualDeviceChanged();
 
     /**
      * Validate the virtual device.
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
index 966df4f..cc2cdba 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
@@ -35,6 +35,7 @@
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.when;
 import static org.testng.Assert.assertThrows;
 
@@ -110,6 +111,12 @@
     private static final String GOOGLE_MAPS_PACKAGE_NAME = "com.google.android.apps.maps";
     private static final String DEVICE_NAME = "device name";
     private static final int DISPLAY_ID = 2;
+    private static final int UID_1 = 0;
+    private static final int UID_2 = 10;
+    private static final int UID_3 = 10000;
+    private static final int UID_4 = 10001;
+    private static final int ASSOCIATION_ID_1 = 1;
+    private static final int ASSOCIATION_ID_2 = 2;
     private static final int PRODUCT_ID = 10;
     private static final int VENDOR_ID = 5;
     private static final String UNIQUE_ID = "uniqueid";
@@ -143,6 +150,8 @@
     @Mock
     private VirtualDeviceManagerInternal.VirtualDisplayListener mDisplayListener;
     @Mock
+    private VirtualDeviceManagerInternal.AppsOnVirtualDeviceListener mAppsOnVirtualDeviceListener;
+    @Mock
     IPowerManager mIPowerManagerMock;
     @Mock
     IThermalService mIThermalServiceMock;
@@ -242,7 +251,7 @@
     }
 
     @Test
-    public void onVirtualDisplayCreatedLocked_listenersNotified() throws RemoteException {
+    public void onVirtualDisplayCreatedLocked_listenersNotified() {
         mLocalService.registerVirtualDisplayListener(mDisplayListener);
 
         mLocalService.onVirtualDisplayCreated(DISPLAY_ID);
@@ -252,7 +261,7 @@
     }
 
     @Test
-    public void onVirtualDisplayRemovedLocked_listenersNotified() throws RemoteException {
+    public void onVirtualDisplayRemovedLocked_listenersNotified() {
         mLocalService.registerVirtualDisplayListener(mDisplayListener);
         mDeviceImpl.onVirtualDisplayCreatedLocked(
                 mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
@@ -264,13 +273,61 @@
     }
 
     @Test
+    public void onAppsOnVirtualDeviceChanged_singleVirtualDevice_listenersNotified() {
+        ArraySet<Integer> uids = new ArraySet<>(Arrays.asList(UID_1, UID_2));
+        mLocalService.registerAppsOnVirtualDeviceListener(mAppsOnVirtualDeviceListener);
+
+        mVdms.notifyRunningAppsChanged(ASSOCIATION_ID_1, uids);
+        TestableLooper.get(this).processAllMessages();
+
+        verify(mAppsOnVirtualDeviceListener).onAppsOnAnyVirtualDeviceChanged(uids);
+    }
+
+    @Test
+    public void onAppsOnVirtualDeviceChanged_multipleVirtualDevices_listenersNotified() {
+        ArraySet<Integer> uidsOnDevice1 = new ArraySet<>(Arrays.asList(UID_1, UID_2));
+        ArraySet<Integer> uidsOnDevice2 = new ArraySet<>(Arrays.asList(UID_3, UID_4));
+        mLocalService.registerAppsOnVirtualDeviceListener(mAppsOnVirtualDeviceListener);
+
+        // Notifies that the running apps on the first virtual device has changed.
+        mVdms.notifyRunningAppsChanged(ASSOCIATION_ID_1, uidsOnDevice1);
+        TestableLooper.get(this).processAllMessages();
+        verify(mAppsOnVirtualDeviceListener).onAppsOnAnyVirtualDeviceChanged(
+                new ArraySet<>(Arrays.asList(UID_1, UID_2)));
+
+        // Notifies that the running apps on the second virtual device has changed.
+        mVdms.notifyRunningAppsChanged(ASSOCIATION_ID_2, uidsOnDevice2);
+        TestableLooper.get(this).processAllMessages();
+        // The union of the apps running on both virtual devices are sent to the listeners.
+        verify(mAppsOnVirtualDeviceListener).onAppsOnAnyVirtualDeviceChanged(
+                new ArraySet<>(Arrays.asList(UID_1, UID_2, UID_3, UID_4)));
+
+        // Notifies that the running apps on the first virtual device has changed again.
+        uidsOnDevice1.remove(UID_2);
+        mVdms.notifyRunningAppsChanged(ASSOCIATION_ID_1, uidsOnDevice1);
+        mLocalService.onAppsOnVirtualDeviceChanged();
+        TestableLooper.get(this).processAllMessages();
+        // The union of the apps running on both virtual devices are sent to the listeners.
+        verify(mAppsOnVirtualDeviceListener).onAppsOnAnyVirtualDeviceChanged(
+                new ArraySet<>(Arrays.asList(UID_1, UID_3, UID_4)));
+
+        // Notifies that the running apps on the first virtual device has changed but with the same
+        // set of UIDs.
+        mVdms.notifyRunningAppsChanged(ASSOCIATION_ID_1, uidsOnDevice1);
+        mLocalService.onAppsOnVirtualDeviceChanged();
+        TestableLooper.get(this).processAllMessages();
+        // Listeners should not be notified.
+        verifyNoMoreInteractions(mAppsOnVirtualDeviceListener);
+    }
+
+    @Test
     public void onVirtualDisplayCreatedLocked_wakeLockIsAcquired() throws RemoteException {
         verify(mIPowerManagerMock, never()).acquireWakeLock(any(Binder.class), anyInt(),
                 nullable(String.class), nullable(String.class), nullable(WorkSource.class),
                 nullable(String.class), anyInt(), eq(null));
         mDeviceImpl.onVirtualDisplayCreatedLocked(
                 mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
-        verify(mIPowerManagerMock, Mockito.times(1)).acquireWakeLock(any(Binder.class), anyInt(),
+        verify(mIPowerManagerMock).acquireWakeLock(any(Binder.class), anyInt(),
                 nullable(String.class), nullable(String.class), nullable(WorkSource.class),
                 nullable(String.class), eq(DISPLAY_ID), eq(null));
     }
@@ -284,7 +341,7 @@
         assertThrows(IllegalStateException.class,
                 () -> mDeviceImpl.onVirtualDisplayCreatedLocked(gwpc, DISPLAY_ID));
         TestableLooper.get(this).processAllMessages();
-        verify(mIPowerManagerMock, Mockito.times(1)).acquireWakeLock(any(Binder.class), anyInt(),
+        verify(mIPowerManagerMock).acquireWakeLock(any(Binder.class), anyInt(),
                 nullable(String.class), nullable(String.class), nullable(WorkSource.class),
                 nullable(String.class), eq(DISPLAY_ID), eq(null));
     }
@@ -302,14 +359,14 @@
                 mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
         ArgumentCaptor<IBinder> wakeLockCaptor = ArgumentCaptor.forClass(IBinder.class);
         TestableLooper.get(this).processAllMessages();
-        verify(mIPowerManagerMock, Mockito.times(1)).acquireWakeLock(wakeLockCaptor.capture(),
+        verify(mIPowerManagerMock).acquireWakeLock(wakeLockCaptor.capture(),
                 anyInt(),
                 nullable(String.class), nullable(String.class), nullable(WorkSource.class),
                 nullable(String.class), eq(DISPLAY_ID), eq(null));
 
         IBinder wakeLock = wakeLockCaptor.getValue();
         mDeviceImpl.onVirtualDisplayRemovedLocked(DISPLAY_ID);
-        verify(mIPowerManagerMock, Mockito.times(1)).releaseWakeLock(eq(wakeLock), anyInt());
+        verify(mIPowerManagerMock).releaseWakeLock(eq(wakeLock), anyInt());
     }
 
     @Test
@@ -318,7 +375,7 @@
                 mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
         ArgumentCaptor<IBinder> wakeLockCaptor = ArgumentCaptor.forClass(IBinder.class);
         TestableLooper.get(this).processAllMessages();
-        verify(mIPowerManagerMock, Mockito.times(1)).acquireWakeLock(wakeLockCaptor.capture(),
+        verify(mIPowerManagerMock).acquireWakeLock(wakeLockCaptor.capture(),
                 anyInt(),
                 nullable(String.class), nullable(String.class), nullable(WorkSource.class),
                 nullable(String.class), eq(DISPLAY_ID), eq(null));
@@ -326,7 +383,7 @@
 
         // Close the VirtualDevice without first notifying it of the VirtualDisplay removal.
         mDeviceImpl.close();
-        verify(mIPowerManagerMock, Mockito.times(1)).releaseWakeLock(eq(wakeLock), anyInt());
+        verify(mIPowerManagerMock).releaseWakeLock(eq(wakeLock), anyInt());
     }
 
     @Test