SystemUI: Refactor QS media artwork
Change-Id: I711c1e9ebafa886040d12651ed3070157cbd91ab Signed-off-by: Ghosuto <clash.raja10@gmail.com>
This commit is contained in:
@@ -1049,6 +1049,9 @@ public final class NotificationPanelViewController implements
|
||||
// start fading the shade.
|
||||
mIsBrightnessMirrorShowing.setValue(isShowing);
|
||||
}
|
||||
if (mScrimController != null) {
|
||||
mScrimController.notifyBrightnessMirrorChanged(isShowing);
|
||||
}
|
||||
setAlpha(isShowing ? 0 : 255, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,11 +21,9 @@ import android.database.ContentObserver;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.ColorMatrix;
|
||||
import android.graphics.ColorMatrixColorFilter;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.TransitionDrawable;
|
||||
import android.graphics.RenderEffect;
|
||||
import android.graphics.Shader;
|
||||
import android.media.session.PlaybackState;
|
||||
@@ -34,7 +32,6 @@ import android.os.Looper;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.systemui.media.MediaSessionManager;
|
||||
import com.android.systemui.scrim.ScrimView;
|
||||
@@ -50,6 +47,11 @@ public class MediaArtScrimController implements MediaSessionManager.MediaDataLis
|
||||
private static final int MAX_BITMAP_SIZE = 400;
|
||||
private static final int DEFAULT_DIM_AMOUNT = 10;
|
||||
|
||||
private static final long ARTWORK_UPDATE_DEBOUNCE_MS = 200L;
|
||||
|
||||
private static final int CROSSFADE_DURATION_MS = 300;
|
||||
private static final boolean ENABLE_CROSSFADE = true;
|
||||
|
||||
private final Context mContext;
|
||||
private final ContentResolver mContentResolver;
|
||||
private final Handler mHandler;
|
||||
@@ -75,9 +77,15 @@ public class MediaArtScrimController implements MediaSessionManager.MediaDataLis
|
||||
private float mQsExpansion = 0f;
|
||||
private float mLastAppliedExpansion = 0f;
|
||||
private Bitmap mCurrentBitmap = null;
|
||||
private boolean mBrightnessMirrorShowing = false;
|
||||
|
||||
private Runnable mPendingStateUpdate = null;
|
||||
private static final long STATE_UPDATE_DELAY_MS = 30;
|
||||
|
||||
private Runnable mPendingArtworkUpdate = null;
|
||||
private Drawable mPendingArtwork = null;
|
||||
|
||||
private Drawable mLastAppliedArtwork = null;
|
||||
|
||||
private final ContentObserver mSettingsObserver = new ContentObserver(
|
||||
new Handler(Looper.getMainLooper())) {
|
||||
@@ -170,16 +178,13 @@ public class MediaArtScrimController implements MediaSessionManager.MediaDataLis
|
||||
}
|
||||
}
|
||||
|
||||
private void updateMediaArtScrimEnabled() {
|
||||
updateSettings();
|
||||
}
|
||||
|
||||
private boolean shouldShowMediaArt() {
|
||||
if (!mMediaArtScrimEnabled) return false;
|
||||
if (mCurrentMediaArtwork == null || !mHasActiveMedia) return false;
|
||||
if (mKeyguardShowing) return false;
|
||||
if (mBouncerShowing) return false;
|
||||
if (mKeyguardGoingAway) return false;
|
||||
if (mBrightnessMirrorShowing) return true;
|
||||
if (mQsExpansion < MIN_QS_EXPANSION_FOR_MEDIA_ART) return false;
|
||||
return true;
|
||||
}
|
||||
@@ -195,24 +200,59 @@ public class MediaArtScrimController implements MediaSessionManager.MediaDataLis
|
||||
|
||||
@Override
|
||||
public void onAlbumArtChanged(Drawable drawable) {
|
||||
mCurrentMediaArtwork = drawable;
|
||||
if (mMediaArtScrimEnabled) {
|
||||
if (mIsApplied) {
|
||||
if (mPendingStateUpdate != null) {
|
||||
mHandler.removeCallbacks(mPendingStateUpdate);
|
||||
}
|
||||
|
||||
mPendingStateUpdate = () -> {
|
||||
mPendingStateUpdate = null;
|
||||
mIsApplied = false;
|
||||
updateScrimState();
|
||||
};
|
||||
|
||||
mHandler.postDelayed(mPendingStateUpdate, 150);
|
||||
} else {
|
||||
scheduleStateUpdate();
|
||||
}
|
||||
if (mPendingArtworkUpdate != null) {
|
||||
mHandler.removeCallbacks(mPendingArtworkUpdate);
|
||||
mPendingArtworkUpdate = null;
|
||||
}
|
||||
|
||||
mPendingArtwork = drawable;
|
||||
|
||||
if (isSameArtwork(mPendingArtwork, mCurrentMediaArtwork)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mPendingArtworkUpdate = () -> {
|
||||
mCurrentMediaArtwork = mPendingArtwork;
|
||||
mPendingArtworkUpdate = null;
|
||||
|
||||
if (mMediaArtScrimEnabled) {
|
||||
if (mIsApplied) {
|
||||
if (mPendingStateUpdate != null) {
|
||||
mHandler.removeCallbacks(mPendingStateUpdate);
|
||||
}
|
||||
|
||||
mPendingStateUpdate = () -> {
|
||||
mPendingStateUpdate = null;
|
||||
mIsApplied = false;
|
||||
updateScrimState();
|
||||
};
|
||||
|
||||
mHandler.postDelayed(mPendingStateUpdate, 150);
|
||||
} else {
|
||||
scheduleStateUpdate();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
mHandler.postDelayed(mPendingArtworkUpdate, ARTWORK_UPDATE_DEBOUNCE_MS);
|
||||
}
|
||||
|
||||
private boolean isSameArtwork(Drawable drawable1, Drawable drawable2) {
|
||||
if (drawable1 == drawable2) return true;
|
||||
if (drawable1 == null || drawable2 == null) return false;
|
||||
|
||||
if (drawable1.getIntrinsicWidth() != drawable2.getIntrinsicWidth() ||
|
||||
drawable1.getIntrinsicHeight() != drawable2.getIntrinsicHeight()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (drawable1 instanceof BitmapDrawable && drawable2 instanceof BitmapDrawable) {
|
||||
Bitmap bitmap1 = ((BitmapDrawable) drawable1).getBitmap();
|
||||
Bitmap bitmap2 = ((BitmapDrawable) drawable2).getBitmap();
|
||||
return bitmap1 != null && bitmap1.sameAs(bitmap2);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -222,6 +262,7 @@ public class MediaArtScrimController implements MediaSessionManager.MediaDataLis
|
||||
|
||||
if (!mHasActiveMedia) {
|
||||
mCurrentMediaArtwork = null;
|
||||
mLastAppliedArtwork = null;
|
||||
if (mIsApplied) {
|
||||
mHandler.post(() -> {
|
||||
restoreRegularScrimImmediate();
|
||||
@@ -229,6 +270,11 @@ public class MediaArtScrimController implements MediaSessionManager.MediaDataLis
|
||||
} else {
|
||||
cleanupBitmap();
|
||||
}
|
||||
|
||||
if (mPendingArtworkUpdate != null) {
|
||||
mHandler.removeCallbacks(mPendingArtworkUpdate);
|
||||
mPendingArtworkUpdate = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (mMediaArtScrimEnabled && wasActive != mHasActiveMedia) {
|
||||
@@ -244,6 +290,27 @@ public class MediaArtScrimController implements MediaSessionManager.MediaDataLis
|
||||
public void onMetadataChanged(String track, String artist) {
|
||||
}
|
||||
|
||||
public void setBrightnessMirrorShowing(boolean showing) {
|
||||
Log.d(TAG, "setBrightnessMirrorShowing: " + showing + ", mIsApplied: " + mIsApplied);
|
||||
|
||||
boolean wasShowing = mBrightnessMirrorShowing;
|
||||
mBrightnessMirrorShowing = showing;
|
||||
|
||||
if (showing && mIsApplied) {
|
||||
if (mNotificationsScrim != null) {
|
||||
mNotificationsScrim.setAlpha(0f);
|
||||
}
|
||||
} else if (!showing && wasShowing && mIsApplied) {
|
||||
if (mNotificationsScrim != null) {
|
||||
mNotificationsScrim.setRenderEffect(mBlurEffect);
|
||||
mNotificationsScrim.setViewAlpha(mQsExpansion);
|
||||
mNotificationsScrim.setAlpha(mQsExpansion);
|
||||
}
|
||||
} else if (!showing && !mIsApplied && canShowMediaArt()) {
|
||||
scheduleStateUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
public void onPanelExpansionChanged(float expansion) {
|
||||
if (!mMediaArtScrimEnabled || mNotificationsScrim == null) {
|
||||
return;
|
||||
@@ -252,6 +319,10 @@ public class MediaArtScrimController implements MediaSessionManager.MediaDataLis
|
||||
float oldExpansion = mQsExpansion;
|
||||
mQsExpansion = expansion;
|
||||
|
||||
if (mBrightnessMirrorShowing) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!canShowMediaArt() && mIsApplied) {
|
||||
restoreRegularScrimImmediate();
|
||||
return;
|
||||
@@ -306,20 +377,13 @@ public class MediaArtScrimController implements MediaSessionManager.MediaDataLis
|
||||
|
||||
private void applyMediaArt() {
|
||||
if (!shouldShowMediaArt()) {
|
||||
Log.d(TAG, "Skipping media art application - conditions not met");
|
||||
if (mIsApplied) {
|
||||
restoreRegularScrimImmediate();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (mIsApplied) {
|
||||
if (Math.abs(mLastAppliedExpansion - mQsExpansion) > 0.01f) {
|
||||
mNotificationsScrim.setAlpha(mQsExpansion);
|
||||
mLastAppliedExpansion = mQsExpansion;
|
||||
}
|
||||
return;
|
||||
}
|
||||
boolean isReapplying = mIsApplied;
|
||||
|
||||
if (mOriginalTint == -1) {
|
||||
saveOriginalScrimState();
|
||||
@@ -327,17 +391,24 @@ public class MediaArtScrimController implements MediaSessionManager.MediaDataLis
|
||||
|
||||
Bitmap bitmap = drawableToBitmap(mCurrentMediaArtwork);
|
||||
if (bitmap != null) {
|
||||
mNotificationsScrim.setBackground(null);
|
||||
|
||||
cleanupBitmap();
|
||||
|
||||
mCurrentBitmap = applyDimToBitmap(bitmap);
|
||||
BitmapDrawable blurredDrawable = new BitmapDrawable(
|
||||
BitmapDrawable newDrawable = new BitmapDrawable(
|
||||
mContext.getResources(), mCurrentBitmap);
|
||||
|
||||
mNotificationsScrim.setMediaArtApplied(true);
|
||||
if (ENABLE_CROSSFADE && isReapplying
|
||||
&& mLastAppliedArtwork != null
|
||||
&& mNotificationsScrim.getBackground() != null
|
||||
&& !mBrightnessMirrorShowing) {
|
||||
applyCrossfadeTransition(newDrawable);
|
||||
} else {
|
||||
mNotificationsScrim.setBackground(newDrawable);
|
||||
}
|
||||
|
||||
mNotificationsScrim.setBackground(blurredDrawable);
|
||||
mLastAppliedArtwork = mCurrentMediaArtwork;
|
||||
|
||||
mNotificationsScrim.setMediaArtApplied(true);
|
||||
mNotificationsScrim.setRenderEffect(mBlurEffect);
|
||||
mNotificationsScrim.setTint(android.graphics.Color.TRANSPARENT);
|
||||
mNotificationsScrim.setViewAlpha(mQsExpansion);
|
||||
@@ -345,12 +416,50 @@ public class MediaArtScrimController implements MediaSessionManager.MediaDataLis
|
||||
mIsApplied = true;
|
||||
mLastAppliedExpansion = mQsExpansion;
|
||||
|
||||
Log.d(TAG, "Applied media art to notifications scrim with dim amount: " + mMediaArtDimAmount);
|
||||
Log.d(TAG, "Applied media art to notifications scrim with dim amount: "
|
||||
+ mMediaArtDimAmount + (isReapplying && ENABLE_CROSSFADE ? " (with crossfade)" : ""));
|
||||
} else {
|
||||
Log.e(TAG, "Failed to create bitmap from artwork");
|
||||
}
|
||||
}
|
||||
|
||||
private void applyCrossfadeTransition(Drawable newDrawable) {
|
||||
try {
|
||||
Drawable currentBackground = mNotificationsScrim.getBackground();
|
||||
|
||||
if (currentBackground != null && currentBackground instanceof BitmapDrawable) {
|
||||
BitmapDrawable oldDrawable = (BitmapDrawable) currentBackground;
|
||||
Bitmap oldBitmap = oldDrawable.getBitmap();
|
||||
|
||||
if (oldBitmap != null && !oldBitmap.isRecycled()) {
|
||||
Drawable[] layers = new Drawable[] {
|
||||
new BitmapDrawable(mContext.getResources(), oldBitmap),
|
||||
newDrawable
|
||||
};
|
||||
|
||||
TransitionDrawable transition = new TransitionDrawable(layers);
|
||||
transition.setCrossFadeEnabled(true);
|
||||
|
||||
mNotificationsScrim.setBackground(transition);
|
||||
|
||||
transition.startTransition(CROSSFADE_DURATION_MS);
|
||||
|
||||
Log.d(TAG, "Started crossfade transition (" + CROSSFADE_DURATION_MS + "ms)");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mNotificationsScrim.setBackground(newDrawable);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error during crossfade transition, falling back to direct set", e);
|
||||
try {
|
||||
mNotificationsScrim.setBackground(newDrawable);
|
||||
} catch (Exception ex) {
|
||||
Log.e(TAG, "Critical error setting background", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Bitmap applyDimToBitmap(Bitmap source) {
|
||||
if (source == null || mMediaArtDimAmount <= 0) {
|
||||
return source;
|
||||
@@ -469,6 +578,10 @@ public class MediaArtScrimController implements MediaSessionManager.MediaDataLis
|
||||
return;
|
||||
}
|
||||
|
||||
if (mBrightnessMirrorShowing) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mPendingStateUpdate != null) {
|
||||
mHandler.removeCallbacks(mPendingStateUpdate);
|
||||
mPendingStateUpdate = null;
|
||||
@@ -476,9 +589,11 @@ public class MediaArtScrimController implements MediaSessionManager.MediaDataLis
|
||||
|
||||
mNotificationsScrim.setBackground(null);
|
||||
mNotificationsScrim.setRenderEffect(null);
|
||||
mNotificationsScrim.setMediaArtApplied(false);
|
||||
|
||||
mIsApplied = false;
|
||||
mLastAppliedExpansion = 0f;
|
||||
mLastAppliedArtwork = null;
|
||||
|
||||
cleanupBitmap();
|
||||
|
||||
@@ -595,12 +710,21 @@ public class MediaArtScrimController implements MediaSessionManager.MediaDataLis
|
||||
return mMediaArtDimAmount;
|
||||
}
|
||||
|
||||
public boolean shouldSkipNotificationsScrimUpdate() {
|
||||
return mIsApplied;
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
if (mPendingStateUpdate != null) {
|
||||
mHandler.removeCallbacks(mPendingStateUpdate);
|
||||
mPendingStateUpdate = null;
|
||||
}
|
||||
|
||||
if (mPendingArtworkUpdate != null) {
|
||||
mHandler.removeCallbacks(mPendingArtworkUpdate);
|
||||
mPendingArtworkUpdate = null;
|
||||
}
|
||||
|
||||
mContentResolver.unregisterContentObserver(mSettingsObserver);
|
||||
if (mListening) {
|
||||
mMediaSessionManager.removeListener(this);
|
||||
@@ -610,6 +734,8 @@ public class MediaArtScrimController implements MediaSessionManager.MediaDataLis
|
||||
restoreRegularScrim();
|
||||
cleanupBitmap();
|
||||
mCurrentMediaArtwork = null;
|
||||
mLastAppliedArtwork = null;
|
||||
mPendingArtwork = null;
|
||||
mOriginalScrimBackground = null;
|
||||
mBlurEffect = null;
|
||||
}
|
||||
|
||||
@@ -1292,7 +1292,10 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
||||
|
||||
mScrimInFront.setColors(mColors, animateScrimInFront);
|
||||
mScrimBehind.setColors(mColors, animateBehindScrim);
|
||||
mNotificationsScrim.setColors(mColors, animateScrimNotifications);
|
||||
|
||||
if (!shouldSkipNotificationsScrimUpdate()) {
|
||||
mNotificationsScrim.setColors(mColors, animateScrimNotifications);
|
||||
}
|
||||
|
||||
dispatchBackScrimState(mScrimBehind.getViewAlpha());
|
||||
}
|
||||
@@ -1300,7 +1303,9 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
||||
// Blur the notification scrim as needed. The blur is needed only when we show the
|
||||
// expanded shade behind the bouncer. Without it, the notification scrim outline is
|
||||
// visible behind the bouncer.
|
||||
mNotificationsScrim.setBlurRadius(mState.getNotifBlurRadius());
|
||||
if (!shouldSkipNotificationsScrimUpdate()) {
|
||||
mNotificationsScrim.setBlurRadius(mState.getNotifBlurRadius());
|
||||
}
|
||||
}
|
||||
|
||||
// We also want to hide FLAG_SHOW_WHEN_LOCKED activities under the scrim.
|
||||
@@ -1367,8 +1372,14 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
||||
}
|
||||
|
||||
private boolean shouldSkipNotificationsScrimUpdate() {
|
||||
return mMediaArtScrimController != null &&
|
||||
mMediaArtScrimController.isMediaArtApplied();
|
||||
return mMediaArtScrimController != null
|
||||
&& mMediaArtScrimController.isMediaArtApplied();
|
||||
}
|
||||
|
||||
public void notifyBrightnessMirrorChanged(boolean showing) {
|
||||
if (mMediaArtScrimController != null) {
|
||||
mMediaArtScrimController.setBrightnessMirrorShowing(showing);
|
||||
}
|
||||
}
|
||||
|
||||
private void setScrimAlpha(ScrimView scrim, float alpha) {
|
||||
|
||||
Reference in New Issue
Block a user