diff options
| author | Jorim Jaggi <jjaggi@google.com> | 2015-06-02 15:07:33 -0700 |
|---|---|---|
| committer | Jorim Jaggi <jjaggi@google.com> | 2015-06-04 11:21:49 -0700 |
| commit | 900fb48d269e2fbf3baea995c6324e4c08ad7c22 (patch) | |
| tree | ee7f9dc9fa0b73a5a0bd9b34d1df5379a610f435 | |
| parent | 658807a801cf5c484f4f4ec9dd896fa8d02249ea (diff) | |
| download | frameworks_base-900fb48d269e2fbf3baea995c6324e4c08ad7c22.zip frameworks_base-900fb48d269e2fbf3baea995c6324e4c08ad7c22.tar.gz frameworks_base-900fb48d269e2fbf3baea995c6324e4c08ad7c22.tar.bz2 | |
Make entering recents a lot faster
- Precache the bitmap for the window animation in the preload phase
- Remove some post's so we have a faster path from UP -> startActivity
- Don't dim the headers in the first frame drawn, because layer
creation is slow. Instead, do it in the second frame, when the window
animation is already running.
All these changes combined make going to recents about 40-50ms faster.
Change-Id: I3e4060af1ac57b3f359fe7f86f9e3814c6490323
7 files changed, 168 insertions, 43 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java index bbd3e60..7d2b5c87 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java +++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java @@ -32,6 +32,7 @@ import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Rect; +import android.os.AsyncTask; import android.os.Handler; import android.os.SystemClock; import android.os.UserHandle; @@ -40,6 +41,7 @@ import android.util.Pair; import android.view.Display; import android.view.LayoutInflater; import android.view.View; + import com.android.systemui.R; import com.android.systemui.RecentsComponent; import com.android.systemui.SystemUI; @@ -184,12 +186,16 @@ public class Recents extends SystemUI // Header (for transition) TaskViewHeader mHeaderBar; + final Object mHeaderBarLock = new Object(); TaskStackView mDummyStackView; // Variables to keep track of if we need to start recents after binding boolean mTriggeredFromAltTab; long mLastToggleTime; + Bitmap mThumbnailTransitionBitmapCache; + Task mThumbnailTransitionBitmapCacheKey; + public Recents() { } @@ -360,13 +366,16 @@ public class Recents extends SystemUI void preloadRecentsInternal() { // Preload only the raw task list into a new load plan (which will be consumed by the // RecentsActivity) + ActivityManager.RunningTaskInfo topTask = mSystemServicesProxy.getTopMostTask(); + MutableBoolean topTaskHome = new MutableBoolean(true); RecentsTaskLoader loader = RecentsTaskLoader.getInstance(); sInstanceLoadPlan = loader.createLoadPlan(mContext); - - ActivityManager.RunningTaskInfo topTask = mSystemServicesProxy.getTopMostTask(); - MutableBoolean isTopTaskHome = new MutableBoolean(true); - if (topTask != null && mSystemServicesProxy.isRecentsTopMost(topTask, isTopTaskHome)) { - sInstanceLoadPlan.preloadRawTasks(isTopTaskHome.value); + if (topTask != null && !mSystemServicesProxy.isRecentsTopMost(topTask, topTaskHome)) { + sInstanceLoadPlan.preloadRawTasks(topTaskHome.value); + loader.preloadTasks(sInstanceLoadPlan, topTaskHome.value); + TaskStack top = sInstanceLoadPlan.getAllTaskStacks().get(0); + preCacheThumbnailTransitionBitmapAsync(topTask, top, mDummyStackView, + topTaskHome.value); } } @@ -513,12 +522,14 @@ public class Recents extends SystemUI algo.computeRects(mWindowRect.width(), mWindowRect.height(), taskStackBounds); Rect taskViewSize = algo.getUntransformedTaskViewSize(); int taskBarHeight = res.getDimensionPixelSize(R.dimen.recents_task_bar_height); - mHeaderBar = (TaskViewHeader) mInflater.inflate(R.layout.recents_task_view_header, null, - false); - mHeaderBar.measure( - View.MeasureSpec.makeMeasureSpec(taskViewSize.width(), View.MeasureSpec.EXACTLY), - View.MeasureSpec.makeMeasureSpec(taskBarHeight, View.MeasureSpec.EXACTLY)); - mHeaderBar.layout(0, 0, taskViewSize.width(), taskBarHeight); + synchronized (mHeaderBarLock) { + mHeaderBar = (TaskViewHeader) mInflater.inflate(R.layout.recents_task_view_header, null, + false); + mHeaderBar.measure( + View.MeasureSpec.makeMeasureSpec(taskViewSize.width(), View.MeasureSpec.EXACTLY), + View.MeasureSpec.makeMeasureSpec(taskBarHeight, View.MeasureSpec.EXACTLY)); + mHeaderBar.layout(0, 0, taskViewSize.width(), taskBarHeight); + } } /** Prepares the search bar app widget */ @@ -607,30 +618,27 @@ public class Recents extends SystemUI */ ActivityOptions getThumbnailTransitionActivityOptions(ActivityManager.RunningTaskInfo topTask, TaskStack stack, TaskStackView stackView) { + // Update the destination rect Task toTask = new Task(); TaskViewTransform toTransform = getThumbnailTransitionTransform(stack, stackView, topTask.id, toTask); - if (toTransform != null && toTask.key != null) { - Rect toTaskRect = toTransform.rect; - int toHeaderWidth = (int) (mHeaderBar.getMeasuredWidth() * toTransform.scale); - int toHeaderHeight = (int) (mHeaderBar.getMeasuredHeight() * toTransform.scale); - Bitmap thumbnail = Bitmap.createBitmap(toHeaderWidth, toHeaderHeight, - Bitmap.Config.ARGB_8888); - if (Constants.DebugFlags.App.EnableTransitionThumbnailDebugMode) { - thumbnail.eraseColor(0xFFff0000); - } else { - Canvas c = new Canvas(thumbnail); - c.scale(toTransform.scale, toTransform.scale); - mHeaderBar.rebindToTask(toTask); - mHeaderBar.draw(c); - c.setBitmap(null); - } - Bitmap thumbnailImmutable = thumbnail.createAshmemBitmap(); - + Rect toTaskRect = toTransform.rect; + Bitmap thumbnail; + if (mThumbnailTransitionBitmapCacheKey != null + && mThumbnailTransitionBitmapCacheKey.key != null + && mThumbnailTransitionBitmapCacheKey.key.equals(toTask.key)) { + thumbnail = mThumbnailTransitionBitmapCache; + mThumbnailTransitionBitmapCacheKey = null; + mThumbnailTransitionBitmapCache = null; + } else { + preloadIcon(topTask); + thumbnail = drawThumbnailTransitionBitmap(toTask, toTransform); + } + if (thumbnail != null) { mStartAnimationTriggered = false; return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mDummyStackView, - thumbnailImmutable, toTaskRect.left, toTaskRect.top, toTaskRect.width(), + thumbnail, toTaskRect.left, toTaskRect.top, toTaskRect.width(), toTaskRect.height(), mHandler, this); } @@ -638,6 +646,72 @@ public class Recents extends SystemUI return getUnknownTransitionActivityOptions(); } + /** + * Preloads the icon of a task. + */ + void preloadIcon(ActivityManager.RunningTaskInfo task) { + + // Ensure that we load the running task's icon + RecentsTaskLoadPlan.Options launchOpts = new RecentsTaskLoadPlan.Options(); + launchOpts.runningTaskId = task.id; + launchOpts.loadThumbnails = false; + launchOpts.onlyLoadForCache = true; + RecentsTaskLoader.getInstance().loadTasks(mContext, sInstanceLoadPlan, launchOpts); + } + + /** + * Caches the header thumbnail used for a window animation asynchronously into + * {@link #mThumbnailTransitionBitmapCache}. + */ + void preCacheThumbnailTransitionBitmapAsync(ActivityManager.RunningTaskInfo topTask, + TaskStack stack, TaskStackView stackView, boolean isTopTaskHome) { + preloadIcon(topTask); + + // Update the destination rect + mDummyStackView.updateMinMaxScrollForStack(stack, mTriggeredFromAltTab, isTopTaskHome); + final Task toTask = new Task(); + final TaskViewTransform toTransform = getThumbnailTransitionTransform(stack, stackView, + topTask.id, toTask); + new AsyncTask<Void, Void, Bitmap>() { + @Override + protected Bitmap doInBackground(Void... params) { + return drawThumbnailTransitionBitmap(toTask, toTransform); + } + + @Override + protected void onPostExecute(Bitmap bitmap) { + mThumbnailTransitionBitmapCache = bitmap; + mThumbnailTransitionBitmapCacheKey = toTask; + } + }.execute(); + } + + /** + * Draws the header of a task used for the window animation into a bitmap. + */ + Bitmap drawThumbnailTransitionBitmap(Task toTask, TaskViewTransform toTransform) { + if (toTransform != null && toTask.key != null) { + Bitmap thumbnail; + synchronized (mHeaderBarLock) { + int toHeaderWidth = (int) (mHeaderBar.getMeasuredWidth() * toTransform.scale); + int toHeaderHeight = (int) (mHeaderBar.getMeasuredHeight() * toTransform.scale); + thumbnail = Bitmap.createBitmap(toHeaderWidth, toHeaderHeight, + Bitmap.Config.ARGB_8888); + if (Constants.DebugFlags.App.EnableTransitionThumbnailDebugMode) { + thumbnail.eraseColor(0xFFff0000); + } else { + Canvas c = new Canvas(thumbnail); + c.scale(toTransform.scale, toTransform.scale); + mHeaderBar.rebindToTask(toTask); + mHeaderBar.draw(c); + c.setBitmap(null); + } + } + return thumbnail.createAshmemBitmap(); + } + return null; + } + /** Returns the transition rect for the given task id. */ TaskViewTransform getThumbnailTransitionTransform(TaskStack stack, TaskStackView stackView, int runningTaskId, Task runningTaskOut) { @@ -694,7 +768,9 @@ public class Recents extends SystemUI return; } - loader.preloadTasks(sInstanceLoadPlan, isTopTaskHome); + if (!sInstanceLoadPlan.hasTasks()) { + loader.preloadTasks(sInstanceLoadPlan, isTopTaskHome); + } ArrayList<TaskStack> stacks = sInstanceLoadPlan.getAllTaskStacks(); TaskStack stack = stacks.get(0); @@ -706,12 +782,6 @@ public class Recents extends SystemUI boolean useThumbnailTransition = (topTask != null) && !isTopTaskHome && hasRecentTasks; if (useThumbnailTransition) { - // Ensure that we load the running task's icon - RecentsTaskLoadPlan.Options launchOpts = new RecentsTaskLoadPlan.Options(); - launchOpts.runningTaskId = topTask.id; - launchOpts.loadThumbnails = false; - launchOpts.onlyLoadForCache = true; - loader.loadTasks(mContext, sInstanceLoadPlan, launchOpts); // Try starting with a thumbnail transition ActivityOptions opts = getThumbnailTransitionActivityOptions(topTask, stack, diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java index ad97f91..9404dcb 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java @@ -441,6 +441,10 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView if (mConfig.launchedHasConfigurationChanged) { onEnterAnimationTriggered(); } + + if (!mConfig.launchedHasConfigurationChanged) { + mRecentsView.disableLayersForOneFrame(); + } } @Override diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java index cec613c..1a21d8a 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java @@ -431,6 +431,13 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV return false; } + public void disableLayersForOneFrame() { + List<TaskStackView> stackViews = getTaskStackViews(); + for (int i = 0; i < stackViews.size(); i++) { + stackViews.get(i).disableLayersForOneFrame(); + } + } + /**** TaskStackView.TaskStackCallbacks Implementation ****/ @Override diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java index 5f151e8..5711cd6 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java @@ -19,6 +19,7 @@ package com.android.systemui.recents.views; import android.animation.ValueAnimator; import android.content.ComponentName; import android.content.Context; +import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.Rect; import android.view.LayoutInflater; @@ -63,7 +64,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal public void onTaskResize(Task t); } - RecentsConfiguration mConfig; TaskStack mStack; @@ -81,7 +81,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal boolean mDismissAllButtonAnimating; int mFocusedTaskIndex = -1; int mPrevAccessibilityFocusedIndex = -1; - // Optimizations int mStackViewsAnimationDuration; boolean mStackViewsDirty = true; @@ -99,6 +98,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal ArrayList<TaskView> mTaskViews = new ArrayList<TaskView>(); List<TaskView> mImmutableTaskViews = new ArrayList<TaskView>(); LayoutInflater mInflater; + boolean mLayersDisabled; // A convenience update listener to request updating clipping of tasks ValueAnimator.AnimatorUpdateListener mRequestUpdateClippingListener = @@ -375,7 +375,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal if (tv == null) { tv = mViewPool.pickUpViewFromPool(task, task); - + if (mLayersDisabled) { + tv.disableLayersForOneFrame(); + } if (mStackViewsAnimationDuration > 0) { // For items in the list, put them in start animating them from the // approriate ends of the list where they are expected to appear @@ -1031,6 +1033,20 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal mUIDozeTrigger.poke(); } + @Override + protected void dispatchDraw(Canvas canvas) { + mLayersDisabled = false; + super.dispatchDraw(canvas); + } + + public void disableLayersForOneFrame() { + mLayersDisabled = true; + List<TaskView> taskViews = getTaskViews(); + for (int i = 0; i < taskViews.size(); i++) { + taskViews.get(i).disableLayersForOneFrame(); + } + } + /**** TaskStackCallbacks Implementation ****/ @Override 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 01ed08a..c27e3a8 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java @@ -650,6 +650,10 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, } } + public void disableLayersForOneFrame() { + mHeaderView.disableLayersForOneFrame(); + } + /**** TaskCallbacks Implementation ****/ /** Binds this task view to the task */ 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 f397bc3..09e9839 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java @@ -80,6 +80,8 @@ public class TaskViewHeader extends FrameLayout { Paint mDimLayerPaint = new Paint(); PorterDuffColorFilter mDimColorFilter = new PorterDuffColorFilter(0, PorterDuff.Mode.SRC_ATOP); + boolean mLayersDisabled; + public TaskViewHeader(Context context) { this(context, null); } @@ -172,7 +174,9 @@ public class TaskViewHeader extends FrameLayout { void setDimAlpha(int alpha) { mDimColorFilter.setColor(Color.argb(alpha, 0, 0, 0)); mDimLayerPaint.setColorFilter(mDimColorFilter); - setLayerType(LAYER_TYPE_HARDWARE, mDimLayerPaint); + if (!mLayersDisabled) { + setLayerType(LAYER_TYPE_HARDWARE, mDimLayerPaint); + } } /** Returns the secondary color for a primary color. */ @@ -305,6 +309,28 @@ public class TaskViewHeader extends FrameLayout { return new int[] {}; } + @Override + protected void dispatchDraw(Canvas canvas) { + super.dispatchDraw(canvas); + if (mLayersDisabled) { + mLayersDisabled = false; + postOnAnimation(new Runnable() { + @Override + public void run() { + mLayersDisabled = false; + setLayerType(LAYER_TYPE_HARDWARE, mDimLayerPaint); + } + }); + } + } + + public void disableLayersForOneFrame() { + mLayersDisabled = true; + + // Disable layer for a frame so we can draw our first frame faster. + setLayerType(LAYER_TYPE_NONE, null); + } + /** Notifies the associated TaskView has been focused. */ void onTaskViewFocusChanged(boolean focused, boolean animateFocusedState) { // If we are not animating the visible state, just return diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index fa172a4..f05ac1a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -1030,9 +1030,7 @@ public abstract class BaseStatusBar extends SystemUI implements @Override public void toggleRecentApps() { - int msg = MSG_TOGGLE_RECENTS_APPS; - mHandler.removeMessages(msg); - mHandler.sendEmptyMessage(msg); + toggleRecents(); } @Override |
