From 0fb1e4b5a77cf169629b2d89cdeda54ea3995b24 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Thu, 24 May 2018 12:16:38 -0700 Subject: Cancelling quickscrub state incease we missed quickscrub end event > This can happen when the remote transition is cancelled while animating down during quickscrub, cause WindowTransformSwipeHandler to get invalidated and miss onQuickscrubEnd Bug: 80140388 Change-Id: I0221e301d4d633bab0defaa6af76e0054776a95a --- .../com/android/launcher3/uioverrides/FastOverviewState.java | 6 ++++++ quickstep/src/com/android/quickstep/QuickScrubController.java | 11 +++++++++++ .../com/android/quickstep/WindowTransformSwipeHandler.java | 1 + 3 files changed, 18 insertions(+) diff --git a/quickstep/src/com/android/launcher3/uioverrides/FastOverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/FastOverviewState.java index 43d982230..cd92314a7 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/FastOverviewState.java +++ b/quickstep/src/com/android/launcher3/uioverrides/FastOverviewState.java @@ -76,4 +76,10 @@ public class FastOverviewState extends OverviewState { return Math.min(Math.min(dp.availableHeightPx / usedHeight, dp.availableWidthPx / usedWidth), MAX_PREVIEW_SCALE_UP); } + + @Override + public void onStateDisabled(Launcher launcher) { + super.onStateDisabled(launcher); + launcher.getOverviewPanel().getQuickScrubController().cancelActiveQuickscrub(); + } } diff --git a/quickstep/src/com/android/quickstep/QuickScrubController.java b/quickstep/src/com/android/quickstep/QuickScrubController.java index 8e1a3d5d8..95a82dd86 100644 --- a/quickstep/src/com/android/quickstep/QuickScrubController.java +++ b/quickstep/src/com/android/quickstep/QuickScrubController.java @@ -132,6 +132,17 @@ public class QuickScrubController implements OnAlarmListener { } } + public void cancelActiveQuickscrub() { + if (!mInQuickScrub) { + return; + } + Log.d(TAG, "Quickscrub was active, cancelling"); + mInQuickScrub = false; + mActivityControlHelper = null; + mOnFinishedTransitionToQuickScrubRunnable = null; + mRecentsView.setNextPageSwitchRunnable(null); + } + /** * Initializes the UI for quick scrub, returns true if success. */ diff --git a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java index e93c80789..695e046b1 100644 --- a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java +++ b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java @@ -700,6 +700,7 @@ public class WindowTransformSwipeHandler { mRecentsView.setRunningTaskHidden(false); mRecentsView.setRunningTaskIconScaledDown(false /* isScaledDown */, false /* animate */); + mQuickScrubController.cancelActiveQuickscrub(); } private void notifyTransitionCancelled() { -- cgit v1.2.3 From 4ff7d8e7b37f92420159e0eda41f38b34aaada24 Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Thu, 24 May 2018 17:13:36 -0700 Subject: Use correct interpolator for recents scale when quick scrubbing Use same interpolator for scale and translationY so that they feel more coordinated. (They were already the same in all cases except when scrubbing when already in overview, which never had a scale component before.) Bug: 80139193 Change-Id: Id143b5cc9279d55aaa1b0444db5fe4b41ce92170 --- .../launcher3/uioverrides/RecentsViewStateController.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java index e3aabd6c8..ea27eb25b 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java @@ -76,15 +76,16 @@ public class RecentsViewStateController implements StateHandler { } PropertySetter setter = config.getPropertySetter(builder); float[] scaleTranslationYFactor = toState.getOverviewScaleAndTranslationYFactor(mLauncher); - Interpolator scaleInterpolator = builder.getInterpolator(ANIM_OVERVIEW_SCALE, LINEAR); - setter.setFloat(mRecentsView, SCALE_PROPERTY, scaleTranslationYFactor[0], scaleInterpolator); - Interpolator transYInterpolator = scaleInterpolator; + Interpolator scaleAndTransYInterpolator = builder.getInterpolator( + ANIM_OVERVIEW_SCALE, LINEAR); if (mLauncher.getStateManager().getState() == OVERVIEW && toState == FAST_OVERVIEW) { - transYInterpolator = Interpolators.clampToProgress(QUICK_SCRUB_START_INTERPOLATOR, 0, - QUICK_SCRUB_TRANSLATION_Y_FACTOR); + scaleAndTransYInterpolator = Interpolators.clampToProgress( + QUICK_SCRUB_START_INTERPOLATOR, 0, QUICK_SCRUB_TRANSLATION_Y_FACTOR); } + setter.setFloat(mRecentsView, SCALE_PROPERTY, scaleTranslationYFactor[0], + scaleAndTransYInterpolator); setter.setFloat(mRecentsView, TRANSLATION_Y_FACTOR, scaleTranslationYFactor[1], - transYInterpolator); + scaleAndTransYInterpolator); setter.setFloat(mRecentsViewContainer, CONTENT_ALPHA, toState.overviewUi ? 1 : 0, builder.getInterpolator(ANIM_OVERVIEW_FADE, AGGRESSIVE_EASE_IN_OUT)); -- cgit v1.2.3 From 012d39a0e954614d41229e35af5152dbd3b27efb Mon Sep 17 00:00:00 2001 From: Jon Miranda Date: Fri, 25 May 2018 10:37:53 -0700 Subject: Fix crash caused by removing update listener in update listener. Bug: 80236772 Test: Fling all apps open, and catch it before it reaches the top Change-Id: I082a26b97afb7dbc162758ff9654e4a3707f9d7e --- src/com/android/launcher3/allapps/AllAppsContainerView.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java index 68ad6e346..72ba418b2 100644 --- a/src/com/android/launcher3/allapps/AllAppsContainerView.java +++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java @@ -466,9 +466,12 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo */ public void addSpringFromFlingUpdateListener(ValueAnimator animator, float velocity) { animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + boolean shouldSpring = true; + @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { - if (valueAnimator.getAnimatedFraction() >= FLING_ANIMATION_THRESHOLD) { + if (shouldSpring + && valueAnimator.getAnimatedFraction() >= FLING_ANIMATION_THRESHOLD) { int searchViewId = getSearchView().getId(); addSpringView(searchViewId); @@ -481,7 +484,7 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo } }); - animator.removeUpdateListener(this); + shouldSpring = false; } } }); -- cgit v1.2.3 From db9f86a472844aa3a24c422983839ffd0253e2f8 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Wed, 23 May 2018 15:49:39 -0700 Subject: Accounting for view translation when calculating the focus location Bug: 80160107 Change-Id: Ibb0cb82c33c141bb3abf9b7576be4253630cb8c5 --- .../launcher3/keyboard/ViewGroupFocusHelper.java | 23 ++-------------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/src/com/android/launcher3/keyboard/ViewGroupFocusHelper.java b/src/com/android/launcher3/keyboard/ViewGroupFocusHelper.java index bd5c06e5b..fde220cbf 100644 --- a/src/com/android/launcher3/keyboard/ViewGroupFocusHelper.java +++ b/src/com/android/launcher3/keyboard/ViewGroupFocusHelper.java @@ -18,7 +18,6 @@ package com.android.launcher3.keyboard; import android.graphics.Rect; import android.view.View; -import android.view.View.OnFocusChangeListener; import com.android.launcher3.PagedView; @@ -52,8 +51,8 @@ public class ViewGroupFocusHelper extends FocusIndicatorHelper { private void computeLocationRelativeToContainer(View child, Rect outRect) { View parent = (View) child.getParent(); - outRect.left += child.getLeft(); - outRect.top += child.getTop(); + outRect.left += child.getX(); + outRect.top += child.getY(); if (parent != mContainer) { if (parent instanceof PagedView) { @@ -64,22 +63,4 @@ public class ViewGroupFocusHelper extends FocusIndicatorHelper { computeLocationRelativeToContainer(parent, outRect); } } - - /** - * Sets the alpha of this FocusIndicatorHelper to 0 when a view with this listener - * receives focus. - */ - public View.OnFocusChangeListener getHideIndicatorOnFocusListener() { - return new OnFocusChangeListener() { - @Override - public void onFocusChange(View v, boolean hasFocus) { - if (hasFocus) { - endCurrentAnimation(); - setCurrentView(null); - setAlpha(0); - invalidateDirty(); - } - } - }; - } } -- cgit v1.2.3 From de184a243d7e5190d6e2b5fb6cc57f372e9210cc Mon Sep 17 00:00:00 2001 From: Hyunyoung Song Date: Thu, 24 May 2018 13:05:50 -0700 Subject: Add logging for selected text and split screen Bug: 79787082 action:LONGPRESS Source child:TASK_PREVIEW action:TAP Source child:SPLIT_SCREEN_TARGET Change-Id: Ica5a3955f092c6678e646b6df76567cdfa3485df --- protos/launcher_log.proto | 2 ++ quickstep/src/com/android/quickstep/TaskSystemShortcut.java | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/protos/launcher_log.proto b/protos/launcher_log.proto index cab20a3be..06e6a923d 100644 --- a/protos/launcher_log.proto +++ b/protos/launcher_log.proto @@ -110,6 +110,8 @@ enum ControlType { QUICK_SCRUB_BUTTON = 12; CLEAR_ALL_BUTTON = 13; CANCEL_TARGET = 14; + TASK_PREVIEW = 15; + SPLIT_SCREEN_TARGET = 16; } enum TipType { diff --git a/quickstep/src/com/android/quickstep/TaskSystemShortcut.java b/quickstep/src/com/android/quickstep/TaskSystemShortcut.java index 228af8e90..f82ff8c53 100644 --- a/quickstep/src/com/android/quickstep/TaskSystemShortcut.java +++ b/quickstep/src/com/android/quickstep/TaskSystemShortcut.java @@ -16,6 +16,8 @@ package com.android.quickstep; +import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.TAP; + import android.content.ComponentName; import android.content.Intent; import android.graphics.Bitmap; @@ -35,6 +37,7 @@ import com.android.launcher3.ItemInfo; import com.android.launcher3.R; import com.android.launcher3.ShortcutInfo; import com.android.launcher3.popup.SystemShortcut; +import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.launcher3.util.InstantAppResolver; import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.TaskThumbnailView; @@ -166,7 +169,8 @@ public class TaskSystemShortcut extends SystemShortcut Log.w(TAG, "Failed to notify SysUI of split screen: ", e); return; } - + activity.getUserEventDispatcher().logActionOnControl(TAP, + LauncherLogProto.ControlType.SPLIT_SCREEN_TARGET); // Add a device profile change listener to kick off animating the side tasks // once we enter multiwindow mode and relayout activity.addOnDeviceProfileChangeListener(onDeviceProfileChangeListener); -- cgit v1.2.3 From 35cde20a171a774f048b6c25013d1389c734c0c8 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Thu, 24 May 2018 16:45:26 -0700 Subject: Tweaking quickscrub launch animation for new task sizes. Bug: 79945202 Change-Id: Ibe1e53d45bc3fda325cebc14aa6a61f61f08edb0 --- .../launcher3/LauncherAppTransitionManagerImpl.java | 16 +++++++++++----- .../src/com/android/quickstep/QuickScrubController.java | 6 +++++- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java index 6703bb546..87854234b 100644 --- a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java +++ b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java @@ -105,6 +105,7 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag private static final int APP_LAUNCH_ALPHA_DURATION = 50; public static final int RECENTS_LAUNCH_DURATION = 336; + public static final int RECENTS_QUICKSCRUB_LAUNCH_DURATION = 300; private static final int LAUNCHER_RESUME_START_DELAY = 100; private static final int CLOSING_TRANSITION_DURATION_MS = 250; @@ -253,15 +254,21 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag RecentsView recentsView = mLauncher.getOverviewPanel(); boolean launcherClosing = launcherIsATargetWithMode(targets, MODE_CLOSING); boolean skipLauncherChanges = !launcherClosing; + boolean isLaunchingFromQuickscrub = + recentsView.getQuickScrubController().isWaitingForTaskLaunch(); TaskView taskView = findTaskViewToLaunch(mLauncher, v, targets); if (taskView == null) { return false; } + int duration = isLaunchingFromQuickscrub + ? RECENTS_QUICKSCRUB_LAUNCH_DURATION + : RECENTS_LAUNCH_DURATION; + ClipAnimationHelper helper = new ClipAnimationHelper(); target.play(getRecentsWindowAnimator(taskView, skipLauncherChanges, targets, helper) - .setDuration(RECENTS_LAUNCH_DURATION)); + .setDuration(duration)); Animator childStateAnimation = null; // Found a visible recents task that matches the opening app, lets launch the app from there @@ -270,7 +277,7 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag if (launcherClosing) { launcherAnim = recentsView.createAdjacentPageAnimForTaskLaunch(taskView, helper); launcherAnim.setInterpolator(Interpolators.TOUCH_RESPONSE_INTERPOLATOR); - launcherAnim.setDuration(RECENTS_LAUNCH_DURATION); + launcherAnim.setDuration(duration); // Make sure recents gets fixed up by resetting task alphas and scales, etc. windowAnimEndListener = new AnimatorListenerAdapter() { @@ -282,11 +289,10 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag }; } else { AnimatorPlaybackController controller = - mLauncher.getStateManager() - .createAnimationToNewWorkspace(NORMAL, RECENTS_LAUNCH_DURATION); + mLauncher.getStateManager().createAnimationToNewWorkspace(NORMAL, duration); controller.dispatchOnStart(); childStateAnimation = controller.getTarget(); - launcherAnim = controller.getAnimationPlayer().setDuration(RECENTS_LAUNCH_DURATION); + launcherAnim = controller.getAnimationPlayer().setDuration(duration); windowAnimEndListener = new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { diff --git a/quickstep/src/com/android/quickstep/QuickScrubController.java b/quickstep/src/com/android/quickstep/QuickScrubController.java index 8e1a3d5d8..3cd6b0175 100644 --- a/quickstep/src/com/android/quickstep/QuickScrubController.java +++ b/quickstep/src/com/android/quickstep/QuickScrubController.java @@ -40,7 +40,7 @@ import com.android.quickstep.views.TaskView; public class QuickScrubController implements OnAlarmListener { public static final int QUICK_SCRUB_FROM_APP_START_DURATION = 240; - public static final int QUICK_SCRUB_FROM_HOME_START_DURATION = 150; + public static final int QUICK_SCRUB_FROM_HOME_START_DURATION = 200; // We want the translation y to finish faster than the rest of the animation. public static final float QUICK_SCRUB_TRANSLATION_Y_FACTOR = 5f / 6; public static final Interpolator QUICK_SCRUB_START_INTERPOLATOR = FAST_OUT_SLOW_IN; @@ -145,6 +145,10 @@ public class QuickScrubController implements OnAlarmListener { return true; } + public boolean isWaitingForTaskLaunch() { + return mWaitingForTaskLaunch; + } + /** * Attempts to go to normal overview or back to home, so UI doesn't prevent user interaction. */ -- cgit v1.2.3 From 4dcda06542648f19ca496085a76c3184492d1d48 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Fri, 25 May 2018 10:32:40 -0700 Subject: Fixing launcher going to a different state when dragging an icon from different activity Bug: 80191074 Change-Id: I45ea646dc2bd21627e8b724dac9c9fc23c18797d --- .../LauncherAppTransitionManagerImpl.java | 9 +++- .../android/launcher3/LauncherInitListener.java | 6 ++- .../android/launcher3/uioverrides/UiFactory.java | 24 ++++++++++ .../util/RemoteFadeOutAnimationListener.java | 53 ++++++++++++++++++++++ .../launcher3/dragndrop/BaseItemDragListener.java | 2 +- .../launcher3/dragndrop/PinItemDragListener.java | 20 ++++++++ .../android/launcher3/uioverrides/UiFactory.java | 4 ++ 7 files changed, 114 insertions(+), 4 deletions(-) create mode 100644 quickstep/src/com/android/quickstep/util/RemoteFadeOutAnimationListener.java diff --git a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java index 6703bb546..fe2a98fea 100644 --- a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java +++ b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java @@ -50,6 +50,7 @@ import android.graphics.Matrix; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.os.Build; +import android.os.CancellationSignal; import android.os.Handler; import android.os.Looper; import android.util.Log; @@ -236,8 +237,14 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag return bounds; } - public void setRemoteAnimationProvider(RemoteAnimationProvider animationProvider) { + public void setRemoteAnimationProvider(final RemoteAnimationProvider animationProvider, + CancellationSignal cancellationSignal) { mRemoteAnimationProvider = animationProvider; + cancellationSignal.setOnCancelListener(() -> { + if (animationProvider == mRemoteAnimationProvider) { + mRemoteAnimationProvider = null; + } + }); } /** diff --git a/quickstep/src/com/android/launcher3/LauncherInitListener.java b/quickstep/src/com/android/launcher3/LauncherInitListener.java index e5e377f83..08b6bfc6a 100644 --- a/quickstep/src/com/android/launcher3/LauncherInitListener.java +++ b/quickstep/src/com/android/launcher3/LauncherInitListener.java @@ -20,6 +20,7 @@ import android.content.Context; import android.content.Intent; import android.os.Build; import android.os.Bundle; +import android.os.CancellationSignal; import android.os.Handler; import com.android.launcher3.states.InternalStateHandler; @@ -48,10 +49,11 @@ public class LauncherInitListener extends InternalStateHandler implements Activi // Set a one-time animation provider. After the first call, this will get cleared. // TODO: Probably also check the intended target id. + CancellationSignal cancellationSignal = new CancellationSignal(); appTransitionManager.setRemoteAnimationProvider((targets) -> { // On the first call clear the reference. - appTransitionManager.setRemoteAnimationProvider(null); + cancellationSignal.cancel(); RemoteAnimationProvider provider = mRemoteAnimationProvider; mRemoteAnimationProvider = null; @@ -59,7 +61,7 @@ public class LauncherInitListener extends InternalStateHandler implements Activi return provider.createWindowAnimation(targets); } return null; - }); + }, cancellationSignal); } OverviewCallbacks.get(launcher).onInitOverviewTransition(); return mOnInitListener.test(launcher, alreadyOnHome); diff --git a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java index d0c7b2117..dd5dcbeaf 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java +++ b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java @@ -25,14 +25,19 @@ import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.allapps.DiscoveryBounce.HOME_BOUNCE_SEEN; import static com.android.launcher3.allapps.DiscoveryBounce.SHELF_BOUNCE_SEEN; +import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING; +import android.animation.AnimatorSet; +import android.animation.ValueAnimator; import android.app.Activity; import android.content.Context; +import android.os.CancellationSignal; import android.util.Base64; import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Launcher; +import com.android.launcher3.LauncherAppTransitionManagerImpl; import com.android.launcher3.LauncherState; import com.android.launcher3.LauncherStateManager; import com.android.launcher3.LauncherStateManager.StateHandler; @@ -41,6 +46,8 @@ import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.util.TouchController; import com.android.quickstep.OverviewInteractionState; import com.android.quickstep.RecentsModel; +import com.android.quickstep.util.RemoteAnimationTargetSet; +import com.android.quickstep.util.RemoteFadeOutAnimationListener; import com.android.quickstep.views.RecentsView; import com.android.systemui.shared.system.ActivityCompat; import com.android.systemui.shared.system.WindowManagerWrapper; @@ -179,6 +186,23 @@ public class UiFactory { } } + public static void useFadeOutAnimationForLauncherStart(Launcher launcher, + CancellationSignal cancellationSignal) { + LauncherAppTransitionManagerImpl appTransitionManager = + (LauncherAppTransitionManagerImpl) launcher.getAppTransitionManager(); + appTransitionManager.setRemoteAnimationProvider((targets) -> { + + // On the first call clear the reference. + cancellationSignal.cancel(); + + ValueAnimator fadeAnimation = ValueAnimator.ofFloat(1, 0); + fadeAnimation.addUpdateListener(new RemoteFadeOutAnimationListener(targets)); + AnimatorSet anim = new AnimatorSet(); + anim.play(fadeAnimation); + return anim; + }, cancellationSignal); + } + public static boolean dumpActivity(Activity activity, PrintWriter writer) { if (!Utilities.IS_DEBUG_DEVICE) { return false; diff --git a/quickstep/src/com/android/quickstep/util/RemoteFadeOutAnimationListener.java b/quickstep/src/com/android/quickstep/util/RemoteFadeOutAnimationListener.java new file mode 100644 index 000000000..40dd74bbb --- /dev/null +++ b/quickstep/src/com/android/quickstep/util/RemoteFadeOutAnimationListener.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2018 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.quickstep.util; + +import static com.android.quickstep.util.RemoteAnimationProvider.prepareTargetsForFirstFrame; +import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING; + +import android.animation.ValueAnimator; +import android.animation.ValueAnimator.AnimatorUpdateListener; + +import com.android.systemui.shared.system.RemoteAnimationTargetCompat; +import com.android.systemui.shared.system.TransactionCompat; + +/** + * Animation listener which fades out the closing targets + */ +public class RemoteFadeOutAnimationListener implements AnimatorUpdateListener { + + private final RemoteAnimationTargetSet mTarget; + private boolean mFirstFrame = true; + + public RemoteFadeOutAnimationListener(RemoteAnimationTargetCompat[] targets) { + mTarget = new RemoteAnimationTargetSet(targets, MODE_CLOSING); + } + + @Override + public void onAnimationUpdate(ValueAnimator valueAnimator) { + TransactionCompat t = new TransactionCompat(); + if (mFirstFrame) { + prepareTargetsForFirstFrame(mTarget.unfilteredApps, t, MODE_CLOSING); + mFirstFrame = false; + } + + float alpha = 1 - valueAnimator.getAnimatedFraction(); + for (RemoteAnimationTargetCompat app : mTarget.apps) { + t.setAlpha(app.leash, alpha); + } + t.apply(); + } +} diff --git a/src/com/android/launcher3/dragndrop/BaseItemDragListener.java b/src/com/android/launcher3/dragndrop/BaseItemDragListener.java index df4a7c1f5..1e84b416b 100644 --- a/src/com/android/launcher3/dragndrop/BaseItemDragListener.java +++ b/src/com/android/launcher3/dragndrop/BaseItemDragListener.java @@ -159,7 +159,7 @@ public abstract class BaseItemDragListener extends InternalStateHandler implemen postCleanup(); } - private void postCleanup() { + protected void postCleanup() { clearReference(); if (mLauncher != null) { // Remove any drag params from the launcher intent since the drag operation is complete. diff --git a/src/com/android/launcher3/dragndrop/PinItemDragListener.java b/src/com/android/launcher3/dragndrop/PinItemDragListener.java index 924bb4c25..07eb0d60b 100644 --- a/src/com/android/launcher3/dragndrop/PinItemDragListener.java +++ b/src/com/android/launcher3/dragndrop/PinItemDragListener.java @@ -22,14 +22,17 @@ import android.content.pm.LauncherApps.PinItemRequest; import android.graphics.Rect; import android.os.Build; import android.os.Bundle; +import android.os.CancellationSignal; import android.view.DragEvent; import android.view.View; import android.widget.RemoteViews; import com.android.launcher3.DragSource; import com.android.launcher3.ItemInfo; +import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAppWidgetProviderInfo; import com.android.launcher3.PendingAddItemInfo; +import com.android.launcher3.uioverrides.UiFactory; import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.launcher3.widget.PendingAddShortcutInfo; import com.android.launcher3.widget.PendingAddWidgetInfo; @@ -44,11 +47,13 @@ import com.android.launcher3.widget.WidgetAddFlowHandler; public class PinItemDragListener extends BaseItemDragListener { private final PinItemRequest mRequest; + private final CancellationSignal mCancelSignal; public PinItemDragListener(PinItemRequest request, Rect previewRect, int previewBitmapWidth, int previewViewWidth) { super(previewRect, previewBitmapWidth, previewViewWidth); mRequest = request; + mCancelSignal = new CancellationSignal(); } @Override @@ -59,6 +64,15 @@ public class PinItemDragListener extends BaseItemDragListener { return super.onDragStart(event); } + @Override + public boolean init(Launcher launcher, boolean alreadyOnHome) { + super.init(launcher, alreadyOnHome); + if (!alreadyOnHome) { + UiFactory.useFadeOutAnimationForLauncherStart(launcher, mCancelSignal); + } + return false; + } + @Override protected PendingItemDragHelper createDragHelper() { final PendingAddItemInfo item; @@ -95,6 +109,12 @@ public class PinItemDragListener extends BaseItemDragListener { targetParent.containerType = LauncherLogProto.ContainerType.PINITEM; } + @Override + protected void postCleanup() { + super.postCleanup(); + mCancelSignal.cancel(); + } + public static RemoteViews getPreview(PinItemRequest request) { Bundle extras = request.getExtras(); if (extras != null && diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java b/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java index db98f9a80..5a7e50fae 100644 --- a/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java +++ b/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java @@ -18,6 +18,7 @@ package com.android.launcher3.uioverrides; import android.app.Activity; import android.content.Context; +import android.os.CancellationSignal; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherStateManager.StateHandler; @@ -51,6 +52,9 @@ public class UiFactory { public static void onTrimMemory(Launcher launcher, int level) { } + public static void useFadeOutAnimationForLauncherStart(Launcher launcher, + CancellationSignal cancellationSignal) { } + public static boolean dumpActivity(Activity activity, PrintWriter writer) { return false; } -- cgit v1.2.3 From 528b9e0615e9427eda667599b387a67ff1a393a8 Mon Sep 17 00:00:00 2001 From: Vadim Tryshev Date: Thu, 24 May 2018 18:22:03 -0700 Subject: Reporting range of visible tasks Also fixes task position being incorrectly reported specifically for swipe events due to using stale getCurrentPage(). Bug: 72222505 Test: Manual Change-Id: Ic79b67f8a6ffbfabc397b411b14afc309405197e --- .../com/android/quickstep/views/RecentsView.java | 9 ++++--- src/com/android/launcher3/PagedView.java | 31 ++++++++++++++++++++++ src/com/android/launcher3/Workspace.java | 25 +++-------------- 3 files changed, 39 insertions(+), 26 deletions(-) diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index dee15d0d7..02cdd3a7c 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -1307,10 +1307,11 @@ public abstract class RecentsView extends PagedView impl super.onInitializeAccessibilityEvent(event); if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) { - final int visiblePageNumber = getChildCount() - getCurrentPage() - 1; - event.setFromIndex(visiblePageNumber); - event.setToIndex(visiblePageNumber); - event.setItemCount(getChildCount()); + final int childCount = getChildCount(); + final int[] visibleTasks = getVisibleChildrenRange(); + event.setFromIndex(childCount - visibleTasks[1] - 1); + event.setToIndex(childCount - visibleTasks[0] - 1); + event.setItemCount(childCount); } } diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java index 5cc2e8fc5..62b581f83 100644 --- a/src/com/android/launcher3/PagedView.java +++ b/src/com/android/launcher3/PagedView.java @@ -152,6 +152,8 @@ public abstract class PagedView extends ViewGrou // Similar to the platform implementation of isLayoutValid(); protected boolean mIsLayoutValid; + private int[] mTmpIntPair = new int[2]; + public PagedView(Context context) { this(context, null); } @@ -1600,4 +1602,33 @@ public abstract class PagedView extends ViewGrou boolean shouldIncludeView(View view); } + + public int[] getVisibleChildrenRange() { + float visibleLeft = 0; + float visibleRight = visibleLeft + getMeasuredWidth(); + float scaleX = getScaleX(); + if (scaleX < 1 && scaleX > 0) { + float mid = getMeasuredWidth() / 2; + visibleLeft = mid - ((mid - visibleLeft) / scaleX); + visibleRight = mid + ((visibleRight - mid) / scaleX); + } + + int leftChild = -1; + int rightChild = -1; + final int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + final View child = getPageAt(i); + + float left = child.getLeft() + child.getTranslationX() - getScrollX(); + if (left <= visibleRight && (left + child.getMeasuredWidth()) >= visibleLeft) { + if (leftChild == -1) { + leftChild = i; + } + rightChild = i; + } + } + mTmpIntPair[0] = leftChild; + mTmpIntPair[1] = rightChild; + return mTmpIntPair; + } } diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index 42e8fde3b..7e652cbc5 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -1381,28 +1381,9 @@ public class Workspace extends PagedView if (mChildrenLayersEnabled) { final int screenCount = getChildCount(); - float visibleLeft = 0; - float visibleRight = visibleLeft + getMeasuredWidth(); - float scaleX = getScaleX(); - if (scaleX < 1 && scaleX > 0) { - float mid = getMeasuredWidth() / 2; - visibleLeft = mid - ((mid - visibleLeft) / scaleX); - visibleRight = mid + ((visibleRight - mid) / scaleX); - } - - int leftScreen = -1; - int rightScreen = -1; - for (int i = 0; i < screenCount; i++) { - final View child = getPageAt(i); - - float left = child.getLeft() + child.getTranslationX() - getScrollX(); - if (left <= visibleRight && (left + child.getMeasuredWidth()) >= visibleLeft) { - if (leftScreen == -1) { - leftScreen = i; - } - rightScreen = i; - } - } + final int[] visibleScreens = getVisibleChildrenRange(); + int leftScreen = visibleScreens[0]; + int rightScreen = visibleScreens[1]; if (mForceDrawAdjacentPages) { // In overview mode, make sure that the two side pages are visible. leftScreen = Utilities.boundToRange(getCurrentPage() - 1, 0, rightScreen); -- cgit v1.2.3 From 49df554dc22521b2b4cb56f879846ccce81f4e0d Mon Sep 17 00:00:00 2001 From: Hyunyoung Song Date: Fri, 25 May 2018 16:30:23 -0700 Subject: Fix clipping of adaptive icons Bug:62372639 Context: only noticeable on large form factor AND Large display setting Ceiling operation is needed to calculate offset of the drawing. Change-Id: I7c77fa53f0811990b8cfdc3a12e2b43eb4d2d73e --- src/com/android/launcher3/graphics/LauncherIcons.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/com/android/launcher3/graphics/LauncherIcons.java b/src/com/android/launcher3/graphics/LauncherIcons.java index f020d2d7c..89ba72abf 100644 --- a/src/com/android/launcher3/graphics/LauncherIcons.java +++ b/src/com/android/launcher3/graphics/LauncherIcons.java @@ -330,9 +330,9 @@ public class LauncherIcons implements AutoCloseable { mOldBounds.set(icon.getBounds()); if (Utilities.ATLEAST_OREO && icon instanceof AdaptiveIconDrawable) { - int offset = Math.max((int)(BLUR_FACTOR * textureWidth), Math.min(left, top)); + int offset = Math.max((int) Math.ceil(BLUR_FACTOR * textureWidth), Math.max(left, top)); int size = Math.max(width, height); - icon.setBounds(offset, offset, size, size); + icon.setBounds(offset, offset, offset + size, offset + size); } else { icon.setBounds(left, top, left+width, top+height); } -- cgit v1.2.3 From 68ac46da0c79408c6b0f66960cfb0a87ce266e2a Mon Sep 17 00:00:00 2001 From: Vadim Tryshev Date: Fri, 25 May 2018 20:03:52 -0700 Subject: Fix testWidgetsContainerFling It relies on the presence of the popup in the accessibility view. Bug: 72967764 Test: atest google/perf/jank/SystemUI/UbSystemUIJankTests:android.platform.systemui.tests.jank.LauncherJankTests#testWidgetsContainerFling Change-Id: I9d41ddcd60f9dc7626a96762b4e78a7b862aa1c9 --- res/layout/longpress_options_menu.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/res/layout/longpress_options_menu.xml b/res/layout/longpress_options_menu.xml index 168dbc3a2..20bb5b81b 100644 --- a/res/layout/longpress_options_menu.xml +++ b/res/layout/longpress_options_menu.xml @@ -22,4 +22,5 @@ android:clipToPadding="false" android:clipChildren="false" android:elevation="@dimen/deep_shortcuts_elevation" + android:importantForAccessibility="yes" android:orientation="vertical" /> -- cgit v1.2.3 From 1d1a3d7242d0c0e89c856d00e06bc3df7b55bc9d Mon Sep 17 00:00:00 2001 From: Jorim Jaggi Date: Mon, 28 May 2018 18:08:40 +0200 Subject: Fix binder call for app opening Needs to acquire the AM/WM lock, which may cause jank during the animation. Test: Open app, observe no binder calls. Bug: 78611607 Change-Id: I3459383c9597801405dd9c688837a2bffeeb7f9e --- .../com/android/launcher3/LauncherAppTransitionManagerImpl.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java index 6703bb546..3075c3f48 100644 --- a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java +++ b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java @@ -581,11 +581,8 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag float offsetX = (scaledWindowWidth - iconWidth) / 2; float offsetY = (scaledWindowHeight - iconHeight) / 2; - if (mLauncher.isInMultiWindowModeCompat()) { - mFloatingView.getLocationOnScreen(floatingViewBounds); - } else { - mFloatingView.getLocationInWindow(floatingViewBounds); - } + mFloatingView.getLocationOnScreen(floatingViewBounds); + float transX0 = floatingViewBounds[0] - offsetX; float transY0 = floatingViewBounds[1] - offsetY; matrix.postTranslate(transX0, transY0); -- cgit v1.2.3 From a3e48d8035c39f47e5dde30061adc0b53824e9e3 Mon Sep 17 00:00:00 2001 From: Vadim Tryshev Date: Thu, 24 May 2018 14:21:05 -0700 Subject: Enable accessibility of Clear All button. The button appears in the accessibility hierarchy as a child of RecentsView. This makes both Talkback and Switch access to work with it normally. Bug: 80156299 Test: Manual Change-Id: Ife2044b2ef78fb27b32f2d33fb17744662a2b054 --- .../android/quickstep/views/ClearAllButton.java | 13 ++----- .../com/android/quickstep/views/RecentsView.java | 44 +++++++++++++++++++++- .../quickstep/views/RecentsViewContainer.java | 5 +++ 3 files changed, 51 insertions(+), 11 deletions(-) diff --git a/quickstep/src/com/android/quickstep/views/ClearAllButton.java b/quickstep/src/com/android/quickstep/views/ClearAllButton.java index 25e3dc6c1..0025df136 100644 --- a/quickstep/src/com/android/quickstep/views/ClearAllButton.java +++ b/quickstep/src/com/android/quickstep/views/ClearAllButton.java @@ -16,13 +16,11 @@ package com.android.quickstep.views; -import static android.view.accessibility.AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS; - import android.content.Context; import android.graphics.Rect; -import android.os.Bundle; import android.support.annotation.Nullable; import android.util.AttributeSet; +import android.view.accessibility.AccessibilityNodeInfo; import android.widget.Button; public class ClearAllButton extends Button { @@ -37,12 +35,9 @@ public class ClearAllButton extends Button { } @Override - public boolean performAccessibilityAction(int action, Bundle arguments) { - final boolean res = super.performAccessibilityAction(action, arguments); - if (action == ACTION_ACCESSIBILITY_FOCUS) { - mRecentsView.revealClearAllButton(); - } - return res; + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setParent(mRecentsView); // Pretend we are a part of the task carousel. } @Override diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index 02cdd3a7c..e98b16a44 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -39,6 +39,7 @@ import android.graphics.Point; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.os.Build; +import android.os.Bundle; import android.os.Handler; import android.os.UserHandle; import android.support.annotation.Nullable; @@ -386,7 +387,13 @@ public abstract class RecentsView extends PagedView impl private void updateClearAllButtonAlpha() { if (mClearAllButton != null) { final float alpha = calculateClearAllButtonAlpha(); - mIsClearAllButtonFullyRevealed = alpha == 1; + final boolean revealed = alpha == 1; + if (mIsClearAllButtonFullyRevealed != revealed) { + mIsClearAllButtonFullyRevealed = revealed; + mClearAllButton.setImportantForAccessibility(revealed ? + IMPORTANT_FOR_ACCESSIBILITY_YES : + IMPORTANT_FOR_ACCESSIBILITY_NO); + } mClearAllButton.setAlpha(alpha * mContentAlpha); } } @@ -1284,8 +1291,31 @@ public abstract class RecentsView extends PagedView impl scrollTo(mIsRtl ? 0 : computeMaxScrollX(), 0); } + @Override + public boolean performAccessibilityAction(int action, Bundle arguments) { + if (getChildCount() > 0) { + switch (action) { + case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: { + if (!mIsClearAllButtonFullyRevealed && getCurrentPage() == getPageCount() - 1) { + revealClearAllButton(); + return true; + } + } + case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: { + if (mIsClearAllButtonFullyRevealed) { + setCurrentPage(getChildCount() - 1); + return true; + } + } + break; + } + } + return super.performAccessibilityAction(action, arguments); + } + @Override public void addChildrenForAccessibility(ArrayList outChildren) { + outChildren.add(mClearAllButton); for (int i = getChildCount() - 1; i >= 0; --i) { outChildren.add(getChildAt(i)); } @@ -1295,6 +1325,13 @@ public abstract class RecentsView extends PagedView impl public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); + if (getChildCount() > 0) { + info.addAction(mIsClearAllButtonFullyRevealed ? + AccessibilityNodeInfo.ACTION_SCROLL_FORWARD : + AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD); + info.setScrollable(true); + } + final AccessibilityNodeInfo.CollectionInfo collectionInfo = AccessibilityNodeInfo.CollectionInfo.obtain( 1, getChildCount(), false, @@ -1306,7 +1343,10 @@ public abstract class RecentsView extends PagedView impl public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); - if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) { + event.setScrollable(getPageCount() > 0); + + if (!mIsClearAllButtonFullyRevealed + && event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) { final int childCount = getChildCount(); final int[] visibleTasks = getVisibleChildrenRange(); event.setFromIndex(childCount - visibleTasks[1] - 1); diff --git a/quickstep/src/com/android/quickstep/views/RecentsViewContainer.java b/quickstep/src/com/android/quickstep/views/RecentsViewContainer.java index 31c8b6448..c6cd52769 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsViewContainer.java +++ b/quickstep/src/com/android/quickstep/views/RecentsViewContainer.java @@ -124,4 +124,9 @@ public class RecentsViewContainer extends InsettableFrameLayout { return mRecentsView.requestFocus(direction, previouslyFocusedRect) || super.requestFocus(direction, previouslyFocusedRect); } + + @Override + public void addChildrenForAccessibility(ArrayList outChildren) { + outChildren.add(mRecentsView); + } } \ No newline at end of file -- cgit v1.2.3 From 615ad40c38a75a197c2adf266a539e8a0258245d Mon Sep 17 00:00:00 2001 From: Tony Date: Tue, 29 May 2018 12:09:57 -0700 Subject: Fix clipping recents when scaling down - Parent shouldn't clip scaled down child - Remove outline provider from scaled down child so it doesn't clip Bug: 80267476 Change-Id: I9feb1ccf2069b8c88d8499e2813c818f9aea19af --- quickstep/res/layout/fallback_recents_activity.xml | 2 ++ quickstep/res/layout/overview_panel.xml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/quickstep/res/layout/fallback_recents_activity.xml b/quickstep/res/layout/fallback_recents_activity.xml index 7ecab3201..84e13add5 100644 --- a/quickstep/res/layout/fallback_recents_activity.xml +++ b/quickstep/res/layout/fallback_recents_activity.xml @@ -24,6 +24,7 @@ android:id="@+id/overview_panel_container" android:layout_width="match_parent" android:layout_height="match_parent" + android:clipChildren="false" > @@ -33,6 +34,7 @@ android:layout_height="match_parent" android:clipChildren="false" android:clipToPadding="false" + android:outlineProvider="none" android:focusableInTouchMode="true" android:theme="@style/HomeScreenElementTheme" > diff --git a/quickstep/res/layout/overview_panel.xml b/quickstep/res/layout/overview_panel.xml index 919afdb37..840b040ac 100644 --- a/quickstep/res/layout/overview_panel.xml +++ b/quickstep/res/layout/overview_panel.xml @@ -18,6 +18,7 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" + android:clipChildren="false" android:visibility="invisible" > @@ -28,6 +29,7 @@ android:layout_height="match_parent" android:clipChildren="false" android:clipToPadding="false" + android:outlineProvider="none" android:focusableInTouchMode="true" android:accessibilityPaneTitle="@string/accessibility_recent_apps" android:theme="@style/HomeScreenElementTheme" -- cgit v1.2.3 From 9bb8ffb5e303597bd65ee4cae957c64c1f532d10 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Thu, 24 May 2018 17:11:16 -0700 Subject: Various quickscrub fixes > Fixing PagedView resetting the currentPage, if scrollToPage was called before first layout This causes quickscrub to jump back to the current task if launcher activity was dead. > Fixing missing callbacks in DeferredTouchConsumer causing missed quick scrub flings > Sending the resents animation callbacks on the motion queue thread, to avoid synchronization issues with sysui callbacks. > Waiting until the recents animation is received before starting the scale down animation > Calculating the offset for quickscrub statically incase launcher activity was dead Bug: 80214390 Change-Id: I1b7d00b7b266655a92fcd6239f25ba191655150f --- .../android/quickstep/ActivityControlHelper.java | 20 +++-- .../android/quickstep/DeferredTouchConsumer.java | 15 ++++ .../com/android/quickstep/MotionEventQueue.java | 11 +++ .../quickstep/OtherActivityTouchConsumer.java | 90 +++++++++++++++------- .../android/quickstep/RecentsAnimationWrapper.java | 21 +++++ .../src/com/android/quickstep/TouchConsumer.java | 2 + .../quickstep/WindowTransformSwipeHandler.java | 73 +++++++++++------- .../com/android/quickstep/views/RecentsView.java | 1 + .../src/com/android/quickstep/views/TaskView.java | 4 +- src/com/android/launcher3/PagedView.java | 4 + 10 files changed, 179 insertions(+), 62 deletions(-) diff --git a/quickstep/src/com/android/quickstep/ActivityControlHelper.java b/quickstep/src/com/android/quickstep/ActivityControlHelper.java index e202c574a..52a6dd5fe 100644 --- a/quickstep/src/com/android/quickstep/ActivityControlHelper.java +++ b/quickstep/src/com/android/quickstep/ActivityControlHelper.java @@ -46,6 +46,7 @@ import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherInitListener; import com.android.launcher3.LauncherState; +import com.android.launcher3.R; import com.android.launcher3.allapps.AllAppsTransitionController; import com.android.launcher3.allapps.DiscoveryBounce; import com.android.launcher3.anim.AnimatorPlaybackController; @@ -82,7 +83,8 @@ public interface ActivityControlHelper { void onQuickInteractionStart(T activity, @Nullable RunningTaskInfo taskInfo, boolean activityVisible); - float getTranslationYForQuickScrub(T activity); + float getTranslationYForQuickScrub(TransformedRect targetRect, DeviceProfile dp, + Context context); void executeOnWindowAvailable(T activity, Runnable action); @@ -151,10 +153,15 @@ public interface ActivityControlHelper { } @Override - public float getTranslationYForQuickScrub(Launcher activity) { - LauncherRecentsView recentsView = activity.getOverviewPanel(); - return recentsView.computeTranslationYForFactor( - FastOverviewState.OVERVIEW_TRANSLATION_FACTOR); + public float getTranslationYForQuickScrub(TransformedRect targetRect, DeviceProfile dp, + Context context) { + // The padding calculations are exactly same as that of RecentsView.setInsets + int topMargin = context.getResources() + .getDimensionPixelSize(R.dimen.task_thumbnail_top_margin); + int paddingTop = targetRect.rect.top - topMargin - dp.getInsets().top; + int paddingBottom = dp.availableHeightPx + dp.getInsets().top - targetRect.rect.bottom; + + return FastOverviewState.OVERVIEW_TRANSLATION_FACTOR * (paddingBottom - paddingTop); } @Override @@ -380,7 +387,8 @@ public interface ActivityControlHelper { } @Override - public float getTranslationYForQuickScrub(RecentsActivity activity) { + public float getTranslationYForQuickScrub(TransformedRect targetRect, DeviceProfile dp, + Context context) { return 0; } diff --git a/quickstep/src/com/android/quickstep/DeferredTouchConsumer.java b/quickstep/src/com/android/quickstep/DeferredTouchConsumer.java index b92678a2e..8e83bd079 100644 --- a/quickstep/src/com/android/quickstep/DeferredTouchConsumer.java +++ b/quickstep/src/com/android/quickstep/DeferredTouchConsumer.java @@ -63,6 +63,16 @@ public class DeferredTouchConsumer implements TouchConsumer { mTarget.onQuickScrubProgress(progress); } + @Override + public void onQuickStep(MotionEvent ev) { + mTarget.onQuickStep(ev); + } + + @Override + public void onCommand(int command) { + mTarget.onCommand(command); + } + @Override public void preProcessMotionEvent(MotionEvent ev) { mVelocityTracker.addMovement(ev); @@ -92,6 +102,11 @@ public class DeferredTouchConsumer implements TouchConsumer { return target == null ? true : target.deferNextEventToMainThread(); } + @Override + public void onShowOverviewFromAltTab() { + mTarget.onShowOverviewFromAltTab(); + } + public interface DeferredTouchProvider { TouchConsumer createTouchConsumer(VelocityTracker tracker); diff --git a/quickstep/src/com/android/quickstep/MotionEventQueue.java b/quickstep/src/com/android/quickstep/MotionEventQueue.java index 15f5aa524..f73be6cba 100644 --- a/quickstep/src/com/android/quickstep/MotionEventQueue.java +++ b/quickstep/src/com/android/quickstep/MotionEventQueue.java @@ -55,6 +55,8 @@ public class MotionEventQueue { ACTION_VIRTUAL | (6 << ACTION_POINTER_INDEX_SHIFT); private static final int ACTION_QUICK_STEP = ACTION_VIRTUAL | (7 << ACTION_POINTER_INDEX_SHIFT); + private static final int ACTION_COMMAND = + ACTION_VIRTUAL | (8 << ACTION_POINTER_INDEX_SHIFT); private final EventArray mEmptyArray = new EventArray(); private final Object mExecutionLock = new Object(); @@ -165,6 +167,9 @@ public class MotionEventQueue { case ACTION_QUICK_STEP: mConsumer.onQuickStep(event); break; + case ACTION_COMMAND: + mConsumer.onCommand(event.getSource()); + break; default: Log.e(TAG, "Invalid virtual event: " + event.getAction()); } @@ -222,6 +227,12 @@ public class MotionEventQueue { queueVirtualAction(ACTION_DEFER_INIT, 0); } + public void onCommand(int command) { + MotionEvent ev = MotionEvent.obtain(0, 0, ACTION_COMMAND, 0, 0, 0); + ev.setSource(command); + queueNoPreProcess(ev); + } + public TouchConsumer getConsumer() { return mConsumer; } diff --git a/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java b/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java index 9ba332831..23357ea59 100644 --- a/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java +++ b/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java @@ -37,6 +37,7 @@ import android.os.Build; import android.os.Bundle; import android.os.Looper; import android.os.SystemClock; +import android.util.SparseArray; import android.view.Choreographer; import android.view.Display; import android.view.MotionEvent; @@ -69,6 +70,7 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC private static final long LAUNCHER_DRAW_TIMEOUT_MS = 150; + private final SparseArray mAnimationStates = new SparseArray<>(); private final RunningTaskInfo mRunningTask; private final RecentsModel mRecentsModel; private final Intent mHomeIntent; @@ -212,8 +214,9 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC private void startTouchTrackingForWindowAnimation(long touchTimeMs) { // Create the shared handler + RecentsAnimationState animationState = new RecentsAnimationState(); final WindowTransformSwipeHandler handler = new WindowTransformSwipeHandler( - mRunningTask, this, touchTimeMs, mActivityControlHelper); + animationState.id, mRunningTask, this, touchTimeMs, mActivityControlHelper); // Preload the plan mRecentsModel.loadTasks(mRunningTask.id, null); @@ -237,31 +240,7 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC public void onHandleAssistData(Bundle bundle) { mRecentsModel.preloadAssistData(mRunningTask.id, bundle); } - }, - new RecentsAnimationListener() { - public void onAnimationStart( - RecentsAnimationControllerCompat controller, - RemoteAnimationTargetCompat[] apps, Rect homeContentInsets, - Rect minimizedHomeBounds) { - if (mInteractionHandler == handler) { - TraceHelper.partitionSection("RecentsController", "Received"); - handler.onRecentsAnimationStart(controller, - new RemoteAnimationTargetSet(apps, MODE_CLOSING), - homeContentInsets, minimizedHomeBounds); - } else { - TraceHelper.endSection("RecentsController", "Finishing no handler"); - controller.finish(false /* toHome */); - } - } - - public void onAnimationCanceled() { - TraceHelper.endSection("RecentsController", - "Cancelled: " + mInteractionHandler); - if (mInteractionHandler == handler) { - handler.onRecentsAnimationCanceled(); - } - } - }, null, null); + }, animationState, null, null); if (Looper.myLooper() != Looper.getMainLooper()) { startActivity.run(); @@ -277,6 +256,14 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC } } + @Override + public void onCommand(int command) { + RecentsAnimationState state = mAnimationStates.get(command); + if (state != null) { + state.execute(); + } + } + /** * Called when the gesture has ended. Does not correlate to the completion of the interaction as * the animation can still be running. @@ -398,4 +385,55 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC // TODO: Consider also check if the eventQueue is using mainThread of not. return mInteractionHandler != null; } + + private class RecentsAnimationState implements RecentsAnimationListener { + + private final int id; + + private RecentsAnimationControllerCompat mController; + private RemoteAnimationTargetSet mTargets; + private Rect mHomeContentInsets; + private Rect mMinimizedHomeBounds; + private boolean mCancelled; + + public RecentsAnimationState() { + id = mAnimationStates.size(); + mAnimationStates.put(id, this); + } + + @Override + public void onAnimationStart( + RecentsAnimationControllerCompat controller, + RemoteAnimationTargetCompat[] apps, Rect homeContentInsets, + Rect minimizedHomeBounds) { + mController = controller; + mTargets = new RemoteAnimationTargetSet(apps, MODE_CLOSING); + mHomeContentInsets = homeContentInsets; + mMinimizedHomeBounds = minimizedHomeBounds; + mEventQueue.onCommand(id); + } + + @Override + public void onAnimationCanceled() { + mCancelled = true; + mEventQueue.onCommand(id); + } + + public void execute() { + if (mInteractionHandler == null || mInteractionHandler.id != id) { + if (!mCancelled && mController != null) { + TraceHelper.endSection("RecentsController", "Finishing no handler"); + mController.finish(false /* toHome */); + } + } else if (mCancelled) { + TraceHelper.endSection("RecentsController", + "Cancelled: " + mInteractionHandler); + mInteractionHandler.onRecentsAnimationCanceled(); + } else { + TraceHelper.partitionSection("RecentsController", "Received"); + mInteractionHandler.onRecentsAnimationStart(mController, mTargets, + mHomeContentInsets, mMinimizedHomeBounds); + } + } + } } diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationWrapper.java b/quickstep/src/com/android/quickstep/RecentsAnimationWrapper.java index 30b10b0ea..34d42ac92 100644 --- a/quickstep/src/com/android/quickstep/RecentsAnimationWrapper.java +++ b/quickstep/src/com/android/quickstep/RecentsAnimationWrapper.java @@ -20,6 +20,8 @@ import com.android.launcher3.util.TraceHelper; import com.android.launcher3.util.UiThreadHelper; import com.android.quickstep.util.RemoteAnimationTargetSet; import com.android.systemui.shared.system.RecentsAnimationControllerCompat; + +import java.util.ArrayList; import java.util.concurrent.ExecutorService; /** @@ -27,6 +29,10 @@ import java.util.concurrent.ExecutorService; */ public class RecentsAnimationWrapper { + // A list of callbacks to run when we receive the recents animation target. There are different + // than the state callbacks as these run on the current worker thread. + private final ArrayList mCallbacks = new ArrayList<>(); + public RemoteAnimationTargetSet targetSet; private RecentsAnimationControllerCompat mController; @@ -46,6 +52,21 @@ public class RecentsAnimationWrapper { if (mInputConsumerEnabled) { enableInputConsumer(); } + + if (!mCallbacks.isEmpty()) { + for (Runnable action : new ArrayList<>(mCallbacks)) { + action.run(); + } + mCallbacks.clear(); + } + } + + public synchronized void runOnInit(Runnable action) { + if (targetSet == null) { + mCallbacks.add(action); + } else { + action.run(); + } } /** diff --git a/quickstep/src/com/android/quickstep/TouchConsumer.java b/quickstep/src/com/android/quickstep/TouchConsumer.java index aa844d80d..4cecffa2b 100644 --- a/quickstep/src/com/android/quickstep/TouchConsumer.java +++ b/quickstep/src/com/android/quickstep/TouchConsumer.java @@ -48,6 +48,8 @@ public interface TouchConsumer extends Consumer { default void onQuickStep(MotionEvent ev) { } + default void onCommand(int command) { } + /** * Called on the binder thread to allow the consumer to process the motion event before it is * posted on a handler thread. diff --git a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java index d171f6945..939811bd1 100644 --- a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java +++ b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java @@ -29,6 +29,7 @@ import android.animation.ObjectAnimator; import android.annotation.TargetApi; import android.app.ActivityManager.RunningTaskInfo; import android.content.Context; +import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.Point; import android.graphics.Rect; @@ -36,6 +37,7 @@ import android.os.Build; import android.os.Handler; import android.os.Looper; import android.os.SystemClock; +import android.os.UserHandle; import android.support.annotation.AnyThread; import android.support.annotation.UiThread; import android.support.annotation.WorkerThread; @@ -51,6 +53,7 @@ import com.android.launcher3.DeviceProfile; import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.LauncherAppState; import com.android.launcher3.R; +import com.android.launcher3.Utilities; import com.android.launcher3.anim.AnimationSuccessListener; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.logging.UserEventDispatcher; @@ -65,11 +68,12 @@ import com.android.quickstep.ActivityControlHelper.AnimationFactory; import com.android.quickstep.ActivityControlHelper.LayoutListener; import com.android.quickstep.TouchConsumer.InteractionType; import com.android.quickstep.util.ClipAnimationHelper; -import com.android.quickstep.util.TransformedRect; import com.android.quickstep.util.RemoteAnimationTargetSet; +import com.android.quickstep.util.TransformedRect; import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.TaskView; import com.android.systemui.shared.recents.model.ThumbnailData; +import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.InputConsumerController; import com.android.systemui.shared.system.LatencyTrackerCompat; import com.android.systemui.shared.system.RecentsAnimationControllerCompat; @@ -167,6 +171,12 @@ public class WindowTransformSwipeHandler { private final Handler mMainThreadHandler = new Handler(Looper.getMainLooper()); + // An increasing identifier per single instance of OtherActivityTouchConsumer. Generally one + // instance of OtherActivityTouchConsumer will only have one swipe handle, but sometimes we can + // end up with multiple handlers if we get recents command in the middle of a swipe gesture. + // This is used to match the corresponding activity manager callbacks in + // OtherActivityTouchConsumer + public final int id; private final Context mContext; private final ActivityControlHelper mActivityControlHelper; private final ActivityInitListener mActivityInitListener; @@ -199,6 +209,7 @@ public class WindowTransformSwipeHandler { InputConsumerController.getRecentsAnimationInputConsumer(); private final RecentsAnimationWrapper mRecentsAnimationWrapper = new RecentsAnimationWrapper(); + private final long mTouchTimeMs; private long mLauncherFrameDrawnTime; @@ -207,8 +218,9 @@ public class WindowTransformSwipeHandler { private float mLongSwipeDisplacement = 0; private LongSwipeHelper mLongSwipeController; - WindowTransformSwipeHandler(RunningTaskInfo runningTaskInfo, Context context, long touchTimeMs, - ActivityControlHelper controller) { + WindowTransformSwipeHandler(int id, RunningTaskInfo runningTaskInfo, Context context, + long touchTimeMs, ActivityControlHelper controller) { + this.id = id; mContext = context; mRunningTaskInfo = runningTaskInfo; mRunningTaskId = runningTaskInfo.id; @@ -453,6 +465,7 @@ public class WindowTransformSwipeHandler { "Can't change interaction type to " + interactionType); } mInteractionType = interactionType; + mRecentsAnimationWrapper.runOnInit(this::shiftAnimationDestinationForQuickscrub); setStateOnUiThread(STATE_QUICK_SCRUB_START | STATE_GESTURE_COMPLETED); @@ -460,6 +473,34 @@ public class WindowTransformSwipeHandler { animateToProgress(1f, QUICK_SCRUB_FROM_APP_START_DURATION, LINEAR); } + private void shiftAnimationDestinationForQuickscrub() { + TransformedRect tempRect = new TransformedRect(); + mActivityControlHelper + .getSwipeUpDestinationAndLength(mDp, mContext, mInteractionType, tempRect); + mClipAnimationHelper.updateTargetRect(tempRect); + + float offsetY = + mActivityControlHelper.getTranslationYForQuickScrub(tempRect, mDp, mContext); + float scale, offsetX; + Resources res = mContext.getResources(); + + if (ActivityManagerWrapper.getInstance().getRecentTasks(2, UserHandle.myUserId()).size() + < 2) { + // There are not enough tasks, we don't need to shift + offsetX = 0; + scale = 1; + } else { + offsetX = res.getDimensionPixelSize(R.dimen.recents_page_spacing) + + tempRect.rect.width(); + float distanceToReachEdge = mDp.widthPx / 2 + tempRect.rect.width() / 2 + + res.getDimensionPixelSize(R.dimen.recents_page_spacing); + float interpolation = Math.min(1, offsetX / distanceToReachEdge); + scale = TaskView.getCurveScaleForInterpolation(interpolation); + } + mClipAnimationHelper.offsetTarget(scale, Utilities.isRtl(res) ? -offsetX : offsetX, offsetY, + QuickScrubController.QUICK_SCRUB_START_INTERPOLATOR); + } + @WorkerThread public void updateDisplacement(float displacement) { // We are moving in the negative x/y direction @@ -658,7 +699,7 @@ public class WindowTransformSwipeHandler { : STATE_SCALED_CONTROLLER_APP); } }); - anim.start(); + mRecentsAnimationWrapper.runOnInit(anim::start); } @UiThread @@ -786,30 +827,6 @@ public class WindowTransformSwipeHandler { // Inform the last progress in case we skipped before. mQuickScrubController.onQuickScrubProgress(mCurrentQuickScrubProgress); - - // Make sure the window follows the first task if it moves, e.g. during quick scrub. - TaskView firstTask = mRecentsView.getPageAt(0); - // The first task may be null if we are swiping up from a task that does not - // appear in the list (i.e. the assistant) - if (firstTask != null) { - int scrollForFirstTask = mRecentsView.getScrollForPage(0); - int scrollForSecondTask = mRecentsView.getChildCount() > 1 - ? mRecentsView.getScrollForPage(1) : scrollForFirstTask; - float offsetFromFirstTask = scrollForFirstTask - scrollForSecondTask; - - TransformedRect tempRect = new TransformedRect(); - mActivityControlHelper - .getSwipeUpDestinationAndLength(mDp, mContext, mInteractionType, tempRect); - float distanceToReachEdge = mDp.widthPx / 2 + tempRect.rect.width() / 2 + - mContext.getResources().getDimensionPixelSize(R.dimen.recents_page_spacing); - float interpolation = Math.min(1, - Math.abs(offsetFromFirstTask) / distanceToReachEdge); - - mClipAnimationHelper.offsetTarget( - firstTask.getCurveScaleForInterpolation(interpolation), offsetFromFirstTask, - mActivityControlHelper.getTranslationYForQuickScrub(mActivity), - QuickScrubController.QUICK_SCRUB_START_INTERPOLATOR); - } } private void onFinishedTransitionToQuickScrub() { diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index 02cdd3a7c..776509c85 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -507,6 +507,7 @@ public abstract class RecentsView extends PagedView impl DeviceProfile dp = mActivity.getDeviceProfile(); getTaskSize(dp, mTempRect); + // Keep this logic in sync with ActivityControlHelper.getTranslationYForQuickScrub. mTempRect.top -= mTaskTopMargin; setPadding(mTempRect.left - mInsets.left, mTempRect.top - mInsets.top, dp.availableWidthPx + mInsets.left - mTempRect.right, diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java index 5413a1319..91c0fa5be 100644 --- a/quickstep/src/com/android/quickstep/views/TaskView.java +++ b/quickstep/src/com/android/quickstep/views/TaskView.java @@ -250,12 +250,12 @@ public class TaskView extends FrameLayout implements TaskCallbacks, PageCallback setPivotY(mSnapshotView.getTop() + mSnapshotView.getHeight() * 0.5f); } - public float getCurveScaleForInterpolation(float linearInterpolation) { + public static float getCurveScaleForInterpolation(float linearInterpolation) { float curveInterpolation = CURVE_INTERPOLATOR.getInterpolation(linearInterpolation); return getCurveScaleForCurveInterpolation(curveInterpolation); } - private float getCurveScaleForCurveInterpolation(float curveInterpolation) { + private static float getCurveScaleForCurveInterpolation(float curveInterpolation) { return 1 - curveInterpolation * EDGE_SCALE_DOWN_FACTOR; } diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java index 62b581f83..de9cd986f 100644 --- a/src/com/android/launcher3/PagedView.java +++ b/src/com/android/launcher3/PagedView.java @@ -1450,6 +1450,10 @@ public abstract class PagedView extends ViewGrou protected boolean snapToPage(int whichPage, int delta, int duration, boolean immediate, TimeInterpolator interpolator) { + if (mFirstLayout) { + setCurrentPage(whichPage); + return false; + } if (FeatureFlags.IS_DOGFOOD_BUILD) { duration *= Settings.System.getFloat(getContext().getContentResolver(), -- cgit v1.2.3 From 9c3f172d9c10d8144c44c069e19d854b375e6112 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Tue, 29 May 2018 12:12:59 -0700 Subject: Accounting for one frame jump when starting a fling animation Bug: 80292740 Change-Id: I47bca071d42d1d217068c128f9793e87210d0286 --- quickstep/src/com/android/quickstep/AnimatedFloat.java | 4 ++-- .../android/quickstep/WindowTransformSwipeHandler.java | 16 +++++++++++----- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/quickstep/src/com/android/quickstep/AnimatedFloat.java b/quickstep/src/com/android/quickstep/AnimatedFloat.java index 84dfa457e..84dfdbd1d 100644 --- a/quickstep/src/com/android/quickstep/AnimatedFloat.java +++ b/quickstep/src/com/android/quickstep/AnimatedFloat.java @@ -46,9 +46,9 @@ public class AnimatedFloat { mUpdateCallback = updateCallback; } - public ObjectAnimator animateToValue(float v) { + public ObjectAnimator animateToValue(float start, float end) { cancelAnimation(); - mValueAnimator = ObjectAnimator.ofFloat(this, VALUE, v); + mValueAnimator = ObjectAnimator.ofFloat(this, VALUE, start, end); mValueAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animator) { diff --git a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java index 939811bd1..b1663b169 100644 --- a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java +++ b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java @@ -16,6 +16,7 @@ package com.android.quickstep; import static com.android.launcher3.BaseActivity.INVISIBLE_BY_STATE_HANDLER; +import static com.android.launcher3.Utilities.SINGLE_FRAME_MS; import static com.android.launcher3.Utilities.postAsyncCallback; import static com.android.launcher3.anim.Interpolators.DEACCEL; import static com.android.launcher3.anim.Interpolators.LINEAR; @@ -470,7 +471,7 @@ public class WindowTransformSwipeHandler { setStateOnUiThread(STATE_QUICK_SCRUB_START | STATE_GESTURE_COMPLETED); // Start the window animation without waiting for launcher. - animateToProgress(1f, QUICK_SCRUB_FROM_APP_START_DURATION, LINEAR); + animateToProgress(mCurrentShift.value, 1f, QUICK_SCRUB_FROM_APP_START_DURATION, LINEAR); } private void shiftAnimationDestinationForQuickscrub() { @@ -647,11 +648,13 @@ public class WindowTransformSwipeHandler { private void handleNormalGestureEnd(float endVelocity, boolean isFling) { long duration = MAX_SWIPE_DURATION; final float endShift; + final float startShift; if (!isFling) { endShift = mCurrentShift.value >= MIN_PROGRESS_FOR_OVERVIEW && mGestureStarted ? 1 : 0; long expectedDuration = Math.abs(Math.round((endShift - mCurrentShift.value) * MAX_SWIPE_DURATION * SWIPE_DURATION_MULTIPLIER)); duration = Math.min(MAX_SWIPE_DURATION, expectedDuration); + startShift = mCurrentShift.value; } else { endShift = endVelocity < 0 ? 1 : 0; float minFlingVelocity = mContext.getResources() @@ -665,9 +668,11 @@ public class WindowTransformSwipeHandler { long baseDuration = Math.round(1000 * Math.abs(distanceToTravel / endVelocity)); duration = Math.min(MAX_SWIPE_DURATION, 2 * baseDuration); } + startShift = Utilities.boundToRange(mCurrentShift.value - endVelocity * SINGLE_FRAME_MS + / (mTransitionDragLength * 1000), 0, 1); } - animateToProgress(endShift, duration, DEACCEL); + animateToProgress(startShift, endShift, duration, DEACCEL); } private void doLogGesture(boolean toLauncher) { @@ -687,9 +692,10 @@ public class WindowTransformSwipeHandler { } /** Animates to the given progress, where 0 is the current app and 1 is overview. */ - private void animateToProgress(float progress, long duration, Interpolator interpolator) { - mIsGoingToHome = Float.compare(progress, 1) == 0; - ObjectAnimator anim = mCurrentShift.animateToValue(progress).setDuration(duration); + private void animateToProgress(float start, float end, long duration, + Interpolator interpolator) { + mIsGoingToHome = Float.compare(end, 1) == 0; + ObjectAnimator anim = mCurrentShift.animateToValue(start, end).setDuration(duration); anim.setInterpolator(interpolator); anim.addListener(new AnimationSuccessListener() { @Override -- cgit v1.2.3 From bb9378aead84fe55c2a0edcf190008b0b7b52c20 Mon Sep 17 00:00:00 2001 From: Tony Date: Tue, 29 May 2018 14:44:41 -0700 Subject: Unhide badge when popup closes without animation Bug: 80379412 Change-Id: I7d6c1b67a07747078b43b17612d8c67a46c8cc0e --- src/com/android/launcher3/popup/PopupContainerWithArrow.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java index f276fbfea..172cf41e0 100644 --- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java +++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java @@ -527,6 +527,7 @@ public class PopupContainerWithArrow extends ArrowPopup implements DragSource, protected void closeComplete() { super.closeComplete(); mOriginalIcon.setTextVisibility(mOriginalIcon.shouldTextBeVisible()); + mOriginalIcon.forceHideBadge(false); } @Override -- cgit v1.2.3 From 8935d9515c17db0d717757022d9d2442153ecf0d Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Fri, 18 May 2018 16:12:54 -0700 Subject: Set mState = mCurrentStableState in onAnimationCancel mState is set when the transition starts toward that state even if it is never reached. If the animation is canceled, therefore, we should reset mState = mCurrentStableState since that is the state we came from. For instance, when swiping up from overview, mState = ALL_APPS, but when swiping back down we cancel that animation and create the task launch animation. When creating the task launch animation, we reapplyState(), which, before this change, was still ALL_APPS instead of OVERVIEW. Bug: 79935289 Change-Id: I59c5799e92350747e4ef1d99a80ba678a2ce7b98 --- src/com/android/launcher3/LauncherStateManager.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/com/android/launcher3/LauncherStateManager.java b/src/com/android/launcher3/LauncherStateManager.java index b5eef8bd3..02fa916b1 100644 --- a/src/com/android/launcher3/LauncherStateManager.java +++ b/src/com/android/launcher3/LauncherStateManager.java @@ -347,6 +347,12 @@ public class LauncherStateManager { } } + @Override + public void onAnimationCancel(Animator animation) { + super.onAnimationCancel(animation); + mState = mCurrentStableState; + } + @Override public void onAnimationSuccess(Animator animator) { // Run any queued runnables @@ -432,7 +438,6 @@ public class LauncherStateManager { } public void setCurrentUserControlledAnimation(AnimatorPlaybackController controller) { - clearCurrentAnimation(); setCurrentAnimation(controller.getTarget()); mConfig.userControlled = true; mConfig.playbackController = controller; -- cgit v1.2.3 From ab66067defad22a632c390df8d0afaecc04bbe19 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Tue, 29 May 2018 15:54:16 -0700 Subject: Update displacement on ACTION_UP as well, in case ACTION_UP and came in a different frame than last ACTION_MOVE Bug: 80292740 Change-Id: Ie75ac3ebb74024073965a7455a6503e8ed3f6d99 --- quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java b/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java index 23357ea59..c85628263 100644 --- a/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java +++ b/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java @@ -185,7 +185,7 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC case ACTION_UP: { TraceHelper.endSection("TouchInt"); - finishTouchTracking(); + finishTouchTracking(ev); break; } } @@ -268,8 +268,10 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC * Called when the gesture has ended. Does not correlate to the completion of the interaction as * the animation can still be running. */ - private void finishTouchTracking() { + private void finishTouchTracking(MotionEvent ev) { if (mPassedInitialSlop && mInteractionHandler != null) { + mInteractionHandler.updateDisplacement(getDisplacement(ev) - mStartDisplacement); + mVelocityTracker.computeCurrentVelocity(1000, ViewConfiguration.get(this).getScaledMaximumFlingVelocity()); -- cgit v1.2.3 From 67f9cad75a5fd3088b7e5c1e987ba501a99b6d0a Mon Sep 17 00:00:00 2001 From: Tony Date: Tue, 29 May 2018 17:33:16 -0700 Subject: Fix animation not playing when going home while another animation is playing When going to a new state, we cancel any currently playing animation. When canceling the animation, we reset mState = mCurrentStableState. Thus, when determining the duration of the new animation, we have both state == NORMAL and mState == NORMAL, leading to a duration of 0 and therefore no animation. Storing the fromState before canceling/resetting fixes the issue. Change-Id: I92332deae8058c4dd41212fe7f749955ede28b1c --- src/com/android/launcher3/LauncherStateManager.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/com/android/launcher3/LauncherStateManager.java b/src/com/android/launcher3/LauncherStateManager.java index 02fa916b1..05c515bf4 100644 --- a/src/com/android/launcher3/LauncherStateManager.java +++ b/src/com/android/launcher3/LauncherStateManager.java @@ -17,7 +17,6 @@ package com.android.launcher3; import static android.view.View.VISIBLE; - import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_FADE; import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_SCALE; @@ -222,7 +221,8 @@ public class LauncherStateManager { } } - // Cancel the current animation + // Cancel the current animation. This will reset mState to mCurrentStableState, so store it. + LauncherState fromState = mState; mConfig.reset(); if (!animated) { @@ -245,10 +245,10 @@ public class LauncherStateManager { // Since state NORMAL can be reached from multiple states, just assume that the // transition plays in reverse and use the same duration as previous state. - mConfig.duration = state == NORMAL ? mState.transitionDuration : state.transitionDuration; + mConfig.duration = state == NORMAL ? fromState.transitionDuration : state.transitionDuration; AnimatorSetBuilder builder = new AnimatorSetBuilder(); - prepareForAtomicAnimation(mState, state, builder); + prepareForAtomicAnimation(fromState, state, builder); AnimatorSet animation = createAnimationToNewWorkspaceInternal( state, builder, onCompleteRunnable); Runnable runnable = new StartAnimRunnable(animation); -- cgit v1.2.3 From 442fc108c365f8759c157996e1e6603c17a4bf35 Mon Sep 17 00:00:00 2001 From: Vadim Tryshev Date: Tue, 29 May 2018 17:29:03 -0700 Subject: Removing accessibility action for Clear-all Now that Clear-all button is visible for accessibility, there is no need in it. Bug: 80156299 Test: Manual Change-Id: I5997692be015947692a8bb720a449d1d36302526 --- .../quickstep/fallback/FallbackRecentsView.java | 19 ---------- .../com/android/quickstep/views/RecentsView.java | 3 -- .../android/quickstep/views/ShelfScrimView.java | 43 ---------------------- .../src/com/android/quickstep/views/TaskView.java | 2 - 4 files changed, 67 deletions(-) diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java index c5d74c7d9..9e2de3395 100644 --- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java +++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java @@ -20,10 +20,8 @@ import android.graphics.Canvas; import android.graphics.Rect; import android.util.AttributeSet; import android.view.View; -import android.view.accessibility.AccessibilityNodeInfo; import com.android.launcher3.DeviceProfile; -import com.android.launcher3.R; import com.android.quickstep.RecentsActivity; import com.android.quickstep.util.LayoutUtils; import com.android.quickstep.views.RecentsView; @@ -73,21 +71,4 @@ public class FallbackRecentsView extends RecentsView { // Just use the activity task size for multi-window as well. return false; } - - @Override - public void addTaskAccessibilityActionsExtra(AccessibilityNodeInfo info) { - info.addAction( - new AccessibilityNodeInfo.AccessibilityAction( - R.string.recents_clear_all, - getContext().getText(R.string.recents_clear_all))); - } - - @Override - public boolean performTaskAccessibilityActionExtra(int action) { - if (action == R.string.recents_clear_all) { - dismissAllTasks(); - return true; - } - return false; - } } diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index 4c2795ba0..d550edcd3 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -1367,9 +1367,6 @@ public abstract class RecentsView extends PagedView impl return true; } - public void addTaskAccessibilityActionsExtra(AccessibilityNodeInfo info) { - } - public boolean performTaskAccessibilityActionExtra(int action) { return false; } diff --git a/quickstep/src/com/android/quickstep/views/ShelfScrimView.java b/quickstep/src/com/android/quickstep/views/ShelfScrimView.java index aca8351a0..1ea112da0 100644 --- a/quickstep/src/com/android/quickstep/views/ShelfScrimView.java +++ b/quickstep/src/com/android/quickstep/views/ShelfScrimView.java @@ -28,9 +28,6 @@ import android.graphics.Paint; import android.graphics.Path; import android.graphics.Path.Direction; import android.graphics.Path.Op; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat; import android.util.AttributeSet; import com.android.launcher3.DeviceProfile; @@ -51,7 +48,6 @@ public class ShelfScrimView extends ScrimView { private static final int THRESHOLD_ALPHA_DARK = 102; private static final int THRESHOLD_ALPHA_LIGHT = 46; private static final int THRESHOLD_ALPHA_SUPER_LIGHT = 128; - private static final int CLEAR_ALL_TASKS = R.string.recents_clear_all; // In transposed layout, we simply draw a flat color. private boolean mDrawingFlatColor; @@ -208,43 +204,4 @@ public class ShelfScrimView extends ScrimView { mRadius, mRadius, mPaint); return minTop - mDragHandleSize - top; } - - @NonNull - @Override - protected AccessibilityHelper createAccessibilityHelper() { - return new ShelfScrimAccessibilityHelper(); - } - - protected class ShelfScrimAccessibilityHelper extends AccessibilityHelper { - @Override - protected void onPopulateNodeForVirtualView(int virtualViewId, - AccessibilityNodeInfoCompat node) { - super.onPopulateNodeForVirtualView(virtualViewId, node); - - if (mLauncher.isInState(OVERVIEW)) { - final RecentsView overviewPanel = mLauncher.getOverviewPanel(); - if (overviewPanel.getChildCount() != 0) { - node.addAction( - new AccessibilityNodeInfoCompat.AccessibilityActionCompat( - CLEAR_ALL_TASKS, - getContext().getText(CLEAR_ALL_TASKS))); - } - } - } - - @Override - protected boolean onPerformActionForVirtualView( - int virtualViewId, int action, Bundle arguments) { - if (super.onPerformActionForVirtualView(virtualViewId, action, arguments)) return true; - - if (action == CLEAR_ALL_TASKS) { - if (mLauncher.isInState(OVERVIEW)) { - mLauncher.getOverviewPanel().dismissAllTasks(); - } - return true; - } - - return false; - } - } } diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java index 91c0fa5be..b5f31b8e2 100644 --- a/quickstep/src/com/android/quickstep/views/TaskView.java +++ b/quickstep/src/com/android/quickstep/views/TaskView.java @@ -321,8 +321,6 @@ public class TaskView extends FrameLayout implements TaskCallbacks, PageCallback } final RecentsView recentsView = getRecentsView(); - recentsView.addTaskAccessibilityActionsExtra(info); - final AccessibilityNodeInfo.CollectionItemInfo itemInfo = AccessibilityNodeInfo.CollectionItemInfo.obtain( 0, 1, recentsView.getChildCount() - recentsView.indexOfChild(this) - 1, 1, -- cgit v1.2.3 From 2f347149afae96848efc6a6f16529556fbce4878 Mon Sep 17 00:00:00 2001 From: Tony Date: Wed, 30 May 2018 13:13:37 -0700 Subject: Shift recents up slightly in quick scrub Bug: 79883290 Change-Id: If57fd52505d7f965ea8a28e90e715c5723915e57 --- quickstep/src/com/android/launcher3/uioverrides/FastOverviewState.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickstep/src/com/android/launcher3/uioverrides/FastOverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/FastOverviewState.java index cd92314a7..26453022f 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/FastOverviewState.java +++ b/quickstep/src/com/android/launcher3/uioverrides/FastOverviewState.java @@ -34,7 +34,7 @@ public class FastOverviewState extends OverviewState { /** * Vertical transition of the task previews relative to the full container. */ - public static final float OVERVIEW_TRANSLATION_FACTOR = 0.5f; + public static final float OVERVIEW_TRANSLATION_FACTOR = 0.4f; private static final int STATE_FLAGS = FLAG_DISABLE_RESTORE | FLAG_DISABLE_INTERACTION | FLAG_OVERVIEW_UI | FLAG_HIDE_BACK_BUTTON | FLAG_DISABLE_ACCESSIBILITY; -- cgit v1.2.3 From 337fcb7983e318e245b9b08a5d748a7500ae6675 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Wed, 30 May 2018 12:00:43 -0700 Subject: Theme updates for dark text: > Using white scrim on adjescent tiles in overview > Using a ligher scrim in dark-theme+dark-text Bug: 80253867 Change-Id: I3f257d3addaca8bc5970a61722f5ae0e7af89382 --- .../android/quickstep/views/ShelfScrimView.java | 12 +------- .../android/quickstep/views/TaskThumbnailView.java | 35 +++++++++++++++------- res/values/attrs.xml | 1 + res/values/styles.xml | 4 +++ src/com/android/launcher3/util/Themes.java | 7 +++++ 5 files changed, 38 insertions(+), 21 deletions(-) diff --git a/quickstep/src/com/android/quickstep/views/ShelfScrimView.java b/quickstep/src/com/android/quickstep/views/ShelfScrimView.java index 1ea112da0..c780b6234 100644 --- a/quickstep/src/com/android/quickstep/views/ShelfScrimView.java +++ b/quickstep/src/com/android/quickstep/views/ShelfScrimView.java @@ -45,10 +45,6 @@ import com.android.launcher3.views.ScrimView; */ public class ShelfScrimView extends ScrimView { - private static final int THRESHOLD_ALPHA_DARK = 102; - private static final int THRESHOLD_ALPHA_LIGHT = 46; - private static final int THRESHOLD_ALPHA_SUPER_LIGHT = 128; - // In transposed layout, we simply draw a flat color. private boolean mDrawingFlatColor; @@ -77,13 +73,7 @@ public class ShelfScrimView extends ScrimView { mMaxScrimAlpha = OVERVIEW.getWorkspaceScrimAlpha(mLauncher); mEndAlpha = Color.alpha(mEndScrim); - if (Themes.getAttrBoolean(mLauncher, R.attr.isMainColorDark)) { - mThresholdAlpha = THRESHOLD_ALPHA_DARK; - } else if (Themes.getAttrBoolean(mLauncher, R.attr.isWorkspaceDarkText)) { - mThresholdAlpha = THRESHOLD_ALPHA_SUPER_LIGHT; - } else { - mThresholdAlpha = THRESHOLD_ALPHA_LIGHT; - } + mThresholdAlpha = Themes.getAttrInteger(context, R.attr.allAppsInterimScrimAlpha); mRadius = mLauncher.getResources().getDimension(R.dimen.shelf_surface_radius); mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); diff --git a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java index 128a19e06..d9dfd1815 100644 --- a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java +++ b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java @@ -29,6 +29,7 @@ import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.Shader; +import android.support.v4.graphics.ColorUtils; import android.util.AttributeSet; import android.util.FloatProperty; import android.util.Property; @@ -37,8 +38,10 @@ import android.view.View; import com.android.launcher3.BaseActivity; import com.android.launcher3.DeviceProfile; import com.android.launcher3.R; +import com.android.launcher3.Utilities; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.util.SystemUiController; +import com.android.launcher3.util.Themes; import com.android.quickstep.TaskOverlayFactory; import com.android.quickstep.TaskOverlayFactory.TaskOverlay; import com.android.systemui.shared.recents.model.Task; @@ -50,6 +53,7 @@ import com.android.systemui.shared.recents.model.ThumbnailData; public class TaskThumbnailView extends View { private static final LightingColorFilter[] sDimFilterCache = new LightingColorFilter[256]; + private static final LightingColorFilter[] sHighlightFilterCache = new LightingColorFilter[256]; public static final Property DIM_ALPHA_MULTIPLIER = new FloatProperty("dimAlphaMultiplier") { @@ -68,6 +72,7 @@ public class TaskThumbnailView extends View { private final BaseActivity mActivity; private final TaskOverlay mOverlay; + private final boolean mIsDarkTextTheme; private final Paint mPaint = new Paint(); private final Paint mBackgroundPaint = new Paint(); @@ -97,6 +102,7 @@ public class TaskThumbnailView extends View { mPaint.setFilterBitmap(true); mBackgroundPaint.setColor(Color.WHITE); mActivity = BaseActivity.fromContext(context); + mIsDarkTextTheme = Themes.getAttrBoolean(mActivity, R.attr.isWorkspaceDarkText); } public void bind() { @@ -198,7 +204,7 @@ public class TaskThumbnailView extends View { private void updateThumbnailPaintFilter() { int mul = (int) ((1 - mDimAlpha * mDimAlphaMultiplier) * 255); if (mBitmapShader != null) { - LightingColorFilter filter = getLightingColorFilter(mul); + LightingColorFilter filter = getDimmingColorFilter(mul, mIsDarkTextTheme); mPaint.setColorFilter(filter); mBackgroundPaint.setColorFilter(filter); } else { @@ -287,16 +293,25 @@ public class TaskThumbnailView extends View { updateThumbnailMatrix(); } - private static LightingColorFilter getLightingColorFilter(int dimColor) { - if (dimColor < 0) { - dimColor = 0; - } else if (dimColor > 255) { - dimColor = 255; + private static LightingColorFilter getDimmingColorFilter(int intensity, boolean shouldLighten) { + intensity = Utilities.boundToRange(intensity, 0, 255); + if (intensity == 255) { + return null; } - if (sDimFilterCache[dimColor] == null) { - sDimFilterCache[dimColor] = - new LightingColorFilter(Color.argb(255, dimColor, dimColor, dimColor), 0); + if (shouldLighten) { + if (sHighlightFilterCache[intensity] == null) { + int colorAdd = 255 - intensity; + sHighlightFilterCache[intensity] = new LightingColorFilter( + Color.argb(255, intensity, intensity, intensity), + Color.argb(255, colorAdd, colorAdd, colorAdd)); + } + return sHighlightFilterCache[intensity]; + } else { + if (sDimFilterCache[intensity] == null) { + sDimFilterCache[intensity] = new LightingColorFilter( + Color.argb(255, intensity, intensity, intensity), 0); + } + return sDimFilterCache[intensity]; } - return sDimFilterCache[dimColor]; } } diff --git a/res/values/attrs.xml b/res/values/attrs.xml index 64ca05e3c..30091a5f7 100644 --- a/res/values/attrs.xml +++ b/res/values/attrs.xml @@ -20,6 +20,7 @@ + diff --git a/res/values/styles.xml b/res/values/styles.xml index 2b760f349..31cbaa11a 100644 --- a/res/values/styles.xml +++ b/res/values/styles.xml @@ -29,6 +29,7 @@