diff options
14 files changed, 201 insertions, 115 deletions
diff --git a/packages/SystemUI/res/layout/recents_stack_action_button.xml b/packages/SystemUI/res/layout/recents_stack_action_button.xml index 625e9c111672..43b3de1a0244 100644 --- a/packages/SystemUI/res/layout/recents_stack_action_button.xml +++ b/packages/SystemUI/res/layout/recents_stack_action_button.xml @@ -32,4 +32,5 @@ android:shadowRadius="5" android:fontFamily="sans-serif-medium" android:background="?android:selectableItemBackground" - android:visibility="invisible" /> + android:visibility="invisible" + android:forceHasOverlappingRendering="false" /> diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java index 4d69280dfa22..a58e12e169dc 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java @@ -349,7 +349,7 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD loader.loadTasks(this, loadPlan, loadOpts); TaskStack stack = loadPlan.getTaskStack(); mRecentsView.onReload(mIsVisible, stack.getTaskCount() == 0); - mRecentsView.updateStack(stack); + mRecentsView.updateStack(stack, true /* setStackViewTasks */); // Update the nav bar scrim, but defer the animation until the enter-window event boolean animateNavBarScrim = !launchState.launchedViaDockGesture; @@ -455,13 +455,7 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD EventBus.getDefault().send(new ConfigurationChangedEvent(true /* fromMultiWindow */, false /* fromDeviceOrientationChange */, numStackTasks > 0)); - - if (mRecentsView != null) { - mRecentsView.updateStack(stack); - } - - EventBus.getDefault().send(new MultiWindowStateChangedEvent(isInMultiWindowMode, - numStackTasks > 0)); + EventBus.getDefault().send(new MultiWindowStateChangedEvent(isInMultiWindowMode, stack)); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java index 0413bc9fcc4e..e192da7bb547 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java @@ -771,8 +771,9 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener if (icon != null) { icon.setCallback(null); } - mHeaderBar.rebindToTask(toTask, false /* touchExplorationEnabled */, + mHeaderBar.bindToTask(toTask, false /* touchExplorationEnabled */, disabledInSafeMode); + mHeaderBar.onTaskDataLoaded(); mHeaderBar.setDimAlpha(toTransform.dimAlpha); mHeaderBar.draw(c); c.setBitmap(null); diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/MultiWindowStateChangedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/MultiWindowStateChangedEvent.java index cf2a68e2cf95..11649fbbb6a6 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/MultiWindowStateChangedEvent.java +++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/MultiWindowStateChangedEvent.java @@ -17,17 +17,18 @@ package com.android.systemui.recents.events.activity; import com.android.systemui.recents.events.EventBus; +import com.android.systemui.recents.model.TaskStack; /** * This is sent by the activity whenever the multi-window state has changed. */ -public class MultiWindowStateChangedEvent extends EventBus.Event { +public class MultiWindowStateChangedEvent extends EventBus.AnimatedEvent { public final boolean inMultiWindow; - public final boolean hasStackTasks; + public final TaskStack stack; - public MultiWindowStateChangedEvent(boolean inMultiWindow, boolean hasStackTasks) { + public MultiWindowStateChangedEvent(boolean inMultiWindow, TaskStack stack) { this.inMultiWindow = inMultiWindow; - this.hasStackTasks = hasStackTasks; + this.stack = stack; } } 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 82c81ae3e5d3..fb92971703d5 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java @@ -353,23 +353,15 @@ public class RecentsTaskLoader { /** * Acquires the task resource data directly from the cache, loading if necessary. - * - * @param fetchAndInvalidateThumbnails If set, will try loading thumbnails, invalidating them - * in the cache and loading if necessary. Otherwise, do not - * load the thumbnail unless the icon also has to be loaded. */ - public void loadTaskData(Task t, boolean fetchAndInvalidateThumbnails) { + public void loadTaskData(Task t) { Drawable icon = mIconCache.getAndInvalidateIfModified(t.key); Bitmap thumbnail = null; ActivityManager.TaskThumbnailInfo thumbnailInfo = null; - if (fetchAndInvalidateThumbnails) { - ThumbnailData thumbnailData = mThumbnailCache.getAndInvalidateIfModified(t.key); - if (thumbnailData != null) { - thumbnail = thumbnailData.thumbnail; - thumbnailInfo = thumbnailData.thumbnailInfo; - } - } else { - thumbnail = mDefaultThumbnail; + ThumbnailData thumbnailData = mThumbnailCache.getAndInvalidateIfModified(t.key); + if (thumbnailData != null) { + thumbnail = thumbnailData.thumbnail; + thumbnailInfo = thumbnailData.thumbnailInfo; } // Grab the thumbnail/icon from the cache, if either don't exist, then trigger a reload and 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 d55c7d80f0ee..6604cccdb93d 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java @@ -57,6 +57,7 @@ import com.android.systemui.recents.events.activity.DockedFirstAnimationFrameEve import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationCompletedEvent; import com.android.systemui.recents.events.activity.HideStackActionButtonEvent; import com.android.systemui.recents.events.activity.LaunchTaskEvent; +import com.android.systemui.recents.events.activity.MultiWindowStateChangedEvent; import com.android.systemui.recents.events.activity.ShowStackActionButtonEvent; import com.android.systemui.recents.events.ui.AllTaskViewsDismissedEvent; import com.android.systemui.recents.events.ui.DismissAllTaskViewsEvent; @@ -143,7 +144,6 @@ public class RecentsView extends FrameLayout { R.dimen.recents_task_view_rounded_corners_radius); mStackActionButton = (TextView) inflater.inflate(R.layout.recents_stack_action_button, this, false); - mStackActionButton.forceHasOverlappingRendering(false); mStackActionButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -203,9 +203,11 @@ public class RecentsView extends FrameLayout { /** * Called from RecentsActivity when the task stack is updated. */ - public void updateStack(TaskStack stack) { + public void updateStack(TaskStack stack, boolean setStackViewTasks) { mStack = stack; - mTaskStackView.setTasks(stack, true /* allowNotifyStackChanges */); + if (setStackViewTasks) { + mTaskStackView.setTasks(stack, true /* allowNotifyStackChanges */); + } // Update the top level view's visibilities if (stack.getTaskCount() > 0) { @@ -622,6 +624,10 @@ public class RecentsView extends FrameLayout { hideStackActionButton(HIDE_STACK_ACTION_BUTTON_DURATION, true /* translate */); } + public final void onBusEvent(MultiWindowStateChangedEvent event) { + updateStack(event.stack, false /* setStackViewTasks */); + } + /** * Shows the stack action button. */ diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java b/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java index dce235318733..06a2c1e4af78 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java @@ -146,7 +146,7 @@ public class SystemBarScrimViews { } public final void onBusEvent(MultiWindowStateChangedEvent event) { - animateScrimToCurrentNavBarState(event.hasStackTasks); + animateScrimToCurrentNavBarState(event.stack.getStackTaskCount() > 0); } /** diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java index 665d9ad94002..e79306f55e3d 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java @@ -485,7 +485,7 @@ public class TaskStackAnimationHelper { // Get the final set of task transforms mStackView.getLayoutTaskTransforms(newScroll, stackLayout.getFocusState(), stackTasks, - mTmpFinalTaskTransforms); + true /* ignoreTaskOverrides */, mTmpFinalTaskTransforms); // Focus the task view TaskView newFocusedTaskView = mStackView.getChildViewForTask(newFocusedTask); @@ -529,7 +529,7 @@ public class TaskStackAnimationHelper { int duration; Interpolator interpolator; if (willScrollToFront) { - duration = Math.max(100, 100 + ((i - 1) * 50)); + duration = calculateStaggeredAnimDuration(i); interpolator = FOCUS_BEHIND_NEXT_TASK_INTERPOLATOR; } else { if (i < newFocusTaskViewIndex) { @@ -553,4 +553,100 @@ public class TaskStackAnimationHelper { } return willScroll; } + + /** + * Starts the animation to go to the initial stack layout with a task focused. In addition, the + * previous task will be animated in after the scroll completes. + */ + public void startNewStackScrollAnimation(TaskStack newStack, + ReferenceCountedTrigger animationTrigger) { + TaskStackLayoutAlgorithm stackLayout = mStackView.getStackAlgorithm(); + TaskStackViewScroller stackScroller = mStackView.getScroller(); + + // Get the current set of task transforms + ArrayList<Task> stackTasks = newStack.getStackTasks(); + mStackView.getCurrentTaskTransforms(stackTasks, mTmpCurrentTaskTransforms); + + // Update the stack + mStackView.setTasks(newStack, false /* allowNotifyStackChanges */); + mStackView.updateLayoutAlgorithm(false /* boundScroll */); + + // Pick up the newly visible views after the scroll + final float newScroll = stackLayout.mInitialScrollP; + mStackView.bindVisibleTaskViews(newScroll); + + // Update the internal state + stackLayout.setFocusState(TaskStackLayoutAlgorithm.STATE_UNFOCUSED); + stackLayout.setTaskOverridesForInitialState(newStack, true /* ignoreScrollToFront */); + stackScroller.setStackScroll(newScroll); + mStackView.cancelDeferredTaskViewLayoutAnimation(); + + // Get the final set of task transforms + mStackView.getLayoutTaskTransforms(newScroll, stackLayout.getFocusState(), stackTasks, + false /* ignoreTaskOverrides */, mTmpFinalTaskTransforms); + + // Hide the front most task view until the scroll is complete + Task frontMostTask = newStack.getStackFrontMostTask(false /* includeFreeform */); + final TaskView frontMostTaskView = mStackView.getChildViewForTask(frontMostTask); + final TaskViewTransform frontMostTransform = mTmpFinalTaskTransforms.get( + stackTasks.indexOf(frontMostTask)); + if (frontMostTaskView != null) { + mStackView.updateTaskViewToTransform(frontMostTaskView, + stackLayout.getFrontOfStackTransform(), AnimationProps.IMMEDIATE); + } + + // Setup the end listener to return all the hidden views to the view pool after the + // focus animation + animationTrigger.addLastDecrementRunnable(new Runnable() { + @Override + public void run() { + mStackView.bindVisibleTaskViews(newScroll); + + // Now, animate in the front-most task + if (frontMostTaskView != null) { + mStackView.updateTaskViewToTransform(frontMostTaskView, frontMostTransform, + new AnimationProps(75, 200, FOCUS_BEHIND_NEXT_TASK_INTERPOLATOR)); + } + } + }); + + List<TaskView> taskViews = mStackView.getTaskViews(); + int taskViewCount = taskViews.size(); + for (int i = 0; i < taskViewCount; i++) { + TaskView tv = taskViews.get(i); + Task task = tv.getTask(); + + if (mStackView.isIgnoredTask(task)) { + continue; + } + if (task == frontMostTask && frontMostTaskView != null) { + continue; + } + + int taskIndex = stackTasks.indexOf(task); + TaskViewTransform fromTransform = mTmpCurrentTaskTransforms.get(taskIndex); + TaskViewTransform toTransform = mTmpFinalTaskTransforms.get(taskIndex); + + // Update the task to the initial state (for the newly picked up tasks) + mStackView.updateTaskViewToTransform(tv, fromTransform, AnimationProps.IMMEDIATE); + + int duration = calculateStaggeredAnimDuration(i); + Interpolator interpolator = FOCUS_BEHIND_NEXT_TASK_INTERPOLATOR; + + AnimationProps anim = new AnimationProps() + .setDuration(AnimationProps.BOUNDS, duration) + .setInterpolator(AnimationProps.BOUNDS, interpolator) + .setListener(animationTrigger.decrementOnAnimationEnd()); + animationTrigger.increment(); + mStackView.updateTaskViewToTransform(tv, toTransform, anim); + } + } + + /** + * Caclulates a staggered duration for {@link #startScrollToFocusedTaskAnimation} and + * {@link #startNewStackScrollAnimation}. + */ + private int calculateStaggeredAnimDuration(int i) { + return Math.max(100, 100 + ((i - 1) * 50)); + } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java index 34d6bcecdee6..57c2bc01e61f 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java @@ -577,7 +577,7 @@ public class TaskStackLayoutAlgorithm { /** * Creates task overrides to ensure the initial stack layout if necessary. */ - public void setTaskOverridesForInitialState(TaskStack stack) { + public void setTaskOverridesForInitialState(TaskStack stack, boolean ignoreScrollToFront) { RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState(); mTaskIndexOverrideMap.clear(); @@ -585,7 +585,7 @@ public class TaskStackLayoutAlgorithm { boolean scrollToFront = launchState.launchedFromHome || launchState.launchedViaDockGesture; if (getInitialFocusState() == STATE_UNFOCUSED && mNumStackTasks > 1) { - if (!launchState.launchedWithAltTab && !scrollToFront) { + if (ignoreScrollToFront || (!launchState.launchedWithAltTab && !scrollToFront)) { // Set the initial scroll to the predefined state (which differs from the stack) float [] initialNormX = new float[] { getNormalizedXFromUnfocusedY(mSystemInsets.bottom + mInitialBottomOffset, @@ -938,7 +938,11 @@ public class TaskStackLayoutAlgorithm { * stack. */ float getStackScrollForTask(Task t) { - return mTaskIndexOverrideMap.get(t.key.id, (float) mTaskIndexMap.get(t.key.id, 0)); + Float overrideP = mTaskIndexOverrideMap.get(t.key.id, null); + if (overrideP == null) { + return (float) mTaskIndexMap.get(t.key.id, 0); + } + return overrideP; } /** 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 a75d1e1339e2..068596bba54d 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java @@ -328,6 +328,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal */ public void setTasks(TaskStack stack, boolean allowNotifyStackChanges) { boolean isInitialized = mLayoutAlgorithm.isInitialized(); + // Only notify if we are already initialized, otherwise, everything will pick up all the // new and old tasks when we next layout mStack.setTasks(getContext(), stack.computeAllTasksList(), @@ -344,7 +345,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal */ public void updateToInitialState() { mStackScroller.setStackScrollToInitialState(); - mLayoutAlgorithm.setTaskOverridesForInitialState(mStack); + mLayoutAlgorithm.setTaskOverridesForInitialState(mStack, false /* ignoreScrollToFront */); } /** Updates the list of task views */ @@ -508,11 +509,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal * Binds the visible {@link TaskView}s at the given target scroll. */ void bindVisibleTaskViews(float targetStackScroll) { - bindVisibleTaskViews(targetStackScroll, mIgnoreTasks, false /* ignoreTaskOverrides */); - } - - void bindVisibleTaskViews(float targetStackScroll, boolean ignoreTaskOverrides) { - bindVisibleTaskViews(targetStackScroll, mIgnoreTasks, ignoreTaskOverrides); + bindVisibleTaskViews(targetStackScroll, false /* ignoreTaskOverrides */); } /** @@ -525,17 +522,14 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal * @param targetStackScroll If provided, will ensure that the set of visible {@link TaskView}s * includes those visible at the current stack scroll, and all at the * target stack scroll. - * @param ignoreTasksSet The set of tasks to ignore in this rebinding of the visible - * {@link TaskView}s * @param ignoreTaskOverrides If set, the visible task computation will get the transforms for * tasks at their non-overridden task progress */ - void bindVisibleTaskViews(float targetStackScroll, ArraySet<Task.TaskKey> ignoreTasksSet, - boolean ignoreTaskOverrides) { + void bindVisibleTaskViews(float targetStackScroll, boolean ignoreTaskOverrides) { // Get all the task transforms ArrayList<Task> tasks = mStack.getStackTasks(); int[] visibleTaskRange = computeVisibleTaskTransforms(mCurrentTaskTransforms, tasks, - mStackScroller.getStackScroll(), targetStackScroll, ignoreTasksSet, + mStackScroller.getStackScroll(), targetStackScroll, mIgnoreTasks, ignoreTaskOverrides); // Return all the invisible children to the pool @@ -548,7 +542,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal Task task = tv.getTask(); // Skip ignored tasks - if (ignoreTasksSet.contains(task.key)) { + if (mIgnoreTasks.contains(task.key)) { continue; } @@ -578,7 +572,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal TaskViewTransform transform = mCurrentTaskTransforms.get(i); // Skip ignored tasks - if (ignoreTasksSet.contains(task.key)) { + if (mIgnoreTasks.contains(task.key)) { continue; } @@ -626,10 +620,10 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal } /** - * @see #relayoutTaskViews(AnimationProps, ArraySet<Task.TaskKey>, boolean) + * @see #relayoutTaskViews(AnimationProps, boolean) */ public void relayoutTaskViews(AnimationProps animation) { - relayoutTaskViews(animation, mIgnoreTasks, false /* ignoreTaskOverrides */); + relayoutTaskViews(animation, false /* ignoreTaskOverrides */); } /** @@ -637,16 +631,13 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal * {@link TaskStackLayoutAlgorithm} with the given {@param animation}. This call cancels any * animations that are current running on those task views, and will ensure that the children * {@link TaskView}s will match the set of visible tasks in the stack. - * - * @param ignoreTasksSet the set of tasks to ignore in the relayout */ - private void relayoutTaskViews(AnimationProps animation, ArraySet<Task.TaskKey> ignoreTasksSet, - boolean ignoreTaskOverrides) { + private void relayoutTaskViews(AnimationProps animation, boolean ignoreTaskOverrides) { // If we had a deferred animation, cancel that mDeferredTaskViewLayoutAnimation = null; // Synchronize the current set of TaskViews - bindVisibleTaskViews(mStackScroller.getStackScroll(), ignoreTasksSet, + bindVisibleTaskViews(mStackScroller.getStackScroll(), ignoreTaskOverrides /* ignoreTaskOverrides */); // Animate them to their final transforms with the given animation @@ -657,7 +648,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal int taskIndex = mStack.indexOfStackTask(tv.getTask()); TaskViewTransform transform = mCurrentTaskTransforms.get(taskIndex); - if (ignoreTasksSet.contains(tv.getTask().key)) { + if (mIgnoreTasks.contains(tv.getTask().key)) { continue; } @@ -715,13 +706,13 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal * {@param stackScroll} and {@param focusState}. */ public void getLayoutTaskTransforms(float stackScroll, int focusState, ArrayList<Task> tasks, - ArrayList<TaskViewTransform> transformsOut) { + boolean ignoreTaskOverrides, ArrayList<TaskViewTransform> transformsOut) { Utilities.matchTaskListSize(tasks, transformsOut); for (int i = tasks.size() - 1; i >= 0; i--) { Task task = tasks.get(i); TaskViewTransform transform = transformsOut.get(i); mLayoutAlgorithm.getStackTransform(task, stackScroll, focusState, transform, null, - true /* forceUpdate */, true /* ignoreTaskOverrides */); + true /* forceUpdate */, ignoreTaskOverrides); transform.visible = true; } } @@ -812,22 +803,10 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal /** * Updates the layout algorithm min and max virtual scroll bounds. - * - * @see #updateLayoutAlgorithm(boolean, ArraySet<Task.TaskKey>) */ public void updateLayoutAlgorithm(boolean boundScrollToNewMinMax) { - updateLayoutAlgorithm(boundScrollToNewMinMax, mIgnoreTasks); - } - - /** - * Updates the min and max virtual scroll bounds. - * - * @param ignoreTasksSet the set of tasks to ignore in the relayout - */ - private void updateLayoutAlgorithm(boolean boundScrollToNewMinMax, - ArraySet<Task.TaskKey> ignoreTasksSet) { // Compute the min and max scroll values - mLayoutAlgorithm.update(mStack, ignoreTasksSet); + mLayoutAlgorithm.update(mStack, mIgnoreTasks); // Update the freeform workspace background SystemServicesProxy ssp = Recents.getSystemServices(); @@ -1195,8 +1174,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal } // Rebind all the views, including the ignore ones - bindVisibleTaskViews(mStackScroller.getStackScroll(), mIgnoreTasks, - false /* ignoreTaskOverrides */); + bindVisibleTaskViews(mStackScroller.getStackScroll(), false /* ignoreTaskOverrides */); // Measure each of the TaskViews mTmpTaskViews.clear(); @@ -1553,7 +1531,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal tv.onTaskBound(task); // Load the task data - Recents.getTaskLoader().loadTaskData(task, true /* fetchAndInvalidateThumbnails */); + Recents.getTaskLoader().loadTaskData(task); } private void unbindTaskView(TaskView tv, Task task) { @@ -1834,7 +1812,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal updateLayoutAlgorithm(true /* boundScroll */); addIgnoreTask(event.task); } - relayoutTaskViews(animation, mIgnoreTasks, ignoreTaskOverrides); + relayoutTaskViews(animation, ignoreTaskOverrides); } public final void onBusEvent(final DragEndEvent event) { @@ -1948,26 +1926,24 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal } } - public final void onBusEvent(MultiWindowStateChangedEvent event) { - if (!event.inMultiWindow) { + public final void onBusEvent(final MultiWindowStateChangedEvent event) { + if (event.inMultiWindow) { + setTasks(event.stack, true /* allowNotifyStackChanges */); + } else { + // Reset the launch state before handling the multiwindow change + RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState(); + launchState.reset(); + // Defer until the next frame to ensure that we have received all the system insets, and // initial layout updates + event.getAnimationTrigger().increment(); post(new Runnable() { @Override public void run() { // Scroll the stack to the front to see the undocked task - mStackScroller.animateScroll(mLayoutAlgorithm.mMaxScrollP, new Runnable() { - @Override - public void run() { - List<TaskView> taskViews = getTaskViews(); - int taskViewCount = taskViews.size(); - for (int i = 0; i < taskViewCount; i++) { - TaskView tv = taskViews.get(i); - tv.getHeaderView().rebindToTask(tv.getTask(), - tv.mTouchExplorationEnabled, tv.mIsDisabledInSafeMode); - } - } - }); + mAnimationHelper.startNewStackScrollAnimation(event.stack, + event.getAnimationTrigger()); + event.getAnimationTrigger().decrement(); } }); } 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 3cdb1fb27854..4441ddcca777 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java @@ -483,7 +483,7 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback { // Get the final set of task transforms (with task removed) mSv.getLayoutTaskTransforms(newStackScroll, TaskStackLayoutAlgorithm.STATE_UNFOCUSED, - mCurrentTasks, mFinalTaskTransforms); + mCurrentTasks, true /* ignoreTaskOverrides */, mFinalTaskTransforms); // Set the target to scroll towards upon dismissal mTargetStackScroll = newStackScroll; 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 37f5a9fc9974..7ea70b587fd7 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java @@ -24,13 +24,9 @@ import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.app.ActivityManager; import android.content.Context; -import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Outline; -import android.graphics.Paint; import android.graphics.Point; -import android.graphics.PorterDuff; -import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; import android.util.AttributeSet; import android.util.FloatProperty; @@ -607,6 +603,8 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks mTask = t; mTask.addCallback(this); mIsDisabledInSafeMode = !mTask.isSystemApp && ssp.isInSafeMode(); + mThumbnailView.bindToTask(mTask, mIsDisabledInSafeMode); + mHeaderView.bindToTask(mTask, mTouchExplorationEnabled, mIsDisabledInSafeMode); if (!t.isDockable && ssp.hasDockedTask()) { if (mIncompatibleAppToastView == null) { @@ -623,15 +621,15 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks @Override public void onTaskDataLoaded(Task task, ActivityManager.TaskThumbnailInfo thumbnailInfo) { - // Bind each of the views to the new task data - mThumbnailView.rebindToTask(mTask, thumbnailInfo, mIsDisabledInSafeMode); - mHeaderView.rebindToTask(mTask, mTouchExplorationEnabled, mIsDisabledInSafeMode); + // Update each of the views to the new task data + mThumbnailView.onTaskDataLoaded(thumbnailInfo); + mHeaderView.onTaskDataLoaded(); mTaskDataLoaded = true; } @Override public void onTaskDataUnloaded() { - // Unbind each of the views from the task data and remove the task callback + // Unbind each of the views from the task and remove the task callback mTask.removeCallback(this); mThumbnailView.unbindFromTask(); mHeaderView.unbindFromTask(mTouchExplorationEnabled); @@ -640,7 +638,9 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks @Override public void onTaskStackIdChanged() { - mHeaderView.rebindToTask(mTask, mTouchExplorationEnabled, mIsDisabledInSafeMode); + // Force rebind the header, the thumbnail does not change due to stack changes + mHeaderView.bindToTask(mTask, mTouchExplorationEnabled, mIsDisabledInSafeMode); + mHeaderView.onTaskDataLoaded(); } /**** View.OnClickListener Implementation ****/ 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 fb0fc3076f30..aac6d13706a7 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java @@ -438,21 +438,18 @@ public class TaskViewHeader extends FrameLayout } } - /** Binds the bar view to the task */ - public void rebindToTask(Task t, boolean touchExplorationEnabled, boolean disabledInSafeMode) { + /** + * Binds the bar view to the task. + */ + public void bindToTask(Task t, boolean touchExplorationEnabled, boolean disabledInSafeMode) { mTask = 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 int primaryColor = disabledInSafeMode ? mDisabledTaskBarBackgroundColor : t.colorPrimary; if (mBackground.getColor() != primaryColor) { updateBackgroundColor(primaryColor, mDimAlpha); } - if (t.icon != null) { - mIconView.setImageDrawable(t.icon); - } if (!mTitleView.getText().toString().equals(t.title)) { mTitleView.setText(t.title); } @@ -497,6 +494,16 @@ public class TaskViewHeader extends FrameLayout } } + /** + * Called when the bound task's data has loaded and this view should update to reflect the + * changes. + */ + public void onTaskDataLoaded() { + if (mTask.icon != null) { + mIconView.setImageDrawable(mTask.icon); + } + } + /** Unbinds the bar view from the task */ void unbindFromTask(boolean touchExplorationEnabled) { mTask = null; 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 4de7713eb2fb..8977f504209f 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java @@ -302,21 +302,29 @@ public class TaskViewThumbnail extends View { updateThumbnailPaintFilter(); } - /** Binds the thumbnail view to the task */ - void rebindToTask(Task t, ActivityManager.TaskThumbnailInfo thumbnailInfo, - boolean disabledInSafeMode) { + /** + * Binds the thumbnail view to the task. + */ + void bindToTask(Task t, boolean disabledInSafeMode) { mTask = t; mDisabledInSafeMode = disabledInSafeMode; - if (t.thumbnail != null) { - setThumbnail(t.thumbnail, thumbnailInfo); - } else { - setThumbnail(null, null); - } if (t.colorBackground != 0) { mBgFillPaint.setColor(t.colorBackground); } } + /** + * Called when the bound task's data has loaded and this view should update to reflect the + * changes. + */ + void onTaskDataLoaded(ActivityManager.TaskThumbnailInfo thumbnailInfo) { + if (mTask.thumbnail != null) { + setThumbnail(mTask.thumbnail, thumbnailInfo); + } else { + setThumbnail(null, null); + } + } + /** Unbinds the thumbnail view from the task */ void unbindFromTask() { mTask = null; |