diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java index 8a80b76edc14a..e7ac2e1ec5681 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java +++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java @@ -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 diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java index 56de0be56042a..1e581c1daf4a9 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java @@ -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 diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/ReferenceCountedTrigger.java b/packages/SystemUI/src/com/android/systemui/recents/misc/ReferenceCountedTrigger.java index 31825afa545ff..4c0ff481a2897 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/misc/ReferenceCountedTrigger.java +++ b/packages/SystemUI/src/com/android/systemui/recents/misc/ReferenceCountedTrigger.java @@ -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 */ diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java index bda195b548c00..607e155d92f6f 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java +++ b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java @@ -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. */ diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/BitmapLruCache.java b/packages/SystemUI/src/com/android/systemui/recents/model/BitmapLruCache.java index 1344729001c28..757c07fbb28db 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/BitmapLruCache.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/BitmapLruCache.java @@ -29,6 +29,6 @@ class BitmapLruCache extends KeyStoreLruCache { @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(); } } \ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/DrawableLruCache.java b/packages/SystemUI/src/com/android/systemui/recents/model/DrawableLruCache.java index 61d19da86d261..5b5035865d36f 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/DrawableLruCache.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/DrawableLruCache.java @@ -31,6 +31,6 @@ class DrawableLruCache extends KeyStoreLruCache { // 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; } } \ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/KeyStoreLruCache.java b/packages/SystemUI/src/com/android/systemui/recents/model/KeyStoreLruCache.java index 3ccca9a2e9447..5f4fabeaa918b 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/KeyStoreLruCache.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/KeyStoreLruCache.java @@ -73,11 +73,6 @@ public class KeyStoreLruCache { 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); diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsPackageMonitor.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsPackageMonitor.java index 2d50659858f9f..2f1c1c43d200d 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsPackageMonitor.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsPackageMonitor.java @@ -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(); } 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 854ea1c8446bc..cbb8892dea94e 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java @@ -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 mQueue = new ConcurrentLinkedQueue(); - ConcurrentHashMap mForceLoadSet = - new ConcurrentHashMap(); - - 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 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, 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 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 tasksToForceLoad = new ArrayList(); + LinkedHashSet tasksToLoad = new LinkedHashSet(); 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); } diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java index 88e9f40ea8130..1670735873048 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java @@ -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; diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java index 7dd15a6c057da..e3bcff0749879 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java @@ -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 taskMap = new HashMap(); // Sort all tasks by increasing firstActiveTime of the task 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 99b012e0c9bcb..73bbf86165c69 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java @@ -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(); } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java index db849626a07a3..deb9df3ed67eb 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java @@ -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 */ 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 599c59072862f..adc808a733fac 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java @@ -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 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 diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java index 908e0636245d0..9c48896ca9d65 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java @@ -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 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 5524e155b283c..ab148632698c5 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java @@ -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);