11/ Update MultiStateCallbacks to support multiple callbacks
- Allow multiple callbacks to be set for the same state - Expose method to set state on ui thread directly - Ensure callbacks are made immediately if the state is already set - Clarify that the one shot callbacks vs the state listeners Bug: 141886704 Change-Id: I8ea0dcd2821ee18d071706eaddeb2852afa13f30
This commit is contained in:
parent
c80b3224aa
commit
981ef3a88a
|
@ -130,7 +130,6 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
|
|||
|
||||
protected Runnable mGestureEndCallback;
|
||||
|
||||
protected final Handler mMainThreadHandler = MAIN_EXECUTOR.getHandler();
|
||||
protected MultiStateCallback mStateCallback;
|
||||
|
||||
protected boolean mCanceled;
|
||||
|
@ -157,14 +156,6 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
|
|||
.getDeviceProfile(mContext));
|
||||
}
|
||||
|
||||
protected void setStateOnUiThread(int stateFlag) {
|
||||
if (Looper.myLooper() == mMainThreadHandler.getLooper()) {
|
||||
mStateCallback.setState(stateFlag);
|
||||
} else {
|
||||
postAsyncCallback(mMainThreadHandler, () -> mStateCallback.setState(stateFlag));
|
||||
}
|
||||
}
|
||||
|
||||
protected void performHapticFeedback() {
|
||||
if (!mVibrator.hasVibrator()) {
|
||||
return;
|
||||
|
@ -253,9 +244,9 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
|
|||
} else {
|
||||
mActivityInterface.onLaunchTaskSuccess(mActivity);
|
||||
}
|
||||
}, mMainThreadHandler);
|
||||
}, MAIN_EXECUTOR.getHandler());
|
||||
}
|
||||
setStateOnUiThread(successStateFlag);
|
||||
mStateCallback.setStateOnUiThread(successStateFlag);
|
||||
}
|
||||
mCanceled = false;
|
||||
mFinishingRecentsAnimationForNewTaskId = -1;
|
||||
|
|
|
@ -211,58 +211,57 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
|||
private void initStateCallbacks() {
|
||||
mStateCallback = new MultiStateCallback(STATE_NAMES);
|
||||
|
||||
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_GESTURE_STARTED,
|
||||
mStateCallback.runOnceAtState(STATE_LAUNCHER_PRESENT | STATE_GESTURE_STARTED,
|
||||
this::onLauncherPresentAndGestureStarted);
|
||||
|
||||
mStateCallback.addCallback(STATE_LAUNCHER_DRAWN | STATE_GESTURE_STARTED,
|
||||
mStateCallback.runOnceAtState(STATE_LAUNCHER_DRAWN | STATE_GESTURE_STARTED,
|
||||
this::initializeLauncherAnimationController);
|
||||
|
||||
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_LAUNCHER_DRAWN,
|
||||
mStateCallback.runOnceAtState(STATE_LAUNCHER_PRESENT | STATE_LAUNCHER_DRAWN,
|
||||
this::launcherFrameDrawn);
|
||||
|
||||
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_LAUNCHER_STARTED
|
||||
mStateCallback.runOnceAtState(STATE_LAUNCHER_PRESENT | STATE_LAUNCHER_STARTED
|
||||
| STATE_GESTURE_CANCELLED,
|
||||
this::resetStateForAnimationCancel);
|
||||
|
||||
mStateCallback.addCallback(STATE_LAUNCHER_STARTED | STATE_APP_CONTROLLER_RECEIVED,
|
||||
mStateCallback.runOnceAtState(STATE_LAUNCHER_STARTED | STATE_APP_CONTROLLER_RECEIVED,
|
||||
this::sendRemoteAnimationsToAnimationFactory);
|
||||
|
||||
mStateCallback.addCallback(STATE_RESUME_LAST_TASK | STATE_APP_CONTROLLER_RECEIVED,
|
||||
mStateCallback.runOnceAtState(STATE_RESUME_LAST_TASK | STATE_APP_CONTROLLER_RECEIVED,
|
||||
this::resumeLastTask);
|
||||
mStateCallback.addCallback(STATE_START_NEW_TASK | STATE_SCREENSHOT_CAPTURED,
|
||||
mStateCallback.runOnceAtState(STATE_START_NEW_TASK | STATE_SCREENSHOT_CAPTURED,
|
||||
this::startNewTask);
|
||||
|
||||
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_APP_CONTROLLER_RECEIVED
|
||||
mStateCallback.runOnceAtState(STATE_LAUNCHER_PRESENT | STATE_APP_CONTROLLER_RECEIVED
|
||||
| STATE_LAUNCHER_DRAWN | STATE_CAPTURE_SCREENSHOT,
|
||||
this::switchToScreenshot);
|
||||
|
||||
mStateCallback.addCallback(STATE_SCREENSHOT_CAPTURED | STATE_GESTURE_COMPLETED
|
||||
mStateCallback.runOnceAtState(STATE_SCREENSHOT_CAPTURED | STATE_GESTURE_COMPLETED
|
||||
| STATE_SCALED_CONTROLLER_RECENTS,
|
||||
this::finishCurrentTransitionToRecents);
|
||||
|
||||
mStateCallback.addCallback(STATE_SCREENSHOT_CAPTURED | STATE_GESTURE_COMPLETED
|
||||
mStateCallback.runOnceAtState(STATE_SCREENSHOT_CAPTURED | STATE_GESTURE_COMPLETED
|
||||
| STATE_SCALED_CONTROLLER_HOME,
|
||||
this::finishCurrentTransitionToHome);
|
||||
mStateCallback.addCallback(STATE_SCALED_CONTROLLER_HOME | STATE_CURRENT_TASK_FINISHED,
|
||||
mStateCallback.runOnceAtState(STATE_SCALED_CONTROLLER_HOME | STATE_CURRENT_TASK_FINISHED,
|
||||
this::reset);
|
||||
|
||||
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_APP_CONTROLLER_RECEIVED
|
||||
mStateCallback.runOnceAtState(STATE_LAUNCHER_PRESENT | STATE_APP_CONTROLLER_RECEIVED
|
||||
| STATE_LAUNCHER_DRAWN | STATE_SCALED_CONTROLLER_RECENTS
|
||||
| STATE_CURRENT_TASK_FINISHED | STATE_GESTURE_COMPLETED
|
||||
| STATE_GESTURE_STARTED,
|
||||
this::setupLauncherUiAfterSwipeUpToRecentsAnimation);
|
||||
|
||||
mGestureState.addCallback(STATE_END_TARGET_ANIMATION_FINISHED,
|
||||
this::onEndTargetSet);
|
||||
mGestureState.runOnceAtState(STATE_END_TARGET_ANIMATION_FINISHED, this::onEndTargetSet);
|
||||
|
||||
mStateCallback.addCallback(STATE_HANDLER_INVALIDATED, this::invalidateHandler);
|
||||
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_HANDLER_INVALIDATED,
|
||||
mStateCallback.runOnceAtState(STATE_HANDLER_INVALIDATED, this::invalidateHandler);
|
||||
mStateCallback.runOnceAtState(STATE_LAUNCHER_PRESENT | STATE_HANDLER_INVALIDATED,
|
||||
this::invalidateHandlerWithLauncher);
|
||||
mStateCallback.addCallback(STATE_HANDLER_INVALIDATED | STATE_RESUME_LAST_TASK,
|
||||
mStateCallback.runOnceAtState(STATE_HANDLER_INVALIDATED | STATE_RESUME_LAST_TASK,
|
||||
this::notifyTransitionCancelled);
|
||||
|
||||
if (!ENABLE_QUICKSTEP_LIVE_TILE.get()) {
|
||||
mStateCallback.addChangeHandler(STATE_APP_CONTROLLER_RECEIVED | STATE_LAUNCHER_PRESENT
|
||||
mStateCallback.addChangeListener(STATE_APP_CONTROLLER_RECEIVED | STATE_LAUNCHER_PRESENT
|
||||
| STATE_SCREENSHOT_VIEW_SHOWN | STATE_CAPTURE_SCREENSHOT,
|
||||
(b) -> mRecentsView.setRunningTaskHidden(!b));
|
||||
}
|
||||
|
@ -330,7 +329,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
|||
// Launcher is visible, but might be about to stop. Thus, if we prepare recents
|
||||
// now, it might get overridden by moveToRestState() in onStop(). To avoid this,
|
||||
// wait until the next gesture (and possibly launcher) starts.
|
||||
mStateCallback.addCallback(STATE_GESTURE_STARTED, initAnimFactory);
|
||||
mStateCallback.runOnceAtState(STATE_GESTURE_STARTED, initAnimFactory);
|
||||
} else {
|
||||
initAnimFactory.run();
|
||||
}
|
||||
|
@ -596,9 +595,9 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
|||
super.onRecentsAnimationStart(controller, targets);
|
||||
|
||||
// Only add the callback to enable the input consumer after we actually have the controller
|
||||
mStateCallback.addCallback(STATE_APP_CONTROLLER_RECEIVED | STATE_GESTURE_STARTED,
|
||||
mStateCallback.runOnceAtState(STATE_APP_CONTROLLER_RECEIVED | STATE_GESTURE_STARTED,
|
||||
mRecentsAnimationController::enableInputConsumer);
|
||||
setStateOnUiThread(STATE_APP_CONTROLLER_RECEIVED);
|
||||
mStateCallback.setStateOnUiThread(STATE_APP_CONTROLLER_RECEIVED);
|
||||
|
||||
mPassedOverviewThreshold = false;
|
||||
}
|
||||
|
@ -608,7 +607,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
|||
super.onRecentsAnimationCanceled(thumbnailData);
|
||||
mRecentsView.setRecentsAnimationTargets(null, null);
|
||||
mActivityInitListener.unregister();
|
||||
setStateOnUiThread(STATE_GESTURE_CANCELLED | STATE_HANDLER_INVALIDATED);
|
||||
mStateCallback.setStateOnUiThread(STATE_GESTURE_CANCELLED | STATE_HANDLER_INVALIDATED);
|
||||
ActiveGestureLog.INSTANCE.addLog("cancelRecentsAnimation");
|
||||
}
|
||||
|
||||
|
@ -616,7 +615,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
|||
public void onGestureStarted() {
|
||||
notifyGestureStartedAsync();
|
||||
mShiftAtGestureStart = mCurrentShift.value;
|
||||
setStateOnUiThread(STATE_GESTURE_STARTED);
|
||||
mStateCallback.setStateOnUiThread(STATE_GESTURE_STARTED);
|
||||
mGestureStarted = true;
|
||||
}
|
||||
|
||||
|
@ -639,7 +638,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
|||
@Override
|
||||
public void onGestureCancelled() {
|
||||
updateDisplacement(0);
|
||||
setStateOnUiThread(STATE_GESTURE_COMPLETED);
|
||||
mStateCallback.setStateOnUiThread(STATE_GESTURE_COMPLETED);
|
||||
mLogAction = Touch.SWIPE_NOOP;
|
||||
handleNormalGestureEnd(0, false, new PointF(), true /* isCancel */);
|
||||
}
|
||||
|
@ -654,7 +653,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
|||
float flingThreshold = mContext.getResources()
|
||||
.getDimension(R.dimen.quickstep_fling_threshold_velocity);
|
||||
boolean isFling = mGestureStarted && Math.abs(endVelocity) > flingThreshold;
|
||||
setStateOnUiThread(STATE_GESTURE_COMPLETED);
|
||||
mStateCallback.setStateOnUiThread(STATE_GESTURE_COMPLETED);
|
||||
|
||||
mLogAction = isFling ? Touch.FLING : Touch.SWIPE;
|
||||
boolean isVelocityVertical = Math.abs(velocity.y) > Math.abs(velocity.x);
|
||||
|
@ -906,7 +905,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
|||
return AnimatorPlaybackController.wrap(new AnimatorSet(), duration);
|
||||
}
|
||||
};
|
||||
mStateCallback.addChangeHandler(STATE_LAUNCHER_PRESENT | STATE_HANDLER_INVALIDATED,
|
||||
mStateCallback.addChangeListener(STATE_LAUNCHER_PRESENT | STATE_HANDLER_INVALIDATED,
|
||||
isPresent -> mRecentsView.startHome());
|
||||
}
|
||||
RectFSpringAnim windowAnim = createWindowAnimationToHome(start, homeAnimFactory);
|
||||
|
@ -1042,7 +1041,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
|||
}
|
||||
|
||||
private void reset() {
|
||||
setStateOnUiThread(STATE_HANDLER_INVALIDATED);
|
||||
mStateCallback.setStateOnUiThread(STATE_HANDLER_INVALIDATED);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1122,10 +1121,10 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
|||
}
|
||||
mRecentsView.updateThumbnail(mRunningTaskId, mTaskSnapshot, false /* refreshNow */);
|
||||
}
|
||||
setStateOnUiThread(STATE_SCREENSHOT_CAPTURED);
|
||||
mStateCallback.setStateOnUiThread(STATE_SCREENSHOT_CAPTURED);
|
||||
} else if (!hasTargets()) {
|
||||
// If there are no targets, then we don't need to capture anything
|
||||
setStateOnUiThread(STATE_SCREENSHOT_CAPTURED);
|
||||
mStateCallback.setStateOnUiThread(STATE_SCREENSHOT_CAPTURED);
|
||||
} else {
|
||||
boolean finishTransitionPosted = false;
|
||||
if (mRecentsAnimationController != null) {
|
||||
|
@ -1145,14 +1144,15 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
|||
// Defer finishing the animation until the next launcher frame with the
|
||||
// new thumbnail
|
||||
finishTransitionPosted = ViewUtils.postDraw(taskView,
|
||||
() -> setStateOnUiThread(STATE_SCREENSHOT_CAPTURED), this::isCanceled);
|
||||
() -> mStateCallback.setStateOnUiThread(STATE_SCREENSHOT_CAPTURED),
|
||||
this::isCanceled);
|
||||
}
|
||||
}
|
||||
if (!finishTransitionPosted) {
|
||||
// If we haven't posted a draw callback, set the state immediately.
|
||||
Object traceToken = TraceHelper.INSTANCE.beginSection(SCREENSHOT_CAPTURED_EVT,
|
||||
TraceHelper.FLAG_CHECK_FOR_RACE_CONDITIONS);
|
||||
setStateOnUiThread(STATE_SCREENSHOT_CAPTURED);
|
||||
mStateCallback.setStateOnUiThread(STATE_SCREENSHOT_CAPTURED);
|
||||
TraceHelper.INSTANCE.endSection(traceToken);
|
||||
}
|
||||
}
|
||||
|
@ -1160,14 +1160,14 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
|||
|
||||
private void finishCurrentTransitionToRecents() {
|
||||
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
|
||||
setStateOnUiThread(STATE_CURRENT_TASK_FINISHED);
|
||||
mStateCallback.setStateOnUiThread(STATE_CURRENT_TASK_FINISHED);
|
||||
} else if (!hasTargets()) {
|
||||
// If there are no targets, then there is nothing to finish
|
||||
setStateOnUiThread(STATE_CURRENT_TASK_FINISHED);
|
||||
mStateCallback.setStateOnUiThread(STATE_CURRENT_TASK_FINISHED);
|
||||
} else {
|
||||
synchronized (mRecentsAnimationController) {
|
||||
mRecentsAnimationController.finish(true /* toRecents */,
|
||||
() -> setStateOnUiThread(STATE_CURRENT_TASK_FINISHED));
|
||||
() -> mStateCallback.setStateOnUiThread(STATE_CURRENT_TASK_FINISHED));
|
||||
}
|
||||
}
|
||||
ActiveGestureLog.INSTANCE.addLog("finishRecentsAnimation", true);
|
||||
|
@ -1176,7 +1176,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
|||
private void finishCurrentTransitionToHome() {
|
||||
synchronized (mRecentsAnimationController) {
|
||||
mRecentsAnimationController.finish(true /* toRecents */,
|
||||
() -> setStateOnUiThread(STATE_CURRENT_TASK_FINISHED),
|
||||
() -> mStateCallback.setStateOnUiThread(STATE_CURRENT_TASK_FINISHED),
|
||||
true /* sendUserLeaveHint */);
|
||||
}
|
||||
ActiveGestureLog.INSTANCE.addLog("finishRecentsAnimation", true);
|
||||
|
|
|
@ -113,7 +113,7 @@ public class DeviceLockedInputConsumer implements InputConsumer,
|
|||
|
||||
// Init states
|
||||
mStateCallback = new MultiStateCallback(STATE_NAMES);
|
||||
mStateCallback.addCallback(STATE_TARGET_RECEIVED | STATE_HANDLER_INVALIDATED,
|
||||
mStateCallback.runOnceAtState(STATE_TARGET_RECEIVED | STATE_HANDLER_INVALIDATED,
|
||||
this::endRemoteAnimation);
|
||||
|
||||
mVelocityTracker = VelocityTracker.obtain();
|
||||
|
|
|
@ -145,20 +145,20 @@ public class FallbackNoButtonInputConsumer extends
|
|||
private void initStateCallbacks() {
|
||||
mStateCallback = new MultiStateCallback(STATE_NAMES);
|
||||
|
||||
mStateCallback.addCallback(STATE_HANDLER_INVALIDATED,
|
||||
mStateCallback.runOnceAtState(STATE_HANDLER_INVALIDATED,
|
||||
this::onHandlerInvalidated);
|
||||
mStateCallback.addCallback(STATE_RECENTS_PRESENT | STATE_HANDLER_INVALIDATED,
|
||||
mStateCallback.runOnceAtState(STATE_RECENTS_PRESENT | STATE_HANDLER_INVALIDATED,
|
||||
this::onHandlerInvalidatedWithRecents);
|
||||
|
||||
mStateCallback.addCallback(STATE_GESTURE_CANCELLED | STATE_APP_CONTROLLER_RECEIVED,
|
||||
mStateCallback.runOnceAtState(STATE_GESTURE_CANCELLED | STATE_APP_CONTROLLER_RECEIVED,
|
||||
this::finishAnimationTargetSetAnimationComplete);
|
||||
|
||||
if (mInQuickSwitchMode) {
|
||||
mStateCallback.addCallback(STATE_GESTURE_COMPLETED | STATE_APP_CONTROLLER_RECEIVED
|
||||
mStateCallback.runOnceAtState(STATE_GESTURE_COMPLETED | STATE_APP_CONTROLLER_RECEIVED
|
||||
| STATE_RECENTS_PRESENT,
|
||||
this::finishAnimationTargetSet);
|
||||
} else {
|
||||
mStateCallback.addCallback(STATE_GESTURE_COMPLETED | STATE_APP_CONTROLLER_RECEIVED,
|
||||
mStateCallback.runOnceAtState(STATE_GESTURE_COMPLETED | STATE_APP_CONTROLLER_RECEIVED,
|
||||
this::finishAnimationTargetSet);
|
||||
}
|
||||
}
|
||||
|
@ -186,7 +186,7 @@ public class FallbackNoButtonInputConsumer extends
|
|||
mRecentsView.onGestureAnimationStart(mRunningTaskId);
|
||||
}
|
||||
}
|
||||
setStateOnUiThread(STATE_RECENTS_PRESENT);
|
||||
mStateCallback.setStateOnUiThread(STATE_RECENTS_PRESENT);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -251,7 +251,7 @@ public class FallbackNoButtonInputConsumer extends
|
|||
public void onGestureCancelled() {
|
||||
updateDisplacement(0);
|
||||
mGestureState.setEndTarget(LAST_TASK);
|
||||
setStateOnUiThread(STATE_GESTURE_CANCELLED);
|
||||
mStateCallback.setStateOnUiThread(STATE_GESTURE_CANCELLED);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -275,7 +275,7 @@ public class FallbackNoButtonInputConsumer extends
|
|||
: LAST_TASK);
|
||||
}
|
||||
}
|
||||
setStateOnUiThread(STATE_GESTURE_COMPLETED);
|
||||
mStateCallback.setStateOnUiThread(STATE_GESTURE_COMPLETED);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -302,7 +302,7 @@ public class FallbackNoButtonInputConsumer extends
|
|||
mRecentsView.setOnScrollChangeListener(null);
|
||||
}
|
||||
} else {
|
||||
setStateOnUiThread(STATE_HANDLER_INVALIDATED);
|
||||
mStateCallback.setStateOnUiThread(STATE_HANDLER_INVALIDATED);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -366,7 +366,7 @@ public class FallbackNoButtonInputConsumer extends
|
|||
}
|
||||
}
|
||||
|
||||
setStateOnUiThread(STATE_HANDLER_INVALIDATED);
|
||||
mStateCallback.setStateOnUiThread(STATE_HANDLER_INVALIDATED);
|
||||
}
|
||||
|
||||
private void finishAnimationTargetSet() {
|
||||
|
@ -436,14 +436,14 @@ public class FallbackNoButtonInputConsumer extends
|
|||
}
|
||||
applyTransformUnchecked();
|
||||
|
||||
setStateOnUiThread(STATE_APP_CONTROLLER_RECEIVED);
|
||||
mStateCallback.setStateOnUiThread(STATE_APP_CONTROLLER_RECEIVED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRecentsAnimationCanceled(ThumbnailData thumbnailData) {
|
||||
super.onRecentsAnimationCanceled(thumbnailData);
|
||||
mRecentsView.setRecentsAnimationTargets(null, null);
|
||||
setStateOnUiThread(STATE_HANDLER_INVALIDATED);
|
||||
mStateCallback.setStateOnUiThread(STATE_HANDLER_INVALIDATED);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -19,7 +19,6 @@ import android.view.MotionEvent;
|
|||
|
||||
import com.android.quickstep.InputConsumer;
|
||||
import com.android.quickstep.TaskAnimationManager;
|
||||
import com.android.quickstep.TouchInteractionService;
|
||||
|
||||
/**
|
||||
* A NO_OP input consumer which also resets any pending gesture
|
||||
|
|
|
@ -129,8 +129,8 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL
|
|||
/**
|
||||
* Adds a callback for when the states matching the given {@param stateMask} is set.
|
||||
*/
|
||||
public void addCallback(int stateMask, Runnable callback) {
|
||||
mStateCallback.addCallback(stateMask, callback);
|
||||
public void runOnceAtState(int stateMask, Runnable callback) {
|
||||
mStateCallback.runOnceAtState(stateMask, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -196,7 +196,7 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL
|
|||
*/
|
||||
public void setFinishingRecentsAnimationTaskId(int taskId) {
|
||||
mFinishingRecentsAnimationTaskId = taskId;
|
||||
mStateCallback.addCallback(STATE_RECENTS_ANIMATION_FINISHED, () -> {
|
||||
mStateCallback.runOnceAtState(STATE_RECENTS_ANIMATION_FINISHED, () -> {
|
||||
mFinishingRecentsAnimationTaskId = -1;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -15,11 +15,17 @@
|
|||
*/
|
||||
package com.android.quickstep;
|
||||
|
||||
import static com.android.launcher3.Utilities.postAsyncCallback;
|
||||
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
|
||||
|
||||
import android.os.Looper;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
|
@ -31,16 +37,29 @@ public class MultiStateCallback {
|
|||
private static final String TAG = "MultiStateCallback";
|
||||
public static final boolean DEBUG_STATES = false;
|
||||
|
||||
private final SparseArray<Runnable> mCallbacks = new SparseArray<>();
|
||||
private final SparseArray<Consumer<Boolean>> mStateChangeHandlers = new SparseArray<>();
|
||||
private final SparseArray<LinkedList<Runnable>> mCallbacks = new SparseArray<>();
|
||||
private final SparseArray<ArrayList<Consumer<Boolean>>> mStateChangeListeners =
|
||||
new SparseArray<>();
|
||||
|
||||
private final String[] mStateNames;
|
||||
|
||||
private int mState = 0;
|
||||
|
||||
public MultiStateCallback(String[] stateNames) {
|
||||
mStateNames = DEBUG_STATES ? stateNames : null;
|
||||
}
|
||||
|
||||
private int mState = 0;
|
||||
/**
|
||||
* Adds the provided state flags to the global state on the UI thread and executes any callbacks
|
||||
* as a result.
|
||||
*/
|
||||
public void setStateOnUiThread(int stateFlag) {
|
||||
if (Looper.myLooper() == Looper.getMainLooper()) {
|
||||
setState(stateFlag);
|
||||
} else {
|
||||
postAsyncCallback(MAIN_EXECUTOR.getHandler(), () -> setState(stateFlag));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the provided state flags to the global state and executes any callbacks as a result.
|
||||
|
@ -51,7 +70,7 @@ public class MultiStateCallback {
|
|||
+ convertToFlagNames(stateFlag) + " to " + convertToFlagNames(mState));
|
||||
}
|
||||
|
||||
int oldState = mState;
|
||||
final int oldState = mState;
|
||||
mState = mState | stateFlag;
|
||||
|
||||
int count = mCallbacks.size();
|
||||
|
@ -59,15 +78,13 @@ public class MultiStateCallback {
|
|||
int state = mCallbacks.keyAt(i);
|
||||
|
||||
if ((mState & state) == state) {
|
||||
Runnable callback = mCallbacks.valueAt(i);
|
||||
if (callback != null) {
|
||||
// Set the callback to null, so that it does not run again.
|
||||
mCallbacks.setValueAt(i, null);
|
||||
callback.run();
|
||||
LinkedList<Runnable> callbacks = mCallbacks.valueAt(i);
|
||||
while (!callbacks.isEmpty()) {
|
||||
callbacks.pollFirst().run();
|
||||
}
|
||||
}
|
||||
}
|
||||
notifyStateChangeHandlers(oldState);
|
||||
notifyStateChangeListeners(oldState);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -82,38 +99,61 @@ public class MultiStateCallback {
|
|||
|
||||
int oldState = mState;
|
||||
mState = mState & ~stateFlag;
|
||||
notifyStateChangeHandlers(oldState);
|
||||
notifyStateChangeListeners(oldState);
|
||||
}
|
||||
|
||||
private void notifyStateChangeHandlers(int oldState) {
|
||||
int count = mStateChangeHandlers.size();
|
||||
private void notifyStateChangeListeners(int oldState) {
|
||||
int count = mStateChangeListeners.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
int state = mStateChangeHandlers.keyAt(i);
|
||||
int state = mStateChangeListeners.keyAt(i);
|
||||
boolean wasOn = (state & oldState) == state;
|
||||
boolean isOn = (state & mState) == state;
|
||||
|
||||
if (wasOn != isOn) {
|
||||
mStateChangeHandlers.valueAt(i).accept(isOn);
|
||||
ArrayList<Consumer<Boolean>> listeners = mStateChangeListeners.valueAt(i);
|
||||
for (Consumer<Boolean> listener : listeners) {
|
||||
listener.accept(isOn);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the callbacks to be run when the provided states are enabled.
|
||||
* The callback is only run once.
|
||||
* Sets a callback to be run when the provided states in the given {@param stateMask} is
|
||||
* enabled. The callback is only run *once*, and if the states are already set at the time of
|
||||
* this call then the callback will be made immediately.
|
||||
*/
|
||||
public void addCallback(int stateMask, Runnable callback) {
|
||||
if (FeatureFlags.IS_DOGFOOD_BUILD && mCallbacks.get(stateMask) != null) {
|
||||
throw new IllegalStateException("Multiple callbacks on same state");
|
||||
public void runOnceAtState(int stateMask, Runnable callback) {
|
||||
if ((mState & stateMask) == stateMask) {
|
||||
callback.run();
|
||||
} else {
|
||||
final LinkedList<Runnable> callbacks;
|
||||
if (mCallbacks.indexOfKey(stateMask) >= 0) {
|
||||
callbacks = mCallbacks.get(stateMask);
|
||||
if (FeatureFlags.IS_DOGFOOD_BUILD && callbacks.contains(callback)) {
|
||||
throw new IllegalStateException("Existing callback for state found");
|
||||
}
|
||||
} else {
|
||||
callbacks = new LinkedList<>();
|
||||
mCallbacks.put(stateMask, callbacks);
|
||||
}
|
||||
callbacks.add(callback);
|
||||
}
|
||||
mCallbacks.put(stateMask, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the handler to be called when the provided states are enabled or disabled.
|
||||
* Adds a persistent listener to be called states in the given {@param stateMask} are enabled
|
||||
* or disabled.
|
||||
*/
|
||||
public void addChangeHandler(int stateMask, Consumer<Boolean> handler) {
|
||||
mStateChangeHandlers.put(stateMask, handler);
|
||||
public void addChangeListener(int stateMask, Consumer<Boolean> listener) {
|
||||
final ArrayList<Consumer<Boolean>> listeners;
|
||||
if (mStateChangeListeners.indexOfKey(stateMask) >= 0) {
|
||||
listeners = mStateChangeListeners.get(stateMask);
|
||||
} else {
|
||||
listeners = new ArrayList<>();
|
||||
mStateChangeListeners.put(stateMask, listeners);
|
||||
}
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
public int getState() {
|
||||
|
|
Loading…
Reference in New Issue