Merge "Make entering recents a lot faster" into mnc-dev

This commit is contained in:
Jorim Jaggi
2015-06-04 21:52:00 +00:00
committed by Android (Google) Code Review
7 changed files with 168 additions and 43 deletions

View File

@@ -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,

View File

@@ -441,6 +441,10 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
if (mConfig.launchedHasConfigurationChanged) {
onEnterAnimationTriggered();
}
if (!mConfig.launchedHasConfigurationChanged) {
mRecentsView.disableLayersForOneFrame();
}
}
@Override

View File

@@ -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

View File

@@ -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

View File

@@ -651,6 +651,10 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
}
}
public void disableLayersForOneFrame() {
mHeaderView.disableLayersForOneFrame();
}
/**** TaskCallbacks Implementation ****/
/** Binds this task view to the task */

View File

@@ -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. */
@@ -304,6 +308,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

View File

@@ -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