diff options
author | Selim Cinek <cinek@google.com> | 2014-09-17 04:03:52 +0200 |
---|---|---|
committer | Selim Cinek <cinek@google.com> | 2014-09-18 14:26:35 +0200 |
commit | e8199c582d826a39e6e47b0d8418834c15242fec (patch) | |
tree | 05e4c6bbb1047a4f2931d74da8e91148e1edb4b6 /packages/SystemUI/src/com/android/systemui/recents | |
parent | 941aa1afe35851185df56a9e4304a916db82b57f (diff) | |
download | frameworks_base-e8199c582d826a39e6e47b0d8418834c15242fec.zip frameworks_base-e8199c582d826a39e6e47b0d8418834c15242fec.tar.gz frameworks_base-e8199c582d826a39e6e47b0d8418834c15242fec.tar.bz2 |
Removed round rect clipping and hardware layers from recents
This saves us a lot of memory and we avoid the clipToOutline.
The view still looks the same, as we now draw the thumbnail
in a rounded rect.
We now only use a hardware layer on the header, which is much
smaller.
Bug: 17522143
Change-Id: I197a1172efe8450ffb0b537c780a240d38f84275
Diffstat (limited to 'packages/SystemUI/src/com/android/systemui/recents')
6 files changed, 189 insertions, 48 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java index 2a2caa0..2f5b07b 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java @@ -119,6 +119,7 @@ public class RecentsConfiguration { public int launchedToTaskId; /** Misc **/ + public boolean useHardwareLayers; public int altTabKeyDelay; /** Dev options and global settings */ @@ -271,6 +272,7 @@ public class RecentsConfiguration { res.getInteger(R.integer.recents_nav_bar_scrim_enter_duration); // Misc + useHardwareLayers = res.getBoolean(R.bool.config_recents_use_hardware_layers); altTabKeyDelay = res.getInteger(R.integer.recents_alt_tab_key_delay); } diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java index e5c06fd..d4b403d 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java @@ -204,7 +204,8 @@ class TaskResourceLoader implements Runnable { if (!mCancelled) { // Notify that the task data has changed final Drawable newIcon = cachedIcon; - final Bitmap newThumbnail = cachedThumbnail; + final Bitmap newThumbnail = cachedThumbnail == mDefaultThumbnail + ? null : cachedThumbnail; mMainThreadHandler.post(new Runnable() { @Override public void run() { @@ -252,7 +253,6 @@ public class RecentsTaskLoader { BitmapDrawable mDefaultApplicationIcon; Bitmap mDefaultThumbnail; - Bitmap mLoadingThumbnail; /** Private Constructor */ private RecentsTaskLoader(Context context) { @@ -271,9 +271,6 @@ public class RecentsTaskLoader { mDefaultThumbnail = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); mDefaultThumbnail.setHasAlpha(false); mDefaultThumbnail.eraseColor(0xFFffffff); - mLoadingThumbnail = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); - mLoadingThumbnail.setHasAlpha(false); - mLoadingThumbnail.eraseColor(0xFFffffff); mDefaultApplicationIcon = new BitmapDrawable(context.getResources(), icon); // Initialize the proxy, cache and loaders @@ -500,17 +497,16 @@ public class RecentsTaskLoader { // use the default assets in their place until they load boolean requiresLoad = (applicationIcon == null) || (thumbnail == null); applicationIcon = applicationIcon != null ? applicationIcon : mDefaultApplicationIcon; - thumbnail = thumbnail != null ? thumbnail : mDefaultThumbnail; if (requiresLoad) { mLoadQueue.addTask(t); } - t.notifyTaskDataLoaded(thumbnail, applicationIcon); + t.notifyTaskDataLoaded(thumbnail == mDefaultThumbnail ? null : thumbnail, applicationIcon); } /** Releases the task resource data back into the pool. */ public void unloadTaskData(Task t) { mLoadQueue.removeTask(t); - t.notifyTaskDataUnloaded(mDefaultThumbnail, mDefaultApplicationIcon); + t.notifyTaskDataUnloaded(null, mDefaultApplicationIcon); } /** Completely removes the resource data from the pool. */ @@ -519,7 +515,7 @@ public class RecentsTaskLoader { mThumbnailCache.remove(t.key); mApplicationIconCache.remove(t.key); if (notifyTaskDataUnloaded) { - t.notifyTaskDataUnloaded(mDefaultThumbnail, mDefaultApplicationIcon); + t.notifyTaskDataUnloaded(null, mDefaultApplicationIcon); } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java b/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java index d6889d0..0adc73c 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java @@ -44,7 +44,6 @@ public class AnimateableViewBounds extends ViewOutlineProvider { mConfig = RecentsConfiguration.getInstance(); mSourceView = source; mCornerRadius = cornerRadius; - mSourceView.setClipToOutline(true); setClipTop(getClipTop()); setClipRight(getClipRight()); setClipBottom(getClipBottom()); diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java index 51adc28..a1ddf0f 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java @@ -637,17 +637,31 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, /** Returns the current dim. */ public void setDim(int dim) { mDim = dim; - // Defer setting hardware layers if we have not yet measured, or there is no dim to draw - if (getMeasuredWidth() > 0 && getMeasuredHeight() > 0) { - if (mDimAnimator != null) { - mDimAnimator.removeAllListeners(); - mDimAnimator.cancel(); - } + if (mDimAnimator != null) { + mDimAnimator.removeAllListeners(); + mDimAnimator.cancel(); + } + if (mConfig.useHardwareLayers) { + // Defer setting hardware layers if we have not yet measured, or there is no dim to draw + if (getMeasuredWidth() > 0 && getMeasuredHeight() > 0) { + if (mDimAnimator != null) { + mDimAnimator.removeAllListeners(); + mDimAnimator.cancel(); + } - int inverse = 255 - mDim; - mDimColorFilter.setColor(Color.argb(0xFF, inverse, inverse, inverse)); - mLayerPaint.setColorFilter(mDimColorFilter); - setLayerType(LAYER_TYPE_HARDWARE, mLayerPaint); + int inverse = 255 - mDim; + mDimColorFilter.setColor(Color.argb(0xFF, inverse, inverse, inverse)); + mLayerPaint.setColorFilter(mDimColorFilter); + setLayerType(LAYER_TYPE_HARDWARE, mLayerPaint); + } + } else { + float dimAlpha = mDim / 255.0f; + if (mThumbnailView != null) { + mThumbnailView.setDimAlpha(dimAlpha); + } + if (mHeaderView != null) { + mHeaderView.setDimAlpha(dim); + } } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java index 1743433..fd39126 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java @@ -30,10 +30,13 @@ import android.graphics.Color; import android.graphics.Outline; import android.graphics.Paint; import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; import android.graphics.PorterDuffXfermode; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; +import android.graphics.drawable.GradientDrawable; import android.graphics.drawable.RippleDrawable; +import android.graphics.drawable.ShapeDrawable; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; @@ -58,17 +61,20 @@ public class TaskViewHeader extends FrameLayout { TextView mActivityDescription; RippleDrawable mBackground; - ColorDrawable mBackgroundColor; + GradientDrawable mBackgroundColorDrawable; + int mBackgroundColor; Drawable mLightDismissDrawable; Drawable mDarkDismissDrawable; AnimatorSet mFocusAnimator; ValueAnimator backgroundColorAnimator; + PorterDuffColorFilter mDimFilter = new PorterDuffColorFilter(0, PorterDuff.Mode.SRC_ATOP); boolean mIsFullscreen; boolean mCurrentPrimaryColorIsDark; int mCurrentPrimaryColor; static Paint sHighlightPaint; + private Paint mDimPaint = new Paint(); public TaskViewHeader(Context context) { this(context, null); @@ -140,13 +146,14 @@ public class TaskViewHeader extends FrameLayout { } } - mBackgroundColor = new ColorDrawable(0); + mBackgroundColorDrawable = (GradientDrawable) getContext().getDrawable(R.drawable + .recents_task_view_header_bg_color); // Copy the ripple drawable since we are going to be manipulating it mBackground = (RippleDrawable) getContext().getDrawable(R.drawable.recents_task_view_header_bg); mBackground = (RippleDrawable) mBackground.mutate().getConstantState().newDrawable(); mBackground.setColor(ColorStateList.valueOf(0)); - mBackground.setDrawableByLayerId(mBackground.getId(0), mBackgroundColor); + mBackground.setDrawableByLayerId(mBackground.getId(0), mBackgroundColorDrawable); setBackground(mBackground); } @@ -197,7 +204,8 @@ public class TaskViewHeader extends FrameLayout { int existingBgColor = (getBackground() instanceof ColorDrawable) ? ((ColorDrawable) getBackground()).getColor() : 0; if (existingBgColor != t.colorPrimary) { - mBackgroundColor.setColor(t.colorPrimary); + mBackgroundColorDrawable.setColor(t.colorPrimary); + mBackgroundColor = t.colorPrimary; } mCurrentPrimaryColor = t.colorPrimary; mCurrentPrimaryColorIsDark = t.useLightOnPrimaryColor; @@ -276,7 +284,7 @@ public class TaskViewHeader extends FrameLayout { mBackground.setColor(new ColorStateList(states, colors)); mBackground.setState(newStates); // Pulse the background color - int currentColor = mBackgroundColor.getColor(); + int currentColor = mBackgroundColor; int lightPrimaryColor = getSecondaryColor(mCurrentPrimaryColor, mCurrentPrimaryColorIsDark); ValueAnimator backgroundColor = ValueAnimator.ofObject(new ArgbEvaluator(), lightPrimaryColor, currentColor); @@ -289,7 +297,9 @@ public class TaskViewHeader extends FrameLayout { backgroundColor.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { - mBackgroundColor.setColor((Integer) animation.getAnimatedValue()); + int color = (int) animation.getAnimatedValue(); + mBackgroundColorDrawable.setColor(color); + mBackgroundColor = color; } }); backgroundColor.setRepeatCount(ValueAnimator.INFINITE); @@ -307,13 +317,15 @@ public class TaskViewHeader extends FrameLayout { } else { if (isRunning) { // Restore the background color - int currentColor = mBackgroundColor.getColor(); + int currentColor = mBackgroundColor; ValueAnimator backgroundColor = ValueAnimator.ofObject(new ArgbEvaluator(), currentColor, mCurrentPrimaryColor); backgroundColor.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { - mBackgroundColor.setColor((Integer) animation.getAnimatedValue()); + int color = (int) animation.getAnimatedValue(); + mBackgroundColorDrawable.setColor(color); + mBackgroundColor = color; } }); // Restore the translation @@ -329,4 +341,11 @@ public class TaskViewHeader extends FrameLayout { } } } + + public void setDimAlpha(int alpha) { + int color = Color.argb(alpha, 0, 0, 0); + mDimFilter.setColor(color); + mDimPaint.setColorFilter(mDimFilter); + setLayerType(LAYER_TYPE_HARDWARE, mDimPaint); + } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java index fe36987..11ca103 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java @@ -16,9 +16,20 @@ package com.android.systemui.recents.views; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Bitmap; +import android.graphics.BitmapShader; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.LightingColorFilter; +import android.graphics.Matrix; +import android.graphics.Paint; import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.Shader; import android.util.AttributeSet; import android.view.View; import com.android.systemui.recents.RecentsConfiguration; @@ -26,12 +37,30 @@ import com.android.systemui.recents.model.Task; /** The task thumbnail view */ -public class TaskViewThumbnail extends FixedSizeImageView { +public class TaskViewThumbnail extends View { + private final int mCornerRadius; + private final Matrix mScaleMatrix = new Matrix(); RecentsConfiguration mConfig; // Task bar clipping Rect mClipRect = new Rect(); + Paint mDrawPaint = new Paint(); + LightingColorFilter mLightingColorFilter = new LightingColorFilter(0xffffffff, 0); + private final RectF mBitmapRect = new RectF(); + private final RectF mLayoutRect = new RectF(); + private BitmapShader mBitmapShader; + private float mBitmapAlpha; + private float mDimAlpha; + private ValueAnimator mAlphaAnimator; + private ValueAnimator.AnimatorUpdateListener mAlphaUpdateListener + = new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + mBitmapAlpha = (float) animation.getAnimatedValue(); + updateFilter(); + } + }; public TaskViewThumbnail(Context context) { this(context, null); @@ -48,12 +77,43 @@ public class TaskViewThumbnail extends FixedSizeImageView { public TaskViewThumbnail(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); mConfig = RecentsConfiguration.getInstance(); - setScaleType(ScaleType.FIT_XY); + mCornerRadius = mConfig.taskViewRoundedCornerRadiusPx; + mDrawPaint.setColorFilter(mLightingColorFilter); + mDrawPaint.setFilterBitmap(true); + mDrawPaint.setAntiAlias(true); + } + + @Override + protected void onDraw(Canvas canvas) { + canvas.drawRoundRect(0, + 0, + getWidth(), + getHeight(), + mCornerRadius, + mCornerRadius, + mDrawPaint); } @Override protected void onFinishInflate() { - setAlpha(0.9f); + mBitmapAlpha = 0.9f; + updateFilter(); + } + + private void updateFilter() { + int mul = (int) ((1.0f - mDimAlpha) * mBitmapAlpha * 255); + int add = (int) ((1.0f - mDimAlpha) * (1 - mBitmapAlpha) * 255); + if (mBitmapShader != null) { + mLightingColorFilter.setColorMultiply(Color.argb(255, mul, mul, mul)); + mLightingColorFilter.setColorAdd(Color.argb(0, add, add, add)); + mDrawPaint.setColorFilter(mLightingColorFilter); + mDrawPaint.setColor(0xffffffff); + } else { + mDrawPaint.setColorFilter(null); + int grey = mul + add; + mDrawPaint.setColor(Color.argb(255, grey, grey, grey)); + } + invalidate(); } /** Updates the clip rect based on the given task bar. */ @@ -72,11 +132,8 @@ public class TaskViewThumbnail extends FixedSizeImageView { /** Binds the thumbnail view to the screenshot. */ boolean bindToScreenshot(Bitmap ss) { - if (ss != null) { - setImageBitmap(ss); - return true; - } - return false; + setImageBitmap(ss); + return ss != null; } /** Unbinds the thumbnail view from the screenshot. */ @@ -88,12 +145,49 @@ public class TaskViewThumbnail extends FixedSizeImageView { void rebindToTask(Task t) { if (t.thumbnail != null) { setImageBitmap(t.thumbnail); + } else { + setImageBitmap(null); + } + } + + public void setImageBitmap(Bitmap bm) { + if (bm != null) { + mBitmapShader = new BitmapShader(bm, Shader.TileMode.CLAMP, + Shader.TileMode.CLAMP); + mDrawPaint.setShader(mBitmapShader); + mBitmapRect.set(0, 0, bm.getWidth(), bm.getHeight()); + updateBitmapScale(); + } else { + mBitmapShader = null; + mDrawPaint.setShader(null); } + updateFilter(); + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + if (changed) { + mLayoutRect.set(0, 0, getWidth(), getHeight()); + updateBitmapScale(); + } + } + + private void updateBitmapScale() { + if (mBitmapShader != null) { + mScaleMatrix.setRectToRect(mBitmapRect, mLayoutRect, Matrix.ScaleToFit.FILL); + mBitmapShader.setLocalMatrix(mScaleMatrix); + } + } + + public void setDimAlpha(float dimAlpha) { + mDimAlpha = dimAlpha; + updateFilter(); } /** Unbinds the thumbnail view from the task */ void unbindFromTask() { - setImageDrawable(null); + setImageBitmap(null); } /** Handles focus changes. */ @@ -112,10 +206,11 @@ public class TaskViewThumbnail extends FixedSizeImageView { /** Prepares for the enter recents animation. */ void prepareEnterRecentsAnimation(boolean isTaskViewLaunchTargetTask) { if (isTaskViewLaunchTargetTask) { - setAlpha(1f); + mBitmapAlpha = 1f; } else { - setAlpha(mConfig.taskViewThumbnailAlpha); + mBitmapAlpha = mConfig.taskViewThumbnailAlpha; } + updateFilter(); } /** Animates this task thumbnail as it enters recents */ @@ -130,16 +225,32 @@ public class TaskViewThumbnail extends FixedSizeImageView { } /** Animates the thumbnail alpha. */ - void startFadeAnimation(float finalAlpha, int delay, int duration, Runnable postAnimRunnable) { + void startFadeAnimation(float finalAlpha, int delay, int duration, final Runnable postAnimRunnable) { + if (mAlphaAnimator != null) { + mAlphaAnimator.cancel(); + } + mAlphaAnimator = ValueAnimator.ofFloat(mBitmapAlpha, finalAlpha); + mAlphaAnimator.addUpdateListener(mAlphaUpdateListener); + mAlphaAnimator.setStartDelay(delay); + mAlphaAnimator.setInterpolator(mConfig.fastOutSlowInInterpolator); + mAlphaAnimator.setDuration(duration); + mAlphaAnimator.start(); if (postAnimRunnable != null) { - animate().withEndAction(postAnimRunnable); + mAlphaAnimator.addListener(new AnimatorListenerAdapter() { + public boolean mCancelled; + + @Override + public void onAnimationCancel(Animator animation) { + mCancelled = true; + } + + @Override + public void onAnimationEnd(Animator animation) { + if (!mCancelled) { + postAnimRunnable.run(); + } + } + }); } - animate() - .alpha(finalAlpha) - .setStartDelay(delay) - .setInterpolator(mConfig.fastOutSlowInInterpolator) - .setDuration(duration) - .withLayer() - .start(); } } |