blob: bc2d00f531867dd610831f0a4448171df0f84e82 [file] [log] [blame]
Jorim Jaggi7d16bb12014-05-22 04:24:50 +02001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
17package com.android.systemui.statusbar.phone;
18
Lucas Dupin7da4f262018-09-20 13:41:46 -070019import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInOffset;
Adrian Roosdc747bd2017-06-01 16:09:15 -070020import static com.android.systemui.statusbar.notification.NotificationUtils.interpolate;
21
Jorim Jaggi7d16bb12014-05-22 04:24:50 +020022import android.content.res.Resources;
Lucas Dupind285cf02018-01-18 09:18:23 -080023import android.util.MathUtils;
Jorim Jaggi7d16bb12014-05-22 04:24:50 +020024
Lucas Dupin60661a62018-04-12 10:50:13 -070025import com.android.keyguard.KeyguardStatusView;
Lucas Dupin41ff6952018-02-18 19:39:32 -080026import com.android.systemui.Interpolators;
Jorim Jaggi7d16bb12014-05-22 04:24:50 +020027import com.android.systemui.R;
28
29/**
30 * Utility class to calculate the clock position and top padding of notifications on Keyguard.
31 */
32public class KeyguardClockPositionAlgorithm {
33
Lucas Dupin41ff6952018-02-18 19:39:32 -080034 /**
35 * How much the clock height influences the shade position.
36 * 0 means nothing, 1 means move the shade up by the height of the clock
37 * 0.5f means move the shade up by half of the size of the clock.
38 */
39 private static float CLOCK_HEIGHT_WEIGHT = 0.7f;
40
41 /**
42 * Margin between the bottom of the clock and the notification shade.
43 */
Lucas Dupind285cf02018-01-18 09:18:23 -080044 private int mClockNotificationsMargin;
Lucas Dupin41ff6952018-02-18 19:39:32 -080045
46 /**
Lucas Dupin41ff6952018-02-18 19:39:32 -080047 * Height of the parent view - display size in px.
48 */
Jorim Jaggi7d16bb12014-05-22 04:24:50 +020049 private int mHeight;
Lucas Dupin41ff6952018-02-18 19:39:32 -080050
51 /**
52 * Height of {@link KeyguardStatusView}.
53 */
Jorim Jaggi7d16bb12014-05-22 04:24:50 +020054 private int mKeyguardStatusHeight;
Lucas Dupin41ff6952018-02-18 19:39:32 -080055
56 /**
Robert Snoeberger69956802019-04-16 16:55:21 -040057 * Preferred Y position of clock.
58 */
59 private int mClockPreferredY;
60
61 /**
Robert Snoeberger168949a2019-04-18 09:39:42 -040062 * Whether or not there is a custom clock face on keyguard.
63 */
64 private boolean mHasCustomClock;
65
66 /**
67 * Whether or not the NSSL contains any visible notifications.
68 */
69 private boolean mHasVisibleNotifs;
70
71 /**
Lucas Dupin41ff6952018-02-18 19:39:32 -080072 * Height of notification stack: Sum of height of each notification.
73 */
74 private int mNotificationStackHeight;
75
76 /**
77 * Minimum top margin to avoid overlap with status bar.
78 */
79 private int mMinTopMargin;
80
81 /**
82 * Maximum bottom padding to avoid overlap with {@link KeyguardBottomAreaView} or
83 * the ambient indication.
84 */
85 private int mMaxShadeBottom;
86
87 /**
Lucas Dupinbc9aac12018-03-04 20:18:15 -080088 * Minimum distance from the status bar.
Lucas Dupin41ff6952018-02-18 19:39:32 -080089 */
Lucas Dupinbc9aac12018-03-04 20:18:15 -080090 private int mContainerTopPadding;
Lucas Dupin41ff6952018-02-18 19:39:32 -080091
92 /**
Lucas Dupin60661a62018-04-12 10:50:13 -070093 * @see NotificationPanelView#getExpandedFraction()
Lucas Dupin41ff6952018-02-18 19:39:32 -080094 */
Lucas Dupin60661a62018-04-12 10:50:13 -070095 private float mPanelExpansion;
Lucas Dupin41ff6952018-02-18 19:39:32 -080096
97 /**
98 * Burn-in prevention x translation.
99 */
Adrian Roosdc747bd2017-06-01 16:09:15 -0700100 private int mBurnInPreventionOffsetX;
Lucas Dupin41ff6952018-02-18 19:39:32 -0800101
102 /**
103 * Burn-in prevention y translation.
104 */
Adrian Roosdc747bd2017-06-01 16:09:15 -0700105 private int mBurnInPreventionOffsetY;
Jorim Jaggi7d16bb12014-05-22 04:24:50 +0200106
107 /**
Lucas Dupin41ff6952018-02-18 19:39:32 -0800108 * Doze/AOD transition amount.
Jorim Jaggi7d16bb12014-05-22 04:24:50 +0200109 */
Adrian Roos52414e32017-04-28 09:23:19 -0700110 private float mDarkAmount;
Selim Cinekf99d0002014-06-13 07:36:01 +0200111
Lucas Dupin55c6e802018-09-27 18:07:36 -0700112 private float mEmptyDragAmount;
Lucas Dupin4c2aa392018-03-28 18:00:45 -0700113
114 /**
Jorim Jaggi7d16bb12014-05-22 04:24:50 +0200115 * Refreshes the dimension values.
116 */
117 public void loadDimens(Resources res) {
Lucas Dupind285cf02018-01-18 09:18:23 -0800118 mClockNotificationsMargin = res.getDimensionPixelSize(
119 R.dimen.keyguard_clock_notifications_margin);
Robert Snoeberger69969c22019-05-02 16:44:11 -0400120 // Consider the lock icon when determining the minimum top padding between the status bar
121 // and top of the clock.
122 mContainerTopPadding = Math.max(res.getDimensionPixelSize(
123 R.dimen.keyguard_clock_top_margin),
124 res.getDimensionPixelSize(R.dimen.keyguard_lock_height)
125 + res.getDimensionPixelSize(R.dimen.keyguard_lock_padding)
126 + res.getDimensionPixelSize(R.dimen.keyguard_clock_lock_margin));
Adrian Roosdc747bd2017-06-01 16:09:15 -0700127 mBurnInPreventionOffsetX = res.getDimensionPixelSize(
128 R.dimen.burn_in_prevention_offset_x);
129 mBurnInPreventionOffsetY = res.getDimensionPixelSize(
130 R.dimen.burn_in_prevention_offset_y);
Jorim Jaggi7d16bb12014-05-22 04:24:50 +0200131 }
132
Lucas Dupin41ff6952018-02-18 19:39:32 -0800133 public void setup(int minTopMargin, int maxShadeBottom, int notificationStackHeight,
Robert Snoeberger69956802019-04-16 16:55:21 -0400134 float panelExpansion, int parentHeight, int keyguardStatusHeight, int clockPreferredY,
Robert Snoeberger168949a2019-04-18 09:39:42 -0400135 boolean hasCustomClock, boolean hasVisibleNotifs, float dark, float emptyDragAmount) {
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800136 mMinTopMargin = minTopMargin + mContainerTopPadding;
Lucas Dupin41ff6952018-02-18 19:39:32 -0800137 mMaxShadeBottom = maxShadeBottom;
138 mNotificationStackHeight = notificationStackHeight;
Lucas Dupin60661a62018-04-12 10:50:13 -0700139 mPanelExpansion = panelExpansion;
Lucas Dupin41ff6952018-02-18 19:39:32 -0800140 mHeight = parentHeight;
Jorim Jaggi7d16bb12014-05-22 04:24:50 +0200141 mKeyguardStatusHeight = keyguardStatusHeight;
Robert Snoeberger69956802019-04-16 16:55:21 -0400142 mClockPreferredY = clockPreferredY;
Robert Snoeberger168949a2019-04-18 09:39:42 -0400143 mHasCustomClock = hasCustomClock;
144 mHasVisibleNotifs = hasVisibleNotifs;
Adrian Roos52414e32017-04-28 09:23:19 -0700145 mDarkAmount = dark;
Lucas Dupin55c6e802018-09-27 18:07:36 -0700146 mEmptyDragAmount = emptyDragAmount;
Selim Cinek5f71bee2015-11-18 10:25:23 -0800147 }
148
Jorim Jaggi7d16bb12014-05-22 04:24:50 +0200149 public void run(Result result) {
Lucas Dupin41ff6952018-02-18 19:39:32 -0800150 final int y = getClockY();
Lucas Dupind285cf02018-01-18 09:18:23 -0800151 result.clockY = y;
Lucas Dupin41ff6952018-02-18 19:39:32 -0800152 result.clockAlpha = getClockAlpha(y);
Lucas Dupin00be88f2019-01-03 17:50:52 -0800153 result.stackScrollerPadding = y + mKeyguardStatusHeight;
Adrian Roosdc747bd2017-06-01 16:09:15 -0700154 result.clockX = (int) interpolate(0, burnInPreventionOffsetX(), mDarkAmount);
Selim Cinekf99d0002014-06-13 07:36:01 +0200155 }
156
Lucas Dupin41ff6952018-02-18 19:39:32 -0800157 public float getMinStackScrollerPadding() {
158 return mMinTopMargin + mKeyguardStatusHeight + mClockNotificationsMargin;
Jorim Jaggi7d16bb12014-05-22 04:24:50 +0200159 }
160
Lucas Dupin41ff6952018-02-18 19:39:32 -0800161 private int getMaxClockY() {
162 return mHeight / 2 - mKeyguardStatusHeight - mClockNotificationsMargin;
163 }
164
Robert Snoeberger69956802019-04-16 16:55:21 -0400165 private int getPreferredClockY() {
Robert Snoeberger4cbd1592019-04-24 14:20:38 -0400166 return mClockPreferredY;
167 }
168
169 private int getExpandedPreferredClockY() {
170 return (mHasCustomClock && !mHasVisibleNotifs) ? getPreferredClockY()
171 : getExpandedClockPosition();
Robert Snoeberger69956802019-04-16 16:55:21 -0400172 }
173
Lucas Dupin41ff6952018-02-18 19:39:32 -0800174 /**
175 * Vertically align the clock and the shade in the available space considering only
176 * a percentage of the clock height defined by {@code CLOCK_HEIGHT_WEIGHT}.
177 * @return Clock Y in pixels.
178 */
Lucas Dupin60661a62018-04-12 10:50:13 -0700179 public int getExpandedClockPosition() {
Lucas Dupin41ff6952018-02-18 19:39:32 -0800180 final int availableHeight = mMaxShadeBottom - mMinTopMargin;
181 final int containerCenter = mMinTopMargin + availableHeight / 2;
182
183 float y = containerCenter - mKeyguardStatusHeight * CLOCK_HEIGHT_WEIGHT
184 - mClockNotificationsMargin - mNotificationStackHeight / 2;
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800185 if (y < mMinTopMargin) {
186 y = mMinTopMargin;
Lucas Dupin41ff6952018-02-18 19:39:32 -0800187 }
188
189 // Don't allow the clock base to be under half of the screen
190 final float maxClockY = getMaxClockY();
191 if (y > maxClockY) {
192 y = maxClockY;
193 }
194
195 return (int) y;
Jorim Jaggi7d16bb12014-05-22 04:24:50 +0200196 }
197
198 private int getClockY() {
Lucas Dupind285cf02018-01-18 09:18:23 -0800199 // Dark: Align the bottom edge of the clock at about half of the screen:
Robert Snoeberger4cbd1592019-04-24 14:20:38 -0400200 float clockYDark = (mHasCustomClock ? getPreferredClockY() : getMaxClockY())
201 + burnInPreventionOffsetY();
Robert Snoeberger10b63532018-11-07 16:14:11 -0500202 clockYDark = MathUtils.max(0, clockYDark);
Lucas Dupin56057342018-04-10 11:49:18 -0700203
Robert Snoeberger4cbd1592019-04-24 14:20:38 -0400204 float clockYRegular = getExpandedPreferredClockY();
Lucas Dupin55c6e802018-09-27 18:07:36 -0700205 float clockYBouncer = -mKeyguardStatusHeight;
Lucas Dupin41ff6952018-02-18 19:39:32 -0800206
207 // Move clock up while collapsing the shade
Lucas Dupin60661a62018-04-12 10:50:13 -0700208 float shadeExpansion = Interpolators.FAST_OUT_LINEAR_IN.getInterpolation(mPanelExpansion);
Lucas Dupin55c6e802018-09-27 18:07:36 -0700209 float clockY = MathUtils.lerp(clockYBouncer, clockYRegular, shadeExpansion);
210 clockYDark = MathUtils.lerp(clockYBouncer, clockYDark, shadeExpansion);
Lucas Dupin41ff6952018-02-18 19:39:32 -0800211
Lucas Dupin55c6e802018-09-27 18:07:36 -0700212 return (int) (MathUtils.lerp(clockY, clockYDark, mDarkAmount) + mEmptyDragAmount);
Lucas Dupin41ff6952018-02-18 19:39:32 -0800213 }
214
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800215 /**
216 * We might want to fade out the clock when the user is swiping up.
217 * One exception is when the bouncer will become visible, in this cause the clock
218 * should always persist.
219 *
220 * @param y Current clock Y.
221 * @return Alpha from 0 to 1.
222 */
Lucas Dupin41ff6952018-02-18 19:39:32 -0800223 private float getClockAlpha(int y) {
Robert Snoeberger4cbd1592019-04-24 14:20:38 -0400224 float alphaKeyguard = Math.max(0, y / Math.max(1f, getExpandedPreferredClockY()));
Lucas Dupin2e838ac2019-04-17 16:50:58 -0700225 alphaKeyguard = Interpolators.ACCELERATE.getInterpolation(alphaKeyguard);
Lucas Dupin41ff6952018-02-18 19:39:32 -0800226 return MathUtils.lerp(alphaKeyguard, 1f, mDarkAmount);
Adrian Roosdc747bd2017-06-01 16:09:15 -0700227 }
228
229 private float burnInPreventionOffsetY() {
Lucas Dupin7da4f262018-09-20 13:41:46 -0700230 return getBurnInOffset(mBurnInPreventionOffsetY * 2, false /* xAxis */)
Adrian Roosdc747bd2017-06-01 16:09:15 -0700231 - mBurnInPreventionOffsetY;
232 }
233
234 private float burnInPreventionOffsetX() {
Lucas Dupin7da4f262018-09-20 13:41:46 -0700235 return getBurnInOffset(mBurnInPreventionOffsetX * 2, true /* xAxis */)
Adrian Roosdc747bd2017-06-01 16:09:15 -0700236 - mBurnInPreventionOffsetX;
237 }
238
Jorim Jaggi7d16bb12014-05-22 04:24:50 +0200239 public static class Result {
240
241 /**
Lucas Dupin41ff6952018-02-18 19:39:32 -0800242 * The x translation of the clock.
243 */
244 public int clockX;
245
246 /**
Jorim Jaggi7d16bb12014-05-22 04:24:50 +0200247 * The y translation of the clock.
248 */
249 public int clockY;
250
251 /**
Jorim Jaggi7d16bb12014-05-22 04:24:50 +0200252 * The alpha value of the clock.
253 */
254 public float clockAlpha;
255
256 /**
257 * The top padding of the stack scroller, in pixels.
258 */
259 public int stackScrollerPadding;
Jorim Jaggi7d16bb12014-05-22 04:24:50 +0200260 }
261}