Merge "DO NOT MERGE Fixing some regressions" into lmp-dev

This commit is contained in:
Winson Chung
2014-07-14 17:17:08 +00:00
committed by Android (Google) Code Review
16 changed files with 174 additions and 208 deletions

View File

@@ -32,7 +32,7 @@ public class Constants {
// Enables the filtering of tasks according to their grouping
public static final boolean EnableTaskFiltering = false;
// Enables clipping of tasks against each other
public static final boolean EnableTaskStackClipping = true;
public static final boolean EnableTaskStackClipping = false;
// Enables tapping on the TaskBar to launch the task
public static final boolean EnableTaskBarTouchEvents = true;
// Enables app-info pane on long-pressing the icon

View File

@@ -458,8 +458,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
filter.addAction(ACTION_TOGGLE_RECENTS_ACTIVITY);
filter.addAction(ACTION_START_ENTER_ANIMATION);
registerReceiver(mServiceBroadcastReceiver, filter);
mVisible = true;
}
@Override
@@ -485,6 +483,8 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
}
}, 1);
}
mVisible = true;
}
@Override

View File

@@ -72,7 +72,12 @@ public class ReferenceCountedTrigger {
/** Adds a runnable to the last-decrement runnables list. */
public void addLastDecrementRunnable(Runnable r) {
// To ensure that the last decrement always calls, we increment and decrement after setting
// the last decrement runnable
boolean ensureLastDecrement = (mCount == 0);
if (ensureLastDecrement) increment();
mLastDecRunnables.add(r);
if (ensureLastDecrement) decrement();
}
/** Decrements the ref count */

View File

@@ -16,16 +16,10 @@
package com.android.systemui.recents.misc;
import android.app.ActivityManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.ParcelFileDescriptor;
import com.android.systemui.recents.RecentsConfiguration;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -73,22 +67,25 @@ public class Utilities {
}
}
/** Calculates the luminance-preserved greyscale of a given color. */
public static int colorToGreyscale(int color) {
return Math.round(0.2126f * Color.red(color) + 0.7152f * Color.green(color) +
0.0722f * Color.blue(color));
}
/** Calculates the constrast between two colors, using the algorithm provided by the WCAG v2. */
public static float computeContrastBetweenColors(int bg, int fg) {
float bgR = Color.red(bg) / 255f;
float bgG = Color.green(bg) / 255f;
float bgB = Color.blue(bg) / 255f;
bgR = (bgR < 0.03928f) ? bgR / 12.92f : (float) Math.pow((bgR + 0.055f) / 1.055f, 2.4f);
bgG = (bgG < 0.03928f) ? bgG / 12.92f : (float) Math.pow((bgG + 0.055f) / 1.055f, 2.4f);
bgB = (bgB < 0.03928f) ? bgB / 12.92f : (float) Math.pow((bgB + 0.055f) / 1.055f, 2.4f);
float bgL = 0.2126f * bgR + 0.7152f * bgG + 0.0722f * bgB;
float fgR = Color.red(fg) / 255f;
float fgG = Color.green(fg) / 255f;
float fgB = Color.blue(fg) / 255f;
fgR = (fgR < 0.03928f) ? fgR / 12.92f : (float) Math.pow((fgR + 0.055f) / 1.055f, 2.4f);
fgG = (fgG < 0.03928f) ? fgG / 12.92f : (float) Math.pow((fgG + 0.055f) / 1.055f, 2.4f);
fgB = (fgB < 0.03928f) ? fgB / 12.92f : (float) Math.pow((fgB + 0.055f) / 1.055f, 2.4f);
float fgL = 0.2126f * fgR + 0.7152f * fgG + 0.0722f * fgB;
/** Returns the ideal color to draw on top of a specified background color. */
public static int getIdealColorForBackgroundColorGreyscale(int greyscale, int lightRes,
int darkRes) {
return (greyscale < 128) ? lightRes : darkRes;
}
/** Returns the ideal drawable to draw on top of a specified background color. */
public static Drawable getIdealResourceForBackgroundColorGreyscale(int greyscale,
Drawable lightRes,
Drawable darkRes) {
return (greyscale < 128) ? lightRes : darkRes;
return Math.abs((fgL + 0.05f) / (bgL + 0.05f));
}
/** Sets some private shadow properties. */

View File

@@ -29,6 +29,6 @@ class BitmapLruCache extends KeyStoreLruCache<Bitmap> {
@Override
protected int computeSize(Bitmap b) {
// The cache size will be measured in kilobytes rather than number of items
return b.getAllocationByteCount() / 1024;
return b.getAllocationByteCount();
}
}

View File

@@ -31,6 +31,6 @@ class DrawableLruCache extends KeyStoreLruCache<Drawable> {
// The cache size will be measured in kilobytes rather than number of items
// NOTE: this isn't actually correct, as the icon may be smaller
int maxBytes = (d.getIntrinsicWidth() * d.getIntrinsicHeight() * 4);
return maxBytes / 1024;
return maxBytes;
}
}

View File

@@ -73,11 +73,6 @@ public class KeyStoreLruCache<V> {
return mCache.get(key);
}
/** Gets the previous task key that matches the specified key. */
final Task.TaskKey getKey(Task.TaskKey key) {
return mKeys.get(key);
}
/** Puts an entry in the cache for a specific key. */
final void put(Task.TaskKey key, V value) {
mCache.put(key, value);

View File

@@ -45,7 +45,7 @@ public class RecentsPackageMonitor extends PackageMonitor {
mSystemServicesProxy = new SystemServicesProxy(context);
mCb = cb;
try {
register(context, Looper.getMainLooper(), false);
register(context, Looper.getMainLooper(), true);
} catch (IllegalStateException e) {
e.printStackTrace();
}

View File

@@ -27,38 +27,29 @@ import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.UserHandle;
import android.util.Pair;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.misc.Console;
import com.android.systemui.recents.misc.SystemServicesProxy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
/** A bitmap load queue */
class TaskResourceLoadQueue {
ConcurrentLinkedQueue<Task> mQueue = new ConcurrentLinkedQueue<Task>();
ConcurrentHashMap<Task.TaskKey, Boolean> mForceLoadSet =
new ConcurrentHashMap<Task.TaskKey, Boolean>();
static final Boolean sFalse = new Boolean(false);
/** Adds a new task to the load queue */
void addTask(Task t, boolean forceLoad) {
void addTask(Task t) {
if (Console.Enabled) {
Console.log(Constants.Log.App.TaskDataLoader, " [TaskResourceLoadQueue|addTask]");
}
if (!mQueue.contains(t)) {
mQueue.add(t);
}
if (forceLoad) {
mForceLoadSet.put(t.key, new Boolean(true));
}
synchronized(this) {
notifyAll();
}
@@ -68,19 +59,11 @@ class TaskResourceLoadQueue {
* Retrieves the next task from the load queue, as well as whether we want that task to be
* force reloaded.
*/
Pair<Task, Boolean> nextTask() {
Task nextTask() {
if (Console.Enabled) {
Console.log(Constants.Log.App.TaskDataLoader, " [TaskResourceLoadQueue|nextTask]");
}
Task task = mQueue.poll();
Boolean forceLoadTask = null;
if (task != null) {
forceLoadTask = mForceLoadSet.remove(task.key);
}
if (forceLoadTask == null) {
forceLoadTask = sFalse;
}
return new Pair<Task, Boolean>(task, forceLoadTask);
return mQueue.poll();
}
/** Removes a task from the load queue */
@@ -89,7 +72,6 @@ class TaskResourceLoadQueue {
Console.log(Constants.Log.App.TaskDataLoader, " [TaskResourceLoadQueue|removeTask]");
}
mQueue.remove(t);
mForceLoadSet.remove(t.key);
}
/** Clears all the tasks from the load queue */
@@ -98,7 +80,6 @@ class TaskResourceLoadQueue {
Console.log(Constants.Log.App.TaskDataLoader, " [TaskResourceLoadQueue|clearTasks]");
}
mQueue.clear();
mForceLoadSet.clear();
}
/** Returns whether the load queue is empty */
@@ -119,19 +100,20 @@ class TaskResourceLoader implements Runnable {
DrawableLruCache mApplicationIconCache;
BitmapLruCache mThumbnailCache;
Bitmap mDefaultThumbnail;
BitmapDrawable mDefaultApplicationIcon;
boolean mCancelled;
boolean mWaitingOnLoadQueue;
/** Constructor, creates a new loading thread that loads task resources in the background */
public TaskResourceLoader(TaskResourceLoadQueue loadQueue,
DrawableLruCache applicationIconCache,
BitmapLruCache thumbnailCache,
Bitmap defaultThumbnail) {
public TaskResourceLoader(TaskResourceLoadQueue loadQueue, DrawableLruCache applicationIconCache,
BitmapLruCache thumbnailCache, Bitmap defaultThumbnail,
BitmapDrawable defaultApplicationIcon) {
mLoadQueue = loadQueue;
mApplicationIconCache = applicationIconCache;
mThumbnailCache = thumbnailCache;
mDefaultThumbnail = defaultThumbnail;
mDefaultApplicationIcon = defaultApplicationIcon;
mMainThreadHandler = new Handler();
mLoadThread = new HandlerThread("Recents-TaskResourceLoader");
mLoadThread.setPriority(Thread.NORM_PRIORITY - 1);
@@ -200,59 +182,51 @@ class TaskResourceLoader implements Runnable {
SystemServicesProxy ssp = mSystemServicesProxy;
// Load the next item from the queue
Pair<Task, Boolean> nextTaskData = mLoadQueue.nextTask();
final Task t = nextTaskData.first;
final boolean forceLoadTask = nextTaskData.second;
final Task t = mLoadQueue.nextTask();
if (t != null) {
Drawable loadIcon = mApplicationIconCache.getCheckLastActiveTime(t.key);
Bitmap loadThumbnail = mThumbnailCache.getCheckLastActiveTime(t.key);
Drawable cachedIcon = mApplicationIconCache.getCheckLastActiveTime(t.key);
Bitmap cachedThumbnail = mThumbnailCache.getCheckLastActiveTime(t.key);
if (Console.Enabled) {
Console.log(Constants.Log.App.TaskDataLoader,
" [TaskResourceLoader|load]",
t + " icon: " + loadIcon + " thumbnail: " + loadThumbnail +
" forceLoad: " + forceLoadTask);
t + " icon: " + cachedIcon + " thumbnail: " + cachedThumbnail);
}
// Load the application icon
if (loadIcon == null || forceLoadTask) {
// Load the application icon if it is stale or we haven't cached one yet
if (cachedIcon == null) {
Drawable icon = null;
ActivityInfo info = ssp.getActivityInfo(t.key.baseIntent.getComponent(),
t.userId);
Drawable icon = ssp.getActivityIcon(info, t.userId);
if (!mCancelled) {
if (icon != null) {
if (Console.Enabled) {
Console.log(Constants.Log.App.TaskDataLoader,
" [TaskResourceLoader|loadIcon]", icon);
}
loadIcon = icon;
mApplicationIconCache.put(t.key, icon);
if (info != null) {
icon = ssp.getActivityIcon(info, t.userId);
if (Console.Enabled) {
Console.log(Constants.Log.App.TaskDataLoader,
" [TaskResourceLoader|loadedIcon]", icon);
}
}
// If we can't load the icon, then set the default application icon into the
// cache. This will remain until the task's last active time is updated.
cachedIcon = icon != null ? icon : mDefaultApplicationIcon;
mApplicationIconCache.put(t.key, cachedIcon);
}
// Load the thumbnail
if (loadThumbnail == null || forceLoadTask) {
// Load the thumbnail if it is stale or we haven't cached one yet
if (cachedThumbnail == null) {
Bitmap thumbnail = ssp.getTaskThumbnail(t.key.id);
if (!mCancelled) {
if (thumbnail != null) {
if (Console.Enabled) {
Console.log(Constants.Log.App.TaskDataLoader,
" [TaskResourceLoader|loadThumbnail]", thumbnail);
}
thumbnail.setHasAlpha(false);
loadThumbnail = thumbnail;
} else {
loadThumbnail = mDefaultThumbnail;
Console.logError(mContext,
"Failed to load task top thumbnail for: " +
t.key.baseIntent.getComponent().getPackageName());
if (thumbnail != null) {
thumbnail.setHasAlpha(false);
if (Console.Enabled) {
Console.log(Constants.Log.App.TaskDataLoader,
" [TaskResourceLoader|loadedThumbnail]", thumbnail);
}
// We put the default thumbnail in the cache anyways
mThumbnailCache.put(t.key, loadThumbnail);
}
// Even if we can't load the icon, we set the default thumbnail into the
// cache. This will remain until the task's last active time is updated.
cachedThumbnail = thumbnail != null ? thumbnail : mDefaultThumbnail;
mThumbnailCache.put(t.key, cachedThumbnail);
}
if (!mCancelled) {
// Notify that the task data has changed
final Drawable newIcon = loadIcon;
final Bitmap newThumbnail = loadThumbnail;
final Drawable newIcon = cachedIcon;
final Bitmap newThumbnail = cachedThumbnail;
mMainThreadHandler.post(new Runnable() {
@Override
public void run() {
@@ -306,11 +280,11 @@ public class RecentsTaskLoader {
/** Private Constructor */
private RecentsTaskLoader(Context context) {
// Calculate the cache sizes, we just use a reasonable number here similar to those
// suggested in the Android docs, 1/8th for the thumbnail cache and 1/32 of the max memory
// suggested in the Android docs, 1/6th for the thumbnail cache and 1/30 of the max memory
// for icons.
int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
mMaxThumbnailCacheSize = maxMemory / 8;
mMaxIconCacheSize = mMaxThumbnailCacheSize / 4;
int maxMemory = (int) Runtime.getRuntime().maxMemory();
mMaxThumbnailCacheSize = maxMemory / 6;
mMaxIconCacheSize = mMaxThumbnailCacheSize / 5;
int iconCacheSize = Constants.DebugFlags.App.DisableBackgroundCache ? 1 :
mMaxIconCacheSize;
int thumbnailCacheSize = Constants.DebugFlags.App.DisableBackgroundCache ? 1 :
@@ -340,7 +314,7 @@ public class RecentsTaskLoader {
mApplicationIconCache = new DrawableLruCache(iconCacheSize);
mThumbnailCache = new BitmapLruCache(thumbnailCacheSize);
mLoader = new TaskResourceLoader(mLoadQueue, mApplicationIconCache, mThumbnailCache,
mDefaultThumbnail);
mDefaultThumbnail, mDefaultApplicationIcon);
if (Console.Enabled) {
Console.log(Constants.Log.App.TaskDataLoader,
@@ -394,7 +368,7 @@ public class RecentsTaskLoader {
}
RecentsConfiguration config = RecentsConfiguration.getInstance();
Resources res = context.getResources();
ArrayList<Task> tasksToForceLoad = new ArrayList<Task>();
LinkedHashSet<Task> tasksToLoad = new LinkedHashSet<Task>();
TaskStack stack = new TaskStack();
SpaceNode root = new SpaceNode();
root.setStack(stack);
@@ -446,15 +420,16 @@ public class RecentsTaskLoader {
if (isForemostTask) {
// We force loading the application icon for the foremost task
task.applicationIcon = ssp.getActivityIcon(info, task.userId);
if (task.applicationIcon != null) {
mApplicationIconCache.put(task.key, task.applicationIcon);
} else {
if (task.applicationIcon == null) {
task.applicationIcon = mDefaultApplicationIcon;
}
// Even if we can't load the icon we set the default application icon into
// the cache. This will remain until the task's last active time is updated.
mApplicationIconCache.put(task.key, task.applicationIcon);
} else {
// Either the task has updated, or we haven't cached any information for the
// task, so reload it
tasksToForceLoad.add(task);
// Either the task has changed since the last active time, or it was not
// previously cached, so try and load the task anew.
tasksToLoad.add(task);
}
}
@@ -473,11 +448,13 @@ public class RecentsTaskLoader {
} else {
task.thumbnail = mDefaultThumbnail;
}
// Even if we can't load the thumbnail we set the default thumbnail into
// the cache. This will remain until the task's last active time is updated.
mThumbnailCache.put(task.key, task.thumbnail);
} else {
// Either the task has updated, or we haven't cached any information for the
// task, so reload it
tasksToForceLoad.add(task);
// Either the task has changed since the last active time, or it was not
// previously cached, so try and load the task anew.
tasksToLoad.add(task);
}
}
}
@@ -496,14 +473,14 @@ public class RecentsTaskLoader {
}
// Simulate the groupings that we describe
stack.createSimulatedAffiliatedGroupings();
stack.createAffiliatedGroupings();
// Start the task loader
mLoader.start(context);
// Add all the tasks that we are force/re-loading
for (Task t : tasksToForceLoad) {
mLoadQueue.addTask(t, true);
// Add all the tasks that we are reloading
for (Task t : tasksToLoad) {
mLoadQueue.addTask(t);
}
// Update the package monitor with the list of packages to listen for
@@ -526,7 +503,7 @@ public class RecentsTaskLoader {
stack.addTask(new Task(t.persistentId, true, t.baseIntent, t.affiliatedTaskId, null,
null, 0, 0, t.firstActiveTime, t.lastActiveTime, (i == (taskCount - 1))));
}
stack.createSimulatedAffiliatedGroupings();
stack.createAffiliatedGroupings();
return stack;
}
@@ -551,7 +528,7 @@ public class RecentsTaskLoader {
requiresLoad = true;
}
if (requiresLoad) {
mLoadQueue.addTask(t, false);
mLoadQueue.addTask(t);
}
t.notifyTaskDataLoaded(thumbnail, applicationIcon);
}

View File

@@ -18,6 +18,7 @@ package com.android.systemui.recents.model;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import com.android.systemui.recents.misc.Utilities;
@@ -84,7 +85,7 @@ public class Task {
public Drawable activityIcon;
public String activityLabel;
public int colorPrimary;
public int colorPrimaryGreyscale;
public boolean useLightOnPrimaryColor;
public Bitmap thumbnail;
public boolean isActive;
public boolean canLockToTask;
@@ -104,7 +105,8 @@ public class Task {
this.activityLabel = activityTitle;
this.activityIcon = activityIcon;
this.colorPrimary = colorPrimary;
this.colorPrimaryGreyscale = Utilities.colorToGreyscale(colorPrimary);
this.useLightOnPrimaryColor = Utilities.computeContrastBetweenColors(colorPrimary,
Color.WHITE) > 3f;
this.isActive = isActive;
this.canLockToTask = canLockToTask;
this.userId = userId;

View File

@@ -320,7 +320,7 @@ public class TaskStack {
/**
* Temporary: This method will simulate affiliation groups by
*/
public void createSimulatedAffiliatedGroupings() {
public void createAffiliatedGroupings() {
if (Constants.DebugFlags.App.EnableSimulatedTaskGroups) {
HashMap<Task.TaskKey, Task> taskMap = new HashMap<Task.TaskKey, Task>();
// Sort all tasks by increasing firstActiveTime of the task

View File

@@ -191,10 +191,6 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
/** Requests all task stacks to start their enter-recents animation */
public void startEnterRecentsAnimation(ViewAnimation.TaskViewEnterContext ctx) {
// Handle the case when there are no views by incrementing and decrementing after all
// animations are started.
ctx.postAnimationTrigger.increment();
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
@@ -203,18 +199,10 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
stackView.startEnterRecentsAnimation(ctx);
}
}
// Handle the case when there are no views by incrementing and decrementing after all
// animations are started.
ctx.postAnimationTrigger.decrement();
}
/** Requests all task stacks to start their exit-recents animation */
public void startExitToHomeAnimation(ViewAnimation.TaskViewExitContext ctx) {
// Handle the case when there are no views by incrementing and decrementing after all
// animations are started.
ctx.postAnimationTrigger.increment();
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
@@ -224,10 +212,6 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
}
}
// Handle the case when there are no views by incrementing and decrementing after all
// animations are started.
ctx.postAnimationTrigger.decrement();
// Notify of the exit animation
mCb.onExitToHomeAnimationTriggered();
}

View File

@@ -162,11 +162,10 @@ class TaskBarView extends FrameLayout {
}
// Try and apply the system ui tint
setBackgroundColor(t.colorPrimary);
mActivityDescription.setTextColor(Utilities.getIdealColorForBackgroundColorGreyscale(
t.colorPrimaryGreyscale, mConfig.taskBarViewLightTextColor,
mConfig.taskBarViewDarkTextColor));
mDismissButton.setImageDrawable(Utilities.getIdealResourceForBackgroundColorGreyscale(
t.colorPrimaryGreyscale, mLightDismissDrawable, mDarkDismissDrawable));
mActivityDescription.setTextColor(t.useLightOnPrimaryColor ?
mConfig.taskBarViewLightTextColor : mConfig.taskBarViewDarkTextColor);
mDismissButton.setImageDrawable(t.useLightOnPrimaryColor ?
mLightDismissDrawable : mDarkDismissDrawable);
}
/** Unbinds the bar view from the task */

View File

@@ -302,7 +302,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
int[] visibleRange = mTmpVisibleRange;
updateStackTransforms(mCurrentTaskTransforms, tasks, stackScroll, visibleRange, false);
TaskViewTransform tmpTransform = new TaskViewTransform();
TaskStack.GroupTaskIndex gti = new TaskStack.GroupTaskIndex();
// Return all the invisible children to the pool
HashMap<Task, TaskView> taskChildViewMap = getTaskChildViewMap();
@@ -355,6 +354,47 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
}
/** Updates the clip for each of the task views. */
void clipTaskViews() {
// Update the clip on each task child
if (Constants.DebugFlags.App.EnableTaskStackClipping) {
int childCount = getChildCount();
for (int i = 0; i < childCount - 1; i++) {
TaskView tv = (TaskView) getChildAt(i);
TaskView nextTv = null;
TaskView tmpTv = null;
int clipBottom = 0;
if (tv.shouldClipViewInStack()) {
// Find the next view to clip against
int nextIndex = i;
while (nextIndex < getChildCount()) {
tmpTv = (TaskView) getChildAt(++nextIndex);
if (tmpTv != null && tmpTv.shouldClipViewInStack()) {
nextTv = tmpTv;
break;
}
}
// Clip against the next view, this is just an approximation since we are
// stacked and we can make assumptions about the visibility of the this
// task relative to the ones in front of it.
if (nextTv != null) {
// XXX: Can hash the visible rects for this run
tv.getHitRect(mTmpRect);
nextTv.getHitRect(mTmpRect2);
clipBottom = (mTmpRect.bottom - mTmpRect2.top);
}
}
tv.setClipFromBottom(clipBottom);
}
}
if (getChildCount() > 0) {
// The front most task should never be clipped
TaskView tv = (TaskView) getChildAt(getChildCount() - 1);
tv.setClipFromBottom(0);
}
}
/** Sets the current stack scroll */
public void setStackScroll(int value) {
mStackScroll = value;
@@ -641,50 +681,10 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
Console.AnsiPurple);
}
synchronizeStackViewsWithModel();
clipTaskViews();
super.dispatchDraw(canvas);
}
@Override
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
if (Constants.DebugFlags.App.EnableTaskStackClipping) {
TaskView tv = (TaskView) child;
TaskView nextTv = null;
TaskView tmpTv = null;
if (tv.shouldClipViewInStack()) {
int curIndex = indexOfChild(tv);
// Find the next view to clip against
while (nextTv == null && curIndex < getChildCount()) {
tmpTv = (TaskView) getChildAt(++curIndex);
if (tmpTv != null && tmpTv.shouldClipViewInStack()) {
nextTv = tmpTv;
}
}
// Clip against the next view (if we aren't animating its alpha)
if (nextTv != null) {
Rect curRect = tv.getClippingRect(mTmpRect);
Rect nextRect = nextTv.getClippingRect(mTmpRect2);
// The hit rects are relative to the task view, which needs to be offset by
// the system bar height
curRect.offset(0, mConfig.systemInsets.top);
nextRect.offset(0, mConfig.systemInsets.top);
// Compute the clip region
Region clipRegion = new Region();
clipRegion.op(curRect, Region.Op.UNION);
clipRegion.op(nextRect, Region.Op.DIFFERENCE);
// Clip the canvas
int saveCount = canvas.save(Canvas.CLIP_SAVE_FLAG);
canvas.clipRegion(clipRegion);
boolean invalidate = super.drawChild(canvas, child, drawingTime);
canvas.restoreToCount(saveCount);
return invalidate;
}
}
}
return super.drawChild(canvas, child, drawingTime);
}
/** Computes the stack and task rects */
public void computeRects(int width, int height, int insetLeft, int insetBottom) {
// Compute the rects in the stack algorithm
@@ -1155,6 +1155,11 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
mStack.removeTask(task);
}
@Override
public void onTaskViewClipStateChanged(TaskView tv) {
invalidate(mStackAlgorithm.mStackRect);
}
/**** RecentsPackageMonitor.PackageCallbacks Implementation ****/
@Override

View File

@@ -135,9 +135,9 @@ public class TaskStackViewLayoutAlgorithm {
// Set the y translation
if (boundedT < 0f) {
transformOut.translationY = (int) ((Math.max(-numPeekCards, boundedT) /
numPeekCards) * peekHeight - scaleYOffset - scaleBarYOffset);
numPeekCards) * peekHeight - scaleYOffset);
} else {
transformOut.translationY = (int) (boundedT * overlapHeight - scaleYOffset - scaleBarYOffset);
transformOut.translationY = (int) (boundedT * overlapHeight - scaleYOffset);
}
// Set the z translation

View File

@@ -46,8 +46,9 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
interface TaskViewCallbacks {
public void onTaskViewAppIconClicked(TaskView tv);
public void onTaskViewAppInfoClicked(TaskView tv);
public void onTaskViewClicked(TaskView tv, Task t, boolean lockToTask);
public void onTaskViewClicked(TaskView tv, Task task, boolean lockToTask);
public void onTaskViewDismissed(TaskView tv);
public void onTaskViewClipStateChanged(TaskView tv);
}
RecentsConfiguration mConfig;
@@ -65,7 +66,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
boolean mIsFocused;
boolean mIsStub;
boolean mClipViewInStack;
Rect mTmpRect = new Rect();
int mClipFromBottom;
Paint mLayerPaint = new Paint();
TaskThumbnailView mThumbnailView;
@@ -118,7 +119,9 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
setOutlineProvider(new ViewOutlineProvider() {
@Override
public boolean getOutline(View view, Outline outline) {
int height = getHeight() - mMaxFooterHeight + mFooterHeight;
// The current height is measured with the footer, so account for the footer height
// and the current clip (in the stack)
int height = getMeasuredHeight() - mClipFromBottom - mMaxFooterHeight + mFooterHeight;
outline.setRoundRect(0, 0, getWidth(), height,
mConfig.taskViewRoundedCornerRadiusPx);
return true;
@@ -483,15 +486,6 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
mBarView.setNoUserInteractionState();
}
/** Returns the rect we want to clip (it may not be the full rect) */
Rect getClippingRect(Rect outRect) {
getHitRect(outRect);
// XXX: We should get the hit rect of the thumbnail view and intersect, but this is faster
outRect.right = outRect.left + mThumbnailView.getRight();
outRect.bottom = outRect.top + mThumbnailView.getBottom();
return outRect;
}
/** Enable the hw layers on this task view */
void enableHwLayers() {
mThumbnailView.setLayerType(View.LAYER_TYPE_HARDWARE, mLayerPaint);
@@ -506,7 +500,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
mLockToAppButtonView.setLayerType(View.LAYER_TYPE_NONE, mLayerPaint);
}
/** Sets the stubbed state of this task view. */
/** Sets the stubbed state of this task view.
void setStubState(boolean isStub) {
if (!mIsStub && isStub) {
// This is now a stub task view, so clip to the bar height, hide the thumbnail
@@ -519,7 +513,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
mThumbnailView.setVisibility(View.VISIBLE);
}
mIsStub = isStub;
}
} */
/**
* Returns whether this view should be clipped, or any views below should clip against this
@@ -533,19 +527,26 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
void setClipViewInStack(boolean clip) {
if (clip != mClipViewInStack) {
mClipViewInStack = clip;
if (getParent() instanceof View) {
getHitRect(mTmpRect);
((View) getParent()).invalidate(mTmpRect);
}
mCb.onTaskViewClipStateChanged(this);
}
}
void setClipFromBottom(int clipFromBottom) {
clipFromBottom = Math.max(0, Math.min(getMeasuredHeight(), clipFromBottom));
if (mClipFromBottom != clipFromBottom) {
mClipFromBottom = clipFromBottom;
invalidateOutline();
}
}
/** Sets the footer height. */
public void setFooterHeight(int height) {
mFooterHeight = height;
invalidateOutline();
invalidate(0, getMeasuredHeight() - mMaxFooterHeight, getMeasuredWidth(),
getMeasuredHeight());
public void setFooterHeight(int footerHeight) {
if (footerHeight != mFooterHeight) {
mFooterHeight = footerHeight;
invalidateOutline();
invalidate(0, getMeasuredHeight() - mMaxFooterHeight, getMeasuredWidth(),
getMeasuredHeight());
}
}
/** Gets the footer height. */
@@ -677,6 +678,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
mTask = t;
mTask.setCallbacks(this);
if (getMeasuredWidth() == 0) {
// If we haven't yet measured, we should just set the footer height with any animation
animateFooterVisibility(t.canLockToTask, 0, 0);
} else {
animateFooterVisibility(t.canLockToTask, mConfig.taskViewLockToAppLongAnimDuration, 0);