blob: c246af57504cb1da1d6255e6c7ea5a434dd45f03 [file] [log] [blame]
Jorim Jaggid552d9d2014-05-07 19:41:13 +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
Rohan Shah20790b82018-07-02 17:21:04 -070017package com.android.systemui.statusbar.notification.stack;
Jorim Jaggid552d9d2014-05-07 19:41:13 +020018
Eliot Courtney5d3d2d02018-01-18 15:59:03 +090019import android.annotation.Nullable;
Selim Cinek281c2022016-10-13 19:14:43 -070020import android.content.Context;
Jorim Jaggid552d9d2014-05-07 19:41:13 +020021import android.view.View;
Selim Cineka59ecc32015-04-07 10:51:49 -070022
Kevina97ea052018-09-11 13:53:18 -070023import com.android.systemui.Dependency;
Selim Cinek281c2022016-10-13 19:14:43 -070024import com.android.systemui.R;
Kevina97ea052018-09-11 13:53:18 -070025import com.android.systemui.statusbar.AmbientPulseManager;
Gus Prevase2d6f042018-10-17 15:25:30 -040026import com.android.systemui.statusbar.NotificationShelf;
27import com.android.systemui.statusbar.StatusBarState;
Ned Burnsf81c4c42019-01-07 14:10:43 -050028import com.android.systemui.statusbar.notification.collection.NotificationEntry;
Rohan Shah20790b82018-07-02 17:21:04 -070029import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
30import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
31import com.android.systemui.statusbar.notification.row.ExpandableView;
Jorim Jaggid552d9d2014-05-07 19:41:13 +020032
33import java.util.ArrayList;
Gus Prevase2d6f042018-10-17 15:25:30 -040034import java.util.List;
Jorim Jaggid552d9d2014-05-07 19:41:13 +020035
36/**
37 * A global state to track all input states for the algorithm.
38 */
39public class AmbientState {
Gus Prevase2d6f042018-10-17 15:25:30 -040040
41 private static final int NO_SECTION_BOUNDARY = -1;
42
Dave Mankoffa4d195d2018-11-16 13:33:27 -050043 private ArrayList<ExpandableView> mDraggedViews = new ArrayList<>();
Jorim Jaggid552d9d2014-05-07 19:41:13 +020044 private int mScrollY;
Gus Prevas0fa58d62019-01-11 13:58:40 -050045 private int mAnchorViewIndex;
46 private int mAnchorViewY;
Jorim Jaggid552d9d2014-05-07 19:41:13 +020047 private boolean mDimmed;
Selim Cineka32ab602014-06-11 15:06:01 +020048 private ActivatableNotificationView mActivatedChild;
Selim Cinek8d9ff9c2014-05-12 15:13:04 +020049 private float mOverScrollTopAmount;
50 private float mOverScrollBottomAmount;
Selim Cinekdb167372016-11-17 15:41:17 -080051 private int mSpeedBumpIndex = -1;
Gus Prevase2d6f042018-10-17 15:25:30 -040052 private final List<Integer> mSectionBoundaryIndices = new ArrayList<>();
John Spurlockbf370992014-06-17 13:58:31 -040053 private boolean mDark;
Jorim Jaggiae441282014-08-01 02:45:18 +020054 private boolean mHideSensitive;
Kevina97ea052018-09-11 13:53:18 -070055 private AmbientPulseManager mAmbientPulseManager = Dependency.get(AmbientPulseManager.class);
Selim Cineka59ecc32015-04-07 10:51:49 -070056 private float mStackTranslation;
Selim Cinekb8f09cf2015-03-16 17:09:28 -070057 private int mLayoutHeight;
58 private int mTopPadding;
59 private boolean mShadeExpanded;
60 private float mMaxHeadsUpTranslation;
Selim Cinek9c17b772015-07-07 20:37:09 -070061 private boolean mDismissAllInProgress;
Selim Cinekbc243a92016-09-27 16:35:13 -070062 private int mLayoutMinHeight;
Selim Cinek281c2022016-10-13 19:14:43 -070063 private NotificationShelf mShelf;
64 private int mZDistanceBetweenElements;
65 private int mBaseZHeight;
Selim Cinek91d4cba2016-11-10 19:59:48 -080066 private int mMaxLayoutHeight;
Selim Cinekdb167372016-11-17 15:41:17 -080067 private ActivatableNotificationView mLastVisibleBackgroundChild;
Selim Cinek727903c2016-12-06 17:28:10 -080068 private float mCurrentScrollVelocity;
Selim Cinek355652a2016-12-07 13:32:12 -080069 private int mStatusBarState;
Selim Cinekd5ab6452016-12-08 16:34:00 -080070 private float mExpandingVelocity;
71 private boolean mPanelTracking;
72 private boolean mExpansionChanging;
Selim Cinekfcff4c62016-12-27 14:26:06 +010073 private boolean mPanelFullWidth;
yoshiki iguchi4e30e762018-02-06 12:09:23 +090074 private boolean mPulsing;
Selim Cinekec29d342017-05-05 18:31:49 -070075 private boolean mUnlockHintRunning;
Selim Cinek5cf1d052017-06-01 17:36:46 -070076 private boolean mQsCustomizerShowing;
Selim Cinek1f624952017-06-08 19:11:50 -070077 private int mIntrinsicPadding;
Selim Cinek2627d722018-01-19 12:16:49 -080078 private int mExpandAnimationTopChange;
79 private ExpandableNotificationRow mExpandingNotification;
Lucas Dupinb561eda2018-04-09 17:25:04 -070080 private float mDarkAmount;
shawnlin5be1f7c2018-05-21 20:50:54 +080081 private boolean mAppearing;
Selim Cinek281c2022016-10-13 19:14:43 -070082
83 public AmbientState(Context context) {
Gus Prevase2d6f042018-10-17 15:25:30 -040084 mSectionBoundaryIndices.add(NO_SECTION_BOUNDARY);
Selim Cinek281c2022016-10-13 19:14:43 -070085 reload(context);
86 }
87
88 /**
89 * Reload the dimens e.g. if the density changed.
90 */
91 public void reload(Context context) {
Selim Cinek2627d722018-01-19 12:16:49 -080092 mZDistanceBetweenElements = getZDistanceBetweenElements(context);
93 mBaseZHeight = getBaseHeight(mZDistanceBetweenElements);
94 }
95
96 private static int getZDistanceBetweenElements(Context context) {
97 return Math.max(1, context.getResources()
Selim Cinek281c2022016-10-13 19:14:43 -070098 .getDimensionPixelSize(R.dimen.z_distance_between_notifications));
Selim Cinek2627d722018-01-19 12:16:49 -080099 }
100
101 private static int getBaseHeight(int zdistanceBetweenElements) {
102 return 4 * zdistanceBetweenElements;
103 }
104
105 /**
106 * @return the launch height for notifications that are launched
107 */
108 public static int getNotificationLaunchHeight(Context context) {
109 int zDistance = getZDistanceBetweenElements(context);
110 return getBaseHeight(zDistance) * 2;
Selim Cinek281c2022016-10-13 19:14:43 -0700111 }
112
113 /**
114 * @return the basic Z height on which notifications remain.
115 */
116 public int getBaseZHeight() {
117 return mBaseZHeight;
118 }
119
120 /**
121 * @return the distance in Z between two overlaying notifications.
122 */
123 public int getZDistanceBetweenElements() {
124 return mZDistanceBetweenElements;
125 }
Jorim Jaggid552d9d2014-05-07 19:41:13 +0200126
127 public int getScrollY() {
128 return mScrollY;
129 }
130
131 public void setScrollY(int scrollY) {
132 this.mScrollY = scrollY;
133 }
134
Gus Prevas0fa58d62019-01-11 13:58:40 -0500135 /**
136 * Index of the child view whose Y position on screen is returned by {@link #getAnchorViewY()}.
137 * Other views are laid out outwards from this view in both directions.
138 */
139 public int getAnchorViewIndex() {
140 return mAnchorViewIndex;
141 }
142
143 public void setAnchorViewIndex(int anchorViewIndex) {
144 mAnchorViewIndex = anchorViewIndex;
145 }
146
147 /** Current Y position of the view at {@link #getAnchorViewIndex()}. */
148 public int getAnchorViewY() {
149 return mAnchorViewY;
150 }
151
152 public void setAnchorViewY(int anchorViewY) {
153 mAnchorViewY = anchorViewY;
154 }
155
Dave Mankoffa4d195d2018-11-16 13:33:27 -0500156 /** Call when dragging begins. */
157 public void onBeginDrag(ExpandableView view) {
Jorim Jaggid552d9d2014-05-07 19:41:13 +0200158 mDraggedViews.add(view);
159 }
160
161 public void onDragFinished(View view) {
162 mDraggedViews.remove(view);
163 }
164
Dave Mankoffa4d195d2018-11-16 13:33:27 -0500165 public ArrayList<ExpandableView> getDraggedViews() {
Jorim Jaggid552d9d2014-05-07 19:41:13 +0200166 return mDraggedViews;
167 }
168
169 /**
170 * @param dimmed Whether we are in a dimmed state (on the lockscreen), where the backgrounds are
171 * translucent and everything is scaled back a bit.
172 */
173 public void setDimmed(boolean dimmed) {
174 mDimmed = dimmed;
175 }
176
John Spurlockbf370992014-06-17 13:58:31 -0400177 /** In dark mode, we draw as little as possible, assuming a black background */
178 public void setDark(boolean dark) {
179 mDark = dark;
180 }
181
Lucas Dupinb561eda2018-04-09 17:25:04 -0700182 /** Dark ratio of the status bar **/
183 public void setDarkAmount(float darkAmount) {
184 mDarkAmount = darkAmount;
185 }
186
187 /** Returns the dark ratio of the status bar */
188 public float getDarkAmount() {
189 return mDarkAmount;
190 }
191
Jorim Jaggiae441282014-08-01 02:45:18 +0200192 public void setHideSensitive(boolean hideSensitive) {
193 mHideSensitive = hideSensitive;
194 }
195
Jorim Jaggid552d9d2014-05-07 19:41:13 +0200196 /**
197 * In dimmed mode, a child can be activated, which happens on the first tap of the double-tap
198 * interaction. This child is then scaled normally and its background is fully opaque.
199 */
Selim Cineka32ab602014-06-11 15:06:01 +0200200 public void setActivatedChild(ActivatableNotificationView activatedChild) {
Jorim Jaggid552d9d2014-05-07 19:41:13 +0200201 mActivatedChild = activatedChild;
202 }
203
204 public boolean isDimmed() {
205 return mDimmed;
206 }
207
John Spurlockbf370992014-06-17 13:58:31 -0400208 public boolean isDark() {
209 return mDark;
210 }
211
Jorim Jaggiae441282014-08-01 02:45:18 +0200212 public boolean isHideSensitive() {
213 return mHideSensitive;
214 }
215
Selim Cineka32ab602014-06-11 15:06:01 +0200216 public ActivatableNotificationView getActivatedChild() {
Jorim Jaggid552d9d2014-05-07 19:41:13 +0200217 return mActivatedChild;
218 }
Selim Cinek8d9ff9c2014-05-12 15:13:04 +0200219
220 public void setOverScrollAmount(float amount, boolean onTop) {
221 if (onTop) {
222 mOverScrollTopAmount = amount;
223 } else {
224 mOverScrollBottomAmount = amount;
225 }
226 }
227
228 public float getOverScrollAmount(boolean top) {
229 return top ? mOverScrollTopAmount : mOverScrollBottomAmount;
230 }
Selim Cinekc27437b2014-05-14 10:23:33 +0200231
Selim Cinekdb167372016-11-17 15:41:17 -0800232 public int getSpeedBumpIndex() {
233 return mSpeedBumpIndex;
Selim Cinekc27437b2014-05-14 10:23:33 +0200234 }
235
Selim Cinekdb167372016-11-17 15:41:17 -0800236 public void setSpeedBumpIndex(int shelfIndex) {
237 mSpeedBumpIndex = shelfIndex;
Selim Cinekc27437b2014-05-14 10:23:33 +0200238 }
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700239
Gus Prevase2d6f042018-10-17 15:25:30 -0400240 /**
241 * Returns the index of the boundary between two sections, where the first section is at index
242 * {@code boundaryNum}.
243 */
244 public int getSectionBoundaryIndex(int boundaryNum) {
245 return mSectionBoundaryIndices.get(boundaryNum);
246 }
247
248 /** Returns true if the item at {@code index} is directly below a section boundary. */
249 public boolean beginsNewSection(int index) {
250 return mSectionBoundaryIndices.contains(index);
251 }
252
253 /**
254 * Sets the index of the boundary between the section at {@code boundaryNum} and the following
255 * section to {@code boundaryIndex}.
256 */
257 public void setSectionBoundaryIndex(int boundaryNum, int boundaryIndex) {
258 mSectionBoundaryIndices.set(boundaryNum, boundaryIndex);
259 }
260
Selim Cineka59ecc32015-04-07 10:51:49 -0700261 public float getStackTranslation() {
262 return mStackTranslation;
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700263 }
264
Selim Cineka59ecc32015-04-07 10:51:49 -0700265 public void setStackTranslation(float stackTranslation) {
266 mStackTranslation = stackTranslation;
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700267 }
268
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700269 public void setLayoutHeight(int layoutHeight) {
270 mLayoutHeight = layoutHeight;
271 }
272
Selim Cineka59ecc32015-04-07 10:51:49 -0700273 public float getTopPadding() {
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700274 return mTopPadding;
275 }
276
277 public void setTopPadding(int topPadding) {
278 mTopPadding = topPadding;
279 }
280
281 public int getInnerHeight() {
Selim Cinekc25989e2018-02-16 16:42:14 -0800282 return Math.max(Math.min(mLayoutHeight, mMaxLayoutHeight) - mTopPadding, mLayoutMinHeight);
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700283 }
284
285 public boolean isShadeExpanded() {
286 return mShadeExpanded;
287 }
288
289 public void setShadeExpanded(boolean shadeExpanded) {
290 mShadeExpanded = shadeExpanded;
291 }
292
293 public void setMaxHeadsUpTranslation(float maxHeadsUpTranslation) {
294 mMaxHeadsUpTranslation = maxHeadsUpTranslation;
295 }
296
297 public float getMaxHeadsUpTranslation() {
298 return mMaxHeadsUpTranslation;
299 }
Selim Cineka59ecc32015-04-07 10:51:49 -0700300
Selim Cinek9c17b772015-07-07 20:37:09 -0700301 public void setDismissAllInProgress(boolean dismissAllInProgress) {
302 mDismissAllInProgress = dismissAllInProgress;
303 }
304
305 public boolean isDismissAllInProgress() {
306 return mDismissAllInProgress;
307 }
Selim Cinekbc243a92016-09-27 16:35:13 -0700308
309 public void setLayoutMinHeight(int layoutMinHeight) {
310 mLayoutMinHeight = layoutMinHeight;
311 }
Selim Cinek281c2022016-10-13 19:14:43 -0700312
313 public void setShelf(NotificationShelf shelf) {
314 mShelf = shelf;
315 }
316
Eliot Courtney5d3d2d02018-01-18 15:59:03 +0900317 @Nullable
Selim Cinek281c2022016-10-13 19:14:43 -0700318 public NotificationShelf getShelf() {
319 return mShelf;
320 }
Selim Cinek91d4cba2016-11-10 19:59:48 -0800321
322 public void setLayoutMaxHeight(int maxLayoutHeight) {
323 mMaxLayoutHeight = maxLayoutHeight;
324 }
Selim Cinekdb167372016-11-17 15:41:17 -0800325
326 /**
327 * Sets the last visible view of the host layout, that has a background, i.e the very last
328 * view in the shade, without the clear all button.
329 */
330 public void setLastVisibleBackgroundChild(
331 ActivatableNotificationView lastVisibleBackgroundChild) {
332 mLastVisibleBackgroundChild = lastVisibleBackgroundChild;
333 }
334
335 public ActivatableNotificationView getLastVisibleBackgroundChild() {
336 return mLastVisibleBackgroundChild;
337 }
Selim Cinek727903c2016-12-06 17:28:10 -0800338
339 public void setCurrentScrollVelocity(float currentScrollVelocity) {
340 mCurrentScrollVelocity = currentScrollVelocity;
341 }
342
343 public float getCurrentScrollVelocity() {
344 return mCurrentScrollVelocity;
345 }
Selim Cinek355652a2016-12-07 13:32:12 -0800346
347 public boolean isOnKeyguard() {
348 return mStatusBarState == StatusBarState.KEYGUARD;
349 }
350
351 public void setStatusBarState(int statusBarState) {
352 mStatusBarState = statusBarState;
353 }
Selim Cinekd5ab6452016-12-08 16:34:00 -0800354
355 public void setExpandingVelocity(float expandingVelocity) {
356 mExpandingVelocity = expandingVelocity;
357 }
358
359 public void setExpansionChanging(boolean expansionChanging) {
360 mExpansionChanging = expansionChanging;
361 }
362
363 public boolean isExpansionChanging() {
364 return mExpansionChanging;
365 }
366
367 public float getExpandingVelocity() {
368 return mExpandingVelocity;
369 }
370
371 public void setPanelTracking(boolean panelTracking) {
372 mPanelTracking = panelTracking;
373 }
374
Selim Cinekbe2c4432017-05-30 12:11:09 -0700375 public boolean hasPulsingNotifications() {
Lucas Dupin00be88f2019-01-03 17:50:52 -0800376 return mPulsing && mAmbientPulseManager != null
377 && mAmbientPulseManager.hasNotifications();
Adrian Roosd83e9992017-03-16 15:17:57 -0700378 }
379
yoshiki iguchi4e30e762018-02-06 12:09:23 +0900380 public void setPulsing(boolean hasPulsing) {
Selim Cinekebf42342017-07-13 15:46:10 +0200381 mPulsing = hasPulsing;
382 }
383
Ned Burnsf81c4c42019-01-07 14:10:43 -0500384 public boolean isPulsing(NotificationEntry entry) {
Kevina97ea052018-09-11 13:53:18 -0700385 if (!mPulsing || mAmbientPulseManager == null) {
Selim Cinekebf42342017-07-13 15:46:10 +0200386 return false;
387 }
Kevina97ea052018-09-11 13:53:18 -0700388 return mAmbientPulseManager.isAlerting(entry.key);
Adrian Roosd83e9992017-03-16 15:17:57 -0700389 }
390
Selim Cinekd5ab6452016-12-08 16:34:00 -0800391 public boolean isPanelTracking() {
392 return mPanelTracking;
393 }
Selim Cinekfcff4c62016-12-27 14:26:06 +0100394
395 public boolean isPanelFullWidth() {
396 return mPanelFullWidth;
397 }
398
399 public void setPanelFullWidth(boolean panelFullWidth) {
400 mPanelFullWidth = panelFullWidth;
401 }
Selim Cinekec29d342017-05-05 18:31:49 -0700402
403 public void setUnlockHintRunning(boolean unlockHintRunning) {
404 mUnlockHintRunning = unlockHintRunning;
405 }
406
407 public boolean isUnlockHintRunning() {
408 return mUnlockHintRunning;
409 }
Selim Cinek5cf1d052017-06-01 17:36:46 -0700410
411 public boolean isQsCustomizerShowing() {
412 return mQsCustomizerShowing;
413 }
414
415 public void setQsCustomizerShowing(boolean qsCustomizerShowing) {
416 mQsCustomizerShowing = qsCustomizerShowing;
417 }
Selim Cinek1f624952017-06-08 19:11:50 -0700418
419 public void setIntrinsicPadding(int intrinsicPadding) {
420 mIntrinsicPadding = intrinsicPadding;
421 }
422
423 public int getIntrinsicPadding() {
424 return mIntrinsicPadding;
425 }
Selim Cinekebf42342017-07-13 15:46:10 +0200426
427 /**
428 * Similar to the normal is above shelf logic but doesn't allow it to be above in AOD1.
429 *
430 * @param expandableView the view to check
431 */
432 public boolean isAboveShelf(ExpandableView expandableView) {
433 if (!(expandableView instanceof ExpandableNotificationRow)) {
434 return expandableView.isAboveShelf();
435 }
436 ExpandableNotificationRow row = (ExpandableNotificationRow) expandableView;
437 return row.isAboveShelf() && !isDozingAndNotPulsing(row);
438 }
439
440 /**
441 * @return whether a view is dozing and not pulsing right now
442 */
443 public boolean isDozingAndNotPulsing(ExpandableView view) {
444 if (view instanceof ExpandableNotificationRow) {
445 return isDozingAndNotPulsing((ExpandableNotificationRow) view);
446 }
447 return false;
448 }
449
450 /**
451 * @return whether a row is dozing and not pulsing right now
452 */
453 public boolean isDozingAndNotPulsing(ExpandableNotificationRow row) {
454 return isDark() && !isPulsing(row.getEntry());
455 }
Selim Cinek2627d722018-01-19 12:16:49 -0800456
457 public void setExpandAnimationTopChange(int expandAnimationTopChange) {
458 mExpandAnimationTopChange = expandAnimationTopChange;
459 }
460
461 public void setExpandingNotification(ExpandableNotificationRow row) {
462 mExpandingNotification = row;
463 }
464
465 public ExpandableNotificationRow getExpandingNotification() {
466 return mExpandingNotification;
467 }
468
469 public int getExpandAnimationTopChange() {
470 return mExpandAnimationTopChange;
471 }
Lucas Dupin16cfe452018-02-08 13:14:50 -0800472
473 /**
Lucas Dupin16cfe452018-02-08 13:14:50 -0800474 * @return {@code true } when shade is completely dark: in AOD or ambient display.
475 */
476 public boolean isFullyDark() {
Lucas Dupinb561eda2018-04-09 17:25:04 -0700477 return mDarkAmount == 1;
Lucas Dupin16cfe452018-02-08 13:14:50 -0800478 }
479
Gus Prevas99ba4ba2018-10-01 16:40:23 -0400480 public boolean isDarkAtAll() {
481 return mDarkAmount != 0;
482 }
483
shawnlin5be1f7c2018-05-21 20:50:54 +0800484 public void setAppearing(boolean appearing) {
485 mAppearing = appearing;
486 }
487
488 public boolean isAppearing() {
489 return mAppearing;
490 }
Jorim Jaggid552d9d2014-05-07 19:41:13 +0200491}