From ab5f39bdc08f4469f1c759b7dcd0fd7cf56654fb Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Thu, 20 Jan 2022 23:55:17 +0000 Subject: [PATCH 1/3] Dispatch hover events through the input consumer proxy - Touch explore uses hover events to focus views for accessibility, but we were dropping these events when handling them through the input consumer proxy. The reason this changed is that in sc-v2 we moved the recents input consumer to the top of the task display area to ensure that it was always above any of the tasks in splitscreen, but by doing so, it was always above launcher even after settling in overview. The existing path for handling motion events is heavily tied to touch handling (action down/move/up) so we just add a separate path for dispatching hover events through the normal mechanism to launcher via the consumer. Bug: 197043796 Change-Id: I5f8cfd357ff13971fe172ce1d0179535479cd26c (cherry picked from commit eff9a120c67bb85d66f6d2244da05f283f30f93d) Merged-In:I5f8cfd357ff13971fe172ce1d0179535479cd26c --- .../com/android/quickstep/InputConsumer.java | 2 ++ .../inputconsumers/OverviewInputConsumer.java | 7 +++++++ .../quickstep/util/InputConsumerProxy.java | 20 ++++++++++++++++++- 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/quickstep/src/com/android/quickstep/InputConsumer.java b/quickstep/src/com/android/quickstep/InputConsumer.java index 0b093234f3..c455dc7462 100644 --- a/quickstep/src/com/android/quickstep/InputConsumer.java +++ b/quickstep/src/com/android/quickstep/InputConsumer.java @@ -99,6 +99,8 @@ public interface InputConsumer { default void onMotionEvent(MotionEvent ev) { } + default void onHoverEvent(MotionEvent ev) { } + default void onKeyEvent(KeyEvent ev) { } default void onInputEvent(InputEvent ev) { diff --git a/quickstep/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java index b0df2869c7..02ac48ebeb 100644 --- a/quickstep/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java +++ b/quickstep/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java @@ -100,6 +100,13 @@ public class OverviewInputConsumer, T extends StatefulAct } } + @Override + public void onHoverEvent(MotionEvent ev) { + if (ENABLE_QUICKSTEP_LIVE_TILE.get()) { + mActivity.dispatchGenericMotionEvent(ev); + } + } + @Override public void onKeyEvent(KeyEvent ev) { if (ENABLE_QUICKSTEP_LIVE_TILE.get()) { diff --git a/quickstep/src/com/android/quickstep/util/InputConsumerProxy.java b/quickstep/src/com/android/quickstep/util/InputConsumerProxy.java index c2101a848e..91b53c7ff2 100644 --- a/quickstep/src/com/android/quickstep/util/InputConsumerProxy.java +++ b/quickstep/src/com/android/quickstep/util/InputConsumerProxy.java @@ -71,7 +71,16 @@ public class InputConsumerProxy { private boolean onInputConsumerEvent(InputEvent ev) { if (ev instanceof MotionEvent) { - onInputConsumerMotionEvent((MotionEvent) ev); + MotionEvent event = (MotionEvent) ev; + int action = event.getActionMasked(); + boolean isHoverEvent = action == MotionEvent.ACTION_HOVER_ENTER + || action == MotionEvent.ACTION_HOVER_MOVE + || action == MotionEvent.ACTION_HOVER_EXIT; + if (isHoverEvent) { + onInputConsumerHoverEvent(event); + } else { + onInputConsumerMotionEvent(event); + } } else if (ev instanceof KeyEvent) { initInputConsumerIfNeeded(); mInputConsumer.onKeyEvent((KeyEvent) ev); @@ -113,6 +122,15 @@ public class InputConsumerProxy { return true; } + private void onInputConsumerHoverEvent(MotionEvent ev) { + initInputConsumerIfNeeded(); + if (mInputConsumer != null) { + SimpleOrientationTouchTransformer.INSTANCE.get(mContext).transform(ev, + mRotationSupplier.get()); + mInputConsumer.onHoverEvent(ev); + } + } + public void destroy() { if (mTouchInProgress) { mDestroyPending = true; From 3db7cd137e8e342d7eb6aa6f04fea03088ac7976 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Fri, 21 Jan 2022 06:17:10 +0000 Subject: [PATCH 2/3] Add fallback for missing remote animation callbacks - In some cases WM won't callback the remote animation callbacks (neither start nor cancel) and Launcher never finishes executing the pending command (preventing the subsequent commands from running). For the time being, just cancel the current state to allow the commands to be processed. Bug: 194011186 Test: Mash on overview and home buttons with a 3p launcher Signed-off-by: Winson Chung Change-Id: I1b1296fab316b979f441ebb474d1475e3fa68f95 Merged-In: I1b1296fab316b979f441ebb474d1475e3fa68f95 (cherry picked from commit bb530e9058e085bb1668a42ed9dc81f079af6304) Merged-In:I1b1296fab316b979f441ebb474d1475e3fa68f95 --- .../quickstep/OverviewCommandHelper.java | 9 +++++++++ .../android/quickstep/RecentsActivity.java | 19 +++++++++++++++++++ .../quickstep/TouchInteractionService.java | 3 +++ 3 files changed, 31 insertions(+) diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java index 75e8dd1f7a..17baa3ad91 100644 --- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java +++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java @@ -38,6 +38,7 @@ import com.android.quickstep.views.TaskView; import com.android.systemui.shared.recents.model.ThumbnailData; import com.android.systemui.shared.system.InteractionJankMonitorWrapper; +import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashMap; @@ -271,6 +272,14 @@ public class OverviewCommandHelper { scheduleNextTask(cmd); } + public void dump(PrintWriter pw) { + pw.println("OverviewCommandHelper:"); + pw.println(" mPendingCommands=" + mPendingCommands.size()); + if (!mPendingCommands.isEmpty()) { + pw.println(" pendingCommandType=" + mPendingCommands.get(0).type); + } + } + private static class CommandInfo { public final long createTime = SystemClock.elapsedRealtime(); public final int type; diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java index 103f350c0f..1dc49339b6 100644 --- a/quickstep/src/com/android/quickstep/RecentsActivity.java +++ b/quickstep/src/com/android/quickstep/RecentsActivity.java @@ -99,6 +99,7 @@ public final class RecentsActivity extends StatefulActivity { private Handler mUiHandler = new Handler(Looper.getMainLooper()); private static final long HOME_APPEAR_DURATION = 250; + private static final long RECENTS_ANIMATION_TIMEOUT = 1000; private RecentsDragLayer mDragLayer; private ScrimView mScrimView; @@ -115,6 +116,11 @@ public final class RecentsActivity extends StatefulActivity { // Strong refs to runners which are cleared when the activity is destroyed private RemoteAnimationFactory mActivityLaunchAnimationRunner; + // For handling degenerate cases where starting an activity doesn't actually trigger the remote + // animation callback + private final Handler mHandler = new Handler(); + private final Runnable mAnimationStartTimeoutRunnable = this::onAnimationStartTimeout; + /** * Init drag layer and overview panel views. */ @@ -219,6 +225,16 @@ public final class RecentsActivity extends StatefulActivity { // TODO(b/137318995) This should go home, but doing so removes freeform windows } + /** + * Called if the remote animation callback from #getActivityLaunchOptions() hasn't called back + * in a reasonable time due to a conflict with the recents animation. + */ + private void onAnimationStartTimeout() { + if (mActivityLaunchAnimationRunner != null) { + mActivityLaunchAnimationRunner.onAnimationCancelled(); + } + } + @Override public ActivityOptionsWrapper getActivityLaunchOptions(final View v, @Nullable ItemInfo item) { if (!(v instanceof TaskView)) { @@ -233,6 +249,7 @@ public final class RecentsActivity extends StatefulActivity { public void onCreateAnimation(int transit, RemoteAnimationTargetCompat[] appTargets, RemoteAnimationTargetCompat[] wallpaperTargets, RemoteAnimationTargetCompat[] nonAppTargets, AnimationResult result) { + mHandler.removeCallbacks(mAnimationStartTimeoutRunnable); AnimatorSet anim = composeRecentsLaunchAnimator(taskView, appTargets, wallpaperTargets, nonAppTargets); anim.addListener(resetStateListener()); @@ -242,6 +259,7 @@ public final class RecentsActivity extends StatefulActivity { @Override public void onAnimationCancelled() { + mHandler.removeCallbacks(mAnimationStartTimeoutRunnable); onEndCallback.executeAllAndDestroy(); } }; @@ -256,6 +274,7 @@ public final class RecentsActivity extends StatefulActivity { ActivityOptionsCompat.makeRemoteAnimation(adapterCompat), onEndCallback); activityOptions.options.setSplashscreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_ICON); + mHandler.postDelayed(mAnimationStartTimeoutRunnable, RECENTS_ANIMATION_TIMEOUT); return activityOptions; } diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java index 539239d36a..1f6a974c23 100644 --- a/quickstep/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java @@ -967,6 +967,9 @@ public class TouchInteractionService extends Service if (mOverviewComponentObserver != null) { mOverviewComponentObserver.dump(pw); } + if (mOverviewCommandHelper != null) { + mOverviewCommandHelper.dump(pw); + } if (mGestureState != null) { mGestureState.dump(pw); } From e44c403710e5942d6d2032dc20d0639cb984eef1 Mon Sep 17 00:00:00 2001 From: Jon Miranda Date: Thu, 20 Jan 2022 13:48:40 -0800 Subject: [PATCH 3/3] Fix bug where back swipe to icon in All Apps search result. Issue is that All Apps is scaling during the animation, so when FloatingIconView looks for it in the view hierarchy, it's not in its final position. This would be the cleanest approach for a scv2 fix Bug: 213306709 Test: manual Change-Id: Iaec77d15c9533edccd9c82164143af8fa522158f Merged-In: Iaec77d15c9533edccd9c82164143af8fa522158f (cherry picked from commit db767aa5757878ff37b82951b1bda71be1c9be4f) Merged-In:Iaec77d15c9533edccd9c82164143af8fa522158f --- .../launcher3/QuickstepTransitionManager.java | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java index 6e2fadd7d3..49b2cc5894 100644 --- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java +++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java @@ -367,7 +367,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener if (launcherClosing) { // Delay animation by a frame to avoid jank. Pair launcherContentAnimator = - getLauncherContentAnimator(true /* isAppOpening */, startDelay); + getLauncherContentAnimator(true /* isAppOpening */, startDelay, false); anim.play(launcherContentAnimator.first); anim.addListener(new AnimatorListenerAdapter() { @Override @@ -464,9 +464,10 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener * @param isAppOpening True when this is called when an app is opening. * False when this is called when an app is closing. * @param startDelay Start delay duration. + * @param skipAllAppsScale True if we want to avoid scaling All Apps */ private Pair getLauncherContentAnimator(boolean isAppOpening, - int startDelay) { + int startDelay, boolean skipAllAppsScale) { AnimatorSet launcherAnimator = new AnimatorSet(); Runnable endListener; @@ -484,7 +485,6 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener final float startAlpha = appsView.getAlpha(); final float startScale = SCALE_PROPERTY.get(appsView); appsView.setAlpha(alphas[0]); - SCALE_PROPERTY.set(appsView, scales[0]); ObjectAnimator alpha = ObjectAnimator.ofFloat(appsView, View.ALPHA, alphas); alpha.setDuration(CONTENT_ALPHA_DURATION); @@ -496,12 +496,16 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener appsView.setLayerType(View.LAYER_TYPE_NONE, null); } }); - ObjectAnimator scale = ObjectAnimator.ofFloat(appsView, SCALE_PROPERTY, scales); - scale.setInterpolator(AGGRESSIVE_EASE); - scale.setDuration(CONTENT_SCALE_DURATION); + + if (!skipAllAppsScale) { + SCALE_PROPERTY.set(appsView, scales[0]); + ObjectAnimator scale = ObjectAnimator.ofFloat(appsView, SCALE_PROPERTY, scales); + scale.setInterpolator(AGGRESSIVE_EASE); + scale.setDuration(CONTENT_SCALE_DURATION); + launcherAnimator.play(scale); + } launcherAnimator.play(alpha); - launcherAnimator.play(scale); endListener = () -> { appsView.setAlpha(startAlpha); @@ -1565,6 +1569,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener || mLauncher.getWorkspace().isOverlayShown(); boolean playWorkspaceReveal = true; + boolean skipAllAppsScale = false; if (mFromUnlock) { anim.play(getUnlockWindowAnimator(appTargets, wallpaperTargets)); } else if (ENABLE_BACK_SWIPE_HOME_ANIMATION.get() @@ -1579,6 +1584,10 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener true /* animateOverviewScrim */, launcherView).getAnimators()); // We play StaggeredWorkspaceAnim as a part of the closing window animation. playWorkspaceReveal = false; + } else { + // Skip scaling all apps, otherwise FloatingIconView will get wrong + // layout bounds. + skipAllAppsScale = true; } } else { anim.play(getFallbackClosingWindowAnimators(appTargets)); @@ -1600,7 +1609,8 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener if (mLauncher.isInState(LauncherState.ALL_APPS)) { Pair contentAnimator = - getLauncherContentAnimator(false, LAUNCHER_RESUME_START_DELAY); + getLauncherContentAnimator(false, LAUNCHER_RESUME_START_DELAY, + skipAllAppsScale); anim.play(contentAnimator.first); anim.addListener(new AnimatorListenerAdapter() { @Override