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