Merge "[CredManUI] UI style P0 fixes" into udc-dev
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 6422865..3615435 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -198,6 +198,26 @@
  * possible for a node to contain outdated information because the window content may change at any
  * time.
  * </p>
+ * <h3>Drawing Accessibility Overlays</h3>
+ * <p>Accessibility services can draw overlays on top of existing screen contents.
+ * Accessibility overlays can be used to visually highlight items on the screen
+ * e.g. indicate the current item with accessibility focus.
+ * Overlays can also offer the user a way to interact with the service directly and quickly
+ * customize the service's behavior.</p>
+ * <p>Accessibility overlays can be attached to a particular window or to the display itself.
+ * Attaching an overlay to a window allows the overly to move, grow and shrink as the window does.
+ * The overlay will maintain the same relative position within the window bounds as the window
+ * moves. The overlay will also maintain the same relative position within the window bounds if
+ * the window is resized.
+ * To attach an overlay to a window, use {@link attachAccessibilityOverlayToWindow}.
+ * Attaching an overlay to the display means that the overlay is independent of the active
+ * windows on that display.
+ * To attach an overlay to a display, use {@link attachAccessibilityOverlayToDisplay}. </p>
+ * <p> When positioning an overlay that is attached to a window, the service must use window
+ * coordinates. In order to position an overlay on top of an existing UI element it is necessary
+ * to know the bounds of that element in window coordinates. To find the bounds in window
+ * coordinates of an element, find the corresponding {@link AccessibilityNodeInfo} as discussed
+ * above and call {@link AccessibilityNodeInfo#getBoundsInWindow}. </p>
  * <h3>Notification strategy</h3>
  * <p>
  * All accessibility services are notified of all events they have requested, regardless of their
@@ -3421,22 +3441,28 @@
     }
 
     /**
-     * Attaches a {@link android.view.SurfaceControl} containing an accessibility
+     * <p>Attaches a {@link android.view.SurfaceControl} containing an accessibility
      * overlay to the
      * specified display. This type of overlay should be used for content that does
      * not need to
      * track the location and size of Views in the currently active app e.g. service
      * configuration
-     * or general service UI. To remove this overlay and free the associated
+     * or general service UI.</p>
+     * <p>Generally speaking, an accessibility overlay  will be  a {@link android.view.View}.
+     * To embed the View into a {@link android.view.SurfaceControl}, create a
+     * {@link android.view.SurfaceControlViewHost} and attach the View using
+     * {@link android.view.SurfaceControlViewHost#setView}. Then obtain the SurfaceControl by
+     * calling <code> viewHost.getSurfacePackage().getSurfaceControl()</code>.</p>
+     * <p>To remove this overlay and free the associated
      * resources, use
-     * <code> new SurfaceControl.Transaction().reparent(sc, null).apply();</code>.
-     * If the specified overlay has already been attached to the specified display
+     * <code> new SurfaceControl.Transaction().reparent(sc, null).apply();</code>.</p>
+     * <p>If the specified overlay has already been attached to the specified display
      * this method does nothing.
      * If the specified overlay has already been attached to a previous display this
      * function will transfer the overlay to the new display.
      * Services can attach multiple overlays. Use
      * <code> new SurfaceControl.Transaction().setLayer(sc, layer).apply();</code>.
-     * to coordinate the order of the overlays on screen.
+     * to coordinate the order of the overlays on screen.</p>
      *
      * @param displayId the display to which the SurfaceControl should be attached.
      * @param sc        the SurfaceControl containing the overlay content
@@ -3456,20 +3482,24 @@
     }
 
     /**
-     * Attaches an accessibility overlay {@link android.view.SurfaceControl} to the
+     * <p>Attaches an accessibility overlay {@link android.view.SurfaceControl} to the
      * specified
      * window. This method should be used when you want the overlay to move and
-     * resize as the parent
-     * window moves and resizes. To remove this overlay and free the associated
-     * resources, use
-     * <code> new SurfaceControl.Transaction().reparent(sc, null).apply();</code>.
-     * If the specified overlay has already been attached to the specified window
+     * resize as the parent window moves and resizes.</p>
+     * <p>Generally speaking, an accessibility overlay  will be  a {@link android.view.View}.
+     * To embed the View into a {@link android.view.SurfaceControl}, create a
+     * {@link android.view.SurfaceControlViewHost} and attach the View using
+     * {@link android.view.SurfaceControlViewHost#setView}. Then obtain the SurfaceControl by
+     * calling <code> viewHost.getSurfacePackage().getSurfaceControl()</code>.</p>
+     * <p>To remove this overlay and free the associated resources, use
+     * <code> new SurfaceControl.Transaction().reparent(sc, null).apply();</code>.</p>
+     * <p>If the specified overlay has already been attached to the specified window
      * this method does nothing.
      * If the specified overlay has already been attached to a previous window this
      * function will transfer the overlay to the new window.
      * Services can attach multiple overlays. Use
      * <code> new SurfaceControl.Transaction().setLayer(sc, layer).apply();</code>.
-     * to coordinate the order of the overlays on screen.
+     * to coordinate the order of the overlays on screen.</p>
      *
      * @param accessibilityWindowId The window id, from
      *                              {@link AccessibilityWindowInfo#getId()}.
diff --git a/core/java/android/credentials/CreateCredentialRequest.java b/core/java/android/credentials/CreateCredentialRequest.java
index b756a43..c89a5c6 100644
--- a/core/java/android/credentials/CreateCredentialRequest.java
+++ b/core/java/android/credentials/CreateCredentialRequest.java
@@ -244,7 +244,7 @@
     /** A builder for {@link CreateCredentialRequest}. */
     public static final class Builder {
 
-        private boolean mAlwaysSendAppInfoToProvider;
+        private boolean mAlwaysSendAppInfoToProvider = true;
 
         @NonNull
         private String mType;
diff --git a/core/java/android/credentials/ui/CancelUiRequest.java b/core/java/android/credentials/ui/CancelUiRequest.java
new file mode 100644
index 0000000..6bd9de4
--- /dev/null
+++ b/core/java/android/credentials/ui/CancelUiRequest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 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 android.credentials.ui;
+
+import android.annotation.NonNull;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.AnnotationValidations;
+
+/**
+ * A request to cancel any ongoing UI matching this request.
+ *
+ * @hide
+ */
+public final class CancelUiRequest implements Parcelable {
+
+    /**
+     * The intent extra key for the {@code CancelUiRequest} object when launching the UX
+     * activities.
+     */
+    @NonNull public static final String EXTRA_CANCEL_UI_REQUEST =
+            "android.credentials.ui.extra.EXTRA_CANCEL_UI_REQUEST";
+
+    @NonNull
+    private final IBinder mToken;
+
+    /** Returns the request token matching the user request that should be cancelled. */
+    @NonNull
+    public IBinder getToken() {
+        return mToken;
+    }
+
+    public CancelUiRequest(@NonNull IBinder token) {
+        mToken = token;
+    }
+
+    private CancelUiRequest(@NonNull Parcel in) {
+        mToken = in.readStrongBinder();
+        AnnotationValidations.validate(NonNull.class, null, mToken);
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeStrongBinder(mToken);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @NonNull public static final Creator<CancelUiRequest> CREATOR = new Creator<>() {
+        @Override
+        public CancelUiRequest createFromParcel(@NonNull Parcel in) {
+            return new CancelUiRequest(in);
+        }
+
+        @Override
+        public CancelUiRequest[] newArray(int size) {
+            return new CancelUiRequest[size];
+        }
+    };
+}
diff --git a/core/java/android/credentials/ui/IntentFactory.java b/core/java/android/credentials/ui/IntentFactory.java
index 3c10e81..dcfef56 100644
--- a/core/java/android/credentials/ui/IntentFactory.java
+++ b/core/java/android/credentials/ui/IntentFactory.java
@@ -22,6 +22,7 @@
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.res.Resources;
+import android.os.IBinder;
 import android.os.Parcel;
 import android.os.ResultReceiver;
 
@@ -66,6 +67,25 @@
     }
 
     /**
+     * Creates an Intent that cancels any UI matching the given request token id.
+     *
+     * @hide
+     */
+    @NonNull
+    public static Intent createCancelUiIntent(@NonNull IBinder requestToken) {
+        Intent intent = new Intent();
+        ComponentName componentName =
+                ComponentName.unflattenFromString(
+                        Resources.getSystem()
+                                .getString(
+                                        com.android.internal.R.string
+                                                .config_credentialManagerDialogComponent));
+        intent.setComponent(componentName);
+        intent.putExtra(CancelUiRequest.EXTRA_CANCEL_UI_REQUEST, new CancelUiRequest(requestToken));
+        return intent;
+    }
+
+    /**
      * Notify the UI that providers have been enabled/disabled.
      *
      * @hide
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
index f8ad196..3d718a2 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
@@ -23,6 +23,7 @@
 import android.credentials.CredentialOption
 import android.credentials.GetCredentialRequest
 import android.credentials.ui.AuthenticationEntry
+import android.credentials.ui.CancelUiRequest
 import android.credentials.ui.Constants
 import android.credentials.ui.Entry
 import android.credentials.ui.CreateCredentialProviderData
@@ -223,6 +224,14 @@
                 resultReceiver.send(cancelCode, resultData)
             }
         }
+
+        /** Return the request token whose UI should be cancelled, or null otherwise. */
+        fun getCancelUiRequestToken(intent: Intent): IBinder? {
+            return intent.extras?.getParcelable(
+                CancelUiRequest.EXTRA_CANCEL_UI_REQUEST,
+                CancelUiRequest::class.java
+            )?.token
+        }
     }
 
     // TODO: below are prototype functionalities. To be removed for productionization.
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt
index a3e4c81..e8e3974 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt
@@ -47,6 +47,12 @@
         super.onCreate(savedInstanceState)
         Log.d(Constants.LOG_TAG, "Creating new CredentialSelectorActivity")
         try {
+            if (CredentialManagerRepo.getCancelUiRequestToken(intent) != null) {
+                Log.d(
+                    Constants.LOG_TAG, "Received UI cancellation intent; cancelling the activity.")
+                this.finish()
+                return
+            }
             val userConfigRepo = UserConfigRepo(this)
             val credManRepo = CredentialManagerRepo(this, intent, userConfigRepo)
             setContent {
@@ -67,10 +73,19 @@
         setIntent(intent)
         Log.d(Constants.LOG_TAG, "Existing activity received new intent")
         try {
-            val userConfigRepo = UserConfigRepo(this)
-            val credManRepo = CredentialManagerRepo(this, intent, userConfigRepo)
+            val cancelUiRequestToken = CredentialManagerRepo.getCancelUiRequestToken(intent)
             val viewModel: CredentialSelectorViewModel by viewModels()
-            viewModel.onNewCredentialManagerRepo(credManRepo)
+            if (cancelUiRequestToken != null &&
+                viewModel.shouldCancelCurrentUi(cancelUiRequestToken)) {
+                Log.d(
+                    Constants.LOG_TAG, "Received UI cancellation intent; cancelling the activity.")
+                this.finish()
+                return
+            } else {
+                val userConfigRepo = UserConfigRepo(this)
+                val credManRepo = CredentialManagerRepo(this, intent, userConfigRepo)
+                viewModel.onNewCredentialManagerRepo(credManRepo)
+            }
         } catch (e: Exception) {
             onInitializationError(e, intent)
         }
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt
index a1e0823..9b7139c 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt
@@ -17,6 +17,7 @@
 package com.android.credentialmanager
 
 import android.app.Activity
+import android.os.IBinder
 import android.util.Log
 import androidx.activity.compose.ManagedActivityResultLauncher
 import androidx.activity.result.ActivityResult
@@ -135,6 +136,11 @@
         uiState = uiState.copy(dialogState = DialogState.COMPLETE)
     }
 
+    /** Return true if the current UI's request token matches the UI cancellation request token. */
+    fun shouldCancelCurrentUi(cancelRequestToken: IBinder): Boolean {
+        return credManRepo.requestInfo.token.equals(cancelRequestToken)
+    }
+
     /**************************************************************************/
     /*****                      Get Flow Callbacks                        *****/
     /**************************************************************************/
diff --git a/packages/DynamicSystemInstallationService/AndroidManifest.xml b/packages/DynamicSystemInstallationService/AndroidManifest.xml
index b194738..c2aaeac 100644
--- a/packages/DynamicSystemInstallationService/AndroidManifest.xml
+++ b/packages/DynamicSystemInstallationService/AndroidManifest.xml
@@ -21,12 +21,7 @@
             android:exported="true"
             android:permission="android.permission.INSTALL_DYNAMIC_SYSTEM"
             android:foregroundServiceType="systemExempted"
-            android:process=":dynsystem">
-            <intent-filter>
-                <action android:name="android.os.image.action.NOTIFY_IF_IN_USE" />
-                <category android:name="android.intent.category.DEFAULT" />
-            </intent-filter>
-        </service>
+            android:process=":dynsystem" />
 
         <activity android:name=".VerificationActivity"
             android:exported="true"
diff --git a/packages/SystemUI/res-keyguard/layout/fsi_chrome_view.xml b/packages/SystemUI/res-keyguard/layout/fsi_chrome_view.xml
deleted file mode 100644
index 4ff2967..0000000
--- a/packages/SystemUI/res-keyguard/layout/fsi_chrome_view.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<com.android.systemui.statusbar.notification.fsi.FsiChromeView android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:layout_margin="50dp"
-    android:orientation="vertical"
-    xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:layout_width="match_parent"
-        android:id="@+id/fsi_chrome"
-        android:layout_height="50dp"
-        android:orientation="horizontal">
-
-        <ImageView
-            android:id="@+id/fsi_app_icon"
-            android:layout_width="50dp"
-            android:layout_height="match_parent"
-            android:contentDescription="@null" />
-
-        <TextView
-            android:id="@+id/fsi_app_name"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:padding="10dp"
-            android:textSize="22dp"
-            android:gravity="center"
-            android:textColor="#FFFFFF"
-            android:text="AppName" />
-
-        <Space
-            android:layout_width="0dp"
-            android:layout_height="0dp"
-            android:layout_weight="1" />
-
-        <Button
-            android:id="@+id/fsi_fullscreen_button"
-            android:layout_width="100dp"
-            android:layout_height="match_parent"
-            android:text="fullscreen" />
-
-        <Button
-            android:id="@+id/fsi_dismiss_button"
-            android:layout_width="100dp"
-            android:layout_height="match_parent"
-            android:text="dismiss" />
-
-    </LinearLayout>
-
-</com.android.systemui.statusbar.notification.fsi.FsiChromeView>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index ac07d564..76f6f8a 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -257,9 +257,6 @@
     <!-- Radius for notifications corners with adjacent notifications -->
     <dimen name="notification_corner_radius_small">4dp</dimen>
 
-    <!-- Vertical padding of the FSI container -->
-    <dimen name="fsi_chrome_vertical_padding">80dp</dimen>
-
     <!-- the padding of the shelf icon container -->
     <dimen name="shelf_icon_container_padding">13dp</dimen>
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
index b53b868..f4c5815 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
@@ -21,8 +21,6 @@
 
 import com.android.keyguard.KeyguardClockSwitch.ClockSize;
 import com.android.keyguard.logging.KeyguardLogger;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
 import com.android.systemui.plugins.ClockAnimations;
 import com.android.systemui.statusbar.notification.AnimatableProperty;
 import com.android.systemui.statusbar.notification.PropertyAnimator;
@@ -62,7 +60,6 @@
             KeyguardUpdateMonitor keyguardUpdateMonitor,
             ConfigurationController configurationController,
             DozeParameters dozeParameters,
-            FeatureFlags featureFlags,
             ScreenOffAnimationController screenOffAnimationController,
             KeyguardLogger logger) {
         super(keyguardStatusView);
@@ -73,8 +70,6 @@
         mKeyguardVisibilityHelper = new KeyguardVisibilityHelper(mView, keyguardStateController,
                 dozeParameters, screenOffAnimationController, /* animateYPos= */ true,
                 logger.getBuffer());
-        mKeyguardVisibilityHelper.setOcclusionTransitionFlagEnabled(
-                featureFlags.isEnabled(Flags.UNOCCLUSION_TRANSITION));
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java b/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java
index 7e48193..a678edc 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java
@@ -28,7 +28,6 @@
 import com.android.systemui.statusbar.notification.AnimatableProperty;
 import com.android.systemui.statusbar.notification.PropertyAnimator;
 import com.android.systemui.statusbar.notification.stack.AnimationProperties;
-import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
 import com.android.systemui.statusbar.phone.DozeParameters;
 import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -49,7 +48,6 @@
     private boolean mAnimateYPos;
     private boolean mKeyguardViewVisibilityAnimating;
     private boolean mLastOccludedState = false;
-    private boolean mIsUnoccludeTransitionFlagEnabled = false;
     private final AnimationProperties mAnimationProperties = new AnimationProperties();
     private final LogBuffer mLogBuffer;
 
@@ -77,10 +75,6 @@
         return mKeyguardViewVisibilityAnimating;
     }
 
-    public void setOcclusionTransitionFlagEnabled(boolean enabled) {
-        mIsUnoccludeTransitionFlagEnabled = enabled;
-    }
-
     /**
      * Set the visibility of a keyguard view based on some new state.
      */
@@ -156,24 +150,9 @@
                 // since it may need to be cancelled due to keyguard lifecycle events.
                 mScreenOffAnimationController.animateInKeyguard(
                         mView, mAnimateKeyguardStatusViewVisibleEndRunnable);
-            } else if (!mIsUnoccludeTransitionFlagEnabled && mLastOccludedState && !isOccluded) {
-                // An activity was displayed over the lock screen, and has now gone away
-                log("Unoccluded transition");
-                mView.setVisibility(View.VISIBLE);
-                mView.setAlpha(0f);
-
-                mView.animate()
-                        .setDuration(StackStateAnimator.ANIMATION_DURATION_WAKEUP)
-                        .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
-                        .alpha(1f)
-                        .withEndAction(mAnimateKeyguardStatusViewVisibleEndRunnable)
-                        .start();
             } else {
                 log("Direct set Visibility to VISIBLE");
                 mView.setVisibility(View.VISIBLE);
-                if (!mIsUnoccludeTransitionFlagEnabled) {
-                    mView.setAlpha(1f);
-                }
             }
         } else {
             log("Direct set Visibility to GONE");
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt b/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
index 9921b1f..b86d419 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
@@ -47,10 +47,7 @@
 import com.android.systemui.recents.Recents
 import com.android.systemui.settings.dagger.MultiUserUtilsModule
 import com.android.systemui.shortcut.ShortcutKeyDispatcher
-import com.android.systemui.statusbar.notification.fsi.FsiChromeRepo
 import com.android.systemui.statusbar.notification.InstantAppNotifier
-import com.android.systemui.statusbar.notification.fsi.FsiChromeViewModelFactory
-import com.android.systemui.statusbar.notification.fsi.FsiChromeViewBinder
 import com.android.systemui.statusbar.phone.KeyguardLiftController
 import com.android.systemui.stylus.StylusUsiPowerStartable
 import com.android.systemui.temporarydisplay.chipbar.ChipbarCoordinator
@@ -91,24 +88,6 @@
     @ClassKey(ClipboardListener::class)
     abstract fun bindClipboardListener(sysui: ClipboardListener): CoreStartable
 
-    /** Inject into FsiChromeRepo.  */
-    @Binds
-    @IntoMap
-    @ClassKey(FsiChromeRepo::class)
-    abstract fun bindFSIChromeRepo(sysui: FsiChromeRepo): CoreStartable
-
-    /** Inject into FsiChromeWindowViewModel.  */
-    @Binds
-    @IntoMap
-    @ClassKey(FsiChromeViewModelFactory::class)
-    abstract fun bindFSIChromeWindowViewModel(sysui: FsiChromeViewModelFactory): CoreStartable
-
-    /** Inject into FsiChromeWindowBinder.  */
-    @Binds
-    @IntoMap
-    @ClassKey(FsiChromeViewBinder::class)
-    abstract fun bindFsiChromeWindowBinder(sysui: FsiChromeViewBinder): CoreStartable
-
     /** Inject into GlobalActionsComponent.  */
     @Binds
     @IntoMap
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index ab78b1b..2f44560 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -87,9 +87,6 @@
     val NOTIFICATION_GROUP_DISMISSAL_ANIMATION =
         releasedFlag(259217907, "notification_group_dismissal_animation")
 
-    // TODO(b/257506350): Tracking Bug
-    @JvmField val FSI_CHROME = unreleasedFlag(117, "fsi_chrome")
-
     @JvmField
     val SIMPLIFIED_APPEAR_FRACTION =
         unreleasedFlag(259395680, "simplified_appear_fraction", teamfood = true)
@@ -189,10 +186,6 @@
     @JvmField
     val REVAMPED_WALLPAPER_UI = releasedFlag(222, "revamped_wallpaper_ui")
 
-    /** A different path for unocclusion transitions back to keyguard */
-    // TODO(b/262859270): Tracking Bug
-    @JvmField val UNOCCLUSION_TRANSITION = releasedFlag(223, "unocclusion_transition")
-
     // flag for controlling auto pin confirmation and material u shapes in bouncer
     @JvmField
     val AUTO_PIN_CONFIRMATION =
@@ -382,6 +375,9 @@
     // TODO(b/265045965): Tracking Bug
     val SHOW_LOWLIGHT_ON_DIRECT_BOOT = releasedFlag(1003, "show_lowlight_on_direct_boot")
 
+    @JvmField
+    val ENABLE_LOW_LIGHT_CLOCK_UNDOCKED = unreleasedFlag(1004, "enable_low_light_clock_undocked")
+
     // 1100 - windowing
     @Keep
     @JvmField
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 02bee3e..2ad1ab7 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -127,8 +127,6 @@
 import com.android.systemui.dagger.qualifiers.UiBackground;
 import com.android.systemui.dreams.DreamOverlayStateController;
 import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
 import com.android.systemui.keyguard.dagger.KeyguardModule;
 import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -522,8 +520,6 @@
 
     private CentralSurfaces mCentralSurfaces;
 
-    private boolean mUnocclusionTransitionFlagEnabled = false;
-
     private final DeviceConfig.OnPropertiesChangedListener mOnPropertiesChangedListener =
             new DeviceConfig.OnPropertiesChangedListener() {
             @Override
@@ -970,9 +966,6 @@
                 public void onAnimationStart(int transit, RemoteAnimationTarget[] apps,
                         RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps,
                         IRemoteAnimationFinishedCallback finishedCallback) throws RemoteException {
-                    if (!mUnocclusionTransitionFlagEnabled) {
-                        setOccluded(true /* isOccluded */, true /* animate */);
-                    }
                     if (apps == null || apps.length == 0 || apps[0] == null) {
                         if (DEBUG) {
                             Log.d(TAG, "No apps provided to the OccludeByDream runner; "
@@ -1023,7 +1016,7 @@
                             @Override
                             public void onAnimationEnd(Animator animation) {
                                 try {
-                                    if (!mIsCancelled && mUnocclusionTransitionFlagEnabled) {
+                                    if (!mIsCancelled) {
                                         // We're already on the main thread, don't queue this call
                                         handleSetOccluded(true /* isOccluded */,
                                                 false /* animate */);
@@ -1200,7 +1193,6 @@
             ScreenOnCoordinator screenOnCoordinator,
             InteractionJankMonitor interactionJankMonitor,
             DreamOverlayStateController dreamOverlayStateController,
-            FeatureFlags featureFlags,
             Lazy<ShadeController> shadeControllerLazy,
             Lazy<NotificationShadeWindowController> notificationShadeWindowControllerLazy,
             Lazy<ActivityLaunchAnimator> activityLaunchAnimator,
@@ -1259,7 +1251,6 @@
 
         mDreamOpenAnimationDuration = (int) DREAMING_ANIMATION_DURATION_MS;
         mDreamCloseAnimationDuration = (int) LOCKSCREEN_ANIMATION_DURATION_MS;
-        mUnocclusionTransitionFlagEnabled = featureFlags.isEnabled(Flags.UNOCCLUSION_TRANSITION);
     }
 
     public void userActivity() {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
index 98d3570..47ef0fa 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
@@ -39,7 +39,6 @@
 import com.android.systemui.dagger.qualifiers.UiBackground;
 import com.android.systemui.dreams.DreamOverlayStateController;
 import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.keyguard.DismissCallbackRegistry;
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
 import com.android.systemui.keyguard.KeyguardViewMediator;
@@ -113,7 +112,6 @@
             ScreenOnCoordinator screenOnCoordinator,
             InteractionJankMonitor interactionJankMonitor,
             DreamOverlayStateController dreamOverlayStateController,
-            FeatureFlags featureFlags,
             Lazy<ShadeController> shadeController,
             Lazy<NotificationShadeWindowController> notificationShadeWindowController,
             Lazy<ActivityLaunchAnimator> activityLaunchAnimator,
@@ -144,7 +142,6 @@
                 screenOnCoordinator,
                 interactionJankMonitor,
                 dreamOverlayStateController,
-                featureFlags,
                 shadeController,
                 notificationShadeWindowController,
                 activityLaunchAnimator,
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index b502b4d..95206e5 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -465,7 +465,7 @@
     private int mPanelAlpha;
     private Runnable mPanelAlphaEndAction;
     private float mBottomAreaShadeAlpha;
-    private final ValueAnimator mBottomAreaShadeAlphaAnimator;
+    final ValueAnimator mBottomAreaShadeAlphaAnimator;
     private final AnimatableProperty mPanelAlphaAnimator = AnimatableProperty.from("panelAlpha",
             NotificationPanelView::setPanelAlphaInternal,
             NotificationPanelView::getCurrentPanelAlpha,
@@ -597,7 +597,6 @@
     private int mLockscreenToDreamingTransitionTranslationY;
     private int mGoneToDreamingTransitionTranslationY;
     private int mLockscreenToOccludedTransitionTranslationY;
-    private boolean mUnocclusionTransitionFlagEnabled = false;
 
     private final Runnable mFlingCollapseRunnable = () -> fling(0, false /* expand */,
             mNextCollapseSpeedUpFactor, false /* expandBecauseOfFalsing */);
@@ -886,7 +885,6 @@
         mNotificationPanelUnfoldAnimationController = unfoldComponent.map(
                 SysUIUnfoldComponent::getNotificationPanelUnfoldAnimationController);
 
-        mUnocclusionTransitionFlagEnabled = featureFlags.isEnabled(Flags.UNOCCLUSION_TRANSITION);
         updateUserSwitcherFlags();
         mKeyguardBottomAreaViewModel = keyguardBottomAreaViewModel;
         mKeyguardBottomAreaInteractor = keyguardBottomAreaInteractor;
@@ -1045,62 +1043,50 @@
         mNotificationPanelUnfoldAnimationController.ifPresent(controller ->
                 controller.setup(mNotificationContainerParent));
 
-        if (mUnocclusionTransitionFlagEnabled) {
-            // Dreaming->Lockscreen
-            collectFlow(mView, mKeyguardTransitionInteractor.getDreamingToLockscreenTransition(),
-                    mDreamingToLockscreenTransition, mMainDispatcher);
-            collectFlow(mView, mDreamingToLockscreenTransitionViewModel.getLockscreenAlpha(),
-                    setTransitionAlpha(mNotificationStackScrollLayoutController),
-                    mMainDispatcher);
-            collectFlow(mView, mDreamingToLockscreenTransitionViewModel.lockscreenTranslationY(
-                    mDreamingToLockscreenTransitionTranslationY),
-                    setTransitionY(mNotificationStackScrollLayoutController),
-                    mMainDispatcher);
+        // Dreaming->Lockscreen
+        collectFlow(mView, mKeyguardTransitionInteractor.getDreamingToLockscreenTransition(),
+                mDreamingToLockscreenTransition, mMainDispatcher);
+        collectFlow(mView, mDreamingToLockscreenTransitionViewModel.getLockscreenAlpha(),
+                setTransitionAlpha(mNotificationStackScrollLayoutController), mMainDispatcher);
+        collectFlow(mView, mDreamingToLockscreenTransitionViewModel.lockscreenTranslationY(
+                mDreamingToLockscreenTransitionTranslationY),
+                setTransitionY(mNotificationStackScrollLayoutController), mMainDispatcher);
 
-            // Occluded->Lockscreen
-            collectFlow(mView, mKeyguardTransitionInteractor.getOccludedToLockscreenTransition(),
-                    mOccludedToLockscreenTransition, mMainDispatcher);
-            collectFlow(mView, mOccludedToLockscreenTransitionViewModel.getLockscreenAlpha(),
-                    setTransitionAlpha(mNotificationStackScrollLayoutController),
-                    mMainDispatcher);
-            collectFlow(mView, mOccludedToLockscreenTransitionViewModel.lockscreenTranslationY(
-                    mOccludedToLockscreenTransitionTranslationY),
-                    setTransitionY(mNotificationStackScrollLayoutController),
-                    mMainDispatcher);
+        // Occluded->Lockscreen
+        collectFlow(mView, mKeyguardTransitionInteractor.getOccludedToLockscreenTransition(),
+                mOccludedToLockscreenTransition, mMainDispatcher);
+        collectFlow(mView, mOccludedToLockscreenTransitionViewModel.getLockscreenAlpha(),
+                setTransitionAlpha(mNotificationStackScrollLayoutController), mMainDispatcher);
+        collectFlow(mView, mOccludedToLockscreenTransitionViewModel.lockscreenTranslationY(
+                mOccludedToLockscreenTransitionTranslationY),
+                setTransitionY(mNotificationStackScrollLayoutController), mMainDispatcher);
 
-            // Lockscreen->Dreaming
-            collectFlow(mView, mKeyguardTransitionInteractor.getLockscreenToDreamingTransition(),
-                    mLockscreenToDreamingTransition, mMainDispatcher);
-            collectFlow(mView, mLockscreenToDreamingTransitionViewModel.getLockscreenAlpha(),
-                    setTransitionAlpha(mNotificationStackScrollLayoutController),
-                    mMainDispatcher);
-            collectFlow(mView, mLockscreenToDreamingTransitionViewModel.lockscreenTranslationY(
-                    mLockscreenToDreamingTransitionTranslationY),
-                    setTransitionY(mNotificationStackScrollLayoutController),
-                    mMainDispatcher);
+        // Lockscreen->Dreaming
+        collectFlow(mView, mKeyguardTransitionInteractor.getLockscreenToDreamingTransition(),
+                mLockscreenToDreamingTransition, mMainDispatcher);
+        collectFlow(mView, mLockscreenToDreamingTransitionViewModel.getLockscreenAlpha(),
+                setTransitionAlpha(mNotificationStackScrollLayoutController), mMainDispatcher);
+        collectFlow(mView, mLockscreenToDreamingTransitionViewModel.lockscreenTranslationY(
+                mLockscreenToDreamingTransitionTranslationY),
+                setTransitionY(mNotificationStackScrollLayoutController), mMainDispatcher);
 
-            // Gone->Dreaming
-            collectFlow(mView, mKeyguardTransitionInteractor.getGoneToDreamingTransition(),
-                    mGoneToDreamingTransition, mMainDispatcher);
-            collectFlow(mView, mGoneToDreamingTransitionViewModel.getLockscreenAlpha(),
-                    setTransitionAlpha(mNotificationStackScrollLayoutController),
-                    mMainDispatcher);
-            collectFlow(mView, mGoneToDreamingTransitionViewModel.lockscreenTranslationY(
-                    mGoneToDreamingTransitionTranslationY),
-                    setTransitionY(mNotificationStackScrollLayoutController),
-                    mMainDispatcher);
+        // Gone->Dreaming
+        collectFlow(mView, mKeyguardTransitionInteractor.getGoneToDreamingTransition(),
+                mGoneToDreamingTransition, mMainDispatcher);
+        collectFlow(mView, mGoneToDreamingTransitionViewModel.getLockscreenAlpha(),
+                setTransitionAlpha(mNotificationStackScrollLayoutController), mMainDispatcher);
+        collectFlow(mView, mGoneToDreamingTransitionViewModel.lockscreenTranslationY(
+                mGoneToDreamingTransitionTranslationY),
+                setTransitionY(mNotificationStackScrollLayoutController), mMainDispatcher);
 
-            // Lockscreen->Occluded
-            collectFlow(mView, mKeyguardTransitionInteractor.getLockscreenToOccludedTransition(),
-                    mLockscreenToOccludedTransition, mMainDispatcher);
-            collectFlow(mView, mLockscreenToOccludedTransitionViewModel.getLockscreenAlpha(),
-                    setTransitionAlpha(mNotificationStackScrollLayoutController),
-                    mMainDispatcher);
-            collectFlow(mView, mLockscreenToOccludedTransitionViewModel.lockscreenTranslationY(
-                    mLockscreenToOccludedTransitionTranslationY),
-                    setTransitionY(mNotificationStackScrollLayoutController),
-                    mMainDispatcher);
-        }
+        // Lockscreen->Occluded
+        collectFlow(mView, mKeyguardTransitionInteractor.getLockscreenToOccludedTransition(),
+                mLockscreenToOccludedTransition, mMainDispatcher);
+        collectFlow(mView, mLockscreenToOccludedTransitionViewModel.getLockscreenAlpha(),
+                setTransitionAlpha(mNotificationStackScrollLayoutController), mMainDispatcher);
+        collectFlow(mView, mLockscreenToOccludedTransitionViewModel.lockscreenTranslationY(
+                mLockscreenToOccludedTransitionTranslationY),
+                setTransitionY(mNotificationStackScrollLayoutController), mMainDispatcher);
     }
 
     @VisibleForTesting
@@ -2480,9 +2466,6 @@
     }
 
     private void onExpandingFinished() {
-        if (!mUnocclusionTransitionFlagEnabled) {
-            mScrimController.onExpandingFinished();
-        }
         mNotificationStackScrollLayoutController.onExpansionStopped();
         mHeadsUpManager.onExpandingFinished();
         mConversationNotificationManager.onNotificationPanelExpandStateChanged(isFullyCollapsed());
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
index 60fa865..87350b46 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
@@ -38,8 +38,6 @@
 import com.android.systemui.R;
 import com.android.systemui.classifier.FalsingCollector;
 import com.android.systemui.dock.DockManager;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
 import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
@@ -132,7 +130,6 @@
             NotificationInsetsController notificationInsetsController,
             AmbientState ambientState,
             PulsingGestureListener pulsingGestureListener,
-            FeatureFlags featureFlags,
             KeyguardBouncerViewModel keyguardBouncerViewModel,
             KeyguardBouncerComponent.Factory keyguardBouncerComponentFactory,
             AlternateBouncerInteractor alternateBouncerInteractor,
@@ -165,10 +162,8 @@
                 keyguardBouncerViewModel,
                 keyguardBouncerComponentFactory);
 
-        if (featureFlags.isEnabled(Flags.UNOCCLUSION_TRANSITION)) {
-            collectFlow(mView, keyguardTransitionInteractor.getLockscreenToDreamingTransition(),
-                    mLockscreenToDreamingTransition);
-        }
+        collectFlow(mView, keyguardTransitionInteractor.getLockscreenToDreamingTransition(),
+                mLockscreenToDreamingTransition);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeRepo.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeRepo.kt
deleted file mode 100644
index b483228..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeRepo.kt
+++ /dev/null
@@ -1,102 +0,0 @@
-package com.android.systemui.statusbar.notification.fsi
-
-import android.app.PendingIntent
-import android.content.Context
-import android.content.pm.PackageManager
-import android.graphics.drawable.Drawable
-import android.os.RemoteException
-import android.service.dreams.IDreamManager
-import com.android.systemui.CoreStartable
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
-import com.android.systemui.keyguard.data.repository.KeyguardRepository
-import com.android.systemui.statusbar.notification.collection.NotificationEntry
-import com.android.systemui.statusbar.notification.collection.provider.LaunchFullScreenIntentProvider
-import com.android.systemui.statusbar.notification.fsi.FsiDebug.Companion.log
-import com.android.systemui.statusbar.phone.CentralSurfaces
-import java.util.concurrent.Executor
-import javax.inject.Inject
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.StateFlow
-
-/**
- * Class that bridges the gap between clean app architecture and existing code. Provides new
- * implementation of StatusBarNotificationActivityStarter launchFullscreenIntent that pipes
- * one-directional data => FsiChromeViewModel => FsiChromeView.
- */
-@SysUISingleton
-class FsiChromeRepo
-@Inject
-constructor(
-    private val context: Context,
-    private val pm: PackageManager,
-    private val keyguardRepo: KeyguardRepository,
-    private val launchFullScreenIntentProvider: LaunchFullScreenIntentProvider,
-    private val featureFlags: FeatureFlags,
-    private val uiBgExecutor: Executor,
-    private val dreamManager: IDreamManager,
-    private val centralSurfaces: CentralSurfaces
-) : CoreStartable {
-
-    companion object {
-        private const val classTag = "FsiChromeRepo"
-    }
-
-    data class FSIInfo(
-        val appName: String,
-        val appIcon: Drawable,
-        val fullscreenIntent: PendingIntent
-    )
-
-    private val _infoFlow = MutableStateFlow<FSIInfo?>(null)
-    val infoFlow: StateFlow<FSIInfo?> = _infoFlow
-
-    override fun start() {
-        log("$classTag start listening for FSI notifications")
-
-        // Listen for FSI launch events for the lifetime of SystemUI.
-        launchFullScreenIntentProvider.registerListener { entry -> launchFullscreenIntent(entry) }
-    }
-
-    fun dismiss() {
-        _infoFlow.value = null
-    }
-
-    fun onFullscreen() {
-        // TODO(b/243421660) implement transition from container to fullscreen
-    }
-
-    fun stopScreenSaver() {
-        uiBgExecutor.execute {
-            try {
-                dreamManager.awaken()
-            } catch (e: RemoteException) {
-                e.printStackTrace()
-            }
-        }
-    }
-
-    fun launchFullscreenIntent(entry: NotificationEntry) {
-        if (!featureFlags.isEnabled(Flags.FSI_CHROME)) {
-            return
-        }
-        if (!keyguardRepo.isKeyguardShowing()) {
-            return
-        }
-        stopScreenSaver()
-
-        var appName = pm.getApplicationLabel(context.applicationInfo) as String
-        val appIcon = pm.getApplicationIcon(context.packageName)
-        val fullscreenIntent = entry.sbn.notification.fullScreenIntent
-
-        log("FsiChromeRepo launchFullscreenIntent appName=$appName appIcon $appIcon")
-        _infoFlow.value = FSIInfo(appName, appIcon, fullscreenIntent)
-
-        // If screen is off or we're showing AOD, show lockscreen.
-        centralSurfaces.wakeUpForFullScreenIntent()
-
-        // Don't show HUN since we're already showing FSI.
-        entry.notifyFullScreenIntentLaunched()
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeView.kt
deleted file mode 100644
index 6e5fcf4..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeView.kt
+++ /dev/null
@@ -1,83 +0,0 @@
-package com.android.systemui.statusbar.notification.fsi
-
-import android.content.Context
-import android.graphics.Color
-import android.graphics.Color.DKGRAY
-import android.graphics.Outline
-import android.util.AttributeSet
-import android.view.View
-import android.view.ViewOutlineProvider
-import android.widget.Button
-import android.widget.ImageView
-import android.widget.LinearLayout
-import android.widget.TextView
-import com.android.systemui.R
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.statusbar.notification.fsi.FsiDebug.Companion.log
-
-@SysUISingleton
-class FsiChromeView
-@JvmOverloads
-constructor(
-    context: Context?,
-    attrs: AttributeSet? = null,
-    defStyleAttr: Int = 0,
-    defStyleRes: Int = 0
-) : LinearLayout(context, attrs, defStyleAttr, defStyleRes) {
-
-    companion object {
-        private const val classTag = "FsiChromeView"
-    }
-
-    lateinit var chromeContainer: LinearLayout
-    lateinit var appIconImageView: ImageView
-    lateinit var appNameTextView: TextView
-    lateinit var dismissButton: Button
-    lateinit var fullscreenButton: Button
-
-    private val cornerRadius: Float =
-        resources.getDimensionPixelSize(R.dimen.notification_corner_radius).toFloat()
-    private val vertPadding: Int =
-        resources.getDimensionPixelSize(R.dimen.fsi_chrome_vertical_padding)
-    private val sidePadding: Int =
-        resources.getDimensionPixelSize(R.dimen.notification_side_paddings)
-
-    init {
-        log("$classTag init")
-    }
-
-    override fun onFinishInflate() {
-        log("$classTag onFinishInflate")
-        super.onFinishInflate()
-
-        setBackgroundColor(Color.TRANSPARENT)
-        setPadding(
-            sidePadding,
-            vertPadding,
-            sidePadding,
-            vertPadding
-        ) // Make smaller than fullscreen.
-
-        chromeContainer = findViewById(R.id.fsi_chrome)
-        chromeContainer.setBackgroundColor(DKGRAY)
-
-        appIconImageView = findViewById(R.id.fsi_app_icon)
-        appNameTextView = findViewById(R.id.fsi_app_name)
-        dismissButton = findViewById(R.id.fsi_dismiss_button)
-        fullscreenButton = findViewById(R.id.fsi_fullscreen_button)
-
-        outlineProvider =
-            object : ViewOutlineProvider() {
-                override fun getOutline(view: View, outline: Outline) {
-                    outline.setRoundRect(
-                        /* left */ sidePadding,
-                        /* top */ vertPadding,
-                        /* right */ view.width - sidePadding,
-                        /* bottom */ view.height - vertPadding,
-                        cornerRadius
-                    )
-                }
-            }
-        clipToOutline = true
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeViewBinder.kt
deleted file mode 100644
index 1a3927b..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeViewBinder.kt
+++ /dev/null
@@ -1,99 +0,0 @@
-package com.android.systemui.statusbar.notification.fsi
-
-import android.content.Context
-import android.view.LayoutInflater
-import android.view.WindowManager
-import com.android.systemui.CoreStartable
-import com.android.systemui.R
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.statusbar.notification.fsi.FsiDebug.Companion.log
-import com.android.systemui.statusbar.phone.CentralSurfaces
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.launch
-import java.util.concurrent.Executor
-import javax.inject.Inject
-
-@SysUISingleton
-class FsiChromeViewBinder
-@Inject
-constructor(
-    val context: Context,
-    val windowManager: WindowManager,
-    val viewModelFactory: FsiChromeViewModelFactory,
-    val layoutInflater: LayoutInflater,
-    val centralSurfaces: CentralSurfaces,
-    @Main val mainExecutor: Executor,
-    @Application val scope: CoroutineScope,
-) : CoreStartable {
-
-    companion object {
-        private const val classTag = "FsiChromeViewBinder"
-    }
-
-    private val fsiChromeView =
-        layoutInflater.inflate(R.layout.fsi_chrome_view, null /* root */, false /* attachToRoot */)
-            as FsiChromeView
-
-    var addedToWindowManager = false
-    var cornerRadius: Int = context.resources.getDimensionPixelSize(
-            R.dimen.notification_corner_radius)
-
-    override fun start() {
-        val methodTag = "start"
-        log("$classTag $methodTag ")
-
-        scope.launch {
-            log("$classTag $methodTag launch ")
-            viewModelFactory.viewModelFlow.collect { vm -> updateForViewModel(vm) }
-        }
-    }
-
-    private fun updateForViewModel(vm: FsiChromeViewModel?) {
-        val methodTag = "updateForViewModel"
-
-        if (vm == null) {
-            log("$classTag $methodTag viewModel is null, removing from window manager")
-
-            if (addedToWindowManager) {
-                windowManager.removeView(fsiChromeView)
-                addedToWindowManager = false
-            }
-            return
-        }
-
-        bindViewModel(vm, windowManager)
-
-        if (addedToWindowManager) {
-            log("$classTag $methodTag already addedToWindowManager")
-        } else {
-            windowManager.addView(fsiChromeView, FsiTaskViewConfig.getWmLayoutParams("PackageName"))
-            addedToWindowManager = true
-        }
-    }
-
-    private fun bindViewModel(
-        vm: FsiChromeViewModel,
-        windowManager: WindowManager,
-    ) {
-        log("$classTag bindViewModel")
-
-        fsiChromeView.appIconImageView.setImageDrawable(vm.appIcon)
-        fsiChromeView.appNameTextView.text = vm.appName
-
-        fsiChromeView.dismissButton.setOnClickListener { vm.onDismiss() }
-        fsiChromeView.fullscreenButton.setOnClickListener { vm.onFullscreen() }
-
-        vm.taskView.cornerRadius = cornerRadius.toFloat()
-        vm.taskView.startActivity(
-            vm.fsi,
-            FsiTaskViewConfig.getFillInIntent(),
-            FsiTaskViewConfig.getActivityOptions(context, windowManager),
-            FsiTaskViewConfig.getLaunchBounds(windowManager)
-        )
-
-        log("$classTag bindViewModel started taskview activity")
-        fsiChromeView.addView(vm.taskView)
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeViewModelFactory.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeViewModelFactory.kt
deleted file mode 100644
index 1ca698b..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeViewModelFactory.kt
+++ /dev/null
@@ -1,87 +0,0 @@
-package com.android.systemui.statusbar.notification.fsi
-
-import android.annotation.UiContext
-import android.app.PendingIntent
-import android.content.Context
-import android.graphics.drawable.Drawable
-import com.android.systemui.CoreStartable
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.statusbar.notification.fsi.FsiDebug.Companion.log
-import com.android.wm.shell.TaskView
-import com.android.wm.shell.TaskViewFactory
-import java.util.Optional
-import java.util.concurrent.Executor
-import javax.inject.Inject
-import kotlin.coroutines.resume
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.mapLatest
-import kotlinx.coroutines.suspendCancellableCoroutine
-
-/**
- * Handle view-related data for fullscreen intent container on lockscreen. Wraps FsiChromeRepo,
- * transforms events/state into view-relevant representation for FsiChromeView. Alive for lifetime
- * of SystemUI.
- */
-@SysUISingleton
-class FsiChromeViewModelFactory
-@Inject
-constructor(
-    val repo: FsiChromeRepo,
-    val taskViewFactory: Optional<TaskViewFactory>,
-    @UiContext val context: Context,
-    @Main val mainExecutor: Executor,
-) : CoreStartable {
-
-    companion object {
-        private const val classTag = "FsiChromeViewModelFactory"
-    }
-
-    val viewModelFlow: Flow<FsiChromeViewModel?> =
-        repo.infoFlow.mapLatest { fsiInfo ->
-            fsiInfo?.let {
-                log("$classTag viewModelFlow got new fsiInfo")
-
-                // mapLatest emits null when FSIInfo is null
-                FsiChromeViewModel(
-                    fsiInfo.appName,
-                    fsiInfo.appIcon,
-                    createTaskView(),
-                    fsiInfo.fullscreenIntent,
-                    repo
-                )
-            }
-        }
-
-    override fun start() {
-        log("$classTag start")
-    }
-
-    private suspend fun createTaskView(): TaskView = suspendCancellableCoroutine { k ->
-        log("$classTag createTaskView")
-
-        taskViewFactory.get().create(context, mainExecutor) { taskView -> k.resume(taskView) }
-    }
-}
-
-// Alive for lifetime of FSI.
-data class FsiChromeViewModel(
-    val appName: String,
-    val appIcon: Drawable,
-    val taskView: TaskView,
-    val fsi: PendingIntent,
-    val repo: FsiChromeRepo
-) {
-    companion object {
-        private const val classTag = "FsiChromeViewModel"
-    }
-
-    fun onDismiss() {
-        log("$classTag onDismiss")
-        repo.dismiss()
-    }
-    fun onFullscreen() {
-        log("$classTag onFullscreen")
-        repo.onFullscreen()
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiDebug.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiDebug.kt
deleted file mode 100644
index d9e3f8f..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiDebug.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.android.systemui.statusbar.notification.fsi
-
-class FsiDebug {
-
-    companion object {
-        private const val debugTag = "FsiDebug"
-        private const val debug = true
-
-        fun log(s: Any) {
-            if (!debug) {
-                return
-            }
-            android.util.Log.d(debugTag, "$s")
-        }
-    }
-}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiTaskViewConfig.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiTaskViewConfig.kt
deleted file mode 100644
index 034ab56..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiTaskViewConfig.kt
+++ /dev/null
@@ -1,75 +0,0 @@
-package com.android.systemui.statusbar.notification.fsi
-
-import android.app.ActivityOptions
-import android.content.Context
-import android.content.Intent
-import android.graphics.PixelFormat
-import android.graphics.Rect
-import android.os.Binder
-import android.view.ViewGroup
-import android.view.WindowManager
-
-/**
- * Config for adding the FsiChromeView window to WindowManager and starting the FSI activity.
- */
-class FsiTaskViewConfig {
-
-    companion object {
-
-        private const val classTag = "FsiTaskViewConfig"
-
-        fun getWmLayoutParams(packageName: String): WindowManager.LayoutParams {
-            val params: WindowManager.LayoutParams?
-            params =
-                WindowManager.LayoutParams(
-                    ViewGroup.LayoutParams.MATCH_PARENT,
-                    ViewGroup.LayoutParams.MATCH_PARENT,
-                    WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
-                    WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE or
-                        WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED or
-                            WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER,
-                    PixelFormat.TRANSLUCENT
-                )
-            params.setTrustedOverlay()
-            params.fitInsetsTypes = 0
-            params.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
-            params.token = Binder()
-            params.packageName = packageName
-            params.layoutInDisplayCutoutMode =
-                WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
-            params.privateFlags =
-                params.privateFlags or WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS
-            return params
-        }
-
-        fun getFillInIntent(): Intent {
-            val fillInIntent = Intent()
-            fillInIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT)
-            fillInIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
-            // FLAG_ACTIVITY_NEW_TASK is auto-applied because
-            // we're starting the FSI activity from a non-Activity context
-            return fillInIntent
-        }
-
-        fun getLaunchBounds(windowManager: WindowManager): Rect {
-            // TODO(b/243421660) check this works for non-resizeable activity
-            return Rect()
-        }
-
-        fun getActivityOptions(context: Context, windowManager: WindowManager): ActivityOptions {
-            // Custom options so there is no activity transition animation
-            val options =
-                ActivityOptions.makeCustomAnimation(context, 0 /* enterResId */, 0 /* exitResId */)
-
-            options.taskAlwaysOnTop = true
-
-            options.pendingIntentLaunchFlags =
-                Intent.FLAG_ACTIVITY_NEW_DOCUMENT or
-                    Intent.FLAG_ACTIVITY_MULTIPLE_TASK or
-                    Intent.FLAG_ACTIVITY_NEW_TASK
-
-            options.launchBounds = getLaunchBounds(windowManager)
-            return options
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
index 8dcfec7..9e62817 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
@@ -375,8 +375,6 @@
     void fadeKeyguardAfterLaunchTransition(Runnable beforeFading,
             Runnable endRunnable, Runnable cancelRunnable);
 
-    void animateKeyguardUnoccluding();
-
     void startLaunchTransitionTimeout();
 
     boolean hideKeyguardImpl(boolean forceStateChange);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
index 93b580c..ae97407 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -2998,16 +2998,6 @@
     }
 
     /**
-     * Plays the animation when an activity that was occluding Keyguard goes away.
-     */
-    @Override
-    public void animateKeyguardUnoccluding() {
-        mNotificationPanelViewController.setExpandedFraction(0f);
-        mCommandQueueCallbacks.animateExpandNotificationsPanel();
-        mScrimController.setUnocclusionAnimationRunning(true);
-    }
-
-    /**
      * Starts the timeout when we try to start the affordances on Keyguard. We usually rely that
      * Keyguard goes away via fadeKeyguardAfterLaunchTransition, however, that might not happen
      * because the launched app crashed or something else went wrong.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 80093a3..8e0ec284 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -138,26 +138,12 @@
     private boolean mTransitioningToFullShade;
 
     /**
-     * Is there currently an unocclusion animation running. Used to avoid bright flickers
-     * of the notification scrim.
-     */
-    private boolean mUnOcclusionAnimationRunning;
-
-    /**
      * The percentage of the bouncer which is hidden. If 1, the bouncer is completely hidden. If
      * 0, the bouncer is visible.
      */
     @FloatRange(from = 0, to = 1)
     private float mBouncerHiddenFraction = KeyguardBouncerConstants.EXPANSION_HIDDEN;
 
-    /**
-     * Set whether an unocclusion animation is currently running on the notification panel. Used
-     * to avoid bright flickers of the notification scrim.
-     */
-    public void setUnocclusionAnimationRunning(boolean unocclusionAnimationRunning) {
-        mUnOcclusionAnimationRunning = unocclusionAnimationRunning;
-    }
-
     @IntDef(prefix = {"VISIBILITY_"}, value = {
             TRANSPARENT,
             SEMI_TRANSPARENT,
@@ -532,10 +518,6 @@
         }
     }
 
-    public void onExpandingFinished() {
-        setUnocclusionAnimationRunning(false);
-    }
-
     @VisibleForTesting
     protected void onHideWallpaperTimeout() {
         if (mState != ScrimState.AOD && mState != ScrimState.PULSING) {
@@ -875,13 +857,6 @@
             if (mKeyguardOccluded || hideNotificationScrim) {
                 mNotificationsAlpha = 0;
             }
-            if (mUnOcclusionAnimationRunning && mState == ScrimState.KEYGUARD) {
-                // We're unoccluding the keyguard and don't want to have a bright flash.
-                mNotificationsAlpha = ScrimState.KEYGUARD.getNotifAlpha();
-                mNotificationsTint = ScrimState.KEYGUARD.getNotifTint();
-                mBehindAlpha = ScrimState.KEYGUARD.getBehindAlpha();
-                mBehindTint = ScrimState.KEYGUARD.getBehindTint();
-            }
         }
         if (mState != ScrimState.UNLOCKED) {
             mAnimatingPanelExpansionOnUnlock = false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index a127139..66f5b65 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -281,7 +281,6 @@
     private float mQsExpansion;
     final Set<KeyguardViewManagerCallback> mCallbacks = new HashSet<>();
     private boolean mIsModernAlternateBouncerEnabled;
-    private boolean mIsUnoccludeTransitionFlagEnabled;
     private boolean mIsBackAnimationEnabled;
 
     private OnDismissAction mAfterKeyguardGoneAction;
@@ -361,7 +360,6 @@
                 .map(SysUIUnfoldComponent::getFoldAodAnimationController).orElse(null);
         mIsModernAlternateBouncerEnabled = featureFlags.isEnabled(Flags.MODERN_ALTERNATE_BOUNCER);
         mAlternateBouncerInteractor = alternateBouncerInteractor;
-        mIsUnoccludeTransitionFlagEnabled = featureFlags.isEnabled(Flags.UNOCCLUSION_TRANSITION);
         mIsBackAnimationEnabled =
                 featureFlags.isEnabled(Flags.WM_ENABLE_PREDICTIVE_BACK_BOUNCER_ANIM);
     }
@@ -880,11 +878,6 @@
             // by a FLAG_DISMISS_KEYGUARD_ACTIVITY.
             reset(isOccluding /* hideBouncerWhenShowing*/);
         }
-        if (!mIsUnoccludeTransitionFlagEnabled) {
-            if (animate && !isOccluded && isShowing && !primaryBouncerIsShowing()) {
-                mCentralSurfaces.animateKeyguardUnoccluding();
-            }
-        }
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index 3471a46..726b234 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -561,10 +561,6 @@
             mLogger.logFullScreenIntentSuppressedByVR(entry);
             return;
         }
-        if (mFeatureFlags.isEnabled(Flags.FSI_CHROME)) {
-            // FsiChromeRepo runs its own implementation of launchFullScreenIntent
-            return;
-        }
         // Stop screensaver if the notification has a fullscreen intent.
         // (like an incoming phone call)
         mUiBgExecutor.execute(() -> {
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java
index dfad15d..7144914 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java
@@ -26,7 +26,6 @@
 
 import com.android.keyguard.logging.KeyguardLogger;
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.plugins.ClockAnimations;
 import com.android.systemui.statusbar.phone.DozeParameters;
 import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
@@ -61,8 +60,6 @@
     @Mock
     DozeParameters mDozeParameters;
     @Mock
-    FeatureFlags mFeatureFlags;
-    @Mock
     ScreenOffAnimationController mScreenOffAnimationController;
     @Captor
     private ArgumentCaptor<KeyguardUpdateMonitorCallback> mKeyguardUpdateMonitorCallbackCaptor;
@@ -83,7 +80,6 @@
                 mKeyguardUpdateMonitor,
                 mConfigurationController,
                 mDozeParameters,
-                mFeatureFlags,
                 mScreenOffAnimationController,
                 mKeyguardLogger);
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
index 7c20e3c..c93e677 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -29,7 +29,6 @@
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.atLeast;
-import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
@@ -67,7 +66,6 @@
 import com.android.systemui.colorextraction.SysuiColorExtractor;
 import com.android.systemui.dreams.DreamOverlayStateController;
 import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.shade.NotificationShadeWindowControllerImpl;
@@ -136,7 +134,6 @@
     private @Mock SysuiColorExtractor mColorExtractor;
     private @Mock AuthController mAuthController;
     private @Mock ShadeExpansionStateManager mShadeExpansionStateManager;
-    private @Mock FeatureFlags mFeatureFlags;
     private @Mock ShadeWindowLogger mShadeWindowLogger;
     private DeviceConfigProxy mDeviceConfig = new DeviceConfigProxyFake();
     private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
@@ -545,7 +542,6 @@
                 mScreenOnCoordinator,
                 mInteractionJankMonitor,
                 mDreamOverlayStateController,
-                mFeatureFlags,
                 () -> mShadeController,
                 () -> mNotificationShadeWindowController,
                 () -> mActivityLaunchAnimator,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
new file mode 100644
index 0000000..52b0b6a
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
@@ -0,0 +1,753 @@
+/*
+ * Copyright (C) 2023 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 static android.content.res.Configuration.ORIENTATION_PORTRAIT;
+
+import static com.android.keyguard.KeyguardClockSwitch.LARGE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static kotlinx.coroutines.flow.FlowKt.emptyFlow;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.annotation.IdRes;
+import android.content.ContentResolver;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.database.ContentObserver;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.PowerManager;
+import android.os.UserManager;
+import android.util.DisplayMetrics;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewParent;
+import android.view.ViewPropertyAnimator;
+import android.view.ViewStub;
+import android.view.ViewTreeObserver;
+import android.view.accessibility.AccessibilityManager;
+
+import androidx.constraintlayout.widget.ConstraintSet;
+
+import com.android.internal.jank.InteractionJankMonitor;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.UiEventLogger;
+import com.android.internal.logging.testing.UiEventLoggerFake;
+import com.android.internal.util.LatencyTracker;
+import com.android.keyguard.KeyguardClockSwitch;
+import com.android.keyguard.KeyguardClockSwitchController;
+import com.android.keyguard.KeyguardStatusView;
+import com.android.keyguard.KeyguardStatusViewController;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.LockIconViewController;
+import com.android.keyguard.dagger.KeyguardQsUserSwitchComponent;
+import com.android.keyguard.dagger.KeyguardStatusBarViewComponent;
+import com.android.keyguard.dagger.KeyguardStatusViewComponent;
+import com.android.keyguard.dagger.KeyguardUserSwitcherComponent;
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.biometrics.AuthController;
+import com.android.systemui.classifier.FalsingCollectorFake;
+import com.android.systemui.classifier.FalsingManagerFake;
+import com.android.systemui.common.ui.view.LongPressHandlingView;
+import com.android.systemui.doze.DozeLog;
+import com.android.systemui.dump.DumpManager;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.fragments.FragmentHostManager;
+import com.android.systemui.fragments.FragmentService;
+import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
+import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository;
+import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository;
+import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
+import com.android.systemui.keyguard.domain.interactor.KeyguardBottomAreaInteractor;
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
+import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel;
+import com.android.systemui.keyguard.ui.viewmodel.GoneToDreamingTransitionViewModel;
+import com.android.systemui.keyguard.ui.viewmodel.KeyguardBottomAreaViewModel;
+import com.android.systemui.keyguard.ui.viewmodel.KeyguardLongPressViewModel;
+import com.android.systemui.keyguard.ui.viewmodel.LockscreenToDreamingTransitionViewModel;
+import com.android.systemui.keyguard.ui.viewmodel.LockscreenToOccludedTransitionViewModel;
+import com.android.systemui.keyguard.ui.viewmodel.OccludedToLockscreenTransitionViewModel;
+import com.android.systemui.media.controls.pipeline.MediaDataManager;
+import com.android.systemui.media.controls.ui.KeyguardMediaController;
+import com.android.systemui.media.controls.ui.MediaHierarchyManager;
+import com.android.systemui.model.SysUiState;
+import com.android.systemui.navigationbar.NavigationBarController;
+import com.android.systemui.navigationbar.NavigationModeController;
+import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.plugins.qs.QS;
+import com.android.systemui.qs.QSFragment;
+import com.android.systemui.screenrecord.RecordingController;
+import com.android.systemui.shade.transition.ShadeTransitionController;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.KeyguardIndicationController;
+import com.android.systemui.statusbar.LockscreenShadeTransitionController;
+import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.NotificationShadeDepthController;
+import com.android.systemui.statusbar.NotificationShadeWindowController;
+import com.android.systemui.statusbar.NotificationShelfController;
+import com.android.systemui.statusbar.PulseExpansionHandler;
+import com.android.systemui.statusbar.QsFrameTranslateController;
+import com.android.systemui.statusbar.StatusBarStateControllerImpl;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
+import com.android.systemui.statusbar.VibratorHelper;
+import com.android.systemui.statusbar.notification.ConversationNotificationManager;
+import com.android.systemui.statusbar.notification.DynamicPrivacyController;
+import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
+import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinatorLogger;
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
+import com.android.systemui.statusbar.notification.stack.AmbientState;
+import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
+import com.android.systemui.statusbar.notification.stack.NotificationRoundnessManager;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
+import com.android.systemui.statusbar.notification.stack.NotificationStackSizeCalculator;
+import com.android.systemui.statusbar.phone.CentralSurfaces;
+import com.android.systemui.statusbar.phone.ConfigurationControllerImpl;
+import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.statusbar.phone.HeadsUpAppearanceController;
+import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
+import com.android.systemui.statusbar.phone.HeadsUpTouchHelper;
+import com.android.systemui.statusbar.phone.KeyguardBottomAreaView;
+import com.android.systemui.statusbar.phone.KeyguardBottomAreaViewController;
+import com.android.systemui.statusbar.phone.KeyguardBypassController;
+import com.android.systemui.statusbar.phone.KeyguardStatusBarView;
+import com.android.systemui.statusbar.phone.KeyguardStatusBarViewController;
+import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
+import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
+import com.android.systemui.statusbar.phone.ScrimController;
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+import com.android.systemui.statusbar.phone.StatusBarTouchableRegionManager;
+import com.android.systemui.statusbar.phone.TapAgainViewController;
+import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.KeyguardQsUserSwitchController;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.policy.KeyguardUserSwitcherController;
+import com.android.systemui.statusbar.policy.KeyguardUserSwitcherView;
+import com.android.systemui.statusbar.window.StatusBarWindowStateController;
+import com.android.systemui.unfold.SysUIUnfoldComponent;
+import com.android.systemui.util.time.FakeSystemClock;
+import com.android.systemui.util.time.SystemClock;
+import com.android.wm.shell.animation.FlingAnimationUtils;
+
+import org.junit.After;
+import org.junit.Before;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.stubbing.Answer;
+
+import java.util.List;
+import java.util.Optional;
+
+import dagger.Lazy;
+import kotlinx.coroutines.CoroutineDispatcher;
+
+public class NotificationPanelViewControllerBaseTest extends SysuiTestCase {
+
+    protected static final int SPLIT_SHADE_FULL_TRANSITION_DISTANCE = 400;
+    protected static final int NOTIFICATION_SCRIM_TOP_PADDING_IN_SPLIT_SHADE = 50;
+    protected static final int PANEL_WIDTH = 500; // Random value just for the test.
+
+    @Mock protected CentralSurfaces mCentralSurfaces;
+    @Mock protected NotificationStackScrollLayout mNotificationStackScrollLayout;
+    @Mock protected KeyguardBottomAreaView mKeyguardBottomArea;
+    @Mock protected KeyguardBottomAreaViewController mKeyguardBottomAreaViewController;
+    @Mock protected KeyguardBottomAreaView mQsFrame;
+    @Mock protected HeadsUpManagerPhone mHeadsUpManager;
+    @Mock protected NotificationShelfController mNotificationShelfController;
+    @Mock protected NotificationGutsManager mGutsManager;
+    @Mock protected KeyguardStatusBarView mKeyguardStatusBar;
+    @Mock protected KeyguardUserSwitcherView mUserSwitcherView;
+    @Mock protected ViewStub mUserSwitcherStubView;
+    @Mock protected HeadsUpTouchHelper.Callback mHeadsUpCallback;
+    @Mock protected KeyguardUpdateMonitor mUpdateMonitor;
+    @Mock protected KeyguardBypassController mKeyguardBypassController;
+    @Mock protected DozeParameters mDozeParameters;
+    @Mock protected ScreenOffAnimationController mScreenOffAnimationController;
+    @Mock protected NotificationPanelView mView;
+    @Mock protected LayoutInflater mLayoutInflater;
+    @Mock protected FeatureFlags mFeatureFlags;
+    @Mock protected DynamicPrivacyController mDynamicPrivacyController;
+    @Mock protected StatusBarTouchableRegionManager mStatusBarTouchableRegionManager;
+    @Mock protected KeyguardStateController mKeyguardStateController;
+    @Mock protected DozeLog mDozeLog;
+    @Mock protected ShadeLogger mShadeLog;
+    @Mock protected ShadeHeightLogger mShadeHeightLogger;
+    @Mock protected CommandQueue mCommandQueue;
+    @Mock protected VibratorHelper mVibratorHelper;
+    @Mock protected LatencyTracker mLatencyTracker;
+    @Mock protected PowerManager mPowerManager;
+    @Mock protected AccessibilityManager mAccessibilityManager;
+    @Mock protected MetricsLogger mMetricsLogger;
+    @Mock protected Resources mResources;
+    @Mock protected Configuration mConfiguration;
+    @Mock protected KeyguardClockSwitch mKeyguardClockSwitch;
+    @Mock protected MediaHierarchyManager mMediaHierarchyManager;
+    @Mock protected ConversationNotificationManager mConversationNotificationManager;
+    @Mock protected StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
+    @Mock protected KeyguardStatusViewComponent.Factory mKeyguardStatusViewComponentFactory;
+    @Mock protected KeyguardQsUserSwitchComponent.Factory mKeyguardQsUserSwitchComponentFactory;
+    @Mock protected KeyguardQsUserSwitchComponent mKeyguardQsUserSwitchComponent;
+    @Mock protected KeyguardQsUserSwitchController mKeyguardQsUserSwitchController;
+    @Mock protected KeyguardUserSwitcherComponent.Factory mKeyguardUserSwitcherComponentFactory;
+    @Mock protected KeyguardUserSwitcherComponent mKeyguardUserSwitcherComponent;
+    @Mock protected KeyguardUserSwitcherController mKeyguardUserSwitcherController;
+    @Mock protected KeyguardStatusViewComponent mKeyguardStatusViewComponent;
+    @Mock protected KeyguardStatusBarViewComponent.Factory mKeyguardStatusBarViewComponentFactory;
+    @Mock protected KeyguardStatusBarViewComponent mKeyguardStatusBarViewComponent;
+    @Mock protected KeyguardClockSwitchController mKeyguardClockSwitchController;
+    @Mock protected KeyguardStatusViewController mKeyguardStatusViewController;
+    @Mock protected KeyguardStatusBarViewController mKeyguardStatusBarViewController;
+    @Mock protected NotificationStackScrollLayoutController
+            mNotificationStackScrollLayoutController;
+    @Mock protected NotificationShadeDepthController mNotificationShadeDepthController;
+    @Mock protected LockscreenShadeTransitionController mLockscreenShadeTransitionController;
+    @Mock protected AuthController mAuthController;
+    @Mock protected ScrimController mScrimController;
+    @Mock protected MediaDataManager mMediaDataManager;
+    @Mock protected AmbientState mAmbientState;
+    @Mock protected UserManager mUserManager;
+    @Mock protected UiEventLogger mUiEventLogger;
+    @Mock protected LockIconViewController mLockIconViewController;
+    @Mock protected KeyguardMediaController mKeyguardMediaController;
+    @Mock protected NavigationModeController mNavigationModeController;
+    @Mock protected NavigationBarController mNavigationBarController;
+    @Mock protected QuickSettingsController mQsController;
+    @Mock protected ShadeHeaderController mShadeHeaderController;
+    @Mock protected ContentResolver mContentResolver;
+    @Mock protected TapAgainViewController mTapAgainViewController;
+    @Mock protected KeyguardIndicationController mKeyguardIndicationController;
+    @Mock protected FragmentService mFragmentService;
+    @Mock protected FragmentHostManager mFragmentHostManager;
+    @Mock protected NotificationRemoteInputManager mNotificationRemoteInputManager;
+    @Mock protected RecordingController mRecordingController;
+    @Mock protected LockscreenGestureLogger mLockscreenGestureLogger;
+    @Mock protected DumpManager mDumpManager;
+    @Mock protected InteractionJankMonitor mInteractionJankMonitor;
+    @Mock protected NotificationsQSContainerController mNotificationsQSContainerController;
+    @Mock protected QsFrameTranslateController mQsFrameTranslateController;
+    @Mock protected StatusBarWindowStateController mStatusBarWindowStateController;
+    @Mock protected KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
+    @Mock protected NotificationShadeWindowController mNotificationShadeWindowController;
+    @Mock protected SysUiState mSysUiState;
+    @Mock protected NotificationListContainer mNotificationListContainer;
+    @Mock protected NotificationStackSizeCalculator mNotificationStackSizeCalculator;
+    @Mock protected UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
+    @Mock protected ShadeTransitionController mShadeTransitionController;
+    @Mock protected QS mQs;
+    @Mock protected QSFragment mQSFragment;
+    @Mock protected ViewGroup mQsHeader;
+    @Mock protected ViewParent mViewParent;
+    @Mock protected ViewTreeObserver mViewTreeObserver;
+    @Mock protected KeyguardBottomAreaViewModel mKeyguardBottomAreaViewModel;
+    @Mock protected DreamingToLockscreenTransitionViewModel
+            mDreamingToLockscreenTransitionViewModel;
+    @Mock protected OccludedToLockscreenTransitionViewModel
+            mOccludedToLockscreenTransitionViewModel;
+    @Mock protected LockscreenToDreamingTransitionViewModel
+            mLockscreenToDreamingTransitionViewModel;
+    @Mock protected LockscreenToOccludedTransitionViewModel
+            mLockscreenToOccludedTransitionViewModel;
+    @Mock protected GoneToDreamingTransitionViewModel mGoneToDreamingTransitionViewModel;
+
+    @Mock protected KeyguardTransitionInteractor mKeyguardTransitionInteractor;
+    @Mock protected KeyguardLongPressViewModel mKeyuardLongPressViewModel;
+    @Mock protected AlternateBouncerInteractor mAlternateBouncerInteractor;
+    @Mock protected MotionEvent mDownMotionEvent;
+    @Mock protected CoroutineDispatcher mMainDispatcher;
+    @Captor
+    protected ArgumentCaptor<NotificationStackScrollLayout.OnEmptySpaceClickListener>
+            mEmptySpaceClickListenerCaptor;
+
+    protected KeyguardBottomAreaInteractor mKeyguardBottomAreaInteractor;
+    protected KeyguardInteractor mKeyguardInteractor;
+    protected NotificationPanelViewController.TouchHandler mTouchHandler;
+    protected ConfigurationController mConfigurationController;
+    protected SysuiStatusBarStateController mStatusBarStateController;
+    protected NotificationPanelViewController mNotificationPanelViewController;
+    protected View.AccessibilityDelegate mAccessibilityDelegate;
+    protected NotificationsQuickSettingsContainer mNotificationContainerParent;
+    protected List<View.OnAttachStateChangeListener> mOnAttachStateChangeListeners;
+    protected Handler mMainHandler;
+    protected View.OnLayoutChangeListener mLayoutChangeListener;
+
+    protected final FalsingManagerFake mFalsingManager = new FalsingManagerFake();
+    protected final Optional<SysUIUnfoldComponent> mSysUIUnfoldComponent = Optional.empty();
+    protected final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
+    protected final ShadeExpansionStateManager mShadeExpansionStateManager =
+            new ShadeExpansionStateManager();
+
+    protected QuickSettingsController mQuickSettingsController;
+    @Mock protected Lazy<NotificationPanelViewController> mNotificationPanelViewControllerLazy;
+
+    protected FragmentHostManager.FragmentListener mFragmentListener;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        mMainDispatcher = getMainDispatcher();
+        mKeyguardBottomAreaInteractor = new KeyguardBottomAreaInteractor(
+                new FakeKeyguardRepository());
+        mKeyguardInteractor = new KeyguardInteractor(new FakeKeyguardRepository(), mCommandQueue,
+                mFeatureFlags, new FakeKeyguardBouncerRepository());
+        SystemClock systemClock = new FakeSystemClock();
+        mStatusBarStateController = new StatusBarStateControllerImpl(mUiEventLogger, mDumpManager,
+                mInteractionJankMonitor, mShadeExpansionStateManager);
+
+        KeyguardStatusView keyguardStatusView = new KeyguardStatusView(mContext);
+        keyguardStatusView.setId(R.id.keyguard_status_view);
+
+        when(mAuthController.isUdfpsEnrolled(anyInt())).thenReturn(false);
+        when(mHeadsUpCallback.getContext()).thenReturn(mContext);
+        when(mView.getResources()).thenReturn(mResources);
+        when(mView.getWidth()).thenReturn(PANEL_WIDTH);
+        when(mResources.getConfiguration()).thenReturn(mConfiguration);
+        mConfiguration.orientation = ORIENTATION_PORTRAIT;
+        when(mResources.getDisplayMetrics()).thenReturn(mDisplayMetrics);
+        mDisplayMetrics.density = 100;
+        when(mResources.getBoolean(R.bool.config_enableNotificationShadeDrag)).thenReturn(true);
+        when(mResources.getDimensionPixelSize(R.dimen.notifications_top_padding_split_shade))
+                .thenReturn(NOTIFICATION_SCRIM_TOP_PADDING_IN_SPLIT_SHADE);
+        when(mResources.getDimensionPixelSize(R.dimen.notification_panel_margin_horizontal))
+                .thenReturn(10);
+        when(mResources.getDimensionPixelSize(R.dimen.split_shade_full_transition_distance))
+                .thenReturn(SPLIT_SHADE_FULL_TRANSITION_DISTANCE);
+        when(mView.getContext()).thenReturn(getContext());
+        when(mView.findViewById(R.id.keyguard_header)).thenReturn(mKeyguardStatusBar);
+        when(mView.findViewById(R.id.keyguard_user_switcher_view)).thenReturn(mUserSwitcherView);
+        when(mView.findViewById(R.id.keyguard_user_switcher_stub)).thenReturn(
+                mUserSwitcherStubView);
+        when(mView.findViewById(R.id.keyguard_clock_container)).thenReturn(mKeyguardClockSwitch);
+        when(mView.findViewById(R.id.notification_stack_scroller))
+                .thenReturn(mNotificationStackScrollLayout);
+        when(mNotificationStackScrollLayoutController.getHeight()).thenReturn(1000);
+        when(mNotificationStackScrollLayoutController.getHeadsUpCallback())
+                .thenReturn(mHeadsUpCallback);
+        when(mKeyguardBottomAreaViewController.getView()).thenReturn(mKeyguardBottomArea);
+        when(mView.findViewById(R.id.keyguard_bottom_area)).thenReturn(mKeyguardBottomArea);
+        when(mKeyguardBottomArea.animate()).thenReturn(mock(ViewPropertyAnimator.class));
+        when(mView.findViewById(R.id.qs_frame)).thenReturn(mQsFrame);
+        when(mView.findViewById(R.id.keyguard_status_view))
+                .thenReturn(mock(KeyguardStatusView.class));
+        mNotificationContainerParent = new NotificationsQuickSettingsContainer(getContext(), null);
+        mNotificationContainerParent.addView(keyguardStatusView);
+        mNotificationContainerParent.onFinishInflate();
+        when(mView.findViewById(R.id.notification_container_parent))
+                .thenReturn(mNotificationContainerParent);
+        when(mFragmentService.getFragmentHostManager(mView)).thenReturn(mFragmentHostManager);
+        FlingAnimationUtils.Builder flingAnimationUtilsBuilder = new FlingAnimationUtils.Builder(
+                mDisplayMetrics);
+        when(mKeyguardQsUserSwitchComponentFactory.build(any()))
+                .thenReturn(mKeyguardQsUserSwitchComponent);
+        when(mKeyguardQsUserSwitchComponent.getKeyguardQsUserSwitchController())
+                .thenReturn(mKeyguardQsUserSwitchController);
+        when(mKeyguardUserSwitcherComponentFactory.build(any()))
+                .thenReturn(mKeyguardUserSwitcherComponent);
+        when(mKeyguardUserSwitcherComponent.getKeyguardUserSwitcherController())
+                .thenReturn(mKeyguardUserSwitcherController);
+        when(mScreenOffAnimationController.shouldAnimateClockChange()).thenReturn(true);
+        when(mQs.getView()).thenReturn(mView);
+        when(mQSFragment.getView()).thenReturn(mView);
+        doAnswer(invocation -> {
+            mFragmentListener = invocation.getArgument(1);
+            return null;
+        }).when(mFragmentHostManager).addTagListener(eq(QS.TAG), any());
+        doAnswer((Answer<Void>) invocation -> {
+            mTouchHandler = invocation.getArgument(0);
+            return null;
+        }).when(mView).setOnTouchListener(any(NotificationPanelViewController.TouchHandler.class));
+
+        // Dreaming->Lockscreen
+        when(mKeyguardTransitionInteractor.getDreamingToLockscreenTransition())
+                .thenReturn(emptyFlow());
+        when(mDreamingToLockscreenTransitionViewModel.getLockscreenAlpha())
+                .thenReturn(emptyFlow());
+        when(mDreamingToLockscreenTransitionViewModel.lockscreenTranslationY(anyInt()))
+                .thenReturn(emptyFlow());
+
+        // Occluded->Lockscreen
+        when(mKeyguardTransitionInteractor.getOccludedToLockscreenTransition())
+                .thenReturn(emptyFlow());
+        when(mOccludedToLockscreenTransitionViewModel.getLockscreenAlpha())
+                .thenReturn(emptyFlow());
+        when(mOccludedToLockscreenTransitionViewModel.lockscreenTranslationY(anyInt()))
+                .thenReturn(emptyFlow());
+
+        // Lockscreen->Dreaming
+        when(mKeyguardTransitionInteractor.getLockscreenToDreamingTransition())
+                .thenReturn(emptyFlow());
+        when(mLockscreenToDreamingTransitionViewModel.getLockscreenAlpha())
+                .thenReturn(emptyFlow());
+        when(mLockscreenToDreamingTransitionViewModel.lockscreenTranslationY(anyInt()))
+                .thenReturn(emptyFlow());
+
+        // Gone->Dreaming
+        when(mKeyguardTransitionInteractor.getGoneToDreamingTransition())
+                .thenReturn(emptyFlow());
+        when(mGoneToDreamingTransitionViewModel.getLockscreenAlpha())
+                .thenReturn(emptyFlow());
+        when(mGoneToDreamingTransitionViewModel.lockscreenTranslationY(anyInt()))
+                .thenReturn(emptyFlow());
+
+        // Lockscreen->Occluded
+        when(mKeyguardTransitionInteractor.getLockscreenToOccludedTransition())
+                .thenReturn(emptyFlow());
+        when(mLockscreenToOccludedTransitionViewModel.getLockscreenAlpha())
+                .thenReturn(emptyFlow());
+        when(mLockscreenToOccludedTransitionViewModel.lockscreenTranslationY(anyInt()))
+                .thenReturn(emptyFlow());
+
+        NotificationWakeUpCoordinator coordinator =
+                new NotificationWakeUpCoordinator(
+                        mDumpManager,
+                        mock(HeadsUpManagerPhone.class),
+                        new StatusBarStateControllerImpl(new UiEventLoggerFake(), mDumpManager,
+                                mInteractionJankMonitor, mShadeExpansionStateManager),
+                        mKeyguardBypassController,
+                        mDozeParameters,
+                        mScreenOffAnimationController,
+                        mock(NotificationWakeUpCoordinatorLogger.class));
+        mConfigurationController = new ConfigurationControllerImpl(mContext);
+        PulseExpansionHandler expansionHandler = new PulseExpansionHandler(
+                mContext,
+                coordinator,
+                mKeyguardBypassController, mHeadsUpManager,
+                mock(NotificationRoundnessManager.class),
+                mConfigurationController,
+                mStatusBarStateController,
+                mFalsingManager,
+                mShadeExpansionStateManager,
+                mLockscreenShadeTransitionController,
+                new FalsingCollectorFake(),
+                mDumpManager);
+        when(mKeyguardStatusViewComponentFactory.build(any()))
+                .thenReturn(mKeyguardStatusViewComponent);
+        when(mKeyguardStatusViewComponent.getKeyguardClockSwitchController())
+                .thenReturn(mKeyguardClockSwitchController);
+        when(mKeyguardStatusViewComponent.getKeyguardStatusViewController())
+                .thenReturn(mKeyguardStatusViewController);
+        when(mKeyguardStatusBarViewComponentFactory.build(any(), any()))
+                .thenReturn(mKeyguardStatusBarViewComponent);
+        when(mKeyguardStatusBarViewComponent.getKeyguardStatusBarViewController())
+                .thenReturn(mKeyguardStatusBarViewController);
+        when(mLayoutInflater.inflate(eq(R.layout.keyguard_status_view), any(), anyBoolean()))
+                .thenReturn(keyguardStatusView);
+        when(mLayoutInflater.inflate(eq(R.layout.keyguard_user_switcher), any(), anyBoolean()))
+                .thenReturn(mUserSwitcherView);
+        when(mLayoutInflater.inflate(eq(R.layout.keyguard_bottom_area), any(), anyBoolean()))
+                .thenReturn(mKeyguardBottomArea);
+        when(mNotificationRemoteInputManager.isRemoteInputActive())
+                .thenReturn(false);
+        when(mInteractionJankMonitor.begin(any(), anyInt()))
+                .thenReturn(true);
+        when(mInteractionJankMonitor.end(anyInt()))
+                .thenReturn(true);
+        doAnswer(invocation -> {
+            ((Runnable) invocation.getArgument(0)).run();
+            return null;
+        }).when(mNotificationShadeWindowController).batchApplyWindowLayoutParams(any());
+        doAnswer(invocation -> {
+            mLayoutChangeListener = invocation.getArgument(0);
+            return null;
+        }).when(mView).addOnLayoutChangeListener(any());
+
+        when(mView.getViewTreeObserver()).thenReturn(mViewTreeObserver);
+        when(mView.getParent()).thenReturn(mViewParent);
+        when(mQs.getHeader()).thenReturn(mQsHeader);
+        when(mDownMotionEvent.getAction()).thenReturn(MotionEvent.ACTION_DOWN);
+        when(mSysUiState.setFlag(anyInt(), anyBoolean())).thenReturn(mSysUiState);
+
+        mMainHandler = new Handler(Looper.getMainLooper());
+
+        when(mView.requireViewById(R.id.keyguard_long_press))
+                .thenReturn(mock(LongPressHandlingView.class));
+
+        mNotificationPanelViewController = new NotificationPanelViewController(
+                mView,
+                mMainHandler,
+                mLayoutInflater,
+                mFeatureFlags,
+                coordinator, expansionHandler, mDynamicPrivacyController, mKeyguardBypassController,
+                mFalsingManager, new FalsingCollectorFake(),
+                mKeyguardStateController,
+                mStatusBarStateController,
+                mStatusBarWindowStateController,
+                mNotificationShadeWindowController,
+                mDozeLog, mDozeParameters, mCommandQueue, mVibratorHelper,
+                mLatencyTracker, mPowerManager, mAccessibilityManager, 0, mUpdateMonitor,
+                mMetricsLogger,
+                mShadeLog,
+                mShadeHeightLogger,
+                mConfigurationController,
+                () -> flingAnimationUtilsBuilder, mStatusBarTouchableRegionManager,
+                mConversationNotificationManager, mMediaHierarchyManager,
+                mStatusBarKeyguardViewManager,
+                mGutsManager,
+                mNotificationsQSContainerController,
+                mNotificationStackScrollLayoutController,
+                mKeyguardStatusViewComponentFactory,
+                mKeyguardQsUserSwitchComponentFactory,
+                mKeyguardUserSwitcherComponentFactory,
+                mKeyguardStatusBarViewComponentFactory,
+                mLockscreenShadeTransitionController,
+                mAuthController,
+                mScrimController,
+                mUserManager,
+                mMediaDataManager,
+                mNotificationShadeDepthController,
+                mAmbientState,
+                mLockIconViewController,
+                mKeyguardMediaController,
+                mTapAgainViewController,
+                mNavigationModeController,
+                mNavigationBarController,
+                mQsController,
+                mFragmentService,
+                mContentResolver,
+                mRecordingController,
+                mShadeHeaderController,
+                mScreenOffAnimationController,
+                mLockscreenGestureLogger,
+                mShadeExpansionStateManager,
+                mNotificationRemoteInputManager,
+                mSysUIUnfoldComponent,
+                mSysUiState,
+                () -> mKeyguardBottomAreaViewController,
+                mKeyguardUnlockAnimationController,
+                mKeyguardIndicationController,
+                mNotificationListContainer,
+                mNotificationStackSizeCalculator,
+                mUnlockedScreenOffAnimationController,
+                mShadeTransitionController,
+                systemClock,
+                mKeyguardBottomAreaViewModel,
+                mKeyguardBottomAreaInteractor,
+                mAlternateBouncerInteractor,
+                mDreamingToLockscreenTransitionViewModel,
+                mOccludedToLockscreenTransitionViewModel,
+                mLockscreenToDreamingTransitionViewModel,
+                mGoneToDreamingTransitionViewModel,
+                mLockscreenToOccludedTransitionViewModel,
+                mMainDispatcher,
+                mKeyguardTransitionInteractor,
+                mDumpManager,
+                mKeyuardLongPressViewModel,
+                mKeyguardInteractor);
+        mNotificationPanelViewController.initDependencies(
+                mCentralSurfaces,
+                null,
+                () -> {},
+                mNotificationShelfController);
+        mNotificationPanelViewController.setTrackingStartedListener(() -> {});
+        mNotificationPanelViewController.setOpenCloseListener(
+                new NotificationPanelViewController.OpenCloseListener() {
+                    @Override
+                    public void onClosingFinished() {}
+
+                    @Override
+                    public void onOpenStarted() {}
+                });
+        mNotificationPanelViewController.setHeadsUpManager(mHeadsUpManager);
+        ArgumentCaptor<View.OnAttachStateChangeListener> onAttachStateChangeListenerArgumentCaptor =
+                ArgumentCaptor.forClass(View.OnAttachStateChangeListener.class);
+        verify(mView, atLeast(1)).addOnAttachStateChangeListener(
+                onAttachStateChangeListenerArgumentCaptor.capture());
+        mOnAttachStateChangeListeners = onAttachStateChangeListenerArgumentCaptor.getAllValues();
+
+        ArgumentCaptor<View.AccessibilityDelegate> accessibilityDelegateArgumentCaptor =
+                ArgumentCaptor.forClass(View.AccessibilityDelegate.class);
+        verify(mView).setAccessibilityDelegate(accessibilityDelegateArgumentCaptor.capture());
+        mAccessibilityDelegate = accessibilityDelegateArgumentCaptor.getValue();
+        mNotificationPanelViewController.getStatusBarStateController()
+                .addCallback(mNotificationPanelViewController.getStatusBarStateListener());
+        mNotificationPanelViewController
+                .setHeadsUpAppearanceController(mock(HeadsUpAppearanceController.class));
+        verify(mNotificationStackScrollLayoutController)
+                .setOnEmptySpaceClickListener(mEmptySpaceClickListenerCaptor.capture());
+        verify(mKeyguardStatusViewController).displayClock(LARGE, /* animate */ true);
+        reset(mKeyguardStatusViewController);
+
+        when(mNotificationPanelViewControllerLazy.get())
+                .thenReturn(mNotificationPanelViewController);
+        mQuickSettingsController = new QuickSettingsController(
+                mNotificationPanelViewControllerLazy,
+                mView,
+                mQsFrameTranslateController,
+                mShadeTransitionController,
+                expansionHandler,
+                mNotificationRemoteInputManager,
+                mShadeExpansionStateManager,
+                mStatusBarKeyguardViewManager,
+                mNotificationStackScrollLayoutController,
+                mLockscreenShadeTransitionController,
+                mNotificationShadeDepthController,
+                mShadeHeaderController,
+                mStatusBarTouchableRegionManager,
+                mKeyguardStateController,
+                mKeyguardBypassController,
+                mUpdateMonitor,
+                mScrimController,
+                mMediaDataManager,
+                mMediaHierarchyManager,
+                mAmbientState,
+                mRecordingController,
+                mFalsingManager,
+                new FalsingCollectorFake(),
+                mAccessibilityManager,
+                mLockscreenGestureLogger,
+                mMetricsLogger,
+                mFeatureFlags,
+                mInteractionJankMonitor,
+                mShadeLog
+        );
+    }
+
+    @After
+    public void tearDown() {
+        mNotificationPanelViewController.mBottomAreaShadeAlphaAnimator.cancel();
+        mNotificationPanelViewController.cancelHeightAnimator();
+        mMainHandler.removeCallbacksAndMessages(null);
+    }
+
+    protected void setBottomPadding(int stackBottom, int lockIconPadding, int indicationPadding,
+            int ambientPadding) {
+
+        when(mNotificationStackScrollLayoutController.getTop()).thenReturn(0);
+        when(mNotificationStackScrollLayoutController.getHeight()).thenReturn(stackBottom);
+        when(mNotificationStackScrollLayoutController.getBottom()).thenReturn(stackBottom);
+        when(mLockIconViewController.getTop()).thenReturn((float) (stackBottom - lockIconPadding));
+
+        when(mResources.getDimensionPixelSize(R.dimen.keyguard_indication_bottom_padding))
+                .thenReturn(indicationPadding);
+        mNotificationPanelViewController.loadDimens();
+
+        mNotificationPanelViewController.setAmbientIndicationTop(
+                /* ambientIndicationTop= */ stackBottom - ambientPadding,
+                /* ambientTextVisible= */ true);
+    }
+
+    protected void triggerPositionClockAndNotifications() {
+        mNotificationPanelViewController.onQsSetExpansionHeightCalled(false);
+    }
+
+    protected FalsingManager.FalsingTapListener getFalsingTapListener() {
+        for (View.OnAttachStateChangeListener listener : mOnAttachStateChangeListeners) {
+            listener.onViewAttachedToWindow(mView);
+        }
+        assertThat(mFalsingManager.getTapListeners().size()).isEqualTo(1);
+        return mFalsingManager.getTapListeners().get(0);
+    }
+
+    protected void givenViewAttached() {
+        for (View.OnAttachStateChangeListener listener : mOnAttachStateChangeListeners) {
+            listener.onViewAttachedToWindow(mView);
+        }
+    }
+
+    protected ConstraintSet.Layout getConstraintSetLayout(@IdRes int id) {
+        ConstraintSet constraintSet = new ConstraintSet();
+        constraintSet.clone(mNotificationContainerParent);
+        return constraintSet.getConstraint(id).layout;
+    }
+
+    protected void enableSplitShade(boolean enabled) {
+        when(mResources.getBoolean(R.bool.config_use_split_notification_shade)).thenReturn(enabled);
+        mNotificationPanelViewController.updateResources();
+    }
+
+    protected void updateMultiUserSetting(boolean enabled) {
+        when(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user)).thenReturn(false);
+        when(mUserManager.isUserSwitcherEnabled(false)).thenReturn(enabled);
+        final ArgumentCaptor<ContentObserver> observerCaptor =
+                ArgumentCaptor.forClass(ContentObserver.class);
+        verify(mContentResolver)
+                .registerContentObserver(any(), anyBoolean(), observerCaptor.capture());
+        observerCaptor.getValue().onChange(/* selfChange */ false);
+    }
+
+    protected void updateSmallestScreenWidth(int smallestScreenWidthDp) {
+        Configuration configuration = new Configuration();
+        configuration.smallestScreenWidthDp = smallestScreenWidthDp;
+        mConfigurationController.onConfigurationChanged(configuration);
+    }
+
+    protected void onTouchEvent(MotionEvent ev) {
+        mTouchHandler.onTouch(mView, ev);
+    }
+
+    protected void setDozing(boolean dozing, boolean dozingAlwaysOn) {
+        when(mDozeParameters.getAlwaysOn()).thenReturn(dozingAlwaysOn);
+        mNotificationPanelViewController.setDozing(
+                /* dozing= */ dozing,
+                /* animate= */ false
+        );
+    }
+
+    protected void assertKeyguardStatusViewCentered() {
+        mNotificationPanelViewController.updateResources();
+        assertThat(getConstraintSetLayout(R.id.keyguard_status_view).endToEnd).isAnyOf(
+                ConstraintSet.PARENT_ID, ConstraintSet.UNSET);
+    }
+
+    protected void assertKeyguardStatusViewNotCentered() {
+        mNotificationPanelViewController.updateResources();
+        assertThat(getConstraintSetLayout(R.id.keyguard_status_view).endToEnd).isEqualTo(
+                R.id.qs_edge_guideline);
+    }
+
+    protected void setIsFullWidth(boolean fullWidth) {
+        float nsslWidth = fullWidth ? PANEL_WIDTH : PANEL_WIDTH / 2f;
+        when(mNotificationStackScrollLayoutController.getWidth()).thenReturn(nsslWidth);
+        triggerLayoutChange();
+    }
+
+    protected void triggerLayoutChange() {
+        mLayoutChangeListener.onLayoutChange(
+                mView,
+                /* left= */ 0,
+                /* top= */ 0,
+                /* right= */ 0,
+                /* bottom= */ 0,
+                /* oldLeft= */ 0,
+                /* oldTop= */ 0,
+                /* oldRight= */ 0,
+                /* oldBottom= */ 0
+        );
+    }
+
+    protected CoroutineDispatcher getMainDispatcher() {
+        return mMainDispatcher;
+    }
+}
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 8f6653f..abcde3d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
@@ -16,8 +16,6 @@
 
 package com.android.systemui.shade;
 
-import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
-
 import static com.android.keyguard.FaceAuthApiRequestReason.NOTIFICATION_PANEL_CLICKED;
 import static com.android.keyguard.KeyguardClockSwitch.LARGE;
 import static com.android.keyguard.KeyguardClockSwitch.SMALL;
@@ -31,592 +29,53 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyFloat;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.atLeast;
-import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.clearInvocations;
-import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import android.annotation.IdRes;
-import android.content.ContentResolver;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.database.ContentObserver;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.PowerManager;
-import android.os.UserManager;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
-import android.util.DisplayMetrics;
-import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewParent;
-import android.view.ViewPropertyAnimator;
-import android.view.ViewStub;
-import android.view.ViewTreeObserver;
-import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.AccessibilityNodeInfo;
 
 import androidx.constraintlayout.widget.ConstraintSet;
 import androidx.test.filters.SmallTest;
 
-import com.android.internal.jank.InteractionJankMonitor;
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.UiEventLogger;
-import com.android.internal.logging.testing.UiEventLoggerFake;
-import com.android.internal.util.CollectionUtils;
-import com.android.internal.util.LatencyTracker;
 import com.android.keyguard.FaceAuthApiRequestReason;
-import com.android.keyguard.KeyguardClockSwitch;
-import com.android.keyguard.KeyguardClockSwitchController;
-import com.android.keyguard.KeyguardStatusView;
-import com.android.keyguard.KeyguardStatusViewController;
-import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.keyguard.LockIconViewController;
-import com.android.keyguard.dagger.KeyguardQsUserSwitchComponent;
-import com.android.keyguard.dagger.KeyguardStatusBarViewComponent;
-import com.android.keyguard.dagger.KeyguardStatusViewComponent;
-import com.android.keyguard.dagger.KeyguardUserSwitcherComponent;
 import com.android.systemui.DejankUtils;
 import com.android.systemui.R;
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.biometrics.AuthController;
-import com.android.systemui.classifier.FalsingCollectorFake;
-import com.android.systemui.classifier.FalsingManagerFake;
-import com.android.systemui.common.ui.view.LongPressHandlingView;
-import com.android.systemui.doze.DozeLog;
-import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.fragments.FragmentHostManager;
-import com.android.systemui.fragments.FragmentService;
-import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
-import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
-import com.android.systemui.keyguard.domain.interactor.KeyguardBottomAreaInteractor;
-import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
-import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
-import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel;
-import com.android.systemui.keyguard.ui.viewmodel.GoneToDreamingTransitionViewModel;
-import com.android.systemui.keyguard.ui.viewmodel.KeyguardBottomAreaViewModel;
-import com.android.systemui.keyguard.ui.viewmodel.KeyguardLongPressViewModel;
-import com.android.systemui.keyguard.ui.viewmodel.LockscreenToDreamingTransitionViewModel;
-import com.android.systemui.keyguard.ui.viewmodel.LockscreenToOccludedTransitionViewModel;
-import com.android.systemui.keyguard.ui.viewmodel.OccludedToLockscreenTransitionViewModel;
-import com.android.systemui.media.controls.pipeline.MediaDataManager;
-import com.android.systemui.media.controls.ui.KeyguardMediaController;
-import com.android.systemui.media.controls.ui.MediaHierarchyManager;
-import com.android.systemui.model.SysUiState;
-import com.android.systemui.navigationbar.NavigationBarController;
-import com.android.systemui.navigationbar.NavigationModeController;
-import com.android.systemui.plugins.FalsingManager;
-import com.android.systemui.plugins.qs.QS;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.qs.QSFragment;
-import com.android.systemui.screenrecord.RecordingController;
-import com.android.systemui.shade.transition.ShadeTransitionController;
-import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.KeyguardIndicationController;
-import com.android.systemui.statusbar.LockscreenShadeTransitionController;
-import com.android.systemui.statusbar.NotificationRemoteInputManager;
-import com.android.systemui.statusbar.NotificationShadeDepthController;
-import com.android.systemui.statusbar.NotificationShadeWindowController;
-import com.android.systemui.statusbar.NotificationShelfController;
-import com.android.systemui.statusbar.PulseExpansionHandler;
-import com.android.systemui.statusbar.QsFrameTranslateController;
-import com.android.systemui.statusbar.StatusBarStateControllerImpl;
-import com.android.systemui.statusbar.SysuiStatusBarStateController;
-import com.android.systemui.statusbar.VibratorHelper;
-import com.android.systemui.statusbar.notification.ConversationNotificationManager;
-import com.android.systemui.statusbar.notification.DynamicPrivacyController;
-import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
-import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinatorLogger;
 import com.android.systemui.statusbar.notification.row.ExpandableView;
 import com.android.systemui.statusbar.notification.row.ExpandableView.OnHeightChangedListener;
-import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
 import com.android.systemui.statusbar.notification.stack.AmbientState;
-import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
-import com.android.systemui.statusbar.notification.stack.NotificationRoundnessManager;
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
-import com.android.systemui.statusbar.notification.stack.NotificationStackSizeCalculator;
-import com.android.systemui.statusbar.phone.CentralSurfaces;
-import com.android.systemui.statusbar.phone.ConfigurationControllerImpl;
-import com.android.systemui.statusbar.phone.DozeParameters;
-import com.android.systemui.statusbar.phone.HeadsUpAppearanceController;
-import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
-import com.android.systemui.statusbar.phone.HeadsUpTouchHelper;
-import com.android.systemui.statusbar.phone.KeyguardBottomAreaView;
-import com.android.systemui.statusbar.phone.KeyguardBottomAreaViewController;
-import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.phone.KeyguardStatusBarView;
-import com.android.systemui.statusbar.phone.KeyguardStatusBarViewController;
-import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
-import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
-import com.android.systemui.statusbar.phone.ScrimController;
-import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
-import com.android.systemui.statusbar.phone.StatusBarTouchableRegionManager;
-import com.android.systemui.statusbar.phone.TapAgainViewController;
-import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
-import com.android.systemui.statusbar.policy.ConfigurationController;
-import com.android.systemui.statusbar.policy.KeyguardQsUserSwitchController;
-import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.systemui.statusbar.policy.KeyguardUserSwitcherController;
-import com.android.systemui.statusbar.policy.KeyguardUserSwitcherView;
-import com.android.systemui.statusbar.window.StatusBarWindowStateController;
-import com.android.systemui.unfold.SysUIUnfoldComponent;
-import com.android.systemui.util.time.FakeSystemClock;
-import com.android.systemui.util.time.SystemClock;
-import com.android.wm.shell.animation.FlingAnimationUtils;
 
-import org.junit.After;
 import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
 import org.mockito.InOrder;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.mockito.stubbing.Answer;
 
 import java.util.List;
-import java.util.Optional;
-
-import dagger.Lazy;
-import kotlinx.coroutines.CoroutineDispatcher;
 
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper(setAsMainLooper = true)
-public class NotificationPanelViewControllerTest extends SysuiTestCase {
-
-    private static final int SPLIT_SHADE_FULL_TRANSITION_DISTANCE = 400;
-    private static final int NOTIFICATION_SCRIM_TOP_PADDING_IN_SPLIT_SHADE = 50;
-    private static final int PANEL_WIDTH = 500; // Random value just for the test.
-
-    @Mock private CentralSurfaces mCentralSurfaces;
-    @Mock private NotificationStackScrollLayout mNotificationStackScrollLayout;
-    @Mock private KeyguardBottomAreaView mKeyguardBottomArea;
-    @Mock private KeyguardBottomAreaViewController mKeyguardBottomAreaViewController;
-    @Mock private KeyguardBottomAreaView mQsFrame;
-    @Mock private HeadsUpManagerPhone mHeadsUpManager;
-    @Mock private NotificationShelfController mNotificationShelfController;
-    @Mock private NotificationGutsManager mGutsManager;
-    @Mock private KeyguardStatusBarView mKeyguardStatusBar;
-    @Mock private KeyguardUserSwitcherView mUserSwitcherView;
-    @Mock private ViewStub mUserSwitcherStubView;
-    @Mock private HeadsUpTouchHelper.Callback mHeadsUpCallback;
-    @Mock private KeyguardUpdateMonitor mUpdateMonitor;
-    @Mock private KeyguardBypassController mKeyguardBypassController;
-    @Mock private DozeParameters mDozeParameters;
-    @Mock private ScreenOffAnimationController mScreenOffAnimationController;
-    @Mock private NotificationPanelView mView;
-    @Mock private LayoutInflater mLayoutInflater;
-    @Mock private FeatureFlags mFeatureFlags;
-    @Mock private DynamicPrivacyController mDynamicPrivacyController;
-    @Mock private StatusBarTouchableRegionManager mStatusBarTouchableRegionManager;
-    @Mock private KeyguardStateController mKeyguardStateController;
-    @Mock private DozeLog mDozeLog;
-    @Mock private ShadeLogger mShadeLog;
-    @Mock private ShadeHeightLogger mShadeHeightLogger;
-    @Mock private CommandQueue mCommandQueue;
-    @Mock private VibratorHelper mVibratorHelper;
-    @Mock private LatencyTracker mLatencyTracker;
-    @Mock private PowerManager mPowerManager;
-    @Mock private AccessibilityManager mAccessibilityManager;
-    @Mock private MetricsLogger mMetricsLogger;
-    @Mock private Resources mResources;
-    @Mock private Configuration mConfiguration;
-    @Mock private KeyguardClockSwitch mKeyguardClockSwitch;
-    @Mock private MediaHierarchyManager mMediaHierarchyManager;
-    @Mock private ConversationNotificationManager mConversationNotificationManager;
-    @Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
-    @Mock private KeyguardStatusViewComponent.Factory mKeyguardStatusViewComponentFactory;
-    @Mock private KeyguardQsUserSwitchComponent.Factory mKeyguardQsUserSwitchComponentFactory;
-    @Mock private KeyguardQsUserSwitchComponent mKeyguardQsUserSwitchComponent;
-    @Mock private KeyguardQsUserSwitchController mKeyguardQsUserSwitchController;
-    @Mock private KeyguardUserSwitcherComponent.Factory mKeyguardUserSwitcherComponentFactory;
-    @Mock private KeyguardUserSwitcherComponent mKeyguardUserSwitcherComponent;
-    @Mock private KeyguardUserSwitcherController mKeyguardUserSwitcherController;
-    @Mock private KeyguardStatusViewComponent mKeyguardStatusViewComponent;
-    @Mock private KeyguardStatusBarViewComponent.Factory mKeyguardStatusBarViewComponentFactory;
-    @Mock private KeyguardStatusBarViewComponent mKeyguardStatusBarViewComponent;
-    @Mock private KeyguardClockSwitchController mKeyguardClockSwitchController;
-    @Mock private KeyguardStatusViewController mKeyguardStatusViewController;
-    @Mock private KeyguardStatusBarViewController mKeyguardStatusBarViewController;
-    @Mock private NotificationStackScrollLayoutController mNotificationStackScrollLayoutController;
-    @Mock private NotificationShadeDepthController mNotificationShadeDepthController;
-    @Mock private LockscreenShadeTransitionController mLockscreenShadeTransitionController;
-    @Mock private AuthController mAuthController;
-    @Mock private ScrimController mScrimController;
-    @Mock private MediaDataManager mMediaDataManager;
-    @Mock private AmbientState mAmbientState;
-    @Mock private UserManager mUserManager;
-    @Mock private UiEventLogger mUiEventLogger;
-    @Mock private LockIconViewController mLockIconViewController;
-    @Mock private KeyguardMediaController mKeyguardMediaController;
-    @Mock private NavigationModeController mNavigationModeController;
-    @Mock private NavigationBarController mNavigationBarController;
-    @Mock private QuickSettingsController mQsController;
-    @Mock private ShadeHeaderController mShadeHeaderController;
-    @Mock private ContentResolver mContentResolver;
-    @Mock private TapAgainViewController mTapAgainViewController;
-    @Mock private KeyguardIndicationController mKeyguardIndicationController;
-    @Mock private FragmentService mFragmentService;
-    @Mock private FragmentHostManager mFragmentHostManager;
-    @Mock private NotificationRemoteInputManager mNotificationRemoteInputManager;
-    @Mock private RecordingController mRecordingController;
-    @Mock private LockscreenGestureLogger mLockscreenGestureLogger;
-    @Mock private DumpManager mDumpManager;
-    @Mock private InteractionJankMonitor mInteractionJankMonitor;
-    @Mock private NotificationsQSContainerController mNotificationsQSContainerController;
-    @Mock private QsFrameTranslateController mQsFrameTranslateController;
-    @Mock private StatusBarWindowStateController mStatusBarWindowStateController;
-    @Mock private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
-    @Mock private NotificationShadeWindowController mNotificationShadeWindowController;
-    @Mock private SysUiState mSysUiState;
-    @Mock private NotificationListContainer mNotificationListContainer;
-    @Mock private NotificationStackSizeCalculator mNotificationStackSizeCalculator;
-    @Mock private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
-    @Mock private ShadeTransitionController mShadeTransitionController;
-    @Mock private QS mQs;
-    @Mock private QSFragment mQSFragment;
-    @Mock private ViewGroup mQsHeader;
-    @Mock private ViewParent mViewParent;
-    @Mock private ViewTreeObserver mViewTreeObserver;
-    @Mock private KeyguardBottomAreaViewModel mKeyguardBottomAreaViewModel;
-    @Mock private KeyguardBottomAreaInteractor mKeyguardBottomAreaInteractor;
-    @Mock private AlternateBouncerInteractor mAlternateBouncerInteractor;
-    @Mock private DreamingToLockscreenTransitionViewModel mDreamingToLockscreenTransitionViewModel;
-    @Mock private OccludedToLockscreenTransitionViewModel mOccludedToLockscreenTransitionViewModel;
-    @Mock private LockscreenToDreamingTransitionViewModel mLockscreenToDreamingTransitionViewModel;
-    @Mock private LockscreenToOccludedTransitionViewModel mLockscreenToOccludedTransitionViewModel;
-    @Mock private GoneToDreamingTransitionViewModel mGoneToDreamingTransitionViewModel;
-
-    @Mock private KeyguardTransitionInteractor mKeyguardTransitionInteractor;
-    @Mock private KeyguardInteractor mKeyguardInteractor;
-    @Mock private KeyguardLongPressViewModel mKeyuardLongPressViewModel;
-    @Mock private CoroutineDispatcher mMainDispatcher;
-    @Mock private MotionEvent mDownMotionEvent;
-    @Captor
-    private ArgumentCaptor<NotificationStackScrollLayout.OnEmptySpaceClickListener>
-            mEmptySpaceClickListenerCaptor;
-
-    private NotificationPanelViewController.TouchHandler mTouchHandler;
-    private ConfigurationController mConfigurationController;
-    private SysuiStatusBarStateController mStatusBarStateController;
-    private NotificationPanelViewController mNotificationPanelViewController;
-    private View.AccessibilityDelegate mAccessibilityDelegate;
-    private NotificationsQuickSettingsContainer mNotificationContainerParent;
-    private List<View.OnAttachStateChangeListener> mOnAttachStateChangeListeners;
-    private Handler mMainHandler;
-    private View.OnLayoutChangeListener mLayoutChangeListener;
-
-    private final FalsingManagerFake mFalsingManager = new FalsingManagerFake();
-    private final Optional<SysUIUnfoldComponent> mSysUIUnfoldComponent = Optional.empty();
-    private final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
-    private final ShadeExpansionStateManager mShadeExpansionStateManager =
-            new ShadeExpansionStateManager();
-
-    private QuickSettingsController mQuickSettingsController;
-    @Mock private Lazy<NotificationPanelViewController> mNotificationPanelViewControllerLazy;
-
-    private FragmentHostManager.FragmentListener mFragmentListener;
+public class NotificationPanelViewControllerTest extends NotificationPanelViewControllerBaseTest {
 
     @Before
-    public void setup() {
-        MockitoAnnotations.initMocks(this);
-        SystemClock systemClock = new FakeSystemClock();
-        mStatusBarStateController = new StatusBarStateControllerImpl(mUiEventLogger, mDumpManager,
-                mInteractionJankMonitor, mShadeExpansionStateManager);
-
-        KeyguardStatusView keyguardStatusView = new KeyguardStatusView(mContext);
-        keyguardStatusView.setId(R.id.keyguard_status_view);
+    public void before() {
         DejankUtils.setImmediate(true);
-
-        when(mAuthController.isUdfpsEnrolled(anyInt())).thenReturn(false);
-        when(mHeadsUpCallback.getContext()).thenReturn(mContext);
-        when(mView.getResources()).thenReturn(mResources);
-        when(mView.getWidth()).thenReturn(PANEL_WIDTH);
-        when(mResources.getConfiguration()).thenReturn(mConfiguration);
-        mConfiguration.orientation = ORIENTATION_PORTRAIT;
-        when(mResources.getDisplayMetrics()).thenReturn(mDisplayMetrics);
-        mDisplayMetrics.density = 100;
-        when(mResources.getBoolean(R.bool.config_enableNotificationShadeDrag)).thenReturn(true);
-        when(mResources.getDimensionPixelSize(R.dimen.notifications_top_padding_split_shade))
-                .thenReturn(NOTIFICATION_SCRIM_TOP_PADDING_IN_SPLIT_SHADE);
-        when(mResources.getDimensionPixelSize(R.dimen.notification_panel_margin_horizontal))
-                .thenReturn(10);
-        when(mResources.getDimensionPixelSize(R.dimen.split_shade_full_transition_distance))
-                .thenReturn(SPLIT_SHADE_FULL_TRANSITION_DISTANCE);
-        when(mView.getContext()).thenReturn(getContext());
-        when(mView.findViewById(R.id.keyguard_header)).thenReturn(mKeyguardStatusBar);
-        when(mView.findViewById(R.id.keyguard_user_switcher_view)).thenReturn(mUserSwitcherView);
-        when(mView.findViewById(R.id.keyguard_user_switcher_stub)).thenReturn(
-                mUserSwitcherStubView);
-        when(mView.findViewById(R.id.keyguard_clock_container)).thenReturn(mKeyguardClockSwitch);
-        when(mView.findViewById(R.id.notification_stack_scroller))
-                .thenReturn(mNotificationStackScrollLayout);
-        when(mNotificationStackScrollLayoutController.getHeight()).thenReturn(1000);
-        when(mNotificationStackScrollLayoutController.getHeadsUpCallback())
-                .thenReturn(mHeadsUpCallback);
-        when(mKeyguardBottomAreaViewController.getView()).thenReturn(mKeyguardBottomArea);
-        when(mView.findViewById(R.id.keyguard_bottom_area)).thenReturn(mKeyguardBottomArea);
-        when(mKeyguardBottomArea.animate()).thenReturn(mock(ViewPropertyAnimator.class));
-        when(mView.findViewById(R.id.qs_frame)).thenReturn(mQsFrame);
-        when(mView.findViewById(R.id.keyguard_status_view))
-                .thenReturn(mock(KeyguardStatusView.class));
-        mNotificationContainerParent = new NotificationsQuickSettingsContainer(getContext(), null);
-        mNotificationContainerParent.addView(keyguardStatusView);
-        mNotificationContainerParent.onFinishInflate();
-        when(mView.findViewById(R.id.notification_container_parent))
-                .thenReturn(mNotificationContainerParent);
-        when(mFragmentService.getFragmentHostManager(mView)).thenReturn(mFragmentHostManager);
-        FlingAnimationUtils.Builder flingAnimationUtilsBuilder = new FlingAnimationUtils.Builder(
-                mDisplayMetrics);
-        when(mKeyguardQsUserSwitchComponentFactory.build(any()))
-                .thenReturn(mKeyguardQsUserSwitchComponent);
-        when(mKeyguardQsUserSwitchComponent.getKeyguardQsUserSwitchController())
-                .thenReturn(mKeyguardQsUserSwitchController);
-        when(mKeyguardUserSwitcherComponentFactory.build(any()))
-                .thenReturn(mKeyguardUserSwitcherComponent);
-        when(mKeyguardUserSwitcherComponent.getKeyguardUserSwitcherController())
-                .thenReturn(mKeyguardUserSwitcherController);
-        when(mScreenOffAnimationController.shouldAnimateClockChange()).thenReturn(true);
-        when(mQs.getView()).thenReturn(mView);
-        when(mQSFragment.getView()).thenReturn(mView);
-        doAnswer(invocation -> {
-            mFragmentListener = invocation.getArgument(1);
-            return null;
-        }).when(mFragmentHostManager).addTagListener(eq(QS.TAG), any());
-        doAnswer((Answer<Void>) invocation -> {
-            mTouchHandler = invocation.getArgument(0);
-            return null;
-        }).when(mView).setOnTouchListener(any(NotificationPanelViewController.TouchHandler.class));
-
-        NotificationWakeUpCoordinator coordinator =
-                new NotificationWakeUpCoordinator(
-                        mDumpManager,
-                        mock(HeadsUpManagerPhone.class),
-                        new StatusBarStateControllerImpl(new UiEventLoggerFake(), mDumpManager,
-                                mInteractionJankMonitor, mShadeExpansionStateManager),
-                        mKeyguardBypassController,
-                        mDozeParameters,
-                        mScreenOffAnimationController,
-                        mock(NotificationWakeUpCoordinatorLogger.class));
-        mConfigurationController = new ConfigurationControllerImpl(mContext);
-        PulseExpansionHandler expansionHandler = new PulseExpansionHandler(
-                mContext,
-                coordinator,
-                mKeyguardBypassController, mHeadsUpManager,
-                mock(NotificationRoundnessManager.class),
-                mConfigurationController,
-                mStatusBarStateController,
-                mFalsingManager,
-                mShadeExpansionStateManager,
-                mLockscreenShadeTransitionController,
-                new FalsingCollectorFake(),
-                mDumpManager);
-        when(mKeyguardStatusViewComponentFactory.build(any()))
-                .thenReturn(mKeyguardStatusViewComponent);
-        when(mKeyguardStatusViewComponent.getKeyguardClockSwitchController())
-                .thenReturn(mKeyguardClockSwitchController);
-        when(mKeyguardStatusViewComponent.getKeyguardStatusViewController())
-                .thenReturn(mKeyguardStatusViewController);
-        when(mKeyguardStatusBarViewComponentFactory.build(any(), any()))
-                .thenReturn(mKeyguardStatusBarViewComponent);
-        when(mKeyguardStatusBarViewComponent.getKeyguardStatusBarViewController())
-                .thenReturn(mKeyguardStatusBarViewController);
-        when(mLayoutInflater.inflate(eq(R.layout.keyguard_status_view), any(), anyBoolean()))
-                .thenReturn(keyguardStatusView);
-        when(mLayoutInflater.inflate(eq(R.layout.keyguard_user_switcher), any(), anyBoolean()))
-                .thenReturn(mUserSwitcherView);
-        when(mLayoutInflater.inflate(eq(R.layout.keyguard_bottom_area), any(), anyBoolean()))
-                .thenReturn(mKeyguardBottomArea);
-        when(mNotificationRemoteInputManager.isRemoteInputActive())
-                .thenReturn(false);
-        when(mInteractionJankMonitor.begin(any(), anyInt()))
-                .thenReturn(true);
-        when(mInteractionJankMonitor.end(anyInt()))
-                .thenReturn(true);
-        doAnswer(invocation -> {
-            ((Runnable) invocation.getArgument(0)).run();
-            return null;
-        }).when(mNotificationShadeWindowController).batchApplyWindowLayoutParams(any());
-        doAnswer(invocation -> {
-            mLayoutChangeListener = invocation.getArgument(0);
-            return null;
-        }).when(mView).addOnLayoutChangeListener(any());
-
-        when(mView.getViewTreeObserver()).thenReturn(mViewTreeObserver);
-        when(mView.getParent()).thenReturn(mViewParent);
-        when(mQs.getHeader()).thenReturn(mQsHeader);
-        when(mDownMotionEvent.getAction()).thenReturn(MotionEvent.ACTION_DOWN);
-        when(mSysUiState.setFlag(anyInt(), anyBoolean())).thenReturn(mSysUiState);
-
-        mMainHandler = new Handler(Looper.getMainLooper());
-
-        when(mView.requireViewById(R.id.keyguard_long_press))
-                .thenReturn(mock(LongPressHandlingView.class));
-
-        mNotificationPanelViewController = new NotificationPanelViewController(
-                mView,
-                mMainHandler,
-                mLayoutInflater,
-                mFeatureFlags,
-                coordinator, expansionHandler, mDynamicPrivacyController, mKeyguardBypassController,
-                mFalsingManager, new FalsingCollectorFake(),
-                mKeyguardStateController,
-                mStatusBarStateController,
-                mStatusBarWindowStateController,
-                mNotificationShadeWindowController,
-                mDozeLog, mDozeParameters, mCommandQueue, mVibratorHelper,
-                mLatencyTracker, mPowerManager, mAccessibilityManager, 0, mUpdateMonitor,
-                mMetricsLogger,
-                mShadeLog,
-                mShadeHeightLogger,
-                mConfigurationController,
-                () -> flingAnimationUtilsBuilder, mStatusBarTouchableRegionManager,
-                mConversationNotificationManager, mMediaHierarchyManager,
-                mStatusBarKeyguardViewManager,
-                mGutsManager,
-                mNotificationsQSContainerController,
-                mNotificationStackScrollLayoutController,
-                mKeyguardStatusViewComponentFactory,
-                mKeyguardQsUserSwitchComponentFactory,
-                mKeyguardUserSwitcherComponentFactory,
-                mKeyguardStatusBarViewComponentFactory,
-                mLockscreenShadeTransitionController,
-                mAuthController,
-                mScrimController,
-                mUserManager,
-                mMediaDataManager,
-                mNotificationShadeDepthController,
-                mAmbientState,
-                mLockIconViewController,
-                mKeyguardMediaController,
-                mTapAgainViewController,
-                mNavigationModeController,
-                mNavigationBarController,
-                mQsController,
-                mFragmentService,
-                mContentResolver,
-                mRecordingController,
-                mShadeHeaderController,
-                mScreenOffAnimationController,
-                mLockscreenGestureLogger,
-                mShadeExpansionStateManager,
-                mNotificationRemoteInputManager,
-                mSysUIUnfoldComponent,
-                mSysUiState,
-                () -> mKeyguardBottomAreaViewController,
-                mKeyguardUnlockAnimationController,
-                mKeyguardIndicationController,
-                mNotificationListContainer,
-                mNotificationStackSizeCalculator,
-                mUnlockedScreenOffAnimationController,
-                mShadeTransitionController,
-                systemClock,
-                mKeyguardBottomAreaViewModel,
-                mKeyguardBottomAreaInteractor,
-                mAlternateBouncerInteractor,
-                mDreamingToLockscreenTransitionViewModel,
-                mOccludedToLockscreenTransitionViewModel,
-                mLockscreenToDreamingTransitionViewModel,
-                mGoneToDreamingTransitionViewModel,
-                mLockscreenToOccludedTransitionViewModel,
-                mMainDispatcher,
-                mKeyguardTransitionInteractor,
-                mDumpManager,
-                mKeyuardLongPressViewModel,
-                mKeyguardInteractor);
-        mNotificationPanelViewController.initDependencies(
-                mCentralSurfaces,
-                null,
-                () -> {},
-                mNotificationShelfController);
-        mNotificationPanelViewController.setTrackingStartedListener(() -> {});
-        mNotificationPanelViewController.setOpenCloseListener(
-                new NotificationPanelViewController.OpenCloseListener() {
-                    @Override
-                    public void onClosingFinished() {}
-
-                    @Override
-                    public void onOpenStarted() {}
-                });
-        mNotificationPanelViewController.setHeadsUpManager(mHeadsUpManager);
-        ArgumentCaptor<View.OnAttachStateChangeListener> onAttachStateChangeListenerArgumentCaptor =
-                ArgumentCaptor.forClass(View.OnAttachStateChangeListener.class);
-        verify(mView, atLeast(1)).addOnAttachStateChangeListener(
-                onAttachStateChangeListenerArgumentCaptor.capture());
-        mOnAttachStateChangeListeners = onAttachStateChangeListenerArgumentCaptor.getAllValues();
-
-        ArgumentCaptor<View.AccessibilityDelegate> accessibilityDelegateArgumentCaptor =
-                ArgumentCaptor.forClass(View.AccessibilityDelegate.class);
-        verify(mView).setAccessibilityDelegate(accessibilityDelegateArgumentCaptor.capture());
-        mAccessibilityDelegate = accessibilityDelegateArgumentCaptor.getValue();
-        mNotificationPanelViewController.getStatusBarStateController()
-                .addCallback(mNotificationPanelViewController.getStatusBarStateListener());
-        mNotificationPanelViewController
-                .setHeadsUpAppearanceController(mock(HeadsUpAppearanceController.class));
-        verify(mNotificationStackScrollLayoutController)
-                .setOnEmptySpaceClickListener(mEmptySpaceClickListenerCaptor.capture());
-        verify(mKeyguardStatusViewController).displayClock(LARGE, /* animate */ true);
-        reset(mKeyguardStatusViewController);
-
-        when(mNotificationPanelViewControllerLazy.get())
-                .thenReturn(mNotificationPanelViewController);
-        mQuickSettingsController = new QuickSettingsController(
-                mNotificationPanelViewControllerLazy,
-                mView,
-                mQsFrameTranslateController,
-                mShadeTransitionController,
-                expansionHandler,
-                mNotificationRemoteInputManager,
-                mShadeExpansionStateManager,
-                mStatusBarKeyguardViewManager,
-                mNotificationStackScrollLayoutController,
-                mLockscreenShadeTransitionController,
-                mNotificationShadeDepthController,
-                mShadeHeaderController,
-                mStatusBarTouchableRegionManager,
-                mKeyguardStateController,
-                mKeyguardBypassController,
-                mUpdateMonitor,
-                mScrimController,
-                mMediaDataManager,
-                mMediaHierarchyManager,
-                mAmbientState,
-                mRecordingController,
-                mFalsingManager,
-                new FalsingCollectorFake(),
-                mAccessibilityManager,
-                mLockscreenGestureLogger,
-                mMetricsLogger,
-                mFeatureFlags,
-                mInteractionJankMonitor,
-                mShadeLog
-        );
-    }
-
-    @After
-    public void tearDown() {
-        mNotificationPanelViewController.cancelHeightAnimator();
-        mMainHandler.removeCallbacksAndMessages(null);
     }
 
     @Test
@@ -671,23 +130,6 @@
                 .isNotEqualTo(-1);
     }
 
-    private void setBottomPadding(int stackBottom, int lockIconPadding, int indicationPadding,
-            int ambientPadding) {
-
-        when(mNotificationStackScrollLayoutController.getTop()).thenReturn(0);
-        when(mNotificationStackScrollLayoutController.getHeight()).thenReturn(stackBottom);
-        when(mNotificationStackScrollLayoutController.getBottom()).thenReturn(stackBottom);
-        when(mLockIconViewController.getTop()).thenReturn((float) (stackBottom - lockIconPadding));
-
-        when(mResources.getDimensionPixelSize(R.dimen.keyguard_indication_bottom_padding))
-                .thenReturn(indicationPadding);
-        mNotificationPanelViewController.loadDimens();
-
-        mNotificationPanelViewController.setAmbientIndicationTop(
-                /* ambientIndicationTop= */ stackBottom - ambientPadding,
-                /* ambientTextVisible= */ true);
-    }
-
     @Test
     @Ignore("b/261472011 - Test appears inconsistent across environments")
     public void getVerticalSpaceForLockscreenNotifications_useLockIconBottomPadding_returnsSpaceAvailable() {
@@ -992,68 +434,6 @@
     }
 
     @Test
-    public void testDisableUserSwitcherAfterEnabling_returnsViewStubToTheViewHierarchy() {
-        givenViewAttached();
-        when(mResources.getBoolean(
-                com.android.internal.R.bool.config_keyguardUserSwitcher)).thenReturn(true);
-        updateMultiUserSetting(true);
-        clearInvocations(mView);
-
-        updateMultiUserSetting(false);
-
-        ArgumentCaptor<View> captor = ArgumentCaptor.forClass(View.class);
-        verify(mView, atLeastOnce()).addView(captor.capture(), anyInt());
-        final View userSwitcherStub = CollectionUtils.find(captor.getAllValues(),
-                view -> view.getId() == R.id.keyguard_user_switcher_stub);
-        assertThat(userSwitcherStub).isNotNull();
-        assertThat(userSwitcherStub).isInstanceOf(ViewStub.class);
-    }
-
-    @Test
-    public void testChangeSmallestScreenWidthAndUserSwitchEnabled_inflatesUserSwitchView() {
-        givenViewAttached();
-        when(mView.findViewById(R.id.keyguard_user_switcher_view)).thenReturn(null);
-        updateSmallestScreenWidth(300);
-        when(mResources.getBoolean(
-                com.android.internal.R.bool.config_keyguardUserSwitcher)).thenReturn(true);
-        when(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user)).thenReturn(false);
-        when(mUserManager.isUserSwitcherEnabled(false)).thenReturn(true);
-
-        updateSmallestScreenWidth(800);
-
-        verify(mUserSwitcherStubView).inflate();
-    }
-
-    @Test
-    public void testFinishInflate_userSwitcherDisabled_doNotInflateUserSwitchView_initClock() {
-        givenViewAttached();
-        when(mResources.getBoolean(
-                com.android.internal.R.bool.config_keyguardUserSwitcher)).thenReturn(true);
-        when(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user)).thenReturn(false);
-        when(mUserManager.isUserSwitcherEnabled(false /* showEvenIfNotActionable */))
-                .thenReturn(false);
-
-        mNotificationPanelViewController.onFinishInflate();
-
-        verify(mUserSwitcherStubView, never()).inflate();
-        verify(mKeyguardStatusViewController, times(3)).displayClock(LARGE, /* animate */ true);
-    }
-
-    @Test
-    public void testReInflateViews_userSwitcherDisabled_doNotInflateUserSwitchView() {
-        givenViewAttached();
-        when(mResources.getBoolean(
-                com.android.internal.R.bool.config_keyguardUserSwitcher)).thenReturn(true);
-        when(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user)).thenReturn(false);
-        when(mUserManager.isUserSwitcherEnabled(false /* showEvenIfNotActionable */))
-                .thenReturn(false);
-
-        mNotificationPanelViewController.reInflateViews();
-
-        verify(mUserSwitcherStubView, never()).inflate();
-    }
-
-    @Test
     public void testCanCollapsePanelOnTouch_trueForKeyGuard() {
         mStatusBarStateController.setState(KEYGUARD);
 
@@ -1129,26 +509,6 @@
     }
 
     @Test
-    public void testDoubleTapRequired_Keyguard() {
-        FalsingManager.FalsingTapListener listener = getFalsingTapListener();
-        mStatusBarStateController.setState(KEYGUARD);
-
-        listener.onAdditionalTapRequired();
-
-        verify(mKeyguardIndicationController).showTransientIndication(anyInt());
-    }
-
-    @Test
-    public void testDoubleTapRequired_ShadeLocked() {
-        FalsingManager.FalsingTapListener listener = getFalsingTapListener();
-        mStatusBarStateController.setState(SHADE_LOCKED);
-
-        listener.onAdditionalTapRequired();
-
-        verify(mTapAgainViewController).show();
-    }
-
-    @Test
     public void testRotatingToSplitShadeWithQsExpanded_transitionsToShadeLocked() {
         mStatusBarStateController.setState(KEYGUARD);
         when(mQsController.getExpanded()).thenReturn(true);
@@ -1423,19 +783,6 @@
     }
 
     @Test
-    public void testOnAttachRefreshStatusBarState() {
-        mStatusBarStateController.setState(KEYGUARD);
-        when(mKeyguardStateController.isKeyguardFadingAway()).thenReturn(false);
-        for (View.OnAttachStateChangeListener listener : mOnAttachStateChangeListeners) {
-            listener.onViewAttachedToWindow(mView);
-        }
-        verify(mKeyguardStatusViewController).setKeyguardStatusViewVisibility(
-                KEYGUARD/*statusBarState*/,
-                false/*keyguardFadingAway*/,
-                false/*goingToFullShade*/, SHADE/*oldStatusBarState*/);
-    }
-
-    @Test
     public void getMaxPanelTransitionDistance_expanding_inSplitShade_returnsSplitShadeFullTransitionDistance() {
         enableSplitShade(true);
         mNotificationPanelViewController.expandWithQs();
@@ -1635,98 +982,4 @@
         mStatusBarStateController.setState(SHADE_LOCKED);
         assertThat(mNotificationPanelViewController.isShadeFullyOpen()).isTrue();
     }
-
-    private static MotionEvent createMotionEvent(int x, int y, int action) {
-        return MotionEvent.obtain(
-                /* downTime= */ 0, /* eventTime= */ 0, action, x, y, /* metaState= */ 0);
-    }
-
-    private void triggerPositionClockAndNotifications() {
-        mNotificationPanelViewController.onQsSetExpansionHeightCalled(false);
-    }
-
-    private FalsingManager.FalsingTapListener getFalsingTapListener() {
-        for (View.OnAttachStateChangeListener listener : mOnAttachStateChangeListeners) {
-            listener.onViewAttachedToWindow(mView);
-        }
-        assertThat(mFalsingManager.getTapListeners().size()).isEqualTo(1);
-        return mFalsingManager.getTapListeners().get(0);
-    }
-
-    private void givenViewAttached() {
-        for (View.OnAttachStateChangeListener listener : mOnAttachStateChangeListeners) {
-            listener.onViewAttachedToWindow(mView);
-        }
-    }
-
-    private ConstraintSet.Layout getConstraintSetLayout(@IdRes int id) {
-        ConstraintSet constraintSet = new ConstraintSet();
-        constraintSet.clone(mNotificationContainerParent);
-        return constraintSet.getConstraint(id).layout;
-    }
-
-    private void enableSplitShade(boolean enabled) {
-        when(mResources.getBoolean(R.bool.config_use_split_notification_shade)).thenReturn(enabled);
-        mNotificationPanelViewController.updateResources();
-    }
-
-    private void updateMultiUserSetting(boolean enabled) {
-        when(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user)).thenReturn(false);
-        when(mUserManager.isUserSwitcherEnabled(false)).thenReturn(enabled);
-        final ArgumentCaptor<ContentObserver> observerCaptor =
-                ArgumentCaptor.forClass(ContentObserver.class);
-        verify(mContentResolver)
-                .registerContentObserver(any(), anyBoolean(), observerCaptor.capture());
-        observerCaptor.getValue().onChange(/* selfChange */ false);
-    }
-
-    private void updateSmallestScreenWidth(int smallestScreenWidthDp) {
-        Configuration configuration = new Configuration();
-        configuration.smallestScreenWidthDp = smallestScreenWidthDp;
-        mConfigurationController.onConfigurationChanged(configuration);
-    }
-
-    private void onTouchEvent(MotionEvent ev) {
-        mTouchHandler.onTouch(mView, ev);
-    }
-
-    private void setDozing(boolean dozing, boolean dozingAlwaysOn) {
-        when(mDozeParameters.getAlwaysOn()).thenReturn(dozingAlwaysOn);
-        mNotificationPanelViewController.setDozing(
-                /* dozing= */ dozing,
-                /* animate= */ false
-        );
-    }
-
-    private void assertKeyguardStatusViewCentered() {
-        mNotificationPanelViewController.updateResources();
-        assertThat(getConstraintSetLayout(R.id.keyguard_status_view).endToEnd).isAnyOf(
-                ConstraintSet.PARENT_ID, ConstraintSet.UNSET);
-    }
-
-    private void assertKeyguardStatusViewNotCentered() {
-        mNotificationPanelViewController.updateResources();
-        assertThat(getConstraintSetLayout(R.id.keyguard_status_view).endToEnd).isEqualTo(
-                R.id.qs_edge_guideline);
-    }
-
-    private void setIsFullWidth(boolean fullWidth) {
-        float nsslWidth = fullWidth ? PANEL_WIDTH : PANEL_WIDTH / 2f;
-        when(mNotificationStackScrollLayoutController.getWidth()).thenReturn(nsslWidth);
-        triggerLayoutChange();
-    }
-
-    private void triggerLayoutChange() {
-        mLayoutChangeListener.onLayoutChange(
-                mView,
-                /* left= */ 0,
-                /* top= */ 0,
-                /* right= */ 0,
-                /* bottom= */ 0,
-                /* oldLeft= */ 0,
-                /* oldTop= */ 0,
-                /* oldRight= */ 0,
-                /* oldBottom= */ 0
-        );
-    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerWithCoroutinesTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerWithCoroutinesTest.kt
new file mode 100644
index 0000000..0c046e9
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerWithCoroutinesTest.kt
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2023 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.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import android.view.View
+import android.view.ViewStub
+import androidx.test.filters.SmallTest
+import com.android.internal.util.CollectionUtils
+import com.android.keyguard.KeyguardClockSwitch.LARGE
+import com.android.systemui.R
+import com.android.systemui.statusbar.StatusBarState.KEYGUARD
+import com.android.systemui.statusbar.StatusBarState.SHADE
+import com.android.systemui.statusbar.StatusBarState.SHADE_LOCKED
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.cancelChildren
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.test.advanceUntilIdle
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.Captor
+import org.mockito.Mockito.atLeastOnce
+import org.mockito.Mockito.clearInvocations
+import org.mockito.Mockito.never
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+@SmallTest
+class NotificationPanelViewControllerWithCoroutinesTest :
+    NotificationPanelViewControllerBaseTest() {
+
+    @Captor private lateinit var viewCaptor: ArgumentCaptor<View>
+
+    override fun getMainDispatcher() = Dispatchers.Main.immediate
+
+    @Test
+    fun testDisableUserSwitcherAfterEnabling_returnsViewStubToTheViewHierarchy() = runTest {
+        launch(Dispatchers.Main.immediate) { givenViewAttached() }
+        advanceUntilIdle()
+
+        whenever(mResources.getBoolean(com.android.internal.R.bool.config_keyguardUserSwitcher))
+            .thenReturn(true)
+        updateMultiUserSetting(true)
+        clearInvocations(mView)
+
+        updateMultiUserSetting(false)
+
+        verify(mView, atLeastOnce()).addView(viewCaptor.capture(), anyInt())
+        val userSwitcherStub =
+            CollectionUtils.find(
+                viewCaptor.getAllValues(),
+                { view -> view.getId() == R.id.keyguard_user_switcher_stub }
+            )
+        assertThat(userSwitcherStub).isNotNull()
+        assertThat(userSwitcherStub).isInstanceOf(ViewStub::class.java)
+    }
+
+    @Test
+    fun testChangeSmallestScreenWidthAndUserSwitchEnabled_inflatesUserSwitchView() = runTest {
+        launch(Dispatchers.Main.immediate) { givenViewAttached() }
+        advanceUntilIdle()
+
+        whenever(mView.findViewById<View>(R.id.keyguard_user_switcher_view)).thenReturn(null)
+        updateSmallestScreenWidth(300)
+        whenever(mResources.getBoolean(com.android.internal.R.bool.config_keyguardUserSwitcher))
+            .thenReturn(true)
+        whenever(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user))
+            .thenReturn(false)
+        whenever(mUserManager.isUserSwitcherEnabled(false)).thenReturn(true)
+
+        updateSmallestScreenWidth(800)
+
+        verify(mUserSwitcherStubView).inflate()
+    }
+
+    @Test
+    fun testFinishInflate_userSwitcherDisabled_doNotInflateUserSwitchView_initClock() = runTest {
+        launch(Dispatchers.Main.immediate) { givenViewAttached() }
+        advanceUntilIdle()
+
+        whenever(mResources.getBoolean(com.android.internal.R.bool.config_keyguardUserSwitcher))
+            .thenReturn(true)
+        whenever(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user))
+            .thenReturn(false)
+        whenever(mUserManager.isUserSwitcherEnabled(false /* showEvenIfNotActionable */))
+            .thenReturn(false)
+
+        mNotificationPanelViewController.onFinishInflate()
+
+        verify(mUserSwitcherStubView, never()).inflate()
+        verify(mKeyguardStatusViewController, times(3)).displayClock(LARGE, /* animate */ true)
+
+        coroutineContext.cancelChildren()
+    }
+
+    @Test
+    fun testReInflateViews_userSwitcherDisabled_doNotInflateUserSwitchView() = runTest {
+        launch(Dispatchers.Main.immediate) { givenViewAttached() }
+        advanceUntilIdle()
+
+        whenever(mResources.getBoolean(com.android.internal.R.bool.config_keyguardUserSwitcher))
+            .thenReturn(true)
+        whenever(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user))
+            .thenReturn(false)
+        whenever(mUserManager.isUserSwitcherEnabled(false /* showEvenIfNotActionable */))
+            .thenReturn(false)
+
+        mNotificationPanelViewController.reInflateViews()
+
+        verify(mUserSwitcherStubView, never()).inflate()
+
+        coroutineContext.cancelChildren()
+    }
+
+    @Test
+    fun testDoubleTapRequired_Keyguard() = runTest {
+        launch(Dispatchers.Main.immediate) {
+            val listener = getFalsingTapListener()
+            mStatusBarStateController.setState(KEYGUARD)
+
+            listener.onAdditionalTapRequired()
+
+            verify(mKeyguardIndicationController).showTransientIndication(anyInt())
+        }
+        advanceUntilIdle()
+    }
+
+    @Test
+    fun testDoubleTapRequired_ShadeLocked() = runTest {
+        launch(Dispatchers.Main.immediate) {
+            val listener = getFalsingTapListener()
+            mStatusBarStateController.setState(SHADE_LOCKED)
+
+            listener.onAdditionalTapRequired()
+
+            verify(mTapAgainViewController).show()
+        }
+        advanceUntilIdle()
+    }
+
+    @Test
+    fun testOnAttachRefreshStatusBarState() = runTest {
+        launch(Dispatchers.Main.immediate) {
+            mStatusBarStateController.setState(KEYGUARD)
+            whenever(mKeyguardStateController.isKeyguardFadingAway()).thenReturn(false)
+            mOnAttachStateChangeListeners.forEach { it.onViewAttachedToWindow(mView) }
+            verify(mKeyguardStatusViewController)
+                .setKeyguardStatusViewVisibility(
+                    KEYGUARD /*statusBarState*/,
+                    false /*keyguardFadingAway*/,
+                    false /*goingToFullShade*/,
+                    SHADE /*oldStatusBarState*/
+                )
+        }
+        advanceUntilIdle()
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
index d229a08..0a401b0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
@@ -28,10 +28,10 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.classifier.FalsingCollectorFake
 import com.android.systemui.dock.DockManager
-import com.android.systemui.flags.FeatureFlags
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController
 import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.shared.model.TransitionStep
 import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel
 import com.android.systemui.shade.NotificationShadeWindowView.InteractionEventHandler
 import com.android.systemui.statusbar.LockscreenShadeTransitionController
@@ -47,6 +47,7 @@
 import com.android.systemui.statusbar.window.StatusBarWindowStateController
 import com.android.systemui.util.mockito.any
 import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.flow.emptyFlow
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -81,8 +82,6 @@
     @Mock
     private lateinit var keyguardUnlockAnimationController: KeyguardUnlockAnimationController
     @Mock
-    private lateinit var featureFlags: FeatureFlags
-    @Mock
     private lateinit var ambientState: AmbientState
     @Mock
     private lateinit var keyguardBouncerViewModel: KeyguardBouncerViewModel
@@ -124,6 +123,8 @@
                 .thenReturn(keyguardBouncerComponent)
         whenever(keyguardBouncerComponent.securityContainerController)
                 .thenReturn(keyguardSecurityContainerController)
+        whenever(keyguardTransitionInteractor.lockscreenToDreamingTransition)
+                .thenReturn(emptyFlow<TransitionStep>())
         underTest = NotificationShadeWindowViewController(
             lockscreenShadeTransitionController,
             FalsingCollectorFake(),
@@ -143,7 +144,6 @@
             notificationInsetsController,
             ambientState,
             pulsingGestureListener,
-            featureFlags,
             keyguardBouncerViewModel,
             keyguardBouncerComponentFactory,
             alternateBouncerInteractor,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java
index 5e9c219..5d71979 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java
@@ -25,6 +25,8 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import static kotlinx.coroutines.flow.FlowKt.emptyFlow;
+
 import android.os.SystemClock;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
@@ -40,7 +42,6 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.classifier.FalsingCollectorFake;
 import com.android.systemui.dock.DockManager;
-import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
 import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
@@ -93,7 +94,6 @@
     @Mock private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
     @Mock private AmbientState mAmbientState;
     @Mock private PulsingGestureListener mPulsingGestureListener;
-    @Mock private FeatureFlags mFeatureFlags;
     @Mock private KeyguardBouncerViewModel mKeyguardBouncerViewModel;
     @Mock private KeyguardBouncerComponent.Factory mKeyguardBouncerComponentFactory;
     @Mock private KeyguardBouncerComponent mKeyguardBouncerComponent;
@@ -125,6 +125,9 @@
 
         when(mDockManager.isDocked()).thenReturn(false);
 
+        when(mKeyguardTransitionInteractor.getLockscreenToDreamingTransition())
+                .thenReturn(emptyFlow());
+
         mController = new NotificationShadeWindowViewController(
                 mLockscreenShadeTransitionController,
                 new FalsingCollectorFake(),
@@ -144,7 +147,6 @@
                 mNotificationInsetsController,
                 mAmbientState,
                 mPulsingGestureListener,
-                mFeatureFlags,
                 mKeyguardBouncerViewModel,
                 mKeyguardBouncerComponentFactory,
                 mAlternateBouncerInteractor,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/fsi/FsiChromeRepoTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/fsi/FsiChromeRepoTest.kt
deleted file mode 100644
index a6a9e51..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/fsi/FsiChromeRepoTest.kt
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * 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.statusbar.notification.fsi
-
-import android.R
-import android.app.Notification
-import android.app.NotificationManager
-import android.app.PendingIntent
-import android.content.pm.ApplicationInfo
-import android.content.pm.PackageManager
-import android.graphics.drawable.Drawable
-import android.os.UserHandle
-import android.service.dreams.IDreamManager
-import android.service.notification.StatusBarNotification
-import android.testing.AndroidTestingRunner
-import android.testing.TestableLooper.RunWithLooper
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.flags.FakeFeatureFlags
-import com.android.systemui.flags.Flags
-import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
-import com.android.systemui.statusbar.notification.collection.NotificationEntry
-import com.android.systemui.statusbar.notification.collection.provider.LaunchFullScreenIntentProvider
-import com.android.systemui.statusbar.phone.CentralSurfaces
-import java.util.concurrent.Executor
-import junit.framework.Assert.assertEquals
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.ArgumentMatchers.any
-import org.mockito.ArgumentMatchers.anyString
-import org.mockito.Mock
-import org.mockito.Mockito
-import org.mockito.Mockito.never
-import org.mockito.Mockito.times
-import org.mockito.Mockito.`when` as whenever
-import org.mockito.MockitoAnnotations
-
-@SmallTest
-@RunWith(AndroidTestingRunner::class)
-@RunWithLooper(setAsMainLooper = true)
-class FsiChromeRepoTest : SysuiTestCase() {
-
-    @Mock lateinit var centralSurfaces: CentralSurfaces
-    @Mock lateinit var fsiChromeRepo: FsiChromeRepo
-    @Mock lateinit var packageManager: PackageManager
-
-    var keyguardRepo = FakeKeyguardRepository()
-    @Mock private lateinit var applicationInfo: ApplicationInfo
-
-    @Mock lateinit var launchFullScreenIntentProvider: LaunchFullScreenIntentProvider
-    var featureFlags = FakeFeatureFlags()
-    @Mock lateinit var dreamManager: IDreamManager
-
-    // Execute all foreground & background requests immediately
-    private val uiBgExecutor = Executor { r -> r.run() }
-
-    private val appName: String = "appName"
-    private val appIcon: Drawable = context.getDrawable(com.android.systemui.R.drawable.ic_android)
-    private val fsi: PendingIntent = Mockito.mock(PendingIntent::class.java)
-
-    @Before
-    fun setUp() {
-        MockitoAnnotations.initMocks(this)
-
-        // Set up package manager mocks
-        whenever(packageManager.getApplicationIcon(anyString())).thenReturn(appIcon)
-        whenever(packageManager.getApplicationIcon(any(ApplicationInfo::class.java)))
-            .thenReturn(appIcon)
-        whenever(packageManager.getApplicationLabel(any())).thenReturn(appName)
-        mContext.setMockPackageManager(packageManager)
-
-        fsiChromeRepo =
-            FsiChromeRepo(
-                mContext,
-                packageManager,
-                keyguardRepo,
-                launchFullScreenIntentProvider,
-                featureFlags,
-                uiBgExecutor,
-                dreamManager,
-                centralSurfaces
-            )
-    }
-
-    private fun createFsiEntry(fsi: PendingIntent): NotificationEntry {
-        val nb =
-            Notification.Builder(mContext, "a")
-                .setContentTitle("foo")
-                .setSmallIcon(R.drawable.sym_def_app_icon)
-                .setFullScreenIntent(fsi, /* highPriority= */ true)
-
-        val sbn =
-            StatusBarNotification(
-                "pkg",
-                "opPkg",
-                /* id= */ 0,
-                "tag" + System.currentTimeMillis(),
-                /* uid= */ 0,
-                /* initialPid */ 0,
-                nb.build(),
-                UserHandle(0),
-                /* overrideGroupKey= */ null,
-                /* postTime= */ 0
-            )
-
-        val entry = Mockito.mock(NotificationEntry::class.java)
-        whenever(entry.importance).thenReturn(NotificationManager.IMPORTANCE_HIGH)
-        whenever(entry.sbn).thenReturn(sbn)
-        return entry
-    }
-
-    @Test
-    fun testLaunchFullscreenIntent_flagNotEnabled_noLaunch() {
-        // Setup
-        featureFlags.set(Flags.FSI_CHROME, false)
-
-        // Test
-        val entry = createFsiEntry(fsi)
-        fsiChromeRepo.launchFullscreenIntent(entry)
-
-        // Verify
-        Mockito.verify(centralSurfaces, never()).wakeUpForFullScreenIntent()
-    }
-
-    @Test
-    fun testLaunchFullscreenIntent_notOnKeyguard_noLaunch() {
-        // Setup
-        featureFlags.set(Flags.FSI_CHROME, true)
-        keyguardRepo.setKeyguardShowing(false)
-
-        // Test
-        val entry = createFsiEntry(fsi)
-        fsiChromeRepo.launchFullscreenIntent(entry)
-
-        // Verify
-        Mockito.verify(centralSurfaces, never()).wakeUpForFullScreenIntent()
-    }
-
-    @Test
-    fun testLaunchFullscreenIntent_stopsScreensaver() {
-        // Setup
-        featureFlags.set(Flags.FSI_CHROME, true)
-        keyguardRepo.setKeyguardShowing(true)
-
-        // Test
-        val entry = createFsiEntry(fsi)
-        fsiChromeRepo.launchFullscreenIntent(entry)
-
-        // Verify
-        Mockito.verify(dreamManager, times(1)).awaken()
-    }
-
-    @Test
-    fun testLaunchFullscreenIntent_updatesFsiInfoFlow() {
-        // Setup
-        featureFlags.set(Flags.FSI_CHROME, true)
-        keyguardRepo.setKeyguardShowing(true)
-
-        // Test
-        val entry = createFsiEntry(fsi)
-        fsiChromeRepo.launchFullscreenIntent(entry)
-
-        // Verify
-        val expectedFsiInfo = FsiChromeRepo.FSIInfo(appName, appIcon, fsi)
-        assertEquals(expectedFsiInfo, fsiChromeRepo.infoFlow.value)
-    }
-
-    @Test
-    fun testLaunchFullscreenIntent_notifyFsiLaunched() {
-        // Setup
-        featureFlags.set(Flags.FSI_CHROME, true)
-        keyguardRepo.setKeyguardShowing(true)
-
-        // Test
-        val entry = createFsiEntry(fsi)
-        fsiChromeRepo.launchFullscreenIntent(entry)
-
-        // Verify
-        Mockito.verify(entry, times(1)).notifyFullScreenIntentLaunched()
-    }
-
-    @Test
-    fun testLaunchFullscreenIntent_wakesUpDevice() {
-        // Setup
-        featureFlags.set(Flags.FSI_CHROME, true)
-        keyguardRepo.setKeyguardShowing(true)
-
-        // Test
-        val entry = createFsiEntry(fsi)
-        fsiChromeRepo.launchFullscreenIntent(entry)
-
-        // Verify
-        Mockito.verify(centralSurfaces, times(1)).wakeUpForFullScreenIntent()
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/fsi/FsiChromeViewModelFactoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/fsi/FsiChromeViewModelFactoryTest.kt
deleted file mode 100644
index 5cee9e3..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/fsi/FsiChromeViewModelFactoryTest.kt
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * 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.statusbar.notification.fsi
-
-import android.app.PendingIntent
-import android.graphics.drawable.Drawable
-import android.testing.AndroidTestingRunner
-import android.testing.TestableLooper.RunWithLooper
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.util.concurrency.FakeExecutor
-import com.android.systemui.util.mockito.any
-import com.android.systemui.util.mockito.mock
-import com.android.systemui.util.mockito.whenever
-import com.android.systemui.util.mockito.withArgCaptor
-import com.android.systemui.util.time.FakeSystemClock
-import com.android.wm.shell.TaskView
-import com.android.wm.shell.TaskViewFactory
-import com.google.common.truth.Truth.assertThat
-import java.util.Optional
-import java.util.function.Consumer
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.SharingStarted
-import kotlinx.coroutines.flow.onStart
-import kotlinx.coroutines.flow.stateIn
-import kotlinx.coroutines.test.runCurrent
-import kotlinx.coroutines.test.runTest
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.Mockito
-import org.mockito.Mockito.verify
-import org.mockito.MockitoAnnotations
-
-@SmallTest
-@RunWith(AndroidTestingRunner::class)
-@RunWithLooper(setAsMainLooper = true)
-class FsiChromeViewModelFactoryTest : SysuiTestCase() {
-    @Mock private lateinit var taskViewFactoryOptional: Optional<TaskViewFactory>
-    @Mock private lateinit var taskViewFactory: TaskViewFactory
-    @Mock lateinit var taskView: TaskView
-
-    @Main var mainExecutor = FakeExecutor(FakeSystemClock())
-    lateinit var viewModelFactory: FsiChromeViewModelFactory
-
-    private val fakeInfoFlow = MutableStateFlow<FsiChromeRepo.FSIInfo?>(null)
-    private var fsiChromeRepo: FsiChromeRepo =
-        mock<FsiChromeRepo>().apply { whenever(infoFlow).thenReturn(fakeInfoFlow) }
-
-    private val appName = "appName"
-    private val appIcon: Drawable = context.getDrawable(com.android.systemui.R.drawable.ic_android)
-    private val fsi: PendingIntent = Mockito.mock(PendingIntent::class.java)
-    private val fsiInfo = FsiChromeRepo.FSIInfo(appName, appIcon, fsi)
-
-    @Before
-    fun setUp() {
-        MockitoAnnotations.initMocks(this)
-
-        whenever(taskViewFactoryOptional.get()).thenReturn(taskViewFactory)
-
-        viewModelFactory =
-            FsiChromeViewModelFactory(fsiChromeRepo, taskViewFactoryOptional, context, mainExecutor)
-    }
-
-    @Test
-    fun testViewModelFlow_update_createsTaskView() {
-        runTest {
-            val latestViewModel =
-                viewModelFactory.viewModelFlow
-                    .onStart { FsiDebug.log("viewModelFactory.viewModelFlow.onStart") }
-                    .stateIn(
-                        backgroundScope, // stateIn runs forever, don't count it as test coroutine
-                        SharingStarted.Eagerly,
-                        null
-                    )
-            runCurrent() // Drain queued backgroundScope operations
-
-            // Test: emit the fake FSIInfo
-            fakeInfoFlow.emit(fsiInfo)
-            runCurrent()
-
-            val taskViewFactoryCallback: Consumer<TaskView> = withArgCaptor {
-                verify(taskViewFactory).create(any(), any(), capture())
-            }
-            taskViewFactoryCallback.accept(taskView) // this will call k.resume
-            runCurrent()
-
-            // Verify that the factory has produced a new ViewModel
-            // containing the relevant data from FsiInfo
-            val expectedViewModel =
-                FsiChromeViewModel(appName, appIcon, taskView, fsi, fsiChromeRepo)
-
-            assertThat(latestViewModel.value).isEqualTo(expectedViewModel)
-        }
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index c0537a6..dc5a047 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -1356,33 +1356,10 @@
     }
 
     @Test
-    public void notificationAlpha_unnocclusionAnimating_bouncerActive_usesKeyguardNotifAlpha() {
-        when(mStatusBarKeyguardViewManager.isPrimaryBouncerInTransit()).thenReturn(true);
-        mScrimController.setClipsQsScrim(true);
-
-        mScrimController.transitionTo(ScrimState.KEYGUARD);
-        mScrimController.setUnocclusionAnimationRunning(true);
-
-        assertAlphaAfterExpansion(
-                mNotificationsScrim, ScrimState.KEYGUARD.getNotifAlpha(), /* expansion */ 0f);
-        assertAlphaAfterExpansion(
-                mNotificationsScrim, ScrimState.KEYGUARD.getNotifAlpha(), /* expansion */ 0.4f);
-        assertAlphaAfterExpansion(
-                mNotificationsScrim, ScrimState.KEYGUARD.getNotifAlpha(), /* expansion */ 1.0f);
-
-        // Verify normal behavior after
-        mScrimController.setUnocclusionAnimationRunning(false);
-        float expansion = 0.4f;
-        float alpha = 1 - BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(expansion);
-        assertAlphaAfterExpansion(mNotificationsScrim, alpha, expansion);
-    }
-
-    @Test
     public void notificationAlpha_unnocclusionAnimating_bouncerNotActive_usesKeyguardNotifAlpha() {
         when(mStatusBarKeyguardViewManager.isPrimaryBouncerInTransit()).thenReturn(false);
 
         mScrimController.transitionTo(ScrimState.KEYGUARD);
-        mScrimController.setUnocclusionAnimationRunning(true);
 
         assertAlphaAfterExpansion(
                 mNotificationsScrim, ScrimState.KEYGUARD.getNotifAlpha(), /* expansion */ 0f);
@@ -1392,7 +1369,6 @@
                 mNotificationsScrim, ScrimState.KEYGUARD.getNotifAlpha(), /* expansion */ 1.0f);
 
         // Verify normal behavior after
-        mScrimController.setUnocclusionAnimationRunning(false);
         float expansion = 0.4f;
         float alpha = 1 - ShadeInterpolation.getNotificationScrimAlpha(expansion);
         assertAlphaAfterExpansion(mNotificationsScrim, alpha, expansion);
@@ -1598,7 +1574,6 @@
 
     @Test
     public void setUnOccludingAnimationKeyguard() {
-        mScrimController.setUnocclusionAnimationRunning(true);
         mScrimController.transitionTo(ScrimState.KEYGUARD);
         finishAnimationsImmediately();
         assertThat(mNotificationsScrim.getViewAlpha())
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index 1aad83e..158e9ad 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -368,17 +368,6 @@
     }
 
     @Test
-    public void setOccluded_animatesPanelExpansion_onlyIfBouncerHidden() {
-        mStatusBarKeyguardViewManager.setOccluded(false /* occluded */, true /* animated */);
-        verify(mCentralSurfaces).animateKeyguardUnoccluding();
-
-        when(mPrimaryBouncerInteractor.isFullyShowing()).thenReturn(true);
-        clearInvocations(mCentralSurfaces);
-        mStatusBarKeyguardViewManager.setOccluded(false /* occluded */, true /* animated */);
-        verify(mCentralSurfaces, never()).animateKeyguardUnoccluding();
-    }
-
-    @Test
     public void setOccluded_onKeyguardOccludedChangedCalled() {
         clearInvocations(mKeyguardStateController);
         clearInvocations(mKeyguardUpdateMonitor);
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 1f8a779..25381be 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -3928,6 +3928,8 @@
                         mGlobalClients.getRegisteredCallbackCookie(i);
                 pw.append(Arrays.toString(client.mPackageNames));
             }
+            pw.println();
+            mProxyManager.dump(fd, pw, args);
         }
     }
 
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
index 094053e..0e25a06 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
@@ -910,6 +910,10 @@
             pw.println("     Top Focused Window Id = " + mTopFocusedWindowId);
             pw.println("     Accessibility Focused Window Id = " + mAccessibilityFocusedWindowId
                     + " ]");
+            if (mIsProxy) {
+                pw.println("Proxy accessibility focused window = "
+                        + mProxyDisplayAccessibilityFocusedWindow);
+            }
             pw.println();
             if (mWindows != null) {
                 final int windowCount = mWindows.size();
diff --git a/services/accessibility/java/com/android/server/accessibility/ProxyAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/ProxyAccessibilityServiceConnection.java
index 945d43b..b19a502 100644
--- a/services/accessibility/java/com/android/server/accessibility/ProxyAccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/ProxyAccessibilityServiceConnection.java
@@ -38,14 +38,18 @@
 import android.os.RemoteException;
 import android.view.KeyEvent;
 import android.view.accessibility.AccessibilityDisplayProxy;
+import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.accessibility.AccessibilityWindowInfo;
 
 import androidx.annotation.Nullable;
 
 import com.android.internal.R;
+import com.android.internal.util.DumpUtils;
 import com.android.server.wm.WindowManagerInternal;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashSet;
@@ -61,6 +65,8 @@
  * TODO(241429275): Initialize this when a proxy is registered.
  */
 public class ProxyAccessibilityServiceConnection extends AccessibilityServiceConnection {
+    private static final String LOG_TAG = "ProxyAccessibilityServiceConnection";
+
     private int mDisplayId;
     private List<AccessibilityServiceInfo> mInstalledAndEnabledServices;
 
@@ -565,4 +571,25 @@
     public void setAnimationScale(float scale) throws UnsupportedOperationException {
         throw new UnsupportedOperationException("setAnimationScale is not supported");
     }
+
+    @Override
+    public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
+        if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return;
+        synchronized (mLock) {
+            pw.append("Proxy[displayId=" + mDisplayId);
+            pw.append(", feedbackType"
+                    + AccessibilityServiceInfo.feedbackTypeToString(mFeedbackType));
+            pw.append(", capabilities=" + mAccessibilityServiceInfo.getCapabilities());
+            pw.append(", eventTypes="
+                    + AccessibilityEvent.eventTypeToString(mEventTypes));
+            pw.append(", notificationTimeout=" + mNotificationTimeout);
+            pw.append(", focusStrokeWidth=").append(String.valueOf(mFocusStrokeWidth));
+            pw.append(", focusColor=").append(String.valueOf(mFocusColor));
+            pw.append(", installedAndEnabledServiceCount=").append(String.valueOf(
+                    mInstalledAndEnabledServices.size()));
+            pw.append(", installedAndEnabledServices=").append(
+                    mInstalledAndEnabledServices.toString());
+            pw.append("]");
+        }
+    }
 }
diff --git a/services/accessibility/java/com/android/server/accessibility/ProxyManager.java b/services/accessibility/java/com/android/server/accessibility/ProxyManager.java
index 9d91d10..e258de1 100644
--- a/services/accessibility/java/com/android/server/accessibility/ProxyManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/ProxyManager.java
@@ -23,6 +23,7 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.RemoteException;
+import android.util.Slog;
 import android.util.SparseArray;
 import android.view.Display;
 import android.view.accessibility.AccessibilityEvent;
@@ -30,6 +31,8 @@
 
 import com.android.server.wm.WindowManagerInternal;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
 import java.util.List;
 
 /**
@@ -42,6 +45,9 @@
  * TODO(262244375): Add unit tests.
  */
 public class ProxyManager {
+    private static final boolean DEBUG = false;
+    private static final String LOG_TAG = "ProxyManager";
+
     // Names used to populate ComponentName and ResolveInfo in connection.mA11yServiceInfo and in
     // the infos of connection.setInstalledAndEnabledServices
     static final String PROXY_COMPONENT_PACKAGE_NAME = "ProxyPackage";
@@ -79,6 +85,9 @@
             AbstractAccessibilityServiceConnection.SystemSupport systemSupport,
             AccessibilityTrace trace,
             WindowManagerInternal windowManagerInternal) throws RemoteException {
+        if (DEBUG) {
+            Slog.v(LOG_TAG, "Register proxy for display id: " + displayId);
+        }
 
         // Set a default AccessibilityServiceInfo that is used before the proxy's info is
         // populated. A proxy has the touch exploration and window capabilities.
@@ -134,6 +143,9 @@
             if (mProxyA11yServiceConnections.contains(displayId)) {
                 mProxyA11yServiceConnections.remove(displayId);
                 removed = true;
+                if (DEBUG) {
+                    Slog.v(LOG_TAG, "Unregister proxy for display id " + displayId);
+                }
             }
         }
         if (removed) {
@@ -155,19 +167,25 @@
      */
     public boolean isProxyed(int displayId) {
         synchronized (mLock) {
-            return mProxyA11yServiceConnections.contains(displayId);
+            final boolean tracked = mProxyA11yServiceConnections.contains(displayId);
+            if (DEBUG) {
+                Slog.v(LOG_TAG, "Tracking proxy display " + displayId + " : " + tracked);
+            }
+            return tracked;
         }
     }
 
     /**
-     * Sends AccessibilityEvents to all proxies.
-     * {@link android.view.accessibility.AccessibilityDisplayProxy} will filter based on display.
-     * TODO(b/250929565): Filtering should happen in the system, not in the proxy.
+     * Sends AccessibilityEvents to a proxy given the event's displayId.
      */
     public void sendAccessibilityEventLocked(AccessibilityEvent event) {
         final ProxyAccessibilityServiceConnection proxy =
                 mProxyA11yServiceConnections.get(event.getDisplayId());
         if (proxy != null) {
+            if (DEBUG) {
+                Slog.v(LOG_TAG, "Send proxy event " + event + " for display id "
+                        + event.getDisplayId());
+            }
             proxy.notifyAccessibilityEvent(event);
         }
     }
@@ -186,6 +204,9 @@
                 break;
             }
         }
+        if (DEBUG) {
+            Slog.v(LOG_TAG, "At least one proxy can retrieve windows: " + observingWindows);
+        }
         return observingWindows;
     }
 
@@ -205,6 +226,14 @@
                 clientState |= AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED;
             }
         }
+
+        if (DEBUG) {
+            Slog.v(LOG_TAG, "Accessibility is enabled for all proxies: "
+                    + ((clientState & AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED) != 0));
+            Slog.v(LOG_TAG, "Touch exploration is enabled for all proxies: "
+                    + ((clientState & AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED)
+                            != 0));
+        }
         return clientState;
         // TODO(b/254545943): When A11yManager is separated, include support for other properties.
     }
@@ -234,6 +263,10 @@
                     mProxyA11yServiceConnections.valueAt(i);
             relevantEventTypes |= proxy.getRelevantEventTypes();
         }
+        if (DEBUG) {
+            Slog.v(LOG_TAG, "Relevant event types for all proxies: "
+                    + AccessibilityEvent.eventTypeToString(relevantEventTypes));
+        }
         return relevantEventTypes;
     }
 
@@ -275,4 +308,25 @@
     void setAccessibilityInputFilter(AccessibilityInputFilter filter) {
         mA11yInputFilter = filter;
     }
+
+
+    /**
+     * Prints information belonging to each display that is controlled by an
+     * AccessibilityDisplayProxy.
+     */
+    void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        synchronized (mLock) {
+            pw.println();
+            pw.println("Proxy manager state:");
+            pw.println("    Number of proxy connections: " + mProxyA11yServiceConnections.size());
+            pw.println("    Registered proxy connections:");
+            for (int i = 0; i < mProxyA11yServiceConnections.size(); i++) {
+                final ProxyAccessibilityServiceConnection proxy =
+                        mProxyA11yServiceConnections.valueAt(i);
+                if (proxy != null) {
+                    proxy.dump(fd, pw, args);
+                }
+            }
+        }
+    }
 }
\ No newline at end of file
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 6557ec5..de5f0c4 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -6675,15 +6675,7 @@
         @Deprecated
         public void legacyDumpProfiles(String packageName, boolean dumpClassesAndMethods)
                 throws LegacyDexoptDisabledException {
-            /* Only the shell, root, or the app user should be able to dump profiles. */
-            final int callingUid = Binder.getCallingUid();
             final Computer snapshot = snapshotComputer();
-            final String[] callerPackageNames = snapshot.getPackagesForUid(callingUid);
-            if (!PackageManagerServiceUtils.isRootOrShell(callingUid)
-                    && !ArrayUtils.contains(callerPackageNames, packageName)) {
-                throw new SecurityException("dumpProfiles");
-            }
-
             AndroidPackage pkg = snapshot.getPackage(packageName);
             if (pkg == null) {
                 throw new IllegalArgumentException("Unknown package: " + packageName);
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 41592bd..586e112 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -391,6 +391,11 @@
     private int runLegacyDexoptCommand(@NonNull String cmd)
             throws RemoteException, LegacyDexoptDisabledException {
         Installer.checkLegacyDexoptDisabled();
+
+        if (!PackageManagerServiceUtils.isRootOrShell(Binder.getCallingUid())) {
+            throw new SecurityException("Dexopt shell commands need root or shell access");
+        }
+
         switch (cmd) {
             case "compile":
                 return runCompile();
diff --git a/telephony/java/android/telephony/DomainSelectionService.java b/telephony/java/android/telephony/DomainSelectionService.java
index c352f2b..abcce5f 100644
--- a/telephony/java/android/telephony/DomainSelectionService.java
+++ b/telephony/java/android/telephony/DomainSelectionService.java
@@ -537,9 +537,9 @@
         }
 
         @Override
-        public void onWlanSelected() {
+        public void onWlanSelected(boolean useEmergencyPdn) {
             try {
-                mCallback.onWlanSelected();
+                mCallback.onWlanSelected(useEmergencyPdn);
             } catch (Exception e) {
                 Rlog.e(TAG, "onWlanSelected e=" + e);
             }
@@ -702,9 +702,10 @@
         }
 
         @Override
-        public void onDomainSelected(@NetworkRegistrationInfo.Domain int domain) {
+        public void onDomainSelected(@NetworkRegistrationInfo.Domain int domain,
+                boolean useEmergencyPdn) {
             try {
-                mCallback.onDomainSelected(domain);
+                mCallback.onDomainSelected(domain, useEmergencyPdn);
             } catch (Exception e) {
                 Rlog.e(TAG, "onDomainSelected e=" + e);
             }
diff --git a/telephony/java/android/telephony/TransportSelectorCallback.java b/telephony/java/android/telephony/TransportSelectorCallback.java
index d396790..04752e4 100644
--- a/telephony/java/android/telephony/TransportSelectorCallback.java
+++ b/telephony/java/android/telephony/TransportSelectorCallback.java
@@ -35,8 +35,10 @@
 
     /**
      * Notify that WLAN transport has been selected.
+     *
+     * @param useEmergencyPdn Indicates whether Wi-Fi emergency services use emergency PDN or not.
      */
-    void onWlanSelected();
+    void onWlanSelected(boolean useEmergencyPdn);
 
     /**
      * Notify that WWAN transport has been selected.
diff --git a/telephony/java/android/telephony/WwanSelectorCallback.java b/telephony/java/android/telephony/WwanSelectorCallback.java
index b3682ca..f9c2620 100644
--- a/telephony/java/android/telephony/WwanSelectorCallback.java
+++ b/telephony/java/android/telephony/WwanSelectorCallback.java
@@ -46,6 +46,7 @@
      * this interface can be discarded.
      *
      * @param domain The selected domain.
+     * @param useEmergencyPdn Indicates whether emergency services use emergency PDN or not.
      */
-    void onDomainSelected(@NetworkRegistrationInfo.Domain int domain);
+    void onDomainSelected(@NetworkRegistrationInfo.Domain int domain, boolean useEmergencyPdn);
 }
diff --git a/telephony/java/com/android/internal/telephony/ITransportSelectorCallback.aidl b/telephony/java/com/android/internal/telephony/ITransportSelectorCallback.aidl
index aca83f4..6777256d 100644
--- a/telephony/java/com/android/internal/telephony/ITransportSelectorCallback.aidl
+++ b/telephony/java/com/android/internal/telephony/ITransportSelectorCallback.aidl
@@ -22,7 +22,7 @@
 
 interface ITransportSelectorCallback {
     oneway void onCreated(in IDomainSelector selector);
-    oneway void onWlanSelected();
+    oneway void onWlanSelected(boolean useEmergencyPdn);
     IWwanSelectorCallback onWwanSelected();
     oneway void onWwanSelectedAsync(in ITransportSelectorResultCallback cb);
     oneway void onSelectionTerminated(int cause);
diff --git a/telephony/java/com/android/internal/telephony/IWwanSelectorCallback.aidl b/telephony/java/com/android/internal/telephony/IWwanSelectorCallback.aidl
index 339fbee..94e7c87 100644
--- a/telephony/java/com/android/internal/telephony/IWwanSelectorCallback.aidl
+++ b/telephony/java/com/android/internal/telephony/IWwanSelectorCallback.aidl
@@ -21,6 +21,6 @@
 oneway interface IWwanSelectorCallback {
     void onRequestEmergencyNetworkScan(in int[] preferredNetworks,
             int scanType, in IWwanSelectorResultCallback cb);
-    void onDomainSelected(int domain);
+    void onDomainSelected(int domain, boolean useEmergencyPdn);
     void onCancel();
 }