Merge "Bouncer cleanup"
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_bouncer.xml b/packages/SystemUI/res-keyguard/layout/keyguard_bouncer.xml
deleted file mode 100644
index 384e02d..0000000
--- a/packages/SystemUI/res-keyguard/layout/keyguard_bouncer.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?><!--
-  ~ Copyright (C) 2014 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
-  -->
-
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:background="@android:color/transparent"
-    android:clipChildren="false"
-    android:clipToPadding="false">
-
-    <include
-        layout="@layout/keyguard_host_view"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content" />
-</FrameLayout>
-
diff --git a/packages/SystemUI/res/layout/super_notification_shade.xml b/packages/SystemUI/res/layout/super_notification_shade.xml
index b28cb2f..60860ba 100644
--- a/packages/SystemUI/res/layout/super_notification_shade.xml
+++ b/packages/SystemUI/res/layout/super_notification_shade.xml
@@ -101,7 +101,10 @@
         <FrameLayout android:id="@+id/keyguard_bouncer_container"
                      android:layout_height="0dp"
                      android:layout_width="match_parent"
-                     android:layout_weight="1" />
+                     android:layout_weight="1"
+                     android:background="@android:color/transparent"
+                     android:clipChildren="false"
+                     android:clipToPadding="false" />
     </LinearLayout>
 
     <com.android.systemui.biometrics.AuthRippleView
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardRootViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardRootViewController.java
deleted file mode 100644
index 4e375c2..0000000
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardRootViewController.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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.view.ViewGroup;
-
-import com.android.keyguard.dagger.KeyguardBouncerScope;
-import com.android.systemui.dagger.qualifiers.RootView;
-import com.android.systemui.statusbar.phone.KeyguardBouncer;
-import com.android.systemui.util.ViewController;
-
-import javax.inject.Inject;
-/** Controller for a {@link KeyguardBouncer}'s Root view. */
-@KeyguardBouncerScope
-public class KeyguardRootViewController extends ViewController<ViewGroup> {
-    @Inject
-    public KeyguardRootViewController(@RootView ViewGroup view) {
-        super(view);
-    }
-
-    public ViewGroup getView() {
-        return mView;
-    }
-
-    @Override
-    protected void onViewAttached() {
-
-    }
-
-    @Override
-    protected void onViewDetached() {
-
-    }
-}
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerComponent.java b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerComponent.java
index 5160b7e..0cbf8bc 100644
--- a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerComponent.java
+++ b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerComponent.java
@@ -16,10 +16,13 @@
 
 package com.android.keyguard.dagger;
 
+import android.view.ViewGroup;
+
 import com.android.keyguard.KeyguardHostViewController;
-import com.android.keyguard.KeyguardRootViewController;
+import com.android.systemui.dagger.qualifiers.RootView;
 import com.android.systemui.statusbar.phone.KeyguardBouncer;
 
+import dagger.BindsInstance;
 import dagger.Subcomponent;
 
 /**
@@ -31,12 +34,9 @@
     /** Simple factory for {@link KeyguardBouncerComponent}. */
     @Subcomponent.Factory
     interface Factory {
-        KeyguardBouncerComponent create();
+        KeyguardBouncerComponent create(@BindsInstance @RootView ViewGroup bouncerContainer);
     }
 
-    /** Returns a {@link KeyguardRootViewController}. */
-    KeyguardRootViewController getKeyguardRootViewController();
-
     /** 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 4fad9a9..b3c1158 100644
--- a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java
+++ b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java
@@ -20,7 +20,6 @@
 import android.view.ViewGroup;
 
 import com.android.keyguard.KeyguardHostView;
-import com.android.keyguard.KeyguardMessageArea;
 import com.android.keyguard.KeyguardSecurityContainer;
 import com.android.keyguard.KeyguardSecurityViewFlipper;
 import com.android.systemui.R;
@@ -35,26 +34,16 @@
  */
 @Module
 public interface KeyguardBouncerModule {
-    /** */
-    @Provides
-    @KeyguardBouncerScope
-    @RootView
-    static ViewGroup providesRootView(LayoutInflater layoutInflater) {
-        return (ViewGroup) layoutInflater.inflate(R.layout.keyguard_bouncer, null);
-    }
 
     /** */
     @Provides
     @KeyguardBouncerScope
-    static KeyguardMessageArea providesKeyguardMessageArea(@RootView ViewGroup viewGroup) {
-        return viewGroup.findViewById(R.id.keyguard_message_area);
-    }
-
-    /** */
-    @Provides
-    @KeyguardBouncerScope
-    static KeyguardHostView providesKeyguardHostView(@RootView ViewGroup rootView) {
-        return rootView.findViewById(R.id.keyguard_host_view);
+    static KeyguardHostView providesKeyguardHostView(@RootView ViewGroup rootView,
+            LayoutInflater layoutInflater) {
+        KeyguardHostView hostView = (KeyguardHostView) layoutInflater.inflate(
+                R.layout.keyguard_host_view, rootView, false);
+        rootView.addView(hostView);
+        return hostView;
     }
 
     /** */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index 9647486..565b2d3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -33,7 +33,6 @@
 
 import com.android.internal.policy.SystemBarUtils;
 import com.android.keyguard.KeyguardHostViewController;
-import com.android.keyguard.KeyguardRootViewController;
 import com.android.keyguard.KeyguardSecurityModel;
 import com.android.keyguard.KeyguardSecurityView;
 import com.android.keyguard.KeyguardUpdateMonitor;
@@ -42,7 +41,6 @@
 import com.android.keyguard.dagger.KeyguardBouncerComponent;
 import com.android.systemui.DejankUtils;
 import com.android.systemui.classifier.FalsingCollector;
-import com.android.systemui.dagger.qualifiers.RootView;
 import com.android.systemui.keyguard.DismissCallbackRegistry;
 import com.android.systemui.shared.system.SysUiStatsLog;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -105,12 +103,11 @@
 
     private int mStatusBarHeight;
     private float mExpansion = EXPANSION_HIDDEN;
-    protected ViewGroup mRoot;
-    private KeyguardRootViewController mRootViewController;
     private boolean mShowingSoon;
     private int mBouncerPromptReason;
     private boolean mIsAnimatingAway;
     private boolean mIsScrimmed;
+    private boolean mInitialized;
 
     private KeyguardBouncer(Context context, ViewMediatorCallback callback,
             ViewGroup container,
@@ -184,7 +181,7 @@
             showPrimarySecurityScreen();
         }
 
-        if (mRoot.getVisibility() == View.VISIBLE || mShowingSoon) {
+        if (mContainer.getVisibility() == View.VISIBLE || mShowingSoon) {
             return;
         }
 
@@ -235,10 +232,8 @@
             Log.wtf(TAG, "onFullyShown when view was null");
         } else {
             mKeyguardViewController.onResume();
-            if (mRoot != null) {
-                mRoot.announceForAccessibility(
-                        mKeyguardViewController.getAccessibilityTitleForCurrentMode());
-            }
+            mContainer.announceForAccessibility(
+                    mKeyguardViewController.getAccessibilityTitleForCurrentMode());
         }
     }
 
@@ -253,10 +248,8 @@
     }
 
     private void setVisibility(@View.Visibility int visibility) {
-        if (mRoot != null) {
-            mRoot.setVisibility(visibility);
-            dispatchVisibilityChanged();
-        }
+        mContainer.setVisibility(visibility);
+        dispatchVisibilityChanged();
     }
 
     private final Runnable mShowRunnable = new Runnable() {
@@ -337,14 +330,12 @@
             mKeyguardViewController.cleanUp();
         }
         mIsAnimatingAway = false;
-        if (mRoot != null) {
-            setVisibility(View.INVISIBLE);
-            if (destroyView) {
+        setVisibility(View.INVISIBLE);
+        if (destroyView) {
 
-                // We have a ViewFlipper that unregisters a broadcast when being detached, which may
-                // be slow because of AM lock contention during unlocking. We can delay it a bit.
-                mHandler.postDelayed(mRemoveViewRunnable, 50);
-            }
+            // We have a ViewFlipper that unregisters a broadcast when being detached, which may
+            // be slow because of AM lock contention during unlocking. We can delay it a bit.
+            mHandler.postDelayed(mRemoveViewRunnable, 50);
         }
     }
 
@@ -370,14 +361,13 @@
     }
 
     public void onScreenTurnedOff() {
-        if (mKeyguardViewController != null
-                && mRoot != null && mRoot.getVisibility() == View.VISIBLE) {
+        if (mKeyguardViewController != null && mContainer.getVisibility() == View.VISIBLE) {
             mKeyguardViewController.onPause();
         }
     }
 
     public boolean isShowing() {
-        return (mShowingSoon || (mRoot != null && mRoot.getVisibility() == View.VISIBLE))
+        return (mShowingSoon || mContainer.getVisibility() == View.VISIBLE)
                 && mExpansion == EXPANSION_VISIBLE && !isAnimatingAway();
     }
 
@@ -401,7 +391,7 @@
     }
 
     public void prepare() {
-        boolean wasInitialized = mRoot != null;
+        boolean wasInitialized = mInitialized;
         ensureView();
         if (wasInitialized) {
             showPrimarySecurityScreen();
@@ -461,7 +451,7 @@
         // in this case we need to force the removal, otherwise we'll
         // end up in an unpredictable state.
         boolean forceRemoval = mHandler.hasCallbacks(mRemoveViewRunnable);
-        if (mRoot == null || forceRemoval) {
+        if (!mInitialized || forceRemoval) {
             inflateView();
         }
     }
@@ -469,28 +459,24 @@
     protected void inflateView() {
         removeView();
         mHandler.removeCallbacks(mRemoveViewRunnable);
-        KeyguardBouncerComponent component = mKeyguardBouncerComponentFactory.create();
-        mRootViewController = component.getKeyguardRootViewController();
-        mRootViewController.init();
-        mRoot = mRootViewController.getView();  // TODO(b/166448040): Don't access root view here.
+
+        KeyguardBouncerComponent component = mKeyguardBouncerComponentFactory.create(mContainer);
         mKeyguardViewController = component.getKeyguardHostViewController();
         mKeyguardViewController.init();
 
-        mContainer.addView(mRoot, mContainer.getChildCount());
         mStatusBarHeight = SystemBarUtils.getStatusBarHeight(mContext);
         setVisibility(View.INVISIBLE);
 
-        final WindowInsets rootInsets = mRoot.getRootWindowInsets();
+        final WindowInsets rootInsets = mContainer.getRootWindowInsets();
         if (rootInsets != null) {
-            mRoot.dispatchApplyWindowInsets(rootInsets);
+            mContainer.dispatchApplyWindowInsets(rootInsets);
         }
+        mInitialized = true;
     }
 
     protected void removeView() {
-        if (mRoot != null && mRoot.getParent() == mContainer) {
-            mContainer.removeView(mRoot);
-            mRoot = null;
-        }
+        mContainer.removeAllViews();
+        mInitialized = false;
     }
 
     /**
@@ -577,7 +563,7 @@
 
     private void dispatchVisibilityChanged() {
         for (BouncerExpansionCallback callback : mExpansionCallbacks) {
-            callback.onVisibilityChanged(mRoot.getVisibility() == View.VISIBLE);
+            callback.onVisibilityChanged(mContainer.getVisibility() == View.VISIBLE);
         }
     }
 
@@ -601,6 +587,7 @@
         pw.println("  mShowingSoon: " + mShowingSoon);
         pw.println("  mBouncerPromptReason: " + mBouncerPromptReason);
         pw.println("  mIsAnimatingAway: " + mIsAnimatingAway);
+        pw.println("  mInitialized: " + mInitialized);
     }
 
     /** Update keyguard position based on a tapped X coordinate. */
@@ -675,7 +662,10 @@
             mKeyguardBouncerComponentFactory = keyguardBouncerComponentFactory;
         }
 
-        public KeyguardBouncer create(@RootView ViewGroup container,
+        /**
+         * Construct a KeyguardBouncer that will exist in the given container.
+         */
+        public KeyguardBouncer create(ViewGroup container,
                 BouncerExpansionCallback expansionCallback) {
             return new KeyguardBouncer(mContext, mCallback, container,
                     mDismissCallbackRegistry, mFalsingCollector, expansionCallback,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 875b7e5..316e682 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -51,7 +51,6 @@
 import com.android.systemui.DejankUtils;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dock.DockManager;
-import com.android.systemui.keyguard.WakefulnessLifecycle;
 import com.android.systemui.navigationbar.NavigationBarView;
 import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -87,7 +86,7 @@
 public class StatusBarKeyguardViewManager implements RemoteInputController.Callback,
         StatusBarStateController.StateListener, ConfigurationController.ConfigurationListener,
         PanelExpansionListener, NavigationModeController.ModeChangedListener,
-        KeyguardViewController, WakefulnessLifecycle.Observer {
+        KeyguardViewController {
 
     // When hiding the Keyguard with timing supplied from WindowManager, better be early than late.
     private static final long HIDE_TIMING_CORRECTION_MS = - 16 * 3;
@@ -392,17 +391,13 @@
         } else {
             mStatusBar.showKeyguard();
             if (hideBouncerWhenShowing) {
-                hideBouncer(shouldDestroyViewOnReset() /* destroyView */);
+                hideBouncer(false /* destroyView */);
                 mBouncer.prepare();
             }
         }
         updateStates();
     }
 
-    protected boolean shouldDestroyViewOnReset() {
-        return false;
-    }
-
     /**
      * If applicable, shows the alternate authentication bouncer. Else, shows the input
      * (pin/password/pattern) bouncer.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
index e5f2aa7..f391eff 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
@@ -26,6 +26,7 @@
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.verifyZeroInteractions;
@@ -43,7 +44,6 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.keyguard.KeyguardHostViewController;
-import com.android.keyguard.KeyguardRootViewController;
 import com.android.keyguard.KeyguardSecurityModel;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.ViewMediatorCallback;
@@ -64,7 +64,6 @@
 import org.mockito.Mock;
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
-import org.mockito.stubbing.Answer;
 
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
@@ -92,13 +91,10 @@
     @Mock
     private KeyguardSecurityModel mKeyguardSecurityModel;
     @Mock
-    private KeyguardRootViewController mRootViewController;
-    @Mock
-    private ViewGroup mRootView;
-    @Mock
     private KeyguardBouncerComponent.Factory mKeyguardBouncerComponentFactory;
     @Mock
     private KeyguardBouncerComponent mKeyguardBouncerComponent;
+    private ViewGroup mContainer;
     @Rule
     public MockitoRule mRule = MockitoJUnit.rule();
     private Integer mRootVisibility = View.INVISIBLE;
@@ -107,32 +103,22 @@
     @Before
     public void setup() {
         allowTestableLooperAsMainThread();
-        mDependency.injectTestDependency(KeyguardUpdateMonitor.class, mKeyguardUpdateMonitor);
-        mDependency.injectMockDependency(KeyguardStateController.class);
-        when(mRootView.getVisibility()).thenAnswer((Answer<Integer>) invocation -> mRootVisibility);
-        doAnswer(invocation -> {
-            mRootVisibility = invocation.getArgument(0);
-            return null;
-        }).when(mRootView).setVisibility(anyInt());
         when(mKeyguardSecurityModel.getSecurityMode(anyInt()))
                 .thenReturn(KeyguardSecurityModel.SecurityMode.None);
         DejankUtils.setImmediate(true);
-        when(mKeyguardBouncerComponentFactory.create()).thenReturn(mKeyguardBouncerComponent);
+
+        mContainer = spy(new FrameLayout(getContext()));
+        when(mKeyguardBouncerComponentFactory.create(mContainer)).thenReturn(
+                mKeyguardBouncerComponent);
         when(mKeyguardBouncerComponent.getKeyguardHostViewController())
                 .thenReturn(mKeyguardHostViewController);
-        when(mKeyguardBouncerComponent.getKeyguardRootViewController())
-                .thenReturn(mRootViewController);
 
-        when(mRootViewController.getView()).thenReturn(mRootView);
-        when(mRootView.getResources()).thenReturn(mContext.getResources());
-
-        final ViewGroup container = new FrameLayout(getContext());
         mBouncer = new KeyguardBouncer.Factory(getContext(), mViewMediatorCallback,
                 mDismissCallbackRegistry, mFalsingCollector,
                 mKeyguardStateController, mKeyguardUpdateMonitor,
                 mKeyguardBypassController, mHandler, mKeyguardSecurityModel,
                 mKeyguardBouncerComponentFactory)
-                .create(container, mExpansionCallback);
+                .create(mContainer, mExpansionCallback);
     }
 
     @Test
@@ -233,7 +219,7 @@
 
         mBouncer.setExpansion(0);
         verify(mKeyguardHostViewController).onResume();
-        verify(mRootView).announceForAccessibility(any());
+        verify(mContainer).announceForAccessibility(any());
     }
 
     @Test