From 83337f9e8e6ff91fe3bf64eddab3d72cc2d8369c Mon Sep 17 00:00:00 2001 From: Jon Miranda Date: Tue, 24 Apr 2018 12:21:28 -0700 Subject: [PATCH] Call close for AbstractFloatingViews that were removed while still open. I'm not sure how/when this case occurs (perhaps during some transition/state change), but manually removing the floating view matches the symptoms in the bug. Bug: 72996404 Change-Id: I1e7c1a338fcd16c8e07b3c49fb9c9b2097eb2708 --- .../launcher3/LauncherAnimationRunner.java | 5 ++--- .../uioverrides/TaskViewTouchController.java | 2 +- .../android/launcher3/AbstractFloatingView.java | 1 + .../launcher3/FirstFrameAnimatorHelper.java | 10 +++++----- src/com/android/launcher3/Utilities.java | 2 ++ src/com/android/launcher3/folder/Folder.java | 16 ++++------------ .../AbstractStateChangeTouchController.java | 2 +- .../android/launcher3/views/BaseDragLayer.java | 17 +++++++++++++++++ 8 files changed, 33 insertions(+), 22 deletions(-) diff --git a/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java b/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java index c9853545f2..b7888e44cb 100644 --- a/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java +++ b/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java @@ -15,6 +15,7 @@ */ package com.android.launcher3; +import static com.android.launcher3.Utilities.SINGLE_FRAME_MS; import static com.android.launcher3.Utilities.postAsyncCallback; import android.animation.Animator; @@ -32,8 +33,6 @@ import com.android.systemui.shared.system.RemoteAnimationTargetCompat; @TargetApi(Build.VERSION_CODES.P) public abstract class LauncherAnimationRunner implements RemoteAnimationRunnerCompat { - private static final int REFRESH_RATE_MS = 16; - private final Handler mHandler; private AnimationResult mAnimationResult; @@ -120,7 +119,7 @@ public abstract class LauncherAnimationRunner implements RemoteAnimationRunnerCo // Because t=0 has the app icon in its original spot, we can skip the // first frame and have the same movement one frame earlier. - mAnimator.setCurrentPlayTime(REFRESH_RATE_MS); + mAnimator.setCurrentPlayTime(SINGLE_FRAME_MS); } } } diff --git a/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java index 5765256290..63a79847f4 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java @@ -15,6 +15,7 @@ */ package com.android.launcher3.uioverrides; +import static com.android.launcher3.Utilities.SINGLE_FRAME_MS; import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity; import android.animation.Animator; @@ -46,7 +47,6 @@ public abstract class TaskViewTouchController private static final String TAG = "OverviewSwipeController"; private static final float ALLOWED_FLING_DIRECTION_CHANGE_PROGRESS = 0.1f; - private static final int SINGLE_FRAME_MS = 16; // Progress after which the transition is assumed to be a success in case user does not fling private static final float SUCCESS_TRANSITION_PROGRESS = 0.5f; diff --git a/src/com/android/launcher3/AbstractFloatingView.java b/src/com/android/launcher3/AbstractFloatingView.java index 693cf31375..097c3415c1 100644 --- a/src/com/android/launcher3/AbstractFloatingView.java +++ b/src/com/android/launcher3/AbstractFloatingView.java @@ -97,6 +97,7 @@ public abstract class AbstractFloatingView extends LinearLayout implements Touch handleClose(animate); BaseActivity.fromContext(getContext()).getUserEventDispatcher() .resetElapsedContainerMillis("container closed"); + mIsOpen = false; } protected abstract void handleClose(boolean animate); diff --git a/src/com/android/launcher3/FirstFrameAnimatorHelper.java b/src/com/android/launcher3/FirstFrameAnimatorHelper.java index 4eac4a4a72..e7ca12148d 100644 --- a/src/com/android/launcher3/FirstFrameAnimatorHelper.java +++ b/src/com/android/launcher3/FirstFrameAnimatorHelper.java @@ -24,7 +24,8 @@ import android.view.View; import android.view.ViewPropertyAnimator; import android.view.ViewTreeObserver; import com.android.launcher3.util.Thunk; -import com.android.launcher3.util.TraceHelper; + +import static com.android.launcher3.Utilities.SINGLE_FRAME_MS; /* * This is a helper class that listens to updates from the corresponding animation. @@ -36,7 +37,6 @@ public class FirstFrameAnimatorHelper extends AnimatorListenerAdapter private static final String TAG = "FirstFrameAnimatorHlpr"; private static final boolean DEBUG = false; private static final int MAX_DELAY = 1000; - private static final int IDEAL_FRAME_DURATION = 16; private final View mTarget; private long mStartFrame; private long mStartTime = -1; @@ -109,9 +109,9 @@ public class FirstFrameAnimatorHelper extends AnimatorListenerAdapter // prevents a large jump in the animation due to an expensive first frame } else if (frameNum == 1 && currentTime < mStartTime + MAX_DELAY && !mAdjustedSecondFrameTime && - currentTime > mStartTime + IDEAL_FRAME_DURATION && - currentPlayTime > IDEAL_FRAME_DURATION) { - animation.setCurrentPlayTime(IDEAL_FRAME_DURATION); + currentTime > mStartTime + SINGLE_FRAME_MS && + currentPlayTime > SINGLE_FRAME_MS) { + animation.setCurrentPlayTime(SINGLE_FRAME_MS); mAdjustedSecondFrameTime = true; } else { if (frameNum > 1) { diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java index 98440fff5d..006dc95906 100644 --- a/src/com/android/launcher3/Utilities.java +++ b/src/com/android/launcher3/Utilities.java @@ -103,6 +103,8 @@ public final class Utilities { public static final boolean ATLEAST_LOLLIPOP_MR1 = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1; + public static final int SINGLE_FRAME_MS = 16; + /** * Indicates if the device has a debug build. Should only be used to store additional info or * add extra logging and not for changing the app behavior. diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java index 12d7dc77a1..99c800d149 100644 --- a/src/com/android/launcher3/folder/Folder.java +++ b/src/com/android/launcher3/folder/Folder.java @@ -39,6 +39,7 @@ import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.view.ViewDebug; +import android.view.ViewGroup; import android.view.accessibility.AccessibilityEvent; import android.view.animation.AnimationUtils; import android.view.inputmethod.EditorInfo; @@ -507,16 +508,9 @@ public class Folder extends AbstractFloatingView implements DragSource, // dropping. One resulting issue is that replaceFolderWithFinalItem() can be called twice. mDeleteFolderOnDropCompleted = false; - final Runnable onCompleteRunnable; centerAboutIcon(); AnimatorSet anim = new FolderAnimationManager(this, true /* isOpening */).getAnimator(); - onCompleteRunnable = new Runnable() { - @Override - public void run() { - mLauncher.getUserEventDispatcher().resetElapsedContainerMillis("folder opened"); - } - }; anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { @@ -532,7 +526,7 @@ public class Folder extends AbstractFloatingView implements DragSource, public void onAnimationEnd(Animator animation) { mState = STATE_OPEN; - onCompleteRunnable.run(); + mLauncher.getUserEventDispatcher().resetElapsedContainerMillis("folder opened"); mContent.setFocusOnFirstChild(); } }); @@ -614,9 +608,6 @@ public class Folder extends AbstractFloatingView implements DragSource, mFolderIcon.clearLeaveBehindIfExists(); } - if (!(getParent() instanceof DragLayer)) return; - DragLayer parent = (DragLayer) getParent(); - if (animate) { animateClosed(); } else { @@ -625,7 +616,8 @@ public class Folder extends AbstractFloatingView implements DragSource, // Notify the accessibility manager that this folder "window" has disappeared and no // longer occludes the workspace items - parent.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); + mLauncher.getDragLayer().sendAccessibilityEvent( + AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); } private void animateClosed() { diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java index 4c7ce1fb44..c0ad110818 100644 --- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java +++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java @@ -15,6 +15,7 @@ */ package com.android.launcher3.touch; +import static com.android.launcher3.Utilities.SINGLE_FRAME_MS; import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity; import android.animation.Animator; @@ -40,7 +41,6 @@ public abstract class AbstractStateChangeTouchController extends AnimatorListene private static final String TAG = "ASCTouchController"; public static final float RECATCH_REJECTION_FRACTION = .0875f; - public static final int SINGLE_FRAME_MS = 16; // Progress after which the transition is assumed to be a success in case user does not fling public static final float SUCCESS_TRANSITION_PROGRESS = 0.5f; diff --git a/src/com/android/launcher3/views/BaseDragLayer.java b/src/com/android/launcher3/views/BaseDragLayer.java index 489e59e75b..149b38b0f3 100644 --- a/src/com/android/launcher3/views/BaseDragLayer.java +++ b/src/com/android/launcher3/views/BaseDragLayer.java @@ -34,6 +34,8 @@ import com.android.launcher3.util.TouchController; import java.util.ArrayList; +import static com.android.launcher3.Utilities.SINGLE_FRAME_MS; + /** * A viewgroup with utility methods for drag-n-drop and touch interception */ @@ -118,6 +120,21 @@ public abstract class BaseDragLayer extends Inse } } + @Override + public void onViewRemoved(View child) { + super.onViewRemoved(child); + if (child instanceof AbstractFloatingView) { + // Handles the case where the view is removed without being properly closed. + // This can happen if something goes wrong during a state change/transition. + postDelayed(() -> { + AbstractFloatingView floatingView = (AbstractFloatingView) child; + if (floatingView.isOpen()) { + floatingView.close(false); + } + }, SINGLE_FRAME_MS); + } + } + @Override public boolean onTouchEvent(MotionEvent ev) { int action = ev.getAction();