Now Playing is too low on the lock screen

NOTE: on udfps devices while now playing + on pixel stand 2, and max density, there remains overlapping related to the assistant icon.

Test: manually test UI on Pixel Stand 2
Test: manually test UI by pushing song to NowPlaying via adb
Test: manually test on devices both with and without udfps, on large screen density and low density
Fixes: 230466568

9761c10a5c706b0921a16e55a51e1b853853e792

Change-Id: I3c67e92d5d9076938c55852898d80903de1d0202
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 93926ef9..40d96ea 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -762,7 +762,7 @@
     <dimen name="keyguard_lock_padding">20dp</dimen>
 
     <dimen name="keyguard_indication_margin_bottom">32dp</dimen>
-    <dimen name="lock_icon_margin_bottom">110dp</dimen>
+    <dimen name="lock_icon_margin_bottom">74dp</dimen>
     <dimen name="ambient_indication_margin_bottom">71dp</dimen>
 
 
diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconView.java b/packages/SystemUI/src/com/android/keyguard/LockIconView.java
index 0a82968..34a5ef7 100644
--- a/packages/SystemUI/src/com/android/keyguard/LockIconView.java
+++ b/packages/SystemUI/src/com/android/keyguard/LockIconView.java
@@ -158,6 +158,10 @@
         return mLockIconCenter.y - mRadius;
     }
 
+    float getLocationBottom() {
+        return mLockIconCenter.y + mRadius;
+    }
+
     /**
      * Updates the icon its default state where no visual is shown.
      */
diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
index fe7c70a..c7cc059 100644
--- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
@@ -280,6 +280,10 @@
         return mView.getLocationTop();
     }
 
+    public float getBottom() {
+        return mView.getLocationBottom();
+    }
+
     private void updateVisibility() {
         if (mCancelDelayedUpdateVisibilityRunnable != null) {
             mCancelDelayedUpdateVisibilityRunnable.run();
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
index c867c6e..ca25282 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.keyguard.data.repository
 
+import com.android.keyguard.KeyguardUpdateMonitor
 import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
 import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
 import com.android.systemui.common.shared.model.Position
@@ -123,6 +124,11 @@
      * Sets the relative offset of the lock-screen clock from its natural position on the screen.
      */
     fun setClockPosition(x: Int, y: Int)
+
+    /**
+     * Returns whether the keyguard bottom area should be constrained to the top of the lock icon
+     */
+    fun isUdfpsSupported(): Boolean
 }
 
 /** Encapsulates application state for the keyguard. */
@@ -130,11 +136,12 @@
 class KeyguardRepositoryImpl
 @Inject
 constructor(
-    statusBarStateController: StatusBarStateController,
-    private val keyguardStateController: KeyguardStateController,
-    dozeHost: DozeHost,
-    wakefulnessLifecycle: WakefulnessLifecycle,
-    biometricUnlockController: BiometricUnlockController,
+        statusBarStateController: StatusBarStateController,
+        dozeHost: DozeHost,
+        wakefulnessLifecycle: WakefulnessLifecycle,
+        biometricUnlockController: BiometricUnlockController,
+        private val keyguardStateController: KeyguardStateController,
+        private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
 ) : KeyguardRepository {
     private val _animateBottomAreaDozingTransitions = MutableStateFlow(false)
     override val animateBottomAreaDozingTransitions =
@@ -311,6 +318,8 @@
         _clockPosition.value = Position(x, y)
     }
 
+    override fun isUdfpsSupported(): Boolean = keyguardUpdateMonitor.isUdfpsSupported
+
     private fun statusBarStateIntToObject(value: Int): StatusBarState {
         return when (value) {
             0 -> StatusBarState.SHADE
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBottomAreaInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBottomAreaInteractor.kt
index ede50b0..d2a7486 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBottomAreaInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBottomAreaInteractor.kt
@@ -48,4 +48,9 @@
     fun setAnimateDozingTransitions(animate: Boolean) {
         repository.setAnimateDozingTransitions(animate)
     }
+
+    /**
+     * Returns whether the keyguard bottom area should be constrained to the top of the lock icon
+     */
+    fun shouldConstrainToTopOfLockIcon(): Boolean = repository.isUdfpsSupported()
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt
index 2c99ca5..3276b6d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt
@@ -27,6 +27,8 @@
 import androidx.core.view.updateLayoutParams
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.repeatOnLifecycle
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.keyguard.LockIconViewController
 import com.android.settingslib.Utils
 import com.android.systemui.R
 import com.android.systemui.animation.Expandable
@@ -69,6 +71,11 @@
 
         /** Notifies that device configuration has changed. */
         fun onConfigurationChanged()
+
+        /**
+         * Returns whether the keyguard bottom area should be constrained to the top of the lock icon
+         */
+        fun shouldConstrainToTopOfLockIcon(): Boolean
     }
 
     /** Binds the view to the view-model, continuing to update the former based on the latter. */
@@ -208,6 +215,9 @@
             override fun onConfigurationChanged() {
                 configurationBasedDimensions.value = loadFromResources(view)
             }
+
+            override fun shouldConstrainToTopOfLockIcon(): Boolean =
+                    viewModel.shouldConstrainToTopOfLockIcon()
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModel.kt
index b6b2304..227796f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModel.kt
@@ -90,6 +90,12 @@
             .distinctUntilChanged()
     }
 
+    /**
+     * Returns whether the keyguard bottom area should be constrained to the top of the lock icon
+     */
+    fun shouldConstrainToTopOfLockIcon(): Boolean =
+            bottomAreaInteractor.shouldConstrainToTopOfLockIcon()
+
     private fun button(
         position: KeyguardQuickAffordancePosition
     ): Flow<KeyguardQuickAffordanceViewModel> {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index 92f5c85..5924e14 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -1309,7 +1309,11 @@
     }
 
     private void initBottomArea() {
-        mKeyguardBottomArea.init(mKeyguardBottomAreaViewModel, mFalsingManager);
+        mKeyguardBottomArea.init(
+                mKeyguardBottomAreaViewModel,
+                mFalsingManager,
+                mLockIconViewController
+        );
     }
 
     @VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.kt
index 4897c52..78b28d2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.kt
@@ -23,6 +23,8 @@
 import android.view.ViewPropertyAnimator
 import android.view.WindowInsets
 import android.widget.FrameLayout
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.keyguard.LockIconViewController
 import com.android.systemui.R
 import com.android.systemui.keyguard.ui.binder.KeyguardBottomAreaViewBinder
 import com.android.systemui.keyguard.ui.binder.KeyguardBottomAreaViewBinder.bind
@@ -51,13 +53,20 @@
 
     private var ambientIndicationArea: View? = null
     private lateinit var binding: KeyguardBottomAreaViewBinder.Binding
+    private lateinit var lockIconViewController: LockIconViewController
 
     /** Initializes the view. */
     fun init(
         viewModel: KeyguardBottomAreaViewModel,
         falsingManager: FalsingManager,
+        lockIconViewController: LockIconViewController,
     ) {
-        binding = bind(this, viewModel, falsingManager)
+        binding = bind(
+                this,
+                viewModel,
+                falsingManager,
+        )
+        this.lockIconViewController = lockIconViewController
     }
 
     /**
@@ -114,4 +123,29 @@
         }
         return insets
     }
+
+    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
+        super.onLayout(changed, left, top, right, bottom)
+        findViewById<View>(R.id.ambient_indication_container)?.let {
+            val (ambientLeft, ambientTop) = it.locationOnScreen
+            if (binding.shouldConstrainToTopOfLockIcon()) {
+                //make top of ambient indication view the bottom of the lock icon
+                it.layout(
+                        ambientLeft,
+                        lockIconViewController.bottom.toInt(),
+                        right - ambientLeft,
+                        ambientTop + it.measuredHeight
+                )
+            } else {
+                //make bottom of ambient indication view the top of the lock icon
+                val lockLocationTop = lockIconViewController.top
+                it.layout(
+                        ambientLeft,
+                        lockLocationTop.toInt() - it.measuredHeight,
+                        right - ambientLeft,
+                        lockLocationTop.toInt()
+                )
+            }
+        }
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
index 53d9b87..ade83cf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
@@ -17,6 +17,7 @@
 package com.android.systemui.keyguard.data.repository
 
 import androidx.test.filters.SmallTest
+import com.android.keyguard.KeyguardUpdateMonitor
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.common.shared.model.Position
 import com.android.systemui.doze.DozeHost
@@ -48,6 +49,7 @@
     @Mock private lateinit var dozeHost: DozeHost
     @Mock private lateinit var keyguardStateController: KeyguardStateController
     @Mock private lateinit var wakefulnessLifecycle: WakefulnessLifecycle
+    @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
     @Mock private lateinit var biometricUnlockController: BiometricUnlockController
 
     private lateinit var underTest: KeyguardRepositoryImpl
@@ -58,11 +60,12 @@
 
         underTest =
             KeyguardRepositoryImpl(
-                statusBarStateController,
-                keyguardStateController,
-                dozeHost,
-                wakefulnessLifecycle,
-                biometricUnlockController,
+                    statusBarStateController,
+                    dozeHost,
+                    wakefulnessLifecycle,
+                    biometricUnlockController,
+                    keyguardStateController,
+                    keyguardUpdateMonitor,
             )
     }
 
@@ -223,6 +226,15 @@
     }
 
     @Test
+    fun isUdfpsSupported() = runBlockingTest {
+        whenever(keyguardUpdateMonitor.isUdfpsSupported).thenReturn(true)
+        assertThat(underTest.isUdfpsSupported()).isTrue()
+
+        whenever(keyguardUpdateMonitor.isUdfpsSupported).thenReturn(false)
+        assertThat(underTest.isUdfpsSupported()).isFalse()
+    }
+
+    @Test
     fun isBouncerShowing() = runBlockingTest {
         whenever(keyguardStateController.isBouncerShowing).thenReturn(false)
         var latest: Boolean? = null
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
index 627bd09..6f70f0e 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
@@ -53,6 +53,8 @@
     private val _wakefulnessState = MutableStateFlow(WakefulnessModel.ASLEEP)
     override val wakefulnessState: Flow<WakefulnessModel> = _wakefulnessState
 
+    private val _isUdfpsSupported = MutableStateFlow(false)
+    
     private val _isBouncerShowing = MutableStateFlow(false)
     override val isBouncerShowing: Flow<Boolean> = _isBouncerShowing
 
@@ -86,4 +88,8 @@
     fun setDozeAmount(dozeAmount: Float) {
         _dozeAmount.value = dozeAmount
     }
+
+    override fun isUdfpsSupported(): Boolean {
+        return _isUdfpsSupported.value
+    }
 }