• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.phone;
18 
19 import android.animation.Animator;
20 import android.animation.AnimatorListenerAdapter;
21 import android.animation.PropertyValuesHolder;
22 import android.animation.ValueAnimator;
23 import android.content.Context;
24 import android.graphics.Color;
25 import android.graphics.Rect;
26 import android.view.View;
27 import android.view.ViewGroup;
28 import android.view.ViewTreeObserver;
29 import android.view.animation.DecelerateInterpolator;
30 import android.view.animation.Interpolator;
31 import android.view.animation.PathInterpolator;
32 
33 import com.android.keyguard.KeyguardUpdateMonitor;
34 import com.android.systemui.R;
35 import com.android.systemui.statusbar.ExpandableNotificationRow;
36 import com.android.systemui.statusbar.NotificationData;
37 import com.android.systemui.statusbar.ScrimView;
38 import com.android.systemui.statusbar.policy.HeadsUpManager;
39 import com.android.systemui.statusbar.stack.StackStateAnimator;
40 
41 /**
42  * Controls both the scrim behind the notifications and in front of the notifications (when a
43  * security method gets shown).
44  */
45 public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
46         HeadsUpManager.OnHeadsUpChangedListener {
47     public static final long ANIMATION_DURATION = 220;
48     public static final Interpolator KEYGUARD_FADE_OUT_INTERPOLATOR
49             = new PathInterpolator(0f, 0, 0.7f, 1f);
50     public static final Interpolator KEYGUARD_FADE_OUT_INTERPOLATOR_LOCKED
51             = new PathInterpolator(0.3f, 0f, 0.8f, 1f);
52     private static final float SCRIM_BEHIND_ALPHA = 0.62f;
53     protected static final float SCRIM_BEHIND_ALPHA_KEYGUARD = 0.45f;
54     protected static final float SCRIM_BEHIND_ALPHA_UNLOCKING = 0.2f;
55     private static final float SCRIM_IN_FRONT_ALPHA = 0.75f;
56     private static final float SCRIM_IN_FRONT_ALPHA_LOCKED = 0.85f;
57     private static final int TAG_KEY_ANIM = R.id.scrim;
58     private static final int TAG_KEY_ANIM_TARGET = R.id.scrim_target;
59     private static final int TAG_START_ALPHA = R.id.scrim_alpha_start;
60     private static final int TAG_END_ALPHA = R.id.scrim_alpha_end;
61 
62     protected final ScrimView mScrimBehind;
63     private final ScrimView mScrimInFront;
64     private final UnlockMethodCache mUnlockMethodCache;
65     private final View mHeadsUpScrim;
66     private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
67 
68     private float mScrimBehindAlpha = SCRIM_BEHIND_ALPHA;
69     private float mScrimBehindAlphaKeyguard = SCRIM_BEHIND_ALPHA_KEYGUARD;
70     private float mScrimBehindAlphaUnlocking = SCRIM_BEHIND_ALPHA_UNLOCKING;
71 
72     protected boolean mKeyguardShowing;
73     private float mFraction;
74 
75     private boolean mDarkenWhileDragging;
76     protected boolean mBouncerShowing;
77     private boolean mWakeAndUnlocking;
78     private boolean mAnimateChange;
79     private boolean mUpdatePending;
80     private boolean mExpanding;
81     private boolean mAnimateKeyguardFadingOut;
82     private long mDurationOverride = -1;
83     private long mAnimationDelay;
84     private Runnable mOnAnimationFinished;
85     private final Interpolator mInterpolator = new DecelerateInterpolator();
86     private boolean mDozing;
87     private float mDozeInFrontAlpha;
88     private float mDozeBehindAlpha;
89     private float mCurrentInFrontAlpha;
90     private float mCurrentBehindAlpha;
91     private float mCurrentHeadsUpAlpha = 1;
92     private int mPinnedHeadsUpCount;
93     private float mTopHeadsUpDragAmount;
94     private View mDraggedHeadsUpView;
95     private boolean mForceHideScrims;
96     private boolean mSkipFirstFrame;
97     private boolean mDontAnimateBouncerChanges;
98     private boolean mKeyguardFadingOutInProgress;
99     private ValueAnimator mKeyguardFadeoutAnimation;
100 
ScrimController(ScrimView scrimBehind, ScrimView scrimInFront, View headsUpScrim)101     public ScrimController(ScrimView scrimBehind, ScrimView scrimInFront, View headsUpScrim) {
102         mScrimBehind = scrimBehind;
103         mScrimInFront = scrimInFront;
104         mHeadsUpScrim = headsUpScrim;
105         final Context context = scrimBehind.getContext();
106         mUnlockMethodCache = UnlockMethodCache.getInstance(context);
107         mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(context);
108         updateHeadsUpScrim(false);
109     }
110 
setKeyguardShowing(boolean showing)111     public void setKeyguardShowing(boolean showing) {
112         mKeyguardShowing = showing;
113         scheduleUpdate();
114     }
115 
setShowScrimBehind(boolean show)116     public void setShowScrimBehind(boolean show) {
117         if (show) {
118             mScrimBehindAlpha = SCRIM_BEHIND_ALPHA;
119             mScrimBehindAlphaKeyguard = SCRIM_BEHIND_ALPHA_KEYGUARD;
120             mScrimBehindAlphaUnlocking = SCRIM_BEHIND_ALPHA_UNLOCKING;
121         } else {
122             mScrimBehindAlpha = 0;
123             mScrimBehindAlphaKeyguard = 0;
124             mScrimBehindAlphaUnlocking = 0;
125         }
126         scheduleUpdate();
127     }
128 
setScrimBehindValues(float scrimBehindAlphaKeyguard, float scrimBehindAlphaUnlocking)129     protected void setScrimBehindValues(float scrimBehindAlphaKeyguard,
130             float scrimBehindAlphaUnlocking) {
131         mScrimBehindAlphaKeyguard = scrimBehindAlphaKeyguard;
132         mScrimBehindAlphaUnlocking = scrimBehindAlphaUnlocking;
133         scheduleUpdate();
134     }
135 
onTrackingStarted()136     public void onTrackingStarted() {
137         mExpanding = true;
138         mDarkenWhileDragging = !mUnlockMethodCache.canSkipBouncer();
139     }
140 
onExpandingFinished()141     public void onExpandingFinished() {
142         mExpanding = false;
143     }
144 
setPanelExpansion(float fraction)145     public void setPanelExpansion(float fraction) {
146         if (mFraction != fraction) {
147             mFraction = fraction;
148             scheduleUpdate();
149             if (mPinnedHeadsUpCount != 0) {
150                 updateHeadsUpScrim(false);
151             }
152             if (mKeyguardFadeoutAnimation != null) {
153                 mKeyguardFadeoutAnimation.cancel();
154             }
155         }
156     }
157 
setBouncerShowing(boolean showing)158     public void setBouncerShowing(boolean showing) {
159         mBouncerShowing = showing;
160         mAnimateChange = !mExpanding && !mDontAnimateBouncerChanges;
161         scheduleUpdate();
162     }
163 
setWakeAndUnlocking()164     public void setWakeAndUnlocking() {
165         mWakeAndUnlocking = true;
166         scheduleUpdate();
167     }
168 
animateKeyguardFadingOut(long delay, long duration, Runnable onAnimationFinished, boolean skipFirstFrame)169     public void animateKeyguardFadingOut(long delay, long duration, Runnable onAnimationFinished,
170             boolean skipFirstFrame) {
171         mWakeAndUnlocking = false;
172         mAnimateKeyguardFadingOut = true;
173         mDurationOverride = duration;
174         mAnimationDelay = delay;
175         mAnimateChange = true;
176         mSkipFirstFrame = skipFirstFrame;
177         mOnAnimationFinished = onAnimationFinished;
178 
179         if (mKeyguardUpdateMonitor.isUserUnlocked()) {
180             scheduleUpdate();
181 
182             // No need to wait for the next frame to be drawn for this case - onPreDraw will execute
183             // the changes we just scheduled.
184             onPreDraw();
185         } else {
186 
187             // In case the user isn't unlocked, make sure to delay a bit because the system is hosed
188             // with too many things in this case, in order to not skip the initial frames.
189             mScrimInFront.postOnAnimationDelayed(this::scheduleUpdate, 16);
190         }
191     }
192 
abortKeyguardFadingOut()193     public void abortKeyguardFadingOut() {
194         if (mAnimateKeyguardFadingOut) {
195             endAnimateKeyguardFadingOut(true /* force */);
196         }
197     }
198 
animateGoingToFullShade(long delay, long duration)199     public void animateGoingToFullShade(long delay, long duration) {
200         mDurationOverride = duration;
201         mAnimationDelay = delay;
202         mAnimateChange = true;
203         scheduleUpdate();
204     }
205 
animateNextChange()206     public void animateNextChange() {
207         mAnimateChange = true;
208     }
209 
setDozing(boolean dozing)210     public void setDozing(boolean dozing) {
211         if (mDozing != dozing) {
212             mDozing = dozing;
213             scheduleUpdate();
214         }
215     }
216 
setDozeInFrontAlpha(float alpha)217     public void setDozeInFrontAlpha(float alpha) {
218         mDozeInFrontAlpha = alpha;
219         updateScrimColor(mScrimInFront);
220     }
221 
setDozeBehindAlpha(float alpha)222     public void setDozeBehindAlpha(float alpha) {
223         mDozeBehindAlpha = alpha;
224         updateScrimColor(mScrimBehind);
225     }
226 
getDozeBehindAlpha()227     public float getDozeBehindAlpha() {
228         return mDozeBehindAlpha;
229     }
230 
getDozeInFrontAlpha()231     public float getDozeInFrontAlpha() {
232         return mDozeInFrontAlpha;
233     }
234 
getScrimInFrontAlpha()235     private float getScrimInFrontAlpha() {
236         return mKeyguardUpdateMonitor.isUserUnlocked()
237                 ? SCRIM_IN_FRONT_ALPHA
238                 : SCRIM_IN_FRONT_ALPHA_LOCKED;
239     }
scheduleUpdate()240     private void scheduleUpdate() {
241         if (mUpdatePending) return;
242 
243         // Make sure that a frame gets scheduled.
244         mScrimBehind.invalidate();
245         mScrimBehind.getViewTreeObserver().addOnPreDrawListener(this);
246         mUpdatePending = true;
247     }
248 
updateScrims()249     protected void updateScrims() {
250         if (mAnimateKeyguardFadingOut || mForceHideScrims) {
251             setScrimInFrontColor(0f);
252             setScrimBehindColor(0f);
253         } else if (mWakeAndUnlocking) {
254 
255             // During wake and unlock, we first hide everything behind a black scrim, which then
256             // gets faded out from animateKeyguardFadingOut.
257             if (mDozing) {
258                 setScrimInFrontColor(0f);
259                 setScrimBehindColor(1f);
260             } else {
261                 setScrimInFrontColor(1f);
262                 setScrimBehindColor(0f);
263             }
264         } else if (!mKeyguardShowing && !mBouncerShowing) {
265             updateScrimNormal();
266             setScrimInFrontColor(0);
267         } else {
268             updateScrimKeyguard();
269         }
270         mAnimateChange = false;
271     }
272 
updateScrimKeyguard()273     private void updateScrimKeyguard() {
274         if (mExpanding && mDarkenWhileDragging) {
275             float behindFraction = Math.max(0, Math.min(mFraction, 1));
276             float fraction = 1 - behindFraction;
277             fraction = (float) Math.pow(fraction, 0.8f);
278             behindFraction = (float) Math.pow(behindFraction, 0.8f);
279             setScrimInFrontColor(fraction * getScrimInFrontAlpha());
280             setScrimBehindColor(behindFraction * mScrimBehindAlphaKeyguard);
281         } else if (mBouncerShowing) {
282             setScrimInFrontColor(getScrimInFrontAlpha());
283             setScrimBehindColor(0f);
284         } else {
285             float fraction = Math.max(0, Math.min(mFraction, 1));
286             setScrimInFrontColor(0f);
287             setScrimBehindColor(fraction
288                     * (mScrimBehindAlphaKeyguard - mScrimBehindAlphaUnlocking)
289                     + mScrimBehindAlphaUnlocking);
290         }
291     }
292 
updateScrimNormal()293     private void updateScrimNormal() {
294         float frac = mFraction;
295         // let's start this 20% of the way down the screen
296         frac = frac * 1.2f - 0.2f;
297         if (frac <= 0) {
298             setScrimBehindColor(0);
299         } else {
300             // woo, special effects
301             final float k = (float)(1f-0.5f*(1f-Math.cos(3.14159f * Math.pow(1f-frac, 2f))));
302             setScrimBehindColor(k * mScrimBehindAlpha);
303         }
304     }
305 
setScrimBehindColor(float alpha)306     private void setScrimBehindColor(float alpha) {
307         setScrimColor(mScrimBehind, alpha);
308     }
309 
setScrimInFrontColor(float alpha)310     private void setScrimInFrontColor(float alpha) {
311         setScrimColor(mScrimInFront, alpha);
312         if (alpha == 0f) {
313             mScrimInFront.setClickable(false);
314         } else {
315 
316             // Eat touch events (unless dozing).
317             mScrimInFront.setClickable(!mDozing);
318         }
319     }
320 
setScrimColor(View scrim, float alpha)321     private void setScrimColor(View scrim, float alpha) {
322         updateScrim(mAnimateChange, scrim, alpha, getCurrentScrimAlpha(scrim));
323     }
324 
getDozeAlpha(View scrim)325     private float getDozeAlpha(View scrim) {
326         return scrim == mScrimBehind ? mDozeBehindAlpha : mDozeInFrontAlpha;
327     }
328 
getCurrentScrimAlpha(View scrim)329     private float getCurrentScrimAlpha(View scrim) {
330         return scrim == mScrimBehind ? mCurrentBehindAlpha
331                 : scrim == mScrimInFront ? mCurrentInFrontAlpha
332                 : mCurrentHeadsUpAlpha;
333     }
334 
setCurrentScrimAlpha(View scrim, float alpha)335     private void setCurrentScrimAlpha(View scrim, float alpha) {
336         if (scrim == mScrimBehind) {
337             mCurrentBehindAlpha = alpha;
338         } else if (scrim == mScrimInFront) {
339             mCurrentInFrontAlpha = alpha;
340         } else {
341             alpha = Math.max(0.0f, Math.min(1.0f, alpha));
342             mCurrentHeadsUpAlpha = alpha;
343         }
344     }
345 
updateScrimColor(View scrim)346     private void updateScrimColor(View scrim) {
347         float alpha1 = getCurrentScrimAlpha(scrim);
348         if (scrim instanceof ScrimView) {
349             float alpha2 = getDozeAlpha(scrim);
350             float alpha = 1 - (1 - alpha1) * (1 - alpha2);
351             alpha = Math.max(0, Math.min(1.0f, alpha));
352             ((ScrimView) scrim).setScrimColor(Color.argb((int) (alpha * 255), 0, 0, 0));
353         } else {
354             scrim.setAlpha(alpha1);
355         }
356     }
357 
startScrimAnimation(final View scrim, float target)358     private void startScrimAnimation(final View scrim, float target) {
359         float current = getCurrentScrimAlpha(scrim);
360         ValueAnimator anim = ValueAnimator.ofFloat(current, target);
361         anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
362             @Override
363             public void onAnimationUpdate(ValueAnimator animation) {
364                 float alpha = (float) animation.getAnimatedValue();
365                 setCurrentScrimAlpha(scrim, alpha);
366                 updateScrimColor(scrim);
367             }
368         });
369         anim.setInterpolator(getInterpolator());
370         anim.setStartDelay(mAnimationDelay);
371         anim.setDuration(mDurationOverride != -1 ? mDurationOverride : ANIMATION_DURATION);
372         anim.addListener(new AnimatorListenerAdapter() {
373             @Override
374             public void onAnimationEnd(Animator animation) {
375                 if (mOnAnimationFinished != null) {
376                     mOnAnimationFinished.run();
377                     mOnAnimationFinished = null;
378                 }
379                 if (mKeyguardFadingOutInProgress) {
380                     mKeyguardFadeoutAnimation = null;
381                     mKeyguardFadingOutInProgress = false;
382                 }
383                 scrim.setTag(TAG_KEY_ANIM, null);
384                 scrim.setTag(TAG_KEY_ANIM_TARGET, null);
385             }
386         });
387         anim.start();
388         if (mAnimateKeyguardFadingOut) {
389             mKeyguardFadingOutInProgress = true;
390             mKeyguardFadeoutAnimation = anim;
391         }
392         if (mSkipFirstFrame) {
393             anim.setCurrentPlayTime(16);
394         }
395         scrim.setTag(TAG_KEY_ANIM, anim);
396         scrim.setTag(TAG_KEY_ANIM_TARGET, target);
397     }
398 
getInterpolator()399     private Interpolator getInterpolator() {
400         if (mAnimateKeyguardFadingOut && !mKeyguardUpdateMonitor.isUserUnlocked()) {
401             return KEYGUARD_FADE_OUT_INTERPOLATOR_LOCKED;
402         } else if (mAnimateKeyguardFadingOut) {
403             return KEYGUARD_FADE_OUT_INTERPOLATOR;
404         } else {
405             return mInterpolator;
406         }
407     }
408 
409     @Override
onPreDraw()410     public boolean onPreDraw() {
411         mScrimBehind.getViewTreeObserver().removeOnPreDrawListener(this);
412         mUpdatePending = false;
413         if (mDontAnimateBouncerChanges) {
414             mDontAnimateBouncerChanges = false;
415         }
416         updateScrims();
417         mDurationOverride = -1;
418         mAnimationDelay = 0;
419         mSkipFirstFrame = false;
420 
421         // Make sure that we always call the listener even if we didn't start an animation.
422         endAnimateKeyguardFadingOut(false /* force */);
423         return true;
424     }
425 
endAnimateKeyguardFadingOut(boolean force)426     private void endAnimateKeyguardFadingOut(boolean force) {
427         mAnimateKeyguardFadingOut = false;
428         if (force || (!isAnimating(mScrimInFront) && !isAnimating(mScrimBehind))) {
429             if (mOnAnimationFinished != null) {
430                 mOnAnimationFinished.run();
431                 mOnAnimationFinished = null;
432             }
433             mKeyguardFadingOutInProgress = false;
434         }
435     }
436 
isAnimating(View scrim)437     private boolean isAnimating(View scrim) {
438         return scrim.getTag(TAG_KEY_ANIM) != null;
439     }
440 
setDrawBehindAsSrc(boolean asSrc)441     public void setDrawBehindAsSrc(boolean asSrc) {
442         mScrimBehind.setDrawAsSrc(asSrc);
443     }
444 
445     @Override
onHeadsUpPinnedModeChanged(boolean inPinnedMode)446     public void onHeadsUpPinnedModeChanged(boolean inPinnedMode) {
447     }
448 
449     @Override
onHeadsUpPinned(ExpandableNotificationRow headsUp)450     public void onHeadsUpPinned(ExpandableNotificationRow headsUp) {
451         mPinnedHeadsUpCount++;
452         updateHeadsUpScrim(true);
453     }
454 
455     @Override
onHeadsUpUnPinned(ExpandableNotificationRow headsUp)456     public void onHeadsUpUnPinned(ExpandableNotificationRow headsUp) {
457         mPinnedHeadsUpCount--;
458         if (headsUp == mDraggedHeadsUpView) {
459             mDraggedHeadsUpView = null;
460             mTopHeadsUpDragAmount = 0.0f;
461         }
462         updateHeadsUpScrim(true);
463     }
464 
465     @Override
onHeadsUpStateChanged(NotificationData.Entry entry, boolean isHeadsUp)466     public void onHeadsUpStateChanged(NotificationData.Entry entry, boolean isHeadsUp) {
467     }
468 
updateHeadsUpScrim(boolean animate)469     private void updateHeadsUpScrim(boolean animate) {
470         updateScrim(animate, mHeadsUpScrim, calculateHeadsUpAlpha(), mCurrentHeadsUpAlpha);
471     }
472 
updateScrim(boolean animate, View scrim, float alpha, float currentAlpha)473     private void updateScrim(boolean animate, View scrim, float alpha, float currentAlpha) {
474         if (mKeyguardFadingOutInProgress) {
475             return;
476         }
477 
478         ValueAnimator previousAnimator = StackStateAnimator.getChildTag(scrim,
479                 TAG_KEY_ANIM);
480         float animEndValue = -1;
481         if (previousAnimator != null) {
482             if (animate || alpha == currentAlpha) {
483                 previousAnimator.cancel();
484             } else {
485                 animEndValue = StackStateAnimator.getChildTag(scrim, TAG_END_ALPHA);
486             }
487         }
488         if (alpha != currentAlpha && alpha != animEndValue) {
489             if (animate) {
490                 startScrimAnimation(scrim, alpha);
491                 scrim.setTag(TAG_START_ALPHA, currentAlpha);
492                 scrim.setTag(TAG_END_ALPHA, alpha);
493             } else {
494                 if (previousAnimator != null) {
495                     float previousStartValue = StackStateAnimator.getChildTag(scrim,
496                             TAG_START_ALPHA);
497                     float previousEndValue = StackStateAnimator.getChildTag(scrim,
498                             TAG_END_ALPHA);
499                     // we need to increase all animation keyframes of the previous animator by the
500                     // relative change to the end value
501                     PropertyValuesHolder[] values = previousAnimator.getValues();
502                     float relativeDiff = alpha - previousEndValue;
503                     float newStartValue = previousStartValue + relativeDiff;
504                     newStartValue = Math.max(0, Math.min(1.0f, newStartValue));
505                     values[0].setFloatValues(newStartValue, alpha);
506                     scrim.setTag(TAG_START_ALPHA, newStartValue);
507                     scrim.setTag(TAG_END_ALPHA, alpha);
508                     previousAnimator.setCurrentPlayTime(previousAnimator.getCurrentPlayTime());
509                 } else {
510                     // update the alpha directly
511                     setCurrentScrimAlpha(scrim, alpha);
512                     updateScrimColor(scrim);
513                 }
514             }
515         }
516     }
517 
518     /**
519      * Set the amount the current top heads up view is dragged. The range is from 0 to 1 and 0 means
520      * the heads up is in its resting space and 1 means it's fully dragged out.
521      *
522      * @param draggedHeadsUpView the dragged view
523      * @param topHeadsUpDragAmount how far is it dragged
524      */
setTopHeadsUpDragAmount(View draggedHeadsUpView, float topHeadsUpDragAmount)525     public void setTopHeadsUpDragAmount(View draggedHeadsUpView, float topHeadsUpDragAmount) {
526         mTopHeadsUpDragAmount = topHeadsUpDragAmount;
527         mDraggedHeadsUpView = draggedHeadsUpView;
528         updateHeadsUpScrim(false);
529     }
530 
calculateHeadsUpAlpha()531     private float calculateHeadsUpAlpha() {
532         float alpha;
533         if (mPinnedHeadsUpCount >= 2) {
534             alpha = 1.0f;
535         } else if (mPinnedHeadsUpCount == 0) {
536             alpha = 0.0f;
537         } else {
538             alpha = 1.0f - mTopHeadsUpDragAmount;
539         }
540         float expandFactor = (1.0f - mFraction);
541         expandFactor = Math.max(expandFactor, 0.0f);
542         return alpha * expandFactor;
543     }
544 
forceHideScrims(boolean hide)545     public void forceHideScrims(boolean hide) {
546         mForceHideScrims = hide;
547         mAnimateChange = false;
548         scheduleUpdate();
549     }
550 
dontAnimateBouncerChangesUntilNextFrame()551     public void dontAnimateBouncerChangesUntilNextFrame() {
552         mDontAnimateBouncerChanges = true;
553     }
554 
setExcludedBackgroundArea(Rect area)555     public void setExcludedBackgroundArea(Rect area) {
556         mScrimBehind.setExcludedArea(area);
557     }
558 
setLeftInset(int inset)559     public void setLeftInset(int inset) {
560         mScrimBehind.setLeftInset(inset);
561     }
562 
getScrimBehindColor()563     public int getScrimBehindColor() {
564         return mScrimBehind.getScrimColorWithAlpha();
565     }
566 
setScrimBehindChangeRunnable(Runnable changeRunnable)567     public void setScrimBehindChangeRunnable(Runnable changeRunnable) {
568         mScrimBehind.setChangeRunnable(changeRunnable);
569     }
570 
onDensityOrFontScaleChanged()571     public void onDensityOrFontScaleChanged() {
572         ViewGroup.LayoutParams layoutParams = mHeadsUpScrim.getLayoutParams();
573         layoutParams.height = mHeadsUpScrim.getResources().getDimensionPixelSize(
574                 R.dimen.heads_up_scrim_height);
575         mHeadsUpScrim.setLayoutParams(layoutParams);
576     }
577 
setCurrentUser(int currentUser)578     public void setCurrentUser(int currentUser) {
579         // Don't care in the base class.
580     }
581 }
582