diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java index 5155ffcdd3..4a8a3de10e 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java @@ -705,13 +705,14 @@ public class TaskbarManager { } } - public void onSystemUiFlagsChanged(@SystemUiStateFlags long systemUiStateFlags) { + /** Called when the SysUI flags for a given display change. */ + public void onSystemUiFlagsChanged(@SystemUiStateFlags long systemUiStateFlags, int displayId) { if (DEBUG) { Log.d(TAG, "SysUI flags changed: " + formatFlagChange(systemUiStateFlags, mSharedState.sysuiStateFlags, QuickStepContract::getSystemUiStateString)); } mSharedState.sysuiStateFlags = systemUiStateFlags; - TaskbarActivityContext taskbar = getTaskbarForDisplay(getDefaultDisplayId()); + TaskbarActivityContext taskbar = getTaskbarForDisplay(displayId); if (taskbar != null) { taskbar.updateSysuiStateFlags(systemUiStateFlags, false /* fromInit */); } diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java index 090ccdc869..74f24ee3e7 100644 --- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java +++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java @@ -88,6 +88,9 @@ import com.android.systemui.shared.system.TaskStackChangeListener; import com.android.systemui.shared.system.TaskStackChangeListeners; import java.io.PrintWriter; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import javax.inject.Inject; @@ -119,6 +122,7 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener, E InputMethodService.canImeRenderGesturalNavButtons(); private @SystemUiStateFlags long mSystemUiStateFlags = QuickStepContract.SYSUI_STATE_AWAKE; + private final Map mSysUIStateFlagsPerDisplay = new ConcurrentHashMap<>(); private NavigationMode mMode = THREE_BUTTONS; private NavBarPosition mNavBarPosition; @@ -353,21 +357,50 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener, E } /** - * Updates the system ui state flags from SystemUI. + * Updates the system ui state flags from SystemUI for a specific display. + * + * @param stateFlags the current {@link SystemUiStateFlags} for the display. + * @param displayId the display's ID. */ - public void setSystemUiFlags(@SystemUiStateFlags long stateFlags) { - mSystemUiStateFlags = stateFlags; + public void setSysUIStateFlagsForDisplay(@SystemUiStateFlags long stateFlags, + int displayId) { + mSysUIStateFlagsPerDisplay.put(displayId, stateFlags); } /** - * @return the system ui state flags. + * Clears the system ui state flags for a specific display. This is called when the display is + * destroyed. + * + * @param displayId the display's ID. + */ + public void clearSysUIStateFlagsForDisplay(int displayId) { + mSysUIStateFlagsPerDisplay.remove(displayId); + } + + /** + * @return the system ui state flags for the default display. */ // TODO(141886704): See if we can remove this @SystemUiStateFlags - public long getSystemUiStateFlags() { - return mSystemUiStateFlags; + public long getSysuiStateFlag() { + return getSystemUiStateFlags(DEFAULT_DISPLAY); } + /** + * @return the system ui state flags for a given display ID. + */ + @SystemUiStateFlags + public long getSystemUiStateFlags(int displayId) { + return mSysUIStateFlagsPerDisplay.getOrDefault(displayId, + QuickStepContract.SYSUI_STATE_AWAKE); + } + + /** + * @return the display ids that have sysui state. + */ + public Set getDisplaysWithSysUIState() { + return mSysUIStateFlagsPerDisplay.keySet(); + } /** * Sets the flag that indicates whether a predictive back-to-home animation is in progress */ @@ -386,8 +419,8 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener, E * @return whether SystemUI is in a state where we can start a system gesture. */ public boolean canStartSystemGesture() { - boolean canStartWithNavHidden = (mSystemUiStateFlags & SYSUI_STATE_NAV_BAR_HIDDEN) == 0 - || (mSystemUiStateFlags & SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY) != 0 + boolean canStartWithNavHidden = (getSysuiStateFlag() & SYSUI_STATE_NAV_BAR_HIDDEN) == 0 + || (getSysuiStateFlag() & SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY) != 0 || mRotationTouchHelper.isTaskListFrozen(); return canStartWithNavHidden && canStartAnyGesture(); } @@ -399,7 +432,7 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener, E */ public boolean canStartTrackpadGesture() { boolean trackpadGesturesEnabled = - (mSystemUiStateFlags & SYSUI_STATE_TOUCHPAD_GESTURES_DISABLED) == 0; + (getSysuiStateFlag() & SYSUI_STATE_TOUCHPAD_GESTURES_DISABLED) == 0; return trackpadGesturesEnabled && canStartAnyGesture(); } @@ -407,8 +440,8 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener, E * Common logic to determine if either trackpad or finger gesture can be started */ private boolean canStartAnyGesture() { - boolean homeOrOverviewEnabled = (mSystemUiStateFlags & SYSUI_STATE_HOME_DISABLED) == 0 - || (mSystemUiStateFlags & SYSUI_STATE_OVERVIEW_DISABLED) == 0; + boolean homeOrOverviewEnabled = (getSysuiStateFlag() & SYSUI_STATE_HOME_DISABLED) == 0 + || (getSysuiStateFlag() & SYSUI_STATE_OVERVIEW_DISABLED) == 0; long gestureDisablingStates = SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED | SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING | SYSUI_STATE_QUICK_SETTINGS_EXPANDED @@ -416,7 +449,7 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener, E | SYSUI_STATE_DEVICE_DREAMING | SYSUI_STATE_DISABLE_GESTURE_SPLIT_INVOCATION | SYSUI_STATE_DISABLE_GESTURE_PIP_ANIMATING; - return (gestureDisablingStates & mSystemUiStateFlags) == 0 && homeOrOverviewEnabled; + return (gestureDisablingStates & getSysuiStateFlag()) == 0 && homeOrOverviewEnabled; } /** @@ -424,35 +457,35 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener, E * (like camera or maps) */ public boolean isKeyguardShowingOccluded() { - return (mSystemUiStateFlags & SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED) != 0; + return (getSysuiStateFlag() & SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED) != 0; } /** * @return whether screen pinning is enabled and active */ public boolean isScreenPinningActive() { - return (mSystemUiStateFlags & SYSUI_STATE_SCREEN_PINNING) != 0; + return (getSysuiStateFlag() & SYSUI_STATE_SCREEN_PINNING) != 0; } /** * @return whether assistant gesture is constraint */ public boolean isAssistantGestureIsConstrained() { - return (mSystemUiStateFlags & SYSUI_STATE_ASSIST_GESTURE_CONSTRAINED) != 0; + return (getSysuiStateFlag() & SYSUI_STATE_ASSIST_GESTURE_CONSTRAINED) != 0; } /** * @return whether the bubble stack is expanded */ public boolean isBubblesExpanded() { - return (mSystemUiStateFlags & SYSUI_STATE_BUBBLES_EXPANDED) != 0; + return (getSysuiStateFlag() & SYSUI_STATE_BUBBLES_EXPANDED) != 0; } /** * @return whether the global actions dialog is showing */ public boolean isSystemUiDialogShowing() { - return (mSystemUiStateFlags & SYSUI_STATE_DIALOG_SHOWING) != 0; + return (getSysuiStateFlag() & SYSUI_STATE_DIALOG_SHOWING) != 0; } /** @@ -466,35 +499,35 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener, E * @return whether the accessibility menu is available. */ public boolean isAccessibilityMenuAvailable() { - return (mSystemUiStateFlags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0; + return (getSysuiStateFlag() & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0; } /** * @return whether the accessibility menu shortcut is available. */ public boolean isAccessibilityMenuShortcutAvailable() { - return (mSystemUiStateFlags & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE) != 0; + return (getSysuiStateFlag() & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE) != 0; } /** * @return whether home is disabled (either by SUW/SysUI/device policy) */ public boolean isHomeDisabled() { - return (mSystemUiStateFlags & SYSUI_STATE_HOME_DISABLED) != 0; + return (getSysuiStateFlag() & SYSUI_STATE_HOME_DISABLED) != 0; } /** * @return whether overview is disabled (either by SUW/SysUI/device policy) */ public boolean isOverviewDisabled() { - return (mSystemUiStateFlags & SYSUI_STATE_OVERVIEW_DISABLED) != 0; + return (getSysuiStateFlag() & SYSUI_STATE_OVERVIEW_DISABLED) != 0; } /** * @return whether one-handed mode is enabled and active */ public boolean isOneHandedModeActive() { - return (mSystemUiStateFlags & SYSUI_STATE_ONE_HANDED_ACTIVE) != 0; + return (getSysuiStateFlag() & SYSUI_STATE_ONE_HANDED_ACTIVE) != 0; } /** @@ -557,7 +590,7 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener, E */ public boolean canTriggerAssistantAction(MotionEvent ev) { return mAssistantAvailable - && !QuickStepContract.isAssistantGestureDisabled(mSystemUiStateFlags) + && !QuickStepContract.isAssistantGestureDisabled(getSysuiStateFlag()) && mRotationTouchHelper.touchInAssistantRegion(ev) && !isTrackpadScroll(ev) && !isLockToAppActive(); @@ -597,7 +630,7 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener, E /** Returns whether IME is rendering nav buttons, and IME is currently showing. */ public boolean isImeRenderingNavButtons() { return mCanImeRenderGesturalNavButtons && mMode == NO_BUTTON - && ((mSystemUiStateFlags & SYSUI_STATE_IME_VISIBLE) != 0); + && ((getSysuiStateFlag() & SYSUI_STATE_IME_VISIBLE) != 0); } /** @@ -629,24 +662,37 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener, E return touchSlop * touchSlop; } + /** Returns a string representation of the system ui state flags for the default display. */ public String getSystemUiStateString() { - return QuickStepContract.getSystemUiStateString(mSystemUiStateFlags); + return getSystemUiStateString(getSysuiStateFlag()); + } + + /** Returns a string representation of the system ui state flags. */ + public String getSystemUiStateString(long flags) { + return QuickStepContract.getSystemUiStateString(flags); } public void dump(PrintWriter pw) { pw.println("DeviceState:"); pw.println(" canStartSystemGesture=" + canStartSystemGesture()); - pw.println(" systemUiFlags=" + mSystemUiStateFlags); + pw.println(" systemUiFlagsForDefaultDisplay=" + getSysuiStateFlag()); pw.println(" systemUiFlagsDesc=" + getSystemUiStateString()); pw.println(" assistantAvailable=" + mAssistantAvailable); pw.println(" assistantDisabled=" - + QuickStepContract.isAssistantGestureDisabled(mSystemUiStateFlags)); + + QuickStepContract.isAssistantGestureDisabled(getSysuiStateFlag())); pw.println(" isOneHandedModeEnabled=" + mIsOneHandedModeEnabled); pw.println(" isSwipeToNotificationEnabled=" + mIsSwipeToNotificationEnabled); pw.println(" deferredGestureRegion=" + mDeferredGestureRegion.getBounds()); pw.println(" exclusionRegion=" + mExclusionRegion.getBounds()); pw.println(" pipIsActive=" + mPipIsActive); pw.println(" predictiveBackToHomeInProgress=" + mIsPredictiveBackToHomeInProgress); + for (int displayId : mSysUIStateFlagsPerDisplay.keySet()) { + pw.println(" systemUiFlagsForDisplay" + displayId + "=" + getSystemUiStateFlags( + displayId)); + pw.println(" systemUiFlagsForDisplay" + displayId + "Desc=" + getSystemUiStateString( + getSystemUiStateFlags(displayId))); + } + pw.println(" RotationTouchHelper:"); mRotationTouchHelper.dump(pw); } } diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java index ba4c65a293..5ca9319772 100644 --- a/quickstep/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java @@ -53,6 +53,7 @@ import android.os.RemoteException; import android.os.SystemClock; import android.util.Log; import android.view.Choreographer; +import android.view.Display; import android.view.InputDevice; import android.view.InputEvent; import android.view.MotionEvent; @@ -274,11 +275,12 @@ public class TouchInteractionService extends Service { } @BinderThread - public void onSystemUiStateChanged(@SystemUiStateFlags long stateFlags) { + public void onSystemUiStateChanged(@SystemUiStateFlags long stateFlags, int displayId) { MAIN_EXECUTOR.execute(() -> executeForTouchInteractionService(tis -> { - long lastFlags = tis.mDeviceState.getSystemUiStateFlags(); - tis.mDeviceState.setSystemUiFlags(stateFlags); - tis.onSystemUiFlagsChanged(lastFlags); + // Last flags is only used for the default display case. + long lastFlags = tis.mDeviceState.getSysuiStateFlag(); + tis.mDeviceState.setSysUIStateFlagsForDisplay(stateFlags, displayId); + tis.onSystemUiFlagsChanged(lastFlags, displayId); })); } @@ -312,6 +314,9 @@ public class TouchInteractionService extends Service { public void onDisplayRemoved(int displayId) { executeForTaskbarManager(taskbarManager -> taskbarManager.onDisplayRemoved(displayId)); + executeForTouchInteractionService(tis -> { + tis.mDeviceState.clearSysUIStateFlagsForDisplay(displayId); + }); } @BinderThread @@ -649,7 +654,9 @@ public class TouchInteractionService extends Service { mResetGestureInputConsumer = new ResetGestureInputConsumer( mTaskAnimationManager, mTaskbarManager::getCurrentActivityContext); mInputConsumer.registerInputConsumer(); - onSystemUiFlagsChanged(mDeviceState.getSystemUiStateFlags()); + for (int displayId : mDeviceState.getDisplaysWithSysUIState()) { + onSystemUiFlagsChanged(mDeviceState.getSystemUiStateFlags(displayId), displayId); + } onAssistantVisibilityChanged(); // Initialize the task tracker @@ -711,13 +718,19 @@ public class TouchInteractionService extends Service { } @UiThread - private void onSystemUiFlagsChanged(@SystemUiStateFlags long lastSysUIFlags) { + private void onSystemUiFlagsChanged(@SystemUiStateFlags long lastSysUIFlags, int displayId) { 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); + long systemUiStateFlags = mDeviceState.getSystemUiStateFlags(displayId); + mTaskbarManager.onSystemUiFlagsChanged(systemUiStateFlags, displayId); + if (displayId == Display.DEFAULT_DISPLAY) { + // The following don't care about non-default displays, at least for now. If they + // ever will, they should be taken care of. + SystemUiProxy.INSTANCE.get(this).setLastSystemUiStateFlags(systemUiStateFlags); + mOverviewComponentObserver.setHomeDisabled(mDeviceState.isHomeDisabled()); + // TODO b/399371607 - Propagate to taskAnimationManager once overview is multi + // display. + mTaskAnimationManager.onSystemUiFlagsChanged(lastSysUIFlags, systemUiStateFlags); + } } } diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/RecentsAnimationDeviceStateTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/RecentsAnimationDeviceStateTest.kt index b652ee8df4..a7370b02e9 100644 --- a/quickstep/tests/multivalentTests/src/com/android/quickstep/RecentsAnimationDeviceStateTest.kt +++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/RecentsAnimationDeviceStateTest.kt @@ -1,5 +1,6 @@ package com.android.quickstep +import android.view.Display import androidx.test.annotation.UiThreadTest import androidx.test.filters.SmallTest import com.android.launcher3.dagger.LauncherComponentProvider @@ -13,6 +14,7 @@ import com.android.launcher3.util.LauncherMultivalentJUnit import com.android.launcher3.util.NavigationMode import com.android.launcher3.util.SandboxApplication import com.android.quickstep.util.GestureExclusionManager +import com.android.systemui.shared.system.QuickStepContract import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_DEVICE_DREAMING import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_DISABLE_GESTURE_SPLIT_INVOCATION @@ -150,7 +152,7 @@ class RecentsAnimationDeviceStateTest { allSysUiStates().forEach { state -> val canStartGesture = !disablingStates.contains(state) - underTest.setSystemUiFlags(state) + underTest.setSysUIStateFlagsForDisplay(state, Display.DEFAULT_DISPLAY) assertThat(underTest.canStartTrackpadGesture()).isEqualTo(canStartGesture) } } @@ -166,7 +168,7 @@ class RecentsAnimationDeviceStateTest { ) stateToExpectedResult.forEach { (state, allowed) -> - underTest.setSystemUiFlags(state) + underTest.setSysUIStateFlagsForDisplay(state, Display.DEFAULT_DISPLAY) assertThat(underTest.canStartTrackpadGesture()).isEqualTo(allowed) } } @@ -177,7 +179,7 @@ class RecentsAnimationDeviceStateTest { allSysUiStates().forEach { state -> val canStartGesture = !disablingStates.contains(state) - underTest.setSystemUiFlags(state) + underTest.setSysUIStateFlagsForDisplay(state, Display.DEFAULT_DISPLAY) assertThat(underTest.canStartSystemGesture()).isEqualTo(canStartGesture) } } @@ -197,11 +199,42 @@ class RecentsAnimationDeviceStateTest { ) stateToExpectedResult.forEach { (state, gestureAllowed) -> - underTest.setSystemUiFlags(state) + underTest.setSysUIStateFlagsForDisplay(state, Display.DEFAULT_DISPLAY) assertThat(underTest.canStartSystemGesture()).isEqualTo(gestureAllowed) } } + @Test + fun getSystemUiStateFlags_defaultAwake() { + val NOT_EXISTENT_DISPLAY = 2 + assertThat(underTest.getSystemUiStateFlags(NOT_EXISTENT_DISPLAY)) + .isEqualTo(QuickStepContract.SYSUI_STATE_AWAKE) + } + + @Test + fun clearSysUIStateFlagsForDisplay_displayNotReturnedAnymore() { + underTest.setSysUIStateFlagsForDisplay(1, /* displayId= */ 1) + + assertThat(underTest.displaysWithSysUIState).contains(1) + assertThat(underTest.getSystemUiStateFlags(1)).isEqualTo(1) + + underTest.clearSysUIStateFlagsForDisplay(1) + + assertThat(underTest.displaysWithSysUIState).doesNotContain(1) + assertThat(underTest.getSystemUiStateFlags(1)) + .isEqualTo(QuickStepContract.SYSUI_STATE_AWAKE) + } + + @Test + fun setSysUIStateFlagsForDisplay_setsCorrectly() { + underTest.setSysUIStateFlagsForDisplay(1, /* displayId= */ 1) + underTest.setSysUIStateFlagsForDisplay(2, /* displayId= */ 2) + + assertThat(underTest.getSystemUiStateFlags(1)).isEqualTo(1) + assertThat(underTest.getSystemUiStateFlags(2)).isEqualTo(2) + assertThat(underTest.displaysWithSysUIState).containsAtLeast(1, 2) + } + private fun allSysUiStates(): List { // SYSUI_STATES_* are binary flags return (0..SYSUI_STATES_COUNT).map { 1L shl it }