diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java index 38ce46786ad23..29f291dc160f4 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java +++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java @@ -170,7 +170,8 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta /** Hides the recents */ public void onHideRecents(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) { if (mBootCompleted) { - if (isRecentsTopMost(getTopMostTask(), null)) { + ActivityManager.RunningTaskInfo topTask = getTopMostTask(); + if (topTask != null && isRecentsTopMost(topTask, null)) { // Notify recents to hide itself Intent intent = new Intent(ACTION_HIDE_RECENTS_ACTIVITY); intent.setPackage(mContext.getPackageName()); @@ -217,6 +218,8 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta if (stack.getTaskCount() == 0) return; ActivityManager.RunningTaskInfo runningTask = getTopMostTask(); + // Return early if there is no running task (can't determine affiliated tasks in this case) + if (runningTask == null) return; // Return early if the running task is in the home stack (optimization) if (mSystemServicesProxy.isInHomeStack(runningTask.id)) return; @@ -369,8 +372,8 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta // If Recents is the front most activity, then we should just communicate with it directly // to launch the first task or dismiss itself ActivityManager.RunningTaskInfo topTask = getTopMostTask(); - AtomicBoolean isTopTaskHome = new AtomicBoolean(); - if (isRecentsTopMost(topTask, isTopTaskHome)) { + AtomicBoolean isTopTaskHome = new AtomicBoolean(true); + if (topTask != null && isRecentsTopMost(topTask, isTopTaskHome)) { // Notify recents to toggle itself Intent intent = new Intent(ACTION_TOGGLE_RECENTS_ACTIVITY); intent.setPackage(mContext.getPackageName()); @@ -389,8 +392,8 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta void startRecentsActivity() { // Check if the top task is in the home stack, and start the recents activity ActivityManager.RunningTaskInfo topTask = getTopMostTask(); - AtomicBoolean isTopTaskHome = new AtomicBoolean(); - if (!isRecentsTopMost(topTask, isTopTaskHome)) { + AtomicBoolean isTopTaskHome = new AtomicBoolean(true); + if (topTask == null || !isRecentsTopMost(topTask, isTopTaskHome)) { startRecentsActivity(topTask, isTopTaskHome.get()); } } @@ -504,7 +507,7 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta TaskStackViewLayoutAlgorithm.VisibilityReport stackVr = mDummyStackView.computeStackVisibilityReport(); boolean hasRecentTasks = stack.getTaskCount() > 0; - boolean useThumbnailTransition = !isTopTaskHome && hasRecentTasks; + boolean useThumbnailTransition = (topTask != null) && !isTopTaskHome && hasRecentTasks; if (useThumbnailTransition) { // Ensure that we load the running task's icon 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 a37b9e63f30f2..255d64299ef49 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java @@ -61,6 +61,14 @@ class FilteredTaskList { } } + /** Resets this FilteredTaskList. */ + void reset() { + mTasks.clear(); + mFilteredTasks.clear(); + mTaskIndices.clear(); + mFilter = null; + } + /** Removes the task filter and returns the previous touch state */ void removeFilter() { mFilter = null; @@ -190,6 +198,14 @@ public class TaskStack { mCb = cb; } + /** Resets this TaskStack. */ + public void reset() { + mCb = null; + mTaskList.reset(); + mGroups.clear(); + mAffinitiesGroups.clear(); + } + /** Adds a new task */ public void addTask(Task t) { mTaskList.add(t); 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 77a050ad3e884..46a5d8d67ba0e 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java @@ -65,7 +65,6 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV ArrayList mStacks; View mSearchBar; RecentsViewCallbacks mCb; - boolean mAlreadyLaunchingTask; public RecentsView(Context context) { super(context); @@ -121,7 +120,10 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV // Update the stack views that we are keeping for (int i = 0; i < numTaskStacksToKeep; i++) { - stackViews.get(i).setStack(stacks.get(i)); + TaskStackView tsv = stackViews.get(i); + // If onRecentsHidden is not triggered, we need to the stack view again here + tsv.reset(); + tsv.setStack(stacks.get(i)); } // Add remaining/recreate stack views @@ -144,8 +146,6 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV } } - // Reset the launched state - mAlreadyLaunchingTask = false; // Trigger a new layout requestLayout(); } @@ -402,11 +402,6 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV if (mCb != null) { mCb.onTaskViewClicked(); } - // Skip if we are already launching tasks - if (mAlreadyLaunchingTask) { - return; - } - mAlreadyLaunchingTask = true; // Upfront the processing of the thumbnail TaskViewTransform transform = new TaskViewTransform(); 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 57328795e079f..2623db3d918ce 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java @@ -132,21 +132,13 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal /** Sets the task stack */ void setStack(TaskStack stack) { - // Unset the old stack - if (mStack != null) { - mStack.setCallbacks(null); - - // Return all existing views to the pool - reset(); - // Layout again with the new stack - requestLayout(); - } - // Set the new stack mStack = stack; if (mStack != null) { mStack.setCallbacks(this); } + // Layout again with the new stack + requestLayout(); } /** Sets the debug overlay */ @@ -178,6 +170,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal } // Reset the stack state + mStack.reset(); mStackViewsDirty = true; mStackViewsClipDirty = true; mAwaitingFirstLayout = true; @@ -239,11 +232,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal float stackScroll, int[] visibleRangeOut, boolean boundTranslationsToRect) { - // XXX: We should be intelligent about where to look for the visible stack range using the - // current stack scroll. - // XXX: We should log extra cases like the ones below where we don't expect to hit very often - // XXX: Print out approximately how many indices we have to go through to find the first visible transform - int taskTransformCount = taskTransforms.size(); int taskCount = tasks.size(); int frontMostVisibleIndex = -1; @@ -295,20 +283,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal return frontMostVisibleIndex != -1 && backMostVisibleIndex != -1; } - /** - * Gets the stack transforms of a list of tasks, and returns the visible range of tasks. This - * call is less optimal than calling updateStackTransforms directly. - */ - private ArrayList getStackTransforms(ArrayList tasks, - float stackScroll, - int[] visibleRangeOut, - boolean boundTranslationsToRect) { - ArrayList taskTransforms = new ArrayList(); - updateStackTransforms(taskTransforms, tasks, stackScroll, visibleRangeOut, - boundTranslationsToRect); - return taskTransforms; - } - /** Synchronizes the views with the model */ boolean synchronizeStackViewsWithModel() { if (mStackViewsDirty) { @@ -440,8 +414,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal /** Updates the min and max virtual scroll bounds */ void updateMinMaxScroll(boolean boundScrollToNewMinMax, boolean launchedWithAltTab, boolean launchedFromHome) { - if (mStack == null) return; - // Compute the min and max scroll values mLayoutAlgorithm.computeMinMaxScroll(mStack.getTasks(), launchedWithAltTab, launchedFromHome); @@ -498,7 +470,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal } /** - * Ensures that there is a task focused, if nothign is focused, then we will use the task + * Ensures that there is a task focused, if nothing is focused, then we will use the task * at the center of the visible stack. */ public boolean ensureFocusedTask() { @@ -545,8 +517,11 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal /** Dismisses the focused task. */ public void dismissFocusedTask() { - // Return early if there is no focused task index - if (mFocusedTaskIndex < 0) return; + // Return early if the focused task index is invalid + if (mFocusedTaskIndex < 0 || mFocusedTaskIndex >= mStack.getTaskCount()) { + mFocusedTaskIndex = -1; + return; + } Task t = mStack.getTasks().get(mFocusedTaskIndex); TaskView tv = getChildViewForTask(t); @@ -567,8 +542,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal @Override public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); - if (mStack == null) return; - int childCount = getChildCount(); if (childCount > 0) { TaskView backMostTask = (TaskView) getChildAt(0); @@ -599,8 +572,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal @Override public void computeScroll() { - if (mStack == null) return; - mStackScroller.computeScroll(); // Synchronize the views synchronizeStackViewsWithModel(); @@ -643,11 +614,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - if (mStack == null) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - return; - } - int width = MeasureSpec.getSize(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); @@ -660,10 +626,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal // If this is the first layout, then scroll to the front of the stack and synchronize the // stack views immediately to load all the views if (mAwaitingFirstLayout) { - if (mStackScroller.setStackScrollToInitialState()) { - requestSynchronizeStackViewsWithModel(); - synchronizeStackViewsWithModel(); - } + mStackScroller.setStackScrollToInitialState(); + requestSynchronizeStackViewsWithModel(); + synchronizeStackViewsWithModel(); } // Measure each of the TaskViews @@ -694,11 +659,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal */ @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - if (mStack == null) { - super.onLayout(changed, left, top, right, bottom); - return; - } - // Layout each of the children int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { @@ -856,7 +816,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal /** Final callback after Recents is finally hidden. */ void onRecentsHidden() { - setStack(null); + reset(); } public boolean isTransformedTouchPointInView(float x, float y, View child) { @@ -1030,8 +990,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal @Override public void prepareViewToLeavePool(TaskView tv, Task task, boolean isNewView) { - if (mStack == null) return; - // It is possible for a view to be returned to the view pool before it is laid out, // which means that we will need to relayout the view when it is first used next. boolean requiresRelayout = tv.getWidth() <= 0 && !isNewView; @@ -1170,8 +1128,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal @Override public void onPackagesChanged(RecentsPackageMonitor monitor, String packageName, int userId) { - if (mStack == null) return; - // Compute which components need to be removed HashSet removedComponents = monitor.computeComponentsRemoved( mStack.getTaskKeys(), packageName, userId); 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 5767e18fbc439..26fbbf4c423e4 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java @@ -274,6 +274,7 @@ public class TaskStackViewLayoutAlgorithm { /** Returns the scroll to such task top = 1f; */ float getStackScrollForTask(Task t) { + if (!mTaskProgressMap.containsKey(t.key)) return 0f; return mTaskProgressMap.get(t.key); } 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 d42fa15617c47..de5974fb9fe9a 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java @@ -350,7 +350,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, public void run() { enableFocusAnimations(); } - }, (startDelay / 2)); + }, startDelay); } public void fadeInActionButton(int delay, int duration) { 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 1e5d9fc8a8156..464d0072d0adc 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java @@ -69,6 +69,7 @@ public class TaskViewHeader extends FrameLayout { RippleDrawable mBackground; GradientDrawable mBackgroundColorDrawable; AnimatorSet mFocusAnimator; + String mDismissContentDescription; // Static highlight that we draw at the top of each view static Paint sHighlightPaint; @@ -105,6 +106,8 @@ public class TaskViewHeader extends FrameLayout { Resources res = context.getResources(); mLightDismissDrawable = res.getDrawable(R.drawable.recents_dismiss_light); mDarkDismissDrawable = res.getDrawable(R.drawable.recents_dismiss_dark); + mDismissContentDescription = + res.getString(R.string.accessibility_recents_item_will_be_dismissed); // Configure the highlight paint if (sHighlightPaint == null) { @@ -127,14 +130,6 @@ public class TaskViewHeader extends FrameLayout { @Override protected void onFinishInflate() { - // Set the outline provider - setOutlineProvider(new ViewOutlineProvider() { - @Override - public void getOutline(View view, Outline outline) { - outline.setRect(0, 0, getMeasuredWidth(), getMeasuredHeight()); - } - }); - // Initialize the icon and description views mApplicationIcon = (ImageView) findViewById(R.id.application_icon); mActivityDescription = (TextView) findViewById(R.id.activity_description); @@ -217,9 +212,8 @@ public class TaskViewHeader extends FrameLayout { mConfig.taskBarViewLightTextColor : mConfig.taskBarViewDarkTextColor); mDismissButton.setImageDrawable(t.useLightOnPrimaryColor ? mLightDismissDrawable : mDarkDismissDrawable); - mDismissButton.setContentDescription( - getContext().getString(R.string.accessibility_recents_item_will_be_dismissed, - t.activityLabel)); + mDismissButton.setContentDescription(String.format(mDismissContentDescription, + t.activityLabel)); } /** Unbinds the bar view from the task */ @@ -307,7 +301,7 @@ public class TaskViewHeader extends FrameLayout { int currentColor = mBackgroundColor; int lightPrimaryColor = getSecondaryColor(mCurrentPrimaryColor, mCurrentPrimaryColorIsDark); ValueAnimator backgroundColor = ValueAnimator.ofObject(new ArgbEvaluator(), - lightPrimaryColor, currentColor); + currentColor, lightPrimaryColor); backgroundColor.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) {