Merge changes Ia8a90434,I35f484c7,I2e87e764 into nyc-dev

* changes:
  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.
This commit is contained in:
Winson Chung
2016-04-22 22:15:45 +00:00
committed by Android (Google) Code Review
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);
}