summaryrefslogtreecommitdiffstats
path: root/packages/SystemUI/src/com/android/systemui/recents
diff options
context:
space:
mode:
authorSelim Cinek <cinek@google.com>2014-09-17 04:03:52 +0200
committerSelim Cinek <cinek@google.com>2014-09-18 14:26:35 +0200
commite8199c582d826a39e6e47b0d8418834c15242fec (patch)
tree05e4c6bbb1047a4f2931d74da8e91148e1edb4b6 /packages/SystemUI/src/com/android/systemui/recents
parent941aa1afe35851185df56a9e4304a916db82b57f (diff)
downloadframeworks_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')
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java34
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java35
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java151
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();
}
}