diff options
author | Winson Chung <winsonc@google.com> | 2014-08-22 15:26:27 -0700 |
---|---|---|
committer | Winson Chung <winsonc@google.com> | 2014-08-25 18:52:32 -0700 |
commit | a4ccb86ddc8f9f486aee25fb836f4aff97bf7679 (patch) | |
tree | 6334f5211160b9811b681ae51dcb90ad5d9a4c2e /packages | |
parent | 9edf297055b4fbc5d5f6dacc469fa87fc1cb5370 (diff) | |
download | frameworks_base-a4ccb86ddc8f9f486aee25fb836f4aff97bf7679.zip frameworks_base-a4ccb86ddc8f9f486aee25fb836f4aff97bf7679.tar.gz frameworks_base-a4ccb86ddc8f9f486aee25fb836f4aff97bf7679.tar.bz2 |
Multiple performance changes to speed recents invocation/app launching time. (Bug 16987565)
- Reverting changes to the existing thumbnail transition to prevent breaking applications
that currently depend on that transition. As a result, we need to create a new, hidden,
aspect-scaled thumbnail transition, and instead use that thumbnail to animate the
recents header so that we don't have to wait to do that inside the Recents activity.
In order for this to work, we also have to ensure that the thumbnail surface destruction
is synchronized with the application that is currently closing (when going down to
recents) or opening (when coming back up). The current thumbnail is destroyed when the
animation ends, but that can be at least 1 frame before the surface for the animating
window is destroyed. We change this by deferring destruction of this thumbnail window
to the animation that is being closed.
Especially on the way up, not having to wait for us to hide the header before doing the
transition up can save us the duration of that first animation (> 100ms).
- Other optimizations:
* No longer creating a new stack view on each transition to calculate the target rect
* Removing unnecessary call to get the thumbnail when transitioning up/down (the actual
window does its own animation.
* We reduced numerous system calls per task by adding a flag to ignore home-stack tasks
and caching the activity label and icon (and task description icon). These caches
follow the same eviction schemes as the thumbnail and icon cache.
- Also tweaked the touch slop for the nav bar swiping gesture to prevent conflicting with
tapping on home (Bug 17109581)
Change-Id: Ica697aad788051a9203edd9351c583e1cb038a71
Diffstat (limited to 'packages')
22 files changed, 364 insertions, 236 deletions
diff --git a/packages/SystemUI/res/anim/recents_from_launcher_enter.xml b/packages/SystemUI/res/anim/recents_from_launcher_enter.xml index 305a82f..4e1d66d 100644 --- a/packages/SystemUI/res/anim/recents_from_launcher_enter.xml +++ b/packages/SystemUI/res/anim/recents_from_launcher_enter.xml @@ -20,9 +20,9 @@ <set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false" android:zAdjustment="normal"> - <alpha android:fromAlpha="1.0" android:toAlpha="1.0" + <alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" android:interpolator="@android:interpolator/linear" - android:duration="200"/> + android:duration="100"/> </set> diff --git a/packages/SystemUI/res/anim/recents_from_launcher_exit.xml b/packages/SystemUI/res/anim/recents_from_launcher_exit.xml index 863591f..afab78d 100644 --- a/packages/SystemUI/res/anim/recents_from_launcher_exit.xml +++ b/packages/SystemUI/res/anim/recents_from_launcher_exit.xml @@ -24,5 +24,5 @@ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" android:interpolator="@android:interpolator/linear_out_slow_in" - android:duration="200"/> + android:duration="100"/> </set> diff --git a/packages/SystemUI/res/anim/recents_to_launcher_enter.xml b/packages/SystemUI/res/anim/recents_to_launcher_enter.xml index adcefe0..4e1d66d 100644 --- a/packages/SystemUI/res/anim/recents_to_launcher_enter.xml +++ b/packages/SystemUI/res/anim/recents_to_launcher_enter.xml @@ -23,6 +23,6 @@ <alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" - android:interpolator="@android:interpolator/fast_out_linear_in" - android:duration="200"/> + android:interpolator="@android:interpolator/linear" + android:duration="100"/> </set> diff --git a/packages/SystemUI/res/anim/recents_to_launcher_exit.xml b/packages/SystemUI/res/anim/recents_to_launcher_exit.xml index 863591f..afab78d 100644 --- a/packages/SystemUI/res/anim/recents_to_launcher_exit.xml +++ b/packages/SystemUI/res/anim/recents_to_launcher_exit.xml @@ -24,5 +24,5 @@ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" android:interpolator="@android:interpolator/linear_out_slow_in" - android:duration="200"/> + android:duration="100"/> </set> diff --git a/packages/SystemUI/res/layout/recents_task_view.xml b/packages/SystemUI/res/layout/recents_task_view.xml index 5253ee0..4cb8498 100644 --- a/packages/SystemUI/res/layout/recents_task_view.xml +++ b/packages/SystemUI/res/layout/recents_task_view.xml @@ -23,45 +23,7 @@ android:id="@+id/task_view_thumbnail" android:layout_width="match_parent" android:layout_height="match_parent" /> - <com.android.systemui.recents.views.TaskViewHeader - android:id="@+id/task_view_bar" - android:layout_width="match_parent" - android:layout_height="@dimen/recents_task_bar_height" - android:layout_gravity="top|center_horizontal"> - <com.android.systemui.recents.views.FixedSizeImageView - android:id="@+id/application_icon" - android:layout_width="@dimen/recents_task_view_application_icon_size" - android:layout_height="@dimen/recents_task_view_application_icon_size" - android:layout_marginStart="8dp" - android:layout_gravity="center_vertical|start" - android:padding="8dp" - android:background="@drawable/recents_button_bg" /> - <TextView - android:id="@+id/activity_description" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical|start" - android:layout_marginStart="64dp" - android:layout_marginEnd="64dp" - android:textSize="16sp" - android:textColor="#ffffffff" - android:text="@string/recents_empty_message" - android:fontFamily="sans-serif-medium" - android:singleLine="true" - android:maxLines="2" - android:ellipsize="marquee" - android:fadingEdge="horizontal" /> - <com.android.systemui.recents.views.FixedSizeImageView - android:id="@+id/dismiss_task" - android:layout_width="48dp" - android:layout_height="48dp" - android:layout_marginEnd="4dp" - android:layout_gravity="center_vertical|end" - android:padding="12dp" - android:background="@drawable/recents_button_bg" - android:visibility="invisible" - android:src="@drawable/recents_dismiss_light" /> - </com.android.systemui.recents.views.TaskViewHeader> + <include layout="@layout/recents_task_view_header" /> <FrameLayout android:id="@+id/lock_to_app_fab" android:layout_width="48dp" diff --git a/packages/SystemUI/res/layout/recents_task_view_header.xml b/packages/SystemUI/res/layout/recents_task_view_header.xml new file mode 100644 index 0000000..f1d8ad0 --- /dev/null +++ b/packages/SystemUI/res/layout/recents_task_view_header.xml @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<com.android.systemui.recents.views.TaskViewHeader + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/task_view_bar" + android:layout_width="match_parent" + android:layout_height="@dimen/recents_task_bar_height" + android:layout_gravity="top|center_horizontal"> + <com.android.systemui.recents.views.FixedSizeImageView + android:id="@+id/application_icon" + android:layout_width="@dimen/recents_task_view_application_icon_size" + android:layout_height="@dimen/recents_task_view_application_icon_size" + android:layout_marginStart="8dp" + android:layout_gravity="center_vertical|start" + android:padding="8dp" + android:background="@drawable/recents_button_bg" /> + <TextView + android:id="@+id/activity_description" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical|start" + android:layout_marginStart="64dp" + android:layout_marginEnd="64dp" + android:textSize="16sp" + android:textColor="#ffffffff" + android:text="@string/recents_empty_message" + android:fontFamily="sans-serif-medium" + android:singleLine="true" + android:maxLines="2" + android:ellipsize="marquee" + android:fadingEdge="horizontal" /> + <com.android.systemui.recents.views.FixedSizeImageView + android:id="@+id/dismiss_task" + android:layout_width="48dp" + android:layout_height="48dp" + android:layout_marginEnd="4dp" + android:layout_gravity="center_vertical|end" + android:padding="12dp" + android:background="@drawable/recents_button_bg" + android:visibility="invisible" + android:src="@drawable/recents_dismiss_light" /> +</com.android.systemui.recents.views.TaskViewHeader>
\ No newline at end of file diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 52dc000..fa00ebf 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -126,7 +126,7 @@ <integer name="recents_animate_task_bar_enter_duration">275</integer> <!-- The animation delay for animating the first task in. This should roughly be the animation duration of the transition in to recents. --> - <integer name="recents_animate_task_bar_enter_delay">225</integer> + <integer name="recents_animate_task_bar_enter_delay">300</integer> <!-- The min animation duration for animating the task bar out. --> <integer name="recents_animate_task_exit_to_home_duration">225</integer> <!-- The min animation duration for animating the task bar out. --> diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java index 354eb55..8710aa2 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java +++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java @@ -22,6 +22,7 @@ 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; @@ -29,6 +30,7 @@ import android.graphics.Canvas; import android.graphics.Rect; import android.os.Handler; import android.os.UserHandle; +import android.view.LayoutInflater; import android.view.View; import com.android.systemui.R; import com.android.systemui.RecentsComponent; @@ -41,6 +43,7 @@ import com.android.systemui.recents.model.TaskGrouping; import com.android.systemui.recents.model.TaskStack; import com.android.systemui.recents.views.TaskStackView; import com.android.systemui.recents.views.TaskStackViewLayoutAlgorithm; +import com.android.systemui.recents.views.TaskViewHeader; import com.android.systemui.recents.views.TaskViewTransform; import java.util.ArrayList; @@ -86,6 +89,10 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta int mNavBarHeight; int mNavBarWidth; + // Header (for transition) + TaskViewHeader mHeaderBar; + TaskStackView mDummyStackView; + // Variables to keep track of if we need to start recents after binding View mStatusBarView; boolean mTriggeredFromAltTab; @@ -114,6 +121,7 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta public void onStart() { // Initialize some static datastructures TaskStackViewLayoutAlgorithm.initializeCurve(); + reloadHeaderBarLayout(); } public void onBootCompleted() { @@ -169,7 +177,7 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta void showRelativeAffiliatedTask(boolean showNextTask) { TaskStack stack = RecentsTaskLoader.getShallowTaskStack(mSystemServicesProxy, - Integer.MAX_VALUE); + Integer.MAX_VALUE, mContext.getResources()); // Return early if there are no tasks if (stack.getTaskCount() == 0) return; @@ -250,6 +258,28 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta mSystemInsets.set(0, mStatusBarHeight, 0, mNavBarHeight); } sLastScreenshot = null; + reloadHeaderBarLayout(); + } + + /** Prepares the header bar layout. */ + void reloadHeaderBarLayout() { + // Inflate the header bar layout so that we can rebind and draw it for the transition + Resources res = mContext.getResources(); + TaskStack stack = new TaskStack(); + mDummyStackView = new TaskStackView(mContext, stack); + TaskStackViewLayoutAlgorithm algo = mDummyStackView.getStackAlgorithm(); + Rect taskStackBounds = new Rect(mTaskStackBounds); + taskStackBounds.bottom -= mSystemInsets.bottom; + algo.computeRects(mWindowRect.width(), mWindowRect.height(), taskStackBounds); + Rect taskViewSize = algo.getUntransformedTaskViewSize(); + int taskBarHeight = res.getDimensionPixelSize(R.dimen.recents_task_bar_height); + LayoutInflater inflater = LayoutInflater.from(mContext); + mHeaderBar = (TaskViewHeader) inflater.inflate(R.layout.recents_task_view_header, null, + false); + mHeaderBar.measure( + View.MeasureSpec.makeMeasureSpec(taskViewSize.width(), View.MeasureSpec.EXACTLY), + View.MeasureSpec.makeMeasureSpec(taskBarHeight, View.MeasureSpec.EXACTLY)); + mHeaderBar.layout(0, 0, taskViewSize.width(), taskBarHeight); } /** Gets the top task. */ @@ -361,27 +391,37 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta } } - // If the screenshot fails, then load the first task thumbnail and use that - Bitmap firstThumbnail = mSystemServicesProxy.getTaskThumbnail(topTask.id); - if (firstThumbnail != null) { - // Update the destination rect - Rect toTaskRect = getThumbnailTransitionRect(topTask.id, isTopTaskHome); - if (toTaskRect.width() > 0 && toTaskRect.height() > 0) { - // Create the new thumbnail for the animation down - // XXX: We should find a way to optimize this so we don't need to create a new bitmap - Bitmap thumbnail = Bitmap.createBitmap(toTaskRect.width(), toTaskRect.height(), - Bitmap.Config.ARGB_8888); - int size = Math.min(firstThumbnail.getWidth(), firstThumbnail.getHeight()); + // Update the destination rect + Task toTask = new Task(); + TaskViewTransform toTransform = getThumbnailTransitionTransform(topTask.id, isTopTaskHome, + 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); + } + + Bitmap thumbnail = Bitmap.createBitmap(toTaskRect.width(), toTaskRect.height(), + Bitmap.Config.ARGB_8888); + if (Constants.DebugFlags.App.EnableTransitionThumbnailDebugMode) { + thumbnail.eraseColor(0xFFff0000); + } else { Canvas c = new Canvas(thumbnail); - c.drawBitmap(firstThumbnail, new Rect(0, 0, size, size), - new Rect(0, 0, toTaskRect.width(), toTaskRect.height()), null); + c.scale(toTransform.scale, toTransform.scale); + mHeaderBar.rebindToTask(toTask); + mHeaderBar.draw(c); c.setBitmap(null); - // Recycle the old thumbnail - firstThumbnail.recycle(); - mStartAnimationTriggered = false; - return ActivityOptions.makeThumbnailScaleDownAnimation(mStatusBarView, - thumbnail, toTaskRect.left, toTaskRect.top, this); } + + mStartAnimationTriggered = false; + return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mStatusBarView, + thumbnail, toTaskRect.left, toTaskRect.top, this); } // If both the screenshot and thumbnail fails, then just fall back to the default transition @@ -389,21 +429,18 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta } /** Returns the transition rect for the given task id. */ - Rect getThumbnailTransitionRect(int runningTaskId, boolean isTopTaskHome) { + TaskViewTransform getThumbnailTransitionTransform(int runningTaskId, boolean isTopTaskHome, + Task runningTaskOut) { // Get the stack of tasks that we are animating into - TaskStack stack = RecentsTaskLoader.getShallowTaskStack(mSystemServicesProxy, -1); + TaskStack stack = RecentsTaskLoader.getShallowTaskStack(mSystemServicesProxy, -1, + mContext.getResources()); if (stack.getTaskCount() == 0) { - return new Rect(); + return null; } // Get the stack - TaskStackView tsv = new TaskStackView(mContext, stack); - TaskStackViewLayoutAlgorithm algo = tsv.getStackAlgorithm(); - Rect taskStackBounds = new Rect(mTaskStackBounds); - taskStackBounds.bottom -= mSystemInsets.bottom; - tsv.computeRects(mWindowRect.width(), mWindowRect.height(), taskStackBounds, - mTriggeredFromAltTab, isTopTaskHome); - tsv.getScroller().setStackScrollToInitialState(); + mDummyStackView.updateMinMaxScrollForStack(stack, mTriggeredFromAltTab, isTopTaskHome); + mDummyStackView.getScroller().setStackScrollToInitialState(); // Find the running task in the TaskStack Task task = null; @@ -415,6 +452,7 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta Task t = tasks.get(i); if (t.key.id == runningTaskId) { task = t; + runningTaskOut.copyFrom(t); break; } } @@ -425,8 +463,9 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta } // Get the transform for the running task - mTmpTransform = algo.getStackTransform(task, tsv.getScroller().getStackScroll(), mTmpTransform, null); - return new Rect(mTmpTransform.rect); + mTmpTransform = mDummyStackView.getStackAlgorithm().getStackTransform(task, + mDummyStackView.getScroller().getStackScroll(), mTmpTransform, null); + return mTmpTransform; } /** Starts the recents activity */ diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java index 3709c43..6f4cf6b 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java +++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java @@ -27,6 +27,8 @@ public class Constants { public static class App { // Enables the screenshot app->Recents transition public static final boolean EnableScreenshotAppTransition = false; + // Enables debug drawing for the transition thumbnail + public static final boolean EnableTransitionThumbnailDebugMode = false; // Enables the filtering of tasks according to their grouping public static final boolean EnableTaskFiltering = false; // Enables clipping of tasks against each other diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java index 7fafe7a..a5b845d 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java @@ -384,7 +384,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView // Private API calls to make the shadows look better try { - Utilities.setShadowProperty("ambientShadowStrength", String.valueOf(35f)); Utilities.setShadowProperty("ambientRatio", String.valueOf(1.5f)); } catch (IllegalAccessException e) { e.printStackTrace(); diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java index 5390daf..b29f378 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java +++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java @@ -174,6 +174,7 @@ public class SystemServicesProxy { int minNumTasksToQuery = 10; int numTasksToQuery = Math.max(minNumTasksToQuery, numLatestTasks); List<ActivityManager.RecentTaskInfo> tasks = mAm.getRecentTasksForUser(numTasksToQuery, + ActivityManager.RECENT_IGNORE_HOME_STACK_TASKS | ActivityManager.RECENT_IGNORE_UNAVAILABLE | ActivityManager.RECENT_INCLUDE_PROFILES | ActivityManager.RECENT_WITH_EXCLUDED, userId); @@ -185,11 +186,6 @@ public class SystemServicesProxy { // NOTE: The order of these checks happens in the expected order of the traversal of the // tasks - // Skip tasks from this Recents package - if (t.baseIntent.getComponent().getPackageName().equals(mRecentsPackage)) { - iter.remove(); - continue; - } // Check the first non-recents task, include this task even if it is marked as excluded // from recents. In other words, only remove excluded tasks if it is not the first task boolean isExcluded = (t.baseIntent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) @@ -199,11 +195,6 @@ public class SystemServicesProxy { continue; } isFirstValidTask = false; - // Skip tasks in the home stack - if (isInHomeStack(t.persistentId)) { - iter.remove(); - continue; - } } return tasks.subList(0, Math.min(tasks.size(), numLatestTasks)); 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 0e2f370..b93c126 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java @@ -18,6 +18,7 @@ package com.android.systemui.recents.model; import android.app.ActivityManager; import android.content.ComponentCallbacks2; +import android.content.ComponentName; import android.content.Context; import android.content.pm.ActivityInfo; import android.content.res.Resources; @@ -31,6 +32,7 @@ import com.android.systemui.recents.Constants; import com.android.systemui.recents.RecentsConfiguration; import com.android.systemui.recents.misc.SystemServicesProxy; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.LinkedHashSet; @@ -171,9 +173,9 @@ class TaskResourceLoader implements Runnable { // Load the application icon if it is stale or we haven't cached one yet if (cachedIcon == null) { ActivityInfo info = ssp.getActivityInfo(t.key.baseIntent.getComponent(), - t.userId); + t.key.userId); if (info != null) { - cachedIcon = ssp.getActivityIcon(info, t.userId); + cachedIcon = ssp.getActivityIcon(info, t.key.userId); } if (cachedIcon == null) { cachedIcon = mDefaultApplicationIcon; @@ -228,8 +230,10 @@ public class RecentsTaskLoader { static RecentsTaskLoader sInstance; SystemServicesProxy mSystemServicesProxy; + DrawableLruCache mTaskDescriptionIconCache; DrawableLruCache mApplicationIconCache; BitmapLruCache mThumbnailCache; + StringLruCache mActivityLabelCache; TaskResourceLoadQueue mLoadQueue; TaskResourceLoader mLoader; @@ -270,8 +274,10 @@ 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); mLoader = new TaskResourceLoader(mLoadQueue, mApplicationIconCache, mThumbnailCache, mDefaultThumbnail, mDefaultApplicationIcon); } @@ -313,6 +319,7 @@ public class RecentsTaskLoader { RecentsConfiguration config = RecentsConfiguration.getInstance(); Resources res = context.getResources(); LinkedHashSet<Task> tasksToLoad = new LinkedHashSet<Task>(); + ArrayList<Task> tasksToAdd = new ArrayList<Task>(); TaskStack stack = new TaskStack(); SpaceNode root = new SpaceNode(); root.setStack(stack); @@ -325,55 +332,80 @@ public class RecentsTaskLoader { int taskCount = tasks.size(); for (int i = 0; i < taskCount; i++) { ActivityManager.RecentTaskInfo t = tasks.get(i); - ActivityInfo info = ssp.getActivityInfo(t.baseIntent.getComponent(), t.userId); - if (info == null) continue; + 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; + String activityLabel = null; Drawable activityIcon = mDefaultApplicationIcon; int activityColor = config.taskBarViewDefaultBackgroundColor; + boolean loadedActivityIcon = false; if (av != null) { - activityLabel = (av.getLabel() != null ? av.getLabel() : ssp.getActivityLabel(info)); - activityIcon = (av.getIcon() != 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(); } - } else { - activityLabel = ssp.getActivityLabel(info); + loadedActivityIcon = (activityIcon != null); + } + // 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); + } } // Create a new task - Task task = new Task(t.persistentId, (t.id > -1), t.baseIntent, t.affiliatedTaskId, - t.affiliatedTaskColor, activityLabel, activityIcon, activityColor, t.userId, - t.firstActiveTime, t.lastActiveTime, (i == (taskCount - 1)), + 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 - task.applicationIcon = mApplicationIconCache.getAndInvalidateIfModified(task.key); - if (task.applicationIcon == null) { - // Load the icon from the system - task.applicationIcon = ssp.getActivityIcon(info, task.userId); - if (task.applicationIcon != null) { - mApplicationIconCache.put(task.key, task.applicationIcon); + // 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 (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); } // Load the thumbnail from the cache if possible - task.thumbnail = mThumbnailCache.getAndInvalidateIfModified(task.key); + task.thumbnail = mThumbnailCache.getAndInvalidateIfModified(taskKey); if (task.thumbnail == null) { // Load the thumbnail from the system - task.thumbnail = ssp.getTaskThumbnail(task.key.id); + task.thumbnail = ssp.getTaskThumbnail(taskKey.id); if (task.thumbnail != null) { task.thumbnail.setHasAlpha(false); - mThumbnailCache.put(task.key, task.thumbnail); + mThumbnailCache.put(taskKey, task.thumbnail); } } if (task.thumbnail == null) { @@ -384,10 +416,11 @@ public class RecentsTaskLoader { } // Add the task to the stack - stack.addTask(task); + 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 @@ -401,21 +434,29 @@ public class RecentsTaskLoader { } /** Creates a lightweight stack of the current recent tasks, without thumbnails and icons. */ - public static TaskStack getShallowTaskStack(SystemServicesProxy ssp, int numTasks) { + 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); - ActivityInfo info = ssp.getActivityInfo(t.baseIntent.getComponent(), t.userId); - if (info == null) continue; + ActivityManager.TaskDescription av = t.taskDescription; - stack.addTask(new Task(t.persistentId, true, t.baseIntent, t.affiliatedTaskId, - t.affiliatedTaskColor, null, null, 0, 0, t.firstActiveTime, t.lastActiveTime, - (i == (taskCount - 1)), config.lockToAppEnabled)); + 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; } @@ -484,18 +525,23 @@ 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; default: break; diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/StringLruCache.java b/packages/SystemUI/src/com/android/systemui/recents/model/StringLruCache.java new file mode 100644 index 0000000..b06c454 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/recents/model/StringLruCache.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.recents.model; + +/** + * The String LRU cache. + */ +class StringLruCache extends KeyStoreLruCache<String> { + public StringLruCache(int cacheSize) { + super(cacheSize); + } + + @Override + protected int computeSize(String s) { + // The cache size is measured in number of strings + return 1; + } +}
\ No newline at end of file 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 f6c3a7e..977db60 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java @@ -88,7 +88,6 @@ public class Task { public boolean isActive; public boolean lockToThisTask; public boolean lockToTaskEnabled; - public int userId; TaskCallbacks mCb; @@ -96,13 +95,12 @@ public class Task { // Only used by RecentsService for task rect calculations. } - public Task(int id, boolean isActive, Intent intent, int taskAffiliation, int taskAffiliationColor, - String activityTitle, Drawable activityIcon, int colorPrimary, int userId, - long firstActiveTime, long lastActiveTime, boolean lockToThisTask, - boolean lockToTaskEnabled) { - boolean isInAffiliationGroup = (taskAffiliation != id); + public Task(TaskKey key, boolean isActive, int taskAffiliation, int taskAffiliationColor, + String activityTitle, Drawable activityIcon, int colorPrimary, + boolean lockToThisTask, boolean lockToTaskEnabled) { + boolean isInAffiliationGroup = (taskAffiliation != key.id); boolean hasAffiliationGroupColor = isInAffiliationGroup && (taskAffiliationColor != 0); - this.key = new TaskKey(id, intent, userId, firstActiveTime, lastActiveTime); + this.key = key; this.taskAffiliation = taskAffiliation; this.taskAffiliationColor = taskAffiliationColor; this.activityLabel = activityTitle; @@ -113,7 +111,20 @@ public class Task { this.isActive = isActive; this.lockToThisTask = lockToTaskEnabled && lockToThisTask; this.lockToTaskEnabled = lockToTaskEnabled; - this.userId = userId; + } + + /** Copies the other task. */ + public void copyFrom(Task o) { + this.key = o.key; + this.taskAffiliation = o.taskAffiliation; + this.taskAffiliationColor = o.taskAffiliationColor; + this.activityLabel = o.activityLabel; + this.activityIcon = o.activityIcon; + this.colorPrimary = o.colorPrimary; + this.useLightOnPrimaryColor = o.useLightOnPrimaryColor; + this.isActive = o.isActive; + this.lockToThisTask = o.lockToThisTask; + this.lockToTaskEnabled = o.lockToTaskEnabled; } /** Set the callbacks */ 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 98bf151..1e47b50 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java @@ -92,7 +92,10 @@ class FilteredTaskList { /** Returns the index of this task in the list of filtered tasks */ int indexOf(Task t) { - return mTaskIndices.get(t.key); + if (mTaskIndices.containsKey(t.key)) { + return mTaskIndices.get(t.key); + } + return -1; } /** Returns the size of the list of filtered tasks */ 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 07a7e74..1dd484b 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java @@ -408,14 +408,26 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV int thumbnailHeight = transform.rect.height(); if (task.thumbnail != null && thumbnailWidth > 0 && thumbnailHeight > 0 && task.thumbnail.getWidth() > 0 && task.thumbnail.getHeight() > 0) { - // Resize the thumbnail to the size of the view that we are animating from - Bitmap b = Bitmap.createBitmap(thumbnailWidth, thumbnailHeight, - Bitmap.Config.ARGB_8888); - Canvas c = new Canvas(b); - c.drawBitmap(task.thumbnail, - new Rect(0, 0, task.thumbnail.getWidth(), task.thumbnail.getHeight()), - new Rect(0, 0, thumbnailWidth, thumbnailHeight), null); - c.setBitmap(null); + Bitmap b; + if (tv != null) { + // Disable any focused state before we draw the header + if (tv.isFocusedTask()) { + tv.unsetFocusedTask(); + } + + b = Bitmap.createBitmap(thumbnailWidth, thumbnailHeight, Bitmap.Config.ARGB_8888); + if (Constants.DebugFlags.App.EnableTransitionThumbnailDebugMode) { + b.eraseColor(0xFFff0000); + } else { + Canvas c = new Canvas(b); + c.scale(tv.getScaleX(), tv.getScaleY()); + tv.mHeaderView.draw(c); + c.setBitmap(null); + } + } else { + // Notify the system to skip the thumbnail layer by using an ALPHA_8 bitmap + b = Bitmap.createBitmap(thumbnailWidth, thumbnailHeight, Bitmap.Config.ALPHA_8); + } ActivityOptions.OnAnimationStartedListener animStartedListener = null; if (lockToTask) { animStartedListener = new ActivityOptions.OnAnimationStartedListener() { @@ -434,7 +446,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV } }; } - opts = ActivityOptions.makeThumbnailScaleUpAnimation(sourceView, + opts = ActivityOptions.makeThumbnailAspectScaleUpAnimation(sourceView, b, offsetX, offsetY, animStartedListener); } @@ -472,7 +484,15 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV if (tv == null) { post(launchRunnable); } else { - stackView.startLaunchTaskAnimation(tv, launchRunnable); + 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); + } else { + // Otherwise, we can start the task transition immediately + stackView.startLaunchTaskAnimation(tv, null); + postDelayed(launchRunnable, 17); + } } } @@ -485,7 +505,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV intent.setComponent(intent.resolveActivity(getContext().getPackageManager())); TaskStackBuilder.create(getContext()) .addNextIntentWithParentStack(intent).startActivities(null, - new UserHandle(t.userId)); + new UserHandle(t.key.userId)); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java index aee558f..861011f 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java @@ -460,7 +460,17 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal } /** - * This is called with the full window width and height to allow stack view children to + * This is ONLY used from AlternateRecentsComponent to update the dummy stack view for purposes + * of getting the task rect to animate to. + */ + public void updateMinMaxScrollForStack(TaskStack stack, boolean launchedWithAltTab, + boolean launchedFromHome) { + mStack = stack; + updateMinMaxScroll(false, launchedWithAltTab, launchedFromHome); + } + + /** + * This is called with the full window width and height to allow stack view children to * perform the full screen transition down. */ @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 f0bdfa2..31fc701 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java @@ -33,7 +33,7 @@ import java.util.HashMap; public class TaskStackViewLayoutAlgorithm { // These are all going to change - static final float StackPeekMinScale = 0.825f; // The min scale of the last card in the peek area + static final float StackPeekMinScale = 0.8f; // The min scale of the last card in the peek area RecentsConfiguration mConfig; @@ -157,7 +157,7 @@ public class TaskStackViewLayoutAlgorithm { public TaskViewTransform getStackTransform(Task task, float stackScroll, TaskViewTransform transformOut, TaskViewTransform prevTransform) { // Return early if we have an invalid index - if (task == null) { + if (task == null || !mTaskProgressMap.containsKey(task.key)) { transformOut.reset(); return transformOut; } @@ -200,6 +200,15 @@ public class TaskStackViewLayoutAlgorithm { } /** + * Returns the untransformed task view size. + */ + public Rect getUntransformedTaskViewSize() { + Rect tvSize = new Rect(mTaskRect); + tvSize.offsetTo(0, 0); + return tvSize; + } + + /** * Returns the scroll to such task top = 1f; */ float getStackScrollForTask(Task t) { 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 e514c90..dfbcce1 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java @@ -235,7 +235,6 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, int initialDim = getDim(); if (mConfig.launchedFromAppWithScreenshot) { if (isTaskViewLaunchTargetTask) { - mHeaderView.prepareEnterRecentsAnimation(); // Hide the footer during the transition in, and animate it out afterwards? if (mFooterView != null) { mFooterView.animateFooterVisibility(false, 0); @@ -246,8 +245,6 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, } else if (mConfig.launchedFromAppWithThumbnail) { if (isTaskViewLaunchTargetTask) { - // Hide the front most task bar view so we can animate it in - mHeaderView.prepareEnterRecentsAnimation(); // Hide the action button if it exists mActionButtonView.setAlpha(0f); // Set the dim to 0 so we can animate it in @@ -306,7 +303,6 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, mViewBounds.animateClipBottom(getMeasuredHeight() - (windowInsetTop + size), duration); } // Animate the task bar of the first task view - mHeaderView.startEnterRecentsAnimation(0, null); animate() .scaleX(taskScale) .scaleY(taskScale) @@ -352,9 +348,8 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, } else if (mConfig.launchedFromAppWithThumbnail) { if (mTask.isLaunchTarget) { - // Animate the task bar of the first task view - mHeaderView.startEnterRecentsAnimation(mConfig.taskBarEnterAnimDelay, - mThumbnailView.enableTaskBarClipAsRunnable(mHeaderView)); + // Enable the task bar clip + mThumbnailView.enableTaskBarClip(mHeaderView); // Animate the dim/overlay if (Constants.DebugFlags.App.EnableThumbnailAlphaOnFrontmost) { // Animate the thumbnail alpha before the dim animation (to prevent updating the @@ -475,14 +470,13 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, } /** Animates this task view as it exits recents */ - void startLaunchTaskAnimation(final Runnable r, boolean isLaunchingTask, + void startLaunchTaskAnimation(final Runnable postAnimRunnable, boolean isLaunchingTask, boolean occludesLaunchTarget) { if (isLaunchingTask) { - // Disable the thumbnail clip and animate the bar out for the window animation out - mHeaderView.startLaunchTaskAnimation(mThumbnailView.disableTaskBarClipAsRunnable(), r, - mIsFocused); + // Disable the thumbnail clip + mThumbnailView.disableTaskBarClip(); // Animate the thumbnail alpha back into full opacity for the window animation out - mThumbnailView.startLaunchTaskAnimation(); + mThumbnailView.startLaunchTaskAnimation(postAnimRunnable); // Animate the dim if (mDim > 0) { @@ -493,7 +487,11 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, } // Animate the action button away - mActionButtonView.animate().alpha(0f) + float toScale = 0.9f; + mActionButtonView.animate() + .alpha(0f) + .scaleX(toScale) + .scaleY(toScale) .setStartDelay(0) .setDuration(mConfig.taskBarExitAnimDuration) .setInterpolator(mConfig.fastOutLinearInInterpolator) @@ -706,22 +704,30 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, } /** + * Unsets the focused task explicitly. + */ + void unsetFocusedTask() { + mIsFocused = false; + if (mFocusAnimationsEnabled) { + // Un-focus the header bar + mHeaderView.onTaskViewFocusChanged(false); + } + + // Update the thumbnail alpha with the focus + mThumbnailView.onFocusChanged(false); + // Call the callback + mCb.onTaskViewFocusChanged(this, false); + invalidate(); + } + + /** * Updates the explicitly focused state when the view focus changes. */ @Override protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) { super.onFocusChanged(gainFocus, direction, previouslyFocusedRect); if (!gainFocus) { - mIsFocused = false; - if (mFocusAnimationsEnabled) { - // Un-focus the header bar - mHeaderView.onTaskViewFocusChanged(false); - } - // Update the thumbnail alpha with the focus - mThumbnailView.onFocusChanged(false); - // Call the callback - mCb.onTaskViewFocusChanged(this, false); - invalidate(); + unsetFocusedTask(); } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java index d39f64e..1743433 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java @@ -49,7 +49,7 @@ import com.android.systemui.recents.model.Task; /* The task bar view */ -class TaskViewHeader extends FrameLayout { +public class TaskViewHeader extends FrameLayout { RecentsConfiguration mConfig; @@ -156,8 +156,11 @@ class TaskViewHeader extends FrameLayout { // Draw the highlight at the top edge (but put the bottom edge just out of view) float offset = (float) Math.ceil(mConfig.taskViewHighlightPx / 2f); float radius = mConfig.taskViewRoundedCornerRadiusPx; + int count = canvas.save(Canvas.CLIP_SAVE_FLAG); + canvas.clipRect(0, 0, getMeasuredWidth(), getMeasuredHeight()); canvas.drawRoundRect(-offset, 0f, (float) getMeasuredWidth() + offset, getMeasuredHeight() + radius, radius, radius, sHighlightPaint); + canvas.restoreToCount(count); } } @@ -178,7 +181,7 @@ class TaskViewHeader extends FrameLayout { } /** Binds the bar view to the task */ - void rebindToTask(Task t) { + public void rebindToTask(Task t) { // If an activity icon is defined, then we use that as the primary icon to show in the bar, // otherwise, we fall back to the application icon if (t.activityIcon != null) { @@ -212,51 +215,6 @@ class TaskViewHeader extends FrameLayout { mApplicationIcon.setImageDrawable(null); } - /** Prepares this task view for the enter-recents animations. This is called earlier in the - * first layout because the actual animation into recents may take a long time. */ - void prepareEnterRecentsAnimation() { - setVisibility(View.INVISIBLE); - } - - /** Animates this task bar as it enters recents */ - void startEnterRecentsAnimation(int delay, Runnable postAnimRunnable) { - // Animate the task bar of the first task view - setVisibility(View.VISIBLE); - setAlpha(0f); - animate() - .alpha(1f) - .setStartDelay(delay) - .setInterpolator(mConfig.linearOutSlowInInterpolator) - .setDuration(mConfig.taskBarEnterAnimDuration) - .withEndAction(postAnimRunnable) - .withLayer() - .start(); - } - - /** Animates this task bar as it exits recents */ - void startLaunchTaskAnimation(Runnable preAnimRunnable, final Runnable postAnimRunnable, - boolean isFocused) { - if (isFocused) { - onTaskViewFocusChanged(false); - } - - // Animate the task bar out of the first task view - animate() - .alpha(0f) - .setStartDelay(0) - .setInterpolator(mConfig.linearOutSlowInInterpolator) - .setDuration(mConfig.taskBarExitAnimDuration) - .withStartAction(preAnimRunnable) - .withEndAction(new Runnable() { - @Override - public void run() { - post(postAnimRunnable); - } - }) - .withLayer() - .start(); - } - /** Animates this task bar dismiss button when launching a task. */ void startLaunchTaskDismissAnimation() { if (mDismissButton.getVisibility() == View.VISIBLE) { diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java index f223bf3..fe36987 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java @@ -64,25 +64,10 @@ public class TaskViewThumbnail extends FixedSizeImageView { setClipBounds(mClipRect); } - /** Convenience method to enable task bar clipping as a runnable. */ - Runnable enableTaskBarClipAsRunnable(final View taskBar) { - return new Runnable() { - @Override - public void run() { - enableTaskBarClip(taskBar); - } - }; - } - /** Disables the task bar clipping. */ - Runnable disableTaskBarClipAsRunnable() { - return new Runnable() { - @Override - public void run() { - mClipRect.set(0, 0, getMeasuredWidth(), getMeasuredHeight()); - setClipBounds(mClipRect); - } - }; + void disableTaskBarClip() { + mClipRect.set(0, 0, getMeasuredWidth(), getMeasuredHeight()); + setClipBounds(mClipRect); } /** Binds the thumbnail view to the screenshot. */ @@ -140,8 +125,8 @@ public class TaskViewThumbnail extends FixedSizeImageView { } /** Animates this task thumbnail as it exits recents */ - void startLaunchTaskAnimation() { - startFadeAnimation(1f, 0, mConfig.taskBarExitAnimDuration, null); + void startLaunchTaskAnimation(Runnable postAnimRunnable) { + startFadeAnimation(1f, 0, mConfig.taskBarExitAnimDuration, postAnimRunnable); } /** Animates the thumbnail alpha. */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarViewTaskSwitchHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarViewTaskSwitchHelper.java index 3c20d1f..b87bec4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarViewTaskSwitchHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarViewTaskSwitchHelper.java @@ -36,7 +36,7 @@ public class NavigationBarViewTaskSwitchHelper extends GestureDetector.SimpleOnG public NavigationBarViewTaskSwitchHelper(Context context) { ViewConfiguration configuration = ViewConfiguration.get(context); - mScrollTouchSlop = configuration.getScaledTouchSlop(); + mScrollTouchSlop = 4 * configuration.getScaledTouchSlop(); mMinFlingVelocity = configuration.getScaledMinimumFlingVelocity(); mTaskSwitcherDetector = new GestureDetector(context, this); } |