1 /* 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 17 package com.android.systemui.statusbar.stack; 18 19 import android.annotation.Nullable; 20 import android.content.Context; 21 import android.view.View; 22 23 import com.android.systemui.R; 24 import com.android.systemui.statusbar.ActivatableNotificationView; 25 import com.android.systemui.statusbar.ExpandableNotificationRow; 26 import com.android.systemui.statusbar.ExpandableView; 27 import com.android.systemui.statusbar.NotificationData; 28 import com.android.systemui.statusbar.NotificationShelf; 29 import com.android.systemui.statusbar.StatusBarState; 30 import com.android.systemui.statusbar.policy.HeadsUpManager; 31 32 import java.util.ArrayList; 33 34 /** 35 * A global state to track all input states for the algorithm. 36 */ 37 public class AmbientState { 38 private ArrayList<View> mDraggedViews = new ArrayList<View>(); 39 private int mScrollY; 40 private boolean mDimmed; 41 private ActivatableNotificationView mActivatedChild; 42 private float mOverScrollTopAmount; 43 private float mOverScrollBottomAmount; 44 private int mSpeedBumpIndex = -1; 45 private boolean mDark; 46 private boolean mHideSensitive; 47 private HeadsUpManager mHeadsUpManager; 48 private float mStackTranslation; 49 private int mLayoutHeight; 50 private int mTopPadding; 51 private boolean mShadeExpanded; 52 private float mMaxHeadsUpTranslation; 53 private boolean mDismissAllInProgress; 54 private int mLayoutMinHeight; 55 private NotificationShelf mShelf; 56 private int mZDistanceBetweenElements; 57 private int mBaseZHeight; 58 private int mMaxLayoutHeight; 59 private ActivatableNotificationView mLastVisibleBackgroundChild; 60 private float mCurrentScrollVelocity; 61 private int mStatusBarState; 62 private float mExpandingVelocity; 63 private boolean mPanelTracking; 64 private boolean mExpansionChanging; 65 private boolean mPanelFullWidth; 66 private boolean mPulsing; 67 private boolean mUnlockHintRunning; 68 private boolean mQsCustomizerShowing; 69 private int mIntrinsicPadding; 70 private int mExpandAnimationTopChange; 71 private ExpandableNotificationRow mExpandingNotification; 72 private int mDarkTopPadding; 73 private float mDarkAmount; 74 private boolean mAppearing; 75 AmbientState(Context context)76 public AmbientState(Context context) { 77 reload(context); 78 } 79 80 /** 81 * Reload the dimens e.g. if the density changed. 82 */ reload(Context context)83 public void reload(Context context) { 84 mZDistanceBetweenElements = getZDistanceBetweenElements(context); 85 mBaseZHeight = getBaseHeight(mZDistanceBetweenElements); 86 } 87 getZDistanceBetweenElements(Context context)88 private static int getZDistanceBetweenElements(Context context) { 89 return Math.max(1, context.getResources() 90 .getDimensionPixelSize(R.dimen.z_distance_between_notifications)); 91 } 92 getBaseHeight(int zdistanceBetweenElements)93 private static int getBaseHeight(int zdistanceBetweenElements) { 94 return 4 * zdistanceBetweenElements; 95 } 96 97 /** 98 * @return the launch height for notifications that are launched 99 */ getNotificationLaunchHeight(Context context)100 public static int getNotificationLaunchHeight(Context context) { 101 int zDistance = getZDistanceBetweenElements(context); 102 return getBaseHeight(zDistance) * 2; 103 } 104 105 /** 106 * @return the basic Z height on which notifications remain. 107 */ getBaseZHeight()108 public int getBaseZHeight() { 109 return mBaseZHeight; 110 } 111 112 /** 113 * @return the distance in Z between two overlaying notifications. 114 */ getZDistanceBetweenElements()115 public int getZDistanceBetweenElements() { 116 return mZDistanceBetweenElements; 117 } 118 getScrollY()119 public int getScrollY() { 120 return mScrollY; 121 } 122 setScrollY(int scrollY)123 public void setScrollY(int scrollY) { 124 this.mScrollY = scrollY; 125 } 126 onBeginDrag(View view)127 public void onBeginDrag(View view) { 128 mDraggedViews.add(view); 129 } 130 onDragFinished(View view)131 public void onDragFinished(View view) { 132 mDraggedViews.remove(view); 133 } 134 getDraggedViews()135 public ArrayList<View> getDraggedViews() { 136 return mDraggedViews; 137 } 138 139 /** 140 * @param dimmed Whether we are in a dimmed state (on the lockscreen), where the backgrounds are 141 * translucent and everything is scaled back a bit. 142 */ setDimmed(boolean dimmed)143 public void setDimmed(boolean dimmed) { 144 mDimmed = dimmed; 145 } 146 147 /** In dark mode, we draw as little as possible, assuming a black background */ setDark(boolean dark)148 public void setDark(boolean dark) { 149 mDark = dark; 150 } 151 152 /** Dark ratio of the status bar **/ setDarkAmount(float darkAmount)153 public void setDarkAmount(float darkAmount) { 154 mDarkAmount = darkAmount; 155 } 156 157 /** Returns the dark ratio of the status bar */ getDarkAmount()158 public float getDarkAmount() { 159 return mDarkAmount; 160 } 161 setHideSensitive(boolean hideSensitive)162 public void setHideSensitive(boolean hideSensitive) { 163 mHideSensitive = hideSensitive; 164 } 165 166 /** 167 * In dimmed mode, a child can be activated, which happens on the first tap of the double-tap 168 * interaction. This child is then scaled normally and its background is fully opaque. 169 */ setActivatedChild(ActivatableNotificationView activatedChild)170 public void setActivatedChild(ActivatableNotificationView activatedChild) { 171 mActivatedChild = activatedChild; 172 } 173 isDimmed()174 public boolean isDimmed() { 175 return mDimmed; 176 } 177 isDark()178 public boolean isDark() { 179 return mDark; 180 } 181 isHideSensitive()182 public boolean isHideSensitive() { 183 return mHideSensitive; 184 } 185 getActivatedChild()186 public ActivatableNotificationView getActivatedChild() { 187 return mActivatedChild; 188 } 189 setOverScrollAmount(float amount, boolean onTop)190 public void setOverScrollAmount(float amount, boolean onTop) { 191 if (onTop) { 192 mOverScrollTopAmount = amount; 193 } else { 194 mOverScrollBottomAmount = amount; 195 } 196 } 197 getOverScrollAmount(boolean top)198 public float getOverScrollAmount(boolean top) { 199 return top ? mOverScrollTopAmount : mOverScrollBottomAmount; 200 } 201 getSpeedBumpIndex()202 public int getSpeedBumpIndex() { 203 return mSpeedBumpIndex; 204 } 205 setSpeedBumpIndex(int shelfIndex)206 public void setSpeedBumpIndex(int shelfIndex) { 207 mSpeedBumpIndex = shelfIndex; 208 } 209 setHeadsUpManager(HeadsUpManager headsUpManager)210 public void setHeadsUpManager(HeadsUpManager headsUpManager) { 211 mHeadsUpManager = headsUpManager; 212 } 213 getStackTranslation()214 public float getStackTranslation() { 215 return mStackTranslation; 216 } 217 setStackTranslation(float stackTranslation)218 public void setStackTranslation(float stackTranslation) { 219 mStackTranslation = stackTranslation; 220 } 221 setLayoutHeight(int layoutHeight)222 public void setLayoutHeight(int layoutHeight) { 223 mLayoutHeight = layoutHeight; 224 } 225 getTopPadding()226 public float getTopPadding() { 227 return mTopPadding; 228 } 229 setTopPadding(int topPadding)230 public void setTopPadding(int topPadding) { 231 mTopPadding = topPadding; 232 } 233 getInnerHeight()234 public int getInnerHeight() { 235 return Math.max(Math.min(mLayoutHeight, mMaxLayoutHeight) - mTopPadding, mLayoutMinHeight); 236 } 237 isShadeExpanded()238 public boolean isShadeExpanded() { 239 return mShadeExpanded; 240 } 241 setShadeExpanded(boolean shadeExpanded)242 public void setShadeExpanded(boolean shadeExpanded) { 243 mShadeExpanded = shadeExpanded; 244 } 245 setMaxHeadsUpTranslation(float maxHeadsUpTranslation)246 public void setMaxHeadsUpTranslation(float maxHeadsUpTranslation) { 247 mMaxHeadsUpTranslation = maxHeadsUpTranslation; 248 } 249 getMaxHeadsUpTranslation()250 public float getMaxHeadsUpTranslation() { 251 return mMaxHeadsUpTranslation; 252 } 253 setDismissAllInProgress(boolean dismissAllInProgress)254 public void setDismissAllInProgress(boolean dismissAllInProgress) { 255 mDismissAllInProgress = dismissAllInProgress; 256 } 257 isDismissAllInProgress()258 public boolean isDismissAllInProgress() { 259 return mDismissAllInProgress; 260 } 261 setLayoutMinHeight(int layoutMinHeight)262 public void setLayoutMinHeight(int layoutMinHeight) { 263 mLayoutMinHeight = layoutMinHeight; 264 } 265 setShelf(NotificationShelf shelf)266 public void setShelf(NotificationShelf shelf) { 267 mShelf = shelf; 268 } 269 270 @Nullable getShelf()271 public NotificationShelf getShelf() { 272 return mShelf; 273 } 274 setLayoutMaxHeight(int maxLayoutHeight)275 public void setLayoutMaxHeight(int maxLayoutHeight) { 276 mMaxLayoutHeight = maxLayoutHeight; 277 } 278 279 /** 280 * Sets the last visible view of the host layout, that has a background, i.e the very last 281 * view in the shade, without the clear all button. 282 */ setLastVisibleBackgroundChild( ActivatableNotificationView lastVisibleBackgroundChild)283 public void setLastVisibleBackgroundChild( 284 ActivatableNotificationView lastVisibleBackgroundChild) { 285 mLastVisibleBackgroundChild = lastVisibleBackgroundChild; 286 } 287 getLastVisibleBackgroundChild()288 public ActivatableNotificationView getLastVisibleBackgroundChild() { 289 return mLastVisibleBackgroundChild; 290 } 291 setCurrentScrollVelocity(float currentScrollVelocity)292 public void setCurrentScrollVelocity(float currentScrollVelocity) { 293 mCurrentScrollVelocity = currentScrollVelocity; 294 } 295 getCurrentScrollVelocity()296 public float getCurrentScrollVelocity() { 297 return mCurrentScrollVelocity; 298 } 299 isOnKeyguard()300 public boolean isOnKeyguard() { 301 return mStatusBarState == StatusBarState.KEYGUARD; 302 } 303 setStatusBarState(int statusBarState)304 public void setStatusBarState(int statusBarState) { 305 mStatusBarState = statusBarState; 306 } 307 setExpandingVelocity(float expandingVelocity)308 public void setExpandingVelocity(float expandingVelocity) { 309 mExpandingVelocity = expandingVelocity; 310 } 311 setExpansionChanging(boolean expansionChanging)312 public void setExpansionChanging(boolean expansionChanging) { 313 mExpansionChanging = expansionChanging; 314 } 315 isExpansionChanging()316 public boolean isExpansionChanging() { 317 return mExpansionChanging; 318 } 319 getExpandingVelocity()320 public float getExpandingVelocity() { 321 return mExpandingVelocity; 322 } 323 setPanelTracking(boolean panelTracking)324 public void setPanelTracking(boolean panelTracking) { 325 mPanelTracking = panelTracking; 326 } 327 hasPulsingNotifications()328 public boolean hasPulsingNotifications() { 329 return mPulsing; 330 } 331 setPulsing(boolean hasPulsing)332 public void setPulsing(boolean hasPulsing) { 333 mPulsing = hasPulsing; 334 } 335 isPulsing(NotificationData.Entry entry)336 public boolean isPulsing(NotificationData.Entry entry) { 337 if (!mPulsing || mHeadsUpManager == null) { 338 return false; 339 } 340 return mHeadsUpManager.getAllEntries().anyMatch(e -> (e == entry)); 341 } 342 isPanelTracking()343 public boolean isPanelTracking() { 344 return mPanelTracking; 345 } 346 isPanelFullWidth()347 public boolean isPanelFullWidth() { 348 return mPanelFullWidth; 349 } 350 setPanelFullWidth(boolean panelFullWidth)351 public void setPanelFullWidth(boolean panelFullWidth) { 352 mPanelFullWidth = panelFullWidth; 353 } 354 setUnlockHintRunning(boolean unlockHintRunning)355 public void setUnlockHintRunning(boolean unlockHintRunning) { 356 mUnlockHintRunning = unlockHintRunning; 357 } 358 isUnlockHintRunning()359 public boolean isUnlockHintRunning() { 360 return mUnlockHintRunning; 361 } 362 isQsCustomizerShowing()363 public boolean isQsCustomizerShowing() { 364 return mQsCustomizerShowing; 365 } 366 setQsCustomizerShowing(boolean qsCustomizerShowing)367 public void setQsCustomizerShowing(boolean qsCustomizerShowing) { 368 mQsCustomizerShowing = qsCustomizerShowing; 369 } 370 setIntrinsicPadding(int intrinsicPadding)371 public void setIntrinsicPadding(int intrinsicPadding) { 372 mIntrinsicPadding = intrinsicPadding; 373 } 374 getIntrinsicPadding()375 public int getIntrinsicPadding() { 376 return mIntrinsicPadding; 377 } 378 379 /** 380 * Similar to the normal is above shelf logic but doesn't allow it to be above in AOD1. 381 * 382 * @param expandableView the view to check 383 */ isAboveShelf(ExpandableView expandableView)384 public boolean isAboveShelf(ExpandableView expandableView) { 385 if (!(expandableView instanceof ExpandableNotificationRow)) { 386 return expandableView.isAboveShelf(); 387 } 388 ExpandableNotificationRow row = (ExpandableNotificationRow) expandableView; 389 return row.isAboveShelf() && !isDozingAndNotPulsing(row); 390 } 391 392 /** 393 * @return whether a view is dozing and not pulsing right now 394 */ isDozingAndNotPulsing(ExpandableView view)395 public boolean isDozingAndNotPulsing(ExpandableView view) { 396 if (view instanceof ExpandableNotificationRow) { 397 return isDozingAndNotPulsing((ExpandableNotificationRow) view); 398 } 399 return false; 400 } 401 402 /** 403 * @return whether a row is dozing and not pulsing right now 404 */ isDozingAndNotPulsing(ExpandableNotificationRow row)405 public boolean isDozingAndNotPulsing(ExpandableNotificationRow row) { 406 return isDark() && !isPulsing(row.getEntry()); 407 } 408 setExpandAnimationTopChange(int expandAnimationTopChange)409 public void setExpandAnimationTopChange(int expandAnimationTopChange) { 410 mExpandAnimationTopChange = expandAnimationTopChange; 411 } 412 setExpandingNotification(ExpandableNotificationRow row)413 public void setExpandingNotification(ExpandableNotificationRow row) { 414 mExpandingNotification = row; 415 } 416 getExpandingNotification()417 public ExpandableNotificationRow getExpandingNotification() { 418 return mExpandingNotification; 419 } 420 getExpandAnimationTopChange()421 public int getExpandAnimationTopChange() { 422 return mExpandAnimationTopChange; 423 } 424 425 /** 426 * @return {@code true } when shade is completely dark: in AOD or ambient display. 427 */ isFullyDark()428 public boolean isFullyDark() { 429 return mDarkAmount == 1; 430 } 431 setDarkTopPadding(int darkTopPadding)432 public void setDarkTopPadding(int darkTopPadding) { 433 mDarkTopPadding = darkTopPadding; 434 } 435 getDarkTopPadding()436 public int getDarkTopPadding() { 437 return mDarkTopPadding; 438 } 439 setAppearing(boolean appearing)440 public void setAppearing(boolean appearing) { 441 mAppearing = appearing; 442 } 443 isAppearing()444 public boolean isAppearing() { 445 return mAppearing; 446 } 447 } 448