Merge changes Ia8a90434,I35f484c7,I2e87e764 into nyc-dev

am: dddfff3

* commit 'dddfff3cddf8c12aba0335eb853f177abb0a68b0':
  Tweaks to make overview animations to match spec.
  Closing system windows when dismissing recents to app or home.
  Caching the display rect to reduce binder calls.

Change-Id: I62e383c2b2f6b029049e02f3a80b298833e664ea
This commit is contained in:
Winson
2016-04-22 22:24:34 +00:00
committed by android-build-merger
13 changed files with 211 additions and 190 deletions

View File

@@ -26,5 +26,6 @@
android:layout_gravity="center"
android:drawableTop="@drawable/recents_info_light"
android:drawablePadding="8dp"
android:text="@string/recents_incompatible_app_message" />
android:text="@string/recents_incompatible_app_message"
android:textColor="@android:color/white" />
</FrameLayout>

View File

@@ -144,12 +144,6 @@
<!-- The min animation duration for animating the nav bar scrim in. -->
<integer name="recents_nav_bar_scrim_enter_duration">400</integer>
<!-- 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

@@ -26,6 +26,7 @@ import android.content.IntentFilter;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
@@ -97,6 +98,7 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
public final static int INCOMPATIBLE_APP_ALPHA_DURATION = 150;
private RecentsPackageMonitor mPackageMonitor;
private Handler mHandler = new Handler();
private long mLastTabKeyEventTime;
private int mLastDeviceOrientation = Configuration.ORIENTATION_UNDEFINED;
private int mLastDisplayDensity;
@@ -138,12 +140,14 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
@Override
public void run() {
try {
ActivityOptions opts = mOpts;
if (opts == null) {
opts = ActivityOptions.makeCustomAnimation(RecentsActivity.this,
R.anim.recents_to_launcher_enter, R.anim.recents_to_launcher_exit);
}
startActivityAsUser(mLaunchIntent, opts.toBundle(), UserHandle.CURRENT);
mHandler.post(() -> {
ActivityOptions opts = mOpts;
if (opts == null) {
opts = ActivityOptions.makeCustomAnimation(RecentsActivity.this,
R.anim.recents_to_launcher_enter, R.anim.recents_to_launcher_exit);
}
startActivityAsUser(mLaunchIntent, opts.toBundle(), UserHandle.CURRENT);
});
} catch (Exception e) {
Log.e(TAG, getString(R.string.recents_launch_error_message, "Home"), e);
}
@@ -223,13 +227,8 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
new DismissRecentsToHomeAnimationStarted(animateTaskViews);
dismissEvent.addPostAnimationCallback(new LaunchHomeRunnable(mHomeIntent,
overrideAnimation));
dismissEvent.addPostAnimationCallback(new Runnable() {
@Override
public void run() {
Recents.getSystemServices().sendCloseSystemWindows(
BaseStatusBar.SYSTEM_DIALOG_REASON_HOME_KEY);
}
});
Recents.getSystemServices().sendCloseSystemWindows(
BaseStatusBar.SYSTEM_DIALOG_REASON_HOME_KEY);
EventBus.getDefault().send(dismissEvent);
}

View File

@@ -588,6 +588,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
*/
private void updateHeaderBarLayout(TaskStack stack, Rect windowRectOverride) {
SystemServicesProxy ssp = Recents.getSystemServices();
Rect displayRect = ssp.getDisplayRect();
Rect systemInsets = new Rect();
ssp.getStableInsets(systemInsets);
Rect windowRect = windowRectOverride != null
@@ -608,10 +609,10 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
// Rebind the header bar and draw it for the transition
stackLayout.setSystemInsets(systemInsets);
if (stack != null) {
stackLayout.getTaskStackBounds(windowRect, systemInsets.top, systemInsets.right,
mTaskStackBounds);
stackLayout.getTaskStackBounds(displayRect, windowRect, systemInsets.top,
systemInsets.right, mTaskStackBounds);
stackLayout.reset();
stackLayout.initialize(windowRect, mTaskStackBounds,
stackLayout.initialize(displayRect, windowRect, mTaskStackBounds,
TaskStackLayoutAlgorithm.StackState.getStackStateForStack(stack));
mDummyStackView.setTasks(stack, false /* allowNotifyStackChanges */);

View File

@@ -49,6 +49,7 @@ import android.util.SparseArray;
import android.view.animation.Interpolator;
import com.android.internal.policy.DockedDividerUtils;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsDebugFlags;
@@ -253,7 +254,7 @@ public class TaskStack {
private static final int HORIZONTAL = 0;
private static final int VERTICAL = 1;
private static final int DOCK_AREA_ALPHA = 192;
private static final int DOCK_AREA_ALPHA = 80;
public static final DockState NONE = new DockState(DOCKED_INVALID, -1, 80, 255, HORIZONTAL,
null, null, null);
public static final DockState LEFT = new DockState(DOCKED_LEFT,
@@ -368,19 +369,28 @@ public class TaskStack {
mDockAreaOverlayAnimator.cancel();
}
ObjectAnimator anim;
ArrayList<Animator> animators = new ArrayList<>();
if (dockAreaOverlay.getAlpha() != areaAlpha) {
if (animateAlpha) {
animators.add(ObjectAnimator.ofInt(dockAreaOverlay,
Utilities.DRAWABLE_ALPHA, dockAreaOverlay.getAlpha(), areaAlpha));
anim = ObjectAnimator.ofInt(dockAreaOverlay,
Utilities.DRAWABLE_ALPHA, dockAreaOverlay.getAlpha(), areaAlpha);
anim.setDuration(duration);
anim.setInterpolator(interpolator);
animators.add(anim);
} else {
dockAreaOverlay.setAlpha(areaAlpha);
}
}
if (mHintTextAlpha != hintAlpha) {
if (animateAlpha) {
animators.add(ObjectAnimator.ofInt(this, HINT_ALPHA, mHintTextAlpha,
hintAlpha));
anim = ObjectAnimator.ofInt(this, HINT_ALPHA, mHintTextAlpha,
hintAlpha);
anim.setDuration(150);
anim.setInterpolator(hintAlpha > mHintTextAlpha
? Interpolators.ALPHA_IN
: Interpolators.ALPHA_OUT);
animators.add(anim);
} else {
mHintTextAlpha = hintAlpha;
dockAreaOverlay.invalidateSelf();
@@ -390,8 +400,11 @@ public class TaskStack {
if (animateBounds) {
PropertyValuesHolder prop = PropertyValuesHolder.ofObject(
Utilities.DRAWABLE_RECT, Utilities.RECT_EVALUATOR,
dockAreaOverlay.getBounds(), bounds);
animators.add(ObjectAnimator.ofPropertyValuesHolder(dockAreaOverlay, prop));
new Rect(dockAreaOverlay.getBounds()), bounds);
anim = ObjectAnimator.ofPropertyValuesHolder(dockAreaOverlay, prop);
anim.setDuration(duration);
anim.setInterpolator(interpolator);
animators.add(anim);
} else {
dockAreaOverlay.setBounds(bounds);
}
@@ -399,8 +412,6 @@ public class TaskStack {
if (!animators.isEmpty()) {
mDockAreaOverlayAnimator = new AnimatorSet();
mDockAreaOverlayAnimator.playTogether(animators);
mDockAreaOverlayAnimator.setDuration(duration);
mDockAreaOverlayAnimator.setInterpolator(interpolator);
mDockAreaOverlayAnimator.start();
}
}
@@ -481,8 +492,9 @@ public class TaskStack {
* Returns the task stack bounds with the given {@param width} and
* {@param height}.
*/
public Rect getDockedTaskStackBounds(int width, int height, int dividerSize, Rect insets,
TaskStackLayoutAlgorithm layoutAlgorithm, Resources res, Rect windowRectOut) {
public Rect getDockedTaskStackBounds(Rect displayRect, int width, int height,
int dividerSize, Rect insets, TaskStackLayoutAlgorithm layoutAlgorithm,
Resources res, Rect windowRectOut) {
// Calculate the inverse docked task bounds
boolean isHorizontalDivision =
res.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
@@ -499,7 +511,8 @@ public class TaskStack {
int top = dockArea.bottom < 1f
? 0
: insets.top;
layoutAlgorithm.getTaskStackBounds(windowRectOut, top, insets.right, taskStackBounds);
layoutAlgorithm.getTaskStackBounds(displayRect, windowRectOut, top, insets.right,
taskStackBounds);
return taskStackBounds;
}
}

View File

@@ -18,6 +18,7 @@ package com.android.systemui.recents.views;
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.annotation.IntDef;
import android.util.SparseArray;
import android.util.SparseLongArray;
@@ -53,6 +54,7 @@ public class AnimationProps {
public static final int FOCUS_STATE = 8;
private SparseLongArray mPropStartDelay;
private SparseLongArray mPropInitialPlayTime;
private SparseLongArray mPropDuration;
private SparseArray<Interpolator> mPropInterpolators;
private Animator.AnimatorListener mListener;
@@ -116,10 +118,14 @@ public class AnimationProps {
* Applies the specific start delay, duration and interpolator to the given {@param animator}
* for the specified {@param propertyType}.
*/
public <T extends Animator> T apply(@PropType int propertyType, T animator) {
public <T extends ValueAnimator> T apply(@PropType int propertyType, T animator) {
animator.setStartDelay(getStartDelay(propertyType));
animator.setDuration(getDuration(propertyType));
animator.setInterpolator(getInterpolator(propertyType));
long initialPlayTime = getInitialPlayTime(propertyType);
if (initialPlayTime != 0) {
animator.setCurrentPlayTime(initialPlayTime);
}
return animator;
}
@@ -134,6 +140,17 @@ public class AnimationProps {
return this;
}
/**
* Sets a initial play time for a specific property.
*/
public AnimationProps setInitialPlayTime(@PropType int propertyType, int initialPlayTime) {
if (mPropInitialPlayTime == null) {
mPropInitialPlayTime = new SparseLongArray();
}
mPropInitialPlayTime.append(propertyType, initialPlayTime);
return this;
}
/**
* Returns the start delay for a specific property.
*/
@@ -199,6 +216,20 @@ public class AnimationProps {
return Interpolators.LINEAR;
}
/**
* Returns the initial play time for a specific property, falling back to the general initial
* play time if there is no specific property interpolator.
*/
public long getInitialPlayTime(@PropType int propertyType) {
if (mPropInitialPlayTime != null) {
if (mPropInitialPlayTime.indexOfKey(propertyType) != -1) {
return mPropInitialPlayTime.get(propertyType);
}
return mPropInitialPlayTime.get(ALL, 0);
}
return 0;
}
/**
* Sets an animator listener for this animation.
*/

View File

@@ -51,6 +51,7 @@ import com.android.systemui.recents.events.component.ScreenPinningRequestEvent;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.TaskStack;
import com.android.systemui.statusbar.BaseStatusBar;
import java.util.ArrayList;
import java.util.Collections;
@@ -167,6 +168,8 @@ public class RecentsTransitionHelper {
animStartedListener);
}
}
Recents.getSystemServices().sendCloseSystemWindows(
BaseStatusBar.SYSTEM_DIALOG_REASON_HOME_KEY);
}
public IRemoteCallback wrapStartedListener(final OnAnimationStartedListener listener) {
@@ -284,7 +287,6 @@ public class RecentsTransitionHelper {
}
// Calculate the offscreen task rect (for tasks that are not backed by views)
float stackScroll = stackView.getScroller().getStackScroll();
TaskView taskView = stackView.getChildViewForTask(task);
TaskStackLayoutAlgorithm stackLayout = stackView.getStackAlgorithm();
Rect offscreenTaskRect = new Rect();
@@ -404,7 +406,7 @@ public class RecentsTransitionHelper {
transform.rect.round(taskRect);
if (stackView.getStack().getStackFrontMostTask(false /* includeFreeformTasks */) !=
taskView.getTask()) {
taskRect.bottom = 2 * Recents.getSystemServices().getDisplayRect().height();
taskRect.bottom = taskRect.top + stackView.getMeasuredHeight();
}
return new AppTransitionAnimationSpec(taskView.getTask().key.id, b, taskRect);
}

View File

@@ -88,7 +88,6 @@ public class RecentsView extends FrameLayout {
private static final String TAG = "RecentsView";
private static final int DOCK_AREA_OVERLAY_TRANSITION_DURATION = 135;
private static final int DEFAULT_UPDATE_SCRIM_DURATION = 200;
private static final float DEFAULT_SCRIM_ALPHA = 0.33f;
@@ -733,8 +732,8 @@ public class RecentsView extends FrameLayout {
TaskStack.DockState.ViewState viewState = dockState.viewState;
if (newDockStates == null || !newDockStatesSet.contains(dockState)) {
// This is no longer visible, so hide it
viewState.startAnimation(null, 0, 0, DOCK_AREA_OVERLAY_TRANSITION_DURATION,
Interpolators.ALPHA_OUT, animateAlpha, animateBounds);
viewState.startAnimation(null, 0, 0, TaskStackView.SLOW_SYNC_STACK_DURATION,
Interpolators.FAST_OUT_SLOW_IN, animateAlpha, animateBounds);
} else {
// This state is now visible, update the bounds and show it
int areaAlpha = overrideAreaAlpha != -1
@@ -752,7 +751,7 @@ public class RecentsView extends FrameLayout {
viewState.dockAreaOverlay.setBounds(bounds);
}
viewState.startAnimation(bounds, areaAlpha, hintAlpha,
DOCK_AREA_OVERLAY_TRANSITION_DURATION, Interpolators.ALPHA_IN,
TaskStackView.SLOW_SYNC_STACK_DURATION, Interpolators.FAST_OUT_SLOW_IN,
animateAlpha, animateBounds);
}
}

View File

@@ -18,6 +18,7 @@ package com.android.systemui.recents.views;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.TimeInterpolator;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -32,7 +33,6 @@ 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;
@@ -74,32 +74,35 @@ public class TaskStackAnimationHelper {
void onStartFrontTaskEnterAnimation(boolean screenPinningEnabled);
}
private static final int DOUBLE_FRAME_OFFSET_MS = 33;
private static final int FRAME_OFFSET_MS = 16;
public static final int ENTER_FROM_HOME_ALPHA_DURATION = 100;
public static final int ENTER_FROM_HOME_TRANSLATION_DURATION = 333;
private static final int ENTER_EXIT_NUM_ANIMATING_TASKS = 5;
private static final PathInterpolator ENTER_FROM_HOME_TRANSLATION_INTERPOLATOR =
new PathInterpolator(0, 0, 0, 1f);
private static final PathInterpolator ENTER_FROM_HOME_ALPHA_INTERPOLATOR =
new PathInterpolator(0, 0, 0.2f, 1f);
private static final int ENTER_FROM_HOME_ALPHA_DURATION = 100;
public static final int ENTER_FROM_HOME_TRANSLATION_DURATION = 300;
private static final Interpolator ENTER_FROM_HOME_TRANSLATION_INTERPOLATOR =
Interpolators.LINEAR_OUT_SLOW_IN;
private static final Interpolator ENTER_FROM_HOME_ALPHA_INTERPOLATOR = Interpolators.LINEAR;
public static final int EXIT_TO_HOME_ALPHA_DURATION = 100;
public static final int EXIT_TO_HOME_TRANSLATION_DURATION = 150;
private static final PathInterpolator EXIT_TO_HOME_TRANSLATION_INTERPOLATOR =
new PathInterpolator(0.8f, 0, 0.6f, 1f);
private static final PathInterpolator EXIT_TO_HOME_ALPHA_INTERPOLATOR =
public static final int EXIT_TO_HOME_TRANSLATION_DURATION = 200;
private static final Interpolator EXIT_TO_HOME_TRANSLATION_INTERPOLATOR =
new PathInterpolator(0.4f, 0, 0.6f, 1f);
private static final int DISMISS_TASK_DURATION = 175;
private static final int DISMISS_ALL_TASKS_DURATION = 200;
private static final Interpolator DISMISS_ALL_TRANSLATION_INTERPOLATOR =
new PathInterpolator(0.4f, 0, 1f, 1f);
private static final PathInterpolator FOCUS_NEXT_TASK_INTERPOLATOR =
private static final Interpolator FOCUS_NEXT_TASK_INTERPOLATOR =
new PathInterpolator(0.4f, 0, 0, 1f);
private static final PathInterpolator FOCUS_IN_FRONT_NEXT_TASK_INTERPOLATOR =
private static final Interpolator FOCUS_IN_FRONT_NEXT_TASK_INTERPOLATOR =
new PathInterpolator(0, 0, 0, 1f);
private static final PathInterpolator FOCUS_BEHIND_NEXT_TASK_INTERPOLATOR =
new PathInterpolator(0.4f, 0, 0.2f, 1f);
private static final Interpolator FOCUS_BEHIND_NEXT_TASK_INTERPOLATOR =
Interpolators.LINEAR_OUT_SLOW_IN;
private static final PathInterpolator ENTER_WHILE_DOCKING_INTERPOLATOR =
new PathInterpolator(0, 0, 0.2f, 1f);
private static final Interpolator ENTER_WHILE_DOCKING_INTERPOLATOR =
Interpolators.LINEAR_OUT_SLOW_IN;
private TaskStackView mStackView;
@@ -251,16 +254,20 @@ public class TaskStackAnimationHelper {
}
} else if (launchState.launchedFromHome) {
// Animate the tasks up
// Animate the tasks up, but offset the animations to be relative to the front-most
// task animation
AnimationProps taskAnimation = new AnimationProps()
.setStartDelay(AnimationProps.ALPHA, taskIndexFromFront * FRAME_OFFSET_MS)
.setInitialPlayTime(AnimationProps.BOUNDS,
Math.min(ENTER_EXIT_NUM_ANIMATING_TASKS, taskIndexFromFront) *
DOUBLE_FRAME_OFFSET_MS)
.setStartDelay(AnimationProps.ALPHA,
Math.min(ENTER_EXIT_NUM_ANIMATING_TASKS, taskIndexFromFront) *
FRAME_OFFSET_MS)
.setDuration(AnimationProps.BOUNDS, ENTER_FROM_HOME_TRANSLATION_DURATION)
.setDuration(AnimationProps.ALPHA, ENTER_FROM_HOME_ALPHA_DURATION)
.setDuration(AnimationProps.BOUNDS, ENTER_FROM_HOME_TRANSLATION_DURATION -
(taskIndexFromFront * FRAME_OFFSET_MS))
.setInterpolator(AnimationProps.BOUNDS,
ENTER_FROM_HOME_TRANSLATION_INTERPOLATOR)
.setInterpolator(AnimationProps.ALPHA,
ENTER_FROM_HOME_ALPHA_INTERPOLATOR)
.setInterpolator(AnimationProps.ALPHA, ENTER_FROM_HOME_ALPHA_INTERPOLATOR)
.setListener(postAnimationTrigger.decrementOnAnimationEnd());
postAnimationTrigger.increment();
mStackView.updateTaskViewToTransform(tv, mTmpTransform, taskAnimation);
@@ -270,8 +277,8 @@ public class TaskStackAnimationHelper {
} else if (launchState.launchedViaDockGesture) {
// Animate the tasks up
AnimationProps taskAnimation = new AnimationProps()
.setDuration(AnimationProps.BOUNDS, (int) (dockGestureAnimDuration +
(taskIndexFromBack * 2f * FRAME_OFFSET_MS)))
.setDuration(AnimationProps.BOUNDS, dockGestureAnimDuration +
(taskIndexFromBack * DOUBLE_FRAME_OFFSET_MS))
.setInterpolator(AnimationProps.BOUNDS,
ENTER_WHILE_DOCKING_INTERPOLATOR)
.setListener(postAnimationTrigger.decrementOnAnimationEnd());
@@ -302,20 +309,17 @@ public class TaskStackAnimationHelper {
for (int i = 0; i < taskViewCount; i++) {
int taskIndexFromFront = taskViewCount - i - 1;
TaskView tv = taskViews.get(i);
Task task = tv.getTask();
// Animate the tasks down
AnimationProps taskAnimation;
if (animated) {
int delay = Math.min(ENTER_EXIT_NUM_ANIMATING_TASKS , taskIndexFromFront) *
DOUBLE_FRAME_OFFSET_MS;
taskAnimation = new AnimationProps()
.setStartDelay(AnimationProps.ALPHA, i * FRAME_OFFSET_MS)
.setDuration(AnimationProps.ALPHA, EXIT_TO_HOME_ALPHA_DURATION)
.setDuration(AnimationProps.BOUNDS, EXIT_TO_HOME_TRANSLATION_DURATION +
(taskIndexFromFront * FRAME_OFFSET_MS))
.setStartDelay(AnimationProps.BOUNDS, delay)
.setDuration(AnimationProps.BOUNDS, EXIT_TO_HOME_TRANSLATION_DURATION)
.setInterpolator(AnimationProps.BOUNDS,
EXIT_TO_HOME_TRANSLATION_INTERPOLATOR)
.setInterpolator(AnimationProps.ALPHA,
EXIT_TO_HOME_ALPHA_INTERPOLATOR)
.setListener(postAnimationTrigger.decrementOnAnimationEnd());
postAnimationTrigger.increment();
} else {
@@ -323,7 +327,6 @@ public class TaskStackAnimationHelper {
}
mTmpTransform.fillIn(tv);
mTmpTransform.alpha = 0f;
mTmpTransform.rect.offset(0, offscreenYOffset);
mStackView.updateTaskViewToTransform(tv, mTmpTransform, taskAnimation);
}
@@ -384,8 +387,6 @@ public class TaskStackAnimationHelper {
Resources res = mStackView.getResources();
TaskStackLayoutAlgorithm stackLayout = mStackView.getStackAlgorithm();
int taskViewRemoveAnimDuration = res.getInteger(
R.integer.recents_animate_task_view_remove_duration);
int offscreenXOffset = mStackView.getMeasuredWidth() - stackLayout.mTaskRect.left;
// Disabling clipping with the stack while the view is animating away, this will get
@@ -393,7 +394,7 @@ public class TaskStackAnimationHelper {
deleteTaskView.setClipViewInStack(false);
// Compose the new animation and transform and star the animation
AnimationProps taskAnimation = new AnimationProps(taskViewRemoveAnimDuration,
AnimationProps taskAnimation = new AnimationProps(DISMISS_TASK_DURATION,
Interpolators.ALPHA_OUT, new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
@@ -413,29 +414,23 @@ public class TaskStackAnimationHelper {
*/
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);
int taskIndexFromFront = taskViewCount - i - 1;
int startDelay = taskIndexFromFront * DOUBLE_FRAME_OFFSET_MS;
// 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,
DISMISS_ALL_TASKS_DURATION, DISMISS_ALL_TRANSLATION_INTERPOLATOR,
new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
@@ -605,7 +600,7 @@ public class TaskStackAnimationHelper {
// Now, animate in the front-most task
if (frontMostTaskView != null) {
mStackView.updateTaskViewToTransform(frontMostTaskView, frontMostTransform,
new AnimationProps(75, 200, FOCUS_BEHIND_NEXT_TASK_INTERPOLATOR));
new AnimationProps(75, 250, FOCUS_BEHIND_NEXT_TASK_INTERPOLATOR));
}
}
});

View File

@@ -432,10 +432,9 @@ public class TaskStackLayoutAlgorithm {
* Computes the stack and task rects. The given task stack bounds already has the top/right
* insets and left/right padding already applied.
*/
public void initialize(Rect windowRect, Rect taskStackBounds, StackState state) {
SystemServicesProxy ssp = Recents.getSystemServices();
public void initialize(Rect displayRect, Rect windowRect, Rect taskStackBounds,
StackState state) {
Rect lastStackRect = new Rect(mStackRect);
Rect displayRect = ssp.getDisplayRect();
int topMargin = getScaleForExtent(windowRect, displayRect, mBaseTopMargin, mMinMargin, HEIGHT);
int bottomMargin = getScaleForExtent(windowRect, displayRect, mBaseBottomMargin, mMinMargin,
@@ -999,14 +998,12 @@ public class TaskStackLayoutAlgorithm {
* top and right system insets (but not the bottom inset) and left/right paddings, but _not_
* the top/bottom padding or insets.
*/
public void getTaskStackBounds(Rect windowRect, int topInset, int rightInset,
public void getTaskStackBounds(Rect displayRect, Rect windowRect, int topInset, int rightInset,
Rect taskStackBounds) {
taskStackBounds.set(windowRect.left, windowRect.top + topInset,
windowRect.right - rightInset, windowRect.bottom);
// Ensure that the new width is at most the smaller display edge size
SystemServicesProxy ssp = Recents.getSystemServices();
Rect displayRect = ssp.getDisplayRect();
int sideMargin = getScaleForExtent(windowRect, displayRect, mBaseSideMargin, mMinMargin,
WIDTH);
int targetStackWidth = taskStackBounds.width() - 2 * sideMargin;

View File

@@ -25,6 +25,7 @@ import android.animation.ValueAnimator;
import android.annotation.IntDef;
import android.content.ComponentName;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Rect;
@@ -109,6 +110,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
private static final float HIDE_STACK_ACTION_BUTTON_SCROLL_THRESHOLD = 0.3f;
public static final int DEFAULT_SYNC_STACK_DURATION = 200;
public static final int SLOW_SYNC_STACK_DURATION = 250;
private static final int DRAG_SCALE_DURATION = 175;
static final float DRAG_SCALE_FACTOR = 1.05f;
@@ -126,48 +128,48 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
/** Update only the layout to the initial state. */
private static final int INITIAL_STATE_UPDATE_LAYOUT_ONLY = 2;
LayoutInflater mInflater;
TaskStack mStack = new TaskStack();
private LayoutInflater mInflater;
private TaskStack mStack = new TaskStack();
@ViewDebug.ExportedProperty(deepExport=true, prefix="layout_")
TaskStackLayoutAlgorithm mLayoutAlgorithm;
// The stable layout algorithm is only used to calculate the task rect with the stable bounds
TaskStackLayoutAlgorithm mStableLayoutAlgorithm;
private TaskStackLayoutAlgorithm mStableLayoutAlgorithm;
@ViewDebug.ExportedProperty(deepExport=true, prefix="scroller_")
TaskStackViewScroller mStackScroller;
private TaskStackViewScroller mStackScroller;
@ViewDebug.ExportedProperty(deepExport=true, prefix="touch_")
TaskStackViewTouchHandler mTouchHandler;
TaskStackAnimationHelper mAnimationHelper;
GradientDrawable mFreeformWorkspaceBackground;
ObjectAnimator mFreeformWorkspaceBackgroundAnimator;
ViewPool<TaskView, Task> mViewPool;
private TaskStackViewTouchHandler mTouchHandler;
private TaskStackAnimationHelper mAnimationHelper;
private GradientDrawable mFreeformWorkspaceBackground;
private ObjectAnimator mFreeformWorkspaceBackgroundAnimator;
private ViewPool<TaskView, Task> mViewPool;
ArrayList<TaskView> mTaskViews = new ArrayList<>();
ArrayList<TaskViewTransform> mCurrentTaskTransforms = new ArrayList<>();
ArraySet<Task.TaskKey> mIgnoreTasks = new ArraySet<>();
AnimationProps mDeferredTaskViewLayoutAnimation = null;
private ArrayList<TaskView> mTaskViews = new ArrayList<>();
private ArrayList<TaskViewTransform> mCurrentTaskTransforms = new ArrayList<>();
private ArraySet<Task.TaskKey> mIgnoreTasks = new ArraySet<>();
private AnimationProps mDeferredTaskViewLayoutAnimation = null;
@ViewDebug.ExportedProperty(deepExport=true, prefix="doze_")
DozeTrigger mUIDozeTrigger;
private DozeTrigger mUIDozeTrigger;
@ViewDebug.ExportedProperty(deepExport=true, prefix="focused_task_")
Task mFocusedTask;
private Task mFocusedTask;
int mTaskCornerRadiusPx;
private int mTaskCornerRadiusPx;
private int mDividerSize;
private int mStartTimerIndicatorDuration;
@ViewDebug.ExportedProperty(category="recents")
boolean mTaskViewsClipDirty = true;
private boolean mTaskViewsClipDirty = true;
@ViewDebug.ExportedProperty(category="recents")
boolean mAwaitingFirstLayout = true;
private boolean mAwaitingFirstLayout = true;
@ViewDebug.ExportedProperty(category="recents")
@InitialStateAction
int mInitialState = INITIAL_STATE_UPDATE_ALL;
private int mInitialState = INITIAL_STATE_UPDATE_ALL;
@ViewDebug.ExportedProperty(category="recents")
boolean mInMeasureLayout = false;
private boolean mInMeasureLayout = false;
@ViewDebug.ExportedProperty(category="recents")
boolean mEnterAnimationComplete = false;
private boolean mEnterAnimationComplete = false;
@ViewDebug.ExportedProperty(category="recents")
boolean mTouchExplorationEnabled;
private boolean mTouchExplorationEnabled;
@ViewDebug.ExportedProperty(category="recents")
boolean mScreenPinningEnabled;
@@ -183,12 +185,17 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// The current window bounds are dynamic and may change as the user drags and drops
@ViewDebug.ExportedProperty(category="recents")
private Rect mWindowRect = new Rect();
// The current display bounds
@ViewDebug.ExportedProperty(category="recents")
private Rect mDisplayRect = new Rect();
// The current display orientation
@ViewDebug.ExportedProperty(category="recents")
private int mDisplayOrientation = Configuration.ORIENTATION_UNDEFINED;
private Rect mTmpRect = new Rect();
private ArrayMap<Task.TaskKey, TaskView> mTmpTaskViewMap = new ArrayMap<>();
private List<TaskView> mTmpTaskViews = new ArrayList<>();
private TaskViewTransform mTmpTransform = new TaskViewTransform();
private ArrayList<TaskViewTransform> mTmpTaskTransforms = new ArrayList<>();
private int[] mTmpIntPair = new int[2];
private boolean mResetToInitialStateWhenResized;
private int mLastWidth;
@@ -248,6 +255,8 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
mTaskCornerRadiusPx = res.getDimensionPixelSize(
R.dimen.recents_task_view_rounded_corners_radius);
mDividerSize = ssp.getDockedDividerSize(context);
mDisplayOrientation = Utilities.getAppConfiguration(mContext).orientation;
mDisplayRect = ssp.getDisplayRect();
int taskBarDismissDozeDelaySeconds = getResources().getInteger(
R.integer.recents_task_bar_dismiss_delay_seconds);
@@ -1150,7 +1159,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// Update the stable stack bounds, but only update the current stack bounds if the stable
// bounds have changed. This is because we may get spurious measures while dragging where
// our current stack bounds reflect the target drop region.
mLayoutAlgorithm.getTaskStackBounds(new Rect(0, 0, width, height),
mLayoutAlgorithm.getTaskStackBounds(mDisplayRect, new Rect(0, 0, width, height),
mLayoutAlgorithm.mSystemInsets.top, mLayoutAlgorithm.mSystemInsets.right, mTmpRect);
if (!mTmpRect.equals(mStableStackBounds)) {
mStableStackBounds.set(mTmpRect);
@@ -1160,9 +1169,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
// Compute the rects in the stack algorithm
mStableLayoutAlgorithm.initialize(mStableWindowRect, mStableStackBounds,
mStableLayoutAlgorithm.initialize(mDisplayRect, mStableWindowRect, mStableStackBounds,
TaskStackLayoutAlgorithm.StackState.getStackStateForStack(mStack));
mLayoutAlgorithm.initialize(mWindowRect, mStackBounds,
mLayoutAlgorithm.initialize(mDisplayRect, mWindowRect, mStackBounds,
TaskStackLayoutAlgorithm.StackState.getStackStateForStack(mStack));
updateLayoutAlgorithm(false /* boundScroll */);
@@ -1538,7 +1547,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
private void bindTaskView(TaskView tv, Task task) {
// Rebind the task and request that this task's data be filled into the TaskView
tv.onTaskBound(task);
tv.onTaskBound(task, mTouchExplorationEnabled, mDisplayOrientation, mDisplayRect);
// Load the task data
Recents.getTaskLoader().loadTaskData(task);
@@ -1789,7 +1798,8 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
public final void onBusEvent(DragDropTargetChangedEvent event) {
AnimationProps animation = new AnimationProps(250, Interpolators.FAST_OUT_SLOW_IN);
AnimationProps animation = new AnimationProps(SLOW_SYNC_STACK_DURATION,
Interpolators.FAST_OUT_SLOW_IN);
boolean ignoreTaskOverrides = false;
if (event.dropTarget instanceof TaskStack.DockState) {
// Calculate the new task stack bounds that matches the window size that Recents will
@@ -1802,11 +1812,11 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
int height = getMeasuredHeight();
height -= systemInsets.bottom;
systemInsets.bottom = 0;
mStackBounds.set(dockState.getDockedTaskStackBounds(getMeasuredWidth(),
mStackBounds.set(dockState.getDockedTaskStackBounds(mDisplayRect, getMeasuredWidth(),
height, mDividerSize, systemInsets,
mLayoutAlgorithm, getResources(), mWindowRect));
mLayoutAlgorithm.setSystemInsets(systemInsets);
mLayoutAlgorithm.initialize(mWindowRect, mStackBounds,
mLayoutAlgorithm.initialize(mDisplayRect, mWindowRect, mStackBounds,
TaskStackLayoutAlgorithm.StackState.getStackStateForStack(mStack));
updateLayoutAlgorithm(true /* boundScroll */);
ignoreTaskOverrides = true;
@@ -1817,7 +1827,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
mStackBounds.set(mStableStackBounds);
removeIgnoreTask(event.task);
mLayoutAlgorithm.setSystemInsets(mStableLayoutAlgorithm.mSystemInsets);
mLayoutAlgorithm.initialize(mWindowRect, mStackBounds,
mLayoutAlgorithm.initialize(mDisplayRect, mWindowRect, mStackBounds,
TaskStackLayoutAlgorithm.StackState.getStackStateForStack(mStack));
updateLayoutAlgorithm(true /* boundScroll */);
addIgnoreTask(event.task);
@@ -1960,6 +1970,10 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
public final void onBusEvent(ConfigurationChangedEvent event) {
if (event.fromDeviceOrientationChange) {
mDisplayOrientation = Utilities.getAppConfiguration(mContext).orientation;
mDisplayRect = Recents.getSystemServices().getDisplayRect();
}
reloadOnConfigurationChange();
// Notify the task views of the configuration change so they can reload their resources
@@ -2072,6 +2086,8 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
writer.print(" stackBounds="); writer.print(Utilities.dumpRect(mStackBounds));
writer.print(" stableWindow="); writer.print(Utilities.dumpRect(mStableWindowRect));
writer.print(" window="); writer.print(Utilities.dumpRect(mWindowRect));
writer.print(" display="); writer.print(Utilities.dumpRect(mDisplayRect));
writer.print(" orientation="); writer.print(mDisplayOrientation);
writer.print(" [0x"); writer.print(id); writer.print("]");
writer.println();

View File

@@ -126,21 +126,21 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks
};
@ViewDebug.ExportedProperty(category="recents")
float mDimAlpha;
float mActionButtonTranslationZ;
private float mDimAlpha;
private float mActionButtonTranslationZ;
@ViewDebug.ExportedProperty(deepExport=true, prefix="task_")
Task mTask;
private Task mTask;
@ViewDebug.ExportedProperty(category="recents")
boolean mTaskDataLoaded;
private boolean mTaskDataLoaded;
@ViewDebug.ExportedProperty(category="recents")
boolean mClipViewInStack = true;
private boolean mClipViewInStack = true;
@ViewDebug.ExportedProperty(category="recents")
boolean mTouchExplorationEnabled;
private boolean mTouchExplorationEnabled;
@ViewDebug.ExportedProperty(category="recents")
boolean mIsDisabledInSafeMode;
private boolean mIsDisabledInSafeMode;
@ViewDebug.ExportedProperty(deepExport=true, prefix="view_bounds_")
AnimateableViewBounds mViewBounds;
private AnimateableViewBounds mViewBounds;
private AnimatorSet mTransformAnimation;
private ObjectAnimator mDimAnimator;
@@ -152,12 +152,12 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks
TaskViewThumbnail mThumbnailView;
@ViewDebug.ExportedProperty(deepExport=true, prefix="header_")
TaskViewHeader mHeaderView;
View mActionButtonView;
View mIncompatibleAppToastView;
TaskViewCallbacks mCb;
private View mActionButtonView;
private View mIncompatibleAppToastView;
private TaskViewCallbacks mCb;
@ViewDebug.ExportedProperty(category="recents")
Point mDownTouchPos = new Point();
private Point mDownTouchPos = new Point();
private Toast mDisabledAppToast;
@@ -196,7 +196,6 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks
*/
void onReload(boolean isResumingFromVisible) {
resetNoUserInteractionState();
readSystemFlags();
if (!isResumingFromVisible) {
resetViewProperties();
}
@@ -212,12 +211,6 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks
return mViewBounds;
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
readSystemFlags();
}
@Override
protected void onFinishInflate() {
// Bind the views
@@ -598,12 +591,14 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks
/**** TaskCallbacks Implementation ****/
public void onTaskBound(Task t) {
public void onTaskBound(Task t, boolean touchExplorationEnabled, int displayOrientation,
Rect displayRect) {
SystemServicesProxy ssp = Recents.getSystemServices();
mTouchExplorationEnabled = touchExplorationEnabled;
mTask = t;
mTask.addCallback(this);
mIsDisabledInSafeMode = !mTask.isSystemApp && ssp.isInSafeMode();
mThumbnailView.bindToTask(mTask, mIsDisabledInSafeMode);
mThumbnailView.bindToTask(mTask, mIsDisabledInSafeMode, displayOrientation, displayRect);
mHeaderView.bindToTask(mTask, mTouchExplorationEnabled, mIsDisabledInSafeMode);
if (!t.isDockable && ssp.hasDockedTask()) {
@@ -709,12 +704,4 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks
}
EventBus.getDefault().unregister(this);
}
/**
* Reads current system flags related to accessibility and screen pinning.
*/
private void readSystemFlags() {
SystemServicesProxy ssp = Recents.getSystemServices();
mTouchExplorationEnabled = ssp.isTouchExplorationEnabled();
}
}

View File

@@ -29,16 +29,12 @@ import android.graphics.LightingColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Region;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewDebug;
import com.android.systemui.R;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.recents.model.Task;
@@ -53,41 +49,38 @@ public class TaskViewThumbnail extends View {
private Task mTask;
private int mDisplayOrientation = Configuration.ORIENTATION_UNDEFINED;
private Rect mDisplayRect = new Rect();
private int mOrientation = Configuration.ORIENTATION_UNDEFINED;
// Drawing
@ViewDebug.ExportedProperty(category="recents")
Rect mTaskViewRect = new Rect();
private Rect mTaskViewRect = new Rect();
@ViewDebug.ExportedProperty(category="recents")
Rect mThumbnailRect = new Rect();
private Rect mThumbnailRect = new Rect();
@ViewDebug.ExportedProperty(category="recents")
float mThumbnailScale;
float mFullscreenThumbnailScale;
ActivityManager.TaskThumbnailInfo mThumbnailInfo;
private float mThumbnailScale;
private float mFullscreenThumbnailScale;
private ActivityManager.TaskThumbnailInfo mThumbnailInfo;
int mCornerRadius;
private int mCornerRadius;
@ViewDebug.ExportedProperty(category="recents")
float mDimAlpha;
Matrix mScaleMatrix = new Matrix();
Paint mDrawPaint = new Paint();
Paint mBgFillPaint = new Paint();
BitmapShader mBitmapShader;
LightingColorFilter mLightingColorFilter = new LightingColorFilter(0xffffffff, 0);
private float mDimAlpha;
private Matrix mScaleMatrix = new Matrix();
private Paint mDrawPaint = new Paint();
private Paint mBgFillPaint = new Paint();
private BitmapShader mBitmapShader;
private LightingColorFilter mLightingColorFilter = new LightingColorFilter(0xffffffff, 0);
// Task bar clipping, the top of this thumbnail can be clipped against the opaque header
// bar that overlaps this thumbnail
View mTaskBar;
@ViewDebug.ExportedProperty(category="recents")
Rect mClipRect = new Rect();
// Clip the top of the thumbnail against the opaque header bar that overlaps this view
private View mTaskBar;
// Visibility optimization, if the thumbnail height is less than the height of the header
// bar for the task view, then just mark this thumbnail view as invisible
@ViewDebug.ExportedProperty(category="recents")
boolean mInvisible;
private boolean mInvisible;
@ViewDebug.ExportedProperty(category="recents")
boolean mDisabledInSafeMode;
private boolean mDisabledInSafeMode;
public TaskViewThumbnail(Context context) {
this(context, null);
@@ -128,15 +121,6 @@ public class TaskViewThumbnail extends View {
updateThumbnailScale();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
SystemServicesProxy ssp = Recents.getSystemServices();
mOrientation = Utilities.getAppConfiguration(mContext).orientation;
mDisplayRect = ssp.getDisplayRect();
}
@Override
protected void onDraw(Canvas canvas) {
if (mInvisible) {
@@ -247,7 +231,7 @@ public class TaskViewThumbnail extends View {
mThumbnailScale = 0f;
} else if (isStackTask) {
float invThumbnailScale = 1f / mFullscreenThumbnailScale;
if (mOrientation == Configuration.ORIENTATION_PORTRAIT) {
if (mDisplayOrientation == Configuration.ORIENTATION_PORTRAIT) {
if (mThumbnailInfo.screenOrientation == Configuration.ORIENTATION_PORTRAIT) {
// If we are in the same orientation as the screenshot, just scale it to the
// width of the task view
@@ -306,9 +290,11 @@ public class TaskViewThumbnail extends View {
/**
* Binds the thumbnail view to the task.
*/
void bindToTask(Task t, boolean disabledInSafeMode) {
void bindToTask(Task t, boolean disabledInSafeMode, int displayOrientation, Rect displayRect) {
mTask = t;
mDisabledInSafeMode = disabledInSafeMode;
mDisplayOrientation = displayOrientation;
mDisplayRect.set(displayRect);
if (t.colorBackground != 0) {
mBgFillPaint.setColor(t.colorBackground);
}