1 /* 2 * Copyright (C) 2017 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.phone; 18 19 import android.graphics.Color; 20 import android.os.Trace; 21 22 import com.android.systemui.dock.DockManager; 23 import com.android.systemui.scrim.ScrimView; 24 import com.android.systemui.statusbar.notification.stack.StackStateAnimator; 25 26 /** 27 * Possible states of the ScrimController state machine. 28 */ 29 public enum ScrimState { 30 31 /** 32 * Initial state. 33 */ 34 UNINITIALIZED, 35 36 /** 37 * When turned off by sensors (prox, presence.) 38 */ 39 OFF { 40 @Override prepare(ScrimState previousState)41 public void prepare(ScrimState previousState) { 42 mFrontTint = Color.BLACK; 43 mBehindTint = Color.BLACK; 44 45 mFrontAlpha = 1f; 46 mBehindAlpha = 1f; 47 48 mAnimationDuration = ScrimController.ANIMATION_DURATION_LONG; 49 } 50 51 @Override isLowPowerState()52 public boolean isLowPowerState() { 53 return true; 54 } 55 }, 56 57 /** 58 * On the lock screen. 59 */ 60 KEYGUARD { 61 @Override prepare(ScrimState previousState)62 public void prepare(ScrimState previousState) { 63 mBlankScreen = false; 64 if (previousState == ScrimState.AOD) { 65 mAnimationDuration = StackStateAnimator.ANIMATION_DURATION_WAKEUP_SCRIM; 66 if (mDisplayRequiresBlanking) { 67 // DisplayPowerManager will blank the screen, we'll just 68 // set our scrim to black in this frame to avoid flickering and 69 // fade it out afterwards. 70 mBlankScreen = true; 71 } 72 } else if (previousState == ScrimState.KEYGUARD) { 73 mAnimationDuration = StackStateAnimator.ANIMATION_DURATION_WAKEUP_SCRIM; 74 } else { 75 mAnimationDuration = ScrimController.ANIMATION_DURATION; 76 } 77 mFrontTint = Color.BLACK; 78 mBehindTint = Color.BLACK; 79 mNotifTint = mClipQsScrim ? Color.BLACK : Color.TRANSPARENT; 80 81 mFrontAlpha = 0; 82 mBehindAlpha = mClipQsScrim ? 1 : mScrimBehindAlphaKeyguard; 83 mNotifAlpha = mClipQsScrim ? mScrimBehindAlphaKeyguard : 0; 84 if (mClipQsScrim) { 85 updateScrimColor(mScrimBehind, 1f /* alpha */, Color.BLACK); 86 } 87 } 88 }, 89 90 AUTH_SCRIMMED_SHADE { 91 @Override prepare(ScrimState previousState)92 public void prepare(ScrimState previousState) { 93 // notif scrim alpha values are determined by ScrimController#applyState 94 // based on the shade expansion 95 96 mFrontTint = Color.BLACK; 97 mFrontAlpha = .66f; 98 99 mBehindTint = Color.BLACK; 100 mBehindAlpha = 1f; 101 } 102 }, 103 104 AUTH_SCRIMMED { 105 @Override prepare(ScrimState previousState)106 public void prepare(ScrimState previousState) { 107 mNotifTint = previousState.mNotifTint; 108 mNotifAlpha = previousState.mNotifAlpha; 109 110 mBehindTint = previousState.mBehindTint; 111 mBehindAlpha = previousState.mBehindAlpha; 112 113 mFrontTint = Color.BLACK; 114 mFrontAlpha = .66f; 115 } 116 }, 117 118 /** 119 * Showing password challenge on the keyguard. 120 */ 121 BOUNCER { 122 @Override prepare(ScrimState previousState)123 public void prepare(ScrimState previousState) { 124 mBehindAlpha = mClipQsScrim ? 1 : mDefaultScrimAlpha; 125 mBehindTint = mClipQsScrim ? Color.BLACK : Color.TRANSPARENT; 126 mNotifAlpha = mClipQsScrim ? mDefaultScrimAlpha : 0; 127 mNotifTint = Color.TRANSPARENT; 128 mFrontAlpha = 0f; 129 } 130 }, 131 132 /** 133 * Showing password challenge on top of a FLAG_SHOW_WHEN_LOCKED activity. 134 */ 135 BOUNCER_SCRIMMED { 136 @Override prepare(ScrimState previousState)137 public void prepare(ScrimState previousState) { 138 mBehindAlpha = 0; 139 mFrontAlpha = mDefaultScrimAlpha; 140 } 141 }, 142 143 SHADE_LOCKED { 144 @Override prepare(ScrimState previousState)145 public void prepare(ScrimState previousState) { 146 mBehindAlpha = mClipQsScrim ? 1 : mDefaultScrimAlpha; 147 mNotifAlpha = 1f; 148 mFrontAlpha = 0f; 149 mBehindTint = mClipQsScrim ? Color.TRANSPARENT : Color.BLACK; 150 151 if (mClipQsScrim) { 152 updateScrimColor(mScrimBehind, 1f /* alpha */, Color.BLACK); 153 } 154 } 155 }, 156 157 /** 158 * Changing screen brightness from quick settings. 159 */ 160 BRIGHTNESS_MIRROR { 161 @Override prepare(ScrimState previousState)162 public void prepare(ScrimState previousState) { 163 mBehindAlpha = 0; 164 mFrontAlpha = 0; 165 } 166 }, 167 168 /** 169 * Always on display or screen off. 170 */ 171 AOD { 172 @Override prepare(ScrimState previousState)173 public void prepare(ScrimState previousState) { 174 final boolean alwaysOnEnabled = mDozeParameters.getAlwaysOn(); 175 final boolean quickPickupEnabled = mDozeParameters.isQuickPickupEnabled(); 176 final boolean isDocked = mDockManager.isDocked(); 177 mBlankScreen = mDisplayRequiresBlanking; 178 179 mFrontTint = Color.BLACK; 180 mFrontAlpha = (alwaysOnEnabled || isDocked || quickPickupEnabled) 181 ? mAodFrontScrimAlpha : 1f; 182 183 mBehindTint = Color.BLACK; 184 mBehindAlpha = ScrimController.TRANSPARENT; 185 186 mAnimationDuration = ScrimController.ANIMATION_DURATION_LONG; 187 // DisplayPowerManager may blank the screen for us, or we might blank it for ourselves 188 // by animating the screen off via the LightRevelScrim. In either case we just need to 189 // set our state. 190 mAnimateChange = mDozeParameters.shouldControlScreenOff() 191 && !mDozeParameters.shouldShowLightRevealScrim(); 192 } 193 194 @Override getMaxLightRevealScrimAlpha()195 public float getMaxLightRevealScrimAlpha() { 196 return mWallpaperSupportsAmbientMode && !mHasBackdrop ? 0f : 1f; 197 } 198 199 @Override isLowPowerState()200 public boolean isLowPowerState() { 201 return true; 202 } 203 204 @Override shouldBlendWithMainColor()205 public boolean shouldBlendWithMainColor() { 206 return false; 207 } 208 }, 209 210 /** 211 * When phone wakes up because you received a notification. 212 */ 213 PULSING { 214 @Override prepare(ScrimState previousState)215 public void prepare(ScrimState previousState) { 216 mFrontAlpha = mAodFrontScrimAlpha; 217 mBehindTint = Color.BLACK; 218 mFrontTint = Color.BLACK; 219 mBlankScreen = mDisplayRequiresBlanking; 220 mAnimationDuration = mWakeLockScreenSensorActive 221 ? ScrimController.ANIMATION_DURATION_LONG : ScrimController.ANIMATION_DURATION; 222 } 223 @Override getMaxLightRevealScrimAlpha()224 public float getMaxLightRevealScrimAlpha() { 225 return mWakeLockScreenSensorActive ? ScrimController.WAKE_SENSOR_SCRIM_ALPHA 226 : AOD.getMaxLightRevealScrimAlpha(); 227 } 228 }, 229 230 /** 231 * Unlocked on top of an app (launcher or any other activity.) 232 */ 233 UNLOCKED { 234 @Override prepare(ScrimState previousState)235 public void prepare(ScrimState previousState) { 236 // State that UI will sync to. 237 mBehindAlpha = mClipQsScrim ? 1 : 0; 238 mNotifAlpha = 0; 239 mFrontAlpha = 0; 240 241 mAnimationDuration = mKeyguardFadingAway 242 ? mKeyguardFadingAwayDuration 243 : CentralSurfaces.FADE_KEYGUARD_DURATION; 244 245 boolean fromAod = previousState == AOD || previousState == PULSING; 246 // If launch/occlude animations were playing, they already animated the scrim 247 // alpha to 0f as part of the animation. If we animate it now, we'll set it back 248 // to 1f and animate it back to 0f, causing an unwanted scrim flash. 249 mAnimateChange = !mLaunchingAffordanceWithPreview 250 && !mOccludeAnimationPlaying 251 && !fromAod; 252 253 mFrontTint = Color.TRANSPARENT; 254 mBehindTint = Color.BLACK; 255 mBlankScreen = false; 256 257 if (mDisplayRequiresBlanking && previousState == ScrimState.AOD) { 258 // Set all scrims black, before they fade transparent. 259 updateScrimColor(mScrimInFront, 1f /* alpha */, Color.BLACK /* tint */); 260 updateScrimColor(mScrimBehind, 1f /* alpha */, Color.BLACK /* tint */); 261 262 // Scrims should still be black at the end of the transition. 263 mFrontTint = Color.BLACK; 264 mBehindTint = Color.BLACK; 265 mBlankScreen = true; 266 } 267 268 if (mClipQsScrim) { 269 updateScrimColor(mScrimBehind, 1f /* alpha */, Color.BLACK); 270 } 271 } 272 }, 273 274 DREAMING { 275 @Override prepare(ScrimState previousState)276 public void prepare(ScrimState previousState) { 277 mFrontTint = Color.TRANSPARENT; 278 mBehindTint = Color.BLACK; 279 mNotifTint = mClipQsScrim ? Color.BLACK : Color.TRANSPARENT; 280 281 mFrontAlpha = 0; 282 mBehindAlpha = mClipQsScrim ? 1 : 0; 283 mNotifAlpha = 0; 284 285 mBlankScreen = false; 286 287 if (mClipQsScrim) { 288 updateScrimColor(mScrimBehind, 1f /* alpha */, Color.BLACK); 289 } 290 } 291 }; 292 293 boolean mBlankScreen = false; 294 long mAnimationDuration = ScrimController.ANIMATION_DURATION; 295 int mFrontTint = Color.TRANSPARENT; 296 int mBehindTint = Color.TRANSPARENT; 297 int mNotifTint = Color.TRANSPARENT; 298 299 boolean mAnimateChange = true; 300 float mAodFrontScrimAlpha; 301 float mFrontAlpha; 302 float mBehindAlpha; 303 float mNotifAlpha; 304 305 float mScrimBehindAlphaKeyguard; 306 float mDefaultScrimAlpha; 307 ScrimView mScrimInFront; 308 ScrimView mScrimBehind; 309 310 DozeParameters mDozeParameters; 311 DockManager mDockManager; 312 boolean mDisplayRequiresBlanking; 313 boolean mWallpaperSupportsAmbientMode; 314 boolean mHasBackdrop; 315 boolean mLaunchingAffordanceWithPreview; 316 boolean mOccludeAnimationPlaying; 317 boolean mWakeLockScreenSensorActive; 318 boolean mKeyguardFadingAway; 319 long mKeyguardFadingAwayDuration; 320 boolean mClipQsScrim; 321 init(ScrimView scrimInFront, ScrimView scrimBehind, DozeParameters dozeParameters, DockManager dockManager)322 public void init(ScrimView scrimInFront, ScrimView scrimBehind, DozeParameters dozeParameters, 323 DockManager dockManager) { 324 mScrimInFront = scrimInFront; 325 mScrimBehind = scrimBehind; 326 327 mDozeParameters = dozeParameters; 328 mDockManager = dockManager; 329 mDisplayRequiresBlanking = dozeParameters.getDisplayNeedsBlanking(); 330 } 331 332 /** Prepare state for transition. */ prepare(ScrimState previousState)333 public void prepare(ScrimState previousState) { 334 } 335 336 /** 337 * Whether a particular state should enable blending with extracted theme colors. 338 */ shouldBlendWithMainColor()339 public boolean shouldBlendWithMainColor() { 340 return true; 341 } 342 getFrontAlpha()343 public float getFrontAlpha() { 344 return mFrontAlpha; 345 } 346 getBehindAlpha()347 public float getBehindAlpha() { 348 return mBehindAlpha; 349 } 350 getMaxLightRevealScrimAlpha()351 public float getMaxLightRevealScrimAlpha() { 352 return 1f; 353 } 354 getNotifAlpha()355 public float getNotifAlpha() { 356 return mNotifAlpha; 357 } 358 getFrontTint()359 public int getFrontTint() { 360 return mFrontTint; 361 } 362 getBehindTint()363 public int getBehindTint() { 364 return mBehindTint; 365 } 366 getNotifTint()367 public int getNotifTint() { 368 return mNotifTint; 369 } 370 getAnimationDuration()371 public long getAnimationDuration() { 372 return mAnimationDuration; 373 } 374 getBlanksScreen()375 public boolean getBlanksScreen() { 376 return mBlankScreen; 377 } 378 updateScrimColor(ScrimView scrim, float alpha, int tint)379 public void updateScrimColor(ScrimView scrim, float alpha, int tint) { 380 if (ScrimController.DEBUG_MODE) { 381 tint = scrim == mScrimInFront ? ScrimController.DEBUG_FRONT_TINT 382 : ScrimController.DEBUG_BEHIND_TINT; 383 } 384 Trace.traceCounter(Trace.TRACE_TAG_APP, 385 scrim == mScrimInFront ? "front_scrim_alpha" : "back_scrim_alpha", 386 (int) (alpha * 255)); 387 388 Trace.traceCounter(Trace.TRACE_TAG_APP, 389 scrim == mScrimInFront ? "front_scrim_tint" : "back_scrim_tint", 390 Color.alpha(tint)); 391 392 scrim.setTint(tint); 393 scrim.setViewAlpha(alpha); 394 } 395 getAnimateChange()396 public boolean getAnimateChange() { 397 return mAnimateChange; 398 } 399 setAodFrontScrimAlpha(float aodFrontScrimAlpha)400 public void setAodFrontScrimAlpha(float aodFrontScrimAlpha) { 401 mAodFrontScrimAlpha = aodFrontScrimAlpha; 402 } 403 setScrimBehindAlphaKeyguard(float scrimBehindAlphaKeyguard)404 public void setScrimBehindAlphaKeyguard(float scrimBehindAlphaKeyguard) { 405 mScrimBehindAlphaKeyguard = scrimBehindAlphaKeyguard; 406 } 407 setDefaultScrimAlpha(float defaultScrimAlpha)408 public void setDefaultScrimAlpha(float defaultScrimAlpha) { 409 mDefaultScrimAlpha = defaultScrimAlpha; 410 } 411 setWallpaperSupportsAmbientMode(boolean wallpaperSupportsAmbientMode)412 public void setWallpaperSupportsAmbientMode(boolean wallpaperSupportsAmbientMode) { 413 mWallpaperSupportsAmbientMode = wallpaperSupportsAmbientMode; 414 } 415 setLaunchingAffordanceWithPreview(boolean launchingAffordanceWithPreview)416 public void setLaunchingAffordanceWithPreview(boolean launchingAffordanceWithPreview) { 417 mLaunchingAffordanceWithPreview = launchingAffordanceWithPreview; 418 } 419 setOccludeAnimationPlaying(boolean occludeAnimationPlaying)420 public void setOccludeAnimationPlaying(boolean occludeAnimationPlaying) { 421 mOccludeAnimationPlaying = occludeAnimationPlaying; 422 } 423 isLowPowerState()424 public boolean isLowPowerState() { 425 return false; 426 } 427 setHasBackdrop(boolean hasBackdrop)428 public void setHasBackdrop(boolean hasBackdrop) { 429 mHasBackdrop = hasBackdrop; 430 } 431 setWakeLockScreenSensorActive(boolean active)432 public void setWakeLockScreenSensorActive(boolean active) { 433 mWakeLockScreenSensorActive = active; 434 } 435 setKeyguardFadingAway(boolean fadingAway, long duration)436 public void setKeyguardFadingAway(boolean fadingAway, long duration) { 437 mKeyguardFadingAway = fadingAway; 438 mKeyguardFadingAwayDuration = duration; 439 } 440 setClipQsScrim(boolean clipsQsScrim)441 public void setClipQsScrim(boolean clipsQsScrim) { 442 mClipQsScrim = clipsQsScrim; 443 } 444 } 445