Moving TisBinder to its own class
> Using callback patter for various change events instead of routing it
via TIS
Bug: 386288280
Test: Presubmit
Flag: EXEMPT refactor
Change-Id: I95577d6a1c17103cb947ef1200c1c22b68fd1d9c
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
index f704254..66f19eb 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
@@ -71,6 +71,7 @@
import com.android.launcher3.util.SimpleBroadcastReceiver;
import com.android.quickstep.AllAppsActionManager;
import com.android.quickstep.RecentsActivity;
+import com.android.quickstep.RecentsAnimationDeviceState;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.fallback.window.RecentsDisplayModel;
import com.android.quickstep.fallback.window.RecentsWindowManager;
@@ -84,6 +85,7 @@
import java.io.PrintWriter;
import java.util.StringJoiner;
+import java.util.function.LongConsumer;
/**
* Class to manage taskbar lifecycle
@@ -244,6 +246,8 @@
}
};
+ private final LongConsumer mSysUiFlagChangeReceiver = this::onSystemUiFlagsChanged;
+
@SuppressLint("WrongConstant")
public TaskbarManager(
Context context,
@@ -278,6 +282,10 @@
mPrimaryWindowContext, RECEIVER_NOT_EXPORTED, ACTION_SHOW_TASKBAR);
});
+ RecentsAnimationDeviceState deviceState = RecentsAnimationDeviceState.INSTANCE.get(context);
+ onSystemUiFlagsChanged(deviceState.getSystemUiStateFlags());
+ deviceState.addSysUiFlagChangeCallback(mSysUiFlagChangeReceiver);
+
debugWhyTaskbarNotDestroyed("TaskbarManager created");
recreateTaskbar();
}
@@ -606,7 +614,7 @@
}
}
- public void onSystemUiFlagsChanged(@SystemUiStateFlags long systemUiStateFlags) {
+ private void onSystemUiFlagsChanged(@SystemUiStateFlags long systemUiStateFlags) {
if (DEBUG) {
Log.d(TAG, "SysUI flags changed: " + formatFlagChange(systemUiStateFlags,
mSharedState.sysuiStateFlags, QuickStepContract::getSystemUiStateString));
@@ -804,6 +812,8 @@
.unregister(USER_SETUP_COMPLETE_URI, mOnSettingsChangeListener);
SettingsCache.INSTANCE.get(mPrimaryWindowContext)
.unregister(NAV_BAR_KIDS_MODE, mOnSettingsChangeListener);
+ RecentsAnimationDeviceState.INSTANCE.get(getPrimaryWindowContext())
+ .removeSysUiFlagChangeCallback(mSysUiFlagChangeReceiver);
Log.d(TASKBAR_NOT_DESTROYED_TAG, "unregistering component callbacks from destroy().");
mPrimaryWindowContext.unregisterComponentCallbacks(mDefaultComponentCallbacks);
mShutdownReceiver.unregisterReceiverSafely(mPrimaryWindowContext);
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index 23f4f67..6eec7d5 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -172,10 +172,12 @@
import com.android.quickstep.OverviewCommandHelper;
import com.android.quickstep.OverviewComponentObserver;
import com.android.quickstep.OverviewComponentObserver.OverviewChangeListener;
+import com.android.quickstep.RecentsAnimationDeviceState;
+import com.android.quickstep.RecentsAnimationDeviceState.AssistantVisibilityChangeListener;
import com.android.quickstep.RecentsModel;
import com.android.quickstep.SystemUiProxy;
+import com.android.quickstep.TISBinder;
import com.android.quickstep.TaskUtils;
-import com.android.quickstep.TouchInteractionService.TISBinder;
import com.android.quickstep.util.ActiveGestureProtoLogProxy;
import com.android.quickstep.util.AsyncClockEventDelegate;
import com.android.quickstep.util.LauncherUnfoldAnimationController;
@@ -222,7 +224,7 @@
import java.util.stream.Stream;
public class QuickstepLauncher extends Launcher implements RecentsViewContainer,
- SystemShortcut.BubbleActivityStarter {
+ SystemShortcut.BubbleActivityStarter, AssistantVisibilityChangeListener {
private static final boolean TRACE_LAYOUTS =
SystemProperties.getBoolean("persist.debug.trace_layouts", false);
private static final String TRACE_RELAYOUT_CLASS =
@@ -593,6 +595,8 @@
mHotseatPredictionController.destroy();
if (mViewCapture != null) mViewCapture.close();
removeBackAnimationCallback(mSplitSelectStateController.getSplitBackHandler());
+ RecentsAnimationDeviceState.INSTANCE.get(this)
+ .removeAssistantVisibilityChangeListener(this);
}
@Override
@@ -726,6 +730,7 @@
View.setTracedRequestLayoutClassClass(TRACE_RELAYOUT_CLASS);
OverviewComponentObserver.INSTANCE.get(this)
.addOverviewChangeListener(mOverviewChangeListener);
+ RecentsAnimationDeviceState.INSTANCE.get(this).addAssistantVisibilityChangeListener(this);
}
@Override
@@ -1085,7 +1090,6 @@
if (taskbarManager != null) {
taskbarManager.setActivity(this);
}
- mTISBindHelper.setPredictiveBackToHomeInProgress(mIsPredictiveBackToHomeInProgress);
}
@Override
@@ -1359,7 +1363,8 @@
*/
public void setPredictiveBackToHomeInProgress(boolean isInProgress) {
mIsPredictiveBackToHomeInProgress = isInProgress;
- mTISBindHelper.setPredictiveBackToHomeInProgress(isInProgress);
+ RecentsAnimationDeviceState.INSTANCE.get(this)
+ .setPredictiveBackToHomeInProgress(isInProgress);
}
public boolean getPredictiveBackToHomeInProgress() {
@@ -1501,6 +1506,11 @@
return getStateManager().getState().isRecentsViewVisible;
}
+ @Override
+ public void onAssistantVisibilityChanged(float visibility) {
+ mHotseat.getQsb().setAlpha(1f - visibility);
+ }
+
public boolean isCanShowAllAppsEducationView() {
return mCanShowAllAppsEducationView;
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
index ff726e6..865e16b 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
@@ -28,8 +28,6 @@
import static com.android.launcher3.anim.AnimatorListeners.forSuccessCallback;
import static com.android.launcher3.util.NavigationMode.THREE_BUTTONS;
import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_ONE_HANDED_ACTIVE;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
@@ -47,7 +45,7 @@
import com.android.launcher3.uioverrides.QuickstepLauncher;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.VibratorWrapper;
-import com.android.quickstep.SystemUiProxy;
+import com.android.quickstep.RecentsAnimationDeviceState;
import com.android.quickstep.util.AnimatorControllerWithResistance;
import com.android.quickstep.util.MotionPauseDetector;
import com.android.quickstep.util.OverviewToHomeAnim;
@@ -113,8 +111,8 @@
return false;
}
mDidTouchStartInNavBar = (ev.getEdgeFlags() & EDGE_NAV_BAR) != 0;
- boolean isOneHandedModeActive = (SystemUiProxy.INSTANCE.get(mLauncher)
- .getLastSystemUiStateFlags() & SYSUI_STATE_ONE_HANDED_ACTIVE) != 0;
+ boolean isOneHandedModeActive =
+ RecentsAnimationDeviceState.INSTANCE.get(mLauncher).isOneHandedModeActive();
// Reset touch slop multiplier to default 1.0f if one-handed-mode is not active
mDetector.setTouchSlopMultiplier(
isOneHandedModeActive ? ONE_HANDED_ACTIVATED_SLOP_MULTIPLIER : 1f /* default */);
@@ -250,9 +248,8 @@
}
private boolean handlingOverviewAnim() {
- long stateFlags = SystemUiProxy.INSTANCE.get(mLauncher).getLastSystemUiStateFlags();
return mDidTouchStartInNavBar && mStartState == NORMAL
- && (stateFlags & SYSUI_STATE_OVERVIEW_DISABLED) == 0;
+ && !RecentsAnimationDeviceState.INSTANCE.get(mLauncher).isOverviewDisabled();
}
@Override
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
index 05d12c3..6bca4c7 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
@@ -55,7 +55,6 @@
import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY;
import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_TRANSLATION;
import static com.android.quickstep.views.RecentsView.TASK_THUMBNAIL_SPLASH_ALPHA;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
@@ -79,7 +78,7 @@
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.TouchController;
import com.android.launcher3.util.VibratorWrapper;
-import com.android.quickstep.SystemUiProxy;
+import com.android.quickstep.RecentsAnimationDeviceState;
import com.android.quickstep.util.AnimatorControllerWithResistance;
import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.util.MotionPauseDetector;
@@ -178,8 +177,7 @@
if ((ev.getEdgeFlags() & Utilities.EDGE_NAV_BAR) == 0) {
return false;
}
- long stateFlags = SystemUiProxy.INSTANCE.get(mLauncher).getLastSystemUiStateFlags();
- if ((stateFlags & SYSUI_STATE_OVERVIEW_DISABLED) != 0) {
+ if (RecentsAnimationDeviceState.INSTANCE.get(mLauncher).isOverviewDisabled()) {
return false;
}
if (isTrackpadMultiFingerSwipe(ev)) {
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
index f582324..7547f15 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
@@ -34,7 +34,6 @@
import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY;
import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
import android.view.MotionEvent;
@@ -46,7 +45,7 @@
import com.android.launcher3.uioverrides.QuickstepLauncher;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.NavigationMode;
-import com.android.quickstep.SystemUiProxy;
+import com.android.quickstep.RecentsAnimationDeviceState;
import com.android.quickstep.TaskUtils;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
@@ -84,8 +83,7 @@
@Override
protected LauncherState getTargetState(LauncherState fromState, boolean isDragTowardPositive) {
- long stateFlags = SystemUiProxy.INSTANCE.get(mLauncher).getLastSystemUiStateFlags();
- if ((stateFlags & SYSUI_STATE_OVERVIEW_DISABLED) != 0) {
+ if (RecentsAnimationDeviceState.INSTANCE.get(mLauncher).isOverviewDisabled()) {
return NORMAL;
}
return isDragTowardPositive ? QUICK_SWITCH_FROM_HOME : NORMAL;
diff --git a/quickstep/src/com/android/quickstep/BaseContainerInterface.java b/quickstep/src/com/android/quickstep/BaseContainerInterface.java
index 6d588d9..82fbaa6 100644
--- a/quickstep/src/com/android/quickstep/BaseContainerInterface.java
+++ b/quickstep/src/com/android/quickstep/BaseContainerInterface.java
@@ -83,8 +83,6 @@
public abstract boolean isInLiveTileMode();
- public abstract void onAssistantVisibilityChanged(float assistantVisibility);
-
public abstract boolean isResumed();
public abstract boolean isStarted();
diff --git a/quickstep/src/com/android/quickstep/FallbackActivityInterface.java b/quickstep/src/com/android/quickstep/FallbackActivityInterface.java
index d8e0296..d122d24 100644
--- a/quickstep/src/com/android/quickstep/FallbackActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/FallbackActivityInterface.java
@@ -69,14 +69,6 @@
}
}
- /** 5 */
- @Override
- public void onAssistantVisibilityChanged(float visibility) {
- // This class becomes active when the screen is locked.
- // Rather than having it handle assistant visibility changes, the assistant visibility is
- // set to zero prior to this class becoming active.
- }
-
/** 6 */
@Override
public AnimationFactory prepareRecentsUI(
diff --git a/quickstep/src/com/android/quickstep/FallbackWindowInterface.java b/quickstep/src/com/android/quickstep/FallbackWindowInterface.java
index 35630ef..33fe02e 100644
--- a/quickstep/src/com/android/quickstep/FallbackWindowInterface.java
+++ b/quickstep/src/com/android/quickstep/FallbackWindowInterface.java
@@ -70,14 +70,6 @@
}
}
- /** 5 */
- @Override
- public void onAssistantVisibilityChanged(float visibility) {
- // This class becomes active when the screen is locked.
- // Rather than having it handle assistant visibility changes, the assistant visibility is
- // set to zero prior to this class becoming active.
- }
-
/** 6 */
@Override
public BaseWindowInterface.AnimationFactory prepareRecentsUI(boolean activityVisible,
diff --git a/quickstep/src/com/android/quickstep/InputConsumerUtils.kt b/quickstep/src/com/android/quickstep/InputConsumerUtils.kt
index c340c92..1a82d3b 100644
--- a/quickstep/src/com/android/quickstep/InputConsumerUtils.kt
+++ b/quickstep/src/com/android/quickstep/InputConsumerUtils.kt
@@ -18,7 +18,6 @@
import android.content.Context
import android.view.MotionEvent
import androidx.annotation.VisibleForTesting
-import com.android.launcher3.anim.AnimatedFloat
import com.android.launcher3.statemanager.BaseState
import com.android.launcher3.statemanager.StatefulContainer
import com.android.launcher3.taskbar.TaskbarManager
@@ -47,7 +46,6 @@
import com.android.systemui.shared.system.InputMonitorCompat
import com.android.wm.shell.Flags
import java.util.function.Consumer
-import java.util.function.Function
/** Utility class for creating input consumers. */
object InputConsumerUtils {
@@ -68,7 +66,6 @@
onCompleteCallback: Consumer<OtherActivityInputConsumer>,
inputEventReceiver: InputChannelCompat.InputEventReceiver,
taskbarManager: TaskbarManager,
- swipeUpProxyProvider: Function<GestureState?, AnimatedFloat?>,
overviewCommandHelper: OverviewCommandHelper,
event: MotionEvent,
): InputConsumer where T : RecentsViewContainer, T : StatefulContainer<S> {
@@ -83,7 +80,7 @@
)
return consumer
}
- val progressProxy = swipeUpProxyProvider.apply(gestureState)
+ val progressProxy = deviceState.getSwipeUpProxy(gestureState)
if (progressProxy != null) {
val consumer: InputConsumer =
ProgressDelegateInputConsumer(
diff --git a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
index ac0aa76..2c37470 100644
--- a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
@@ -97,15 +97,6 @@
}
@Override
- public void onAssistantVisibilityChanged(float visibility) {
- QuickstepLauncher launcher = getCreatedContainer();
- if (launcher == null) {
- return;
- }
- launcher.onAssistantVisibilityChanged(visibility);
- }
-
- @Override
public AnimationFactory prepareRecentsUI(
boolean activityVisible, Consumer<AnimatorControllerWithResistance> callback) {
notifyRecentsOfOrientation();
diff --git a/quickstep/src/com/android/quickstep/OverviewComponentObserver.java b/quickstep/src/com/android/quickstep/OverviewComponentObserver.java
index 1f95c41..a34b239 100644
--- a/quickstep/src/com/android/quickstep/OverviewComponentObserver.java
+++ b/quickstep/src/com/android/quickstep/OverviewComponentObserver.java
@@ -57,6 +57,7 @@
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.function.LongConsumer;
import javax.inject.Inject;
@@ -79,6 +80,7 @@
private final Context mContext;
private final RecentsDisplayModel mRecentsDisplayModel;
+ private final RecentsAnimationDeviceState mDeviceState;
private final Intent mCurrentHomeIntent;
private final Intent mMyHomeIntent;
@@ -100,9 +102,11 @@
public OverviewComponentObserver(
@ApplicationContext Context context,
RecentsDisplayModel recentsDisplayModel,
+ RecentsAnimationDeviceState deviceState,
DaggerSingletonTracker lifecycleTracker) {
mContext = context;
mRecentsDisplayModel = recentsDisplayModel;
+ mDeviceState = deviceState;
mCurrentHomeIntent = createHomeIntent();
mMyHomeIntent = new Intent(mCurrentHomeIntent).setPackage(mContext.getPackageName());
ResolveInfo info = context.getPackageManager().resolveActivity(mMyHomeIntent, 0);
@@ -128,6 +132,12 @@
updateOverviewTargets();
lifecycleTracker.addCloseable(this::onDestroy);
+
+ setHomeDisabled(deviceState.isHomeDisabled());
+ LongConsumer flagChangeCallback = l -> setHomeDisabled(deviceState.isHomeDisabled());
+ deviceState.addSysUiFlagChangeCallback(flagChangeCallback);
+ lifecycleTracker.addCloseable(
+ () -> deviceState.removeSysUiFlagChangeCallback(flagChangeCallback));
}
/** Adds a listener for changes in {@link #isHomeAndOverviewSame()} */
@@ -140,11 +150,7 @@
mOverviewChangeListeners.remove(overviewChangeListener);
}
- /**
- * Called to set home enabled/disabled state via systemUI
- * @param isHomeDisabled
- */
- public void setHomeDisabled(boolean isHomeDisabled) {
+ private void setHomeDisabled(boolean isHomeDisabled) {
if (isHomeDisabled != mIsHomeDisabled) {
mIsHomeDisabled = isHomeDisabled;
updateOverviewTargets();
@@ -175,9 +181,7 @@
// Set assistant visibility to 0 from launcher's perspective, ensures any elements that
// launcher made invisible become visible again before the new activity control helper
// becomes active.
- if (mContainerInterface != null) {
- mContainerInterface.onAssistantVisibilityChanged(0.f);
- }
+ mDeviceState.setAssistantVisibility(0f);
if (SEPARATE_RECENTS_ACTIVITY.get() || Flags.enableLauncherOverviewInWindow()) {
mIsDefaultHome = false;
diff --git a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
index 9b0e75c..90221f3 100644
--- a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
+++ b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
@@ -172,7 +172,7 @@
return response;
case TestProtocol.REQUEST_REFRESH_OVERVIEW_TARGET:
- runOnTISBinder(TouchInteractionService.TISBinder::refreshOverviewTarget);
+ runOnTISBinder(TISBinder::refreshOverviewTarget);
return response;
case TestProtocol.REQUEST_RECREATE_TASKBAR:
@@ -220,7 +220,7 @@
}
private void enableBlockingTimeout(
- TouchInteractionService.TISBinder tisBinder, boolean enable) {
+ TISBinder tisBinder, boolean enable) {
TaskbarActivityContext context = tisBinder.getTaskbarManager().getCurrentActivityContext();
if (context == null) {
return;
@@ -236,7 +236,7 @@
* Runs the given command on the UI thread, after ensuring we are connected to
* TouchInteractionService.
*/
- protected void runOnTISBinder(Consumer<TouchInteractionService.TISBinder> connectionCallback) {
+ protected void runOnTISBinder(Consumer<TISBinder> connectionCallback) {
try {
CountDownLatch countDownLatch = new CountDownLatch(1);
TISBindHelper helper = MAIN_EXECUTOR.submit(() ->
@@ -252,7 +252,7 @@
}
private <T> Bundle getTISBinderUIProperty(
- BundleSetter<T> bundleSetter, Function<TouchInteractionService.TISBinder, T> provider) {
+ BundleSetter<T> bundleSetter, Function<TISBinder, T> provider) {
Bundle response = new Bundle();
runOnTISBinder(tisBinder -> bundleSetter.set(
diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java
index fca67c3..760130e 100644
--- a/quickstep/src/com/android/quickstep/RecentsActivity.java
+++ b/quickstep/src/com/android/quickstep/RecentsActivity.java
@@ -165,7 +165,7 @@
mTISBindHelper = new TISBindHelper(this, this::onTISConnected);
}
- private void onTISConnected(TouchInteractionService.TISBinder binder) {
+ private void onTISConnected(TISBinder binder) {
TaskbarManager taskbarManager = binder.getTaskbarManager();
if (taskbarManager != null) {
taskbarManager.setActivity(this);
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
index 090ccdc..322e7c4 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
@@ -64,6 +64,7 @@
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
+import com.android.launcher3.anim.AnimatedFloat;
import com.android.launcher3.dagger.ApplicationContext;
import com.android.launcher3.dagger.LauncherAppComponent;
import com.android.launcher3.dagger.LauncherAppSingleton;
@@ -88,6 +89,10 @@
import com.android.systemui.shared.system.TaskStackChangeListeners;
import java.io.PrintWriter;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.function.Function;
+import java.util.function.LongConsumer;
import javax.inject.Inject;
@@ -118,12 +123,16 @@
private final boolean mCanImeRenderGesturalNavButtons =
InputMethodService.canImeRenderGesturalNavButtons();
+ private final List<LongConsumer> mFlagChangeCallbacks = new CopyOnWriteArrayList<>();
private @SystemUiStateFlags long mSystemUiStateFlags = QuickStepContract.SYSUI_STATE_AWAKE;
private NavigationMode mMode = THREE_BUTTONS;
private NavBarPosition mNavBarPosition;
private final Region mDeferredGestureRegion = new Region();
private boolean mAssistantAvailable;
+
+ private final List<AssistantVisibilityChangeListener> mAssistantVisibilityChangeListeners =
+ new CopyOnWriteArrayList<>();
private float mAssistantVisibility;
private boolean mIsUserSetupComplete;
private boolean mIsOneHandedModeEnabled;
@@ -136,6 +145,8 @@
private @NonNull Region mExclusionRegion = GestureExclusionManager.EMPTY_REGION;
private boolean mExclusionListenerRegistered;
+ private Function<GestureState, AnimatedFloat> mSwipeUpProxyProvider = null;
+
@VisibleForTesting
@Inject
RecentsAnimationDeviceState(
@@ -355,8 +366,9 @@
/**
* Updates the system ui state flags from SystemUI.
*/
- public void setSystemUiFlags(@SystemUiStateFlags long stateFlags) {
+ public void setSystemUiStateFlags(@SystemUiStateFlags long stateFlags) {
mSystemUiStateFlags = stateFlags;
+ mFlagChangeCallbacks.forEach(c -> c.accept(stateFlags));
}
/**
@@ -369,6 +381,20 @@
}
/**
+ * Adds a callback to receiver sysui flag changes
+ */
+ public void addSysUiFlagChangeCallback(LongConsumer callback) {
+ mFlagChangeCallbacks.add(callback);
+ }
+
+ /**
+ * Removes a previously added sysui flag change callback
+ */
+ public void removeSysUiFlagChangeCallback(LongConsumer callback) {
+ mFlagChangeCallbacks.remove(callback);
+ }
+
+ /**
* Sets the flag that indicates whether a predictive back-to-home animation is in progress
*/
public void setPredictiveBackToHomeInProgress(boolean isInProgress) {
@@ -383,6 +409,22 @@
}
/**
+ * Sets or clears a function to proxy swipe up transition behavior
+ */
+ public void setSwipeUpProxyProvider(
+ @Nullable Function<GestureState, AnimatedFloat> swipeUpProxyProvider) {
+ mSwipeUpProxyProvider = swipeUpProxyProvider;
+ }
+
+ /**
+ * Returns a proxy animation for swipe up transition if a proxy function was previously set
+ */
+ public AnimatedFloat getSwipeUpProxy(GestureState state) {
+ Function<GestureState, AnimatedFloat> provider = mSwipeUpProxyProvider;
+ return provider != null ? provider.apply(state) : null;
+ }
+
+ /**
* @return whether SystemUI is in a state where we can start a system gesture.
*/
public boolean canStartSystemGesture() {
@@ -535,6 +577,8 @@
*/
public void setAssistantVisibility(float visibility) {
mAssistantVisibility = visibility;
+ mAssistantVisibilityChangeListeners.forEach(
+ l -> l.onAssistantVisibilityChanged(visibility));
}
/**
@@ -544,6 +588,16 @@
return mAssistantVisibility;
}
+ /** Add a listener for assistant visibility changes */
+ public void addAssistantVisibilityChangeListener(AssistantVisibilityChangeListener l) {
+ mAssistantVisibilityChangeListeners.add(l);
+ }
+
+ /** Removes a previously added visibility change listener */
+ public void removeAssistantVisibilityChangeListener(AssistantVisibilityChangeListener l) {
+ mAssistantVisibilityChangeListeners.remove(l);
+ }
+
/**
* @return whether the Assistant gesture can be used in 3 button navigation mode.
*/
@@ -633,6 +687,13 @@
return QuickStepContract.getSystemUiStateString(mSystemUiStateFlags);
}
+ /** Interface for listening assistant visibility change */
+ @FunctionalInterface
+ public interface AssistantVisibilityChangeListener {
+ /** Called when assistant visibility changes */
+ void onAssistantVisibilityChanged(float visibility);
+ }
+
public void dump(PrintWriter pw) {
pw.println("DeviceState:");
pw.println(" canStartSystemGesture=" + canStartSystemGesture());
diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.kt b/quickstep/src/com/android/quickstep/SystemUiProxy.kt
index a1ac39e..32bdcdb 100644
--- a/quickstep/src/com/android/quickstep/SystemUiProxy.kt
+++ b/quickstep/src/com/android/quickstep/SystemUiProxy.kt
@@ -65,7 +65,6 @@
import com.android.systemui.shared.recents.ISystemUiProxy
import com.android.systemui.shared.recents.model.ThumbnailData.Companion.wrap
import com.android.systemui.shared.system.QuickStepContract
-import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags
import com.android.systemui.shared.system.RecentsAnimationControllerCompat
import com.android.systemui.shared.system.RecentsAnimationListener
import com.android.systemui.shared.system.smartspace.ILauncherUnlockAnimationController
@@ -162,9 +161,6 @@
private val asyncHandler =
Handler(Executors.UI_HELPER_EXECUTOR.looper) { handleMessageAsync(it) }
- // TODO(141886704): Find a way to remove this
- @SystemUiStateFlags var lastSystemUiStateFlags: Long = 0
-
/**
* This is a singleton pending intent that is used to start recents via Shell (which is a
* different process). It is bare-bones, so it's expected that the component and options will be
@@ -194,7 +190,7 @@
private inline fun executeWithErrorLog(
errorMsg: () -> String,
tag: String = TAG,
- callback: () -> Any?,
+ callback: () -> Unit,
) {
try {
callback.invoke()
@@ -232,36 +228,30 @@
* Sets proxy state, including death linkage, various listeners, and other configuration objects
*/
@MainThread
- fun setProxy(
- proxy: ISystemUiProxy?,
- pip: IPip?,
- bubbles: IBubbles?,
- splitScreen: ISplitScreen?,
- oneHanded: IOneHanded?,
- shellTransitions: IShellTransitions?,
- startingWindow: IStartingWindow?,
- recentTasks: IRecentTasks?,
- sysuiUnlockAnimationController: ISysuiUnlockAnimationController?,
- backAnimation: IBackAnimation?,
- desktopMode: IDesktopMode?,
- unfoldAnimation: IUnfoldAnimation?,
- dragAndDrop: IDragAndDrop?,
- ) {
+ fun setProxy(bundle: Bundle) {
Preconditions.assertUIThread()
unlinkToDeath()
- systemUiProxy = proxy
- this.pip = pip
- this.bubbles = bubbles
- this.splitScreen = splitScreen
- this.oneHanded = oneHanded
- this.shellTransitions = shellTransitions
- this.startingWindow = startingWindow
- this.sysuiUnlockAnimationController = sysuiUnlockAnimationController
- this.recentTasks = recentTasks
- this.backAnimation = backAnimation
- this.desktopMode = desktopMode
- this.unfoldAnimation = if (Flags.enableUnfoldStateAnimation()) null else unfoldAnimation
- this.dragAndDrop = dragAndDrop
+ systemUiProxy = ISystemUiProxy.Stub.asInterface(bundle.getBinder(ISystemUiProxy.DESCRIPTOR))
+ pip = IPip.Stub.asInterface(bundle.getBinder(IPip.DESCRIPTOR))
+ bubbles = IBubbles.Stub.asInterface(bundle.getBinder(IBubbles.DESCRIPTOR))
+ splitScreen = ISplitScreen.Stub.asInterface(bundle.getBinder(ISplitScreen.DESCRIPTOR))
+ oneHanded = IOneHanded.Stub.asInterface(bundle.getBinder(IOneHanded.DESCRIPTOR))
+ shellTransitions =
+ IShellTransitions.Stub.asInterface(bundle.getBinder(IShellTransitions.DESCRIPTOR))
+ startingWindow =
+ IStartingWindow.Stub.asInterface(bundle.getBinder(IStartingWindow.DESCRIPTOR))
+ sysuiUnlockAnimationController =
+ ISysuiUnlockAnimationController.Stub.asInterface(
+ bundle.getBinder(ISysuiUnlockAnimationController.DESCRIPTOR)
+ )
+ recentTasks = IRecentTasks.Stub.asInterface(bundle.getBinder(IRecentTasks.DESCRIPTOR))
+ backAnimation = IBackAnimation.Stub.asInterface(bundle.getBinder(IBackAnimation.DESCRIPTOR))
+ desktopMode = IDesktopMode.Stub.asInterface(bundle.getBinder(IDesktopMode.DESCRIPTOR))
+ unfoldAnimation =
+ if (Flags.enableUnfoldStateAnimation()) null
+ else IUnfoldAnimation.Stub.asInterface(bundle.getBinder(IUnfoldAnimation.DESCRIPTOR))
+ dragAndDrop = IDragAndDrop.Stub.asInterface(bundle.getBinder(IDragAndDrop.DESCRIPTOR))
+
linkToDeath()
// re-attach the listeners once missing due to setProxy has not been initialized yet.
setPipAnimationListener(pipAnimationListener)
@@ -289,15 +279,12 @@
stateChangeCallbacks.forEach { it.run() }
if (unfoldTransitionProvider != null) {
- if (unfoldAnimation != null) {
- try {
- unfoldAnimation.setListener(unfoldTransitionProvider)
+ unfoldTransitionProvider.isActive = false
+ executeWithErrorLog({ "Failed to set unfold anim listener" }) {
+ unfoldAnimation?.apply {
+ setListener(unfoldTransitionProvider)
unfoldTransitionProvider.isActive = true
- } catch (e: RemoteException) {
- // Ignore
}
- } else {
- unfoldTransitionProvider.isActive = false
}
}
}
@@ -305,9 +292,7 @@
/**
* Clear the proxy to release held resources and turn the majority of its operations into no-ops
*/
- @MainThread
- fun clearProxy() =
- setProxy(null, null, null, null, null, null, null, null, null, null, null, null, null)
+ @MainThread fun clearProxy() = setProxy(Bundle.EMPTY)
/** Adds a callback to be notified whenever the active state changes */
fun addOnStateChangeListener(callback: Runnable) = stateChangeCallbacks.add(callback)
diff --git a/quickstep/src/com/android/quickstep/TISBinder.kt b/quickstep/src/com/android/quickstep/TISBinder.kt
new file mode 100644
index 0000000..683012c
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/TISBinder.kt
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2025 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.quickstep
+
+import android.graphics.Region
+import android.os.Bundle
+import android.os.IRemoteCallback
+import android.os.RemoteException
+import android.util.Log
+import androidx.annotation.BinderThread
+import androidx.annotation.VisibleForTesting
+import com.android.launcher3.taskbar.TaskbarManager
+import com.android.launcher3.testing.TestLogging
+import com.android.launcher3.testing.shared.TestProtocol
+import com.android.launcher3.util.Executors
+import com.android.quickstep.OverviewCommandHelper.CommandType.HIDE
+import com.android.quickstep.OverviewCommandHelper.CommandType.KEYBOARD_INPUT
+import com.android.quickstep.OverviewCommandHelper.CommandType.SHOW
+import com.android.quickstep.OverviewCommandHelper.CommandType.TOGGLE
+import com.android.quickstep.util.ActivityPreloadUtil.preloadOverviewForTIS
+import com.android.quickstep.util.ContextualSearchInvoker
+import com.android.systemui.shared.recents.ILauncherProxy
+import com.android.systemui.shared.statusbar.phone.BarTransitions.TransitionMode
+import com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS
+import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags
+import java.lang.ref.WeakReference
+
+/** Local ILauncherProxy implementation with some methods for local components */
+private const val TAG = "TISBinder"
+
+class TISBinder internal constructor(tis: TouchInteractionService) : ILauncherProxy.Stub() {
+
+ private val mTis = WeakReference(tis)
+
+ /** Returns the [TaskbarManager] or `null` if TouchInteractionService is not connected */
+ val taskbarManager: TaskbarManager?
+ get() = mTis.get()?.taskbarManager
+
+ /** Returns the [OverviewCommandHelper] or `null` if TouchInteractionService is not connected */
+ val overviewCommandHelper: OverviewCommandHelper?
+ get() = mTis.get()?.overviewCommandHelper
+
+ private val deviceState: RecentsAnimationDeviceState?
+ get() = mTis.get()?.let { RecentsAnimationDeviceState.INSTANCE[it] }
+
+ private inline fun executeForTaskbarManagerOnMain(
+ crossinline callback: TaskbarManager.() -> Unit
+ ) {
+ Executors.MAIN_EXECUTOR.execute { taskbarManager?.let { callback.invoke(it) } }
+ }
+
+ @BinderThread
+ override fun onInitialize(bundle: Bundle) {
+ Executors.MAIN_EXECUTOR.execute {
+ mTis.get()?.let {
+ SystemUiProxy.INSTANCE[it].setProxy(bundle)
+ preloadOverviewForTIS(it, true /* fromInit */)
+ }
+ }
+ }
+
+ @BinderThread
+ override fun onTaskbarToggled() {
+ executeForTaskbarManagerOnMain { currentActivityContext?.toggleTaskbarStash() }
+ }
+
+ @BinderThread
+ override fun onOverviewToggle() {
+ TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "onOverviewToggle")
+ mTis.get()?.let { tis ->
+ // If currently screen pinning, do not enter overview
+ if (RecentsAnimationDeviceState.INSTANCE[tis].isScreenPinningActive) {
+ return@let
+ }
+ TaskUtils.closeSystemWindowsAsync(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS)
+ tis.overviewCommandHelper.addCommand(TOGGLE)
+ }
+ }
+
+ @BinderThread
+ override fun onOverviewShown(triggeredFromAltTab: Boolean) {
+ overviewCommandHelper?.apply {
+ if (triggeredFromAltTab) {
+ TaskUtils.closeSystemWindowsAsync(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS)
+ addCommand(KEYBOARD_INPUT)
+ } else {
+ addCommand(SHOW)
+ }
+ }
+ }
+
+ @BinderThread
+ override fun onOverviewHidden(triggeredFromAltTab: Boolean, triggeredFromHomeKey: Boolean) {
+ overviewCommandHelper?.apply {
+ if (triggeredFromAltTab && !triggeredFromHomeKey) {
+ // onOverviewShownFromAltTab hides the overview and ends at the target app
+ addCommand(HIDE)
+ }
+ }
+ }
+
+ @BinderThread
+ override fun onAssistantAvailable(available: Boolean, longPressHomeEnabled: Boolean) {
+ Executors.MAIN_EXECUTOR.execute {
+ deviceState?.setAssistantAvailable(available)
+ taskbarManager?.onLongPressHomeEnabled(longPressHomeEnabled)
+ }
+ }
+
+ @BinderThread
+ override fun onAssistantVisibilityChanged(visibility: Float) {
+ Executors.MAIN_EXECUTOR.execute { deviceState?.assistantVisibility = visibility }
+ }
+
+ /**
+ * Sent when the assistant has been invoked with the given type (defined in AssistManager) and
+ * should be shown. This method is used if SystemUiProxy#setAssistantOverridesRequested was
+ * previously called including this invocation type.
+ */
+ override fun onAssistantOverrideInvoked(invocationType: Int) {
+ mTis.get()?.let { tis ->
+ if (!ContextualSearchInvoker(tis).tryStartAssistOverride(invocationType)) {
+ Log.w(TAG, "Failed to invoke Assist override")
+ }
+ }
+ }
+
+ @BinderThread
+ override fun onSystemUiStateChanged(@SystemUiStateFlags stateFlags: Long) {
+ Executors.MAIN_EXECUTOR.execute { deviceState?.systemUiStateFlags = stateFlags }
+ }
+
+ @BinderThread
+ override fun onActiveNavBarRegionChanges(region: Region) {
+ Executors.MAIN_EXECUTOR.execute { deviceState?.setDeferredGestureRegion(region) }
+ }
+
+ @BinderThread
+ override fun enterStageSplitFromRunningApp(leftOrTop: Boolean) {
+ mTis.get()?.let { tis ->
+ OverviewComponentObserver.INSTANCE[tis]
+ .containerInterface
+ .createdContainer
+ ?.enterStageSplitFromRunningApp(leftOrTop)
+ }
+ }
+
+ @BinderThread
+ override fun onDisplayAddSystemDecorations(displayId: Int) {
+ executeForTaskbarManagerOnMain { onDisplayAddSystemDecorations(displayId) }
+ }
+
+ @BinderThread
+ override fun onDisplayRemoved(displayId: Int) {
+ executeForTaskbarManagerOnMain { onDisplayRemoved(displayId) }
+ }
+
+ @BinderThread
+ override fun onDisplayRemoveSystemDecorations(displayId: Int) {
+ executeForTaskbarManagerOnMain { onDisplayRemoveSystemDecorations(displayId) }
+ }
+
+ @BinderThread
+ override fun updateWallpaperVisibility(displayId: Int, visible: Boolean) {
+ executeForTaskbarManagerOnMain { setWallpaperVisible(displayId, visible) }
+ }
+
+ @BinderThread
+ override fun checkNavBarModes(displayId: Int) {
+ executeForTaskbarManagerOnMain { checkNavBarModes(displayId) }
+ }
+
+ @BinderThread
+ override fun finishBarAnimations(displayId: Int) {
+ executeForTaskbarManagerOnMain { finishBarAnimations(displayId) }
+ }
+
+ @BinderThread
+ override fun touchAutoDim(displayId: Int, reset: Boolean) {
+ executeForTaskbarManagerOnMain { touchAutoDim(displayId, reset) }
+ }
+
+ @BinderThread
+ override fun transitionTo(displayId: Int, @TransitionMode barMode: Int, animate: Boolean) {
+ executeForTaskbarManagerOnMain { transitionTo(displayId, barMode, animate) }
+ }
+
+ @BinderThread
+ override fun appTransitionPending(pending: Boolean) {
+ executeForTaskbarManagerOnMain { appTransitionPending(pending) }
+ }
+
+ override fun onRotationProposal(rotation: Int, isValid: Boolean) {
+ executeForTaskbarManagerOnMain { onRotationProposal(rotation, isValid) }
+ }
+
+ override fun disable(displayId: Int, state1: Int, state2: Int, animate: Boolean) {
+ executeForTaskbarManagerOnMain { disableNavBarElements(displayId, state1, state2, animate) }
+ }
+
+ override fun onSystemBarAttributesChanged(displayId: Int, behavior: Int) {
+ executeForTaskbarManagerOnMain { onSystemBarAttributesChanged(displayId, behavior) }
+ }
+
+ override fun onTransitionModeUpdated(barMode: Int, checkBarModes: Boolean) {
+ executeForTaskbarManagerOnMain { onTransitionModeUpdated(barMode, checkBarModes) }
+ }
+
+ override fun onNavButtonsDarkIntensityChanged(darkIntensity: Float) {
+ executeForTaskbarManagerOnMain { onNavButtonsDarkIntensityChanged(darkIntensity) }
+ }
+
+ override fun onNavigationBarLumaSamplingEnabled(displayId: Int, enable: Boolean) {
+ executeForTaskbarManagerOnMain { onNavigationBarLumaSamplingEnabled(displayId, enable) }
+ }
+
+ override fun onUnbind(reply: IRemoteCallback) {
+ // Run everything in the same main thread block to ensure the cleanup happens before
+ // sending the reply.
+ Executors.MAIN_EXECUTOR.execute {
+ taskbarManager?.destroy()
+ try {
+ reply.sendResult(null)
+ } catch (e: RemoteException) {
+ Log.w(TAG, "onUnbind: Failed to reply to LauncherProxyService", e)
+ }
+ }
+ }
+
+ @VisibleForTesting
+ fun injectFakeTrackpadForTesting() = mTis.get()?.injectFakeTrackpadForTesting()
+
+ @VisibleForTesting fun ejectFakeTrackpadForTesting() = mTis.get()?.ejectFakeTrackpadForTesting()
+
+ @VisibleForTesting fun refreshOverviewTarget() = mTis.get()?.refreshOverviewTarget()
+}
diff --git a/quickstep/src/com/android/quickstep/TaskAnimationManager.java b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
index 63b8aaf..e449048 100644
--- a/quickstep/src/com/android/quickstep/TaskAnimationManager.java
+++ b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
@@ -54,22 +54,25 @@
import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.QuickStepContract;
+import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.TaskStackChangeListeners;
import java.io.PrintWriter;
import java.util.HashMap;
+import java.util.function.LongConsumer;
public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAnimationListener {
public static final boolean SHELL_TRANSITIONS_ROTATION =
SystemProperties.getBoolean("persist.wm.debug.shell_transit_rotate", false);
private final Context mCtx;
+ private final RecentsAnimationDeviceState mDeviceState;
+ private final SystemUiProxy mSystemUiProxy;
private RecentsAnimationController mController;
private RecentsAnimationCallbacks mCallbacks;
private RecentsAnimationTargets mTargets;
private TransitionInfo mTransitionInfo;
- private RecentsAnimationDeviceState mDeviceState;
// Temporary until we can hook into gesture state events
private GestureState mLastGestureState;
@@ -102,12 +105,22 @@
}
};
+
+ private @SystemUiStateFlags long mLastSysuiFlags;
+ private final LongConsumer mSysUiFlagChangeCallback = this::onSystemUiFlagsChanged;
+
TaskAnimationManager(Context ctx, RecentsAnimationDeviceState deviceState) {
+ this(ctx, deviceState, SystemUiProxy.INSTANCE.get(ctx));
+ }
+
+ TaskAnimationManager(Context ctx, RecentsAnimationDeviceState deviceState,
+ SystemUiProxy systemUiProxy) {
mCtx = ctx;
mDeviceState = deviceState;
- }
- SystemUiProxy getSystemUiProxy() {
- return SystemUiProxy.INSTANCE.get(mCtx);
+ mSystemUiProxy = systemUiProxy;
+ mLastSysuiFlags = QuickStepContract.SYSUI_STATE_AWAKE;
+ mDeviceState.addSysUiFlagChangeCallback(mSysUiFlagChangeCallback);
+ onSystemUiFlagsChanged(mDeviceState.getSystemUiStateFlags());
}
boolean shouldIgnoreMotionEvents() {
@@ -151,7 +164,7 @@
final BaseContainerInterface containerInterface = gestureState.getContainerInterface();
mLastGestureState = gestureState;
- RecentsAnimationCallbacks newCallbacks = new RecentsAnimationCallbacks(getSystemUiProxy());
+ RecentsAnimationCallbacks newCallbacks = new RecentsAnimationCallbacks(mSystemUiProxy);
mCallbacks = newCallbacks;
mCallbacks.addListener(new RecentsAnimationCallbacks.RecentsAnimationListener() {
@Override
@@ -289,7 +302,7 @@
if(containerInterface.getCreatedContainer() instanceof RecentsWindowManager
&& (Flags.enableFallbackOverviewInWindow()
|| Flags.enableLauncherOverviewInWindow())) {
- mRecentsAnimationStartPending = getSystemUiProxy().startRecentsActivity(intent, options,
+ mRecentsAnimationStartPending = mSystemUiProxy.startRecentsActivity(intent, options,
mCallbacks, gestureState.useSyntheticRecentsTransition());
RecentsDisplayModel.getINSTANCE().get(mCtx)
.getRecentsWindowManager(mDeviceState.getDisplayId())
@@ -321,7 +334,7 @@
});
}
- mRecentsAnimationStartPending = getSystemUiProxy().startRecentsActivity(intent,
+ mRecentsAnimationStartPending = mSystemUiProxy.startRecentsActivity(intent,
options, mCallbacks, false /* useSyntheticRecentsTransition */);
}
@@ -347,8 +360,13 @@
return mCallbacks;
}
- public void onSystemUiFlagsChanged(@QuickStepContract.SystemUiStateFlags long lastSysUIFlags,
- @QuickStepContract.SystemUiStateFlags long newSysUIFlags) {
+ private void onSystemUiFlagsChanged(@SystemUiStateFlags long newSysUIFlags) {
+ onSystemUiFlagsChanged(mLastSysuiFlags, newSysUIFlags);
+ mLastSysuiFlags = newSysUIFlags;
+ }
+
+ private void onSystemUiFlagsChanged(@SystemUiStateFlags long lastSysUIFlags,
+ @SystemUiStateFlags long newSysUIFlags) {
long isShadeExpandedFlagMask =
SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED | SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
boolean wasExpanded = hasAnyFlag(lastSysUIFlags, isShadeExpandedFlagMask);
@@ -509,4 +527,8 @@
mLastGestureState.dump(prefix + '\t', pw);
}
}
+
+ public void onDestroy() {
+ mDeviceState.removeSysUiFlagChangeCallback(mSysUiFlagChangeCallback);
+ }
}
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index ba4c65a..22fc2ea 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -36,7 +36,6 @@
import static com.android.quickstep.InputConsumer.TYPE_CURSOR_HOVER;
import static com.android.quickstep.InputConsumerUtils.newConsumer;
import static com.android.quickstep.InputConsumerUtils.tryCreateAssistantInputConsumer;
-import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import android.app.PendingIntent;
import android.app.Service;
@@ -44,12 +43,9 @@
import android.content.IIntentSender;
import android.content.Intent;
import android.content.res.Configuration;
-import android.graphics.Region;
import android.os.Bundle;
import android.os.IBinder;
-import android.os.IRemoteCallback;
import android.os.Looper;
-import android.os.RemoteException;
import android.os.SystemClock;
import android.util.Log;
import android.view.Choreographer;
@@ -57,7 +53,6 @@
import android.view.InputEvent;
import android.view.MotionEvent;
-import androidx.annotation.BinderThread;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
@@ -67,7 +62,6 @@
import com.android.launcher3.EncryptionType;
import com.android.launcher3.Flags;
import com.android.launcher3.LauncherPrefs;
-import com.android.launcher3.anim.AnimatedFloat;
import com.android.launcher3.desktop.DesktopAppLaunchTransitionManager;
import com.android.launcher3.statehandlers.DesktopVisibilityController;
import com.android.launcher3.statemanager.StatefulActivity;
@@ -98,34 +92,14 @@
import com.android.quickstep.util.ActiveGestureProtoLogProxy;
import com.android.quickstep.util.ActiveTrackpadList;
import com.android.quickstep.util.ActivityPreloadUtil;
-import com.android.quickstep.util.ContextualSearchInvoker;
import com.android.quickstep.util.ContextualSearchStateManager;
import com.android.quickstep.views.RecentsViewContainer;
-import com.android.systemui.shared.recents.ILauncherProxy;
-import com.android.systemui.shared.recents.ISystemUiProxy;
-import com.android.systemui.shared.statusbar.phone.BarTransitions;
import com.android.systemui.shared.system.InputChannelCompat.InputEventReceiver;
import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.InputMonitorCompat;
-import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
-import com.android.systemui.shared.system.smartspace.ISysuiUnlockAnimationController;
-import com.android.systemui.unfold.progress.IUnfoldAnimation;
-import com.android.wm.shell.back.IBackAnimation;
-import com.android.wm.shell.bubbles.IBubbles;
-import com.android.wm.shell.common.pip.IPip;
-import com.android.wm.shell.desktopmode.IDesktopMode;
-import com.android.wm.shell.draganddrop.IDragAndDrop;
-import com.android.wm.shell.onehanded.IOneHanded;
-import com.android.wm.shell.recents.IRecentTasks;
-import com.android.wm.shell.shared.IShellTransitions;
-import com.android.wm.shell.splitscreen.ISplitScreen;
-import com.android.wm.shell.startingsurface.IStartingWindow;
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import java.lang.ref.WeakReference;
-import java.util.function.Consumer;
-import java.util.function.Function;
/**
* Service connected by system-UI for handling touch interaction.
@@ -141,371 +115,6 @@
private final TISBinder mTISBinder = new TISBinder(this);
- /**
- * Local ILauncherProxy implementation with some methods for local components
- */
- public static class TISBinder extends ILauncherProxy.Stub {
-
- private final WeakReference<TouchInteractionService> mTis;
-
- private TISBinder(TouchInteractionService tis) {
- mTis = new WeakReference<>(tis);
- }
-
- @BinderThread
- public void onInitialize(Bundle bundle) {
- ISystemUiProxy proxy = ISystemUiProxy.Stub.asInterface(
- bundle.getBinder(ISystemUiProxy.DESCRIPTOR));
- IPip pip = IPip.Stub.asInterface(bundle.getBinder(IPip.DESCRIPTOR));
- IBubbles bubbles = IBubbles.Stub.asInterface(bundle.getBinder(IBubbles.DESCRIPTOR));
- ISplitScreen splitscreen = ISplitScreen.Stub.asInterface(bundle.getBinder(
- ISplitScreen.DESCRIPTOR));
- IOneHanded onehanded = IOneHanded.Stub.asInterface(
- bundle.getBinder(IOneHanded.DESCRIPTOR));
- IShellTransitions shellTransitions = IShellTransitions.Stub.asInterface(
- bundle.getBinder(IShellTransitions.DESCRIPTOR));
- IStartingWindow startingWindow = IStartingWindow.Stub.asInterface(
- bundle.getBinder(IStartingWindow.DESCRIPTOR));
- ISysuiUnlockAnimationController launcherUnlockAnimationController =
- ISysuiUnlockAnimationController.Stub.asInterface(
- bundle.getBinder(ISysuiUnlockAnimationController.DESCRIPTOR));
- IRecentTasks recentTasks = IRecentTasks.Stub.asInterface(
- bundle.getBinder(IRecentTasks.DESCRIPTOR));
- IBackAnimation backAnimation = IBackAnimation.Stub.asInterface(
- bundle.getBinder(IBackAnimation.DESCRIPTOR));
- IDesktopMode desktopMode = IDesktopMode.Stub.asInterface(
- bundle.getBinder(IDesktopMode.DESCRIPTOR));
- IUnfoldAnimation unfoldTransition = IUnfoldAnimation.Stub.asInterface(
- bundle.getBinder(IUnfoldAnimation.DESCRIPTOR));
- IDragAndDrop dragAndDrop = IDragAndDrop.Stub.asInterface(
- bundle.getBinder(IDragAndDrop.DESCRIPTOR));
- MAIN_EXECUTOR.execute(() -> executeForTouchInteractionService(tis -> {
- SystemUiProxy.INSTANCE.get(tis).setProxy(proxy, pip,
- bubbles, splitscreen, onehanded, shellTransitions, startingWindow,
- recentTasks, launcherUnlockAnimationController, backAnimation, desktopMode,
- unfoldTransition, dragAndDrop);
- tis.initInputMonitor("TISBinder#onInitialize()");
- ActivityPreloadUtil.preloadOverviewForTIS(tis, true /* fromInit */);
- }));
- }
-
- @BinderThread
- @Override
- public void onTaskbarToggled() {
- MAIN_EXECUTOR.execute(() -> executeForTouchInteractionService(tis -> {
- TaskbarActivityContext activityContext =
- tis.mTaskbarManager.getCurrentActivityContext();
-
- if (activityContext != null) {
- activityContext.toggleTaskbarStash();
- }
- }));
- }
-
- @BinderThread
- public void onOverviewToggle() {
- TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "onOverviewToggle");
- executeForTouchInteractionService(tis -> {
- // If currently screen pinning, do not enter overview
- if (tis.mDeviceState.isScreenPinningActive()) {
- return;
- }
- TaskUtils.closeSystemWindowsAsync(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
- tis.mOverviewCommandHelper.addCommand(CommandType.TOGGLE);
- });
- }
-
- @BinderThread
- @Override
- public void onOverviewShown(boolean triggeredFromAltTab) {
- executeForTouchInteractionService(tis -> {
- if (triggeredFromAltTab) {
- TaskUtils.closeSystemWindowsAsync(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
- tis.mOverviewCommandHelper.addCommand(CommandType.KEYBOARD_INPUT);
- } else {
- tis.mOverviewCommandHelper.addCommand(CommandType.SHOW);
- }
- });
- }
-
- @BinderThread
- @Override
- public void onOverviewHidden(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {
- executeForTouchInteractionService(tis -> {
- if (triggeredFromAltTab && !triggeredFromHomeKey) {
- // onOverviewShownFromAltTab hides the overview and ends at the target app
- tis.mOverviewCommandHelper.addCommand(CommandType.HIDE);
- }
- });
- }
-
- @BinderThread
- @Override
- public void onAssistantAvailable(boolean available, boolean longPressHomeEnabled) {
- MAIN_EXECUTOR.execute(() -> executeForTouchInteractionService(tis -> {
- tis.mDeviceState.setAssistantAvailable(available);
- tis.onAssistantVisibilityChanged();
- executeForTaskbarManager(taskbarManager -> taskbarManager
- .onLongPressHomeEnabled(longPressHomeEnabled));
- }));
- }
-
- @BinderThread
- @Override
- public void onAssistantVisibilityChanged(float visibility) {
- MAIN_EXECUTOR.execute(() -> executeForTouchInteractionService(tis -> {
- tis.mDeviceState.setAssistantVisibility(visibility);
- tis.onAssistantVisibilityChanged();
- }));
- }
-
- /**
- * Sent when the assistant has been invoked with the given type (defined in AssistManager)
- * and should be shown. This method is used if SystemUiProxy#setAssistantOverridesRequested
- * was previously called including this invocation type.
- */
- @Override
- public void onAssistantOverrideInvoked(int invocationType) {
- executeForTouchInteractionService(tis -> {
- if (!new ContextualSearchInvoker(tis).tryStartAssistOverride(invocationType)) {
- Log.w(TAG, "Failed to invoke Assist override");
- }
- });
- }
-
- @BinderThread
- public void onSystemUiStateChanged(@SystemUiStateFlags long stateFlags) {
- MAIN_EXECUTOR.execute(() -> executeForTouchInteractionService(tis -> {
- long lastFlags = tis.mDeviceState.getSystemUiStateFlags();
- tis.mDeviceState.setSystemUiFlags(stateFlags);
- tis.onSystemUiFlagsChanged(lastFlags);
- }));
- }
-
- @BinderThread
- public void onActiveNavBarRegionChanges(Region region) {
- MAIN_EXECUTOR.execute(() -> executeForTouchInteractionService(
- tis -> tis.mDeviceState.setDeferredGestureRegion(region)));
- }
-
- @BinderThread
- @Override
- public void enterStageSplitFromRunningApp(boolean leftOrTop) {
- executeForTouchInteractionService(tis -> {
- RecentsViewContainer container = tis.mOverviewComponentObserver
- .getContainerInterface().getCreatedContainer();
- if (container != null) {
- container.enterStageSplitFromRunningApp(leftOrTop);
- }
- });
- }
-
- @BinderThread
- @Override
- public void onDisplayAddSystemDecorations(int displayId) {
- executeForTaskbarManager(taskbarManager ->
- taskbarManager.onDisplayAddSystemDecorations(displayId));
- }
-
- @BinderThread
- @Override
- public void onDisplayRemoved(int displayId) {
- executeForTaskbarManager(taskbarManager ->
- taskbarManager.onDisplayRemoved(displayId));
- }
-
- @BinderThread
- @Override
- public void onDisplayRemoveSystemDecorations(int displayId) {
- executeForTaskbarManager(taskbarManager ->
- taskbarManager.onDisplayRemoveSystemDecorations(displayId));
- }
-
- @BinderThread
- @Override
- public void updateWallpaperVisibility(int displayId, boolean visible) {
- executeForTaskbarManager(taskbarManager ->
- taskbarManager.setWallpaperVisible(displayId, visible));
- }
-
- @BinderThread
- @Override
- public void checkNavBarModes(int displayId) {
- executeForTaskbarManager(taskbarManager ->
- taskbarManager.checkNavBarModes(displayId));
- }
-
- @BinderThread
- @Override
- public void finishBarAnimations(int displayId) {
- executeForTaskbarManager(taskbarManager ->
- taskbarManager.finishBarAnimations(displayId));
- }
-
- @BinderThread
- @Override
- public void touchAutoDim(int displayId, boolean reset) {
- executeForTaskbarManager(taskbarManager ->
- taskbarManager.touchAutoDim(displayId, reset));
- }
-
- @BinderThread
- @Override
- public void transitionTo(int displayId, @BarTransitions.TransitionMode int barMode,
- boolean animate) {
- executeForTaskbarManager(taskbarManager ->
- taskbarManager.transitionTo(displayId, barMode, animate));
- }
-
- @BinderThread
- @Override
- public void appTransitionPending(boolean pending) {
- executeForTaskbarManager(taskbarManager ->
- taskbarManager.appTransitionPending(pending));
- }
-
- @Override
- public void onRotationProposal(int rotation, boolean isValid) {
- executeForTaskbarManager(taskbarManager ->
- taskbarManager.onRotationProposal(rotation, isValid));
- }
-
- @Override
- public void disable(int displayId, int state1, int state2, boolean animate) {
- executeForTaskbarManager(taskbarManager ->
- taskbarManager.disableNavBarElements(displayId, state1, state2, animate));
- }
-
- @Override
- public void onSystemBarAttributesChanged(int displayId, int behavior) {
- executeForTaskbarManager(taskbarManager ->
- taskbarManager.onSystemBarAttributesChanged(displayId, behavior));
- }
-
- @Override
- public void onTransitionModeUpdated(int barMode, boolean checkBarModes) {
- executeForTaskbarManager(taskbarManager ->
- taskbarManager.onTransitionModeUpdated(barMode, checkBarModes));
- }
-
- @Override
- public void onNavButtonsDarkIntensityChanged(float darkIntensity) {
- executeForTaskbarManager(taskbarManager ->
- taskbarManager.onNavButtonsDarkIntensityChanged(darkIntensity));
- }
-
- @Override
- public void onNavigationBarLumaSamplingEnabled(int displayId, boolean enable) {
- executeForTaskbarManager(taskbarManager ->
- taskbarManager.onNavigationBarLumaSamplingEnabled(displayId, enable));
- }
-
- @Override
- public void onUnbind(IRemoteCallback reply) {
- // Run everything in the same main thread block to ensure the cleanup happens before
- // sending the reply.
- MAIN_EXECUTOR.execute(() -> {
- executeForTaskbarManager(TaskbarManager::destroy);
- try {
- reply.sendResult(null);
- } catch (RemoteException e) {
- Log.w(TAG, "onUnbind: Failed to reply to LauncherProxyService", e);
- }
- });
- }
-
- private void executeForTouchInteractionService(
- @NonNull Consumer<TouchInteractionService> tisConsumer) {
- TouchInteractionService tis = mTis.get();
- if (tis == null) return;
- tisConsumer.accept(tis);
- }
-
- private void executeForTaskbarManager(
- @NonNull Consumer<TaskbarManager> taskbarManagerConsumer) {
- MAIN_EXECUTOR.execute(() -> executeForTouchInteractionService(tis -> {
- TaskbarManager taskbarManager = tis.mTaskbarManager;
- if (taskbarManager == null) return;
- taskbarManagerConsumer.accept(taskbarManager);
- }));
- }
-
- /**
- * Returns the {@link TaskbarManager}.
- * <p>
- * Returns {@code null} if TouchInteractionService is not connected
- */
- @Nullable
- public TaskbarManager getTaskbarManager() {
- TouchInteractionService tis = mTis.get();
- if (tis == null) return null;
- return tis.mTaskbarManager;
- }
-
- @VisibleForTesting
- public void injectFakeTrackpadForTesting() {
- TouchInteractionService tis = mTis.get();
- if (tis == null) return;
- tis.mTrackpadsConnected.add(1000);
- tis.initInputMonitor("tapl testing");
- }
-
- @VisibleForTesting
- public void ejectFakeTrackpadForTesting() {
- TouchInteractionService tis = mTis.get();
- if (tis == null) return;
- tis.mTrackpadsConnected.clear();
- // This method destroys the current input monitor if set up, and only init a new one
- // in 3-button mode if {@code mTrackpadsConnected} is not empty. So in other words,
- // it will destroy the input monitor.
- tis.initInputMonitor("tapl testing");
- }
-
- /**
- * Sets whether a predictive back-to-home animation is in progress in the device state
- */
- public void setPredictiveBackToHomeInProgress(boolean isInProgress) {
- executeForTouchInteractionService(tis ->
- tis.mDeviceState.setPredictiveBackToHomeInProgress(isInProgress));
- }
-
- /**
- * Returns the {@link OverviewCommandHelper}.
- * <p>
- * Returns {@code null} if TouchInteractionService is not connected
- */
- @Nullable
- public OverviewCommandHelper getOverviewCommandHelper() {
- TouchInteractionService tis = mTis.get();
- if (tis == null) return null;
- return tis.mOverviewCommandHelper;
- }
-
- /**
- * Sets a proxy to bypass swipe up behavior
- */
- public void setSwipeUpProxy(Function<GestureState, AnimatedFloat> proxy) {
- executeForTouchInteractionService(
- tis -> tis.mSwipeUpProxyProvider = proxy != null ? proxy : (i -> null));
- }
-
- /**
- * Sets the task id where gestures should be blocked
- */
- public void setGestureBlockedTaskId(int taskId) {
- executeForTouchInteractionService(
- tis -> tis.mDeviceState.setGestureBlockingTaskId(taskId));
- }
-
- /** Refreshes the current overview target. */
- public void refreshOverviewTarget() {
- executeForTouchInteractionService(tis -> {
- tis.mAllAppsActionManager.onDestroy();
- tis.onOverviewTargetChanged(tis.mOverviewComponentObserver.isHomeAndOverviewSame());
- });
- }
- }
-
private RotationTouchHelper mRotationTouchHelper;
private final AbsSwipeUpHandler.Factory mLauncherSwipeHandlerFactory =
@@ -521,6 +130,13 @@
private final ScreenOnTracker.ScreenOnListener mScreenOnListener = this::onScreenOnChanged;
private final OverviewChangeListener mOverviewChangeListener = this::onOverviewTargetChanged;
+ private final Runnable mSysUiProxyStateChangeCallback =
+ () -> {
+ if (SystemUiProxy.INSTANCE.get(this).isActive()) {
+ initInputMonitor("TISBinder#onInitialize()");
+ }
+ };
+
private final TaskbarNavButtonCallbacks mNavCallbacks = new TaskbarNavButtonCallbacks() {
@Override
public void onNavigateHome() {
@@ -554,7 +170,6 @@
private InputEventReceiver mInputEventReceiver;
private TaskbarManager mTaskbarManager;
- private Function<GestureState, AnimatedFloat> mSwipeUpProxyProvider = i -> null;
private AllAppsActionManager mAllAppsActionManager;
private ActiveTrackpadList mTrackpadsConnected;
@@ -597,6 +212,7 @@
mDisplayInfoChangeListener =
mDeviceState.addNavigationModeChangedCallback(this::onNavigationModeChanged);
ScreenOnTracker.INSTANCE.get(this).addListener(mScreenOnListener);
+ SystemUiProxy.INSTANCE.get(this).addOnStateChangeListener(mSysUiProxyStateChangeCallback);
}
private void disposeEventHandlers(String reason) {
@@ -649,8 +265,6 @@
mResetGestureInputConsumer = new ResetGestureInputConsumer(
mTaskAnimationManager, mTaskbarManager::getCurrentActivityContext);
mInputConsumer.registerInputConsumer();
- onSystemUiFlagsChanged(mDeviceState.getSystemUiStateFlags());
- onAssistantVisibilityChanged();
// Initialize the task tracker
TopTaskTracker.INSTANCE.get(this);
@@ -669,6 +283,10 @@
return mOverviewCommandHelper;
}
+ public TaskbarManager getTaskbarManager() {
+ return mTaskbarManager;
+ }
+
private void resetHomeBounceSeenOnQuickstepEnabledFirstTime() {
if (!LockedUserState.get(this).isUserUnlocked() || mDeviceState.isButtonNavMode()) {
// Skip if not yet unlocked (can't read user shared prefs) or if the current navigation
@@ -710,34 +328,18 @@
});
}
- @UiThread
- private void onSystemUiFlagsChanged(@SystemUiStateFlags long lastSysUIFlags) {
- if (LockedUserState.get(this).isUserUnlocked()) {
- long systemUiStateFlags = mDeviceState.getSystemUiStateFlags();
- SystemUiProxy.INSTANCE.get(this).setLastSystemUiStateFlags(systemUiStateFlags);
- mOverviewComponentObserver.setHomeDisabled(mDeviceState.isHomeDisabled());
- mTaskbarManager.onSystemUiFlagsChanged(systemUiStateFlags);
- mTaskAnimationManager.onSystemUiFlagsChanged(lastSysUIFlags, systemUiStateFlags);
- }
- }
-
- @UiThread
- private void onAssistantVisibilityChanged() {
- if (LockedUserState.get(this).isUserUnlocked()) {
- mOverviewComponentObserver.getContainerInterface().onAssistantVisibilityChanged(
- mDeviceState.getAssistantVisibility());
- }
- }
-
@Override
public void onDestroy() {
Log.d(TAG, "onDestroy: user=" + getUserId()
+ " instance=" + System.identityHashCode(this));
if (LockedUserState.get(this).isUserUnlocked()) {
mInputConsumer.unregisterInputConsumer();
- mOverviewComponentObserver.setHomeDisabled(false);
mOverviewComponentObserver.removeOverviewChangeListener(mOverviewChangeListener);
}
+ if (mTaskAnimationManager != null) {
+ mTaskAnimationManager.onDestroy();
+ }
+
disposeEventHandlers("TouchInteractionService onDestroy()");
SystemUiProxy.INSTANCE.get(this).clearProxy();
@@ -752,6 +354,8 @@
mDeviceState.removeDisplayInfoChangeListener(mDisplayInfoChangeListener);
LockedUserState.get(this).removeOnUserUnlockedRunnable(mUserUnlockedRunnable);
ScreenOnTracker.INSTANCE.get(this).removeListener(mScreenOnListener);
+ SystemUiProxy.INSTANCE.get(this)
+ .removeOnStateChangeListener(mSysUiProxyStateChangeCallback);
super.onDestroy();
}
@@ -879,7 +483,6 @@
this::onConsumerInactive,
mInputEventReceiver,
mTaskbarManager,
- mSwipeUpProxyProvider,
mOverviewCommandHelper,
event);
mUncheckedConsumer = mConsumer;
@@ -1158,4 +761,26 @@
gestureState, touchTimeMs, mTaskAnimationManager.isRecentsAnimationRunning(),
mInputConsumer, MSDLPlayerWrapper.INSTANCE.get(this));
}
+
+ @VisibleForTesting
+ public void injectFakeTrackpadForTesting() {
+ mTrackpadsConnected.add(1000);
+ initInputMonitor("tapl testing");
+ }
+
+ @VisibleForTesting
+ public void ejectFakeTrackpadForTesting() {
+ mTrackpadsConnected.clear();
+ // This method destroys the current input monitor if set up, and only init a new one
+ // in 3-button mode if {@code mTrackpadsConnected} is not empty. So in other words,
+ // it will destroy the input monitor.
+ initInputMonitor("tapl testing");
+ }
+
+ /** Refreshes the current overview target. */
+ @VisibleForTesting
+ public void refreshOverviewTarget() {
+ mAllAppsActionManager.onDestroy();
+ onOverviewTargetChanged(mOverviewComponentObserver.isHomeAndOverviewSame());
+ }
}
diff --git a/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java b/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
index c986b88..39a9dff 100644
--- a/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
+++ b/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
@@ -72,7 +72,8 @@
import com.android.quickstep.GestureState;
import com.android.quickstep.OverviewComponentObserver;
import com.android.quickstep.OverviewComponentObserver.OverviewChangeListener;
-import com.android.quickstep.TouchInteractionService.TISBinder;
+import com.android.quickstep.RecentsAnimationDeviceState;
+import com.android.quickstep.TISBinder;
import com.android.quickstep.util.ActivityPreloadUtil;
import com.android.quickstep.util.LottieAnimationColorUtils;
import com.android.quickstep.util.TISBindHelper;
@@ -283,16 +284,13 @@
protected void onResume() {
super.onResume();
maybeResumeOrPauseBackgroundAnimation();
- TISBinder binder = mTISBindHelper.getBinder();
- if (binder != null) {
- setSetupUIVisible(true);
- binder.setSwipeUpProxy(this::createSwipeUpProxy);
- }
+ RecentsAnimationDeviceState.INSTANCE.get(this)
+ .setSwipeUpProxyProvider(this::createSwipeUpProxy);
+ setSetupUIVisible(true);
}
private void onTISConnected(TISBinder binder) {
setSetupUIVisible(isResumed());
- binder.setSwipeUpProxy(isResumed() ? this::createSwipeUpProxy : null);
TaskbarManager taskbarManager = binder.getTaskbarManager();
if (taskbarManager != null) {
mLauncherStartAnim = taskbarManager.createLauncherStartFromSuwAnim(MAX_SWIPE_DURATION);
@@ -306,7 +304,8 @@
@Override
protected void onPause() {
super.onPause();
- clearBinderOverride();
+ setSetupUIVisible(false);
+ RecentsAnimationDeviceState.INSTANCE.get(this).setSwipeUpProxyProvider(null);
maybeResumeOrPauseBackgroundAnimation();
if (mSwipeProgress.value >= 1) {
finishAndRemoveTask();
@@ -314,14 +313,6 @@
}
}
- private void clearBinderOverride() {
- TISBinder binder = mTISBindHelper.getBinder();
- if (binder != null) {
- setSetupUIVisible(false);
- binder.setSwipeUpProxy(null);
- }
- }
-
/**
* Should be called when we have successfully reached Launcher, so we dispatch to animation
* listeners to ensure the state matches the visual animation that just occurred.
@@ -338,8 +329,9 @@
protected void onDestroy() {
super.onDestroy();
getIDP().removeOnChangeListener(mOnIDPChangeListener);
+ // In case bindHelper was not connected during onPause, clear UIVisible flag again
+ setSetupUIVisible(false);
mTISBindHelper.onDestroy();
- clearBinderOverride();
if (mBackgroundAnimatorListener != null) {
mAnimatedBackground.removeAnimatorListener(mBackgroundAnimatorListener);
}
diff --git a/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java b/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java
index 0365f89..2114c30 100644
--- a/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java
+++ b/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java
@@ -38,10 +38,9 @@
import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.R;
import com.android.launcher3.logging.StatsLogManager;
-import com.android.quickstep.TouchInteractionService.TISBinder;
+import com.android.quickstep.RecentsAnimationDeviceState;
import com.android.quickstep.interaction.TutorialController.TutorialType;
import com.android.quickstep.util.LayoutUtils;
-import com.android.quickstep.util.TISBindHelper;
import java.util.ArrayList;
import java.util.Arrays;
@@ -64,7 +63,6 @@
private SharedPreferences mSharedPrefs;
private StatsLogManager mStatsLogManager;
- private TISBindHelper mTISBindHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -99,7 +97,6 @@
.commit();
correctUserOrientation();
- mTISBindHelper = new TISBindHelper(this, this::onTISConnected);
initWindowInsets();
}
@@ -349,10 +346,6 @@
updateServiceState(true);
}
- private void onTISConnected(TISBinder binder) {
- updateServiceState(isResumed());
- }
-
@Override
protected void onPause() {
super.onPause();
@@ -360,16 +353,13 @@
}
private void updateServiceState(boolean isEnabled) {
- TISBinder binder = mTISBindHelper.getBinder();
- if (binder != null) {
- binder.setGestureBlockedTaskId(isEnabled ? getTaskId() : -1);
- }
+ RecentsAnimationDeviceState.INSTANCE.get(this)
+ .setGestureBlockingTaskId(isEnabled ? getTaskId() : -1);
}
@Override
protected void onDestroy() {
super.onDestroy();
- mTISBindHelper.onDestroy();
updateServiceState(false);
}
}
diff --git a/quickstep/src/com/android/quickstep/util/ContextualSearchInvoker.kt b/quickstep/src/com/android/quickstep/util/ContextualSearchInvoker.kt
index d00a39c..969aa0f 100644
--- a/quickstep/src/com/android/quickstep/util/ContextualSearchInvoker.kt
+++ b/quickstep/src/com/android/quickstep/util/ContextualSearchInvoker.kt
@@ -21,7 +21,6 @@
import android.app.contextualsearch.ContextualSearchManager.FEATURE_CONTEXTUAL_SEARCH
import android.content.Context
import android.util.Log
-import androidx.annotation.VisibleForTesting
import com.android.internal.app.AssistUtils
import com.android.launcher3.logging.StatsLogManager
import com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_LAUNCH_ASSISTANT_FAILED_SERVICE_ERROR
@@ -34,7 +33,7 @@
import com.android.quickstep.BaseContainerInterface
import com.android.quickstep.DeviceConfigWrapper
import com.android.quickstep.OverviewComponentObserver
-import com.android.quickstep.SystemUiProxy
+import com.android.quickstep.RecentsAnimationDeviceState
import com.android.quickstep.TopTaskTracker
import com.android.quickstep.views.RecentsView
import com.android.systemui.shared.system.QuickStepContract
@@ -45,9 +44,10 @@
private val context: Context,
private val contextualSearchStateManager: ContextualSearchStateManager,
private val topTaskTracker: TopTaskTracker,
- private val systemUiProxy: SystemUiProxy,
+ private val deviceState: RecentsAnimationDeviceState,
private val statsLogManager: StatsLogManager,
private val contextualSearchHapticManager: ContextualSearchHapticManager,
+ private val overviewComponentObserver: OverviewComponentObserver,
private val contextualSearchManager: ContextualSearchManager?,
) {
constructor(
@@ -56,9 +56,10 @@
context,
ContextualSearchStateManager.INSTANCE[context],
TopTaskTracker.INSTANCE[context],
- SystemUiProxy.INSTANCE[context],
+ RecentsAnimationDeviceState.INSTANCE[context],
StatsLogManager.newInstance(context),
ContextualSearchHapticManager.INSTANCE[context],
+ OverviewComponentObserver.INSTANCE[context],
context.getSystemService(ContextualSearchManager::class.java),
)
@@ -189,7 +190,7 @@
if (contextualSearchManager == null) {
return false
}
- val recentsContainerInterface = getRecentsContainerInterface()
+ val recentsContainerInterface = overviewComponentObserver.containerInterface
if (recentsContainerInterface?.isInLiveTileMode() == true) {
Log.i(TAG, "Contextual Search invocation attempted: live tile")
endLiveTileMode(recentsContainerInterface) {
@@ -202,27 +203,20 @@
}
private fun isFakeLandscape(): Boolean =
- getRecentsContainerInterface()
- ?.getCreatedContainer()
+ overviewComponentObserver.containerInterface
+ ?.createdContainer
?.getOverviewPanel<RecentsView<*, *>>()
- ?.getPagedOrientationHandler()
+ ?.pagedOrientationHandler
?.isLayoutNaturalToLauncher == false
- private fun isInSplitscreen(): Boolean {
- return topTaskTracker.getRunningSplitTaskIds().isNotEmpty()
- }
+ private fun isInSplitscreen(): Boolean = topTaskTracker.runningSplitTaskIds.isNotEmpty()
private fun isNotificationShadeShowing(): Boolean {
- return systemUiProxy.lastSystemUiStateFlags and SHADE_EXPANDED_SYSUI_FLAGS != 0L
+ return deviceState.systemUiStateFlags and SHADE_EXPANDED_SYSUI_FLAGS != 0L
}
private fun isKeyguardShowing(): Boolean {
- return systemUiProxy.lastSystemUiStateFlags and KEYGUARD_SHOWING_SYSUI_FLAGS != 0L
- }
-
- @VisibleForTesting
- fun getRecentsContainerInterface(): BaseContainerInterface<*, *>? {
- return OverviewComponentObserver.INSTANCE.get(context).containerInterface
+ return deviceState.systemUiStateFlags and KEYGUARD_SHOWING_SYSUI_FLAGS != 0L
}
/**
diff --git a/quickstep/src/com/android/quickstep/util/TISBindHelper.java b/quickstep/src/com/android/quickstep/util/TISBindHelper.java
index 027dc08..3716efa 100644
--- a/quickstep/src/com/android/quickstep/util/TISBindHelper.java
+++ b/quickstep/src/com/android/quickstep/util/TISBindHelper.java
@@ -28,8 +28,8 @@
import com.android.launcher3.taskbar.TaskbarManager;
import com.android.quickstep.OverviewCommandHelper;
+import com.android.quickstep.TISBinder;
import com.android.quickstep.TouchInteractionService;
-import com.android.quickstep.TouchInteractionService.TISBinder;
import java.util.ArrayList;
import java.util.function.Consumer;
@@ -109,15 +109,6 @@
return mBinder == null ? null : mBinder.getTaskbarManager();
}
- /**
- * Sets flag whether a predictive back-to-home animation is in progress
- */
- public void setPredictiveBackToHomeInProgress(boolean isInProgress) {
- if (mBinder != null) {
- mBinder.setPredictiveBackToHomeInProgress(isInProgress);
- }
- }
-
@Nullable
public OverviewCommandHelper getOverviewCommandHelper() {
return mBinder == null ? null : mBinder.getOverviewCommandHelper();
diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarStashControllerTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarStashControllerTest.kt
index 021e1e4..8395d79 100644
--- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarStashControllerTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarStashControllerTest.kt
@@ -50,8 +50,11 @@
import com.android.launcher3.taskbar.rules.TaskbarUnitTestRule.InjectController
import com.android.launcher3.taskbar.rules.TaskbarUnitTestRule.UserSetupMode
import com.android.launcher3.taskbar.rules.TaskbarWindowSandboxContext
+import com.android.launcher3.util.Executors.MAIN_EXECUTOR
import com.android.launcher3.util.LauncherMultivalentJUnit
import com.android.launcher3.util.LauncherMultivalentJUnit.EmulatedDevices
+import com.android.launcher3.util.TestUtil
+import com.android.quickstep.RecentsAnimationDeviceState
import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BUBBLES_EXPANDED
import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_VISIBLE
import com.android.wm.shell.Flags.FLAG_ENABLE_BUBBLE_BAR
@@ -60,6 +63,8 @@
import org.junit.After
import org.junit.Rule
import org.junit.Test
+import org.junit.rules.TestWatcher
+import org.junit.runner.Description
import org.junit.runner.RunWith
@RunWith(LauncherMultivalentJUnit::class)
@@ -68,7 +73,16 @@
class TaskbarStashControllerTest {
@get:Rule(order = 0) val setFlagsRule = SetFlagsRule()
@get:Rule(order = 1) val context = TaskbarWindowSandboxContext.create()
- @get:Rule(order = 2) val taskbarModeRule = TaskbarModeRule(context)
+ @get:Rule(order = 2)
+ val initSingleton =
+ object : TestWatcher() {
+ override fun starting(description: Description?) {
+ TestUtil.runOnExecutorSync(MAIN_EXECUTOR) {
+ RecentsAnimationDeviceState.INSTANCE[context].systemUiStateFlags = 0
+ }
+ }
+ }
+ @get:Rule(order = 3) val taskbarModeRule = TaskbarModeRule(context)
@get:Rule(order = 4) val animatorTestRule = AnimatorTestRule(this)
@get:Rule(order = 5) val taskbarUnitTestRule = TaskbarUnitTestRule(this, context)
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/RecentsAnimationDeviceStateTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/RecentsAnimationDeviceStateTest.kt
index b652ee8..63115bf 100644
--- a/quickstep/tests/multivalentTests/src/com/android/quickstep/RecentsAnimationDeviceStateTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/RecentsAnimationDeviceStateTest.kt
@@ -150,7 +150,7 @@
allSysUiStates().forEach { state ->
val canStartGesture = !disablingStates.contains(state)
- underTest.setSystemUiFlags(state)
+ underTest.systemUiStateFlags = state
assertThat(underTest.canStartTrackpadGesture()).isEqualTo(canStartGesture)
}
}
@@ -166,7 +166,7 @@
)
stateToExpectedResult.forEach { (state, allowed) ->
- underTest.setSystemUiFlags(state)
+ underTest.systemUiStateFlags = state
assertThat(underTest.canStartTrackpadGesture()).isEqualTo(allowed)
}
}
@@ -177,7 +177,7 @@
allSysUiStates().forEach { state ->
val canStartGesture = !disablingStates.contains(state)
- underTest.setSystemUiFlags(state)
+ underTest.systemUiStateFlags = state
assertThat(underTest.canStartSystemGesture()).isEqualTo(canStartGesture)
}
}
@@ -197,7 +197,7 @@
)
stateToExpectedResult.forEach { (state, gestureAllowed) ->
- underTest.setSystemUiFlags(state)
+ underTest.systemUiStateFlags = state
assertThat(underTest.canStartSystemGesture()).isEqualTo(gestureAllowed)
}
}
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/TaskAnimationManagerTest.java b/quickstep/tests/multivalentTests/src/com/android/quickstep/TaskAnimationManagerTest.java
index 6e9885a..b730f5b 100644
--- a/quickstep/tests/multivalentTests/src/com/android/quickstep/TaskAnimationManagerTest.java
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/TaskAnimationManagerTest.java
@@ -54,12 +54,7 @@
public void setUp() {
MockitoAnnotations.initMocks(this);
mTaskAnimationManager = new TaskAnimationManager(mContext,
- RecentsAnimationDeviceState.INSTANCE.get(mContext)) {
- @Override
- SystemUiProxy getSystemUiProxy() {
- return mSystemUiProxy;
- }
- };
+ RecentsAnimationDeviceState.INSTANCE.get(mContext), mSystemUiProxy);
}
@Test
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/util/ContextualSearchInvokerTest.java b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/ContextualSearchInvokerTest.java
index 61971b1..4e49aec 100644
--- a/quickstep/tests/multivalentTests/src/com/android/quickstep/util/ContextualSearchInvokerTest.java
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/ContextualSearchInvokerTest.java
@@ -50,7 +50,8 @@
import com.android.launcher3.logging.StatsLogManager;
import com.android.quickstep.BaseContainerInterface;
import com.android.quickstep.DeviceConfigWrapper;
-import com.android.quickstep.SystemUiProxy;
+import com.android.quickstep.OverviewComponentObserver;
+import com.android.quickstep.RecentsAnimationDeviceState;
import com.android.quickstep.TopTaskTracker;
import com.android.quickstep.orientation.RecentsPagedOrientationHandler;
import com.android.quickstep.views.RecentsView;
@@ -75,7 +76,7 @@
private @Mock PackageManager mMockPackageManager;
private @Mock ContextualSearchStateManager mMockStateManager;
private @Mock TopTaskTracker mMockTopTaskTracker;
- private @Mock SystemUiProxy mMockSystemUiProxy;
+ private @Mock RecentsAnimationDeviceState mMockDeviceState;
private @Mock StatsLogManager mMockStatsLogManager;
private @Mock StatsLogManager.StatsLogger mMockStatsLogger;
private @Mock ContextualSearchHapticManager mMockContextualSearchHapticManager;
@@ -84,6 +85,7 @@
private @Mock RecentsViewContainer mMockRecentsViewContainer;
private @Mock RecentsView mMockRecentsView;
private @Mock RecentsPagedOrientationHandler mMockOrientationHandler;
+ private @Mock OverviewComponentObserver mMockOverviewComponentObserver;
private ContextualSearchInvoker mContextualSearchInvoker;
@Before
@@ -92,20 +94,21 @@
when(mMockPackageManager.hasSystemFeature(FEATURE_CONTEXTUAL_SEARCH)).thenReturn(true);
Context context = spy(getApplicationContext());
doReturn(mMockPackageManager).when(context).getPackageManager();
- when(mMockSystemUiProxy.getLastSystemUiStateFlags()).thenReturn(0L);
+ when(mMockDeviceState.getSystemUiStateFlags()).thenReturn(0L);
when(mMockTopTaskTracker.getRunningSplitTaskIds()).thenReturn(new int[]{});
when(mMockStateManager.isContextualSearchIntentAvailable()).thenReturn(true);
when(mMockStateManager.isContextualSearchSettingEnabled()).thenReturn(true);
when(mMockStatsLogManager.logger()).thenReturn(mMockStatsLogger);
+
+ doReturn(mMockContainerInterface).when(mMockOverviewComponentObserver)
+ .getContainerInterface();
when(mMockContainerInterface.getCreatedContainer()).thenReturn(mMockRecentsViewContainer);
when(mMockRecentsViewContainer.getOverviewPanel()).thenReturn(mMockRecentsView);
- mContextualSearchInvoker = spy(new ContextualSearchInvoker(context, mMockStateManager,
- mMockTopTaskTracker, mMockSystemUiProxy, mMockStatsLogManager,
- mMockContextualSearchHapticManager, mMockContextualSearchManager
- ));
- doReturn(mMockContainerInterface).when(mContextualSearchInvoker)
- .getRecentsContainerInterface();
+ mContextualSearchInvoker = new ContextualSearchInvoker(context, mMockStateManager,
+ mMockTopTaskTracker, mMockDeviceState, mMockStatsLogManager,
+ mMockContextualSearchHapticManager, mMockOverviewComponentObserver,
+ mMockContextualSearchManager);
}
@Test
@@ -148,7 +151,7 @@
@Test
public void runContextualSearchInvocationChecksAndLogFailures_notificationShadeIsShowing() {
- when(mMockSystemUiProxy.getLastSystemUiStateFlags()).thenReturn(SHADE_EXPANDED_SYSUI_FLAGS);
+ when(mMockDeviceState.getSystemUiStateFlags()).thenReturn(SHADE_EXPANDED_SYSUI_FLAGS);
assertFalse("Expected invocation checks to fail when notification shade is showing",
mContextualSearchInvoker.runContextualSearchInvocationChecksAndLogFailures());
@@ -158,7 +161,7 @@
@Test
public void runContextualSearchInvocationChecksAndLogFailures_keyguardIsShowing() {
- when(mMockSystemUiProxy.getLastSystemUiStateFlags()).thenReturn(
+ when(mMockDeviceState.getSystemUiStateFlags()).thenReturn(
KEYGUARD_SHOWING_SYSUI_FLAGS);
assertFalse("Expected invocation checks to fail when keyguard is showing",
diff --git a/quickstep/tests/src/com/android/quickstep/InputConsumerUtilsTest.java b/quickstep/tests/src/com/android/quickstep/InputConsumerUtilsTest.java
index e2ca91a..a164dad 100644
--- a/quickstep/tests/src/com/android/quickstep/InputConsumerUtilsTest.java
+++ b/quickstep/tests/src/com/android/quickstep/InputConsumerUtilsTest.java
@@ -89,7 +89,6 @@
import org.mockito.junit.MockitoRule;
import java.util.Optional;
-import java.util.function.Function;
import javax.inject.Provider;
@@ -104,7 +103,6 @@
private TaskAnimationManager mTaskAnimationManager;
private InputChannelCompat.InputEventReceiver mInputEventReceiver;
@Nullable private ResetGestureInputConsumer mResetGestureInputConsumer;
- @NonNull private Function<GestureState, AnimatedFloat> mSwipeUpProxyProvider = (state) -> null;
@NonNull @Mock private TaskbarActivityContext mTaskbarActivityContext;
@NonNull @Mock private OverviewComponentObserver mOverviewComponentObserver;
@@ -446,7 +444,7 @@
@Test
public void testNewConsumer_withSwipeUpProxyProvider_returnsProgressDelegateInputConsumer() {
- mSwipeUpProxyProvider = (state) -> new AnimatedFloat();
+ doReturn(new AnimatedFloat()).when(mDeviceState).getSwipeUpProxy(any());
assertCorrectInputConsumer(
this::createInputConsumer,
@@ -496,7 +494,6 @@
otherActivityInputConsumer -> {},
mInputEventReceiver,
mTaskbarManager,
- mSwipeUpProxyProvider,
mOverviewCommandHelper,
event);
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 315301a..04e699c 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -349,8 +349,7 @@
private final int[] mTmpAddItemCellCoordinates = new int[2];
- @Thunk
- Hotseat mHotseat;
+ protected Hotseat mHotseat;
private DropTargetBar mDropTargetBar;
@@ -807,10 +806,6 @@
);
}
- public void onAssistantVisibilityChanged(float visibility) {
- mHotseat.getQsb().setAlpha(1f - visibility);
- }
-
/**
* Returns {@code true} if a new DeviceProfile is initialized, and {@code false} otherwise.
*/