Merge "Revert "Remove KeyguardHostView"" into tm-qpr-dev am: da5de14a55 am: 5f5e8c18f5

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/21345320

Change-Id: Ie29b4bc83b995aef60f535575e449bd3833e8b36
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_host_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_host_view.xml
new file mode 100644
index 0000000..8497ff0
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_host_view.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License")
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<!-- This is the host view that generally contains two sub views: the widget view
+    and the security view. -->
+<com.android.keyguard.KeyguardHostView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/keyguard_host_view"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:clipChildren="false"
+    android:clipToPadding="false"
+    android:paddingTop="@dimen/keyguard_lock_padding"
+    android:importantForAccessibility="yes"> <!-- Needed because TYPE_WINDOW_STATE_CHANGED is sent
+                                                  from this view when bouncer is shown -->
+
+    <com.android.keyguard.KeyguardSecurityContainer
+        android:id="@+id/keyguard_security_container"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:clipChildren="false"
+        android:clipToPadding="false"
+        android:padding="0dp"
+        android:fitsSystemWindows="true"
+        android:layout_gravity="center">
+        <com.android.keyguard.KeyguardSecurityViewFlipper
+            android:id="@+id/view_flipper"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:clipChildren="false"
+            android:clipToPadding="false"
+            android:paddingTop="@dimen/keyguard_security_view_top_margin"
+            android:layout_gravity="center"
+            android:gravity="center">
+        </com.android.keyguard.KeyguardSecurityViewFlipper>
+    </com.android.keyguard.KeyguardSecurityContainer>
+
+</com.android.keyguard.KeyguardHostView>
+
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_security_container_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_security_container_view.xml
deleted file mode 100644
index 426cfaf..0000000
--- a/packages/SystemUI/res-keyguard/layout/keyguard_security_container_view.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 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.
-*/
--->
-
-<com.android.keyguard.KeyguardSecurityContainer
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
-    android:id="@+id/keyguard_security_container"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:clipChildren="false"
-    android:clipToPadding="false"
-    android:paddingTop="@dimen/keyguard_lock_padding"
-    android:importantForAccessibility="yes"> <!-- Needed because TYPE_WINDOW_STATE_CHANGED is sent
-                                                  from this view when bouncer is shown -->
-    <com.android.keyguard.KeyguardSecurityViewFlipper
-        android:id="@+id/view_flipper"
-        android:layout_width="wrap_content"
-        android:layout_height="match_parent"
-        android:clipChildren="false"
-        android:clipToPadding="false"
-        android:paddingTop="@dimen/keyguard_security_view_top_margin"
-        android:layout_gravity="center"
-        android:gravity="center">
-    </com.android.keyguard.KeyguardSecurityViewFlipper>
-</com.android.keyguard.KeyguardSecurityContainer>
-
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
new file mode 100644
index 0000000..2a389b6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2007 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.keyguard;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.widget.FrameLayout;
+
+/**
+ * Base class for keyguard view.  {@link #reset} is where you should
+ * reset the state of your view.  Use the {@link KeyguardViewCallback} via
+ * {@link #getCallback()} to send information back (such as poking the wake lock,
+ * or finishing the keyguard).
+ *
+ * Handles intercepting of media keys that still work when the keyguard is
+ * showing.
+ */
+public class KeyguardHostView extends FrameLayout {
+
+    protected ViewMediatorCallback mViewMediatorCallback;
+    private boolean mIsInteractable;
+
+    public KeyguardHostView(Context context) {
+        this(context, null);
+    }
+
+    public KeyguardHostView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void dispatchDraw(Canvas canvas) {
+        super.dispatchDraw(canvas);
+        if (mViewMediatorCallback != null) {
+            mViewMediatorCallback.keyguardDoneDrawing();
+        }
+    }
+
+    public void setViewMediatorCallback(ViewMediatorCallback viewMediatorCallback) {
+        mViewMediatorCallback = viewMediatorCallback;
+    }
+
+    /** Set true if the view can be interacted with */
+    public void setInteractable(boolean isInteractable) {
+        mIsInteractable = isInteractable;
+    }
+
+    /**
+     * Make sure to disallow touches while transitioning the bouncer, otherwise
+     * it can remain interactable even when barely visible.
+     */
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent ev) {
+        return !mIsInteractable;
+    }
+
+    /** True to consume any events that are sent to it */
+    @Override
+    public boolean onTouchEvent(MotionEvent ev) {
+        return true;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java
new file mode 100644
index 0000000..6139403
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java
@@ -0,0 +1,535 @@
+/*
+ * Copyright (C) 2020 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.keyguard;
+
+import android.app.ActivityManager;
+import android.content.res.ColorStateList;
+import android.content.res.Resources;
+import android.media.AudioManager;
+import android.os.SystemClock;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+import android.util.MathUtils;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.View.OnKeyListener;
+import android.view.ViewTreeObserver;
+import android.widget.FrameLayout;
+import android.window.OnBackAnimationCallback;
+
+import androidx.annotation.NonNull;
+
+import com.android.keyguard.KeyguardSecurityContainer.SecurityCallback;
+import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
+import com.android.keyguard.dagger.KeyguardBouncerScope;
+import com.android.settingslib.Utils;
+import com.android.systemui.R;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.util.ViewController;
+
+import java.io.File;
+
+import javax.inject.Inject;
+
+/** Controller for a {@link KeyguardHostView}. */
+@KeyguardBouncerScope
+public class KeyguardHostViewController extends ViewController<KeyguardHostView> {
+    private static final String TAG = "KeyguardViewBase";
+    public static final boolean DEBUG = KeyguardConstants.DEBUG;
+    // Whether the volume keys should be handled by keyguard. If true, then
+    // they will be handled here for specific media types such as music, otherwise
+    // the audio service will bring up the volume dialog.
+    private static final boolean KEYGUARD_MANAGES_VOLUME = false;
+
+    private static final String ENABLE_MENU_KEY_FILE = "/data/local/enable_menu_key";
+
+    private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+    private final KeyguardSecurityContainerController mKeyguardSecurityContainerController;
+    private final TelephonyManager mTelephonyManager;
+    private final ViewMediatorCallback mViewMediatorCallback;
+    private final AudioManager mAudioManager;
+
+    private ActivityStarter.OnDismissAction mDismissAction;
+    private Runnable mCancelAction;
+    private int mTranslationY;
+
+    private final KeyguardUpdateMonitorCallback mUpdateCallback =
+            new KeyguardUpdateMonitorCallback() {
+                @Override
+                public void onTrustGrantedForCurrentUser(
+                        boolean dismissKeyguard,
+                        boolean newlyUnlocked,
+                        TrustGrantFlags flags,
+                        String message
+                ) {
+                    if (dismissKeyguard) {
+                        if (!mView.isVisibleToUser()) {
+                            // The trust agent dismissed the keyguard without the user proving
+                            // that they are present (by swiping up to show the bouncer). That's
+                            // fine if the user proved presence via some other way to the trust
+                            // agent.
+                            Log.i(TAG, "TrustAgent dismissed Keyguard.");
+                        }
+                        mSecurityCallback.dismiss(
+                                false /* authenticated */,
+                                KeyguardUpdateMonitor.getCurrentUser(),
+                                /* bypassSecondaryLockScreen */ false,
+                                SecurityMode.Invalid
+                        );
+                    } else {
+                        if (flags.isInitiatedByUser() || flags.dismissKeyguardRequested()) {
+                            mViewMediatorCallback.playTrustedSound();
+                        }
+                    }
+                }
+            };
+
+    private final SecurityCallback mSecurityCallback = new SecurityCallback() {
+
+        @Override
+        public boolean dismiss(boolean authenticated, int targetUserId,
+                boolean bypassSecondaryLockScreen, SecurityMode expectedSecurityMode) {
+            return mKeyguardSecurityContainerController.showNextSecurityScreenOrFinish(
+                    authenticated, targetUserId, bypassSecondaryLockScreen, expectedSecurityMode);
+        }
+
+        @Override
+        public void userActivity() {
+            mViewMediatorCallback.userActivity();
+        }
+
+        @Override
+        public void onSecurityModeChanged(SecurityMode securityMode, boolean needsInput) {
+            mViewMediatorCallback.setNeedsInput(needsInput);
+        }
+
+        /**
+         * Authentication has happened and it's time to dismiss keyguard. This function
+         * should clean up and inform KeyguardViewMediator.
+         *
+         * @param strongAuth whether the user has authenticated with strong authentication like
+         *                   pattern, password or PIN but not by trust agents or fingerprint
+         * @param targetUserId a user that needs to be the foreground user at the dismissal
+         *                    completion.
+         */
+        @Override
+        public void finish(boolean strongAuth, int targetUserId) {
+            // If there's a pending runnable because the user interacted with a widget
+            // and we're leaving keyguard, then run it.
+            boolean deferKeyguardDone = false;
+            if (mDismissAction != null) {
+                deferKeyguardDone = mDismissAction.onDismiss();
+                mDismissAction = null;
+                mCancelAction = null;
+            }
+            if (mViewMediatorCallback != null) {
+                if (deferKeyguardDone) {
+                    mViewMediatorCallback.keyguardDonePending(strongAuth, targetUserId);
+                } else {
+                    mViewMediatorCallback.keyguardDone(strongAuth, targetUserId);
+                }
+            }
+        }
+
+        @Override
+        public void reset() {
+            mViewMediatorCallback.resetKeyguard();
+        }
+
+        @Override
+        public void onCancelClicked() {
+            mViewMediatorCallback.onCancelClicked();
+        }
+    };
+
+    private OnKeyListener mOnKeyListener = (v, keyCode, event) -> interceptMediaKey(event);
+
+    @Inject
+    public KeyguardHostViewController(KeyguardHostView view,
+            KeyguardUpdateMonitor keyguardUpdateMonitor,
+            AudioManager audioManager,
+            TelephonyManager telephonyManager,
+            ViewMediatorCallback viewMediatorCallback,
+            KeyguardSecurityContainerController.Factory
+                    keyguardSecurityContainerControllerFactory) {
+        super(view);
+        mKeyguardUpdateMonitor = keyguardUpdateMonitor;
+        mAudioManager = audioManager;
+        mTelephonyManager = telephonyManager;
+        mViewMediatorCallback = viewMediatorCallback;
+        mKeyguardSecurityContainerController = keyguardSecurityContainerControllerFactory.create(
+                mSecurityCallback);
+    }
+
+    /** Initialize the Controller. */
+    public void onInit() {
+        mKeyguardSecurityContainerController.init();
+        updateResources();
+    }
+
+    @Override
+    protected void onViewAttached() {
+        mView.setViewMediatorCallback(mViewMediatorCallback);
+        // Update ViewMediator with the current input method requirements
+        mViewMediatorCallback.setNeedsInput(mKeyguardSecurityContainerController.needsInput());
+        mKeyguardUpdateMonitor.registerCallback(mUpdateCallback);
+        mView.setOnKeyListener(mOnKeyListener);
+        mKeyguardSecurityContainerController.showPrimarySecurityScreen(false);
+    }
+
+    @Override
+    protected void onViewDetached() {
+        mKeyguardUpdateMonitor.removeCallback(mUpdateCallback);
+        mView.setOnKeyListener(null);
+    }
+
+     /** Called before this view is being removed. */
+    public void cleanUp() {
+        mKeyguardSecurityContainerController.onPause();
+    }
+
+    public void resetSecurityContainer() {
+        mKeyguardSecurityContainerController.reset();
+    }
+
+    /**
+     * Dismisses the keyguard by going to the next screen or making it gone.
+     * @param targetUserId a user that needs to be the foreground user at the dismissal completion.
+     * @return True if the keyguard is done.
+     */
+    public boolean dismiss(int targetUserId) {
+        return mSecurityCallback.dismiss(false, targetUserId, false,
+                getCurrentSecurityMode());
+    }
+
+    /**
+     * Called when the Keyguard is actively shown on the screen.
+     */
+    public void onResume() {
+        if (DEBUG) Log.d(TAG, "screen on, instance " + Integer.toHexString(hashCode()));
+        mKeyguardSecurityContainerController.onResume(KeyguardSecurityView.SCREEN_ON);
+        mView.requestFocus();
+    }
+
+    public CharSequence getAccessibilityTitleForCurrentMode() {
+        return mKeyguardSecurityContainerController.getTitle();
+    }
+
+    /**
+     * Starts the animation when the Keyguard gets shown.
+     */
+    public void appear(int statusBarHeight) {
+        // We might still be collapsed and the view didn't have time to layout yet or still
+        // be small, let's wait on the predraw to do the animation in that case.
+        if (mView.getHeight() != 0 && mView.getHeight() != statusBarHeight) {
+            mKeyguardSecurityContainerController.startAppearAnimation();
+        } else {
+            mView.getViewTreeObserver().addOnPreDrawListener(
+                    new ViewTreeObserver.OnPreDrawListener() {
+                        @Override
+                        public boolean onPreDraw() {
+                            mView.getViewTreeObserver().removeOnPreDrawListener(this);
+                            mKeyguardSecurityContainerController.startAppearAnimation();
+                            return true;
+                        }
+                    });
+            mView.requestLayout();
+        }
+    }
+
+    /**
+     * Show a string explaining why the security view needs to be solved.
+     *
+     * @param reason a flag indicating which string should be shown, see
+     *               {@link KeyguardSecurityView#PROMPT_REASON_NONE},
+     *               {@link KeyguardSecurityView#PROMPT_REASON_RESTART},
+     *               {@link KeyguardSecurityView#PROMPT_REASON_TIMEOUT}, and
+     *               {@link KeyguardSecurityView#PROMPT_REASON_PREPARE_FOR_UPDATE}.
+     */
+    public void showPromptReason(int reason) {
+        mKeyguardSecurityContainerController.showPromptReason(reason);
+    }
+
+    public void showMessage(CharSequence message, ColorStateList colorState) {
+        mKeyguardSecurityContainerController.showMessage(message, colorState);
+    }
+
+    public void showErrorMessage(CharSequence customMessage) {
+        showMessage(customMessage, Utils.getColorError(mView.getContext()));
+    }
+
+    /**
+     * Sets an action to run when keyguard finishes.
+     *
+     * @param action
+     */
+    public void setOnDismissAction(ActivityStarter.OnDismissAction action, Runnable cancelAction) {
+        if (mCancelAction != null) {
+            mCancelAction.run();
+            mCancelAction = null;
+        }
+        mDismissAction = action;
+        mCancelAction = cancelAction;
+    }
+
+    public void cancelDismissAction() {
+        setOnDismissAction(null, null);
+    }
+
+    public void startDisappearAnimation(Runnable finishRunnable) {
+        if (!mKeyguardSecurityContainerController.startDisappearAnimation(finishRunnable)
+                && finishRunnable != null) {
+            finishRunnable.run();
+        }
+    }
+
+    /**
+     * Called when the Keyguard is not actively shown anymore on the screen.
+     */
+    public void onPause() {
+        if (DEBUG) {
+            Log.d(TAG, String.format("screen off, instance %s at %s",
+                    Integer.toHexString(hashCode()), SystemClock.uptimeMillis()));
+        }
+        mKeyguardSecurityContainerController.showPrimarySecurityScreen(true);
+        mKeyguardSecurityContainerController.onPause();
+        mView.clearFocus();
+    }
+
+    /**
+     * Called when the view needs to be shown.
+     */
+    public void showPrimarySecurityScreen() {
+        if (DEBUG) Log.d(TAG, "show()");
+        mKeyguardSecurityContainerController.showPrimarySecurityScreen(false);
+    }
+
+    /**
+     * Fades and translates in/out the security screen.
+     * Fades in as expansion approaches 0.
+     * Animation duration is between 0.33f and 0.67f of panel expansion fraction.
+     * @param fraction amount of the screen that should show.
+     */
+    public void setExpansion(float fraction) {
+        float scaledFraction = BouncerPanelExpansionCalculator.showBouncerProgress(fraction);
+        mView.setAlpha(MathUtils.constrain(1 - scaledFraction, 0f, 1f));
+        mView.setTranslationY(scaledFraction * mTranslationY);
+    }
+
+    /**
+     * When bouncer was visible and is starting to become hidden.
+     */
+    public void onStartingToHide() {
+        mKeyguardSecurityContainerController.onStartingToHide();
+    }
+
+    /** Called when bouncer visibility changes. */
+    public void onBouncerVisibilityChanged(@View.Visibility int visibility) {
+        mKeyguardSecurityContainerController.onBouncerVisibilityChanged(visibility);
+    }
+
+    public boolean hasDismissActions() {
+        return mDismissAction != null || mCancelAction != null;
+    }
+
+    public SecurityMode getCurrentSecurityMode() {
+        return mKeyguardSecurityContainerController.getCurrentSecurityMode();
+    }
+
+    public int getTop() {
+        int top = mView.getTop();
+        // The password view has an extra top padding that should be ignored.
+        if (getCurrentSecurityMode() == SecurityMode.Password) {
+            View messageArea = mView.findViewById(R.id.keyguard_message_area);
+            top += messageArea.getTop();
+        }
+        return top;
+    }
+
+    public boolean handleBackKey() {
+        SecurityMode securityMode = mKeyguardSecurityContainerController.getCurrentSecurityMode();
+        if (securityMode != SecurityMode.None) {
+            mKeyguardSecurityContainerController.dismiss(
+                    false, KeyguardUpdateMonitor.getCurrentUser(), securityMode);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * In general, we enable unlocking the insecure keyguard with the menu key. However, there are
+     * some cases where we wish to disable it, notably when the menu button placement or technology
+     * is prone to false positives.
+     *
+     * @return true if the menu key should be enabled
+     */
+    public boolean shouldEnableMenuKey() {
+        final Resources res = mView.getResources();
+        final boolean configDisabled = res.getBoolean(R.bool.config_disableMenuKeyInLockScreen);
+        final boolean isTestHarness = ActivityManager.isRunningInTestHarness();
+        final boolean fileOverride = (new File(ENABLE_MENU_KEY_FILE)).exists();
+        return !configDisabled || isTestHarness || fileOverride;
+    }
+
+    /**
+     * @return true if the current bouncer is password
+     */
+    public boolean dispatchBackKeyEventPreIme() {
+        if (mKeyguardSecurityContainerController.getCurrentSecurityMode()
+                == SecurityMode.Password) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * @return the {@link OnBackAnimationCallback} to animate this view during a back gesture.
+     */
+    @NonNull
+    public OnBackAnimationCallback getBackCallback() {
+        return mKeyguardSecurityContainerController.getBackCallback();
+    }
+
+    /**
+     * Allows the media keys to work when the keyguard is showing.
+     * The media keys should be of no interest to the actual keyguard view(s),
+     * so intercepting them here should not be of any harm.
+     * @param event The key event
+     * @return whether the event was consumed as a media key.
+     */
+    public boolean interceptMediaKey(KeyEvent event) {
+        int keyCode = event.getKeyCode();
+        if (event.getAction() == KeyEvent.ACTION_DOWN) {
+            switch (keyCode) {
+                case KeyEvent.KEYCODE_MEDIA_PLAY:
+                case KeyEvent.KEYCODE_MEDIA_PAUSE:
+                case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
+                    /* Suppress PLAY/PAUSE toggle when phone is ringing or
+                     * in-call to avoid music playback */
+                    if (mTelephonyManager != null &&
+                            mTelephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE) {
+                        return true;  // suppress key event
+                    }
+                case KeyEvent.KEYCODE_MUTE:
+                case KeyEvent.KEYCODE_HEADSETHOOK:
+                case KeyEvent.KEYCODE_MEDIA_STOP:
+                case KeyEvent.KEYCODE_MEDIA_NEXT:
+                case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
+                case KeyEvent.KEYCODE_MEDIA_REWIND:
+                case KeyEvent.KEYCODE_MEDIA_RECORD:
+                case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
+                case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
+                    handleMediaKeyEvent(event);
+                    return true;
+                }
+
+                case KeyEvent.KEYCODE_VOLUME_UP:
+                case KeyEvent.KEYCODE_VOLUME_DOWN:
+                case KeyEvent.KEYCODE_VOLUME_MUTE: {
+                    if (KEYGUARD_MANAGES_VOLUME) {
+                        // Volume buttons should only function for music (local or remote).
+                        // TODO: Actually handle MUTE.
+                        mAudioManager.adjustSuggestedStreamVolume(
+                                keyCode == KeyEvent.KEYCODE_VOLUME_UP
+                                        ? AudioManager.ADJUST_RAISE
+                                        : AudioManager.ADJUST_LOWER /* direction */,
+                                AudioManager.STREAM_MUSIC /* stream */, 0 /* flags */);
+                        // Don't execute default volume behavior
+                        return true;
+                    } else {
+                        return false;
+                    }
+                }
+            }
+        } else if (event.getAction() == KeyEvent.ACTION_UP) {
+            switch (keyCode) {
+                case KeyEvent.KEYCODE_MUTE:
+                case KeyEvent.KEYCODE_HEADSETHOOK:
+                case KeyEvent.KEYCODE_MEDIA_PLAY:
+                case KeyEvent.KEYCODE_MEDIA_PAUSE:
+                case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
+                case KeyEvent.KEYCODE_MEDIA_STOP:
+                case KeyEvent.KEYCODE_MEDIA_NEXT:
+                case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
+                case KeyEvent.KEYCODE_MEDIA_REWIND:
+                case KeyEvent.KEYCODE_MEDIA_RECORD:
+                case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
+                case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
+                    handleMediaKeyEvent(event);
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+
+    private void handleMediaKeyEvent(KeyEvent keyEvent) {
+        mAudioManager.dispatchMediaKeyEvent(keyEvent);
+    }
+
+    public void finish(boolean strongAuth, int currentUser) {
+        mSecurityCallback.finish(strongAuth, currentUser);
+    }
+
+    /**
+     * Apply keyguard configuration from the currently active resources. This can be called when the
+     * device configuration changes, to re-apply some resources that are qualified on the device
+     * configuration.
+     */
+    public void updateResources() {
+        int gravity;
+
+        Resources resources = mView.getResources();
+
+        if (resources.getBoolean(R.bool.can_use_one_handed_bouncer)) {
+            gravity = resources.getInteger(
+                    R.integer.keyguard_host_view_one_handed_gravity);
+        } else {
+            gravity = resources.getInteger(R.integer.keyguard_host_view_gravity);
+        }
+
+        mTranslationY = resources
+                .getDimensionPixelSize(R.dimen.keyguard_host_view_translation_y);
+        // Android SysUI uses a FrameLayout as the top-level, but Auto uses RelativeLayout.
+        // We're just changing the gravity here though (which can't be applied to RelativeLayout),
+        // so only attempt the update if mView is inside a FrameLayout.
+        if (mView.getLayoutParams() instanceof FrameLayout.LayoutParams) {
+            FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mView.getLayoutParams();
+            if (lp.gravity != gravity) {
+                lp.gravity = gravity;
+                mView.setLayoutParams(lp);
+            }
+        }
+
+        if (mKeyguardSecurityContainerController != null) {
+            mKeyguardSecurityContainerController.updateResources();
+        }
+    }
+
+    /** Update keyguard position based on a tapped X coordinate. */
+    public void updateKeyguardPosition(float x) {
+        if (mKeyguardSecurityContainerController != null) {
+            mKeyguardSecurityContainerController.updateKeyguardPosition(x);
+        }
+    }
+
+    /** Set true if the view can be interacted with */
+    public void setInteractable(boolean isInteractable) {
+        mView.setInteractable(isInteractable);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
index bec8547..48844db 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
@@ -52,7 +52,26 @@
     // The following is used to ignore callbacks from SecurityViews that are no longer current
     // (e.g. face unlock). This avoids unwanted asynchronous events from messing with the
     // state for the current security method.
-    private KeyguardSecurityCallback mNullCallback = new KeyguardSecurityCallback() {};
+    private KeyguardSecurityCallback mNullCallback = new KeyguardSecurityCallback() {
+        @Override
+        public void userActivity() { }
+        @Override
+        public void reportUnlockAttempt(int userId, boolean success, int timeoutMs) { }
+        @Override
+        public boolean isVerifyUnlockOnly() {
+            return false;
+        }
+        @Override
+        public void dismiss(boolean securityVerified, int targetUserId,
+                SecurityMode expectedSecurityMode) { }
+        @Override
+        public void dismiss(boolean authenticated, int targetId,
+                boolean bypassSecondaryLockScreen, SecurityMode expectedSecurityMode) { }
+        @Override
+        public void onUserInput() { }
+        @Override
+        public void reset() {}
+    };
 
     protected KeyguardInputViewController(T view, SecurityMode securityMode,
             KeyguardSecurityCallback keyguardSecurityCallback,
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java
index bf9c3bb..bc72f79 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java
@@ -25,9 +25,7 @@
      * @param targetUserId a user that needs to be the foreground user at the dismissal completion.
      * @param expectedSecurityMode The security mode that is invoking this dismiss.
      */
-    default void dismiss(boolean securityVerified, int targetUserId,
-            SecurityMode expectedSecurityMode) {
-    }
+    void dismiss(boolean securityVerified, int targetUserId, SecurityMode expectedSecurityMode);
 
     /**
      * Dismiss the given security screen.
@@ -37,26 +35,19 @@
      *                                  if any, during this dismissal.
      * @param expectedSecurityMode The security mode that is invoking this dismiss.
      */
-    default boolean dismiss(boolean securityVerified, int targetUserId,
-            boolean bypassSecondaryLockScreen,
-            SecurityMode expectedSecurityMode) {
-        return false;
-    }
+    void dismiss(boolean securityVerified, int targetUserId, boolean bypassSecondaryLockScreen,
+            SecurityMode expectedSecurityMode);
 
     /**
      * Manually report user activity to keep the device awake.
      */
-    default void userActivity() {
-    }
+    void userActivity();
 
     /**
      * Checks if keyguard is in "verify credentials" mode.
-     *
      * @return true if user has been asked to verify security.
      */
-    default boolean isVerifyUnlockOnly() {
-        return false;
-    }
+    boolean isVerifyUnlockOnly();
 
     /**
      * Call to report an unlock attempt.
@@ -65,14 +56,12 @@
      * @param timeoutMs timeout in milliseconds to wait before reattempting an unlock.
      *                  Only nonzero if 'success' is false
      */
-    default void reportUnlockAttempt(int userId, boolean success, int timeoutMs) {
-    }
+    void reportUnlockAttempt(int userId, boolean success, int timeoutMs);
 
     /**
      * Resets the keyguard view.
      */
-    default void reset() {
-    }
+    void reset();
 
     /**
      * Call when cancel button is pressed in bouncer.
@@ -84,19 +73,5 @@
     /**
      * Invoked whenever users are typing their password or drawing a pattern.
      */
-    default void onUserInput() {
-    }
-
-
-    /**
-     * Dismisses keyguard and go to unlocked state.
-     */
-    default void finish(boolean strongAuth, int targetUserId) {
-    }
-
-    /**
-     * Specifies that security mode has changed.
-     */
-    default void onSecurityModeChanged(SecurityMode securityMode, boolean needsInput) {
-    }
+    void onUserInput();
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index eec788b..9f07a20 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -50,7 +50,6 @@
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BlendMode;
-import android.graphics.Canvas;
 import android.graphics.Rect;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
@@ -165,8 +164,6 @@
     private boolean mDisappearAnimRunning;
     private SwipeListener mSwipeListener;
     private ViewMode mViewMode = new DefaultViewMode();
-    private boolean mIsInteractable;
-    protected ViewMediatorCallback mViewMediatorCallback;
     /*
      * Using MODE_UNINITIALIZED to mean the view mode is set to DefaultViewMode, but init() has not
      * yet been called on it. This will happen when the ViewController is initialized.
@@ -268,6 +265,31 @@
         return mBackCallback;
     }
 
+    // Used to notify the container when something interesting happens.
+    public interface SecurityCallback {
+        /**
+         * Potentially dismiss the current security screen, after validating that all device
+         * security has been unlocked. Otherwise show the next screen.
+         */
+        boolean dismiss(boolean authenticated, int targetUserId, boolean bypassSecondaryLockScreen,
+                SecurityMode expectedSecurityMode);
+
+        void userActivity();
+
+        void onSecurityModeChanged(SecurityMode securityMode, boolean needsInput);
+
+        /**
+         * @param strongAuth   wheher the user has authenticated with strong authentication like
+         *                     pattern, password or PIN but not by trust agents or fingerprint
+         * @param targetUserId a user that needs to be the foreground user at the finish completion.
+         */
+        void finish(boolean strongAuth, int targetUserId);
+
+        void reset();
+
+        void onCancelClicked();
+    }
+
     public interface SwipeListener {
         void onSwipeUp();
     }
@@ -320,7 +342,7 @@
 
     public KeyguardSecurityContainer(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
-        mSpringAnimation = new SpringAnimation(this, DynamicAnimation.TRANSLATION_Y);
+        mSpringAnimation = new SpringAnimation(this, DynamicAnimation.Y);
         mViewConfiguration = ViewConfiguration.get(context);
         mDoubleTapDetector = new GestureDetector(context, new DoubleTapListener());
     }
@@ -423,11 +445,6 @@
         mViewMode.reset();
     }
 
-    /** Set true if the view can be interacted with */
-    public void setInteractable(boolean isInteractable) {
-        mIsInteractable = isInteractable;
-    }
-
     @Override
     public boolean shouldDelayChildPressedState() {
         return true;
@@ -435,10 +452,6 @@
 
     @Override
     public boolean onInterceptTouchEvent(MotionEvent event) {
-        if (!mIsInteractable) {
-            return true;
-        }
-
         boolean result =  mMotionEventListeners.stream().anyMatch(
                 listener -> listener.onInterceptTouchEvent(event))
                 || super.onInterceptTouchEvent(event);
@@ -626,18 +639,6 @@
         return insets.inset(0, 0, 0, inset);
     }
 
-    @Override
-    protected void dispatchDraw(Canvas canvas) {
-        super.dispatchDraw(canvas);
-        if (mViewMediatorCallback != null) {
-            mViewMediatorCallback.keyguardDoneDrawing();
-        }
-    }
-
-    public void setViewMediatorCallback(ViewMediatorCallback viewMediatorCallback) {
-        mViewMediatorCallback = viewMediatorCallback;
-    }
-
     private void showDialog(String title, String message) {
         if (mAlertDialog != null) {
             mAlertDialog.dismiss();
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index e121bf1..20baa81 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -29,26 +29,17 @@
 import static com.android.keyguard.KeyguardSecurityContainer.USER_TYPE_WORK_PROFILE;
 import static com.android.systemui.DejankUtils.whitelistIpcs;
 
-import android.app.ActivityManager;
 import android.app.admin.DevicePolicyManager;
 import android.content.Intent;
 import android.content.res.ColorStateList;
 import android.content.res.Configuration;
-import android.content.res.Resources;
 import android.hardware.biometrics.BiometricSourceType;
-import android.media.AudioManager;
 import android.metrics.LogMaker;
-import android.os.SystemClock;
 import android.os.UserHandle;
-import android.telephony.TelephonyManager;
 import android.util.Log;
-import android.util.MathUtils;
 import android.util.Slog;
-import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.ViewTreeObserver;
-import android.widget.FrameLayout;
 import android.window.OnBackAnimationCallback;
 
 import androidx.annotation.NonNull;
@@ -62,6 +53,7 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardSecurityContainer.BouncerUiEvent;
+import com.android.keyguard.KeyguardSecurityContainer.SecurityCallback;
 import com.android.keyguard.KeyguardSecurityContainer.SwipeListener;
 import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
 import com.android.keyguard.dagger.KeyguardBouncerScope;
@@ -75,7 +67,6 @@
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.flags.Flags;
 import com.android.systemui.log.SessionTracker;
-import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.shared.system.SysUiStatsLog;
 import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -84,7 +75,6 @@
 import com.android.systemui.util.ViewController;
 import com.android.systemui.util.settings.GlobalSettings;
 
-import java.io.File;
 import java.util.Optional;
 
 import javax.inject.Inject;
@@ -105,6 +95,7 @@
     private final UiEventLogger mUiEventLogger;
     private final KeyguardStateController mKeyguardStateController;
     private final KeyguardSecurityViewFlipperController mSecurityViewFlipperController;
+    private final SecurityCallback mSecurityCallback;
     private final ConfigurationController mConfigurationController;
     private final FalsingCollector mFalsingCollector;
     private final FalsingManager mFalsingManager;
@@ -114,20 +105,6 @@
     private final SessionTracker mSessionTracker;
     private final Optional<SideFpsController> mSideFpsController;
     private final FalsingA11yDelegate mFalsingA11yDelegate;
-    private int mTranslationY;
-    // Whether the volume keys should be handled by keyguard. If true, then
-    // they will be handled here for specific media types such as music, otherwise
-    // the audio service will bring up the volume dialog.
-    private static final boolean KEYGUARD_MANAGES_VOLUME = false;
-
-    private static final String ENABLE_MENU_KEY_FILE = "/data/local/enable_menu_key";
-
-    private final TelephonyManager mTelephonyManager;
-    private final ViewMediatorCallback mViewMediatorCallback;
-    private final AudioManager mAudioManager;
-    private View.OnKeyListener mOnKeyListener = (v, keyCode, event) -> interceptMediaKey(event);
-    private ActivityStarter.OnDismissAction mDismissAction;
-    private Runnable mCancelAction;
 
     private int mLastOrientation = Configuration.ORIENTATION_UNDEFINED;
 
@@ -172,6 +149,11 @@
     };
 
     private KeyguardSecurityCallback mKeyguardSecurityCallback = new KeyguardSecurityCallback() {
+        public void userActivity() {
+            if (mSecurityCallback != null) {
+                mSecurityCallback.userActivity();
+            }
+        }
 
         @Override
         public void onUserInput() {
@@ -186,23 +168,16 @@
         }
 
         @Override
-        public boolean dismiss(boolean authenticated, int targetId,
+        public void dismiss(boolean authenticated, int targetId,
                 boolean bypassSecondaryLockScreen, SecurityMode expectedSecurityMode) {
-            return showNextSecurityScreenOrFinish(
-                    authenticated, targetId, bypassSecondaryLockScreen, expectedSecurityMode);
+            mSecurityCallback.dismiss(authenticated, targetId, bypassSecondaryLockScreen,
+                    expectedSecurityMode);
         }
 
-        @Override
-        public void userActivity() {
-            mViewMediatorCallback.userActivity();
-        }
-
-        @Override
         public boolean isVerifyUnlockOnly() {
             return false;
         }
 
-        @Override
         public void reportUnlockAttempt(int userId, boolean success, int timeoutMs) {
             int bouncerSide = SysUiStatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED__SIDE__DEFAULT;
             if (mView.isSidedSecurityMode()) {
@@ -239,47 +214,12 @@
                             : BouncerUiEvent.BOUNCER_PASSWORD_FAILURE, getSessionId());
         }
 
-        @Override
         public void reset() {
-            mViewMediatorCallback.resetKeyguard();
+            mSecurityCallback.reset();
         }
 
-        @Override
         public void onCancelClicked() {
-            mViewMediatorCallback.onCancelClicked();
-        }
-
-        /**
-         * Authentication has happened and it's time to dismiss keyguard. This function
-         * should clean up and inform KeyguardViewMediator.
-         *
-         * @param strongAuth whether the user has authenticated with strong authentication like
-         *                   pattern, password or PIN but not by trust agents or fingerprint
-         * @param targetUserId a user that needs to be the foreground user at the dismissal
-         *                    completion.
-         */
-        @Override
-        public void finish(boolean strongAuth, int targetUserId) {
-            // If there's a pending runnable because the user interacted with a widget
-            // and we're leaving keyguard, then run it.
-            boolean deferKeyguardDone = false;
-            if (mDismissAction != null) {
-                deferKeyguardDone = mDismissAction.onDismiss();
-                mDismissAction = null;
-                mCancelAction = null;
-            }
-            if (mViewMediatorCallback != null) {
-                if (deferKeyguardDone) {
-                    mViewMediatorCallback.keyguardDonePending(strongAuth, targetUserId);
-                } else {
-                    mViewMediatorCallback.keyguardDone(strongAuth, targetUserId);
-                }
-            }
-        }
-
-        @Override
-        public void onSecurityModeChanged(SecurityMode securityMode, boolean needsInput) {
-            mViewMediatorCallback.setNeedsInput(needsInput);
+            mSecurityCallback.onCancelClicked();
         }
     };
 
@@ -324,34 +264,6 @@
     private final KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback =
             new KeyguardUpdateMonitorCallback() {
                 @Override
-                public void onTrustGrantedForCurrentUser(
-                        boolean dismissKeyguard,
-                        boolean newlyUnlocked,
-                        TrustGrantFlags flags,
-                        String message
-                ) {
-                    if (dismissKeyguard) {
-                        if (!mView.isVisibleToUser()) {
-                            // The trust agent dismissed the keyguard without the user proving
-                            // that they are present (by swiping up to show the bouncer). That's
-                            // fine if the user proved presence via some other way to the trust
-                            // agent.
-                            Log.i(TAG, "TrustAgent dismissed Keyguard.");
-                        }
-                        mKeyguardSecurityCallback.dismiss(
-                                false /* authenticated */,
-                                KeyguardUpdateMonitor.getCurrentUser(),
-                                /* bypassSecondaryLockScreen */ false,
-                                SecurityMode.Invalid
-                        );
-                    } else {
-                        if (flags.isInitiatedByUser() || flags.dismissKeyguardRequested()) {
-                            mViewMediatorCallback.playTrustedSound();
-                        }
-                    }
-                }
-
-                @Override
                 public void onDevicePolicyManagerStateChanged() {
                     showPrimarySecurityScreen(false);
                 }
@@ -370,8 +282,7 @@
                 }
             };
 
-    @Inject
-    public KeyguardSecurityContainerController(KeyguardSecurityContainer view,
+    private KeyguardSecurityContainerController(KeyguardSecurityContainer view,
             AdminSecondaryLockScreenController.Factory adminSecondaryLockScreenControllerFactory,
             LockPatternUtils lockPatternUtils,
             KeyguardUpdateMonitor keyguardUpdateMonitor,
@@ -379,6 +290,7 @@
             MetricsLogger metricsLogger,
             UiEventLogger uiEventLogger,
             KeyguardStateController keyguardStateController,
+            SecurityCallback securityCallback,
             KeyguardSecurityViewFlipperController securityViewFlipperController,
             ConfigurationController configurationController,
             FalsingCollector falsingCollector,
@@ -388,11 +300,7 @@
             GlobalSettings globalSettings,
             SessionTracker sessionTracker,
             Optional<SideFpsController> sideFpsController,
-            FalsingA11yDelegate falsingA11yDelegate,
-            TelephonyManager telephonyManager,
-            ViewMediatorCallback viewMediatorCallback,
-            AudioManager audioManager
-    ) {
+            FalsingA11yDelegate falsingA11yDelegate) {
         super(view);
         mLockPatternUtils = lockPatternUtils;
         mUpdateMonitor = keyguardUpdateMonitor;
@@ -400,6 +308,7 @@
         mMetricsLogger = metricsLogger;
         mUiEventLogger = uiEventLogger;
         mKeyguardStateController = keyguardStateController;
+        mSecurityCallback = securityCallback;
         mSecurityViewFlipperController = securityViewFlipperController;
         mAdminSecondaryLockScreenController = adminSecondaryLockScreenControllerFactory.create(
                 mKeyguardSecurityCallback);
@@ -413,15 +322,11 @@
         mSessionTracker = sessionTracker;
         mSideFpsController = sideFpsController;
         mFalsingA11yDelegate = falsingA11yDelegate;
-        mTelephonyManager = telephonyManager;
-        mViewMediatorCallback = viewMediatorCallback;
-        mAudioManager = audioManager;
     }
 
     @Override
     public void onInit() {
         mSecurityViewFlipperController.init();
-        updateResources();
         configureMode();
     }
 
@@ -432,11 +337,6 @@
         mView.addMotionEventListener(mGlobalTouchListener);
         mConfigurationController.addCallback(mConfigurationListener);
         mUserSwitcherController.addUserSwitchCallback(mUserSwitchCallback);
-        mView.setViewMediatorCallback(mViewMediatorCallback);
-        // Update ViewMediator with the current input method requirements
-        mViewMediatorCallback.setNeedsInput(needsInput());
-        mView.setOnKeyListener(mOnKeyListener);
-        showPrimarySecurityScreen(false);
     }
 
     @Override
@@ -449,11 +349,6 @@
 
     /** */
     public void onPause() {
-        if (DEBUG) {
-            Log.d(TAG, String.format("screen off, instance %s at %s",
-                    Integer.toHexString(hashCode()), SystemClock.uptimeMillis()));
-        }
-        showPrimarySecurityScreen(true);
         mAdminSecondaryLockScreenController.hide();
         if (mCurrentSecurityMode != SecurityMode.None) {
             getCurrentSecurityController().onPause();
@@ -462,7 +357,6 @@
         // It might happen that onStartingToHide is not called when the device is locked while on
         // bouncer.
         setBouncerVisible(false);
-        mView.clearFocus();
     }
 
     private void updateSideFpsVisibility() {
@@ -498,22 +392,12 @@
      * @param turningOff true if the device is being turned off
      */
     public void showPrimarySecurityScreen(boolean turningOff) {
-        if (DEBUG) Log.d(TAG, "show()");
         SecurityMode securityMode = whitelistIpcs(() -> mSecurityModel.getSecurityMode(
                 KeyguardUpdateMonitor.getCurrentUser()));
         if (DEBUG) Log.v(TAG, "showPrimarySecurityScreen(turningOff=" + turningOff + ")");
         showSecurityScreen(securityMode);
     }
 
-    /**
-     * Show a string explaining why the security view needs to be solved.
-     *
-     * @param reason a flag indicating which string should be shown, see
-     *               {@link KeyguardSecurityView#PROMPT_REASON_NONE},
-     *               {@link KeyguardSecurityView#PROMPT_REASON_RESTART},
-     *               {@link KeyguardSecurityView#PROMPT_REASON_TIMEOUT}, and
-     *               {@link KeyguardSecurityView#PROMPT_REASON_PREPARE_FOR_UPDATE}.
-     */
     @Override
     public void showPromptReason(int reason) {
         if (mCurrentSecurityMode != SecurityMode.None) {
@@ -530,32 +414,8 @@
         }
     }
 
-    /**
-     * Sets an action to run when keyguard finishes.
-     *
-     * @param action callback to be invoked when keyguard disappear animation completes.
-     */
-    public void setOnDismissAction(ActivityStarter.OnDismissAction action, Runnable cancelAction) {
-        if (mCancelAction != null) {
-            mCancelAction.run();
-            mCancelAction = null;
-        }
-        mDismissAction = action;
-        mCancelAction = cancelAction;
-    }
-
-    /**
-     * @return whether dismiss action or cancel action has been set.
-     */
-    public boolean hasDismissActions() {
-        return mDismissAction != null || mCancelAction != null;
-    }
-
-    /**
-     * Remove any dismiss action or cancel action that was set.
-     */
-    public void cancelDismissAction() {
-        setOnDismissAction(null, null);
+    public SecurityMode getCurrentSecurityMode() {
+        return mCurrentSecurityMode;
     }
 
     /**
@@ -567,64 +427,17 @@
         mKeyguardSecurityCallback.dismiss(authenticated, targetUserId, expectedSecurityMode);
     }
 
-    /**
-     * Dismisses the keyguard by going to the next screen or making it gone.
-     * @param targetUserId a user that needs to be the foreground user at the dismissal completion.
-     * @return True if the keyguard is done.
-     */
-    public boolean dismiss(int targetUserId) {
-        return mKeyguardSecurityCallback.dismiss(false, targetUserId, false,
-                getCurrentSecurityMode());
-    }
-
-    public SecurityMode getCurrentSecurityMode() {
-        return mCurrentSecurityMode;
-    }
-
-    /**
-     * @return the top of the corresponding view.
-     */
-    public int getTop() {
-        int top = mView.getTop();
-        // The password view has an extra top padding that should be ignored.
-        if (getCurrentSecurityMode() == SecurityMode.Password) {
-            View messageArea = mView.findViewById(R.id.keyguard_message_area);
-            top += messageArea.getTop();
-        }
-        return top;
-    }
-
-    /** Set true if the view can be interacted with */
-    public void setInteractable(boolean isInteractable) {
-        mView.setInteractable(isInteractable);
-    }
-
-    /**
-     * Dismiss keyguard due to a user unlock event.
-     */
-    public void finish(boolean strongAuth, int currentUser) {
-        mKeyguardSecurityCallback.finish(strongAuth, currentUser);
-    }
-
-    /**
-     * @return the text of the KeyguardMessageArea.
-     */
-    public CharSequence getTitle() {
-        return mView.getTitle();
-    }
-
-    /**
-     *  Resets the state of the views.
-     */
     public void reset() {
         mView.reset();
         mSecurityViewFlipperController.reset();
     }
 
+    public CharSequence getTitle() {
+        return mView.getTitle();
+    }
+
     @Override
     public void onResume(int reason) {
-        if (DEBUG) Log.d(TAG, "screen on, instance " + Integer.toHexString(hashCode()));
-        mView.requestFocus();
         if (mCurrentSecurityMode != SecurityMode.None) {
             int state = SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__SHOWN;
             if (mView.isSidedSecurityMode()) {
@@ -642,30 +455,6 @@
                 mKeyguardStateController.isFaceAuthEnabled());
     }
 
-    /**
-     * Show the bouncer and start appear animations.
-     *
-     * @param statusBarHeight
-     */
-    public void appear(int statusBarHeight) {
-        // We might still be collapsed and the view didn't have time to layout yet or still
-        // be small, let's wait on the predraw to do the animation in that case.
-        if (mView.getHeight() != 0 && mView.getHeight() != statusBarHeight) {
-            startAppearAnimation();
-        } else {
-            mView.getViewTreeObserver().addOnPreDrawListener(
-                    new ViewTreeObserver.OnPreDrawListener() {
-                        @Override
-                        public boolean onPreDraw() {
-                            mView.getViewTreeObserver().removeOnPreDrawListener(this);
-                            startAppearAnimation();
-                            return true;
-                        }
-                    });
-            mView.requestLayout();
-        }
-    }
-
     public void startAppearAnimation() {
         if (mCurrentSecurityMode != SecurityMode.None) {
             mView.setAlpha(1f);
@@ -677,13 +466,9 @@
     public boolean startDisappearAnimation(Runnable onFinishRunnable) {
         if (mCurrentSecurityMode != SecurityMode.None) {
             mView.startDisappearAnimation(mCurrentSecurityMode);
-            boolean animating = getCurrentSecurityController().startDisappearAnimation(
-                    onFinishRunnable);
-            if (!animating && onFinishRunnable != null) {
-                onFinishRunnable.run();
-            }
-            return animating;
+            return getCurrentSecurityController().startDisappearAnimation(onFinishRunnable);
         }
+
         return false;
     }
 
@@ -799,7 +584,7 @@
             mUiEventLogger.log(uiEvent, getSessionId());
         }
         if (finish) {
-            mKeyguardSecurityCallback.finish(strongAuth, targetUserId);
+            mSecurityCallback.finish(strongAuth, targetUserId);
         }
         return finish;
     }
@@ -812,114 +597,11 @@
      * @return the {@link OnBackAnimationCallback} to animate this view during a back gesture.
      */
     @NonNull
-    public OnBackAnimationCallback getBackCallback() {
+    OnBackAnimationCallback getBackCallback() {
         return mView.getBackCallback();
     }
 
     /**
-     * @return whether we should dispatch the back key event before Ime.
-     */
-    public boolean dispatchBackKeyEventPreIme() {
-        return getCurrentSecurityMode() == SecurityMode.Password;
-    }
-
-    /**
-     * Allows the media keys to work when the keyguard is showing.
-     * The media keys should be of no interest to the actual keyguard view(s),
-     * so intercepting them here should not be of any harm.
-     * @param event The key event
-     * @return whether the event was consumed as a media key.
-     */
-    public boolean interceptMediaKey(KeyEvent event) {
-        int keyCode = event.getKeyCode();
-        if (event.getAction() == KeyEvent.ACTION_DOWN) {
-            switch (keyCode) {
-                case KeyEvent.KEYCODE_MEDIA_PLAY:
-                case KeyEvent.KEYCODE_MEDIA_PAUSE:
-                case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
-                    /* Suppress PLAY/PAUSE toggle when phone is ringing or
-                     * in-call to avoid music playback */
-                    if (mTelephonyManager != null
-                            && mTelephonyManager.getCallState()
-                            != TelephonyManager.CALL_STATE_IDLE) {
-                        return true;  // suppress key event
-                    }
-                    return false;
-                case KeyEvent.KEYCODE_MUTE:
-                case KeyEvent.KEYCODE_HEADSETHOOK:
-                case KeyEvent.KEYCODE_MEDIA_STOP:
-                case KeyEvent.KEYCODE_MEDIA_NEXT:
-                case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
-                case KeyEvent.KEYCODE_MEDIA_REWIND:
-                case KeyEvent.KEYCODE_MEDIA_RECORD:
-                case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
-                case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
-                    handleMediaKeyEvent(event);
-                    return true;
-                }
-
-                case KeyEvent.KEYCODE_VOLUME_UP:
-                case KeyEvent.KEYCODE_VOLUME_DOWN:
-                case KeyEvent.KEYCODE_VOLUME_MUTE: {
-                    if (KEYGUARD_MANAGES_VOLUME) {
-                        // Volume buttons should only function for music (local or remote).
-                        // TODO: Actually handle MUTE.
-                        mAudioManager.adjustSuggestedStreamVolume(
-                                keyCode == KeyEvent.KEYCODE_VOLUME_UP
-                                        ? AudioManager.ADJUST_RAISE
-                                        : AudioManager.ADJUST_LOWER /* direction */,
-                                AudioManager.STREAM_MUSIC /* stream */, 0 /* flags */);
-                        // Don't execute default volume behavior
-                        return true;
-                    } else {
-                        return false;
-                    }
-                }
-            }
-        } else if (event.getAction() == KeyEvent.ACTION_UP) {
-            switch (keyCode) {
-                case KeyEvent.KEYCODE_MUTE:
-                case KeyEvent.KEYCODE_HEADSETHOOK:
-                case KeyEvent.KEYCODE_MEDIA_PLAY:
-                case KeyEvent.KEYCODE_MEDIA_PAUSE:
-                case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
-                case KeyEvent.KEYCODE_MEDIA_STOP:
-                case KeyEvent.KEYCODE_MEDIA_NEXT:
-                case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
-                case KeyEvent.KEYCODE_MEDIA_REWIND:
-                case KeyEvent.KEYCODE_MEDIA_RECORD:
-                case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
-                case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
-                    handleMediaKeyEvent(event);
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-
-    private void handleMediaKeyEvent(KeyEvent keyEvent) {
-        mAudioManager.dispatchMediaKeyEvent(keyEvent);
-    }
-
-    /**
-     * In general, we enable unlocking the insecure keyguard with the menu key. However, there are
-     * some cases where we wish to disable it, notably when the menu button placement or technology
-     * is prone to false positives.
-     *
-     * @return true if the menu key should be enabled
-     */
-    public boolean shouldEnableMenuKey() {
-        final Resources res = mView.getResources();
-        final boolean configDisabled = res.getBoolean(R.bool.config_disableMenuKeyInLockScreen);
-        final boolean isTestHarness = ActivityManager.isRunningInTestHarness();
-        final boolean fileOverride = (new File(ENABLE_MENU_KEY_FILE)).exists();
-        return !configDisabled || isTestHarness || fileOverride;
-    }
-
-
-    /**
      * Switches to the given security view unless it's already being shown, in which case
      * this is a no-op.
      *
@@ -947,7 +629,7 @@
             configureMode();
         }
 
-        mKeyguardSecurityCallback.onSecurityModeChanged(
+        mSecurityCallback.onSecurityModeChanged(
                 securityMode, newView != null && newView.needsInput());
     }
 
@@ -1045,30 +727,6 @@
      * configuration.
      */
     public void updateResources() {
-        int gravity;
-
-        Resources resources = mView.getResources();
-
-        if (resources.getBoolean(R.bool.can_use_one_handed_bouncer)) {
-            gravity = resources.getInteger(
-                    R.integer.keyguard_host_view_one_handed_gravity);
-        } else {
-            gravity = resources.getInteger(R.integer.keyguard_host_view_gravity);
-        }
-
-        mTranslationY = resources
-                .getDimensionPixelSize(R.dimen.keyguard_host_view_translation_y);
-        // Android SysUI uses a FrameLayout as the top-level, but Auto uses RelativeLayout.
-        // We're just changing the gravity here though (which can't be applied to RelativeLayout),
-        // so only attempt the update if mView is inside a FrameLayout.
-        if (mView.getLayoutParams() instanceof FrameLayout.LayoutParams) {
-            FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mView.getLayoutParams();
-            if (lp.gravity != gravity) {
-                lp.gravity = gravity;
-                mView.setLayoutParams(lp);
-            }
-        }
-
         int newOrientation = getResources().getConfiguration().orientation;
         if (newOrientation != mLastOrientation) {
             mLastOrientation = newOrientation;
@@ -1102,15 +760,77 @@
                 mKeyguardSecurityCallback);
     }
 
-    /**
-     * Fades and translates in/out the security screen.
-     * Fades in as expansion approaches 0.
-     * Animation duration is between 0.33f and 0.67f of panel expansion fraction.
-     * @param fraction amount of the screen that should show.
-     */
-    public void setExpansion(float fraction) {
-        float scaledFraction = BouncerPanelExpansionCalculator.showBouncerProgress(fraction);
-        mView.setAlpha(MathUtils.constrain(1 - scaledFraction, 0f, 1f));
-        mView.setTranslationY(scaledFraction * mTranslationY);
+    static class Factory {
+
+        private final KeyguardSecurityContainer mView;
+        private final AdminSecondaryLockScreenController.Factory
+                mAdminSecondaryLockScreenControllerFactory;
+        private final LockPatternUtils mLockPatternUtils;
+        private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+        private final KeyguardSecurityModel mKeyguardSecurityModel;
+        private final MetricsLogger mMetricsLogger;
+        private final UiEventLogger mUiEventLogger;
+        private final KeyguardStateController mKeyguardStateController;
+        private final KeyguardSecurityViewFlipperController mSecurityViewFlipperController;
+        private final ConfigurationController mConfigurationController;
+        private final FalsingCollector mFalsingCollector;
+        private final FalsingManager mFalsingManager;
+        private final GlobalSettings mGlobalSettings;
+        private final FeatureFlags mFeatureFlags;
+        private final UserSwitcherController mUserSwitcherController;
+        private final SessionTracker mSessionTracker;
+        private final Optional<SideFpsController> mSidefpsController;
+        private final FalsingA11yDelegate mFalsingA11yDelegate;
+
+        @Inject
+        Factory(KeyguardSecurityContainer view,
+                AdminSecondaryLockScreenController.Factory
+                        adminSecondaryLockScreenControllerFactory,
+                LockPatternUtils lockPatternUtils,
+                KeyguardUpdateMonitor keyguardUpdateMonitor,
+                KeyguardSecurityModel keyguardSecurityModel,
+                MetricsLogger metricsLogger,
+                UiEventLogger uiEventLogger,
+                KeyguardStateController keyguardStateController,
+                KeyguardSecurityViewFlipperController securityViewFlipperController,
+                ConfigurationController configurationController,
+                FalsingCollector falsingCollector,
+                FalsingManager falsingManager,
+                UserSwitcherController userSwitcherController,
+                FeatureFlags featureFlags,
+                GlobalSettings globalSettings,
+                SessionTracker sessionTracker,
+                Optional<SideFpsController> sidefpsController,
+                FalsingA11yDelegate falsingA11yDelegate) {
+            mView = view;
+            mAdminSecondaryLockScreenControllerFactory = adminSecondaryLockScreenControllerFactory;
+            mLockPatternUtils = lockPatternUtils;
+            mKeyguardUpdateMonitor = keyguardUpdateMonitor;
+            mKeyguardSecurityModel = keyguardSecurityModel;
+            mMetricsLogger = metricsLogger;
+            mUiEventLogger = uiEventLogger;
+            mKeyguardStateController = keyguardStateController;
+            mSecurityViewFlipperController = securityViewFlipperController;
+            mConfigurationController = configurationController;
+            mFalsingCollector = falsingCollector;
+            mFalsingManager = falsingManager;
+            mFeatureFlags = featureFlags;
+            mGlobalSettings = globalSettings;
+            mUserSwitcherController = userSwitcherController;
+            mSessionTracker = sessionTracker;
+            mSidefpsController = sidefpsController;
+            mFalsingA11yDelegate = falsingA11yDelegate;
+        }
+
+        public KeyguardSecurityContainerController create(
+                SecurityCallback securityCallback) {
+            return new KeyguardSecurityContainerController(mView,
+                    mAdminSecondaryLockScreenControllerFactory, mLockPatternUtils,
+                    mKeyguardUpdateMonitor, mKeyguardSecurityModel, mMetricsLogger, mUiEventLogger,
+                    mKeyguardStateController, securityCallback, mSecurityViewFlipperController,
+                    mConfigurationController, mFalsingCollector, mFalsingManager,
+                    mUserSwitcherController, mFeatureFlags, mGlobalSettings, mSessionTracker,
+                    mSidefpsController, mFalsingA11yDelegate);
+        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index f94e182..f491232 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -3749,7 +3749,7 @@
     }
 
     // TODO: use these callbacks elsewhere in place of the existing notifyScreen*()
-    // (KeyguardViewMediator, KeyguardSecurityContainer)
+    // (KeyguardViewMediator, KeyguardHostView)
     /**
      * Dispatch wakeup events to:
      *  - update biometric listening states
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerComponent.java b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerComponent.java
index 154b0ed..5ad21df 100644
--- a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerComponent.java
+++ b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerComponent.java
@@ -18,7 +18,7 @@
 
 import android.view.ViewGroup;
 
-import com.android.keyguard.KeyguardSecurityContainerController;
+import com.android.keyguard.KeyguardHostViewController;
 import com.android.systemui.dagger.qualifiers.RootView;
 import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor;
 
@@ -37,6 +37,6 @@
         KeyguardBouncerComponent create(@BindsInstance @RootView ViewGroup bouncerContainer);
     }
 
-    /** Returns a {@link KeyguardSecurityContainerController}. */
-    KeyguardSecurityContainerController getSecurityContainerController();
+    /** Returns a {@link KeyguardHostViewController}. */
+    KeyguardHostViewController getKeyguardHostViewController();
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java
index 38f252a..cb7a0a9 100644
--- a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java
+++ b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java
@@ -23,6 +23,7 @@
 import android.view.LayoutInflater;
 import android.view.ViewGroup;
 
+import com.android.keyguard.KeyguardHostView;
 import com.android.keyguard.KeyguardSecurityContainer;
 import com.android.keyguard.KeyguardSecurityViewFlipper;
 import com.android.systemui.R;
@@ -46,13 +47,19 @@
     /** */
     @Provides
     @KeyguardBouncerScope
-    static KeyguardSecurityContainer providesKeyguardSecurityContainer(@RootView ViewGroup rootView,
+    static KeyguardHostView providesKeyguardHostView(@RootView ViewGroup rootView,
             LayoutInflater layoutInflater) {
-        KeyguardSecurityContainer securityContainer =
-                (KeyguardSecurityContainer) layoutInflater.inflate(
-                        R.layout.keyguard_security_container_view, rootView, false);
-        rootView.addView(securityContainer);
-        return securityContainer;
+        KeyguardHostView hostView = (KeyguardHostView) layoutInflater.inflate(
+                R.layout.keyguard_host_view, rootView, false);
+        rootView.addView(hostView);
+        return hostView;
+    }
+
+    /** */
+    @Provides
+    @KeyguardBouncerScope
+    static KeyguardSecurityContainer providesKeyguardSecurityContainer(KeyguardHostView hostView) {
+        return hostView.findViewById(R.id.keyguard_security_container);
     }
 
     /** */
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt
index 8a53315..9f09d53 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt
@@ -23,12 +23,10 @@
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.repeatOnLifecycle
 import com.android.internal.policy.SystemBarUtils
-import com.android.keyguard.KeyguardSecurityContainerController
+import com.android.keyguard.KeyguardHostViewController
 import com.android.keyguard.KeyguardSecurityModel
-import com.android.keyguard.KeyguardSecurityView
 import com.android.keyguard.KeyguardUpdateMonitor
 import com.android.keyguard.dagger.KeyguardBouncerComponent
-import com.android.settingslib.Utils
 import com.android.systemui.keyguard.data.BouncerViewDelegate
 import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_VISIBLE
 import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel
@@ -46,54 +44,52 @@
         viewModel: KeyguardBouncerViewModel,
         componentFactory: KeyguardBouncerComponent.Factory
     ) {
-        // Builds the KeyguardSecurityContainerController from bouncer view group.
-        val securityContainerController: KeyguardSecurityContainerController =
-            componentFactory.create(view).securityContainerController
-        securityContainerController.init()
+        // Builds the KeyguardHostViewController from bouncer view group.
+        val hostViewController: KeyguardHostViewController =
+            componentFactory.create(view).keyguardHostViewController
+        hostViewController.init()
         val delegate =
             object : BouncerViewDelegate {
                 override fun isFullScreenBouncer(): Boolean {
-                    val mode = securityContainerController.currentSecurityMode
+                    val mode = hostViewController.currentSecurityMode
                     return mode == KeyguardSecurityModel.SecurityMode.SimPin ||
                         mode == KeyguardSecurityModel.SecurityMode.SimPuk
                 }
 
                 override fun getBackCallback(): OnBackAnimationCallback {
-                    return securityContainerController.backCallback
+                    return hostViewController.backCallback
                 }
 
                 override fun shouldDismissOnMenuPressed(): Boolean {
-                    return securityContainerController.shouldEnableMenuKey()
+                    return hostViewController.shouldEnableMenuKey()
                 }
 
                 override fun interceptMediaKey(event: KeyEvent?): Boolean {
-                    return securityContainerController.interceptMediaKey(event)
+                    return hostViewController.interceptMediaKey(event)
                 }
 
                 override fun dispatchBackKeyEventPreIme(): Boolean {
-                    return securityContainerController.dispatchBackKeyEventPreIme()
+                    return hostViewController.dispatchBackKeyEventPreIme()
                 }
 
                 override fun showNextSecurityScreenOrFinish(): Boolean {
-                    return securityContainerController.dismiss(
-                        KeyguardUpdateMonitor.getCurrentUser()
-                    )
+                    return hostViewController.dismiss(KeyguardUpdateMonitor.getCurrentUser())
                 }
 
                 override fun resume() {
-                    securityContainerController.showPrimarySecurityScreen(/* isTurningOff= */ false)
-                    securityContainerController.onResume(KeyguardSecurityView.SCREEN_ON)
+                    hostViewController.showPrimarySecurityScreen()
+                    hostViewController.onResume()
                 }
 
                 override fun setDismissAction(
                     onDismissAction: ActivityStarter.OnDismissAction?,
                     cancelAction: Runnable?
                 ) {
-                    securityContainerController.setOnDismissAction(onDismissAction, cancelAction)
+                    hostViewController.setOnDismissAction(onDismissAction, cancelAction)
                 }
 
                 override fun willDismissWithActions(): Boolean {
-                    return securityContainerController.hasDismissActions()
+                    return hostViewController.hasDismissActions()
                 }
             }
         view.repeatWhenAttached {
@@ -102,46 +98,39 @@
                     viewModel.setBouncerViewDelegate(delegate)
                     launch {
                         viewModel.show.collect {
-                            securityContainerController.showPromptReason(it.promptReason)
+                            hostViewController.showPromptReason(it.promptReason)
                             it.errorMessage?.let { errorMessage ->
-                                securityContainerController.showMessage(
-                                    errorMessage,
-                                    Utils.getColorError(view.context)
-                                )
+                                hostViewController.showErrorMessage(errorMessage)
                             }
-                            securityContainerController.showPrimarySecurityScreen(
-                                /* turningOff= */ false
-                            )
-                            securityContainerController.appear(
+                            hostViewController.showPrimarySecurityScreen()
+                            hostViewController.appear(
                                 SystemBarUtils.getStatusBarHeight(view.context)
                             )
-                            securityContainerController.onResume(KeyguardSecurityView.SCREEN_ON)
+                            hostViewController.onResume()
                         }
                     }
 
                     launch {
                         viewModel.hide.collect {
-                            securityContainerController.cancelDismissAction()
-                            securityContainerController.onPause()
-                            securityContainerController.reset()
+                            hostViewController.cancelDismissAction()
+                            hostViewController.cleanUp()
+                            hostViewController.resetSecurityContainer()
                         }
                     }
 
                     launch {
-                        viewModel.startingToHide.collect {
-                            securityContainerController.onStartingToHide()
-                        }
+                        viewModel.startingToHide.collect { hostViewController.onStartingToHide() }
                     }
 
                     launch {
                         viewModel.startDisappearAnimation.collect {
-                            securityContainerController.startDisappearAnimation(it)
+                            hostViewController.startDisappearAnimation(it)
                         }
                     }
 
                     launch {
                         viewModel.bouncerExpansionAmount.collect { expansion ->
-                            securityContainerController.setExpansion(expansion)
+                            hostViewController.setExpansion(expansion)
                         }
                     }
 
@@ -149,8 +138,10 @@
                         viewModel.bouncerExpansionAmount
                             .filter { it == EXPANSION_VISIBLE }
                             .collect {
-                                securityContainerController.onResume(KeyguardSecurityView.SCREEN_ON)
-                                view.announceForAccessibility(securityContainerController.title)
+                                hostViewController.onResume()
+                                view.announceForAccessibility(
+                                    hostViewController.accessibilityTitleForCurrentMode
+                                )
                             }
                     }
 
@@ -158,13 +149,13 @@
                         viewModel.isBouncerVisible.collect { isVisible ->
                             val visibility = if (isVisible) View.VISIBLE else View.INVISIBLE
                             view.visibility = visibility
-                            securityContainerController.onBouncerVisibilityChanged(visibility)
+                            hostViewController.onBouncerVisibilityChanged(visibility)
                         }
                     }
 
                     launch {
                         viewModel.isInteractable.collect { isInteractable ->
-                            securityContainerController.setInteractable(isInteractable)
+                            hostViewController.setInteractable(isInteractable)
                         }
                     }
 
@@ -173,36 +164,33 @@
                             .filter { !it }
                             .collect {
                                 // Remove existing input for security reasons.
-                                securityContainerController.reset()
+                                hostViewController.resetSecurityContainer()
                             }
                     }
 
                     launch {
                         viewModel.keyguardPosition.collect { position ->
-                            securityContainerController.updateKeyguardPosition(position)
+                            hostViewController.updateKeyguardPosition(position)
                         }
                     }
 
                     launch {
                         viewModel.updateResources.collect {
-                            securityContainerController.updateResources()
+                            hostViewController.updateResources()
                             viewModel.notifyUpdateResources()
                         }
                     }
 
                     launch {
                         viewModel.bouncerShowMessage.collect {
-                            securityContainerController.showMessage(it.message, it.colorStateList)
+                            hostViewController.showMessage(it.message, it.colorStateList)
                             viewModel.onMessageShown()
                         }
                     }
 
                     launch {
                         viewModel.keyguardAuthenticated.collect {
-                            securityContainerController.finish(
-                                it,
-                                KeyguardUpdateMonitor.getCurrentUser()
-                            )
+                            hostViewController.finish(it, KeyguardUpdateMonitor.getCurrentUser())
                             viewModel.notifyKeyguardAuthenticated()
                         }
                     }
@@ -216,7 +204,7 @@
                     launch {
                         viewModel.screenTurnedOff.collect {
                             if (view.visibility == View.VISIBLE) {
-                                securityContainerController.onPause()
+                                hostViewController.onPause()
                             }
                         }
                     }
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardHostViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardHostViewControllerTest.java
new file mode 100644
index 0000000..4021652
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardHostViewControllerTest.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.keyguard;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.media.AudioManager;
+import android.telephony.TelephonyManager;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.testing.TestableResources;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class KeyguardHostViewControllerTest extends SysuiTestCase {
+    @Mock
+    private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+
+    private KeyguardHostView mKeyguardHostView;
+    @Mock
+    private AudioManager mAudioManager;
+    @Mock
+    private TelephonyManager mTelephonyManager;
+    @Mock
+    private ViewMediatorCallback mViewMediatorCallback;
+    @Mock
+    KeyguardSecurityContainerController.Factory mKeyguardSecurityContainerControllerFactory;
+    @Mock
+    private KeyguardSecurityContainerController mKeyguardSecurityContainerController;
+
+    @Rule
+    public MockitoRule mMockitoRule = MockitoJUnit.rule();
+
+    private TestableResources mTestableResources;
+    private KeyguardHostViewController mKeyguardHostViewController;
+
+    @Before
+    public void setup() {
+        mTestableResources = mContext.getOrCreateTestableResources();
+
+        mKeyguardHostView = new KeyguardHostView(mContext);
+
+        // Explicitly disable one handed keyguard.
+        mTestableResources.addOverride(
+                R.bool.can_use_one_handed_bouncer, false);
+
+        when(mKeyguardSecurityContainerControllerFactory.create(any(
+                KeyguardSecurityContainer.SecurityCallback.class)))
+                .thenReturn(mKeyguardSecurityContainerController);
+        mKeyguardHostViewController = new KeyguardHostViewController(
+                mKeyguardHostView, mKeyguardUpdateMonitor, mAudioManager, mTelephonyManager,
+                mViewMediatorCallback, mKeyguardSecurityContainerControllerFactory);
+    }
+
+    @Test
+    public void testHasDismissActions() {
+        assertFalse("Action not set yet", mKeyguardHostViewController.hasDismissActions());
+        mKeyguardHostViewController.setOnDismissAction(mock(OnDismissAction.class),
+                null /* cancelAction */);
+        assertTrue("Action should exist", mKeyguardHostViewController.hasDismissActions());
+    }
+
+    @Test
+    public void testOnStartingToHide() {
+        mKeyguardHostViewController.onStartingToHide();
+        verify(mKeyguardSecurityContainerController).onStartingToHide();
+    }
+
+    @Test
+    public void onBouncerVisible_propagatesToKeyguardSecurityContainerController() {
+        mKeyguardHostViewController.onBouncerVisibilityChanged(ViewGroup.VISIBLE);
+        mKeyguardHostViewController.onBouncerVisibilityChanged(ViewGroup.INVISIBLE);
+
+        InOrder order = inOrder(mKeyguardSecurityContainerController);
+        order.verify(mKeyguardSecurityContainerController).onBouncerVisibilityChanged(View.VISIBLE);
+        order.verify(mKeyguardSecurityContainerController).onBouncerVisibilityChanged(
+                View.INVISIBLE);
+    }
+
+    @Test
+    public void testGravityReappliedOnConfigurationChange() {
+        FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                ViewGroup.LayoutParams.MATCH_PARENT);
+        mKeyguardHostView.setLayoutParams(lp);
+
+        // Set initial gravity
+        mTestableResources.addOverride(R.integer.keyguard_host_view_gravity,
+                Gravity.CENTER);
+
+        // Kick off the initial pass...
+        mKeyguardHostViewController.init();
+        assertEquals(
+                ((FrameLayout.LayoutParams) mKeyguardHostView.getLayoutParams()).gravity,
+                Gravity.CENTER);
+
+        // Now simulate a config change
+        mTestableResources.addOverride(R.integer.keyguard_host_view_gravity,
+                Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
+
+        mKeyguardHostViewController.updateResources();
+        assertEquals(
+                ((FrameLayout.LayoutParams) mKeyguardHostView.getLayoutParams()).gravity,
+                Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
+    }
+
+    @Test
+    public void testGravityUsesOneHandGravityWhenApplicable() {
+        FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                ViewGroup.LayoutParams.MATCH_PARENT);
+        mKeyguardHostView.setLayoutParams(lp);
+
+        mTestableResources.addOverride(
+                R.integer.keyguard_host_view_gravity,
+                Gravity.CENTER);
+        mTestableResources.addOverride(
+                R.integer.keyguard_host_view_one_handed_gravity,
+                Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
+
+        // Start disabled.
+        mTestableResources.addOverride(
+                R.bool.can_use_one_handed_bouncer, false);
+
+        mKeyguardHostViewController.init();
+        assertEquals(
+                ((FrameLayout.LayoutParams) mKeyguardHostView.getLayoutParams()).gravity,
+                Gravity.CENTER);
+
+        // And enable
+        mTestableResources.addOverride(
+                R.bool.can_use_one_handed_bouncer, true);
+
+        mKeyguardHostViewController.updateResources();
+        assertEquals(
+                ((FrameLayout.LayoutParams) mKeyguardHostView.getLayoutParams()).gravity,
+                Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
+    }
+
+    @Test
+    public void testUpdateKeyguardPositionDelegatesToSecurityContainer() {
+        mKeyguardHostViewController.updateKeyguardPosition(1.0f);
+
+        verify(mKeyguardSecurityContainerController).updateKeyguardPosition(1.0f);
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
index 80e9e32..0d65f12 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
@@ -23,17 +23,12 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertTrue;
-
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyLong;
-import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.atLeastOnce;
-import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
@@ -44,17 +39,12 @@
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.hardware.biometrics.BiometricSourceType;
-import android.media.AudioManager;
-import android.telephony.TelephonyManager;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
-import android.testing.TestableResources;
-import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.WindowInsetsController;
-import android.widget.FrameLayout;
 
 import androidx.test.filters.SmallTest;
 
@@ -70,7 +60,6 @@
 import com.android.systemui.classifier.FalsingCollector;
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.log.SessionTracker;
-import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -82,7 +71,6 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
-import org.mockito.ArgumentMatcher;
 import org.mockito.Captor;
 import org.mockito.Mock;
 import org.mockito.junit.MockitoJUnit;
@@ -120,6 +108,8 @@
     @Mock
     private KeyguardInputViewController mInputViewController;
     @Mock
+    private KeyguardSecurityContainer.SecurityCallback mSecurityCallback;
+    @Mock
     private WindowInsetsController mWindowInsetsController;
     @Mock
     private KeyguardSecurityViewFlipper mSecurityViewFlipper;
@@ -136,6 +126,8 @@
     @Mock
     private EmergencyButtonController mEmergencyButtonController;
     @Mock
+    private Resources mResources;
+    @Mock
     private FalsingCollector mFalsingCollector;
     @Mock
     private FalsingManager mFalsingManager;
@@ -155,12 +147,6 @@
     private KeyguardPasswordViewController mKeyguardPasswordViewControllerMock;
     @Mock
     private FalsingA11yDelegate mFalsingA11yDelegate;
-    @Mock
-    private TelephonyManager mTelephonyManager;
-    @Mock
-    private ViewMediatorCallback mViewMediatorCallback;
-    @Mock
-    private AudioManager mAudioManager;
 
     @Captor
     private ArgumentCaptor<KeyguardUpdateMonitorCallback> mKeyguardUpdateMonitorCallback;
@@ -172,25 +158,18 @@
     private KeyguardSecurityContainerController mKeyguardSecurityContainerController;
     private KeyguardPasswordViewController mKeyguardPasswordViewController;
     private KeyguardPasswordView mKeyguardPasswordView;
-    private TestableResources mTestableResources;
 
     @Before
     public void setup() {
         mConfiguration = new Configuration();
         mConfiguration.setToDefaults(); // Defaults to ORIENTATION_UNDEFINED.
-        mTestableResources = mContext.getOrCreateTestableResources();
 
+        when(mResources.getConfiguration()).thenReturn(mConfiguration);
         when(mView.getContext()).thenReturn(mContext);
-        when(mView.getResources()).thenReturn(mContext.getResources());
-        FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(/* width=  */ 0, /* height= */
-                0);
-        lp.gravity = 0;
-        when(mView.getLayoutParams()).thenReturn(lp);
+        when(mView.getResources()).thenReturn(mResources);
         when(mAdminSecondaryLockScreenControllerFactory.create(any(KeyguardSecurityCallback.class)))
                 .thenReturn(mAdminSecondaryLockScreenController);
         when(mSecurityViewFlipper.getWindowInsetsController()).thenReturn(mWindowInsetsController);
-        when(mKeyguardSecurityViewFlipperController.getSecurityView(any(SecurityMode.class),
-                any(KeyguardSecurityCallback.class))).thenReturn(mInputViewController);
         mKeyguardPasswordView = spy((KeyguardPasswordView) LayoutInflater.from(mContext).inflate(
                 R.layout.keyguard_password_view, null));
         when(mKeyguardPasswordView.getRootView()).thenReturn(mSecurityViewFlipper);
@@ -199,21 +178,20 @@
         when(mKeyguardMessageAreaControllerFactory.create(any(KeyguardMessageArea.class)))
                 .thenReturn(mKeyguardMessageAreaController);
         when(mKeyguardPasswordView.getWindowInsetsController()).thenReturn(mWindowInsetsController);
-        when(mKeyguardSecurityModel.getSecurityMode(anyInt())).thenReturn(SecurityMode.PIN);
         mKeyguardPasswordViewController = new KeyguardPasswordViewController(
                 (KeyguardPasswordView) mKeyguardPasswordView, mKeyguardUpdateMonitor,
                 SecurityMode.Password, mLockPatternUtils, null,
                 mKeyguardMessageAreaControllerFactory, null, null, mEmergencyButtonController,
                 null, mock(Resources.class), null, mKeyguardViewController);
 
-        mKeyguardSecurityContainerController = new KeyguardSecurityContainerController(
+        mKeyguardSecurityContainerController = new KeyguardSecurityContainerController.Factory(
                 mView, mAdminSecondaryLockScreenControllerFactory, mLockPatternUtils,
                 mKeyguardUpdateMonitor, mKeyguardSecurityModel, mMetricsLogger, mUiEventLogger,
                 mKeyguardStateController, mKeyguardSecurityViewFlipperController,
                 mConfigurationController, mFalsingCollector, mFalsingManager,
                 mUserSwitcherController, mFeatureFlags, mGlobalSettings,
-                mSessionTracker, Optional.of(mSideFpsController), mFalsingA11yDelegate,
-                mTelephonyManager, mViewMediatorCallback, mAudioManager);
+                mSessionTracker, Optional.of(mSideFpsController), mFalsingA11yDelegate).create(
+                mSecurityCallback);
     }
 
     @Test
@@ -265,8 +243,7 @@
                 eq(mFalsingA11yDelegate));
 
         // Update rotation. Should trigger update
-        mTestableResources.getResources().getConfiguration().orientation =
-                Configuration.ORIENTATION_LANDSCAPE;
+        mConfiguration.orientation = Configuration.ORIENTATION_LANDSCAPE;
 
         mKeyguardSecurityContainerController.updateResources();
         verify(mView).initMode(eq(MODE_DEFAULT), eq(mGlobalSettings), eq(mFalsingManager),
@@ -300,7 +277,7 @@
 
     @Test
     public void showSecurityScreen_oneHandedMode_flagDisabled_noOneHandedMode() {
-        mTestableResources.addOverride(R.bool.can_use_one_handed_bouncer, false);
+        when(mResources.getBoolean(R.bool.can_use_one_handed_bouncer)).thenReturn(false);
         when(mKeyguardSecurityViewFlipperController.getSecurityView(
                 eq(SecurityMode.Pattern), any(KeyguardSecurityCallback.class)))
                 .thenReturn((KeyguardInputViewController) mKeyguardPasswordViewController);
@@ -314,7 +291,7 @@
 
     @Test
     public void showSecurityScreen_oneHandedMode_flagEnabled_oneHandedMode() {
-        mTestableResources.addOverride(R.bool.can_use_one_handed_bouncer, true);
+        when(mResources.getBoolean(R.bool.can_use_one_handed_bouncer)).thenReturn(true);
         when(mKeyguardSecurityViewFlipperController.getSecurityView(
                 eq(SecurityMode.Pattern), any(KeyguardSecurityCallback.class)))
                 .thenReturn((KeyguardInputViewController) mKeyguardPasswordViewController);
@@ -328,7 +305,7 @@
 
     @Test
     public void showSecurityScreen_twoHandedMode_flagEnabled_noOneHandedMode() {
-        mTestableResources.addOverride(R.bool.can_use_one_handed_bouncer, true);
+        when(mResources.getBoolean(R.bool.can_use_one_handed_bouncer)).thenReturn(true);
         setupGetSecurityView();
 
         mKeyguardSecurityContainerController.showSecurityScreen(SecurityMode.Password);
@@ -505,9 +482,7 @@
                 SecurityMode.SimPin);
 
         // THEN the next security method of PIN is set, and the keyguard is not marked as done
-
-        verify(mViewMediatorCallback, never()).keyguardDonePending(anyBoolean(), anyInt());
-        verify(mViewMediatorCallback, never()).keyguardDone(anyBoolean(), anyInt());
+        verify(mSecurityCallback, never()).finish(anyBoolean(), anyInt());
         assertThat(mKeyguardSecurityContainerController.getCurrentSecurityMode())
                 .isEqualTo(SecurityMode.PIN);
     }
@@ -581,19 +556,17 @@
     }
 
     @Test
-    public void onDensityOrFontScaleChanged() {
+    public void onDensityorFontScaleChanged() {
         ArgumentCaptor<ConfigurationController.ConfigurationListener>
                 configurationListenerArgumentCaptor = ArgumentCaptor.forClass(
                 ConfigurationController.ConfigurationListener.class);
         mKeyguardSecurityContainerController.onViewAttached();
         verify(mConfigurationController).addCallback(configurationListenerArgumentCaptor.capture());
-        clearInvocations(mKeyguardSecurityViewFlipperController);
-
         configurationListenerArgumentCaptor.getValue().onDensityOrFontScaleChanged();
 
         verify(mView).onDensityOrFontScaleChanged();
         verify(mKeyguardSecurityViewFlipperController).clearViews();
-        verify(mKeyguardSecurityViewFlipperController).getSecurityView(eq(SecurityMode.PIN),
+        verify(mKeyguardSecurityViewFlipperController).getSecurityView(any(SecurityMode.class),
                 any(KeyguardSecurityCallback.class));
     }
 
@@ -604,13 +577,11 @@
                 ConfigurationController.ConfigurationListener.class);
         mKeyguardSecurityContainerController.onViewAttached();
         verify(mConfigurationController).addCallback(configurationListenerArgumentCaptor.capture());
-        clearInvocations(mKeyguardSecurityViewFlipperController);
-
         configurationListenerArgumentCaptor.getValue().onThemeChanged();
 
         verify(mView).reloadColors();
         verify(mKeyguardSecurityViewFlipperController).clearViews();
-        verify(mKeyguardSecurityViewFlipperController).getSecurityView(eq(SecurityMode.PIN),
+        verify(mKeyguardSecurityViewFlipperController).getSecurityView(any(SecurityMode.class),
                 any(KeyguardSecurityCallback.class));
         verify(mView).reset();
         verify(mKeyguardSecurityViewFlipperController).reset();
@@ -623,90 +594,14 @@
                 ConfigurationController.ConfigurationListener.class);
         mKeyguardSecurityContainerController.onViewAttached();
         verify(mConfigurationController).addCallback(configurationListenerArgumentCaptor.capture());
-        clearInvocations(mKeyguardSecurityViewFlipperController);
-
         configurationListenerArgumentCaptor.getValue().onUiModeChanged();
 
         verify(mView).reloadColors();
         verify(mKeyguardSecurityViewFlipperController).clearViews();
-        verify(mKeyguardSecurityViewFlipperController).getSecurityView(eq(SecurityMode.PIN),
+        verify(mKeyguardSecurityViewFlipperController).getSecurityView(any(SecurityMode.class),
                 any(KeyguardSecurityCallback.class));
     }
 
-    @Test
-    public void testHasDismissActions() {
-        assertFalse("Action not set yet", mKeyguardSecurityContainerController.hasDismissActions());
-        mKeyguardSecurityContainerController.setOnDismissAction(mock(
-                        ActivityStarter.OnDismissAction.class),
-                null /* cancelAction */);
-        assertTrue("Action should exist", mKeyguardSecurityContainerController.hasDismissActions());
-    }
-
-    @Test
-    public void testOnStartingToHide() {
-        mKeyguardSecurityContainerController.onStartingToHide();
-        verify(mInputViewController).onStartingToHide();
-    }
-
-    @Test
-    public void testGravityReappliedOnConfigurationChange() {
-        // Set initial gravity
-        mTestableResources.addOverride(R.integer.keyguard_host_view_gravity,
-                Gravity.CENTER);
-
-        // Kick off the initial pass...
-        mKeyguardSecurityContainerController.onInit();
-        verify(mView).setLayoutParams(argThat(
-                (ArgumentMatcher<FrameLayout.LayoutParams>) argument ->
-                        argument.gravity == Gravity.CENTER));
-        clearInvocations(mView);
-
-        // Now simulate a config change
-        mTestableResources.addOverride(R.integer.keyguard_host_view_gravity,
-                Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
-
-        mKeyguardSecurityContainerController.updateResources();
-        verify(mView).setLayoutParams(argThat(
-                (ArgumentMatcher<FrameLayout.LayoutParams>) argument ->
-                        argument.gravity == (Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM)));
-    }
-
-    @Test
-    public void testGravityUsesOneHandGravityWhenApplicable() {
-        mTestableResources.addOverride(
-                R.integer.keyguard_host_view_gravity,
-                Gravity.CENTER);
-        mTestableResources.addOverride(
-                R.integer.keyguard_host_view_one_handed_gravity,
-                Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
-
-        // Start disabled.
-        mTestableResources.addOverride(
-                R.bool.can_use_one_handed_bouncer, false);
-
-        mKeyguardSecurityContainerController.onInit();
-        verify(mView).setLayoutParams(argThat(
-                (ArgumentMatcher<FrameLayout.LayoutParams>) argument ->
-                        argument.gravity == Gravity.CENTER));
-        clearInvocations(mView);
-
-        // And enable
-        mTestableResources.addOverride(
-                R.bool.can_use_one_handed_bouncer, true);
-
-        mKeyguardSecurityContainerController.updateResources();
-        verify(mView).setLayoutParams(argThat(
-                (ArgumentMatcher<FrameLayout.LayoutParams>) argument ->
-                        argument.gravity == (Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM)));
-    }
-
-    @Test
-    public void testUpdateKeyguardPositionDelegatesToSecurityContainer() {
-        mKeyguardSecurityContainerController.updateKeyguardPosition(1.0f);
-        verify(mView).updatePositionByTouchX(1.0f);
-    }
-
-
     private KeyguardSecurityContainer.SwipeListener getRegisteredSwipeListener() {
         mKeyguardSecurityContainerController.onViewAttached();
         verify(mView).setSwipeListener(mSwipeListenerArgumentCaptor.capture());
@@ -732,7 +627,7 @@
     }
 
     private void setSideFpsHintEnabledFromResources(boolean enabled) {
-        mTestableResources.addOverride(R.bool.config_show_sidefps_hint_on_bouncer,
+        when(mResources.getBoolean(R.bool.config_show_sidefps_hint_on_bouncer)).thenReturn(
                 enabled);
     }
 
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..e5d5e3b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
@@ -21,7 +21,7 @@
 import android.view.MotionEvent
 import android.view.ViewGroup
 import androidx.test.filters.SmallTest
-import com.android.keyguard.KeyguardSecurityContainerController
+import com.android.keyguard.KeyguardHostViewController
 import com.android.keyguard.LockIconViewController
 import com.android.keyguard.dagger.KeyguardBouncerComponent
 import com.android.systemui.R
@@ -106,7 +106,7 @@
     private lateinit var alternateBouncerInteractor: AlternateBouncerInteractor
     @Mock lateinit var keyguardBouncerComponentFactory: KeyguardBouncerComponent.Factory
     @Mock lateinit var keyguardBouncerComponent: KeyguardBouncerComponent
-    @Mock lateinit var keyguardSecurityContainerController: KeyguardSecurityContainerController
+    @Mock lateinit var keyguardHostViewController: KeyguardHostViewController
     @Mock lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor
 
     private lateinit var interactionEventHandlerCaptor: ArgumentCaptor<InteractionEventHandler>
@@ -122,8 +122,8 @@
                 .thenReturn(mock(ViewGroup::class.java))
         whenever(keyguardBouncerComponentFactory.create(any(ViewGroup::class.java)))
                 .thenReturn(keyguardBouncerComponent)
-        whenever(keyguardBouncerComponent.securityContainerController)
-                .thenReturn(keyguardSecurityContainerController)
+        whenever(keyguardBouncerComponent.keyguardHostViewController)
+                .thenReturn(keyguardHostViewController)
         underTest = NotificationShadeWindowViewController(
             lockscreenShadeTransitionController,
             FalsingCollectorFake(),
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..5cc3ef1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java
@@ -33,7 +33,7 @@
 
 import androidx.test.filters.SmallTest;
 
-import com.android.keyguard.KeyguardSecurityContainerController;
+import com.android.keyguard.KeyguardHostViewController;
 import com.android.keyguard.LockIconViewController;
 import com.android.keyguard.dagger.KeyguardBouncerComponent;
 import com.android.systemui.R;
@@ -97,7 +97,7 @@
     @Mock private KeyguardBouncerViewModel mKeyguardBouncerViewModel;
     @Mock private KeyguardBouncerComponent.Factory mKeyguardBouncerComponentFactory;
     @Mock private KeyguardBouncerComponent mKeyguardBouncerComponent;
-    @Mock private KeyguardSecurityContainerController mKeyguardSecurityContainerController;
+    @Mock private KeyguardHostViewController mKeyguardHostViewController;
     @Mock private NotificationInsetsController mNotificationInsetsController;
     @Mock private AlternateBouncerInteractor mAlternateBouncerInteractor;
     @Mock private KeyguardTransitionInteractor mKeyguardTransitionInteractor;
@@ -117,8 +117,8 @@
         when(mView.findViewById(R.id.keyguard_bouncer_container)).thenReturn(mock(ViewGroup.class));
         when(mKeyguardBouncerComponentFactory.create(any(ViewGroup.class))).thenReturn(
                 mKeyguardBouncerComponent);
-        when(mKeyguardBouncerComponent.getSecurityContainerController()).thenReturn(
-                mKeyguardSecurityContainerController);
+        when(mKeyguardBouncerComponent.getKeyguardHostViewController()).thenReturn(
+                mKeyguardHostViewController);
 
         when(mStatusBarStateController.isDozing()).thenReturn(false);
         mDependency.injectTestDependency(ShadeController.class, mShadeController);