Merge changes Ie59ed72c,Ie763a2a6,I7f830e5c,Ife637438 into nyc-dev am: fe1886f

am: 843fcb0

* commit '843fcb079ec1d3aae6a431af57530dfa2d385552':
  Should not update initial state at all on resize.
  Adding logging to track down bitmap issues.
  Moving the background to the window.
  Adding clear-all button.

Change-Id: I27ed2e95a43b77e45aa15a7ae1de9c54c4a0d78e
This commit is contained in:
Winson
2016-03-30 01:26:47 +00:00
committed by android-build-merger
24 changed files with 285 additions and 129 deletions

View File

@@ -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

View File

@@ -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"

View File

@@ -153,6 +153,9 @@
<!-- The animation duration for animating the removal of a task view. -->
<integer name="recents_animate_task_view_remove_duration">175</integer>
<!-- The base animation duration for animating the removal of all task views. -->
<integer name="recents_animate_task_views_remove_all_duration">300</integer>
<!-- The animation duration for scrolling the stack to a particular item. -->
<integer name="recents_animate_task_stack_scroll_duration">200</integer>

View File

@@ -574,10 +574,12 @@
<dimen name="recents_layout_bottom_margin">16dp</dimen>
<dimen name="recents_layout_side_margin_phone">16dp</dimen>
<dimen name="recents_layout_side_margin_tablet">48dp</dimen>
<dimen name="recents_layout_side_margin_tablet_docked">16dp</dimen>
<dimen name="recents_layout_side_margin_tablet_xlarge">64dp</dimen>
<dimen name="recents_layout_side_margin_tablet_xlarge_docked">16dp</dimen>
<!-- The height between the top margin and the top of the focused task. -->
<dimen name="recents_layout_top_peek_size">56dp</dimen>
<dimen name="recents_layout_top_peek_size">48dp</dimen>
<!-- The height between the bottom margin and the top of task in front of the focused task. -->
<dimen name="recents_layout_bottom_peek_size">56dp</dimen>

View File

@@ -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);

View File

@@ -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
@@ -274,6 +276,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);
@@ -415,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

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -17,10 +17,11 @@
package com.android.systemui.recents.events.ui;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.views.TaskView;
/**
* This is sent to reset the background scrim back to the initial state.
* This event is sent to request that all the {@link TaskView}s are dismissed.
*/
public class ResetBackgroundScrimEvent extends EventBus.Event {
public class DismissAllTaskViewsEvent extends EventBus.AnimatedEvent {
// Simple event
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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<Task> 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.
*

View File

@@ -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

View File

@@ -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<AppTransitionAnimationSpec> 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<AppTransitionAnimationSpec> 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,

View File

@@ -58,10 +58,11 @@ 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;
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;
@@ -87,6 +88,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;
@@ -99,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;
@@ -135,10 +140,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);
@@ -152,8 +158,6 @@ public class RecentsView extends FrameLayout {
}
mEmptyView = (TextView) inflater.inflate(R.layout.recents_empty, this, false);
addView(mEmptyView);
setBackground(mBackgroundScrim);
}
/**
@@ -179,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);
}
@@ -215,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.
*/
@@ -566,17 +577,21 @@ 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(AllTaskViewsDismissedEvent event) {
hideStackActionButton(HIDE_STACK_ACTION_BUTTON_DURATION, true /* translate */);
}
public final void onBusEvent(ResetBackgroundScrimEvent event) {
animateBackgroundScrim(DEFAULT_SCRIM_ALPHA, DEFAULT_UPDATE_SCRIM_DURATION);
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) {
@@ -584,7 +599,7 @@ public class RecentsView extends FrameLayout {
return;
}
showStackActionButton(150, event.translate);
showStackActionButton(SHOW_STACK_ACTION_BUTTON_DURATION, event.translate);
}
public final void onBusEvent(HideStackActionButtonEvent event) {
@@ -592,7 +607,7 @@ public class RecentsView extends FrameLayout {
return;
}
hideStackActionButton(100, true /* translate */);
hideStackActionButton(HIDE_STACK_ACTION_BUTTON_DURATION, true /* translate */);
}
/**
@@ -623,7 +638,6 @@ public class RecentsView extends FrameLayout {
.alpha(1f)
.setDuration(duration)
.setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
.withLayer()
.start();
}
});
@@ -669,7 +683,6 @@ public class RecentsView extends FrameLayout {
postAnimationTrigger.decrement();
}
})
.withLayer()
.start();
postAnimationTrigger.increment();
}

View File

@@ -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);
}
}
}

View File

@@ -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<TaskView> 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.
*

View File

@@ -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
};
}
}

View File

@@ -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<TaskView> 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<Task> 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,
@@ -1948,27 +1999,15 @@ 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();
}
/**
* 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.
*/

View File

@@ -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

View File

@@ -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() {

View File

@@ -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;
}
}

View File

@@ -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
}