Merge "Fix BaseSwipeDetector#setState() called inside another setState()" into ub-launcher3-master

This commit is contained in:
TreeHugger Robot 2020-01-15 22:03:01 +00:00 committed by Android (Google) Code Review
commit 2abd13a80b
3 changed files with 39 additions and 4 deletions

View File

@ -508,7 +508,7 @@ public abstract class AbstractStateChangeTouchController
mAtomicComponentsController.getAnimationPlayer().end();
mAtomicComponentsController = null;
}
cancelAnimationControllers();
clearState();
boolean shouldGoToTargetState = true;
if (mPendingAnimation != null) {
boolean reachedTarget = mToState == targetState;
@ -546,13 +546,13 @@ public abstract class AbstractStateChangeTouchController
mAtomicAnim = null;
}
mScheduleResumeAtomicComponent = false;
mDetector.finishedScrolling();
mDetector.setDetectableScrollConditions(0, false);
}
private void cancelAnimationControllers() {
mCurrentAnimation = null;
cancelAtomicComponentsController();
mDetector.finishedScrolling();
mDetector.setDetectableScrollConditions(0, false);
}
private void cancelAtomicComponentsController() {

View File

@ -24,6 +24,10 @@ import android.view.VelocityTracker;
import android.view.ViewConfiguration;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import java.util.LinkedList;
import java.util.Queue;
/**
* Scroll/drag/swipe gesture detector.
@ -49,13 +53,15 @@ public abstract class BaseSwipeDetector {
protected final boolean mIsRtl;
protected final float mTouchSlop;
protected final float mMaxVelocity;
private final Queue<Runnable> mSetStateQueue = new LinkedList<>();
private int mActivePointerId = INVALID_POINTER_ID;
private VelocityTracker mVelocityTracker;
private PointF mLastDisplacement = new PointF();
private PointF mDisplacement = new PointF();
protected PointF mSubtractDisplacement = new PointF();
private ScrollState mState = ScrollState.IDLE;
@VisibleForTesting ScrollState mState = ScrollState.IDLE;
private boolean mIsSettingState;
protected boolean mIgnoreSlopWhenSettling;
@ -195,6 +201,12 @@ public abstract class BaseSwipeDetector {
// SETTLING -> (View settled) -> IDLE
private void setState(ScrollState newState) {
if (mIsSettingState) {
mSetStateQueue.add(() -> setState(newState));
return;
}
mIsSettingState = true;
if (DBG) {
Log.d(TAG, "setState:" + mState + "->" + newState);
}
@ -212,6 +224,10 @@ public abstract class BaseSwipeDetector {
}
mState = newState;
mIsSettingState = false;
if (!mSetStateQueue.isEmpty()) {
mSetStateQueue.remove().run();
}
}
private void initializeDragging() {

View File

@ -21,9 +21,11 @@ import static com.android.launcher3.touch.SingleAxisSwipeDetector.DIRECTION_POSI
import static com.android.launcher3.touch.SingleAxisSwipeDetector.HORIZONTAL;
import static com.android.launcher3.touch.SingleAxisSwipeDetector.VERTICAL;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyFloat;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
@ -168,4 +170,21 @@ public class SingleAxisSwipeDetectorTest {
// TODO: actually calculate the following parameters and do exact value checks.
verify(mMockListener).onDragEnd(anyFloat());
}
@Test
public void testInterleavedSetState() {
doAnswer(invocationOnMock -> {
// Sets state to IDLE. (Normally onDragEnd() will have state SETTLING.)
mDetector.finishedScrolling();
return null;
}).when(mMockListener).onDragEnd(anyFloat());
mGenerator.put(0, 100, 100);
mGenerator.move(0, 100, 100 + mTouchSlop);
mGenerator.move(0, 100, 100 + mTouchSlop * 2);
mGenerator.lift(0);
verify(mMockListener).onDragEnd(anyFloat());
assertTrue("SwipeDetector should be IDLE but was " + mDetector.mState,
mDetector.isIdleState());
}
}