From 3b6ba1ab144c53752841869627a1b9f6d357c404 Mon Sep 17 00:00:00 2001 From: Winson Date: Tue, 22 Mar 2016 15:37:54 -0700 Subject: [PATCH 1/4] Adding clear-all button. Change-Id: Ife637438b191c4a5004f3c6551bc75691e8e426b --- .../layout/recents_stack_action_button.xml | 2 - packages/SystemUI/res/values/config.xml | 3 + packages/SystemUI/res/values/dimens.xml | 4 +- .../com/android/systemui/Interpolators.java | 2 + .../systemui/recents/RecentsDebugFlags.java | 2 +- .../events/ui/DismissAllTaskViewsEvent.java | 27 +++++++ .../events/ui/DismissTaskViewEvent.java | 5 +- .../systemui/recents/model/TaskStack.java | 21 +++++ .../tv/views/TaskStackHorizontalGridView.java | 5 ++ .../systemui/recents/views/RecentsView.java | 27 +++++-- .../recents/views/SystemBarScrimViews.java | 11 +++ .../views/TaskStackAnimationHelper.java | 66 ++++++++++++---- .../views/TaskStackLayoutAlgorithm.java | 10 ++- .../systemui/recents/views/TaskStackView.java | 77 ++++++++++++++----- .../views/TaskStackViewTouchHandler.java | 9 ++- .../systemui/recents/views/TaskView.java | 2 +- proto/src/metrics_constants.proto | 3 + 17 files changed, 222 insertions(+), 54 deletions(-) create mode 100644 packages/SystemUI/src/com/android/systemui/recents/events/ui/DismissAllTaskViewsEvent.java diff --git a/packages/SystemUI/res/layout/recents_stack_action_button.xml b/packages/SystemUI/res/layout/recents_stack_action_button.xml index 87832616f7107..2b2ce4e534833 100644 --- a/packages/SystemUI/res/layout/recents_stack_action_button.xml +++ b/packages/SystemUI/res/layout/recents_stack_action_button.xml @@ -27,8 +27,6 @@ android:textSize="14sp" android:textColor="#FFFFFF" android:textAllCaps="true" - android:drawableStart="@drawable/ic_history" - android:drawablePadding="6dp" android:shadowColor="#99000000" android:shadowDx="0" android:shadowDy="2" diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 622ae717058c7..fd051b1b371fa 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -153,6 +153,9 @@ 175 + + 300 + 200 diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index d1faa4a55d969..c094da9db43ae 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -574,10 +574,12 @@ 16dp 16dp 48dp + 16dp 64dp + 16dp - 56dp + 48dp 56dp diff --git a/packages/SystemUI/src/com/android/systemui/Interpolators.java b/packages/SystemUI/src/com/android/systemui/Interpolators.java index 5e33a9f84cacb..17f4dab93bf47 100644 --- a/packages/SystemUI/src/com/android/systemui/Interpolators.java +++ b/packages/SystemUI/src/com/android/systemui/Interpolators.java @@ -17,6 +17,7 @@ package com.android.systemui; import android.view.animation.AccelerateDecelerateInterpolator; +import android.view.animation.AccelerateInterpolator; import android.view.animation.DecelerateInterpolator; import android.view.animation.Interpolator; import android.view.animation.LinearInterpolator; @@ -32,6 +33,7 @@ public class Interpolators { public static final Interpolator ALPHA_IN = new PathInterpolator(0.4f, 0f, 1f, 1f); public static final Interpolator ALPHA_OUT = new PathInterpolator(0f, 0f, 0.8f, 1f); public static final Interpolator LINEAR = new LinearInterpolator(); + public static final Interpolator ACCELERATE = new AccelerateInterpolator(); public static final Interpolator ACCELERATE_DECELERATE = new AccelerateDecelerateInterpolator(); public static final Interpolator DECELERATE_QUINT = new DecelerateInterpolator(2.5f); diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java index 043510ed72ca3..171535691bbc9 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java @@ -36,7 +36,7 @@ public class RecentsDebugFlags implements TunerService.Tunable { // Enables the task affiliations public static final boolean EnableAffiliatedTaskGroups = false; // TODO: To be repurposed - public static final boolean EnableStackActionButton = false; + public static final boolean EnableStackActionButton = true; // Overrides the Tuner flags and enables the timeout private static final boolean EnableFastToggleTimeout = false; // Overrides the Tuner flags and enables the paging via the Recents button diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/DismissAllTaskViewsEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/DismissAllTaskViewsEvent.java new file mode 100644 index 0000000000000..f8b59c7c62f76 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/recents/events/ui/DismissAllTaskViewsEvent.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2016 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.events.ui; + +import com.android.systemui.recents.events.EventBus; +import com.android.systemui.recents.views.TaskView; + +/** + * This event is sent to request that all the {@link TaskView}s are dismissed. + */ +public class DismissAllTaskViewsEvent extends EventBus.AnimatedEvent { + // Simple event +} diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/DismissTaskViewEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/DismissTaskViewEvent.java index 1165f4e768618..1f8c6443502f3 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/events/ui/DismissTaskViewEvent.java +++ b/packages/SystemUI/src/com/android/systemui/recents/events/ui/DismissTaskViewEvent.java @@ -17,7 +17,6 @@ package com.android.systemui.recents.events.ui; import com.android.systemui.recents.events.EventBus; -import com.android.systemui.recents.model.Task; import com.android.systemui.recents.views.TaskView; /** @@ -26,10 +25,8 @@ import com.android.systemui.recents.views.TaskView; public class DismissTaskViewEvent extends EventBus.AnimatedEvent { public final TaskView taskView; - public final Task task; - public DismissTaskViewEvent(TaskView taskView, Task task) { + public DismissTaskViewEvent(TaskView taskView) { this.taskView = taskView; - this.task = task; } } 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 5a2507debd7e1..df3f56c7c3acc 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java @@ -221,6 +221,11 @@ public class TaskStack { void onStackTaskRemoved(TaskStack stack, Task removedTask, boolean wasFrontMostTask, Task newFrontMostTask, AnimationProps animation, boolean fromDockGesture); + /** + * Notifies when all tasks have been removed from the stack. + */ + void onStackTasksRemoved(TaskStack stack); + /** * Notifies when tasks in the stack have been updated. */ @@ -509,6 +514,22 @@ public class TaskStack { mRawTaskList.remove(t); } + /** + * Removes all tasks from the stack. + */ + public void removeAllTasks() { + ArrayList tasks = mStackTaskList.getTasks(); + for (int i = tasks.size() - 1; i >= 0; i--) { + Task t = tasks.get(i); + removeTaskImpl(mStackTaskList, t); + mRawTaskList.remove(t); + } + if (mCb != null) { + // Notify that all tasks have been removed + mCb.onStackTasksRemoved(this); + } + } + /** * Sets a few tasks in one go, without calling any callbacks. * diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java index 3d0e75a8ef700..5eb9fda98d937 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java @@ -157,6 +157,11 @@ public class TaskStackHorizontalGridView extends HorizontalGridView implements T } } + @Override + public void onStackTasksRemoved(TaskStack stack) { + // Do nothing + } + @Override public void onStackTasksUpdated(TaskStack stack) { // Do nothing 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 b23b01f933200..e9ce6372e934e 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java @@ -58,6 +58,9 @@ import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationC import com.android.systemui.recents.events.activity.HideStackActionButtonEvent; import com.android.systemui.recents.events.activity.LaunchTaskEvent; import com.android.systemui.recents.events.activity.ShowStackActionButtonEvent; +import com.android.systemui.recents.events.ui.AllTaskViewsDismissedEvent; +import com.android.systemui.recents.events.ui.DeleteTaskDataEvent; +import com.android.systemui.recents.events.ui.DismissAllTaskViewsEvent; import com.android.systemui.recents.events.ui.DraggingInRecentsEndedEvent; import com.android.systemui.recents.events.ui.DraggingInRecentsEvent; import com.android.systemui.recents.events.ui.ResetBackgroundScrimEvent; @@ -87,6 +90,9 @@ public class RecentsView extends FrameLayout { private static final int DEFAULT_UPDATE_SCRIM_DURATION = 200; private static final float DEFAULT_SCRIM_ALPHA = 0.33f; + private static final int SHOW_STACK_ACTION_BUTTON_DURATION = 150; + private static final int HIDE_STACK_ACTION_BUTTON_DURATION = 100; + private TaskStack mStack; private TaskStackView mTaskStackView; private TextView mStackActionButton; @@ -135,10 +141,11 @@ 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) { - // TODO: To be implemented + EventBus.getDefault().send(new DismissAllTaskViewsEvent()); } }); addView(mStackActionButton); @@ -579,12 +586,24 @@ public class RecentsView extends FrameLayout { animateBackgroundScrim(DEFAULT_SCRIM_ALPHA, DEFAULT_UPDATE_SCRIM_DURATION); } + public final void onBusEvent(AllTaskViewsDismissedEvent event) { + hideStackActionButton(HIDE_STACK_ACTION_BUTTON_DURATION, true /* translate */); + } + + public final void onBusEvent(DismissAllTaskViewsEvent event) { + SystemServicesProxy ssp = Recents.getSystemServices(); + if (!ssp.hasDockedTask()) { + // Animate the background away only if we are dismissing Recents to home + animateBackgroundScrim(0f, DEFAULT_UPDATE_SCRIM_DURATION); + } + } + public final void onBusEvent(ShowStackActionButtonEvent event) { if (!RecentsDebugFlags.Static.EnableStackActionButton) { return; } - showStackActionButton(150, event.translate); + showStackActionButton(SHOW_STACK_ACTION_BUTTON_DURATION, event.translate); } public final void onBusEvent(HideStackActionButtonEvent event) { @@ -592,7 +611,7 @@ public class RecentsView extends FrameLayout { return; } - hideStackActionButton(100, true /* translate */); + hideStackActionButton(HIDE_STACK_ACTION_BUTTON_DURATION, true /* translate */); } /** @@ -623,7 +642,6 @@ public class RecentsView extends FrameLayout { .alpha(1f) .setDuration(duration) .setInterpolator(Interpolators.FAST_OUT_SLOW_IN) - .withLayer() .start(); } }); @@ -669,7 +687,6 @@ public class RecentsView extends FrameLayout { postAnimationTrigger.decrement(); } }) - .withLayer() .start(); postAnimationTrigger.increment(); } 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 9c8189a216bd9..13ad9a5ee90d8 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java @@ -24,6 +24,7 @@ import com.android.systemui.Interpolators; import com.android.systemui.R; import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted; import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationCompletedEvent; +import com.android.systemui.recents.events.ui.DismissAllTaskViewsEvent; /** Manages the scrims for the various system bars. */ public class SystemBarScrimViews { @@ -107,4 +108,14 @@ public class SystemBarScrimViews { animateNavBarScrimVisibility(false, animation); } } + + public final void onBusEvent(DismissAllTaskViewsEvent event) { + if (mHasNavBarScrim) { + AnimationProps animation = new AnimationProps() + .setDuration(AnimationProps.BOUNDS, + TaskStackAnimationHelper.EXIT_TO_HOME_TRANSLATION_DURATION) + .setInterpolator(AnimationProps.BOUNDS, Interpolators.FAST_OUT_SLOW_IN); + animateNavBarScrimVisibility(false, animation); + } + } } 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 8db81f73f700e..1c433d8eb31c2 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java @@ -31,6 +31,7 @@ import com.android.systemui.recents.Recents; import com.android.systemui.recents.RecentsActivityLaunchState; import com.android.systemui.recents.RecentsConfiguration; import com.android.systemui.recents.misc.ReferenceCountedTrigger; +import com.android.systemui.recents.misc.Utilities; import com.android.systemui.recents.model.Task; import com.android.systemui.recents.model.TaskStack; @@ -277,7 +278,6 @@ public class TaskStackAnimationHelper { public void startExitToHomeAnimation(boolean animated, ReferenceCountedTrigger postAnimationTrigger) { TaskStackLayoutAlgorithm stackLayout = mStackView.getStackAlgorithm(); - TaskStackViewScroller stackScroller = mStackView.getScroller(); TaskStack stack = mStackView.getStack(); // Break early if there are no tasks @@ -313,8 +313,7 @@ public class TaskStackAnimationHelper { taskAnimation = AnimationProps.IMMEDIATE; } - stackLayout.getStackTransform(task, stackScroller.getStackScroll(), mTmpTransform, - null); + mTmpTransform.fillIn(tv); mTmpTransform.alpha = 0f; mTmpTransform.rect.offset(0, offscreenYOffset); mStackView.updateTaskViewToTransform(tv, mTmpTransform, taskAnimation); @@ -328,8 +327,6 @@ public class TaskStackAnimationHelper { public void startLaunchTaskAnimation(TaskView launchingTaskView, boolean screenPinningRequested, final ReferenceCountedTrigger postAnimationTrigger) { Resources res = mStackView.getResources(); - TaskStackLayoutAlgorithm stackLayout = mStackView.getStackAlgorithm(); - TaskStackViewScroller stackScroller = mStackView.getScroller(); int taskViewExitToAppDuration = res.getInteger( R.integer.recents_task_exit_to_app_duration); @@ -362,8 +359,7 @@ public class TaskStackAnimationHelper { postAnimationTrigger.decrementOnAnimationEnd()); postAnimationTrigger.increment(); - stackLayout.getStackTransform(task, stackScroller.getStackScroll(), mTmpTransform, - null); + mTmpTransform.fillIn(tv); mTmpTransform.alpha = 0f; mTmpTransform.rect.offset(0, taskViewAffiliateGroupEnterOffset); mStackView.updateTaskViewToTransform(tv, mTmpTransform, taskAnimation); @@ -374,16 +370,14 @@ public class TaskStackAnimationHelper { /** * Starts the delete animation for the specified {@link TaskView}. */ - public void startDeleteTaskAnimation(Task deleteTask, final TaskView deleteTaskView, + public void startDeleteTaskAnimation(final TaskView deleteTaskView, final ReferenceCountedTrigger postAnimationTrigger) { Resources res = mStackView.getResources(); TaskStackLayoutAlgorithm stackLayout = mStackView.getStackAlgorithm(); - TaskStackViewScroller stackScroller = mStackView.getScroller(); int taskViewRemoveAnimDuration = res.getInteger( R.integer.recents_animate_task_view_remove_duration); - int taskViewRemoveAnimTranslationXPx = res.getDimensionPixelSize( - R.dimen.recents_task_view_remove_anim_translation_x); + int offscreenXOffset = mStackView.getMeasuredWidth() - stackLayout.mTaskRect.left; // Disabling clipping with the stack while the view is animating away, this will get // restored when the task is next picked up from the view pool @@ -399,13 +393,57 @@ public class TaskStackAnimationHelper { }); postAnimationTrigger.increment(); - stackLayout.getStackTransform(deleteTask, stackScroller.getStackScroll(), mTmpTransform, - null); + mTmpTransform.fillIn(deleteTaskView); mTmpTransform.alpha = 0f; - mTmpTransform.rect.offset(taskViewRemoveAnimTranslationXPx, 0); + mTmpTransform.rect.offset(offscreenXOffset, 0); mStackView.updateTaskViewToTransform(deleteTaskView, mTmpTransform, taskAnimation); } + /** + * Starts the delete animation for all the {@link TaskView}s. + */ + public void startDeleteAllTasksAnimation(final List taskViews, + final ReferenceCountedTrigger postAnimationTrigger) { + Resources res = mStackView.getResources(); + TaskStackLayoutAlgorithm stackLayout = mStackView.getStackAlgorithm(); + + int taskViewRemoveAnimDuration = res.getInteger( + R.integer.recents_animate_task_views_remove_all_duration); + int offscreenXOffset = mStackView.getMeasuredWidth() - stackLayout.mTaskRect.left; + + int taskViewCount = taskViews.size(); + int startDelayMax = 125; + + for (int i = taskViewCount - 1; i >= 0; i--) { + TaskView tv = taskViews.get(i); + int indexFromFront = taskViewCount - i - 1; + float x = Interpolators.ACCELERATE.getInterpolation((float) indexFromFront / + taskViewCount); + int startDelay = (int) Utilities.mapRange(x, 0, startDelayMax); + + // Disabling clipping with the stack while the view is animating away + tv.setClipViewInStack(false); + + // Compose the new animation and transform and star the animation + AnimationProps taskAnimation = new AnimationProps(startDelay, + taskViewRemoveAnimDuration, Interpolators.FAST_OUT_LINEAR_IN, + new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + postAnimationTrigger.decrement(); + + // Re-enable clipping with the stack (we will reuse this view) + tv.setClipViewInStack(true); + } + }); + postAnimationTrigger.increment(); + + mTmpTransform.fillIn(tv); + mTmpTransform.rect.offset(offscreenXOffset, 0); + mStackView.updateTaskViewToTransform(tv, mTmpTransform, taskAnimation); + } + } + /** * Starts the animation to focus the next {@link TaskView} when paging through recents. * 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 4b1faf3ef3959..25083040df1d8 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java @@ -557,15 +557,17 @@ public class TaskStackLayoutAlgorithm { mInitialScrollP = Utilities.clamp(launchTaskIndex, mMinScrollP, mMaxScrollP); mInitialNormX = null; } else { - float normX = getNormalizedXFromUnfocusedY(mInitialTopOffset, FROM_TOP); - mInitialScrollP = Math.max(mMinScrollP, Math.min(mMaxScrollP, (mNumStackTasks - 2)) - - Math.max(0, mUnfocusedRange.getAbsoluteX(normX))); + // We are overriding the initial two task positions, so set the initial scroll + // position to match the second task (aka focused task) position + float initialTopNormX = getNormalizedXFromUnfocusedY(mInitialTopOffset, FROM_TOP); + mInitialScrollP = Math.max(mMinScrollP, Math.min(mMaxScrollP, (mNumStackTasks - 2)) + - Math.max(0, mUnfocusedRange.getAbsoluteX(initialTopNormX))); // Set the initial scroll to the predefined state (which differs from the stack) mInitialNormX = new float[] { getNormalizedXFromUnfocusedY(mSystemInsets.bottom + mInitialBottomOffset, FROM_BOTTOM), - normX + initialTopNormX }; } } 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 04f153fb79961..58998c645a223 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java @@ -72,6 +72,7 @@ import com.android.systemui.recents.events.activity.PackagesChangedEvent; import com.android.systemui.recents.events.activity.ShowStackActionButtonEvent; import com.android.systemui.recents.events.ui.AllTaskViewsDismissedEvent; import com.android.systemui.recents.events.ui.DeleteTaskDataEvent; +import com.android.systemui.recents.events.ui.DismissAllTaskViewsEvent; import com.android.systemui.recents.events.ui.DismissTaskViewEvent; import com.android.systemui.recents.events.ui.TaskViewDismissedEvent; import com.android.systemui.recents.events.ui.UpdateFreeformTaskViewVisibilityEvent; @@ -1322,7 +1323,8 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal } // Update the stack action button visibility - if (mStackScroller.getStackScroll() < SHOW_STACK_ACTION_BUTTON_SCROLL_THRESHOLD) { + if (mStackScroller.getStackScroll() < SHOW_STACK_ACTION_BUTTON_SCROLL_THRESHOLD && + mStack.getTaskCount() > 0) { EventBus.getDefault().send(new ShowStackActionButtonEvent(false /* translate */)); } else { EventBus.getDefault().send(new HideStackActionButtonEvent()); @@ -1446,6 +1448,26 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal } } + @Override + public void onStackTasksRemoved(TaskStack stack) { + // Reset the focused task + resetFocusedTask(getFocusedTask()); + + // Return all the views to the pool + List taskViews = new ArrayList<>(); + taskViews.addAll(getTaskViews()); + for (int i = taskViews.size() - 1; i >= 0; i--) { + mViewPool.returnViewToPool(taskViews.get(i)); + } + + // Remove all the ignore tasks + mIgnoreTasks.clear(); + + // If there are no remaining tasks, then just close recents + EventBus.getDefault().send(new AllTaskViewsDismissedEvent( + R.string.recents_empty_message_dismissed_all)); + } + @Override public void onStackTasksUpdated(TaskStack stack) { // Update the layout and immediately layout @@ -1597,7 +1619,8 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal if (mEnterAnimationComplete) { if (prevScroll > SHOW_STACK_ACTION_BUTTON_SCROLL_THRESHOLD && - curScroll <= SHOW_STACK_ACTION_BUTTON_SCROLL_THRESHOLD) { + curScroll <= SHOW_STACK_ACTION_BUTTON_SCROLL_THRESHOLD && + mStack.getTaskCount() > 0) { EventBus.getDefault().send(new ShowStackActionButtonEvent(true /* translate */)); } else if (prevScroll < HIDE_STACK_ACTION_BUTTON_SCROLL_THRESHOLD && curScroll >= HIDE_STACK_ACTION_BUTTON_SCROLL_THRESHOLD) { @@ -1705,14 +1728,42 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal } } - public final void onBusEvent(final DismissTaskViewEvent event) { + public final void onBusEvent(DismissTaskViewEvent event) { // For visible children, defer removing the task until after the animation - mAnimationHelper.startDeleteTaskAnimation(event.task, event.taskView, - event.getAnimationTrigger()); + mAnimationHelper.startDeleteTaskAnimation(event.taskView, event.getAnimationTrigger()); + } + + public final void onBusEvent(final DismissAllTaskViewsEvent event) { + // Keep track of the tasks which will have their data removed + ArrayList tasks = new ArrayList<>(mStack.getStackTasks()); + mAnimationHelper.startDeleteAllTasksAnimation(getTaskViews(), event.getAnimationTrigger()); + event.addPostAnimationCallback(new Runnable() { + @Override + public void run() { + // Announce for accessibility + announceForAccessibility(getContext().getString( + R.string.accessibility_recents_all_items_dismissed)); + + // Remove all tasks and delete the task data for all tasks + mStack.removeAllTasks(); + for (int i = tasks.size() - 1; i >= 0; i--) { + EventBus.getDefault().send(new DeleteTaskDataEvent(tasks.get(i))); + } + + MetricsLogger.action(getContext(), MetricsEvent.OVERVIEW_DISMISS_ALL); + } + }); + } public final void onBusEvent(TaskViewDismissedEvent event) { - removeTaskViewFromStack(event.taskView, event.task); + // Announce for accessibility + announceForAccessibility(getContext().getString( + R.string.accessibility_recents_item_dismissed, event.task.title)); + + // Remove the task from the stack + mStack.removeTask(event.task, new AnimationProps(DEFAULT_SYNC_STACK_DURATION, + Interpolators.FAST_OUT_SLOW_IN), false /* fromDockGesture */); EventBus.getDefault().send(new DeleteTaskDataEvent(event.task)); MetricsLogger.action(getContext(), MetricsEvent.OVERVIEW_DISMISS, @@ -1955,20 +2006,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal requestLayout(); } - /** - * Removes the task from the stack, and updates the focus to the next task in the stack if the - * removed TaskView was focused. - */ - private void removeTaskViewFromStack(TaskView tv, Task task) { - // Announce for accessibility - tv.announceForAccessibility(getContext().getString( - R.string.accessibility_recents_item_dismissed, task.title)); - - // Remove the task from the stack - mStack.removeTask(task, new AnimationProps(DEFAULT_SYNC_STACK_DURATION, - Interpolators.FAST_OUT_SLOW_IN), false /* fromDockGesture */); - } - /** * Starts an alpha animation on the freeform workspace background. */ 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 aed19c3e0b9a5..ee0de1ad05dfd 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java @@ -356,6 +356,11 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback { return; } + // Disallow tapping above and below the stack to dismiss recents + if (x > mSv.mLayoutAlgorithm.mStackRect.left && x < mSv.mLayoutAlgorithm.mStackRect.right) { + return; + } + // If tapping on the freeform workspace background, just launch the first freeform task SystemServicesProxy ssp = Recents.getSystemServices(); if (ssp.hasFreeformWorkspaceSupport()) { @@ -507,13 +512,13 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback { tv.setClipViewInStack(true); // Re-enable touch events from this task view tv.setTouchEnabled(true); + // Remove the task view from the stack + EventBus.getDefault().send(new TaskViewDismissedEvent(tv.getTask(), tv)); // Update the scroll to the final scroll position from onBeginDrag() mSv.getScroller().setStackScroll(mTargetStackScroll, null); // Update the focus state to the final focus state mSv.getStackAlgorithm().setFocusState(TaskStackLayoutAlgorithm.STATE_UNFOCUSED); mSv.getStackAlgorithm().clearUnfocusedTaskOverrides(); - // Remove the task view from the stack - EventBus.getDefault().send(new TaskViewDismissedEvent(tv.getTask(), tv)); // Stop tracking this deletion animation mSwipeHelperAnimations.remove(v); // Keep track of deletions by keyboard 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 c085d8092a1ff..f8ed7008d9126 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java @@ -384,7 +384,7 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks void dismissTask() { // Animate out the view and call the callback final TaskView tv = this; - DismissTaskViewEvent dismissEvent = new DismissTaskViewEvent(tv, mTask); + DismissTaskViewEvent dismissEvent = new DismissTaskViewEvent(tv); dismissEvent.addPostAnimationCallback(new Runnable() { @Override public void run() { diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto index d6f1499ef6847..a2cfae9f3f118 100644 --- a/proto/src/metrics_constants.proto +++ b/proto/src/metrics_constants.proto @@ -2017,6 +2017,9 @@ message MetricsEvent { // action pass package name of calling package. ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST_BY_PACKAGE = 356; + // Logged when a user dismisses all task in overview + OVERVIEW_DISMISS_ALL = 357; + // Add new aosp constants above this line. // END OF AOSP CONSTANTS } From e8a4eff9d919481f021903be8389d4b6e93d2ca5 Mon Sep 17 00:00:00 2001 From: Winson Date: Mon, 28 Mar 2016 16:20:35 -0700 Subject: [PATCH 2/4] Moving the background to the window. - Make sure to remove the background from the DecorView while resizing, so we don't draw it twice. Bug: 27869246 Change-Id: I7f830e5c825749fdf2b5bbda7af92239702b70ad --- .../android/internal/policy/DecorView.java | 13 ++++++++ .../systemui/recents/RecentsActivity.java | 3 ++ .../events/ui/ResetBackgroundScrimEvent.java | 26 ---------------- .../events/ui/UpdateBackgroundScrimEvent.java | 31 ------------------- .../systemui/recents/views/RecentsView.java | 28 +++++++---------- 5 files changed, 28 insertions(+), 73 deletions(-) delete mode 100644 packages/SystemUI/src/com/android/systemui/recents/events/ui/ResetBackgroundScrimEvent.java delete mode 100644 packages/SystemUI/src/com/android/systemui/recents/events/ui/UpdateBackgroundScrimEvent.java diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java index 4b695b93d0e92..ea0fbdab1b890 100644 --- a/core/java/com/android/internal/policy/DecorView.java +++ b/core/java/com/android/internal/policy/DecorView.java @@ -209,6 +209,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind private Drawable mResizingBackgroundDrawable; private Drawable mCaptionBackgroundDrawable; private Drawable mUserCaptionBackgroundDrawable; + private Drawable mOriginalBackgroundDrawable; private float mAvailableWidth; @@ -888,6 +889,11 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind mBackgroundPadding.setEmpty(); } drawableChanged(); + + // Make sure we don't reset to the old drawable when finishing resizing. + if (mResizeMode != RESIZE_MODE_INVALID) { + mOriginalBackgroundDrawable = null; + } } } @@ -1950,6 +1956,9 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind updateElevation(); updateColorViews(null /* insets */, false); + + mOriginalBackgroundDrawable = getBackground(); + setBackgroundDrawable(null); } mResizeMode = resizeMode; getViewRootImpl().requestInvalidateRootRenderNode(); @@ -1961,6 +1970,10 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind updateColorViews(null /* insets */, false); mResizeMode = RESIZE_MODE_INVALID; getViewRootImpl().requestInvalidateRootRenderNode(); + if (mOriginalBackgroundDrawable != null) { + setBackgroundDrawable(mOriginalBackgroundDrawable); + mOriginalBackgroundDrawable = null; + } } @Override diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java index b89c2f67a2202..28dbef45e0a05 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java @@ -274,6 +274,9 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD } }); + // Set the window background + getWindow().setBackgroundDrawable(mRecentsView.getBackgroundScrim()); + // Create the home intent runnable mHomeIntent = new Intent(Intent.ACTION_MAIN, null); mHomeIntent.addCategory(Intent.CATEGORY_HOME); diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/ResetBackgroundScrimEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/ResetBackgroundScrimEvent.java deleted file mode 100644 index 863f40b39537b..0000000000000 --- a/packages/SystemUI/src/com/android/systemui/recents/events/ui/ResetBackgroundScrimEvent.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2016 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.events.ui; - -import com.android.systemui.recents.events.EventBus; - -/** - * This is sent to reset the background scrim back to the initial state. - */ -public class ResetBackgroundScrimEvent extends EventBus.Event { - // Simple event -} diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/UpdateBackgroundScrimEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/UpdateBackgroundScrimEvent.java deleted file mode 100644 index fdd4c673540db..0000000000000 --- a/packages/SystemUI/src/com/android/systemui/recents/events/ui/UpdateBackgroundScrimEvent.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2016 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.events.ui; - -import com.android.systemui.recents.events.EventBus; - -/** - * This is sent to request an update to the background scrim. - */ -public class UpdateBackgroundScrimEvent extends EventBus.Event { - - public final float alpha; - - public UpdateBackgroundScrimEvent(float alpha) { - this.alpha = alpha; - } -} 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 e9ce6372e934e..da2f7212cae06 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java @@ -63,8 +63,6 @@ import com.android.systemui.recents.events.ui.DeleteTaskDataEvent; import com.android.systemui.recents.events.ui.DismissAllTaskViewsEvent; import com.android.systemui.recents.events.ui.DraggingInRecentsEndedEvent; import com.android.systemui.recents.events.ui.DraggingInRecentsEvent; -import com.android.systemui.recents.events.ui.ResetBackgroundScrimEvent; -import com.android.systemui.recents.events.ui.UpdateBackgroundScrimEvent; import com.android.systemui.recents.events.ui.dragndrop.DragDropTargetChangedEvent; import com.android.systemui.recents.events.ui.dragndrop.DragEndEvent; import com.android.systemui.recents.events.ui.dragndrop.DragStartEvent; @@ -105,7 +103,8 @@ public class RecentsView extends FrameLayout { private Rect mSystemInsets = new Rect(); private int mDividerSize; - private ColorDrawable mBackgroundScrim = new ColorDrawable(Color.BLACK); + private Drawable mBackgroundScrim = new ColorDrawable( + Color.argb((int) (DEFAULT_SCRIM_ALPHA * 255), 0, 0, 0)).mutate(); private Animator mBackgroundScrimAnimator; private RecentsTransitionHelper mTransitionHelper; @@ -159,8 +158,6 @@ public class RecentsView extends FrameLayout { } mEmptyView = (TextView) inflater.inflate(R.layout.recents_empty, this, false); addView(mEmptyView); - - setBackground(mBackgroundScrim); } /** @@ -186,14 +183,14 @@ public class RecentsView extends FrameLayout { if (isResumingFromVisible) { // If we are already visible, then restore the background scrim - animateBackgroundScrim(DEFAULT_SCRIM_ALPHA, DEFAULT_UPDATE_SCRIM_DURATION); + animateBackgroundScrim(1f, DEFAULT_UPDATE_SCRIM_DURATION); } else { // If we are already occluded by the app, then set the final background scrim alpha now. // Otherwise, defer until the enter animation completes to animate the scrim alpha with // the tasks for the home animation. if (launchState.launchedViaDockGesture || launchState.launchedFromApp || isTaskStackEmpty) { - mBackgroundScrim.setAlpha((int) (DEFAULT_SCRIM_ALPHA * 255)); + mBackgroundScrim.setAlpha(255); } else { mBackgroundScrim.setAlpha(0); } @@ -222,6 +219,13 @@ public class RecentsView extends FrameLayout { return mStack; } + /* + * Returns the window background scrim. + */ + public Drawable getBackgroundScrim() { + return mBackgroundScrim; + } + /** * Returns whether the last task launched was in the freeform stack or not. */ @@ -573,19 +577,11 @@ public class RecentsView extends FrameLayout { RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState(); if (!launchState.launchedViaDockGesture && !launchState.launchedFromApp && mStack.getTaskCount() > 0) { - animateBackgroundScrim(DEFAULT_SCRIM_ALPHA, + animateBackgroundScrim(1f, TaskStackAnimationHelper.ENTER_FROM_HOME_TRANSLATION_DURATION); } } - public final void onBusEvent(UpdateBackgroundScrimEvent event) { - animateBackgroundScrim(event.alpha, DEFAULT_UPDATE_SCRIM_DURATION); - } - - public final void onBusEvent(ResetBackgroundScrimEvent event) { - animateBackgroundScrim(DEFAULT_SCRIM_ALPHA, DEFAULT_UPDATE_SCRIM_DURATION); - } - public final void onBusEvent(AllTaskViewsDismissedEvent event) { hideStackActionButton(HIDE_STACK_ACTION_BUTTON_DURATION, true /* translate */); } From 7845e8c4946f6b5dadfcd9c1d64e826bacc50edb Mon Sep 17 00:00:00 2001 From: Winson Date: Tue, 29 Mar 2016 10:23:19 -0700 Subject: [PATCH 3/4] Adding logging to track down bitmap issues. Bug: 27849282 Change-Id: Ie763a2a6cc968896e1ec0c4d89859cb49bd89e85 --- .../android/systemui/recents/RecentsImpl.java | 21 ++++++---- .../views/RecentsTransitionHelper.java | 42 ++++++++++++------- .../recents/views/TaskViewTransform.java | 5 +++ 3 files changed, 45 insertions(+), 23 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java index ffc037dba5e5b..43d627d9e13a5 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java @@ -663,13 +663,18 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener @Override public void run() { final Bitmap transitionBitmap = drawThumbnailTransitionBitmap(toTask, toTransform); - mHandler.post(new Runnable() { - @Override - public void run() { - mThumbnailTransitionBitmapCache = transitionBitmap; - mThumbnailTransitionBitmapCacheKey = toTask; - } - }); + if (transitionBitmap != null) { + mHandler.post(new Runnable() { + @Override + public void run() { + mThumbnailTransitionBitmapCache = transitionBitmap; + mThumbnailTransitionBitmapCacheKey = toTask; + } + }); + } else { + Log.e(TAG, "Could not load thumbnail for task: " + toTask + " at transform: " + + toTransform); + } } }); } @@ -774,7 +779,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener // Get the transform for the running task stackView.updateLayoutAlgorithm(true /* boundScroll */); stackView.updateToInitialState(true /* scrollToInitialState */); - mTmpTransform = stackView.getStackAlgorithm().getStackTransformScreenCoordinates(launchTask, + stackView.getStackAlgorithm().getStackTransformScreenCoordinates(launchTask, stackView.getScroller().getStackScroll(), mTmpTransform, null); return mTmpTransform; } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java index 9dc3fb14936a8..9eec2ce030c2a 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java @@ -28,11 +28,13 @@ import android.app.ActivityOptions.OnAnimationStartedListener; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; +import android.graphics.Color; import android.graphics.Rect; import android.os.Bundle; import android.os.Handler; import android.os.IRemoteCallback; import android.os.RemoteException; +import android.util.Log; import android.view.AppTransitionAnimationSpec; import android.view.IAppTransitionAnimationSpecsFuture; @@ -252,12 +254,13 @@ public class RecentsTransitionHelper { /** * Composes the transition spec when docking a task, which includes a full task bitmap. */ - public List composeDockAnimationSpec( - TaskView taskView, Rect transform) { - TaskViewTransform viewTransform = new TaskViewTransform(); - viewTransform.fillIn(taskView); - return Collections.singletonList(new AppTransitionAnimationSpec(taskView.getTask().key.id, - RecentsTransitionHelper.composeTaskBitmap(taskView, viewTransform), transform)); + public List composeDockAnimationSpec(TaskView taskView, + Rect bounds) { + mTmpTransform.fillIn(taskView); + Task task = taskView.getTask(); + Bitmap thumbnail = RecentsTransitionHelper.composeTaskBitmap(taskView, mTmpTransform); + return Collections.singletonList(new AppTransitionAnimationSpec(task.key.id, thumbnail, + bounds)); } /** @@ -336,18 +339,27 @@ public class RecentsTransitionHelper { float scale = transform.scale; int fromWidth = (int) (transform.rect.width() * scale); int fromHeight = (int) (transform.rect.height() * scale); - Bitmap b = Bitmap.createBitmap(fromWidth, fromHeight, - Bitmap.Config.ARGB_8888); + if (fromWidth == 0 || fromHeight == 0) { + Log.e(TAG, "Could not compose thumbnail for task: " + taskView.getTask() + + " at transform: " + transform); - if (RecentsDebugFlags.Static.EnableTransitionThumbnailDebugMode) { - b.eraseColor(0xFFff0000); + Bitmap b = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); + b.eraseColor(Color.TRANSPARENT); + return b; } else { - Canvas c = new Canvas(b); - c.scale(scale, scale); - taskView.draw(c); - c.setBitmap(null); + Bitmap b = Bitmap.createBitmap(fromWidth, fromHeight, + Bitmap.Config.ARGB_8888); + + if (RecentsDebugFlags.Static.EnableTransitionThumbnailDebugMode) { + b.eraseColor(0xFFff0000); + } else { + Canvas c = new Canvas(b); + c.scale(scale, scale); + taskView.draw(c); + c.setBitmap(null); + } + return b.createAshmemBitmap(); } - return b.createAshmemBitmap(); } private static Bitmap composeHeaderBitmap(TaskView taskView, diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java index dc76e61c0d1e9..b512393304c3c 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java @@ -226,4 +226,9 @@ public class TaskViewTransform { v.getViewBounds().setClipBottom(0); v.setLeftTopRightBottom(0, 0, 0, 0); } + + @Override + public String toString() { + return "R: " + rect + " V: " + visible; + } } From 44849b8abdcdefbe3112324d98afdea220a37376 Mon Sep 17 00:00:00 2001 From: Winson Date: Tue, 29 Mar 2016 10:45:45 -0700 Subject: [PATCH 4/4] Should not update initial state at all on resize. This fixes an issue with the stack scrolling upon resizing. We only need to update the initial state if docking, or upon rotation. Change-Id: Ie59ed72cb22c9b000289db3f04b1a71ad5f64816 --- .../com/android/systemui/recents/RecentsActivity.java | 11 +++++++++-- .../events/activity/ConfigurationChangedEvent.java | 4 +++- .../android/systemui/recents/views/TaskStackView.java | 10 ++++++---- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java index 28dbef45e0a05..d7777d5693370 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java @@ -90,6 +90,7 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD private RecentsPackageMonitor mPackageMonitor; private long mLastTabKeyEventTime; + private int mLastOrientation = Configuration.ORIENTATION_UNDEFINED; private boolean mFinishedOnStartup; private boolean mIgnoreAltTabRelease; private boolean mIsVisible; @@ -266,6 +267,7 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD getWindow().getAttributes().privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY; + mLastOrientation = getResources().getConfiguration().orientation; mFocusTimerDuration = getResources().getInteger(R.integer.recents_auto_advance_duration); mIterateTrigger = new DozeTrigger(mFocusTimerDuration, new Runnable() { @Override @@ -418,13 +420,18 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD // Update the nav bar for the current orientation updateNavBarScrim(false /* animateNavBarScrim */, AnimationProps.IMMEDIATE); - EventBus.getDefault().send(new ConfigurationChangedEvent(false /* fromMultiWindow */)); + // Notify of the config change + int newOrientation = getResources().getConfiguration().orientation; + EventBus.getDefault().send(new ConfigurationChangedEvent(false /* fromMultiWindow */, + (mLastOrientation != newOrientation))); + mLastOrientation = newOrientation; } @Override public void onMultiWindowChanged(boolean inMultiWindow) { super.onMultiWindowChanged(inMultiWindow); - EventBus.getDefault().send(new ConfigurationChangedEvent(true /* fromMultiWindow */)); + EventBus.getDefault().send(new ConfigurationChangedEvent(true /* fromMultiWindow */, + false /* fromOrientationChange */)); if (mRecentsView != null) { // Reload the task stack completely diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ConfigurationChangedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ConfigurationChangedEvent.java index c234c348ad66c..8be9ca7b5f2bc 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ConfigurationChangedEvent.java +++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ConfigurationChangedEvent.java @@ -24,8 +24,10 @@ import com.android.systemui.recents.events.EventBus; public class ConfigurationChangedEvent extends EventBus.AnimatedEvent { public final boolean fromMultiWindow; + public final boolean fromOrientationChange; - public ConfigurationChangedEvent(boolean fromMultiWindow) { + public ConfigurationChangedEvent(boolean fromMultiWindow, boolean fromOrientationChange) { this.fromMultiWindow = fromMultiWindow; + this.fromOrientationChange = fromOrientationChange; } } 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 58998c645a223..5416a4897666a 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java @@ -1999,10 +1999,12 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal } } - // Trigger a new layout and scroll to the initial state - mInitialState = event.fromMultiWindow - ? INITIAL_STATE_UPDATE_ALL - : INITIAL_STATE_UPDATE_LAYOUT_ONLY; + // Trigger a new layout and update to the initial state if necessary + if (event.fromMultiWindow) { + mInitialState = INITIAL_STATE_UPDATE_ALL; + } else if (event.fromOrientationChange) { + mInitialState = INITIAL_STATE_UPDATE_LAYOUT_ONLY; + } requestLayout(); }