diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java index 38e8e72cb8..4269f2d906 100644 --- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java +++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java @@ -320,6 +320,11 @@ public abstract class BaseQuickstepLauncher extends Launcher mOverviewCommandHelper = binder.getOverviewCommandHelper(); } + @Override + public void runOnBindToTouchInteractionService(Runnable r) { + mTISBindHelper.runOnBindToTouchInteractionService(r); + } + private void initUnfoldTransitionProgressProvider() { final UnfoldTransitionConfig config = UnfoldTransitionFactory.createConfig(this); if (config.isEnabled()) { diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java index 0e5282af91..1f5f2a5625 100644 --- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java +++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java @@ -180,45 +180,51 @@ public abstract class AbsSwipeUpHandler, getFlagForIndex(0, "STATE_LAUNCHER_PRESENT"); protected static final int STATE_LAUNCHER_STARTED = getFlagForIndex(1, "STATE_LAUNCHER_STARTED"); - protected static final int STATE_LAUNCHER_DRAWN = getFlagForIndex(2, "STATE_LAUNCHER_DRAWN"); + protected static final int STATE_LAUNCHER_DRAWN = + getFlagForIndex(2, "STATE_LAUNCHER_DRAWN"); + // Called when the Launcher has connected to the touch interaction service (and the taskbar + // ui controller is initialized) + protected static final int STATE_LAUNCHER_BIND_TO_SERVICE = + getFlagForIndex(3, "STATE_LAUNCHER_BIND_TO_SERVICE"); // Internal initialization states private static final int STATE_APP_CONTROLLER_RECEIVED = - getFlagForIndex(3, "STATE_APP_CONTROLLER_RECEIVED"); + getFlagForIndex(4, "STATE_APP_CONTROLLER_RECEIVED"); // Interaction finish states private static final int STATE_SCALED_CONTROLLER_HOME = - getFlagForIndex(4, "STATE_SCALED_CONTROLLER_HOME"); + getFlagForIndex(5, "STATE_SCALED_CONTROLLER_HOME"); private static final int STATE_SCALED_CONTROLLER_RECENTS = - getFlagForIndex(5, "STATE_SCALED_CONTROLLER_RECENTS"); + getFlagForIndex(6, "STATE_SCALED_CONTROLLER_RECENTS"); protected static final int STATE_HANDLER_INVALIDATED = - getFlagForIndex(6, "STATE_HANDLER_INVALIDATED"); + getFlagForIndex(7, "STATE_HANDLER_INVALIDATED"); private static final int STATE_GESTURE_STARTED = - getFlagForIndex(7, "STATE_GESTURE_STARTED"); + getFlagForIndex(8, "STATE_GESTURE_STARTED"); private static final int STATE_GESTURE_CANCELLED = - getFlagForIndex(8, "STATE_GESTURE_CANCELLED"); + getFlagForIndex(9, "STATE_GESTURE_CANCELLED"); private static final int STATE_GESTURE_COMPLETED = - getFlagForIndex(9, "STATE_GESTURE_COMPLETED"); + getFlagForIndex(10, "STATE_GESTURE_COMPLETED"); private static final int STATE_CAPTURE_SCREENSHOT = - getFlagForIndex(10, "STATE_CAPTURE_SCREENSHOT"); + getFlagForIndex(11, "STATE_CAPTURE_SCREENSHOT"); protected static final int STATE_SCREENSHOT_CAPTURED = - getFlagForIndex(11, "STATE_SCREENSHOT_CAPTURED"); + getFlagForIndex(12, "STATE_SCREENSHOT_CAPTURED"); private static final int STATE_SCREENSHOT_VIEW_SHOWN = - getFlagForIndex(12, "STATE_SCREENSHOT_VIEW_SHOWN"); + getFlagForIndex(13, "STATE_SCREENSHOT_VIEW_SHOWN"); private static final int STATE_RESUME_LAST_TASK = - getFlagForIndex(13, "STATE_RESUME_LAST_TASK"); + getFlagForIndex(14, "STATE_RESUME_LAST_TASK"); private static final int STATE_START_NEW_TASK = - getFlagForIndex(14, "STATE_START_NEW_TASK"); + getFlagForIndex(15, "STATE_START_NEW_TASK"); private static final int STATE_CURRENT_TASK_FINISHED = - getFlagForIndex(15, "STATE_CURRENT_TASK_FINISHED"); + getFlagForIndex(16, "STATE_CURRENT_TASK_FINISHED"); private static final int STATE_FINISH_WITH_NO_END = - getFlagForIndex(16, "STATE_FINISH_WITH_NO_END"); + getFlagForIndex(17, "STATE_FINISH_WITH_NO_END"); private static final int LAUNCHER_UI_STATES = - STATE_LAUNCHER_PRESENT | STATE_LAUNCHER_DRAWN | STATE_LAUNCHER_STARTED; + STATE_LAUNCHER_PRESENT | STATE_LAUNCHER_DRAWN | STATE_LAUNCHER_STARTED | + STATE_LAUNCHER_BIND_TO_SERVICE; public static final long MAX_SWIPE_DURATION = 350; public static final long HOME_DURATION = StaggeredWorkspaceAnim.DURATION_MS; @@ -429,6 +435,7 @@ public abstract class AbsSwipeUpHandler, setupRecentsViewUi(); linkRecentsViewScroll(); + activity.runOnBindToTouchInteractionService(this::onLauncherBindToService); mActivity.registerActivityLifecycleCallbacks(mLifecycleCallbacks); return true; @@ -510,6 +517,11 @@ public abstract class AbsSwipeUpHandler, mStateCallback.setState(STATE_LAUNCHER_STARTED); } + private void onLauncherBindToService() { + mStateCallback.setState(STATE_LAUNCHER_BIND_TO_SERVICE); + flushOnRecentsAnimationAndLauncherBound(); + } + private void onLauncherPresentAndGestureStarted() { // Re-setup the recents UI when gesture starts, as the state could have been changed during // that time by a previous window transition. @@ -812,12 +824,7 @@ public abstract class AbsSwipeUpHandler, } // Notify when the animation starts - if (!mRecentsAnimationStartCallbacks.isEmpty()) { - for (Runnable action : new ArrayList<>(mRecentsAnimationStartCallbacks)) { - action.run(); - } - mRecentsAnimationStartCallbacks.clear(); - } + flushOnRecentsAnimationAndLauncherBound(); TaskViewUtils.setSplitAuxiliarySurfacesShown(mRecentsAnimationTargets.nonApps, false); @@ -1195,7 +1202,7 @@ public abstract class AbsSwipeUpHandler, @UiThread private void animateToProgress(float start, float end, long duration, Interpolator interpolator, GestureEndTarget target, PointF velocityPxPerMs) { - runOnRecentsAnimationStart(() -> animateToProgressInternal(start, end, duration, + runOnRecentsAnimationAndLauncherBound(() -> animateToProgressInternal(start, end, duration, interpolator, target, velocityPxPerMs)); } @@ -1820,12 +1827,12 @@ public abstract class AbsSwipeUpHandler, SurfaceTransactionApplier.create(mRecentsView, applier -> { runActionOnRemoteHandles(remoteTargetHandle -> remoteTargetHandle.getTransformParams() .setSyncTransactionApplier(applier)); - runOnRecentsAnimationStart(() -> + runOnRecentsAnimationAndLauncherBound(() -> mRecentsAnimationTargets.addReleaseCheck(applier)); }); mRecentsView.addOnScrollChangedListener(mOnRecentsScrollListener); - runOnRecentsAnimationStart(() -> + runOnRecentsAnimationAndLauncherBound(() -> mRecentsView.setRecentsAnimationTargets(mRecentsAnimationController, mRecentsAnimationTargets)); mRecentsViewScrollLinked = true; @@ -1871,14 +1878,26 @@ public abstract class AbsSwipeUpHandler, } /** - * Runs the given {@param action} if the recents animation has already started, or queues it to - * be run when it is next started. + * Runs the given {@param action} if the recents animation has already started and Launcher has + * been created and bound to the TouchInteractionService, or queues it to be run when it this + * next happens. */ - protected void runOnRecentsAnimationStart(Runnable action) { - if (mRecentsAnimationTargets == null) { - mRecentsAnimationStartCallbacks.add(action); - } else { - action.run(); + private void runOnRecentsAnimationAndLauncherBound(Runnable action) { + mRecentsAnimationStartCallbacks.add(action); + flushOnRecentsAnimationAndLauncherBound(); + } + + private void flushOnRecentsAnimationAndLauncherBound() { + if (mRecentsAnimationTargets == null || + !mStateCallback.hasStates(STATE_LAUNCHER_BIND_TO_SERVICE)) { + return; + } + + if (!mRecentsAnimationStartCallbacks.isEmpty()) { + for (Runnable action : new ArrayList<>(mRecentsAnimationStartCallbacks)) { + action.run(); + } + mRecentsAnimationStartCallbacks.clear(); } } diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java index d6efc7193d..103f350c0f 100644 --- a/quickstep/src/com/android/quickstep/RecentsActivity.java +++ b/quickstep/src/com/android/quickstep/RecentsActivity.java @@ -141,6 +141,11 @@ public final class RecentsActivity extends StatefulActivity { mTaskbarManager.setActivity(this); } + @Override + public void runOnBindToTouchInteractionService(Runnable r) { + mTISBindHelper.runOnBindToTouchInteractionService(r); + } + public void setTaskbarUIController(FallbackTaskbarUIController taskbarUIController) { mTaskbarUIController = taskbarUIController; } diff --git a/quickstep/src/com/android/quickstep/util/TISBindHelper.java b/quickstep/src/com/android/quickstep/util/TISBindHelper.java index 92c60c84b5..7b122c6c66 100644 --- a/quickstep/src/com/android/quickstep/util/TISBindHelper.java +++ b/quickstep/src/com/android/quickstep/util/TISBindHelper.java @@ -26,6 +26,7 @@ import android.util.Log; import com.android.quickstep.TouchInteractionService; import com.android.quickstep.TouchInteractionService.TISBinder; +import java.util.ArrayList; import java.util.function.Consumer; /** @@ -44,9 +45,11 @@ public class TISBindHelper implements ServiceConnection { private final Runnable mConnectionRunnable = this::internalBindToTIS; private final Context mContext; private final Consumer mConnectionCallback; + private final ArrayList mPendingConnectedCallbacks = new ArrayList<>(); private short mConnectionAttempts; private boolean mTisServiceBound; + private boolean mIsConnected; public TISBindHelper(Context context, Consumer connectionCallback) { mContext = context; @@ -66,7 +69,13 @@ public class TISBindHelper implements ServiceConnection { } Log.d(TAG, "TIS service connected"); + mIsConnected = true; mConnectionCallback.accept((TISBinder) iBinder); + // Flush the pending callbacks + for (Runnable r : mPendingConnectedCallbacks) { + r.run(); + } + mPendingConnectedCallbacks.clear(); resetServiceBindRetryState(); } @@ -79,6 +88,16 @@ public class TISBindHelper implements ServiceConnection { internalBindToTIS(); } + /** + * Runs the given {@param r} runnable when the service is connected. + */ + public void runOnBindToTouchInteractionService(Runnable r) { + if (mIsConnected) { + r.run(); + } else { + mPendingConnectedCallbacks.add(r); + } + } /** * Binds to {@link TouchInteractionService}. If the binding fails, attempts to retry via @@ -120,5 +139,7 @@ public class TISBindHelper implements ServiceConnection { public void onDestroy() { internalUnbindToTIS(); resetServiceBindRetryState(); + mIsConnected = false; + mPendingConnectedCallbacks.clear(); } } diff --git a/src/com/android/launcher3/statemanager/StatefulActivity.java b/src/com/android/launcher3/statemanager/StatefulActivity.java index 7a23caa884..e03694321e 100644 --- a/src/com/android/launcher3/statemanager/StatefulActivity.java +++ b/src/com/android/launcher3/statemanager/StatefulActivity.java @@ -185,4 +185,11 @@ public abstract class StatefulActivity> @RequiresApi(api = Build.VERSION_CODES.R) public void updateWindowInsets(WindowInsets.Builder updatedInsetsBuilder, WindowInsets oldInsets) { } + + /** + * Runs the given {@param r} runnable when this activity binds to the touch interaction service. + */ + public void runOnBindToTouchInteractionService(Runnable r) { + r.run(); + } }