1/ Initialize assistant state change listeners once with the nav bar helper
- Consolidate the meaning of init/destroy into the registration/unregistration of the nav bar helper state callbacks. This allows us to track the case where we are replacing the bars to prevent churn in unregistering and reregistering shared callbacks - Using the above, we can only register the assistant content observers when the first bar is registered, and keep it registered across bar replacements Bug: 219035565 Test: atest NavBarHelperTests Test: atest SystemUITests Change-Id: I2444bb0b27086b72212ef05b8c975c19a05a35d5
This commit is contained in:
@@ -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() {
|
||||
mContentResolver.unregisterContentObserver(mAssistContentObserver);
|
||||
mCommandQueue.removeCallback(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -249,15 +276,8 @@ public class NavBarHelperTest extends SysuiTestCase {
|
||||
ACCESSIBILITY_BUTTON_CLICKABLE_STATE);
|
||||
}
|
||||
|
||||
@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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user