diff options
5 files changed, 107 insertions, 48 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java index 1121e160c353..731f712c57c8 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java @@ -90,6 +90,7 @@ public final class NavBarHelper implements AccessibilityButtonTargetsObserver.TargetsChangedListener, OverviewProxyService.OverviewProxyListener, NavigationModeController.ModeChangedListener, Dumpable, CommandQueue.Callbacks { + private final Handler mHandler = new Handler(Looper.getMainLooper()); private final AccessibilityManager mAccessibilityManager; private final Lazy<AssistManager> mAssistManagerLazy; private final Lazy<Optional<CentralSurfaces>> mCentralSurfacesOptionalLazy; @@ -98,7 +99,7 @@ public final class NavBarHelper implements private final SystemActions mSystemActions; private final AccessibilityButtonModeObserver mAccessibilityButtonModeObserver; private final AccessibilityButtonTargetsObserver mAccessibilityButtonTargetsObserver; - private final List<NavbarTaskbarStateUpdater> mA11yEventListeners = new ArrayList<>(); + private final List<NavbarTaskbarStateUpdater> mStateListeners = new ArrayList<>(); private final Context mContext; private final CommandQueue mCommandQueue; private final ContentResolver mContentResolver; @@ -107,13 +108,14 @@ public final class NavBarHelper implements private boolean mAssistantTouchGestureEnabled; private int mNavBarMode; private int mA11yButtonState; + private boolean mTogglingNavbarTaskbar; // Attributes used in NavBarHelper.CurrentSysuiState private int mWindowStateDisplayId; private @WindowVisibleState int mWindowState; - private final ContentObserver mAssistContentObserver = new ContentObserver( - new Handler(Looper.getMainLooper())) { + // Listens for changes to the assistant + private final ContentObserver mAssistContentObserver = new ContentObserver(mHandler) { @Override public void onChange(boolean selfChange, Uri uri) { updateAssistantAvailability(); @@ -147,18 +149,33 @@ public final class NavBarHelper implements mKeyguardStateController = keyguardStateController; mUserTracker = userTracker; mSystemActions = systemActions; - accessibilityManager.addAccessibilityServicesStateChangeListener(this); mAccessibilityButtonModeObserver = accessibilityButtonModeObserver; mAccessibilityButtonTargetsObserver = accessibilityButtonTargetsObserver; - mAccessibilityButtonModeObserver.addListener(this); - mAccessibilityButtonTargetsObserver.addListener(this); mNavBarMode = navigationModeController.addListener(this); + mCommandQueue.addCallback(this); overviewProxyService.addCallback(this); dumpManager.registerDumpable(this); } - public void init() { + /** + * Hints to the helper that bars are being replaced, which is a signal to potentially suppress + * normal setup/cleanup when no bars are present. + */ + public void setTogglingNavbarTaskbar(boolean togglingNavbarTaskbar) { + mTogglingNavbarTaskbar = togglingNavbarTaskbar; + } + + /** + * Called when the first (non-replacing) bar is registered. + */ + private void setupOnFirstBar() { + // Setup accessibility listeners + mAccessibilityManager.addAccessibilityServicesStateChangeListener(this); + mAccessibilityButtonModeObserver.addListener(this); + mAccessibilityButtonTargetsObserver.addListener(this); + + // Setup assistant listener mContentResolver.registerContentObserver( Settings.Secure.getUriFor(Settings.Secure.ASSISTANT), false /* notifyForDescendants */, mAssistContentObserver, UserHandle.USER_ALL); @@ -168,59 +185,76 @@ public final class NavBarHelper implements mContentResolver.registerContentObserver( Settings.Secure.getUriFor(Settings.Secure.ASSIST_TOUCH_GESTURE_ENABLED), false, mAssistContentObserver, UserHandle.USER_ALL); - updateAssistantAvailability(); - updateA11yState(); - mCommandQueue.addCallback(this); - } - public void destroy() { + /** + * Called after the last (non-replacing) bar is unregistered. + */ + private void cleanupAfterLastBar() { + // Clean up accessibility listeners + mAccessibilityManager.removeAccessibilityServicesStateChangeListener(this); + mAccessibilityButtonModeObserver.removeListener(this); + mAccessibilityButtonTargetsObserver.removeListener(this); + + // Clean up assistant listeners mContentResolver.unregisterContentObserver(mAssistContentObserver); - mCommandQueue.removeCallback(this); } /** + * Registers a listener for future updates to the shared navbar/taskbar state. * @param listener Will immediately get callbacks based on current state */ public void registerNavTaskStateUpdater(NavbarTaskbarStateUpdater listener) { - mA11yEventListeners.add(listener); - listener.updateAccessibilityServicesState(); - listener.updateAssistantAvailable(mAssistantAvailable, mLongPressHomeEnabled); + mStateListeners.add(listener); + if (!mTogglingNavbarTaskbar && mStateListeners.size() == 1) { + setupOnFirstBar(); + + // Update the state once the first bar is registered + updateAssistantAvailability(); + updateA11yState(); + mCommandQueue.recomputeDisableFlags(mContext.getDisplayId(), false /* animate */); + } else { + listener.updateAccessibilityServicesState(); + listener.updateAssistantAvailable(mAssistantAvailable, mLongPressHomeEnabled); + } } + /** + * Removes a previously registered listener. + */ public void removeNavTaskStateUpdater(NavbarTaskbarStateUpdater listener) { - mA11yEventListeners.remove(listener); + mStateListeners.remove(listener); + if (!mTogglingNavbarTaskbar && mStateListeners.isEmpty()) { + cleanupAfterLastBar(); + } } private void dispatchA11yEventUpdate() { - for (NavbarTaskbarStateUpdater listener : mA11yEventListeners) { + for (NavbarTaskbarStateUpdater listener : mStateListeners) { listener.updateAccessibilityServicesState(); } } private void dispatchAssistantEventUpdate(boolean assistantAvailable, boolean longPressHomeEnabled) { - for (NavbarTaskbarStateUpdater listener : mA11yEventListeners) { + for (NavbarTaskbarStateUpdater listener : mStateListeners) { listener.updateAssistantAvailable(assistantAvailable, longPressHomeEnabled); } } @Override public void onAccessibilityServicesStateChanged(AccessibilityManager manager) { - dispatchA11yEventUpdate(); updateA11yState(); } @Override public void onAccessibilityButtonModeChanged(int mode) { updateA11yState(); - dispatchA11yEventUpdate(); } @Override public void onAccessibilityButtonTargetsChanged(String targets) { updateA11yState(); - dispatchA11yEventUpdate(); } /** @@ -262,6 +296,8 @@ public final class NavBarHelper implements updateSystemAction(clickable, SYSTEM_ACTION_ID_ACCESSIBILITY_BUTTON); updateSystemAction(longClickable, SYSTEM_ACTION_ID_ACCESSIBILITY_BUTTON_CHOOSER); } + + dispatchA11yEventUpdate(); } /** diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java index f81743928e3b..1c36e92cff00 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java @@ -677,13 +677,14 @@ public class NavigationBar extends ViewController<NavigationBarView> implements // start firing, since the latter is source of truth parseCurrentSysuiState(); mCommandQueue.addCallback(this); - mLongPressHomeEnabled = mNavBarHelper.getLongPressHomeEnabled(); - mNavBarHelper.init(); mHomeButtonLongPressDurationMs = Optional.of(mDeviceConfigProxy.getLong( DeviceConfig.NAMESPACE_SYSTEMUI, HOME_BUTTON_LONG_PRESS_DURATION_MS, /* defaultValue = */ 0 )).filter(duration -> duration != 0); + // This currently MUST be called after mHomeButtonLongPressDurationMs is initialized since + // the registration callbacks will trigger code that uses it + mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); mDeviceConfigProxy.addOnPropertiesChangedListener( DeviceConfig.NAMESPACE_SYSTEMUI, mHandler::post, mOnPropertiesChangedListener); @@ -709,7 +710,6 @@ public class NavigationBar extends ViewController<NavigationBarView> implements mNavigationModeController.removeListener(mModeChangedListener); mNavBarHelper.removeNavTaskStateUpdater(mNavbarTaskbarStateUpdater); - mNavBarHelper.destroy(); mNotificationShadeDepthController.removeListener(mDepthListener); mDeviceConfigProxy.removeOnPropertiesChangedListener(mOnPropertiesChangedListener); @@ -746,8 +746,6 @@ public class NavigationBar extends ViewController<NavigationBarView> implements mView.getViewRootImpl().addSurfaceChangedCallback(mSurfaceChangedCallback); notifyNavigationBarSurface(); - mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); - mPipOptional.ifPresent(mView::addPipExclusionBoundsChangeListener); mBackAnimation.ifPresent(mView::registerBackAnimation); @@ -1487,6 +1485,7 @@ public class NavigationBar extends ViewController<NavigationBarView> implements } void updateAccessibilityStateFlags() { + mLongPressHomeEnabled = mNavBarHelper.getLongPressHomeEnabled(); if (mView != null) { int a11yFlags = mNavBarHelper.getA11yButtonState(); boolean clickable = (a11yFlags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0; diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java index 153d5a651f9c..21398e23cc10 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java @@ -90,6 +90,7 @@ public class NavigationBarController implements private final DisplayTracker mDisplayTracker; private final DisplayManager mDisplayManager; private final TaskbarDelegate mTaskbarDelegate; + private final NavBarHelper mNavBarHelper; private int mNavMode; @VisibleForTesting boolean mIsLargeScreen; @@ -133,6 +134,7 @@ public class NavigationBarController implements configurationController.addCallback(this); mConfigChanges.applyNewConfig(mContext.getResources()); mNavMode = navigationModeController.addListener(this); + mNavBarHelper = navBarHelper; mTaskbarDelegate = taskbarDelegate; mTaskbarDelegate.setDependencies(commandQueue, overviewProxyService, navBarHelper, navigationModeController, sysUiFlagsContainer, @@ -241,10 +243,15 @@ public class NavigationBarController implements if (taskbarEnabled) { Trace.beginSection("NavigationBarController#initializeTaskbarIfNecessary"); + final int displayId = mContext.getDisplayId(); + // Hint to NavBarHelper if we are replacing an existing bar to skip extra work + mNavBarHelper.setTogglingNavbarTaskbar(mNavigationBars.contains(displayId)); // Remove navigation bar when taskbar is showing - removeNavigationBar(mContext.getDisplayId()); - mTaskbarDelegate.init(mContext.getDisplayId()); + removeNavigationBar(displayId); + mTaskbarDelegate.init(displayId); + mNavBarHelper.setTogglingNavbarTaskbar(false); Trace.endSection(); + } else { mTaskbarDelegate.destroy(); } diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java index 5b02aaf089e0..dc5c9bd7b38a 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java @@ -239,7 +239,6 @@ public class TaskbarDelegate implements CommandQueue.Callbacks, mOverviewProxyService.addCallback(this); onNavigationModeChanged(mNavigationModeController.addListener(this)); mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); - mNavBarHelper.init(); mEdgeBackGestureHandler.onNavBarAttached(); // Initialize component callback Display display = mDisplayManager.getDisplay(displayId); @@ -264,7 +263,6 @@ public class TaskbarDelegate implements CommandQueue.Callbacks, mOverviewProxyService.removeCallback(this); mNavigationModeController.removeListener(this); mNavBarHelper.removeNavTaskStateUpdater(mNavbarTaskbarStateUpdater); - mNavBarHelper.destroy(); mEdgeBackGestureHandler.onNavBarDetached(); mScreenPinningNotify = null; mWindowContext = null; 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 ce6a98c9e162..fbe83af78080 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java @@ -128,20 +128,49 @@ public class NavBarHelperTest extends SysuiTestCase { @Test public void registerListenersInCtor() { - verify(mAccessibilityButtonModeObserver, times(1)).addListener(mNavBarHelper); verify(mNavigationModeController, times(1)).addListener(mNavBarHelper); verify(mOverviewProxyService, times(1)).addCallback(mNavBarHelper); + verify(mCommandQueue, times(1)).addCallback(any()); + } + + @Test + public void registerAccessibilityContentObserver() { + mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); + verify(mAccessibilityButtonModeObserver, times(1)).addListener(mNavBarHelper); + verify(mAccessibilityButtonTargetObserver, times(1)).addListener(mNavBarHelper); + verify(mAccessibilityManager, times(1)).addAccessibilityServicesStateChangeListener( + mNavBarHelper); + } + + @Test + public void unregisterAccessibilityContentObserver() { + 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.init(); + mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); verify(mAssistManager, times(1)).getAssistInfoForUser(anyInt()); } @Test + public void replacingBarsHint() { + mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); + mNavBarHelper.setTogglingNavbarTaskbar(true); + mNavBarHelper.removeNavTaskStateUpdater(mNavbarTaskbarStateUpdater); + mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); + mNavBarHelper.setTogglingNavbarTaskbar(false); + // Use any state in cleanup to verify it was not called + verify(mAccessibilityButtonModeObserver, times(0)).removeListener(mNavBarHelper); + } + + @Test public void callbacksFiredWhenRegistering() { - mNavBarHelper.init(); mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); verify(mNavbarTaskbarStateUpdater, times(1)) .updateAccessibilityServicesState(); @@ -151,7 +180,6 @@ public class NavBarHelperTest extends SysuiTestCase { @Test public void assistantCallbacksFiredAfterConnecting() { - mNavBarHelper.init(); // 1st set of callbacks get called when registering mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); @@ -172,7 +200,6 @@ public class NavBarHelperTest extends SysuiTestCase { @Test public void a11yCallbacksFiredAfterModeChange() { - mNavBarHelper.init(); // 1st set of callbacks get called when registering mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); @@ -185,7 +212,6 @@ public class NavBarHelperTest extends SysuiTestCase { @Test public void assistantCallbacksFiredAfterNavModeChange() { - mNavBarHelper.init(); // 1st set of callbacks get called when registering mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); @@ -198,7 +224,6 @@ public class NavBarHelperTest extends SysuiTestCase { @Test public void removeListenerNoCallbacksFired() { - mNavBarHelper.init(); // 1st set of callbacks get called when registering mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); @@ -220,7 +245,7 @@ public class NavBarHelperTest extends SysuiTestCase { when(mAccessibilityManager.getAccessibilityShortcutTargets( AccessibilityManager.ACCESSIBILITY_BUTTON)).thenReturn(createFakeShortcutTargets()); - mNavBarHelper.init(); + mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); assertThat(mNavBarHelper.getA11yButtonState()).isEqualTo( ACCESSIBILITY_BUTTON_CLICKABLE_STATE); @@ -230,13 +255,15 @@ public class NavBarHelperTest extends SysuiTestCase { public void initAccessibilityStateWithFloatingMenuModeAndTargets_disableClickableState() { when(mAccessibilityButtonModeObserver.getCurrentAccessibilityButtonMode()).thenReturn( ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU); - mNavBarHelper.init(); + + mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); assertThat(mNavBarHelper.getA11yButtonState()).isEqualTo(/* disable_clickable_state */ 0); } @Test public void onA11yServicesStateChangedWithMultipleServices_a11yButtonClickableState() { + mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); when(mAccessibilityButtonModeObserver.getCurrentAccessibilityButtonMode()).thenReturn( ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR); @@ -250,14 +277,7 @@ public class NavBarHelperTest extends SysuiTestCase { } @Test - public void registerCommandQueueCallbacks() { - mNavBarHelper.init(); - verify(mCommandQueue, times(1)).addCallback(any()); - } - - @Test public void saveMostRecentSysuiState() { - mNavBarHelper.init(); mNavBarHelper.setWindowState(DISPLAY_ID, WINDOW, STATE_ID); NavBarHelper.CurrentSysuiState state1 = mNavBarHelper.getCurrentSysuiState(); @@ -274,7 +294,6 @@ public class NavBarHelperTest extends SysuiTestCase { @Test public void ignoreNonNavbarSysuiState() { - mNavBarHelper.init(); mNavBarHelper.setWindowState(DISPLAY_ID, WINDOW, STATE_ID); NavBarHelper.CurrentSysuiState state1 = mNavBarHelper.getCurrentSysuiState(); |