blob: 7bbd3b5268928996b40dff2f81c47a4f6aca2dc1 [file] [log] [blame]
Jorim Jaggiecc798e2014-05-26 18:14:37 +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
19import android.animation.Animator;
20import android.animation.AnimatorListenerAdapter;
21import android.animation.ValueAnimator;
Lucas Dupin82aa1632017-12-13 00:13:57 -080022import android.app.AlarmManager;
Lucas Dupin8da8f2e92017-04-21 14:02:16 -070023import android.app.WallpaperManager;
John Spurlockd06aa572014-09-10 10:40:49 -040024import android.content.Context;
Lucas Dupin8da8f2e92017-04-21 14:02:16 -070025import android.graphics.Color;
Anthony Chene658cc22017-04-27 11:17:35 -070026import android.graphics.drawable.Drawable;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080027import android.os.Handler;
Adrian Roosa5c63222017-07-27 16:33:39 +020028import android.os.Trace;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080029import android.util.Log;
Lucas Dupina0bf8512017-05-24 17:04:47 -070030import android.util.MathUtils;
Jorim Jaggiecc798e2014-05-26 18:14:37 +020031import android.view.View;
32import android.view.ViewTreeObserver;
Jorim Jaggiecc798e2014-05-26 18:14:37 +020033import android.view.animation.DecelerateInterpolator;
34import android.view.animation.Interpolator;
Lucas Dupin8da8f2e92017-04-21 14:02:16 -070035
Lucas Dupin9e3fa102017-11-08 17:16:55 -080036import com.android.internal.annotations.VisibleForTesting;
Lucas Dupine2292a92017-07-06 14:35:30 -070037import com.android.internal.colorextraction.ColorExtractor;
38import com.android.internal.colorextraction.ColorExtractor.GradientColors;
39import com.android.internal.colorextraction.ColorExtractor.OnColorsChangedListener;
Lucas Dupin9324aa92017-07-26 20:29:38 -070040import com.android.internal.graphics.ColorUtils;
Yohei Yukawa795f0102018-04-13 14:55:30 -070041import com.android.internal.util.function.TriConsumer;
Jorim Jaggie8fde5d2016-06-30 23:41:37 -070042import com.android.keyguard.KeyguardUpdateMonitor;
Lucas Dupinf8463ee2018-06-11 16:18:15 -070043import com.android.keyguard.KeyguardUpdateMonitorCallback;
Lucas Dupin314d41f2017-05-08 15:52:58 -070044import com.android.systemui.Dependency;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080045import com.android.systemui.Dumpable;
John Spurlockbf370992014-06-17 13:58:31 -040046import com.android.systemui.R;
Lucas Dupin1ead7fc2017-05-24 14:14:44 -070047import com.android.systemui.colorextraction.SysuiColorExtractor;
Selim Cineka0fad3b2014-09-19 17:20:05 +020048import com.android.systemui.statusbar.ScrimView;
Rohan Shah20790b82018-07-02 17:21:04 -070049import com.android.systemui.statusbar.notification.stack.ViewState;
Lucas Dupin82aa1632017-12-13 00:13:57 -080050import com.android.systemui.util.AlarmTimeout;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080051import com.android.systemui.util.wakelock.DelayedWakeLock;
52import com.android.systemui.util.wakelock.WakeLock;
John Spurlockbf370992014-06-17 13:58:31 -040053
Lucas Dupin9e3fa102017-11-08 17:16:55 -080054import java.io.FileDescriptor;
Adrian Roosba7ca592017-08-15 17:48:05 +020055import java.io.PrintWriter;
Adrian Roosa5c63222017-07-27 16:33:39 +020056import java.util.function.Consumer;
57
Jorim Jaggiecc798e2014-05-26 18:14:37 +020058/**
59 * Controls both the scrim behind the notifications and in front of the notifications (when a
60 * security method gets shown).
61 */
Selim Cinek99e9adf2018-03-15 09:17:47 -070062public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnColorsChangedListener,
63 Dumpable {
Lucas Dupin9e3fa102017-11-08 17:16:55 -080064
Lucas Dupin55c6e802018-09-27 18:07:36 -070065 static final String TAG = "ScrimController";
Lucas Dupin9e3fa102017-11-08 17:16:55 -080066 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
67
Lucas Dupin4749f1b2018-04-04 15:09:06 -070068 /**
69 * General scrim animation duration.
70 */
John Spurlock8b12f222014-09-09 11:54:11 -040071 public static final long ANIMATION_DURATION = 220;
Lucas Dupin4749f1b2018-04-04 15:09:06 -070072 /**
73 * Longer duration, currently only used when going to AOD.
74 */
75 public static final long ANIMATION_DURATION_LONG = 1000;
Lucas Dupin82aa1632017-12-13 00:13:57 -080076 /**
77 * When both scrims have 0 alpha.
78 */
79 public static final int VISIBILITY_FULLY_TRANSPARENT = 0;
80 /**
81 * When scrims aren't transparent (alpha 0) but also not opaque (alpha 1.)
82 */
83 public static final int VISIBILITY_SEMI_TRANSPARENT = 1;
84 /**
85 * When at least 1 scrim is fully opaque (alpha set to 1.)
86 */
87 public static final int VISIBILITY_FULLY_OPAQUE = 2;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080088 /**
89 * Default alpha value for most scrims.
90 */
Lucas Dupin3d36dd82019-01-02 14:38:35 -080091 public static final float GRADIENT_SCRIM_ALPHA = 0.2f;
Lucas Dupin9e3fa102017-11-08 17:16:55 -080092 /**
93 * A scrim varies its opacity based on a busyness factor, for example
94 * how many notifications are currently visible.
95 */
Lucas Dupinde64ee02018-12-21 14:45:12 -080096 public static final float GRADIENT_SCRIM_ALPHA_BUSY = 0.7f;
Lucas Dupinde64ee02018-12-21 14:45:12 -080097
Lucas Dupin55c6e802018-09-27 18:07:36 -070098 /**
Lucas Dupin9e3fa102017-11-08 17:16:55 -080099 * The most common scrim, the one under the keyguard.
100 */
Lucas Dupina0bf8512017-05-24 17:04:47 -0700101 protected static final float SCRIM_BEHIND_ALPHA_KEYGUARD = GRADIENT_SCRIM_ALPHA;
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800102
103 static final int TAG_KEY_ANIM = R.id.scrim;
Selim Cinek5104a6d2015-12-18 18:38:31 -0800104 private static final int TAG_START_ALPHA = R.id.scrim_alpha_start;
105 private static final int TAG_END_ALPHA = R.id.scrim_alpha_end;
Selim Cinek511f2702017-04-10 19:53:01 -0700106 private static final float NOT_INITIALIZED = -1;
John Spurlockbf370992014-06-17 13:58:31 -0400107
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800108 private ScrimState mState = ScrimState.UNINITIALIZED;
109 private final Context mContext;
Xiaohui Chen5da71352016-02-22 10:04:41 -0800110 protected final ScrimView mScrimBehind;
Lucas Dupin8da8f2e92017-04-21 14:02:16 -0700111 protected final ScrimView mScrimInFront;
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800112 private final UnlockMethodCache mUnlockMethodCache;
Jorim Jaggie8fde5d2016-06-30 23:41:37 -0700113 private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800114 private final DozeParameters mDozeParameters;
Lucas Dupin82aa1632017-12-13 00:13:57 -0800115 private final AlarmTimeout mTimeTicker;
Lucas Dupin690c6f52018-07-10 15:28:57 -0700116 private final KeyguardVisibilityCallback mKeyguardVisibilityCallback;
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200117
Lucas Dupin1ead7fc2017-05-24 14:14:44 -0700118 private final SysuiColorExtractor mColorExtractor;
Lucas Dupine2292a92017-07-06 14:35:30 -0700119 private GradientColors mLockColors;
120 private GradientColors mSystemColors;
Lucas Dupin8da8f2e92017-04-21 14:02:16 -0700121 private boolean mNeedsDrawableColorUpdate;
122
Anthony Chen3cb3ad92016-12-01 10:58:47 -0800123 protected float mScrimBehindAlpha;
Lucas Dupin9324aa92017-07-26 20:29:38 -0700124 protected float mScrimBehindAlphaResValue;
Evan Rosky9a895012016-04-21 11:26:15 -0700125 protected float mScrimBehindAlphaKeyguard = SCRIM_BEHIND_ALPHA_KEYGUARD;
Xiaohui Chen4dab4b52016-03-07 12:31:14 -0800126
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800127 // Assuming the shade is expanded during initialization
128 private float mExpansionFraction = 1f;
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200129
130 private boolean mDarkenWhileDragging;
Lucas Dupin67f02632018-03-12 11:08:31 -0700131 private boolean mExpansionAffectsAlpha = true;
Evan Rosky9a895012016-04-21 11:26:15 -0700132 protected boolean mAnimateChange;
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200133 private boolean mUpdatePending;
Jorim Jaggie93698b2016-11-11 18:24:38 -0800134 private boolean mTracking;
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800135 protected long mAnimationDuration = -1;
Jorim Jaggie29b2db2014-05-30 23:17:03 +0200136 private long mAnimationDelay;
137 private Runnable mOnAnimationFinished;
Jorim Jaggif5304ad2017-07-17 18:31:13 +0200138 private boolean mDeferFinishedListener;
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200139 private final Interpolator mInterpolator = new DecelerateInterpolator();
Selim Cinek511f2702017-04-10 19:53:01 -0700140 private float mCurrentInFrontAlpha = NOT_INITIALIZED;
141 private float mCurrentBehindAlpha = NOT_INITIALIZED;
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800142 private int mCurrentInFrontTint;
143 private int mCurrentBehindTint;
Lucas Dupin82aa1632017-12-13 00:13:57 -0800144 private boolean mWallpaperVisibilityTimedOut;
Lucas Dupin82aa1632017-12-13 00:13:57 -0800145 private int mScrimsVisibility;
Yohei Yukawa795f0102018-04-13 14:55:30 -0700146 private final TriConsumer<ScrimState, Float, GradientColors> mScrimStateListener;
Lucas Dupin82aa1632017-12-13 00:13:57 -0800147 private final Consumer<Integer> mScrimVisibleListener;
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800148 private boolean mBlankScreen;
149 private boolean mScreenBlankingCallbackCalled;
150 private Callback mCallback;
Lucas Dupin82aa1632017-12-13 00:13:57 -0800151 private boolean mWallpaperSupportsAmbientMode;
Lucas Dupin3a64ed72018-02-12 12:44:37 -0800152 private boolean mScreenOn;
Lucas Dupin53cf12a2018-02-05 16:14:45 -0800153
154 // Scrim blanking callbacks
Lucas Dupin0791d972018-03-26 13:32:16 -0700155 private Runnable mPendingFrameCallback;
Lucas Dupin53cf12a2018-02-05 16:14:45 -0800156 private Runnable mBlankingTransitionRunnable;
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800157
158 private final WakeLock mWakeLock;
159 private boolean mWakeLockHeld;
Lucas Dupind5107302018-03-19 15:30:29 -0700160 private boolean mKeyguardOccluded;
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200161
shawnlin317db372018-04-09 19:49:48 +0800162 public ScrimController(ScrimView scrimBehind, ScrimView scrimInFront,
Yohei Yukawa795f0102018-04-13 14:55:30 -0700163 TriConsumer<ScrimState, Float, GradientColors> scrimStateListener,
shawnlin317db372018-04-09 19:49:48 +0800164 Consumer<Integer> scrimVisibleListener, DozeParameters dozeParameters,
165 AlarmManager alarmManager) {
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200166 mScrimBehind = scrimBehind;
167 mScrimInFront = scrimInFront;
Yohei Yukawa795f0102018-04-13 14:55:30 -0700168 mScrimStateListener = scrimStateListener;
Adrian Roosa5c63222017-07-27 16:33:39 +0200169 mScrimVisibleListener = scrimVisibleListener;
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800170 mContext = scrimBehind.getContext();
171 mUnlockMethodCache = UnlockMethodCache.getInstance(mContext);
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800172 mDarkenWhileDragging = !mUnlockMethodCache.canSkipBouncer();
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800173 mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
Lucas Dupin690c6f52018-07-10 15:28:57 -0700174 mKeyguardVisibilityCallback = new KeyguardVisibilityCallback();
175 mKeyguardUpdateMonitor.registerCallback(mKeyguardVisibilityCallback);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800176 mScrimBehindAlphaResValue = mContext.getResources().getFloat(R.dimen.scrim_behind_alpha);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800177 mTimeTicker = new AlarmTimeout(alarmManager, this::onHideWallpaperTimeout,
178 "hide_aod_wallpaper", new Handler());
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800179 mWakeLock = createWakeLock();
Lucas Dupin9324aa92017-07-26 20:29:38 -0700180 // Scrim alpha is initially set to the value on the resource but might be changed
181 // to make sure that text on top of it is legible.
182 mScrimBehindAlpha = mScrimBehindAlphaResValue;
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800183 mDozeParameters = dozeParameters;
Anthony Chen3cb3ad92016-12-01 10:58:47 -0800184
Lucas Dupin1ead7fc2017-05-24 14:14:44 -0700185 mColorExtractor = Dependency.get(SysuiColorExtractor.class);
Lucas Dupin314d41f2017-05-08 15:52:58 -0700186 mColorExtractor.addOnColorsChangedListener(this);
Lucas Dupin1ead7fc2017-05-24 14:14:44 -0700187 mLockColors = mColorExtractor.getColors(WallpaperManager.FLAG_LOCK,
Lucas Dupin1ead7fc2017-05-24 14:14:44 -0700188 ColorExtractor.TYPE_DARK, true /* ignoreVisibility */);
Lucas Dupin5266ad12017-06-17 20:57:28 -0700189 mSystemColors = mColorExtractor.getColors(WallpaperManager.FLAG_SYSTEM,
Lucas Dupin1ead7fc2017-05-24 14:14:44 -0700190 ColorExtractor.TYPE_DARK, true /* ignoreVisibility */);
Lucas Dupin8da8f2e92017-04-21 14:02:16 -0700191 mNeedsDrawableColorUpdate = true;
192
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800193 final ScrimState[] states = ScrimState.values();
194 for (int i = 0; i < states.length; i++) {
195 states[i].init(mScrimInFront, mScrimBehind, mDozeParameters);
196 states[i].setScrimBehindAlphaKeyguard(mScrimBehindAlphaKeyguard);
197 }
198 mState = ScrimState.UNINITIALIZED;
199
Lucas Dupin373356b2018-04-07 10:50:25 -0700200 mScrimBehind.setDefaultFocusHighlightEnabled(false);
201 mScrimInFront.setDefaultFocusHighlightEnabled(false);
202
Selim Cinek511f2702017-04-10 19:53:01 -0700203 updateScrims();
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200204 }
205
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800206 public void transitionTo(ScrimState state) {
207 transitionTo(state, null);
208 }
Lucas Dupin8da8f2e92017-04-21 14:02:16 -0700209
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800210 public void transitionTo(ScrimState state, Callback callback) {
211 if (state == mState) {
Lucas Dupin19aba8e2017-12-11 12:42:26 -0800212 // Call the callback anyway, unless it's already enqueued
213 if (callback != null && mCallback != callback) {
214 callback.onFinished();
215 }
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800216 return;
217 } else if (DEBUG) {
218 Log.d(TAG, "State changed to: " + state);
219 }
220
221 if (state == ScrimState.UNINITIALIZED) {
222 throw new IllegalArgumentException("Cannot change to UNINITIALIZED.");
223 }
224
Lucas Dupin8635c442017-12-08 10:36:28 -0800225 final ScrimState oldState = mState;
226 mState = state;
Lucas Dupin5866aaf2018-02-02 14:45:31 -0800227 Trace.traceCounter(Trace.TRACE_TAG_APP, "scrim_state", mState.getIndex());
Lucas Dupin8635c442017-12-08 10:36:28 -0800228
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800229 if (mCallback != null) {
230 mCallback.onCancelled();
231 }
232 mCallback = callback;
233
Lucas Dupin8635c442017-12-08 10:36:28 -0800234 state.prepare(oldState);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800235 mScreenBlankingCallbackCalled = false;
236 mAnimationDelay = 0;
237 mBlankScreen = state.getBlanksScreen();
238 mAnimateChange = state.getAnimateChange();
239 mAnimationDuration = state.getAnimationDuration();
240 mCurrentInFrontTint = state.getFrontTint();
241 mCurrentBehindTint = state.getBehindTint();
242 mCurrentInFrontAlpha = state.getFrontAlpha();
Lucas Dupin3d36dd82019-01-02 14:38:35 -0800243 mCurrentBehindAlpha = state.getBehindAlpha();
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800244 applyExpansionToAlpha();
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800245
Lucas Dupin38962d72018-03-14 12:41:39 -0700246 // Scrim might acquire focus when user is navigating with a D-pad or a keyboard.
247 // We need to disable focus otherwise AOD would end up with a gray overlay.
248 mScrimInFront.setFocusable(!state.isLowPowerState());
249 mScrimBehind.setFocusable(!state.isLowPowerState());
250
Lucas Dupin53cf12a2018-02-05 16:14:45 -0800251 // Cancel blanking transitions that were pending before we requested a new state
Lucas Dupin8c7cb022018-02-05 10:49:03 -0800252 if (mPendingFrameCallback != null) {
Lucas Dupin0791d972018-03-26 13:32:16 -0700253 mScrimBehind.removeCallbacks(mPendingFrameCallback);
Lucas Dupin8c7cb022018-02-05 10:49:03 -0800254 mPendingFrameCallback = null;
255 }
Lucas Dupin53cf12a2018-02-05 16:14:45 -0800256 if (getHandler().hasCallbacks(mBlankingTransitionRunnable)) {
257 getHandler().removeCallbacks(mBlankingTransitionRunnable);
258 mBlankingTransitionRunnable = null;
259 }
Lucas Dupin8c7cb022018-02-05 10:49:03 -0800260
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800261 // Showing/hiding the keyguard means that scrim colors have to be switched, not necessary
262 // to do the same when you're just showing the brightness mirror.
263 mNeedsDrawableColorUpdate = state != ScrimState.BRIGHTNESS_MIRROR;
264
Lucas Dupineea53b32017-12-18 13:47:14 -0800265 // The device might sleep if it's entering AOD, we need to make sure that
266 // the animation plays properly until the last frame.
267 // It's important to avoid holding the wakelock unless necessary because
268 // WakeLock#aqcuire will trigger an IPC and will cause jank.
Lucas Dupin38962d72018-03-14 12:41:39 -0700269 if (mState.isLowPowerState()) {
Lucas Dupineea53b32017-12-18 13:47:14 -0800270 holdWakeLock();
271 }
Lucas Dupin82aa1632017-12-13 00:13:57 -0800272
TYM Tsaia71c8922019-01-07 15:57:53 +0800273 // AOD wallpapers should fade away after a while.
274 // Docking pulses may take a long time, wallpapers should also fade away after a while.
Lucas Dupin023d7272019-01-28 14:31:40 -0800275 if (mWallpaperSupportsAmbientMode && mDozeParameters.getAlwaysOn()
276 && mState == ScrimState.AOD) {
Lucas Dupin82aa1632017-12-13 00:13:57 -0800277 if (!mWallpaperVisibilityTimedOut) {
278 mTimeTicker.schedule(mDozeParameters.getWallpaperAodDuration(),
279 AlarmTimeout.MODE_IGNORE_IF_SCHEDULED);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800280 }
Lucas Dupinc7804042018-12-21 12:26:33 -0800281 } else {
Lucas Dupin82aa1632017-12-13 00:13:57 -0800282 mTimeTicker.cancel();
283 mWallpaperVisibilityTimedOut = false;
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800284 }
285
Lucas Dupinff307d52018-02-05 21:16:39 -0800286 if (mKeyguardUpdateMonitor.needsSlowUnlockTransition() && mState == ScrimState.UNLOCKED) {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800287 // In case the user isn't unlocked, make sure to delay a bit because the system is hosed
288 // with too many things at this case, in order to not skip the initial frames.
289 mScrimInFront.postOnAnimationDelayed(this::scheduleUpdate, 16);
290 mAnimationDelay = StatusBar.FADE_KEYGUARD_START_DELAY;
Lucas Dupin0791d972018-03-26 13:32:16 -0700291 } else if ((!mDozeParameters.getAlwaysOn() && oldState == ScrimState.AOD)
Lucas Dupin16cfe452018-02-08 13:14:50 -0800292 || (mState == ScrimState.AOD && !mDozeParameters.getDisplayNeedsBlanking())) {
293 // Scheduling a frame isn't enough when:
294 // • Leaving doze and we need to modify scrim color immediately
295 // • ColorFade will not kick-in and scrim cannot wait for pre-draw.
Lucas Dupinff307d52018-02-05 21:16:39 -0800296 onPreDraw();
297 } else {
298 scheduleUpdate();
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800299 }
Yohei Yukawa795f0102018-04-13 14:55:30 -0700300
301 dispatchScrimState(mScrimBehind.getViewAlpha());
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800302 }
303
304 public ScrimState getState() {
305 return mState;
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200306 }
307
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800308 protected void setScrimBehindValues(float scrimBehindAlphaKeyguard) {
Jorim Jaggie31f6b82016-07-01 16:15:09 -0700309 mScrimBehindAlphaKeyguard = scrimBehindAlphaKeyguard;
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800310 ScrimState[] states = ScrimState.values();
311 for (int i = 0; i < states.length; i++) {
312 states[i].setScrimBehindAlphaKeyguard(scrimBehindAlphaKeyguard);
313 }
Jorim Jaggie31f6b82016-07-01 16:15:09 -0700314 scheduleUpdate();
315 }
316
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200317 public void onTrackingStarted() {
Jorim Jaggie93698b2016-11-11 18:24:38 -0800318 mTracking = true;
Selim Cineke8bae622015-07-15 13:24:06 -0700319 mDarkenWhileDragging = !mUnlockMethodCache.canSkipBouncer();
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200320 }
321
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +0200322 public void onExpandingFinished() {
Jorim Jaggie93698b2016-11-11 18:24:38 -0800323 mTracking = false;
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +0200324 }
325
Lucas Dupin82aa1632017-12-13 00:13:57 -0800326 @VisibleForTesting
327 protected void onHideWallpaperTimeout() {
TYM Tsaia71c8922019-01-07 15:57:53 +0800328 if (mState != ScrimState.AOD && mState != ScrimState.PULSING) {
Lucas Dupin82aa1632017-12-13 00:13:57 -0800329 return;
330 }
331
332 holdWakeLock();
333 mWallpaperVisibilityTimedOut = true;
334 mAnimateChange = true;
335 mAnimationDuration = mDozeParameters.getWallpaperFadeOutDuration();
336 scheduleUpdate();
337 }
338
339 private void holdWakeLock() {
340 if (!mWakeLockHeld) {
341 if (mWakeLock != null) {
342 mWakeLockHeld = true;
Lucas Dupinee4c9b72019-02-18 17:04:58 -0800343 mWakeLock.acquire(TAG);
Lucas Dupin82aa1632017-12-13 00:13:57 -0800344 } else {
345 Log.w(TAG, "Cannot hold wake lock, it has not been set yet");
346 }
347 }
348 }
349
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800350 /**
351 * Current state of the shade expansion when pulling it from the top.
352 * This value is 1 when on top of the keyguard and goes to 0 as the user drags up.
353 *
354 * The expansion fraction is tied to the scrim opacity.
355 *
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800356 * @param fraction From 0 to 1 where 0 means collapsed and 1 expanded.
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800357 */
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200358 public void setPanelExpansion(float fraction) {
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800359 if (mExpansionFraction != fraction) {
360 mExpansionFraction = fraction;
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800361
Lucas Dupin067136c2018-03-27 18:03:25 -0700362 final boolean keyguardOrUnlocked = mState == ScrimState.UNLOCKED
Lucas Dupin1c327432019-01-03 13:37:53 -0800363 || mState == ScrimState.KEYGUARD || mState == ScrimState.PULSING;
Lucas Dupin067136c2018-03-27 18:03:25 -0700364 if (!keyguardOrUnlocked || !mExpansionAffectsAlpha) {
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800365 return;
366 }
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800367
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800368 applyExpansionToAlpha();
369
370 if (mUpdatePending) {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800371 return;
372 }
373
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800374 setOrAdaptCurrentAnimation(mScrimBehind);
375 setOrAdaptCurrentAnimation(mScrimInFront);
shawnlin317db372018-04-09 19:49:48 +0800376
Yohei Yukawa795f0102018-04-13 14:55:30 -0700377 dispatchScrimState(mScrimBehind.getViewAlpha());
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800378 }
379 }
380
381 private void setOrAdaptCurrentAnimation(View scrim) {
382 if (!isAnimating(scrim)) {
383 updateScrimColor(scrim, getCurrentScrimAlpha(scrim), getCurrentScrimTint(scrim));
384 } else {
385 ValueAnimator previousAnimator = (ValueAnimator) scrim.getTag(TAG_KEY_ANIM);
386 float alpha = getCurrentScrimAlpha(scrim);
387 float previousEndValue = (Float) scrim.getTag(TAG_END_ALPHA);
388 float previousStartValue = (Float) scrim.getTag(TAG_START_ALPHA);
389 float relativeDiff = alpha - previousEndValue;
390 float newStartValue = previousStartValue + relativeDiff;
391 scrim.setTag(TAG_START_ALPHA, newStartValue);
392 scrim.setTag(TAG_END_ALPHA, alpha);
393 previousAnimator.setCurrentPlayTime(previousAnimator.getCurrentPlayTime());
Jorim Jaggi93439da2014-06-30 23:53:39 +0200394 }
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200395 }
396
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800397 private void applyExpansionToAlpha() {
Lucas Dupin67f02632018-03-12 11:08:31 -0700398 if (!mExpansionAffectsAlpha) {
399 return;
400 }
401
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800402 if (mState == ScrimState.UNLOCKED) {
403 // Darken scrim as you pull down the shade when unlocked
404 float behindFraction = getInterpolatedFraction();
405 behindFraction = (float) Math.pow(behindFraction, 0.8f);
Lucas Dupind7c44eb2018-04-05 10:00:31 -0700406 mCurrentBehindAlpha = behindFraction * GRADIENT_SCRIM_ALPHA_BUSY;
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800407 mCurrentInFrontAlpha = 0;
Lucas Dupin1c327432019-01-03 13:37:53 -0800408 } else if (mState == ScrimState.KEYGUARD || mState == ScrimState.PULSING) {
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800409 // Either darken of make the scrim transparent when you
410 // pull down the shade
411 float interpolatedFract = getInterpolatedFraction();
Lucas Dupin3d36dd82019-01-02 14:38:35 -0800412 float alphaBehind = mState.getBehindAlpha();
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800413 if (mDarkenWhileDragging) {
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800414 mCurrentBehindAlpha = MathUtils.lerp(GRADIENT_SCRIM_ALPHA_BUSY, alphaBehind,
Lucas Dupinb380c882018-02-25 21:57:17 -0800415 interpolatedFract);
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800416 mCurrentInFrontAlpha = 0;
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800417 } else {
Lucas Dupinb380c882018-02-25 21:57:17 -0800418 mCurrentBehindAlpha = MathUtils.lerp(0 /* start */, alphaBehind,
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800419 interpolatedFract);
420 mCurrentInFrontAlpha = 0;
421 }
422 }
423 }
424
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800425 /**
Anthony Chene658cc22017-04-27 11:17:35 -0700426 * Sets the given drawable as the background of the scrim that shows up behind the
427 * notifications.
428 */
429 public void setScrimBehindDrawable(Drawable drawable) {
430 mScrimBehind.setDrawable(drawable);
431 }
432
Michael Wrightcae88752018-04-16 23:13:54 +0100433 /**
Lucas Dupin69bda602018-05-18 17:24:52 -0700434 * Sets the front scrim opacity in AOD so it's not as bright.
435 * <p>
436 * Displays usually don't support multiple dimming settings when in low power mode.
437 * The workaround is to modify the front scrim opacity when in AOD, so it's not as
438 * bright when you're at the movies or lying down on bed.
439 * <p>
440 * This value will be lost during transitions and only updated again after the the
441 * device is dozing when the light sensor is on.
Michael Wrightcae88752018-04-16 23:13:54 +0100442 */
443 public void setAodFrontScrimAlpha(float alpha) {
Lucas Dupin69bda602018-05-18 17:24:52 -0700444 if (mState == ScrimState.AOD && mDozeParameters.getAlwaysOn()
445 && mCurrentInFrontAlpha != alpha) {
Michael Wrightcae88752018-04-16 23:13:54 +0100446 mCurrentInFrontAlpha = alpha;
Lucas Dupin8523d132018-05-31 17:34:32 -0700447 updateScrims();
Michael Wrightcae88752018-04-16 23:13:54 +0100448 }
449
450 mState.AOD.setAodFrontScrimAlpha(alpha);
451 }
452
Evan Rosky9a895012016-04-21 11:26:15 -0700453 protected void scheduleUpdate() {
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200454 if (mUpdatePending) return;
Jorim Jaggie29b2db2014-05-30 23:17:03 +0200455
456 // Make sure that a frame gets scheduled.
457 mScrimBehind.invalidate();
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200458 mScrimBehind.getViewTreeObserver().addOnPreDrawListener(this);
459 mUpdatePending = true;
460 }
461
Xiaohui Chen5da71352016-02-22 10:04:41 -0800462 protected void updateScrims() {
Lucas Dupin9324aa92017-07-26 20:29:38 -0700463 // Make sure we have the right gradients and their opacities will satisfy GAR.
Lucas Dupin8da8f2e92017-04-21 14:02:16 -0700464 if (mNeedsDrawableColorUpdate) {
465 mNeedsDrawableColorUpdate = false;
Lucas Dupinf8463ee2018-06-11 16:18:15 -0700466 boolean isKeyguard = mKeyguardUpdateMonitor.isKeyguardVisible() && !mKeyguardOccluded;
467 GradientColors currentScrimColors = isKeyguard ? mLockColors : mSystemColors;
468 // Only animate scrim color if the scrim view is actually visible
469 boolean animateScrimInFront = mScrimInFront.getViewAlpha() != 0 && !mBlankScreen;
470 boolean animateScrimBehind = mScrimBehind.getViewAlpha() != 0 && !mBlankScreen;
471 mScrimInFront.setColors(currentScrimColors, animateScrimInFront);
472 mScrimBehind.setColors(currentScrimColors, animateScrimBehind);
Lucas Dupin9324aa92017-07-26 20:29:38 -0700473
474 // Calculate minimum scrim opacity for white or black text.
475 int textColor = currentScrimColors.supportsDarkText() ? Color.BLACK : Color.WHITE;
476 int mainColor = currentScrimColors.getMainColor();
477 float minOpacity = ColorUtils.calculateMinimumBackgroundAlpha(textColor, mainColor,
478 4.5f /* minimumContrast */) / 255f;
479 mScrimBehindAlpha = Math.max(mScrimBehindAlphaResValue, minOpacity);
Yohei Yukawa795f0102018-04-13 14:55:30 -0700480 dispatchScrimState(mScrimBehind.getViewAlpha());
Lucas Dupin8da8f2e92017-04-21 14:02:16 -0700481 }
482
Lucas Dupind5107302018-03-19 15:30:29 -0700483 // We want to override the back scrim opacity for the AOD state
Lucas Dupin82aa1632017-12-13 00:13:57 -0800484 // when it's time to fade the wallpaper away.
TYM Tsaia71c8922019-01-07 15:57:53 +0800485 boolean aodWallpaperTimeout = (mState == ScrimState.AOD || mState == ScrimState.PULSING)
486 && mWallpaperVisibilityTimedOut;
Lucas Dupind5107302018-03-19 15:30:29 -0700487 // We also want to hide FLAG_SHOW_WHEN_LOCKED activities under the scrim.
488 boolean occludedKeyguard = (mState == ScrimState.PULSING || mState == ScrimState.AOD)
489 && mKeyguardOccluded;
490 if (aodWallpaperTimeout || occludedKeyguard) {
Lucas Dupin82aa1632017-12-13 00:13:57 -0800491 mCurrentBehindAlpha = 1;
492 }
493
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800494 setScrimInFrontAlpha(mCurrentInFrontAlpha);
495 setScrimBehindAlpha(mCurrentBehindAlpha);
496
Adrian Roosa5c63222017-07-27 16:33:39 +0200497 dispatchScrimsVisible();
498 }
499
Yohei Yukawa795f0102018-04-13 14:55:30 -0700500 private void dispatchScrimState(float alpha) {
501 mScrimStateListener.accept(mState, alpha, mScrimInFront.getColors());
502 }
503
Adrian Roosa5c63222017-07-27 16:33:39 +0200504 private void dispatchScrimsVisible() {
Lucas Dupin82aa1632017-12-13 00:13:57 -0800505 final int currentScrimVisibility;
506 if (mScrimInFront.getViewAlpha() == 1 || mScrimBehind.getViewAlpha() == 1) {
507 currentScrimVisibility = VISIBILITY_FULLY_OPAQUE;
508 } else if (mScrimInFront.getViewAlpha() == 0 && mScrimBehind.getViewAlpha() == 0) {
509 currentScrimVisibility = VISIBILITY_FULLY_TRANSPARENT;
510 } else {
511 currentScrimVisibility = VISIBILITY_SEMI_TRANSPARENT;
512 }
Adrian Roosa5c63222017-07-27 16:33:39 +0200513
Lucas Dupin82aa1632017-12-13 00:13:57 -0800514 if (mScrimsVisibility != currentScrimVisibility) {
515 mScrimsVisibility = currentScrimVisibility;
516 mScrimVisibleListener.accept(currentScrimVisibility);
Adrian Roosa5c63222017-07-27 16:33:39 +0200517 }
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200518 }
519
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800520 private float getInterpolatedFraction() {
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800521 float frac = mExpansionFraction;
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200522 // let's start this 20% of the way down the screen
523 frac = frac * 1.2f - 0.2f;
524 if (frac <= 0) {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800525 return 0;
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200526 } else {
527 // woo, special effects
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800528 return (float)(1f-0.5f*(1f-Math.cos(3.14159f * Math.pow(1f-frac, 2f))));
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200529 }
530 }
531
Lucas Dupin8da8f2e92017-04-21 14:02:16 -0700532 private void setScrimBehindAlpha(float alpha) {
533 setScrimAlpha(mScrimBehind, alpha);
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200534 }
535
Lucas Dupin8da8f2e92017-04-21 14:02:16 -0700536 private void setScrimInFrontAlpha(float alpha) {
537 setScrimAlpha(mScrimInFront, alpha);
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200538 }
539
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800540 private void setScrimAlpha(ScrimView scrim, float alpha) {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800541 if (alpha == 0f) {
542 scrim.setClickable(false);
Selim Cinekaac93252015-04-14 20:04:12 -0700543 } else {
Lucas Dupin1c327432019-01-03 13:37:53 -0800544 // Eat touch events (unless dozing).
545 scrim.setClickable(mState != ScrimState.AOD);
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200546 }
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800547 updateScrim(scrim, alpha);
Jorim Jaggi048af1f2014-11-11 22:51:10 +0100548 }
549
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800550 private void updateScrimColor(View scrim, float alpha, int tint) {
551 alpha = Math.max(0, Math.min(1.0f, alpha));
Selim Cinekaac93252015-04-14 20:04:12 -0700552 if (scrim instanceof ScrimView) {
Lucas Dupin8da8f2e92017-04-21 14:02:16 -0700553 ScrimView scrimView = (ScrimView) scrim;
Lucas Dupin8da8f2e92017-04-21 14:02:16 -0700554
Adrian Roosa5c63222017-07-27 16:33:39 +0200555 Trace.traceCounter(Trace.TRACE_TAG_APP,
556 scrim == mScrimInFront ? "front_scrim_alpha" : "back_scrim_alpha",
557 (int) (alpha * 255));
558
Adrian Roosa5c63222017-07-27 16:33:39 +0200559 Trace.traceCounter(Trace.TRACE_TAG_APP,
560 scrim == mScrimInFront ? "front_scrim_tint" : "back_scrim_tint",
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800561 Color.alpha(tint));
Adrian Roosa5c63222017-07-27 16:33:39 +0200562
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800563 scrimView.setTint(tint);
564 scrimView.setViewAlpha(alpha);
Selim Cinekaac93252015-04-14 20:04:12 -0700565 } else {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800566 scrim.setAlpha(alpha);
Selim Cinekaac93252015-04-14 20:04:12 -0700567 }
Selim Cinek8cd80402017-08-01 10:44:29 -0700568 dispatchScrimsVisible();
Jorim Jaggi048af1f2014-11-11 22:51:10 +0100569 }
570
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800571 private void startScrimAnimation(final View scrim, float current) {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800572 ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
573 final int initialScrimTint = scrim instanceof ScrimView ? ((ScrimView) scrim).getTint() :
574 Color.TRANSPARENT;
Lucas Dupin8da8f2e92017-04-21 14:02:16 -0700575 anim.addUpdateListener(animation -> {
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800576 final float startAlpha = (Float) scrim.getTag(TAG_START_ALPHA);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800577 final float animAmount = (float) animation.getAnimatedValue();
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800578 final int finalScrimTint = getCurrentScrimTint(scrim);
579 final float finalScrimAlpha = getCurrentScrimAlpha(scrim);
580 float alpha = MathUtils.lerp(startAlpha, finalScrimAlpha, animAmount);
581 alpha = MathUtils.constrain(alpha, 0f, 1f);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800582 int tint = ColorUtils.blendARGB(initialScrimTint, finalScrimTint, animAmount);
583 updateScrimColor(scrim, alpha, tint);
Adrian Roosa5c63222017-07-27 16:33:39 +0200584 dispatchScrimsVisible();
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200585 });
Lucas Dupin3503c5f2018-03-02 19:04:00 -0800586 anim.setInterpolator(mInterpolator);
Jorim Jaggie29b2db2014-05-30 23:17:03 +0200587 anim.setStartDelay(mAnimationDelay);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800588 anim.setDuration(mAnimationDuration);
Jorim Jaggie29b2db2014-05-30 23:17:03 +0200589 anim.addListener(new AnimatorListenerAdapter() {
Joanne Chunga393ad62019-01-16 21:41:31 +0800590 private Callback lastCallback = mCallback;
591
Jorim Jaggie29b2db2014-05-30 23:17:03 +0200592 @Override
593 public void onAnimationEnd(Animator animation) {
Joanne Chunga393ad62019-01-16 21:41:31 +0800594 onFinished(lastCallback);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800595
596 scrim.setTag(TAG_KEY_ANIM, null);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800597 dispatchScrimsVisible();
598
Jorim Jaggif5304ad2017-07-17 18:31:13 +0200599 if (!mDeferFinishedListener && mOnAnimationFinished != null) {
Jorim Jaggie29b2db2014-05-30 23:17:03 +0200600 mOnAnimationFinished.run();
601 mOnAnimationFinished = null;
602 }
603 }
604 });
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800605
606 // Cache alpha values because we might want to update this animator in the future if
607 // the user expands the panel while the animation is still running.
608 scrim.setTag(TAG_START_ALPHA, current);
609 scrim.setTag(TAG_END_ALPHA, getCurrentScrimAlpha(scrim));
610
John Spurlockbf370992014-06-17 13:58:31 -0400611 scrim.setTag(TAG_KEY_ANIM, anim);
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800612 anim.start();
613 }
614
615 private float getCurrentScrimAlpha(View scrim) {
616 if (scrim == mScrimInFront) {
617 return mCurrentInFrontAlpha;
618 } else if (scrim == mScrimBehind) {
619 return mCurrentBehindAlpha;
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800620 } else {
621 throw new IllegalArgumentException("Unknown scrim view");
622 }
623 }
624
625 private int getCurrentScrimTint(View scrim) {
626 if (scrim == mScrimInFront) {
627 return mCurrentInFrontTint;
628 } else if (scrim == mScrimBehind) {
629 return mCurrentBehindTint;
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800630 } else {
631 throw new IllegalArgumentException("Unknown scrim view");
632 }
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200633 }
634
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200635 @Override
636 public boolean onPreDraw() {
637 mScrimBehind.getViewTreeObserver().removeOnPreDrawListener(this);
638 mUpdatePending = false;
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800639 if (mCallback != null) {
640 mCallback.onStart();
Selim Cinek372d1bd2015-08-14 13:19:37 -0700641 }
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200642 updateScrims();
Lucas Dupin3503c5f2018-03-02 19:04:00 -0800643 if (mOnAnimationFinished != null && !isAnimating(mScrimInFront)
644 && !isAnimating(mScrimBehind)) {
645 mOnAnimationFinished.run();
646 mOnAnimationFinished = null;
647 }
Selim Cinekedd32b82015-06-23 22:05:58 -0400648 return true;
649 }
650
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800651 private void onFinished() {
Joanne Chunga393ad62019-01-16 21:41:31 +0800652 onFinished(mCallback);
653 }
654
655 private void onFinished(Callback callback) {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800656 if (mWakeLockHeld) {
Lucas Dupinee4c9b72019-02-18 17:04:58 -0800657 mWakeLock.release(TAG);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800658 mWakeLockHeld = false;
659 }
Joanne Chunga393ad62019-01-16 21:41:31 +0800660
661 if (callback != null) {
662 callback.onFinished();
663
664 if (callback == mCallback) {
665 mCallback = null;
666 }
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800667 }
Joanne Chunga393ad62019-01-16 21:41:31 +0800668
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800669 // When unlocking with fingerprint, we'll fade the scrims from black to transparent.
670 // At the end of the animation we need to remove the tint.
671 if (mState == ScrimState.UNLOCKED) {
672 mCurrentInFrontTint = Color.TRANSPARENT;
673 mCurrentBehindTint = Color.TRANSPARENT;
674 }
675 }
676
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700677 private boolean isAnimating(View scrim) {
678 return scrim.getTag(TAG_KEY_ANIM) != null;
679 }
680
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800681 @VisibleForTesting
682 void setOnAnimationFinished(Runnable onAnimationFinished) {
683 mOnAnimationFinished = onAnimationFinished;
684 }
Adrian Roos5f72c922016-03-08 15:54:26 -0800685
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800686 private void updateScrim(ScrimView scrim, float alpha) {
687 final float currentAlpha = scrim.getViewAlpha();
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800688
689 ValueAnimator previousAnimator = ViewState.getChildTag(scrim, TAG_KEY_ANIM);
Selim Cinekaac93252015-04-14 20:04:12 -0700690 if (previousAnimator != null) {
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800691 if (mAnimateChange) {
Jorim Jaggif5304ad2017-07-17 18:31:13 +0200692 // We are not done yet! Defer calling the finished listener.
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800693 mDeferFinishedListener = true;
Selim Cinekaac93252015-04-14 20:04:12 -0700694 }
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800695 // Previous animators should always be cancelled. Not doing so would cause
696 // overlap, especially on states that don't animate, leading to flickering,
697 // and in the worst case, an internal state that doesn't represent what
698 // transitionTo requested.
699 cancelAnimator(previousAnimator);
700 mDeferFinishedListener = false;
Selim Cinekaac93252015-04-14 20:04:12 -0700701 }
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800702
Lucas Dupin8c7cb022018-02-05 10:49:03 -0800703 if (mPendingFrameCallback != null) {
704 // Display is off and we're waiting.
705 return;
706 } else if (mBlankScreen) {
707 // Need to blank the display before continuing.
708 blankDisplay();
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800709 return;
710 } else if (!mScreenBlankingCallbackCalled) {
711 // Not blanking the screen. Letting the callback know that we're ready
712 // to replace what was on the screen before.
713 if (mCallback != null) {
714 mCallback.onDisplayBlanked();
715 mScreenBlankingCallbackCalled = true;
716 }
717 }
718
Lucas Dupin6afae372017-11-30 13:09:22 -0500719 if (scrim == mScrimBehind) {
Yohei Yukawa795f0102018-04-13 14:55:30 -0700720 dispatchScrimState(alpha);
Lucas Dupin6afae372017-11-30 13:09:22 -0500721 }
722
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800723 final boolean wantsAlphaUpdate = alpha != currentAlpha;
Lucas Dupin3503c5f2018-03-02 19:04:00 -0800724 final boolean wantsTintUpdate = scrim.getTint() != getCurrentScrimTint(scrim);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800725
726 if (wantsAlphaUpdate || wantsTintUpdate) {
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800727 if (mAnimateChange) {
728 startScrimAnimation(scrim, currentAlpha);
Selim Cinekaac93252015-04-14 20:04:12 -0700729 } else {
Lucas Dupin3daf3b02018-02-27 17:23:41 -0800730 // update the alpha directly
731 updateScrimColor(scrim, alpha, getCurrentScrimTint(scrim));
732 onFinished();
Selim Cinekaac93252015-04-14 20:04:12 -0700733 }
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800734 } else {
735 onFinished();
Selim Cinekaac93252015-04-14 20:04:12 -0700736 }
737 }
738
Lucas Dupin80a3fcc2018-02-07 10:49:55 -0800739 @VisibleForTesting
740 protected void cancelAnimator(ValueAnimator previousAnimator) {
741 if (previousAnimator != null) {
742 previousAnimator.cancel();
743 }
744 }
745
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800746 private void blankDisplay() {
Lucas Dupin8c7cb022018-02-05 10:49:03 -0800747 updateScrimColor(mScrimInFront, 1, Color.BLACK);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800748
Lucas Dupin8c7cb022018-02-05 10:49:03 -0800749 // Notify callback that the screen is completely black and we're
750 // ready to change the display power mode
Lucas Dupin0791d972018-03-26 13:32:16 -0700751 mPendingFrameCallback = () -> {
Lucas Dupin8c7cb022018-02-05 10:49:03 -0800752 if (mCallback != null) {
753 mCallback.onDisplayBlanked();
754 mScreenBlankingCallbackCalled = true;
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800755 }
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800756
Lucas Dupin53cf12a2018-02-05 16:14:45 -0800757 mBlankingTransitionRunnable = () -> {
758 mBlankingTransitionRunnable = null;
Lucas Dupin8c7cb022018-02-05 10:49:03 -0800759 mPendingFrameCallback = null;
760 mBlankScreen = false;
761 // Try again.
762 updateScrims();
763 };
764
765 // Setting power states can happen after we push out the frame. Make sure we
766 // stay fully opaque until the power state request reaches the lower levels.
Lucas Dupin0791d972018-03-26 13:32:16 -0700767 final int delay = mScreenOn ? 32 : 500;
Lucas Dupin53cf12a2018-02-05 16:14:45 -0800768 if (DEBUG) {
Lucas Dupin3a64ed72018-02-12 12:44:37 -0800769 Log.d(TAG, "Fading out scrims with delay: " + delay);
Lucas Dupin53cf12a2018-02-05 16:14:45 -0800770 }
Lucas Dupin3a64ed72018-02-12 12:44:37 -0800771 getHandler().postDelayed(mBlankingTransitionRunnable, delay);
Lucas Dupin8c7cb022018-02-05 10:49:03 -0800772 };
773 doOnTheNextFrame(mPendingFrameCallback);
774 }
775
Lucas Dupin0791d972018-03-26 13:32:16 -0700776 /**
777 * Executes a callback after the frame has hit the display.
778 * @param callback What to run.
779 */
Lucas Dupin8c7cb022018-02-05 10:49:03 -0800780 @VisibleForTesting
Lucas Dupin0791d972018-03-26 13:32:16 -0700781 protected void doOnTheNextFrame(Runnable callback) {
782 // Just calling View#postOnAnimation isn't enough because the frame might not have reached
783 // the display yet. A timeout is the safest solution.
784 mScrimBehind.postOnAnimationDelayed(callback, 32 /* delayMillis */);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800785 }
786
787 @VisibleForTesting
788 protected Handler getHandler() {
789 return Handler.getMain();
790 }
791
Lucas Dupin8da8f2e92017-04-21 14:02:16 -0700792 public int getBackgroundColor() {
793 int color = mLockColors.getMainColor();
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800794 return Color.argb((int) (mScrimBehind.getViewAlpha() * Color.alpha(color)),
Lucas Dupin8da8f2e92017-04-21 14:02:16 -0700795 Color.red(color), Color.green(color), Color.blue(color));
Selim Cinekd35c2792016-01-21 13:20:57 -0800796 }
797
798 public void setScrimBehindChangeRunnable(Runnable changeRunnable) {
799 mScrimBehind.setChangeRunnable(changeRunnable);
800 }
Selim Cineke803491c2016-04-09 21:24:45 -0700801
Jorim Jaggie31f6b82016-07-01 16:15:09 -0700802 public void setCurrentUser(int currentUser) {
803 // Don't care in the base class.
804 }
Lucas Dupin8da8f2e92017-04-21 14:02:16 -0700805
806 @Override
Lucas Dupin7aaa3532017-05-28 08:51:07 -0700807 public void onColorsChanged(ColorExtractor colorExtractor, int which) {
Lucas Dupin8da8f2e92017-04-21 14:02:16 -0700808 if ((which & WallpaperManager.FLAG_LOCK) != 0) {
Lucas Dupin1ead7fc2017-05-24 14:14:44 -0700809 mLockColors = mColorExtractor.getColors(WallpaperManager.FLAG_LOCK,
Lucas Dupin1ead7fc2017-05-24 14:14:44 -0700810 ColorExtractor.TYPE_DARK, true /* ignoreVisibility */);
Lucas Dupin8da8f2e92017-04-21 14:02:16 -0700811 mNeedsDrawableColorUpdate = true;
812 scheduleUpdate();
813 }
814 if ((which & WallpaperManager.FLAG_SYSTEM) != 0) {
Lucas Dupin1ead7fc2017-05-24 14:14:44 -0700815 mSystemColors = mColorExtractor.getColors(WallpaperManager.FLAG_SYSTEM,
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800816 ColorExtractor.TYPE_DARK, mState != ScrimState.UNLOCKED);
Lucas Dupin8da8f2e92017-04-21 14:02:16 -0700817 mNeedsDrawableColorUpdate = true;
818 scheduleUpdate();
819 }
820 }
Adrian Roosba7ca592017-08-15 17:48:05 +0200821
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800822 @VisibleForTesting
823 protected WakeLock createWakeLock() {
824 return new DelayedWakeLock(getHandler(),
Lucas Dupine03081f2018-04-03 11:31:27 -0700825 WakeLock.createPartial(mContext, "Scrims"));
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800826 }
Adrian Roosba7ca592017-08-15 17:48:05 +0200827
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800828 @Override
829 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Lucas Dupin3fcdd472018-01-19 19:06:45 -0800830 pw.println(" ScrimController: ");
831 pw.print(" state: "); pw.println(mState);
832 pw.print(" frontScrim:"); pw.print(" viewAlpha="); pw.print(mScrimInFront.getViewAlpha());
Adrian Roosba7ca592017-08-15 17:48:05 +0200833 pw.print(" alpha="); pw.print(mCurrentInFrontAlpha);
Adrian Roosba7ca592017-08-15 17:48:05 +0200834 pw.print(" tint=0x"); pw.println(Integer.toHexString(mScrimInFront.getTint()));
835
Lucas Dupin3fcdd472018-01-19 19:06:45 -0800836 pw.print(" backScrim:"); pw.print(" viewAlpha="); pw.print(mScrimBehind.getViewAlpha());
Adrian Roosba7ca592017-08-15 17:48:05 +0200837 pw.print(" alpha="); pw.print(mCurrentBehindAlpha);
Adrian Roosba7ca592017-08-15 17:48:05 +0200838 pw.print(" tint=0x"); pw.println(Integer.toHexString(mScrimBehind.getTint()));
839
Adrian Roosba7ca592017-08-15 17:48:05 +0200840 pw.print(" mTracking="); pw.println(mTracking);
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800841 }
842
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700843 public void setWallpaperSupportsAmbientMode(boolean wallpaperSupportsAmbientMode) {
Lucas Dupin82aa1632017-12-13 00:13:57 -0800844 mWallpaperSupportsAmbientMode = wallpaperSupportsAmbientMode;
845 ScrimState[] states = ScrimState.values();
846 for (int i = 0; i < states.length; i++) {
847 states[i].setWallpaperSupportsAmbientMode(wallpaperSupportsAmbientMode);
848 }
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700849 }
850
Lucas Dupin53cf12a2018-02-05 16:14:45 -0800851 /**
852 * Interrupts blanking transitions once the display notifies that it's already on.
853 */
854 public void onScreenTurnedOn() {
Lucas Dupin3a64ed72018-02-12 12:44:37 -0800855 mScreenOn = true;
Lucas Dupin53cf12a2018-02-05 16:14:45 -0800856 final Handler handler = getHandler();
857 if (handler.hasCallbacks(mBlankingTransitionRunnable)) {
858 if (DEBUG) {
859 Log.d(TAG, "Shorter blanking because screen turned on. All good.");
860 }
861 handler.removeCallbacks(mBlankingTransitionRunnable);
862 mBlankingTransitionRunnable.run();
863 }
864 }
865
Lucas Dupin3a64ed72018-02-12 12:44:37 -0800866 public void onScreenTurnedOff() {
867 mScreenOn = false;
868 }
869
Lucas Dupin67f02632018-03-12 11:08:31 -0700870 public void setExpansionAffectsAlpha(boolean expansionAffectsAlpha) {
871 mExpansionAffectsAlpha = expansionAffectsAlpha;
872 }
873
Lucas Dupind5107302018-03-19 15:30:29 -0700874 public void setKeyguardOccluded(boolean keyguardOccluded) {
875 mKeyguardOccluded = keyguardOccluded;
Lucas Dupin63d72172018-06-06 11:42:55 -0700876 updateScrims();
Lucas Dupind5107302018-03-19 15:30:29 -0700877 }
878
Lucas Dupinf8463ee2018-06-11 16:18:15 -0700879 public void setHasBackdrop(boolean hasBackdrop) {
Lucas Dupin193677c2018-06-11 19:16:03 -0700880 for (ScrimState state : ScrimState.values()) {
881 state.setHasBackdrop(hasBackdrop);
882 }
Lucas Dupin9bee5822018-07-09 14:32:53 -0700883
884 // Backdrop event may arrive after state was already applied,
885 // in this case, back-scrim needs to be re-evaluated
886 if (mState == ScrimState.AOD || mState == ScrimState.PULSING) {
Lucas Dupin3d36dd82019-01-02 14:38:35 -0800887 float newBehindAlpha = mState.getBehindAlpha();
Lucas Dupin9bee5822018-07-09 14:32:53 -0700888 if (mCurrentBehindAlpha != newBehindAlpha) {
889 mCurrentBehindAlpha = newBehindAlpha;
890 updateScrims();
891 }
892 }
Lucas Dupin193677c2018-06-11 19:16:03 -0700893 }
894
895 public void setLaunchingAffordanceWithPreview(boolean launchingAffordanceWithPreview) {
896 for (ScrimState state : ScrimState.values()) {
897 state.setLaunchingAffordanceWithPreview(launchingAffordanceWithPreview);
Lucas Dupinf8463ee2018-06-11 16:18:15 -0700898 }
899 }
900
Lucas Dupin00be88f2019-01-03 17:50:52 -0800901 public void setPulseReason(int pulseReason) {
902 ScrimState.PULSING.setPulseReason(pulseReason);
903 }
904
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800905 public interface Callback {
906 default void onStart() {
907 }
908 default void onDisplayBlanked() {
909 }
910 default void onFinished() {
911 }
912 default void onCancelled() {
913 }
Adrian Roosba7ca592017-08-15 17:48:05 +0200914 }
Lucas Dupin690c6f52018-07-10 15:28:57 -0700915
916 /**
917 * Simple keyguard callback that updates scrims when keyguard visibility changes.
918 */
919 private class KeyguardVisibilityCallback extends KeyguardUpdateMonitorCallback {
920
921 @Override
922 public void onKeyguardVisibilityChanged(boolean showing) {
923 mNeedsDrawableColorUpdate = true;
924 scheduleUpdate();
925 }
926 }
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200927}