Merge "Position "At a Glance" on custom clock below status bar." into qt-dev
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/AnalogClockController.java b/packages/SystemUI/src/com/android/keyguard/clock/AnalogClockController.java
index 7d1587c..123e138 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/AnalogClockController.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/AnalogClockController.java
@@ -54,6 +54,11 @@
     private final SysuiColorExtractor mColorExtractor;
 
     /**
+     * Computes preferred position of clock.
+     */
+    private final SmallClockPosition mClockPosition;
+
+    /**
      * Renders preview from clock view.
      */
     private final ViewPreviewer mRenderer = new ViewPreviewer();
@@ -82,6 +87,7 @@
         mResources = res;
         mLayoutInflater = inflater;
         mColorExtractor = colorExtractor;
+        mClockPosition = new SmallClockPosition(res);
     }
 
     private void createViews() {
@@ -153,7 +159,7 @@
 
     @Override
     public int getPreferredY(int totalHeight) {
-        return totalHeight / 4;
+        return mClockPosition.getPreferredY();
     }
 
     @Override
@@ -181,7 +187,9 @@
     }
 
     @Override
-    public void setDarkAmount(float darkAmount) { }
+    public void setDarkAmount(float darkAmount) {
+        mClockPosition.setDarkAmount(darkAmount);
+    }
 
     @Override
     public void onTimeZoneChanged(TimeZone timeZone) {
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java b/packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java
index fbbf64c..8db61b8 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java
@@ -54,6 +54,11 @@
     private final SysuiColorExtractor mColorExtractor;
 
     /**
+     * Computes preferred position of clock.
+     */
+    private final SmallClockPosition mClockPosition;
+
+    /**
      * Renders preview from clock view.
      */
     private final ViewPreviewer mRenderer = new ViewPreviewer();
@@ -82,6 +87,7 @@
         mResources = res;
         mLayoutInflater = inflater;
         mColorExtractor = colorExtractor;
+        mClockPosition = new SmallClockPosition(res);
     }
 
     private void createViews() {
@@ -152,7 +158,7 @@
 
     @Override
     public int getPreferredY(int totalHeight) {
-        return totalHeight / 4;
+        return mClockPosition.getPreferredY();
     }
 
     @Override
@@ -173,7 +179,9 @@
     }
 
     @Override
-    public void setDarkAmount(float darkAmount) { }
+    public void setDarkAmount(float darkAmount) {
+        mClockPosition.setDarkAmount(darkAmount);
+    }
 
     @Override
     public void onTimeTick() {
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/SmallClockPosition.java b/packages/SystemUI/src/com/android/keyguard/clock/SmallClockPosition.java
new file mode 100644
index 0000000..9b15dc6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/clock/SmallClockPosition.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.keyguard.clock;
+
+import android.content.res.Resources;
+import android.util.MathUtils;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * Computes preferred position of clock by considering height of status bar and lock icon.
+ */
+class SmallClockPosition {
+
+    /**
+     * Dimensions used to determine preferred clock position.
+     */
+    private final int mStatusBarHeight;
+    private final int mKeyguardLockPadding;
+    private final int mKeyguardLockHeight;
+    private final int mBurnInOffsetY;
+
+    /**
+     * Amount of transition between AOD and lock screen.
+     */
+    private float mDarkAmount;
+
+    SmallClockPosition(Resources res) {
+        this(res.getDimensionPixelSize(com.android.keyguard.R.dimen.status_bar_height),
+                res.getDimensionPixelSize(com.android.keyguard.R.dimen.keyguard_lock_padding),
+                res.getDimensionPixelSize(com.android.keyguard.R.dimen.keyguard_lock_height),
+                res.getDimensionPixelSize(com.android.keyguard.R.dimen.burn_in_prevention_offset_y)
+        );
+    }
+
+    @VisibleForTesting
+    SmallClockPosition(int statusBarHeight, int lockPadding, int lockHeight, int burnInY) {
+        mStatusBarHeight = statusBarHeight;
+        mKeyguardLockPadding = lockPadding;
+        mKeyguardLockHeight = lockHeight;
+        mBurnInOffsetY = burnInY;
+    }
+
+    /**
+     * See {@link ClockPlugin#setDarkAmount}.
+     */
+    void setDarkAmount(float darkAmount) {
+        mDarkAmount = darkAmount;
+    }
+
+    /**
+     * Gets the preferred Y position accounting for status bar and lock icon heights.
+     */
+    int getPreferredY() {
+        // On AOD, clock needs to appear below the status bar with enough room for pixel shifting
+        int aodY = mStatusBarHeight + mKeyguardLockPadding + mBurnInOffsetY;
+        // On lock screen, clock needs to appear below the lock icon
+        int lockY =  mStatusBarHeight + mKeyguardLockHeight + 2 * mKeyguardLockPadding;
+        return (int) MathUtils.lerp(lockY, aodY, mDarkAmount);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
index 26e0a70..1b86693 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
@@ -158,7 +158,12 @@
     }
 
     private int getPreferredClockY() {
-        return mClockPreferredY - mKeyguardStatusHeight - mClockNotificationsMargin;
+        return mClockPreferredY;
+    }
+
+    private int getExpandedPreferredClockY() {
+        return (mHasCustomClock && !mHasVisibleNotifs) ? getPreferredClockY()
+                : getExpandedClockPosition();
     }
 
     /**
@@ -187,13 +192,11 @@
 
     private int getClockY() {
         // Dark: Align the bottom edge of the clock at about half of the screen:
-        float clockYDark = getPreferredClockY() + burnInPreventionOffsetY();
+        float clockYDark = (mHasCustomClock ? getPreferredClockY() : getMaxClockY())
+                + burnInPreventionOffsetY();
         clockYDark = MathUtils.max(0, clockYDark);
 
-        float clockYRegular = getExpandedClockPosition();
-        if (mHasCustomClock && !mHasVisibleNotifs) {
-            clockYRegular = clockYDark;
-        }
+        float clockYRegular = getExpandedPreferredClockY();
         float clockYBouncer = -mKeyguardStatusHeight;
 
         // Move clock up while collapsing the shade
@@ -213,7 +216,7 @@
      * @return Alpha from 0 to 1.
      */
     private float getClockAlpha(int y) {
-        float alphaKeyguard = Math.max(0, y / Math.max(1f, getExpandedClockPosition()));
+        float alphaKeyguard = Math.max(0, y / Math.max(1f, getExpandedPreferredClockY()));
         alphaKeyguard = Interpolators.ACCELERATE.getInterpolation(alphaKeyguard);
         return MathUtils.lerp(alphaKeyguard, 1f, mDarkAmount);
     }
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/clock/SmallClockPositionTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/clock/SmallClockPositionTest.kt
new file mode 100644
index 0000000..f4d59cc
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/keyguard/clock/SmallClockPositionTest.kt
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.keyguard.clock
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class SmallClockPositionTest : SysuiTestCase() {
+
+    private val statusBarHeight = 100
+    private val lockPadding = 15
+    private val lockHeight = 35
+    private val burnInY = 20
+
+    private lateinit var position: SmallClockPosition
+
+    @Before
+    fun setUp() {
+        position = SmallClockPosition(statusBarHeight, lockPadding, lockHeight, burnInY)
+    }
+
+    @Test
+    fun loadResources() {
+        // Cover constructor taking Resources object.
+        position = SmallClockPosition(context.resources)
+        position.setDarkAmount(1f)
+        assertThat(position.preferredY).isGreaterThan(0)
+    }
+
+    @Test
+    fun darkPosition() {
+        // GIVEN on AOD
+        position.setDarkAmount(1f)
+        // THEN Y position is statusBarHeight + lockPadding + burnInY (100 + 15 + 20 = 135)
+        assertThat(position.preferredY).isEqualTo(135)
+    }
+
+    @Test
+    fun lockPosition() {
+        // GIVEN on lock screen
+        position.setDarkAmount(0f)
+        // THEN Y position is statusBarHeight + lockPadding + lockHeight + lockPadding
+        // (100 + 15 + 35 + 15 = 165)
+        assertThat(position.preferredY).isEqualTo(165)
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
index f191cab..f8394f0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
@@ -316,6 +316,7 @@
         positionClock();
         // THEN the clock Y position is the preferred Y position.
         assertThat(mClockPosition.clockY).isEqualTo(100);
+        assertThat(mClockPosition.clockAlpha).isEqualTo(OPAQUE);
     }
 
     @Test
@@ -333,6 +334,7 @@
         // THEN the clock Y position is the middle of the screen (SCREEN_HEIGHT / 2) and not
         // preferred.
         assertThat(mClockPosition.clockY).isEqualTo(1000);
+        assertThat(mClockPosition.clockAlpha).isEqualTo(OPAQUE);
     }
 
     @Test
@@ -349,6 +351,7 @@
         positionClock();
         // THEN the clock Y position is the middle of the screen (SCREEN_HEIGHT / 2).
         assertThat(mClockPosition.clockY).isEqualTo(1000);
+        assertThat(mClockPosition.clockAlpha).isEqualTo(OPAQUE);
     }
 
     @Test