From 00c3d78191b9fcf5773d1b80c69bf4a2b5158a13 Mon Sep 17 00:00:00 2001 From: Jon Miranda Date: Tue, 17 Oct 2023 18:11:01 -0700 Subject: [PATCH] Add HomeTransitionListener to launcher. Fixes: 279514548 Bug: 284474103 Bug: 306053414 Flag: LEGACY ENABLE_HOME_TRANSITION_LISTENER DISABLED Test: App launch -> Hotseat -> Taskbar stashes Transluscent app launch and launcher still visible -> No change Going home -> Hotseat visible Change-Id: I6db5253ada3e3b37dfae124f3ee88a9805804fb8 --- .../launcher3/HomeTransitionController.java | 57 +++++++++++++++++++ .../taskbar/LauncherTaskbarUIController.java | 38 +++++++------ .../taskbar/TaskbarActivityContext.java | 2 +- .../TaskbarLauncherStateController.java | 28 ++++----- .../uioverrides/QuickstepLauncher.java | 17 +++++- .../com/android/quickstep/SystemUiProxy.java | 22 +++++++ .../launcher3/config/FeatureFlags.java | 4 ++ 7 files changed, 134 insertions(+), 34 deletions(-) create mode 100644 quickstep/src/com/android/launcher3/HomeTransitionController.java diff --git a/quickstep/src/com/android/launcher3/HomeTransitionController.java b/quickstep/src/com/android/launcher3/HomeTransitionController.java new file mode 100644 index 0000000000..b264115bf3 --- /dev/null +++ b/quickstep/src/com/android/launcher3/HomeTransitionController.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.launcher3; + +import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; + +import androidx.annotation.Nullable; + +import com.android.launcher3.uioverrides.QuickstepLauncher; +import com.android.quickstep.SystemUiProxy; +import com.android.wm.shell.transition.IHomeTransitionListener; + +/** + * Controls launcher response to home activity visibility changing. + */ +public class HomeTransitionController { + + private final QuickstepLauncher mLauncher; + @Nullable private IHomeTransitionListener mHomeTransitionListener; + + public HomeTransitionController(QuickstepLauncher launcher) { + mLauncher = launcher; + } + + public void registerHomeTransitionListener() { + mHomeTransitionListener = new IHomeTransitionListener.Stub() { + @Override + public void onHomeVisibilityChanged(boolean isVisible) { + MAIN_EXECUTOR.execute(() -> { + if (mLauncher.getTaskbarUIController() != null) { + mLauncher.getTaskbarUIController().onLauncherVisibilityChanged(isVisible); + } + }); + } + }; + + SystemUiProxy.INSTANCE.get(mLauncher).setHomeTransitionListener(mHomeTransitionListener); + } + + public void unregisterHomeTransitionListener() { + SystemUiProxy.INSTANCE.get(mLauncher).setHomeTransitionListener(null); + mHomeTransitionListener = null; + } +} diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java index a321734cc5..445a1bd7a2 100644 --- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java +++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java @@ -16,9 +16,10 @@ package com.android.launcher3.taskbar; import static com.android.launcher3.QuickstepTransitionManager.TRANSIENT_TASKBAR_TRANSITION_DURATION; +import static com.android.launcher3.config.FeatureFlags.ENABLE_HOME_TRANSITION_LISTENER; import static com.android.launcher3.statemanager.BaseState.FLAG_NON_INTERACTIVE; import static com.android.launcher3.taskbar.TaskbarEduTooltipControllerKt.TOOLTIP_STEP_FEATURES; -import static com.android.launcher3.taskbar.TaskbarLauncherStateController.FLAG_RESUMED; +import static com.android.launcher3.taskbar.TaskbarLauncherStateController.FLAG_VISIBLE; import static com.android.quickstep.TaskAnimationManager.ENABLE_SHELL_TRANSITIONS; import android.animation.Animator; @@ -100,7 +101,9 @@ public class LauncherTaskbarUIController extends TaskbarUIController { mLauncher.setTaskbarUIController(this); - onLauncherResumedOrPaused(mLauncher.hasBeenResumed(), true /* fromInit */); + if (!ENABLE_HOME_TRANSITION_LISTENER.get()) { + onLauncherVisibilityChanged(mLauncher.hasBeenResumed(), true /* fromInit */); + } onStashedInAppChanged(mLauncher.getDeviceProfile()); mLauncher.addOnDeviceProfileChangeListener(mOnDeviceProfileChangeListener); @@ -119,7 +122,7 @@ public class LauncherTaskbarUIController extends TaskbarUIController { @Override protected void onDestroy() { super.onDestroy(); - onLauncherResumedOrPaused(false); + onLauncherVisibilityChanged(false); mTaskbarLauncherStateController.onDestroy(); mLauncher.setTaskbarUIController(null); @@ -160,8 +163,9 @@ public class LauncherTaskbarUIController extends TaskbarUIController { * sub-animations are properly coordinated. This duration should not * actually be used since this animation tracks a swipe progress. */ - protected void addLauncherResumeAnimation(AnimatorSet animation, int placeholderDuration) { - animation.play(onLauncherResumedOrPaused( + protected void addLauncherVisibilityChangedAnimation(AnimatorSet animation, + int placeholderDuration) { + animation.play(onLauncherVisibilityChanged( /* isResumed= */ true, /* fromInit= */ false, /* startAnimation= */ false, @@ -171,41 +175,41 @@ public class LauncherTaskbarUIController extends TaskbarUIController { /** * Should be called from onResume() and onPause(), and animates the Taskbar accordingly. */ - public void onLauncherResumedOrPaused(boolean isResumed) { - onLauncherResumedOrPaused(isResumed, false /* fromInit */); + public void onLauncherVisibilityChanged(boolean isVisible) { + onLauncherVisibilityChanged(isVisible, false /* fromInit */); } - private void onLauncherResumedOrPaused(boolean isResumed, boolean fromInit) { - onLauncherResumedOrPaused( - isResumed, + private void onLauncherVisibilityChanged(boolean isVisible, boolean fromInit) { + onLauncherVisibilityChanged( + isVisible, fromInit, /* startAnimation= */ true, DisplayController.isTransientTaskbar(mLauncher) ? TRANSIENT_TASKBAR_TRANSITION_DURATION - : (!isResumed + : (!isVisible ? QuickstepTransitionManager.TASKBAR_TO_APP_DURATION : QuickstepTransitionManager.TASKBAR_TO_HOME_DURATION)); } @Nullable - private Animator onLauncherResumedOrPaused( - boolean isResumed, boolean fromInit, boolean startAnimation, int duration) { + private Animator onLauncherVisibilityChanged( + boolean isVisible, boolean fromInit, boolean startAnimation, int duration) { // Launcher is resumed during the swipe-to-overview gesture under shell-transitions, so // avoid updating taskbar state in that situation (when it's non-interactive -- or // "background") to avoid premature animations. - if (ENABLE_SHELL_TRANSITIONS && isResumed + if (ENABLE_SHELL_TRANSITIONS && isVisible && mLauncher.getStateManager().getState().hasFlag(FLAG_NON_INTERACTIVE) && !mLauncher.getStateManager().getState().isTaskbarAlignedWithHotseat(mLauncher)) { return null; } - mTaskbarLauncherStateController.updateStateForFlag(FLAG_RESUMED, isResumed); + mTaskbarLauncherStateController.updateStateForFlag(FLAG_VISIBLE, isVisible); return mTaskbarLauncherStateController.applyState(fromInit ? 0 : duration, startAnimation); } @Override public void refreshResumedState() { - onLauncherResumedOrPaused(mLauncher.hasBeenResumed()); + onLauncherVisibilityChanged(mLauncher.hasBeenResumed()); } @Override @@ -353,7 +357,7 @@ public class LauncherTaskbarUIController extends TaskbarUIController { @Override public void onExpandPip() { super.onExpandPip(); - mTaskbarLauncherStateController.updateStateForFlag(FLAG_RESUMED, false); + mTaskbarLauncherStateController.updateStateForFlag(FLAG_VISIBLE, false); mTaskbarLauncherStateController.applyState(); } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java index d4faf47511..cea151d061 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java @@ -1236,7 +1236,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext { TaskbarUIController uiController = mControllers.uiController; if (uiController instanceof LauncherTaskbarUIController) { - ((LauncherTaskbarUIController) uiController).addLauncherResumeAnimation( + ((LauncherTaskbarUIController) uiController).addLauncherVisibilityChangedAnimation( fullAnimation, duration); } mControllers.taskbarStashController.addUnstashToHotseatAnimation(fullAnimation, duration); diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java index 3bfeee8cd7..56ba460f65 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java @@ -68,13 +68,13 @@ public class TaskbarLauncherStateController { private static final String TAG = TaskbarLauncherStateController.class.getSimpleName(); private static final boolean DEBUG = false; - /** Launcher activity is resumed and focused. */ - public static final int FLAG_RESUMED = 1 << 0; + /** Launcher activity is visible and focused. */ + public static final int FLAG_VISIBLE = 1 << 0; /** - * A external transition / animation is running that will result in FLAG_RESUMED being set. + * A external transition / animation is running that will result in FLAG_VISIBLE being set. **/ - public static final int FLAG_TRANSITION_TO_RESUMED = 1 << 1; + public static final int FLAG_TRANSITION_TO_VISIBLE = 1 << 1; /** * Set while the launcher state machine is performing a state transition, see {@link @@ -118,7 +118,7 @@ public class TaskbarLauncherStateController { */ private static final int FLAG_TASKBAR_HIDDEN = 1 << 6; - private static final int FLAGS_LAUNCHER_ACTIVE = FLAG_RESUMED | FLAG_TRANSITION_TO_RESUMED; + private static final int FLAGS_LAUNCHER_ACTIVE = FLAG_VISIBLE | FLAG_TRANSITION_TO_VISIBLE; /** Equivalent to an int with all 1s for binary operation purposes */ private static final int FLAGS_ALL = ~0; @@ -207,7 +207,7 @@ public class TaskbarLauncherStateController { // TODO(b/279514548) Cleans up bad state that can occur when user interacts with // taskbar on top of transparent activity. if (finalState == LauncherState.NORMAL && mLauncher.hasBeenResumed()) { - updateStateForFlag(FLAG_RESUMED, true); + updateStateForFlag(FLAG_VISIBLE, true); } applyState(); boolean disallowLongClick = @@ -282,7 +282,7 @@ public class TaskbarLauncherStateController { } stashController.updateStateForFlag(FLAG_IN_APP, false); - updateStateForFlag(FLAG_TRANSITION_TO_RESUMED, true); + updateStateForFlag(FLAG_TRANSITION_TO_VISIBLE, true); animatorSet.play(stashController.createApplyStateAnimator(duration)); animatorSet.play(applyState(duration, false)); @@ -433,7 +433,7 @@ public class TaskbarLauncherStateController { if (launcherTransitionCompleted && mLauncherState == LauncherState.QUICK_SWITCH_FROM_HOME) { // We're about to be paused, set immediately to ensure seamless handoff. - updateStateForFlag(FLAG_RESUMED, false); + updateStateForFlag(FLAG_VISIBLE, false); applyState(0 /* duration */); } if (mLauncherState == LauncherState.NORMAL) { @@ -759,10 +759,10 @@ public class TaskbarLauncherStateController { mTaskBarRecentsAnimationListener = null; ((RecentsView) mLauncher.getOverviewPanel()).setTaskLaunchListener(null); - // Update the resumed state immediately to ensure a seamless handoff - boolean launcherResumed = !finishedToApp; - updateStateForFlag(FLAG_TRANSITION_TO_RESUMED, false); - updateStateForFlag(FLAG_RESUMED, launcherResumed); + // Update the visible state immediately to ensure a seamless handoff + boolean launcherVisible = !finishedToApp; + updateStateForFlag(FLAG_TRANSITION_TO_VISIBLE, false); + updateStateForFlag(FLAG_VISIBLE, launcherVisible); applyState(); TaskbarStashController controller = mControllers.taskbarStashController; @@ -776,8 +776,8 @@ public class TaskbarLauncherStateController { private static String getStateString(int flags) { StringJoiner result = new StringJoiner("|"); - appendFlag(result, flags, FLAG_RESUMED, "resumed"); - appendFlag(result, flags, FLAG_TRANSITION_TO_RESUMED, "transition_to_resumed"); + appendFlag(result, flags, FLAG_VISIBLE, "flag_visible"); + appendFlag(result, flags, FLAG_TRANSITION_TO_VISIBLE, "transition_to_visible"); appendFlag(result, flags, FLAG_LAUNCHER_IN_STATE_TRANSITION, "launcher_in_state_transition"); appendFlag(result, flags, FLAG_AWAKE, "awake"); diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java index 7d88f051fb..c512aa24e2 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java +++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java @@ -33,6 +33,7 @@ import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.LauncherState.OVERVIEW_MODAL_TASK; import static com.android.launcher3.LauncherState.OVERVIEW_SPLIT_SELECT; import static com.android.launcher3.compat.AccessibilityManagerCompat.sendCustomAccessibilityEvent; +import static com.android.launcher3.config.FeatureFlags.ENABLE_HOME_TRANSITION_LISTENER; import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_LAUNCH_TAP; import static com.android.launcher3.model.data.ItemInfo.NO_MATCHING_ID; @@ -92,6 +93,7 @@ import androidx.annotation.RequiresApi; import com.android.app.viewcapture.SettingsAwareViewCapture; import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.DeviceProfile; +import com.android.launcher3.HomeTransitionController; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.LauncherState; @@ -231,6 +233,8 @@ public class QuickstepLauncher extends Launcher { private boolean mEnableWidgetDepth; + private HomeTransitionController mHomeTransitionController; + @Override protected void setupViews() { super.setupViews(); @@ -261,6 +265,11 @@ public class QuickstepLauncher extends Launcher { mAppTransitionManager.registerRemoteAnimations(); mAppTransitionManager.registerRemoteTransitions(); + if (ENABLE_HOME_TRANSITION_LISTENER.get()) { + mHomeTransitionController = new HomeTransitionController(this); + mHomeTransitionController.registerHomeTransitionListener(); + } + mTISBindHelper = new TISBindHelper(this, this::onTISConnected); mDepthController = new DepthController(this); mDesktopVisibilityController = new DesktopVisibilityController(this); @@ -368,8 +377,8 @@ public class QuickstepLauncher extends Launcher { } if ((changeBits & ACTIVITY_STATE_RESUMED) != 0) { - if (mTaskbarUIController != null) { - mTaskbarUIController.onLauncherResumedOrPaused(hasBeenResumed()); + if (!ENABLE_HOME_TRANSITION_LISTENER.get() && mTaskbarUIController != null) { + mTaskbarUIController.onLauncherVisibilityChanged(hasBeenResumed()); } } @@ -482,6 +491,10 @@ public class QuickstepLauncher extends Launcher { mLauncherUnfoldAnimationController.onDestroy(); } + if (mHomeTransitionController != null) { + mHomeTransitionController.unregisterHomeTransitionListener(); + } + if (mDesktopVisibilityController != null) { mDesktopVisibilityController.unregisterSystemUiListener(); } diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java index 56765e5c69..468d96a82f 100644 --- a/quickstep/src/com/android/quickstep/SystemUiProxy.java +++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java @@ -17,6 +17,7 @@ package com.android.quickstep; import static android.app.ActivityManager.RECENT_IGNORE_UNAVAILABLE; +import static com.android.launcher3.config.FeatureFlags.ENABLE_HOME_TRANSITION_LISTENER; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; import static com.android.launcher3.util.SplitConfigurationOptions.StagePosition; @@ -92,6 +93,7 @@ import com.android.wm.shell.splitscreen.ISplitScreenListener; import com.android.wm.shell.splitscreen.ISplitSelectListener; import com.android.wm.shell.startingsurface.IStartingWindow; import com.android.wm.shell.startingsurface.IStartingWindowListener; +import com.android.wm.shell.transition.IHomeTransitionListener; import com.android.wm.shell.transition.IShellTransitions; import com.android.wm.shell.util.GroupedRecentTaskInfo; @@ -147,6 +149,7 @@ public class SystemUiProxy implements ISystemUiProxy { private IOnBackInvokedCallback mBackToLauncherCallback; private IRemoteAnimationRunner mBackToLauncherRunner; private IDragAndDrop mDragAndDrop; + private IHomeTransitionListener mHomeTransitionListener; // Used to dedupe calls to SystemUI private int mLastShelfHeight; @@ -248,6 +251,7 @@ public class SystemUiProxy implements ISystemUiProxy { setBubblesListener(mBubblesListener); registerSplitScreenListener(mSplitScreenListener); registerSplitSelectListener(mSplitSelectListener); + setHomeTransitionListener(mHomeTransitionListener); setStartingWindowListener(mStartingWindowListener); setLauncherUnlockAnimationController( mLauncherActivityClass, mLauncherUnlockAnimationController); @@ -1043,6 +1047,24 @@ public class SystemUiProxy implements ISystemUiProxy { mRemoteTransitions.remove(remoteTransition); } + public void setHomeTransitionListener(IHomeTransitionListener listener) { + if (!ENABLE_HOME_TRANSITION_LISTENER.get()) { + return; + } + + mHomeTransitionListener = listener; + + if (mShellTransitions != null) { + try { + mShellTransitions.setHomeTransitionListener(listener); + } catch (RemoteException e) { + Log.w(TAG, "Failed call setHomeTransitionListener", e); + } + } else { + Log.w(TAG, "Unable to call setHomeTransitionListener because ShellTransitions is null"); + } + } + /** * Use SystemUI's transaction-queue instead of Launcher's independent one. This is necessary * if Launcher and SystemUI need to coordinate transactions (eg. for shell transitions). diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java index 2ca8a1e9e0..713009ed75 100644 --- a/src/com/android/launcher3/config/FeatureFlags.java +++ b/src/com/android/launcher3/config/FeatureFlags.java @@ -308,6 +308,10 @@ public final class FeatureFlags { "ENABLE_DYNAMIC_TASKBAR_THRESHOLDS", ENABLED, "Enables taskbar thresholds that scale based on screen size."); + public static final BooleanFlag ENABLE_HOME_TRANSITION_LISTENER = getDebugFlag(306053414, + "ENABLE_HOME_TRANSITION_LISTENER", DISABLED, + "Enables launcher to listen to all transitions that include home activity."); + // TODO(Block 21): Clean up flags public static final BooleanFlag ENABLE_APP_ICON_FOR_INLINE_SHORTCUTS = getDebugFlag(270395087, "ENABLE_APP_ICON_IN_INLINE_SHORTCUTS", DISABLED, "Show app icon for inline shortcut");