diff options
6 files changed, 133 insertions, 58 deletions
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java index 5b27c40740da..53fab69bd3b8 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java @@ -96,9 +96,9 @@ public class RotationButtonController { private boolean mHoveringRotationSuggestion; private final AccessibilityManager mAccessibilityManager; private final TaskStackListenerImpl mTaskStackListener; - private Consumer<Integer> mRotWatcherListener; private boolean mListenersRegistered = false; + private boolean mRotationWatcherRegistered = false; private boolean mIsNavigationBarShowing; @SuppressLint("InlinedApi") private @WindowInsetsController.Behavior @@ -140,22 +140,7 @@ public class RotationButtonController { // We need this to be scheduled as early as possible to beat the redrawing of // window in response to the orientation change. mMainThreadHandler.postAtFrontOfQueue(() -> { - // If the screen rotation changes while locked, potentially update lock to flow with - // new screen rotation and hide any showing suggestions. - boolean rotationLocked = isRotationLocked(); - // The isVisible check makes the rotation button disappear when we are not locked - // (e.g. for tabletop auto-rotate). - if (rotationLocked || mRotationButton.isVisible()) { - // Do not allow a change in rotation to set user rotation when docked. - if (shouldOverrideUserLockPrefs(rotation) && rotationLocked && !mDocked) { - setRotationLockedAtAngle(rotation); - } - setRotateSuggestionButtonState(false /* visible */, true /* forced */); - } - - if (mRotWatcherListener != null) { - mRotWatcherListener.accept(rotation); - } + onRotationWatcherChanged(rotation); }); } }; @@ -206,8 +191,11 @@ public class RotationButtonController { return mContext; } + /** + * Called during Taskbar initialization. + */ public void init() { - registerListeners(); + registerListeners(true /* registerRotationWatcher */); if (mContext.getDisplay().getDisplayId() != DEFAULT_DISPLAY) { // Currently there is no accelerometer sensor on non-default display, disable fixed // rotation for non-default display @@ -215,11 +203,14 @@ public class RotationButtonController { } } + /** + * Called during Taskbar uninitialization. + */ public void onDestroy() { unregisterListeners(); } - public void registerListeners() { + public void registerListeners(boolean registerRotationWatcher) { if (mListenersRegistered || getContext().getPackageManager().hasSystemFeature(FEATURE_PC)) { return; } @@ -229,15 +220,18 @@ public class RotationButtonController { updateDockedState(mContext.registerReceiver(mDockedReceiver, new IntentFilter(Intent.ACTION_DOCK_EVENT))); - try { - WindowManagerGlobal.getWindowManagerService() - .watchRotation(mRotationWatcher, DEFAULT_DISPLAY); - } catch (IllegalArgumentException e) { - mListenersRegistered = false; - Log.w(TAG, "RegisterListeners for the display failed"); - } catch (RemoteException e) { - Log.e(TAG, "RegisterListeners caught a RemoteException", e); - return; + if (registerRotationWatcher) { + try { + WindowManagerGlobal.getWindowManagerService() + .watchRotation(mRotationWatcher, DEFAULT_DISPLAY); + mRotationWatcherRegistered = true; + } catch (IllegalArgumentException e) { + mListenersRegistered = false; + Log.w(TAG, "RegisterListeners for the display failed", e); + } catch (RemoteException e) { + Log.e(TAG, "RegisterListeners caught a RemoteException", e); + return; + } } TaskStackChangeListeners.getInstance().registerTaskStackListener(mTaskStackListener); @@ -251,20 +245,19 @@ public class RotationButtonController { mListenersRegistered = false; mContext.unregisterReceiver(mDockedReceiver); - try { - WindowManagerGlobal.getWindowManagerService().removeRotationWatcher(mRotationWatcher); - } catch (RemoteException e) { - Log.e(TAG, "UnregisterListeners caught a RemoteException", e); - return; + if (mRotationWatcherRegistered) { + try { + WindowManagerGlobal.getWindowManagerService().removeRotationWatcher( + mRotationWatcher); + } catch (RemoteException e) { + Log.e(TAG, "UnregisterListeners caught a RemoteException", e); + return; + } } TaskStackChangeListeners.getInstance().unregisterTaskStackListener(mTaskStackListener); } - public void setRotationCallback(Consumer<Integer> watcher) { - mRotWatcherListener = watcher; - } - public void setRotationLockedAtAngle(int rotationSuggestion) { RotationPolicy.setRotationLockAtAngle(mContext, /* enabled= */ isRotationLocked(), /* rotation= */ rotationSuggestion); @@ -427,6 +420,30 @@ public class RotationButtonController { } } + /** + * Called when the rotation watcher rotation changes, either from the watcher registered + * internally in this class, or a signal propagated from NavBarHelper. + */ + public void onRotationWatcherChanged(int rotation) { + if (!mListenersRegistered) { + // Ignore if not registered + return; + } + + // If the screen rotation changes while locked, potentially update lock to flow with + // new screen rotation and hide any showing suggestions. + boolean rotationLocked = isRotationLocked(); + // The isVisible check makes the rotation button disappear when we are not locked + // (e.g. for tabletop auto-rotate). + if (rotationLocked || mRotationButton.isVisible()) { + // Do not allow a change in rotation to set user rotation when docked. + if (shouldOverrideUserLockPrefs(rotation) && rotationLocked && !mDocked) { + setRotationLockedAtAngle(rotation); + } + setRotateSuggestionButtonState(false /* visible */, true /* forced */); + } + } + public void onDisable2FlagChanged(int state2) { final boolean rotateSuggestionsDisabled = hasDisable2RotateSuggestionFlag(state2); if (rotateSuggestionsDisabled) onRotationSuggestionsDisabled(); diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java index 731f712c57c8..24098122aec6 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java @@ -41,11 +41,16 @@ import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.Looper; +import android.os.RemoteException; import android.os.UserHandle; import android.provider.Settings; import android.provider.Settings.Secure; +import android.util.Log; +import android.view.IRotationWatcher; +import android.view.IWindowManager; import android.view.View; import android.view.WindowInsets; +import android.view.WindowManagerGlobal; import android.view.accessibility.AccessibilityManager; import androidx.annotation.NonNull; @@ -58,6 +63,7 @@ import com.android.systemui.assist.AssistManager; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dump.DumpManager; import com.android.systemui.recents.OverviewProxyService; +import com.android.systemui.settings.DisplayTracker; import com.android.systemui.settings.UserTracker; import com.android.systemui.shared.system.QuickStepContract; import com.android.systemui.statusbar.CommandQueue; @@ -90,6 +96,7 @@ public final class NavBarHelper implements AccessibilityButtonTargetsObserver.TargetsChangedListener, OverviewProxyService.OverviewProxyListener, NavigationModeController.ModeChangedListener, Dumpable, CommandQueue.Callbacks { + private static final String TAG = NavBarHelper.class.getSimpleName(); private final Handler mHandler = new Handler(Looper.getMainLooper()); private final AccessibilityManager mAccessibilityManager; private final Lazy<AssistManager> mAssistManagerLazy; @@ -103,11 +110,14 @@ public final class NavBarHelper implements private final Context mContext; private final CommandQueue mCommandQueue; private final ContentResolver mContentResolver; + private final IWindowManager mWm; + private final int mDefaultDisplayId; private boolean mAssistantAvailable; private boolean mLongPressHomeEnabled; private boolean mAssistantTouchGestureEnabled; private int mNavBarMode; private int mA11yButtonState; + private int mRotationWatcherRotation; private boolean mTogglingNavbarTaskbar; // Attributes used in NavBarHelper.CurrentSysuiState @@ -122,6 +132,19 @@ public final class NavBarHelper implements } }; + // Listens for changes to display rotation + private final IRotationWatcher mRotationWatcher = new IRotationWatcher.Stub() { + @Override + public void onRotationChanged(final int rotation) { + // We need this to be scheduled as early as possible to beat the redrawing of + // window in response to the orientation change. + mHandler.postAtFrontOfQueue(() -> { + mRotationWatcherRotation = rotation; + dispatchRotationChanged(rotation); + }); + } + }; + /** * @param context This is not display specific, then again neither is any of the code in * this class. Once there's display specific code, we may want to create an @@ -137,7 +160,9 @@ public final class NavBarHelper implements Lazy<Optional<CentralSurfaces>> centralSurfacesOptionalLazy, KeyguardStateController keyguardStateController, NavigationModeController navigationModeController, + IWindowManager wm, UserTracker userTracker, + DisplayTracker displayTracker, DumpManager dumpManager, CommandQueue commandQueue) { mContext = context; @@ -151,6 +176,8 @@ public final class NavBarHelper implements mSystemActions = systemActions; mAccessibilityButtonModeObserver = accessibilityButtonModeObserver; mAccessibilityButtonTargetsObserver = accessibilityButtonTargetsObserver; + mWm = wm; + mDefaultDisplayId = displayTracker.getDefaultDisplayId(); mNavBarMode = navigationModeController.addListener(this); mCommandQueue.addCallback(this); @@ -185,6 +212,13 @@ public final class NavBarHelper implements mContentResolver.registerContentObserver( Settings.Secure.getUriFor(Settings.Secure.ASSIST_TOUCH_GESTURE_ENABLED), false, mAssistContentObserver, UserHandle.USER_ALL); + + // Setup display rotation watcher + try { + mWm.watchRotation(mRotationWatcher, mDefaultDisplayId); + } catch (Exception e) { + Log.w(TAG, "Failed to register rotation watcher", e); + } } /** @@ -198,6 +232,13 @@ public final class NavBarHelper implements // Clean up assistant listeners mContentResolver.unregisterContentObserver(mAssistContentObserver); + + // Clean up display rotation watcher + try { + mWm.removeRotationWatcher(mRotationWatcher); + } catch (Exception e) { + Log.w(TAG, "Failed to unregister rotation watcher", e); + } } /** @@ -217,6 +258,7 @@ public final class NavBarHelper implements listener.updateAccessibilityServicesState(); listener.updateAssistantAvailable(mAssistantAvailable, mLongPressHomeEnabled); } + listener.updateRotationWatcherState(mRotationWatcherRotation); } /** @@ -393,6 +435,12 @@ public final class NavBarHelper implements mWindowState = state; } + private void dispatchRotationChanged(int rotation) { + for (NavbarTaskbarStateUpdater listener : mStateListeners) { + listener.updateRotationWatcherState(rotation); + } + } + public CurrentSysuiState getCurrentSysuiState() { return new CurrentSysuiState(); } @@ -404,6 +452,7 @@ public final class NavBarHelper implements public interface NavbarTaskbarStateUpdater { void updateAccessibilityServicesState(); void updateAssistantAvailable(boolean available, boolean longPressHomeEnabled); + default void updateRotationWatcherState(int rotation) {} } /** Data class to help Taskbar/Navbar initiate state correctly when switching between the two.*/ diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java index 1c36e92cff00..db545099f8ac 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java @@ -350,6 +350,15 @@ public class NavigationBar extends ViewController<NavigationBarView> implements mLongPressHomeEnabled = longPressHomeEnabled; updateAssistantEntrypoints(available, longPressHomeEnabled); } + @Override + public void updateRotationWatcherState(int rotation) { + if (mIsOnDefaultDisplay && mView != null) { + mView.getRotationButtonController().onRotationWatcherChanged(rotation); + if (mView.needsReorient(rotation)) { + repositionNavigationBar(rotation); + } + } + } }; private final OverviewProxyListener mOverviewProxyListener = new OverviewProxyListener() { @@ -763,7 +772,6 @@ public class NavigationBar extends ViewController<NavigationBarView> implements if (mIsOnDefaultDisplay) { final RotationButtonController rotationButtonController = mView.getRotationButtonController(); - rotationButtonController.setRotationCallback(mRotationWatcher); // Reset user rotation pref to match that of the WindowManager if starting in locked // mode. This will automatically happen when switching from auto-rotate to locked mode. @@ -797,9 +805,6 @@ public class NavigationBar extends ViewController<NavigationBarView> implements @Override public void onViewDetached() { - final RotationButtonController rotationButtonController = - mView.getRotationButtonController(); - rotationButtonController.setRotationCallback(null); mView.setUpdateActiveTouchRegionsCallback(null); getBarTransitions().destroy(); mOverviewProxyService.removeCallback(mOverviewProxyListener); @@ -1701,12 +1706,6 @@ public class NavigationBar extends ViewController<NavigationBarView> implements return mNavBarMode == NAV_BAR_MODE_GESTURAL && mOrientationHandle != null; } - private final Consumer<Integer> mRotationWatcher = rotation -> { - if (mView != null && mView.needsReorient(rotation)) { - repositionNavigationBar(rotation); - } - }; - private final UserTracker.Callback mUserChangedCallback = new UserTracker.Callback() { @Override diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java index 63fb4996fbbf..47701afc387b 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java @@ -1099,7 +1099,7 @@ public class NavigationBarView extends FrameLayout { requestApplyInsets(); reorient(); if (mRotationButtonController != null) { - mRotationButtonController.registerListeners(); + mRotationButtonController.registerListeners(false /* registerRotationWatcher */); } updateNavButtonIcons(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java index fbe83af78080..1076f9f1a947 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java @@ -35,6 +35,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.ComponentName; +import android.view.IWindowManager; import android.view.accessibility.AccessibilityManager; import androidx.test.filters.SmallTest; @@ -47,6 +48,7 @@ import com.android.systemui.accessibility.SystemActions; import com.android.systemui.assist.AssistManager; import com.android.systemui.dump.DumpManager; import com.android.systemui.recents.OverviewProxyService; +import com.android.systemui.settings.DisplayTracker; import com.android.systemui.settings.UserTracker; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.phone.CentralSurfaces; @@ -101,6 +103,10 @@ public class NavBarHelperTest extends SysuiTestCase { NavBarHelper.NavbarTaskbarStateUpdater mNavbarTaskbarStateUpdater; @Mock CommandQueue mCommandQueue; + @Mock + IWindowManager mWm; + @Mock + DisplayTracker mDisplayTracker; private AccessibilityManager.AccessibilityServicesStateChangeListener mAccessibilityServicesStateChangeListener; @@ -114,6 +120,7 @@ public class NavBarHelperTest extends SysuiTestCase { when(mAssistManagerLazy.get()).thenReturn(mAssistManager); when(mAssistManager.getAssistInfoForUser(anyInt())).thenReturn(mAssistantComponent); when(mUserTracker.getUserId()).thenReturn(1); + when(mDisplayTracker.getDefaultDisplayId()).thenReturn(0); doAnswer((invocation) -> mAccessibilityServicesStateChangeListener = invocation.getArgument(0)).when( @@ -122,7 +129,8 @@ public class NavBarHelperTest extends SysuiTestCase { mAccessibilityButtonModeObserver, mAccessibilityButtonTargetObserver, mSystemActions, mOverviewProxyService, mAssistManagerLazy, () -> Optional.of(mock(CentralSurfaces.class)), mock(KeyguardStateController.class), - mNavigationModeController, mUserTracker, mDumpManager, mCommandQueue); + mNavigationModeController, mWm, mUserTracker, mDisplayTracker, mDumpManager, + mCommandQueue); } @@ -134,28 +142,25 @@ public class NavBarHelperTest extends SysuiTestCase { } @Test - public void registerAccessibilityContentObserver() { + public void testSetupBarsRegistersListeners() throws Exception { mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); verify(mAccessibilityButtonModeObserver, times(1)).addListener(mNavBarHelper); verify(mAccessibilityButtonTargetObserver, times(1)).addListener(mNavBarHelper); verify(mAccessibilityManager, times(1)).addAccessibilityServicesStateChangeListener( mNavBarHelper); + verify(mAssistManager, times(1)).getAssistInfoForUser(anyInt()); + verify(mWm, times(1)).watchRotation(any(), anyInt()); } @Test - public void unregisterAccessibilityContentObserver() { + public void testCleanupBarsUnregistersListeners() throws Exception { mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); mNavBarHelper.removeNavTaskStateUpdater(mNavbarTaskbarStateUpdater); verify(mAccessibilityButtonModeObserver, times(1)).removeListener(mNavBarHelper); verify(mAccessibilityButtonTargetObserver, times(1)).removeListener(mNavBarHelper); verify(mAccessibilityManager, times(1)).removeAccessibilityServicesStateChangeListener( mNavBarHelper); - } - - @Test - public void registerAssistantContentObserver() { - mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); - verify(mAssistManager, times(1)).getAssistInfoForUser(anyInt()); + verify(mWm, times(1)).removeRotationWatcher(any()); } @Test @@ -176,6 +181,8 @@ public class NavBarHelperTest extends SysuiTestCase { .updateAccessibilityServicesState(); verify(mNavbarTaskbarStateUpdater, times(1)) .updateAssistantAvailable(anyBoolean(), anyBoolean()); + verify(mNavbarTaskbarStateUpdater, times(1)) + .updateRotationWatcherState(anyInt()); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java index 764ddc49d110..35ab10ff4c16 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java @@ -58,6 +58,7 @@ import android.testing.TestableLooper; import android.testing.TestableLooper.RunWithLooper; import android.view.Display; import android.view.DisplayInfo; +import android.view.IWindowManager; import android.view.MotionEvent; import android.view.View; import android.view.ViewRootImpl; @@ -87,6 +88,7 @@ import com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.recents.OverviewProxyService; import com.android.systemui.recents.Recents; +import com.android.systemui.settings.DisplayTracker; import com.android.systemui.settings.FakeDisplayTracker; import com.android.systemui.settings.UserContextProvider; import com.android.systemui.settings.UserTracker; @@ -250,7 +252,8 @@ public class NavigationBarTest extends SysuiTestCase { mSystemActions, mOverviewProxyService, () -> mock(AssistManager.class), () -> Optional.of(mCentralSurfaces), mKeyguardStateController, mock(NavigationModeController.class), - mock(UserTracker.class), mock(DumpManager.class), mock(CommandQueue.class))); + mock(IWindowManager.class), mock(UserTracker.class), mock(DisplayTracker.class), + mock(DumpManager.class), mock(CommandQueue.class))); mNavigationBar = createNavBar(mContext); mExternalDisplayNavigationBar = createNavBar(mSysuiTestableContextExternal); }); |