diff options
author | Winson Chung <winsonc@google.com> | 2014-08-26 12:25:34 -0700 |
---|---|---|
committer | Winson Chung <winsonc@google.com> | 2014-08-27 19:07:36 +0000 |
commit | ebfc6981828b0699eef85c58b23a61f2cac41af3 (patch) | |
tree | 6db84ea62c9ee802b3e30601530bf685f140f1ac /packages/SystemUI/src/com | |
parent | 2227cac5af26c9ed103d7d8e1c010c3723c1b5b2 (diff) | |
download | frameworks_base-ebfc6981828b0699eef85c58b23a61f2cac41af3.zip frameworks_base-ebfc6981828b0699eef85c58b23a61f2cac41af3.tar.gz frameworks_base-ebfc6981828b0699eef85c58b23a61f2cac41af3.tar.bz2 |
Additional changes to improve performance when loading Recents. (Bug 16987565)
- Ensuring that we consistently load activity icon, title and color for both full and shallow stacks
- Adding activity info caches when loading the stacks
- Should not be scaling pin icon when launching from pin
- Tweaking snap-back, over scroll, and shadows
Change-Id: I556b93562bb2c69e4c25ce787a7a34532ab706ca
Diffstat (limited to 'packages/SystemUI/src/com')
12 files changed, 189 insertions, 161 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java index 0b36bdb..d328660 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java +++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java @@ -22,7 +22,6 @@ import android.content.ActivityNotFoundException; import android.content.ComponentName; import android.content.Context; import android.content.Intent; -import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Bitmap; @@ -36,7 +35,6 @@ import com.android.systemui.R; import com.android.systemui.RecentsComponent; import com.android.systemui.recents.misc.Console; import com.android.systemui.recents.misc.SystemServicesProxy; -import com.android.systemui.recents.misc.Utilities; import com.android.systemui.recents.model.RecentsTaskLoader; import com.android.systemui.recents.model.Task; import com.android.systemui.recents.model.TaskGrouping; @@ -99,6 +97,7 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta long mLastToggleTime; public AlternateRecentsComponent(Context context) { + RecentsTaskLoader.initialize(context); Resources res = context.getResources(); mContext = context; mSystemServicesProxy = new SystemServicesProxy(context); @@ -176,8 +175,9 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta } void showRelativeAffiliatedTask(boolean showNextTask) { - TaskStack stack = RecentsTaskLoader.getShallowTaskStack(mSystemServicesProxy, - Integer.MAX_VALUE, mContext.getResources()); + RecentsTaskLoader loader = RecentsTaskLoader.getInstance(); + TaskStack stack = loader.getTaskStack(mSystemServicesProxy, mContext.getResources(), + -1, -1, false, null, null); // Return early if there are no tasks if (stack.getTaskCount() == 0) return; @@ -385,16 +385,8 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta toTask); if (toTransform != null && toTask.key != null) { Rect toTaskRect = toTransform.rect; - ActivityInfo info = mSystemServicesProxy.getActivityInfo( - toTask.key.baseIntent.getComponent(), toTask.key.userId); - if (toTask.activityIcon == null) { - toTask.activityIcon = mSystemServicesProxy.getActivityIcon(info, - toTask.key.userId); - } - if (toTask.activityLabel == null) { - toTask.activityLabel = mSystemServicesProxy.getActivityLabel(info); - } + // XXX: Reduce the memory usage the to the task bar height Bitmap thumbnail = Bitmap.createBitmap(toTaskRect.width(), toTaskRect.height(), Bitmap.Config.ARGB_8888); if (Constants.DebugFlags.App.EnableTransitionThumbnailDebugMode) { @@ -420,8 +412,9 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta TaskViewTransform getThumbnailTransitionTransform(int runningTaskId, boolean isTopTaskHome, Task runningTaskOut) { // Get the stack of tasks that we are animating into - TaskStack stack = RecentsTaskLoader.getShallowTaskStack(mSystemServicesProxy, -1, - mContext.getResources()); + RecentsTaskLoader loader = RecentsTaskLoader.getInstance(); + TaskStack stack = loader.getTaskStack(mSystemServicesProxy, mContext.getResources(), + runningTaskId, -1, false, null, null); if (stack.getTaskCount() == 0) { return null; } diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java index a5b845d..2f9715f 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java @@ -343,7 +343,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView super.onCreate(savedInstanceState); // Initialize the loader and the configuration - RecentsTaskLoader.initialize(this); mConfig = RecentsConfiguration.reinitialize(this, RecentsTaskLoader.getInstance().getSystemServicesProxy()); diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java index 9803687..5d8181c 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java @@ -67,9 +67,11 @@ public class RecentsConfiguration { public int searchBarSpaceHeightPx; /** Task stack */ + public int taskStackScrollDuration; public int taskStackMaxDim; public int taskStackTopPaddingPx; public float taskStackWidthPaddingPct; + public float taskStackOverscrollPct; /** Task view animation and styles */ public int taskViewEnterFromHomeDuration; @@ -195,9 +197,14 @@ public class RecentsConfiguration { searchBarAppWidgetId = settings.getInt(Constants.Values.App.Key_SearchAppWidgetId, -1); // Task stack + taskStackScrollDuration = + res.getInteger(R.integer.recents_animate_task_stack_scroll_duration); TypedValue widthPaddingPctValue = new TypedValue(); res.getValue(R.dimen.recents_stack_width_padding_percentage, widthPaddingPctValue, true); taskStackWidthPaddingPct = widthPaddingPctValue.getFloat(); + TypedValue stackOverscrollPctValue = new TypedValue(); + res.getValue(R.dimen.recents_stack_overscroll_percentage, stackOverscrollPctValue, true); + taskStackOverscrollPct = stackOverscrollPctValue.getFloat(); taskStackMaxDim = res.getInteger(R.integer.recents_max_task_stack_view_dim); taskStackTopPaddingPx = res.getDimensionPixelSize(R.dimen.recents_stack_top_padding); 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 31011ae..60e89bf 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsPackageMonitor.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsPackageMonitor.java @@ -16,7 +16,6 @@ package com.android.systemui.recents.model; -import android.app.ActivityManager; import android.content.ComponentName; import android.content.Context; import android.os.Looper; @@ -36,7 +35,7 @@ public class RecentsPackageMonitor extends PackageMonitor { } PackageCallbacks mCb; - List<ActivityManager.RecentTaskInfo> mTasks; + List<Task.TaskKey> mTasks; SystemServicesProxy mSystemServicesProxy; /** Registers the broadcast receivers with the specified callbacks. */ @@ -64,7 +63,7 @@ public class RecentsPackageMonitor extends PackageMonitor { } /** Sets the list of tasks to match against package broadcast changes. */ - void setTasks(List<ActivityManager.RecentTaskInfo> tasks) { + void setTasks(List<Task.TaskKey> tasks) { mTasks = tasks; } @@ -75,7 +74,7 @@ public class RecentsPackageMonitor extends PackageMonitor { // Identify all the tasks that should be removed as a result of the package being removed. // Using a set to ensure that we callback once per unique component. HashSet<ComponentName> componentsToRemove = new HashSet<ComponentName>(); - for (ActivityManager.RecentTaskInfo t : mTasks) { + for (Task.TaskKey t : mTasks) { ComponentName cn = t.baseIntent.getComponent(); if (cn.getPackageName().equals(packageName)) { componentsToRemove.add(cn); @@ -99,7 +98,7 @@ public class RecentsPackageMonitor extends PackageMonitor { // Using a set to ensure that we callback once per unique component. HashSet<ComponentName> componentsKnownToExist = new HashSet<ComponentName>(); HashSet<ComponentName> componentsToRemove = new HashSet<ComponentName>(); - for (ActivityManager.RecentTaskInfo t : mTasks) { + for (Task.TaskKey t : mTasks) { ComponentName cn = t.baseIntent.getComponent(); if (cn.getPackageName().equals(packageName)) { if (componentsKnownToExist.contains(cn)) { 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 b93c126..a93e244 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java @@ -35,11 +35,16 @@ import com.android.systemui.recents.misc.SystemServicesProxy; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; -import java.util.LinkedHashSet; +import java.util.HashMap; import java.util.List; import java.util.concurrent.ConcurrentLinkedQueue; +/** Handle to an ActivityInfo */ +class ActivityInfoHandle { + ActivityInfo info; +} + /** A bitmap load queue */ class TaskResourceLoadQueue { ConcurrentLinkedQueue<Task> mQueue = new ConcurrentLinkedQueue<Task>(); @@ -230,7 +235,6 @@ public class RecentsTaskLoader { static RecentsTaskLoader sInstance; SystemServicesProxy mSystemServicesProxy; - DrawableLruCache mTaskDescriptionIconCache; DrawableLruCache mApplicationIconCache; BitmapLruCache mThumbnailCache; StringLruCache mActivityLabelCache; @@ -274,7 +278,6 @@ public class RecentsTaskLoader { mSystemServicesProxy = new SystemServicesProxy(context); mPackageMonitor = new RecentsPackageMonitor(); mLoadQueue = new TaskResourceLoadQueue(); - mTaskDescriptionIconCache = new DrawableLruCache(iconCacheSize); mApplicationIconCache = new DrawableLruCache(iconCacheSize); mThumbnailCache = new BitmapLruCache(thumbnailCacheSize); mActivityLabelCache = new StringLruCache(100); @@ -301,103 +304,151 @@ public class RecentsTaskLoader { } /** Gets the list of recent tasks, ordered from back to front. */ - private static List<ActivityManager.RecentTaskInfo> getRecentTasks(SystemServicesProxy ssp, - int numTasks) { - // Set a default number of tasks to query if none is provided - if (numTasks < 0) { - RecentsConfiguration config = RecentsConfiguration.getInstance(); - numTasks = config.maxNumTasksToLoad; - } + private static List<ActivityManager.RecentTaskInfo> getRecentTasks(SystemServicesProxy ssp) { + RecentsConfiguration config = RecentsConfiguration.getInstance(); List<ActivityManager.RecentTaskInfo> tasks = - ssp.getRecentTasks(numTasks, UserHandle.CURRENT.getIdentifier()); + ssp.getRecentTasks(config.maxNumTasksToLoad, + UserHandle.CURRENT.getIdentifier()); Collections.reverse(tasks); return tasks; } + /** Returns the activity icon using as many cached values as we can. */ + public Drawable getAndUpdateActivityIcon(Task.TaskKey taskKey, + ActivityManager.TaskDescription td, SystemServicesProxy ssp, + Resources res, ActivityInfoHandle infoHandle, boolean preloadTask) { + // Return the cached activity icon if it exists + Drawable icon = mApplicationIconCache.getAndInvalidateIfModified(taskKey); + if (icon != null) { + return icon; + } + // Return the task description icon if it exists + if (td != null && td.getIcon() != null) { + icon = ssp.getBadgedIcon(new BitmapDrawable(res, td.getIcon()), taskKey.userId); + mApplicationIconCache.put(taskKey, icon); + return icon; + } + // If we are preloading this task, continue to load the activity icon + if (preloadTask) { + // All short paths failed, load the icon from the activity info and cache it + if (infoHandle.info == null) { + infoHandle.info = ssp.getActivityInfo(taskKey.baseIntent.getComponent(), + taskKey.userId); + } + icon = ssp.getActivityIcon(infoHandle.info, taskKey.userId); + mApplicationIconCache.put(taskKey, icon); + return icon; + } + // If we are not preloading, return the default icon to show + return null; + } + + /** Returns the activity label using as many cached values as we can. */ + public String getAndUpdateActivityLabel(Task.TaskKey taskKey, + ActivityManager.TaskDescription td, SystemServicesProxy ssp, + ActivityInfoHandle infoHandle) { + // Return the task description label if it exists + if (td != null && td.getLabel() != null) { + return td.getLabel(); + } + // Return the cached activity label if it exists + String label = mActivityLabelCache.getAndInvalidateIfModified(taskKey); + if (label != null) { + return label; + } + // All short paths failed, load the label from the activity info and cache it + if (infoHandle.info == null) { + infoHandle.info = ssp.getActivityInfo(taskKey.baseIntent.getComponent(), + taskKey.userId); + } + label = ssp.getActivityLabel(infoHandle.info); + mActivityLabelCache.put(taskKey, label); + return label; + } + + /** Returns the activity's primary color. */ + public int getActivityPrimaryColor(ActivityManager.TaskDescription td, + RecentsConfiguration config) { + if (td != null && td.getPrimaryColor() != 0) { + return td.getPrimaryColor(); + } + return config.taskBarViewDefaultBackgroundColor; + } + /** Reload the set of recent tasks */ public SpaceNode reload(Context context, int preloadCount) { - RecentsConfiguration config = RecentsConfiguration.getInstance(); - Resources res = context.getResources(); - LinkedHashSet<Task> tasksToLoad = new LinkedHashSet<Task>(); - ArrayList<Task> tasksToAdd = new ArrayList<Task>(); - TaskStack stack = new TaskStack(); + ArrayList<Task.TaskKey> taskKeys = new ArrayList<Task.TaskKey>(); + ArrayList<Task> tasksToLoad = new ArrayList<Task>(); + TaskStack stack = getTaskStack(mSystemServicesProxy, context.getResources(), + -1, preloadCount, true, taskKeys, tasksToLoad); SpaceNode root = new SpaceNode(); root.setStack(stack); - // Get the recent tasks - SystemServicesProxy ssp = mSystemServicesProxy; - List<ActivityManager.RecentTaskInfo> tasks = getRecentTasks(ssp, -1); + // Start the task loader and add all the tasks we need to load + mLoader.start(context); + mLoadQueue.addTasks(tasksToLoad); + + // Update the package monitor with the list of packages to listen for + mPackageMonitor.setTasks(taskKeys); + + return root; + } + + /** Creates a lightweight stack of the current recent tasks, without thumbnails and icons. */ + public TaskStack getTaskStack(SystemServicesProxy ssp, Resources res, + int preloadTaskId, int preloadTaskCount, + boolean loadTaskThumbnails, List<Task.TaskKey> taskKeysOut, + List<Task> tasksToLoadOut) { + RecentsConfiguration config = RecentsConfiguration.getInstance(); + List<ActivityManager.RecentTaskInfo> tasks = getRecentTasks(ssp); + HashMap<ComponentName, ActivityInfoHandle> activityInfoCache = + new HashMap<ComponentName, ActivityInfoHandle>(); + ArrayList<Task> tasksToAdd = new ArrayList<Task>(); + TaskStack stack = new TaskStack(); - // From back to front, add each task to the task stack int taskCount = tasks.size(); for (int i = 0; i < taskCount; i++) { ActivityManager.RecentTaskInfo t = tasks.get(i); + + // Get an existing activity info handle if possible + ComponentName cn = t.baseIntent.getComponent(); + ActivityInfoHandle infoHandle = new ActivityInfoHandle(); + boolean hasCachedActivityInfo = false; + if (activityInfoCache.containsKey(cn)) { + infoHandle = activityInfoCache.get(cn); + hasCachedActivityInfo = true; + } + + // Compose the task key Task.TaskKey taskKey = new Task.TaskKey(t.persistentId, t.baseIntent, t.userId, t.firstActiveTime, t.lastActiveTime); - ComponentName cn = t.baseIntent.getComponent(); - ActivityInfo info = null; - - ActivityManager.TaskDescription av = t.taskDescription; - String activityLabel = null; - Drawable activityIcon = mDefaultApplicationIcon; - int activityColor = config.taskBarViewDefaultBackgroundColor; - boolean loadedActivityIcon = false; - if (av != null) { - activityLabel = av.getLabel(); - activityIcon = mTaskDescriptionIconCache.getAndInvalidateIfModified(taskKey); - if (activityIcon == null) { - activityIcon = (av.getIcon() != null) ? - ssp.getBadgedIcon(new BitmapDrawable(res, av.getIcon()), t.userId) : null; - if (activityIcon != null) { - mTaskDescriptionIconCache.put(taskKey, activityIcon); - } - } - if (av.getPrimaryColor() != 0) { - activityColor = av.getPrimaryColor(); - } - loadedActivityIcon = (activityIcon != null); + + // Determine whether to preload this task + boolean preloadTask = false; + if (preloadTaskId > 0) { + preloadTask = (t.id == preloadTaskId); + } else if (preloadTaskCount > 0) { + preloadTask = (i >= (taskCount - preloadTaskCount)); } - // If there is no activity label, then try and read it from the label cache before - // loading it from the system - if (activityLabel == null) { - activityLabel = mActivityLabelCache.getAndInvalidateIfModified(taskKey); - if (activityLabel == null) { - if (info == null) { - info = ssp.getActivityInfo(cn, t.userId); - } - activityLabel = ssp.getActivityLabel(info); - mActivityLabelCache.put(taskKey, activityLabel); - } + + // Load the label, icon, and color + String activityLabel = getAndUpdateActivityLabel(taskKey, t.taskDescription, + ssp, infoHandle); + Drawable activityIcon = getAndUpdateActivityIcon(taskKey, t.taskDescription, + ssp, res, infoHandle, preloadTask); + int activityColor = getActivityPrimaryColor(t.taskDescription, config); + + // Update the activity info cache + if (!hasCachedActivityInfo && infoHandle.info != null) { + activityInfoCache.put(cn, infoHandle); } - // Create a new task + // Add the task to the stack Task task = new Task(taskKey, (t.id > -1), t.affiliatedTaskId, t.affiliatedTaskColor, activityLabel, activityIcon, activityColor, (i == (taskCount - 1)), config.lockToAppEnabled); - // Preload the specified number of apps - if (i >= (taskCount - preloadCount)) { - // Load the icon from the cache if possible (only if we don't have an activity icon) - if (!loadedActivityIcon) { - task.applicationIcon = - mApplicationIconCache.getAndInvalidateIfModified(taskKey); - if (task.applicationIcon == null) { - // Load the icon from the system - if (info == null) { - info = ssp.getActivityInfo(cn, t.userId); - } - task.applicationIcon = ssp.getActivityIcon(info, taskKey.userId); - if (task.applicationIcon != null) { - mApplicationIconCache.put(taskKey, task.applicationIcon); - } - } - if (task.applicationIcon == null) { - // 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); - } - } - + if (preloadTask && loadTaskThumbnails) { // Load the thumbnail from the cache if possible task.thumbnail = mThumbnailCache.getAndInvalidateIfModified(taskKey); if (task.thumbnail == null) { @@ -408,54 +459,20 @@ public class RecentsTaskLoader { mThumbnailCache.put(taskKey, task.thumbnail); } } - if (task.thumbnail == null) { + if (task.thumbnail == null && tasksToLoadOut != null) { // 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); + tasksToLoadOut.add(task); } } + // Add to the list of task keys + if (taskKeysOut != null) { + taskKeysOut.add(taskKey); + } // Add the task to the stack tasksToAdd.add(task); } - - // Simulate the groupings that we describe - stack.setTasks(tasksToAdd); - stack.createAffiliatedGroupings(config); - - // Start the task loader and add all the tasks we need to load - mLoader.start(context); - mLoadQueue.addTasks(tasksToLoad); - - // Update the package monitor with the list of packages to listen for - mPackageMonitor.setTasks(tasks); - - return root; - } - - /** Creates a lightweight stack of the current recent tasks, without thumbnails and icons. */ - public static TaskStack getShallowTaskStack(SystemServicesProxy ssp, int numTasks, - Resources resources) { - RecentsConfiguration config = RecentsConfiguration.getInstance(); - List<ActivityManager.RecentTaskInfo> tasks = getRecentTasks(ssp, numTasks); - ArrayList<Task> tasksToAdd = new ArrayList<Task>(); - TaskStack stack = new TaskStack(); - - int taskCount = tasks.size(); - for (int i = 0; i < taskCount; i++) { - ActivityManager.RecentTaskInfo t = tasks.get(i); - ActivityManager.TaskDescription av = t.taskDescription; - - BitmapDrawable icon = null; - if (av.getIcon() != null) { - icon = new BitmapDrawable(resources, av.getIcon()); - } - Task.TaskKey taskKey = new Task.TaskKey(t.persistentId, t.baseIntent, t.userId, - t.firstActiveTime, t.lastActiveTime); - tasksToAdd.add(new Task(taskKey, true, t.affiliatedTaskId, t.affiliatedTaskColor, - av.getLabel(), icon, av.getPrimaryColor(), (i == (taskCount - 1)), - config.lockToAppEnabled)); - } stack.setTasks(tasksToAdd); stack.createAffiliatedGroupings(config); return stack; @@ -525,21 +542,18 @@ public class RecentsTaskLoader { // We are leaving recents, so trim the data a bit mThumbnailCache.trimToSize(mMaxThumbnailCacheSize / 2); mApplicationIconCache.trimToSize(mMaxIconCacheSize / 2); - mTaskDescriptionIconCache.trimToSize(mMaxIconCacheSize / 2); break; case ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW: case ComponentCallbacks2.TRIM_MEMORY_MODERATE: // We are going to be low on memory mThumbnailCache.trimToSize(mMaxThumbnailCacheSize / 4); mApplicationIconCache.trimToSize(mMaxIconCacheSize / 4); - mTaskDescriptionIconCache.trimToSize(mMaxIconCacheSize / 4); break; case ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL: case ComponentCallbacks2.TRIM_MEMORY_COMPLETE: // We are low on memory, so release everything mThumbnailCache.evictAll(); mApplicationIconCache.evictAll(); - mTaskDescriptionIconCache.evictAll(); // The cache is small, only clear the label cache when we are critical mActivityLabelCache.evictAll(); break; diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java b/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java index 34f73c6..d6889d0 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java @@ -33,6 +33,8 @@ public class AnimateableViewBounds extends ViewOutlineProvider { Rect mClipRect = new Rect(); Rect mOutlineClipRect = new Rect(); int mCornerRadius; + float mAlpha = 1f; + final float mMinAlpha = 0.25f; ObjectAnimator mClipTopAnimator; ObjectAnimator mClipRightAnimator; @@ -51,6 +53,7 @@ public class AnimateableViewBounds extends ViewOutlineProvider { @Override public void getOutline(View view, Outline outline) { + outline.setAlpha(mMinAlpha + mAlpha / (1f - mMinAlpha)); outline.setRoundRect(Math.max(mClipRect.left, mOutlineClipRect.left), Math.max(mClipRect.top, mOutlineClipRect.top), mSourceView.getMeasuredWidth() - Math.max(mClipRect.right, mOutlineClipRect.right), @@ -58,6 +61,14 @@ public class AnimateableViewBounds extends ViewOutlineProvider { mCornerRadius); } + /** Sets the view outline alpha. */ + void setAlpha(float alpha) { + if (Float.compare(alpha, mAlpha) != 0) { + mAlpha = alpha; + mSourceView.invalidateOutline(); + } + } + /** Animates the top clip. */ void animateClipTop(int top, int duration, ValueAnimator.AnimatorUpdateListener updateListener) { if (mClipTopAnimator != null) { 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 47fda5b..1ac3bc3 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java @@ -477,10 +477,10 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV if (!task.group.isFrontMostTask(task)) { // For affiliated tasks that are behind other tasks, we must animate the front cards // out of view before starting the task transition - stackView.startLaunchTaskAnimation(tv, launchRunnable); + stackView.startLaunchTaskAnimation(tv, launchRunnable, lockToTask); } else { // Otherwise, we can start the task transition immediately - stackView.startLaunchTaskAnimation(tv, null); + stackView.startLaunchTaskAnimation(tv, null, lockToTask); postDelayed(launchRunnable, 17); } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/SwipeHelper.java index e0298ab..fa44551 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/SwipeHelper.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/SwipeHelper.java @@ -28,6 +28,7 @@ import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; import android.view.animation.LinearInterpolator; +import com.android.systemui.recents.RecentsConfiguration; /** * This class facilitates swipe to dismiss. It defines an interface to be implemented by the @@ -50,7 +51,7 @@ public class SwipeHelper { private int DEFAULT_ESCAPE_ANIMATION_DURATION = 75; // ms private int MAX_ESCAPE_ANIMATION_DURATION = 150; // ms private int MAX_DISMISS_VELOCITY = 2000; // dp/sec - private static final int SNAP_ANIM_LEN = SLOW_ANIMATIONS ? 1000 : 150; // ms + private static final int SNAP_ANIM_LEN = SLOW_ANIMATIONS ? 1000 : 250; // ms public static float ALPHA_FADE_START = 0.15f; // fraction of thumbnail width // where fade starts @@ -265,6 +266,7 @@ public class SwipeHelper { ValueAnimator anim = createTranslationAnimation(view, 0); int duration = SNAP_ANIM_LEN; anim.setDuration(duration); + anim.setInterpolator(RecentsConfiguration.getInstance().linearOutSlowInInterpolator); anim.addUpdateListener(new AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { 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 861011f..dbed136 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java @@ -105,7 +105,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal mFilterAlgorithm = new TaskStackViewFilterAlgorithm(mConfig, this, mViewPool); mStackScroller = new TaskStackViewScroller(context, mConfig, mLayoutAlgorithm); mStackScroller.setCallbacks(this); - mTouchHandler = new TaskStackViewTouchHandler(context, this, mStackScroller); + mTouchHandler = new TaskStackViewTouchHandler(context, this, mConfig, mStackScroller); mUIDozeTrigger = new DozeTrigger(mConfig.taskBarDismissDozeDelaySeconds, new Runnable() { @Override public void run() { @@ -647,17 +647,17 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal } /** Animates a task view in this stack as it launches. */ - public void startLaunchTaskAnimation(TaskView tv, final Runnable r) { + public void startLaunchTaskAnimation(TaskView tv, Runnable r, boolean lockToTask) { Task launchTargetTask = tv.getTask(); int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { TaskView t = (TaskView) getChildAt(i); if (t == tv) { - t.startLaunchTaskAnimation(r, true, true); + t.startLaunchTaskAnimation(r, true, true, lockToTask); } else { boolean occludesLaunchTarget = launchTargetTask.group.isTaskAboveTask(t.getTask(), launchTargetTask); - t.startLaunchTaskAnimation(null, false, occludesLaunchTarget); + t.startLaunchTaskAnimation(null, false, occludesLaunchTarget, lockToTask); } } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java index 2c0dc44..5852b88 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java @@ -133,12 +133,8 @@ public class TaskStackViewScroller { stopBoundScrollAnimation(); mScrollAnimator = ObjectAnimator.ofFloat(this, "stackScroll", curScroll, newScroll); - mScrollAnimator.setDuration(200); - // We would have to project the difference into the screen coords, and then use that as the - // duration -// mScrollAnimator.setDuration(Utilities.calculateTranslationAnimationDuration(newScroll - -// curScroll, 250)); - mScrollAnimator.setInterpolator(mConfig.fastOutSlowInInterpolator); + mScrollAnimator.setDuration(mConfig.taskStackScrollDuration); + mScrollAnimator.setInterpolator(mConfig.linearOutSlowInInterpolator); mScrollAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java index 374a27f..8f9b4c2 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java @@ -23,11 +23,13 @@ import android.view.View; import android.view.ViewConfiguration; import android.view.ViewParent; import com.android.systemui.recents.Constants; +import com.android.systemui.recents.RecentsConfiguration; /* Handles touch events for a TaskStackView. */ class TaskStackViewTouchHandler implements SwipeHelper.Callback { static int INACTIVE_POINTER_ID = -1; + RecentsConfiguration mConfig; TaskStackView mSv; TaskStackViewScroller mScroller; VelocityTracker mVelocityTracker; @@ -52,7 +54,8 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback { SwipeHelper mSwipeHelper; boolean mInterceptedBySwipeHelper; - public TaskStackViewTouchHandler(Context context, TaskStackView sv, TaskStackViewScroller scroller) { + public TaskStackViewTouchHandler(Context context, TaskStackView sv, + RecentsConfiguration config, TaskStackViewScroller scroller) { ViewConfiguration configuration = ViewConfiguration.get(context); mMinimumVelocity = configuration.getScaledMinimumFlingVelocity(); mMaximumVelocity = configuration.getScaledMaximumFlingVelocity(); @@ -60,6 +63,7 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback { mPagingTouchSlop = configuration.getScaledPagingTouchSlop(); mSv = sv; mScroller = scroller; + mConfig = config; float densityScale = context.getResources().getDisplayMetrics().density; mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, densityScale, mPagingTouchSlop); @@ -258,7 +262,7 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback { if (Float.compare(overScrollAmount, 0f) != 0) { // Bound the overscroll to a fixed amount, and inversely scale the y-movement // relative to how close we are to the max overscroll - float maxOverScroll = 0.25f; + float maxOverScroll = mConfig.taskStackOverscrollPct; deltaP *= (1f - (Math.min(maxOverScroll, overScrollAmount) / maxOverScroll)); } @@ -280,7 +284,6 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback { velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity); int velocity = (int) velocityTracker.getYVelocity(mActivePointerId); if (mIsScrolling && (Math.abs(velocity) > mMinimumVelocity)) { - // XXX: Should this be calculated as a percentage of a curve? int overscrollRange = (int) (Math.min(1f, Math.abs((float) velocity / mMaximumVelocity)) * Constants.Values.TaskStackView.TaskStackOverscrollRange); 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 dfbcce1..eecc170 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java @@ -471,7 +471,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, /** Animates this task view as it exits recents */ void startLaunchTaskAnimation(final Runnable postAnimRunnable, boolean isLaunchingTask, - boolean occludesLaunchTarget) { + boolean occludesLaunchTarget, boolean lockToTask) { if (isLaunchingTask) { // Disable the thumbnail clip mThumbnailView.disableTaskBarClip(); @@ -487,11 +487,14 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, } // Animate the action button away - float toScale = 0.9f; + if (!lockToTask) { + float toScale = 0.9f; + mActionButtonView.animate() + .scaleX(toScale) + .scaleY(toScale); + } mActionButtonView.animate() .alpha(0f) - .scaleX(toScale) - .scaleY(toScale) .setStartDelay(0) .setDuration(mConfig.taskBarExitAnimDuration) .setInterpolator(mConfig.fastOutLinearInInterpolator) @@ -621,6 +624,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, /** Sets the current task progress. */ public void setTaskProgress(float p) { mTaskProgress = p; + mViewBounds.setAlpha(p); updateDimFromTaskProgress(); } |