Color extraction on scrims

Consuming color extraction library to add wallpaper
colors to sysui scrims. Handles both lock screen and
notification shade.

Bug: 36856508
Bug: 37013527
Test: runtest --path frameworks/base/packages/SystemUI/tests/src/com/android/systemui/statusbar/ScrimViewTest.java
Change-Id: I8d964c978a766243d90bbfb3432d19eebf1a2056
This commit is contained in:
Lucas Dupin
2017-04-21 14:02:16 -07:00
parent aff819542a
commit 8da8f2e9dd
6 changed files with 359 additions and 116 deletions

View File

@@ -37,7 +37,8 @@ LOCAL_STATIC_ANDROID_LIBRARIES := \
android-support-v7-mediarouter \
android-support-v7-palette \
android-support-v14-preference \
android-support-v17-leanback
android-support-v17-leanback \
colorextraction
LOCAL_STATIC_JAVA_LIBRARIES := \
SystemUI-tags \

View File

@@ -19,39 +19,52 @@ package com.android.systemui.statusbar;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.annotation.NonNull;
import android.content.Context;
import android.content.res.TypedArray;
import android.content.res.Configuration;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.v4.graphics.ColorUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Display;
import android.view.View;
import android.view.WindowManager;
import android.view.animation.Interpolator;
import com.android.systemui.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Dependency;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.google.android.colorextraction.ColorExtractor;
import com.google.android.colorextraction.drawable.GradientDrawable;
/**
* A view which can draw a scrim
*/
public class ScrimView extends View
{
private final Paint mPaint = new Paint();
private int mScrimColor;
private boolean mIsEmpty = true;
public class ScrimView extends View implements ConfigurationController.ConfigurationListener {
private static final String TAG = "ScrimView";
private final ColorExtractor.GradientColors mColors;
private boolean mDrawAsSrc;
private float mViewAlpha = 1.0f;
private ValueAnimator mAlphaAnimator;
private Rect mExcludedRect = new Rect();
private boolean mHasExcludedArea;
private ValueAnimator.AnimatorUpdateListener mAlphaUpdateListener
= new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mViewAlpha = (float) animation.getAnimatedValue();
invalidate();
private Drawable mDrawable;
private PorterDuffColorFilter mColorFilter;
private int mTintColor;
private ValueAnimator.AnimatorUpdateListener mAlphaUpdateListener = animation -> {
if (mDrawable == null) {
Log.w(TAG, "Trying to animate null drawable");
return;
}
mDrawable.setAlpha((int) (255 * (float) animation.getAnimatedValue()));
};
private AnimatorListenerAdapter mClearAnimatorListener = new AnimatorListenerAdapter() {
@Override
@@ -76,72 +89,134 @@ public class ScrimView extends View
public ScrimView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ScrimView);
mDrawable = new GradientDrawable(context);
mDrawable.setCallback(this);
mColors = new ColorExtractor.GradientColors();
updateScreenSize();
try {
mScrimColor = ta.getColor(R.styleable.ScrimView_scrimColor, Color.BLACK);
} finally {
ta.recycle();
}
// We need to know about configuration changes to update the gradient size
// since it's independent from view bounds.
ConfigurationController config = Dependency.get(ConfigurationController.class);
config.addCallback(this);
}
@Override
protected void onDraw(Canvas canvas) {
if (mDrawAsSrc || (!mIsEmpty && mViewAlpha > 0f)) {
PorterDuff.Mode mode = mDrawAsSrc ? PorterDuff.Mode.SRC : PorterDuff.Mode.SRC_OVER;
int color = getScrimColorWithAlpha();
if (mDrawAsSrc || mDrawable.getAlpha() > 0) {
if (!mHasExcludedArea) {
canvas.drawColor(color, mode);
mDrawable.draw(canvas);
} else {
mPaint.setColor(color);
if (mExcludedRect.top > 0) {
canvas.drawRect(0, 0, getWidth(), mExcludedRect.top, mPaint);
canvas.save();
canvas.clipRect(0, 0, getWidth(), mExcludedRect.top);
mDrawable.draw(canvas);
canvas.restore();
}
if (mExcludedRect.left > 0) {
canvas.drawRect(0, mExcludedRect.top, mExcludedRect.left, mExcludedRect.bottom,
mPaint);
canvas.save();
canvas.clipRect(0, mExcludedRect.top, mExcludedRect.left,
mExcludedRect.bottom);
mDrawable.draw(canvas);
canvas.restore();
}
if (mExcludedRect.right < getWidth()) {
canvas.drawRect(mExcludedRect.right,
mExcludedRect.top,
getWidth(),
mExcludedRect.bottom,
mPaint);
canvas.save();
canvas.clipRect(mExcludedRect.right, mExcludedRect.top, getWidth(),
mExcludedRect.bottom);
mDrawable.draw(canvas);
canvas.restore();
}
if (mExcludedRect.bottom < getHeight()) {
canvas.drawRect(0, mExcludedRect.bottom, getWidth(), getHeight(), mPaint);
canvas.save();
canvas.clipRect(0, mExcludedRect.bottom, getWidth(), getHeight());
mDrawable.draw(canvas);
canvas.restore();
}
}
}
}
public int getScrimColorWithAlpha() {
int color = mScrimColor;
color = Color.argb((int) (Color.alpha(color) * mViewAlpha), Color.red(color),
Color.green(color), Color.blue(color));
return color;
public void setDrawable(Drawable drawable) {
mDrawable = drawable;
mDrawable.setCallback(this);
mDrawable.setBounds(getLeft(), getTop(), getRight(), getBottom());
invalidate();
}
@Override
public void invalidateDrawable(@NonNull Drawable drawable) {
super.invalidateDrawable(drawable);
if (drawable == mDrawable) {
invalidate();
}
}
public void setDrawAsSrc(boolean asSrc) {
mDrawAsSrc = asSrc;
mPaint.setXfermode(new PorterDuffXfermode(mDrawAsSrc ? PorterDuff.Mode.SRC
: PorterDuff.Mode.SRC_OVER));
invalidate();
PorterDuff.Mode mode = asSrc ? PorterDuff.Mode.SRC : PorterDuff.Mode.SRC_OVER;
mDrawable.setXfermode(new PorterDuffXfermode(mode));
}
public void setScrimColor(int color) {
if (color != mScrimColor) {
mIsEmpty = Color.alpha(color) == 0;
mScrimColor = color;
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (changed) {
mDrawable.setBounds(left, top, right, bottom);
invalidate();
if (mChangeRunnable != null) {
mChangeRunnable.run();
}
}
}
public int getScrimColor() {
return mScrimColor;
public void setColors(@NonNull ColorExtractor.GradientColors colors) {
if (colors == null) {
throw new IllegalArgumentException("Colors cannot be null");
}
if (mColors.equals(colors)) {
return;
}
mColors.set(colors);
updateColorWithTint();
}
@VisibleForTesting
Drawable getDrawable() {
return mDrawable;
}
public void setTint(int color) {
if (mTintColor == color) {
return;
}
mTintColor = color;
updateColorWithTint();
}
private void updateColorWithTint() {
if (mDrawable instanceof GradientDrawable) {
// Optimization to blend colors and avoid a color filter
GradientDrawable drawable = (GradientDrawable) mDrawable;
float tintAmount = Color.alpha(mTintColor) / 255f;
int mainTinted = ColorUtils.blendARGB(mColors.getMainColor(), mTintColor,
tintAmount);
int secondaryTinted = ColorUtils.blendARGB(mColors.getSecondaryColor(), mTintColor,
tintAmount);
drawable.setColors(mainTinted, secondaryTinted, false);
} else {
if (mColorFilter == null) {
mColorFilter = new PorterDuffColorFilter(mTintColor, PorterDuff.Mode.SRC_OVER);
} else {
mColorFilter.setColor(mTintColor);
}
mDrawable.setColorFilter(Color.alpha(mTintColor) == 0 ? null : mColorFilter);
mDrawable.invalidateSelf();
}
if (mChangeRunnable != null) {
mChangeRunnable.run();
}
}
public int getTint() {
return mTintColor;
}
@Override
@@ -150,23 +225,30 @@ public class ScrimView extends View
}
public void setViewAlpha(float alpha) {
if (mAlphaAnimator != null) {
mAlphaAnimator.cancel();
}
if (alpha != mViewAlpha) {
mViewAlpha = alpha;
invalidate();
if (mAlphaAnimator != null) {
mAlphaAnimator.cancel();
}
mDrawable.setAlpha((int) (255 * alpha));
if (mChangeRunnable != null) {
mChangeRunnable.run();
}
}
}
@VisibleForTesting
float getViewAlpha() {
return mViewAlpha;
}
public void animateViewAlpha(float alpha, long durationOut, Interpolator interpolator) {
if (mAlphaAnimator != null) {
mAlphaAnimator.cancel();
}
mAlphaAnimator = ValueAnimator.ofFloat(mViewAlpha, alpha);
mAlphaAnimator = ValueAnimator.ofFloat(getViewAlpha(), alpha);
mAlphaAnimator.addUpdateListener(mAlphaUpdateListener);
mAlphaAnimator.addListener(mClearAnimatorListener);
mAlphaAnimator.setInterpolator(interpolator);
@@ -193,4 +275,25 @@ public class ScrimView extends View
public void setChangeRunnable(Runnable changeRunnable) {
mChangeRunnable = changeRunnable;
}
@Override
public void onConfigChanged(Configuration newConfig) {
updateScreenSize();
}
private void updateScreenSize() {
if (mDrawable instanceof GradientDrawable) {
WindowManager wm = mContext.getSystemService(WindowManager.class);
if (wm == null) {
Log.w(TAG, "Can't resize gradient drawable to fit the screen");
return;
}
Display display = wm.getDefaultDisplay();
if (display != null) {
Point size = new Point();
display.getRealSize(size);
((GradientDrawable) mDrawable).setScreenSize(size.x, size.y);
}
}
}
}

View File

@@ -20,9 +20,12 @@ import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.PropertyValuesHolder;
import android.animation.ValueAnimator;
import android.app.WallpaperManager;
import android.content.Context;
import android.graphics.Color;
import android.graphics.Rect;
import android.support.v4.graphics.ColorUtils;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
@@ -30,6 +33,7 @@ import android.view.ViewTreeObserver;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import android.view.animation.PathInterpolator;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.R;
import com.android.systemui.statusbar.ExpandableNotificationRow;
@@ -38,12 +42,14 @@ import com.android.systemui.statusbar.ScrimView;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
import com.android.systemui.statusbar.stack.ViewState;
import com.google.android.colorextraction.ColorExtractor;
/**
* Controls both the scrim behind the notifications and in front of the notifications (when a
* security method gets shown).
*/
public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
OnHeadsUpChangedListener {
OnHeadsUpChangedListener, ColorExtractor.OnColorsChangedListener {
public static final long ANIMATION_DURATION = 220;
public static final Interpolator KEYGUARD_FADE_OUT_INTERPOLATOR
= new PathInterpolator(0f, 0, 0.7f, 1f);
@@ -61,11 +67,16 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
private final LightBarController mLightBarController;
protected final ScrimView mScrimBehind;
private final ScrimView mScrimInFront;
protected final ScrimView mScrimInFront;
private final UnlockMethodCache mUnlockMethodCache;
private final View mHeadsUpScrim;
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private final ColorExtractor mColorExtractor;
private ColorExtractor.GradientColors mLockColors;
private ColorExtractor.GradientColors mSystemColors;
private boolean mNeedsDrawableColorUpdate;
protected float mScrimBehindAlpha;
protected float mScrimBehindAlphaKeyguard = SCRIM_BEHIND_ALPHA_KEYGUARD;
protected float mScrimBehindAlphaUnlocking = SCRIM_BEHIND_ALPHA_UNLOCKING;
@@ -98,6 +109,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
private boolean mSkipFirstFrame;
private boolean mDontAnimateBouncerChanges;
private boolean mKeyguardFadingOutInProgress;
private boolean mAnimatingDozeUnlock;
private ValueAnimator mKeyguardFadeoutAnimation;
public ScrimController(LightBarController lightBarController, ScrimView scrimBehind,
@@ -111,12 +123,22 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
mLightBarController = lightBarController;
mScrimBehindAlpha = context.getResources().getFloat(R.dimen.scrim_behind_alpha);
mColorExtractor = new ColorExtractor(context);
mColorExtractor.setListener(this);
mLockColors = mColorExtractor.getColors(WallpaperManager.FLAG_LOCK);
mSystemColors = mColorExtractor.getColors(WallpaperManager.FLAG_SYSTEM);
mNeedsDrawableColorUpdate = true;
updateHeadsUpScrim(false);
updateScrims();
}
public void setKeyguardShowing(boolean showing) {
mKeyguardShowing = showing;
// Showing/hiding the keyguard means that scrim colors
// will probably have to be switched
mNeedsDrawableColorUpdate = true;
scheduleUpdate();
}
@@ -157,6 +179,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
public void setWakeAndUnlocking() {
mWakeAndUnlocking = true;
mAnimatingDozeUnlock = true;
scheduleUpdate();
}
@@ -192,7 +215,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
public void animateKeyguardUnoccluding(long duration) {
mAnimateChange = false;
setScrimBehindColor(0f);
setScrimBehindAlpha(0f);
mAnimateChange = true;
scheduleUpdate();
mDurationOverride = duration;
@@ -246,23 +269,35 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
}
protected void updateScrims() {
if (mAnimateKeyguardFadingOut || mForceHideScrims) {
setScrimInFrontColor(0f);
setScrimBehindColor(0f);
} else if (mWakeAndUnlocking) {
// Make sure we have the right gradients
if (mNeedsDrawableColorUpdate) {
mNeedsDrawableColorUpdate = false;
if (mKeyguardShowing) {
mScrimInFront.setColors(mLockColors);
mScrimBehind.setColors(mLockColors);
} else {
mScrimInFront.setColors(mSystemColors);
mScrimBehind.setColors(mSystemColors);
}
}
if (mAnimateKeyguardFadingOut || mForceHideScrims) {
setScrimInFrontAlpha(0f);
setScrimBehindAlpha(0f);
} else if (mWakeAndUnlocking) {
// During wake and unlock, we first hide everything behind a black scrim, which then
// gets faded out from animateKeyguardFadingOut.
if (mDozing) {
setScrimInFrontColor(0f);
setScrimBehindColor(1f);
setScrimInFrontAlpha(0f);
setScrimBehindAlpha(1f);
} else {
setScrimInFrontColor(1f);
setScrimBehindColor(0f);
setScrimInFrontAlpha(1f);
setScrimBehindAlpha(0f);
}
} else if (!mKeyguardShowing && !mBouncerShowing) {
updateScrimNormal();
setScrimInFrontColor(0);
setScrimInFrontAlpha(0);
} else {
updateScrimKeyguard();
}
@@ -275,18 +310,18 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
float fraction = 1 - behindFraction;
fraction = (float) Math.pow(fraction, 0.8f);
behindFraction = (float) Math.pow(behindFraction, 0.8f);
setScrimInFrontColor(fraction * getScrimInFrontAlpha());
setScrimBehindColor(behindFraction * mScrimBehindAlphaKeyguard);
setScrimInFrontAlpha(fraction * getScrimInFrontAlpha());
setScrimBehindAlpha(behindFraction * mScrimBehindAlphaKeyguard);
} else if (mBouncerShowing && !mBouncerIsKeyguard) {
setScrimInFrontColor(getScrimInFrontAlpha());
setScrimInFrontAlpha(getScrimInFrontAlpha());
updateScrimNormal();
} else if (mBouncerShowing) {
setScrimInFrontColor(0f);
setScrimBehindColor(mScrimBehindAlpha);
setScrimInFrontAlpha(0f);
setScrimBehindAlpha(mScrimBehindAlpha);
} else {
float fraction = Math.max(0, Math.min(mFraction, 1));
setScrimInFrontColor(0f);
setScrimBehindColor(fraction
setScrimInFrontAlpha(0f);
setScrimBehindAlpha(fraction
* (mScrimBehindAlphaKeyguard - mScrimBehindAlphaUnlocking)
+ mScrimBehindAlphaUnlocking);
}
@@ -297,30 +332,29 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
// let's start this 20% of the way down the screen
frac = frac * 1.2f - 0.2f;
if (frac <= 0) {
setScrimBehindColor(0);
setScrimBehindAlpha(0);
} else {
// woo, special effects
final float k = (float)(1f-0.5f*(1f-Math.cos(3.14159f * Math.pow(1f-frac, 2f))));
setScrimBehindColor(k * mScrimBehindAlpha);
setScrimBehindAlpha(k * mScrimBehindAlpha);
}
}
private void setScrimBehindColor(float alpha) {
setScrimColor(mScrimBehind, alpha);
private void setScrimBehindAlpha(float alpha) {
setScrimAlpha(mScrimBehind, alpha);
}
private void setScrimInFrontColor(float alpha) {
setScrimColor(mScrimInFront, alpha);
private void setScrimInFrontAlpha(float alpha) {
setScrimAlpha(mScrimInFront, alpha);
if (alpha == 0f) {
mScrimInFront.setClickable(false);
} else {
// Eat touch events (unless dozing).
mScrimInFront.setClickable(!mDozing);
}
}
private void setScrimColor(View scrim, float alpha) {
private void setScrimAlpha(View scrim, float alpha) {
updateScrim(mAnimateChange, scrim, alpha, getCurrentScrimAlpha(scrim));
}
@@ -346,15 +380,20 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
}
}
protected void updateScrimColor(View scrim) {
private void updateScrimColor(View scrim) {
float alpha1 = getCurrentScrimAlpha(scrim);
if (scrim instanceof ScrimView) {
float alpha2 = getDozeAlpha(scrim);
float alpha = 1 - (1 - alpha1) * (1 - alpha2);
ScrimView scrimView = (ScrimView) scrim;
float dozeAlpha = getDozeAlpha(scrim);
float alpha = 1 - (1 - alpha1) * (1 - dozeAlpha);
alpha = Math.max(0, Math.min(1.0f, alpha));
int baseColor = ((ScrimView) scrim).getScrimColor();
((ScrimView) scrim).setScrimColor(
ColorUtils.setAlphaComponent(baseColor, (int) (alpha * 255)));
scrimView.setViewAlpha(alpha);
int dozeTint = Color.TRANSPARENT;
if (mAnimatingDozeUnlock || mDozing) {
dozeTint = Color.BLACK;
}
scrimView.setTint(dozeTint);
} else {
scrim.setAlpha(alpha1);
}
@@ -363,13 +402,10 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
private void startScrimAnimation(final View scrim, float target) {
float current = getCurrentScrimAlpha(scrim);
ValueAnimator anim = ValueAnimator.ofFloat(current, target);
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float alpha = (float) animation.getAnimatedValue();
setCurrentScrimAlpha(scrim, alpha);
updateScrimColor(scrim);
}
anim.addUpdateListener(animation -> {
float alpha = (float) animation.getAnimatedValue();
setCurrentScrimAlpha(scrim, alpha);
updateScrimColor(scrim);
});
anim.setInterpolator(getInterpolator());
anim.setStartDelay(mAnimationDelay);
@@ -384,6 +420,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
if (mKeyguardFadingOutInProgress) {
mKeyguardFadeoutAnimation = null;
mKeyguardFadingOutInProgress = false;
mAnimatingDozeUnlock = false;
}
scrim.setTag(TAG_KEY_ANIM, null);
scrim.setTag(TAG_KEY_ANIM_TARGET, null);
@@ -436,6 +473,8 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
mOnAnimationFinished = null;
}
mKeyguardFadingOutInProgress = false;
if (!mWakeAndUnlocking || force)
mAnimatingDozeUnlock = false;
}
}
@@ -559,8 +598,10 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
mScrimBehind.setExcludedArea(area);
}
public int getScrimBehindColor() {
return mScrimBehind.getScrimColorWithAlpha();
public int getBackgroundColor() {
int color = mLockColors.getMainColor();
return Color.argb((int) (mScrimBehind.getAlpha() * Color.alpha(color)),
Color.red(color), Color.green(color), Color.blue(color));
}
public void setScrimBehindChangeRunnable(Runnable changeRunnable) {
@@ -577,4 +618,18 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
public void setCurrentUser(int currentUser) {
// Don't care in the base class.
}
@Override
public void onColorsChanged(ColorExtractor.GradientColors colors, int which) {
if ((which & WallpaperManager.FLAG_LOCK) != 0) {
mLockColors = colors;
mNeedsDrawableColorUpdate = true;
scheduleUpdate();
}
if ((which & WallpaperManager.FLAG_SYSTEM) != 0) {
mSystemColors = colors;
mNeedsDrawableColorUpdate = true;
scheduleUpdate();
}
}
}

View File

@@ -58,6 +58,7 @@ import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.widget.OverScroller;
import android.widget.ScrollView;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.ExpandHelper;
@@ -87,6 +88,8 @@ import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.ScrollAdapter;
import android.support.v4.graphics.ColorUtils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -485,16 +488,8 @@ public class NotificationStackScrollLayout extends ViewGroup
float alpha = BACKGROUND_ALPHA_DIMMED + (1 - BACKGROUND_ALPHA_DIMMED) * (1.0f - mDimAmount);
alpha *= mBackgroundFadeAmount;
// We need to manually blend in the background color
int scrimColor = mScrimController.getScrimBehindColor();
// SRC_OVER blending Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc
float alphaInv = 1 - alpha;
int color = Color.argb((int) (alpha * 255 + alphaInv * Color.alpha(scrimColor)),
(int) (mBackgroundFadeAmount * Color.red(mBgColor)
+ alphaInv * Color.red(scrimColor)),
(int) (mBackgroundFadeAmount * Color.green(mBgColor)
+ alphaInv * Color.green(scrimColor)),
(int) (mBackgroundFadeAmount * Color.blue(mBgColor)
+ alphaInv * Color.blue(scrimColor)));
int scrimColor = mScrimController.getBackgroundColor();
int color = ColorUtils.blendARGB(scrimColor, mBgColor, alpha);
if (mCachedBackgroundColor != color) {
mCachedBackgroundColor = color;
mBackgroundPaint.setColor(color);
@@ -4074,12 +4069,7 @@ public class NotificationStackScrollLayout extends ViewGroup
public void setScrimController(ScrimController scrimController) {
mScrimController = scrimController;
mScrimController.setScrimBehindChangeRunnable(new Runnable() {
@Override
public void run() {
updateBackgroundDimming();
}
});
mScrimController.setScrimBehindChangeRunnable(this::updateBackgroundDimming);
}
public void forceNoOverlappingRendering(boolean force) {

View File

@@ -43,7 +43,8 @@ LOCAL_STATIC_ANDROID_LIBRARIES := \
android-support-v7-appcompat \
android-support-v7-mediarouter \
android-support-v14-preference \
android-support-v17-leanback
android-support-v17-leanback \
colorextraction
LOCAL_STATIC_JAVA_LIBRARIES := \
metrics-helper-lib \

View File

@@ -0,0 +1,93 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android.systemui.statusbar;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.VectorDrawable;
import android.testing.AndroidTestingRunner;
import android.view.View;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.ScrimView;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.mock;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import static junit.framework.Assert.assertEquals;
@RunWith(AndroidTestingRunner.class)
public class ScrimViewTest extends SysuiTestCase {
ScrimView mView;
@Before
public void setUp() {
mView = new ScrimView(getContext());
mView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
mView.layout(0, 0, 1920, 1080);
}
@Test
public void testSetDrawable_UpdateDrawable() {
Drawable drawable = new ColorDrawable(Color.GREEN);
mView.setDrawable(drawable);
assertEquals(drawable, mView.getDrawable());
}
@Test
public void testSetViewAlpha_propagatesToDrawable() {
float alpha = 0.5f;
mView.setViewAlpha(alpha);
assertEquals(mView.getViewAlpha(), alpha);
}
@Test
public void testOnDraw_ExcludeRectDrawable() {
mView.setExcludedArea(new Rect(10, 10, 20, 20));
Canvas canvas = mock(Canvas.class);
mView.onDraw(canvas);
// One time for each rect side
verify(canvas, times(4)).clipRect(anyInt(), anyInt(), anyInt(), anyInt());
}
@Test
public void setTint_set() {
int tint = Color.BLUE;
mView.setTint(tint);
assertEquals(mView.getTint(), tint);
}
}