diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java deleted file mode 100644 index 52103d3bd7391..0000000000000 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Copyright (C) 2021 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.systemui.navigationbar; - -import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU; - -import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE; -import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE; - -import android.content.ContentResolver; -import android.content.Context; -import android.database.ContentObserver; -import android.net.Uri; -import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; -import android.os.UserHandle; -import android.provider.Settings; -import android.view.accessibility.AccessibilityManager; - -import androidx.annotation.NonNull; - -import com.android.systemui.Dumpable; -import com.android.systemui.accessibility.AccessibilityButtonModeObserver; -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.UserTracker; -import com.android.systemui.shared.system.QuickStepContract; -import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.List; - -import javax.inject.Inject; - -import dagger.Lazy; - -/** - * Extracts shared elements between navbar and taskbar delegate to de-dupe logic and help them - * experience the joys of friendship. - * The events are then passed through - * - * Currently consolidates - * * A11y - * * Assistant - */ -@SysUISingleton -public final class NavBarHelper implements - AccessibilityButtonModeObserver.ModeChangedListener, - OverviewProxyService.OverviewProxyListener, NavigationModeController.ModeChangedListener, - Dumpable { - private final AccessibilityManager mAccessibilityManager; - private final Lazy mAssistManagerLazy; - private final UserTracker mUserTracker; - private final AccessibilityButtonModeObserver mAccessibilityButtonModeObserver; - private final List mA11yEventListeners = new ArrayList<>(); - private Context mContext; - private ContentResolver mContentResolver; - private boolean mAssistantAvailable; - private boolean mLongPressHomeEnabled; - private boolean mAssistantTouchGestureEnabled; - private int mNavBarMode; - - private final ContentObserver mAssistContentObserver = new ContentObserver( - new Handler(Looper.getMainLooper())) { - @Override - public void onChange(boolean selfChange, Uri uri) { - updateAssitantAvailability(); - } - }; - - @Inject - public NavBarHelper(AccessibilityManager accessibilityManager, - AccessibilityManagerWrapper accessibilityManagerWrapper, - AccessibilityButtonModeObserver accessibilityButtonModeObserver, - OverviewProxyService overviewProxyService, - Lazy assistManagerLazy, - NavigationModeController navigationModeController, - UserTracker userTracker, - DumpManager dumpManager) { - mAccessibilityManager = accessibilityManager; - mAssistManagerLazy = assistManagerLazy; - mUserTracker = userTracker; - accessibilityManagerWrapper.addCallback( - accessibilityManager1 -> NavBarHelper.this.dispatchA11yEventUpdate()); - mAccessibilityButtonModeObserver = accessibilityButtonModeObserver; - - mAccessibilityButtonModeObserver.addListener(this); - mNavBarMode = navigationModeController.addListener(this); - overviewProxyService.addCallback(this); - dumpManager.registerDumpable(this); - } - - public void init(Context context) { - mContext = context; - mContentResolver = mContext.getContentResolver(); - mContentResolver.registerContentObserver( - Settings.Secure.getUriFor(Settings.Secure.ASSISTANT), - false /* notifyForDescendants */, mAssistContentObserver, UserHandle.USER_ALL); - mContentResolver.registerContentObserver( - Settings.Secure.getUriFor(Settings.Secure.ASSIST_LONG_PRESS_HOME_ENABLED), - false, mAssistContentObserver, UserHandle.USER_ALL); - mContentResolver.registerContentObserver( - Settings.Secure.getUriFor(Settings.Secure.ASSIST_TOUCH_GESTURE_ENABLED), - false, mAssistContentObserver, UserHandle.USER_ALL); - updateAssitantAvailability(); - } - - public void destroy() { - mContentResolver.unregisterContentObserver(mAssistContentObserver); - } - - /** - * @param listener Will immediately get callbacks based on current state - */ - public void registerNavTaskStateUpdater(NavbarTaskbarStateUpdater listener) { - mA11yEventListeners.add(listener); - listener.updateAccessibilityServicesState(); - listener.updateAssistantAvailable(mAssistantAvailable); - } - - public void removeNavTaskStateUpdater(NavbarTaskbarStateUpdater listener) { - mA11yEventListeners.remove(listener); - } - - private void dispatchA11yEventUpdate() { - for (NavbarTaskbarStateUpdater listener : mA11yEventListeners) { - listener.updateAccessibilityServicesState(); - } - } - - private void dispatchAssistantEventUpdate(boolean assistantAvailable) { - for (NavbarTaskbarStateUpdater listener : mA11yEventListeners) { - listener.updateAssistantAvailable(assistantAvailable); - } - } - - @Override - public void onAccessibilityButtonModeChanged(int mode) { - dispatchA11yEventUpdate(); - } - - /** - * See {@link QuickStepContract#SYSUI_STATE_A11Y_BUTTON_CLICKABLE} and - * {@link QuickStepContract#SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE} - * - * @return the a11y button clickable and long_clickable states, or 0 if there is no - * a11y button in the navbar - */ - public int getA11yButtonState() { - // AccessibilityManagerService resolves services for the current user since the local - // AccessibilityManager is created from a Context with the INTERACT_ACROSS_USERS permission - final List a11yButtonTargets = - mAccessibilityManager.getAccessibilityShortcutTargets( - AccessibilityManager.ACCESSIBILITY_BUTTON); - final int requestingServices = a11yButtonTargets.size(); - - // If accessibility button is floating menu mode, click and long click state should be - // disabled. - if (mAccessibilityButtonModeObserver.getCurrentAccessibilityButtonMode() - == ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU) { - return 0; - } - - return (requestingServices >= 1 ? SYSUI_STATE_A11Y_BUTTON_CLICKABLE : 0) - | (requestingServices >= 2 ? SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE : 0); - } - - @Override - public void onConnectionChanged(boolean isConnected) { - if (isConnected) { - updateAssitantAvailability(); - } - } - - private void updateAssitantAvailability() { - boolean assistantAvailableForUser = mAssistManagerLazy.get() - .getAssistInfoForUser(UserHandle.USER_CURRENT) != null; - boolean longPressDefault = mContext.getResources().getBoolean( - com.android.internal.R.bool.config_assistLongPressHomeEnabledDefault); - mLongPressHomeEnabled = Settings.Secure.getIntForUser(mContentResolver, - Settings.Secure.ASSIST_LONG_PRESS_HOME_ENABLED, longPressDefault ? 1 : 0, - mUserTracker.getUserId()) != 0; - boolean gestureDefault = mContext.getResources().getBoolean( - com.android.internal.R.bool.config_assistTouchGestureEnabledDefault); - mAssistantTouchGestureEnabled = Settings.Secure.getIntForUser(mContentResolver, - Settings.Secure.ASSIST_TOUCH_GESTURE_ENABLED, gestureDefault ? 1 : 0, - mUserTracker.getUserId()) != 0; - - mAssistantAvailable = assistantAvailableForUser - && mAssistantTouchGestureEnabled - && QuickStepContract.isGesturalMode(mNavBarMode); - dispatchAssistantEventUpdate(mAssistantAvailable); - } - - public boolean getLongPressHomeEnabled() { - return mLongPressHomeEnabled; - } - - @Override - public void startAssistant(Bundle bundle) { - mAssistManagerLazy.get().startAssist(bundle); - } - - @Override - public void onNavigationModeChanged(int mode) { - mNavBarMode = mode; - updateAssitantAvailability(); - } - - /** - * Callbacks will get fired once immediately after registering via - * {@link #registerNavTaskStateUpdater(NavbarTaskbarStateUpdater)} - */ - public interface NavbarTaskbarStateUpdater { - void updateAccessibilityServicesState(); - void updateAssistantAvailable(boolean available); - } - - @Override - public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) { - pw.println("NavbarTaskbarFriendster"); - pw.println(" longPressHomeEnabled=" + mLongPressHomeEnabled); - pw.println(" mAssistantTouchGestureEnabled=" + mAssistantTouchGestureEnabled); - pw.println(" mAssistantAvailable=" + mAssistantAvailable); - pw.println(" mNavBarMode=" + mNavBarMode); - } -} diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java index 5141f25e49336..bc023cc892a64 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java @@ -68,18 +68,22 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.res.Configuration; +import android.database.ContentObserver; import android.graphics.Insets; import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.RectF; import android.inputmethodservice.InputMethodService; +import android.net.Uri; import android.os.Binder; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; +import android.os.Looper; import android.os.RemoteException; import android.os.UserHandle; import android.provider.DeviceConfig; +import android.provider.Settings; import android.telecom.TelecomManager; import android.text.TextUtils; import android.util.Log; @@ -196,7 +200,8 @@ public class NavigationBar implements View.OnAttachStateChangeListener, private final Handler mHandler; private final NavigationBarOverlayController mNavbarOverlayController; private final UiEventLogger mUiEventLogger; - private final NavBarHelper mNavBarHelper; + private final NavigationBarA11yHelper mNavigationBarA11yHelper; + private final UserTracker mUserTracker; private final NotificationShadeDepthController mNotificationShadeDepthController; private Bundle mSavedState; @@ -208,7 +213,9 @@ public class NavigationBar implements View.OnAttachStateChangeListener, private int mNavigationIconHints = 0; private @TransitionMode int mNavigationBarMode; private ContentResolver mContentResolver; + private boolean mAssistantAvailable; private boolean mLongPressHomeEnabled; + private boolean mAssistantTouchGestureEnabled; private int mDisabledFlags1; private int mDisabledFlags2; @@ -302,31 +309,16 @@ public class NavigationBar implements View.OnAttachStateChangeListener, } }; - private final NavBarHelper.NavbarTaskbarStateUpdater mNavbarTaskbarStateUpdater = - new NavBarHelper.NavbarTaskbarStateUpdater() { - @Override - public void updateAccessibilityServicesState() { - updateAcessibilityStateFlags(); - } - - @Override - public void updateAssistantAvailable(boolean available) { - // TODO(b/198002034): Content observers currently can still be called back after - // being unregistered, and in this case we can ignore the change if the nav bar - // has been destroyed already - if (mNavigationBarView == null) { - return; - } - mLongPressHomeEnabled = mNavBarHelper.getLongPressHomeEnabled(); - updateAssistantEntrypoints(available); - } - }; - private final OverviewProxyListener mOverviewProxyListener = new OverviewProxyListener() { @Override public void onConnectionChanged(boolean isConnected) { mNavigationBarView.updateStates(); updateScreenPinningGestures(); + + // Send the assistant availability upon connection + if (isConnected) { + updateAssistantEntrypoints(); + } } @Override @@ -429,6 +421,20 @@ public class NavigationBar implements View.OnAttachStateChangeListener, } }; + private final ContentObserver mAssistContentObserver = new ContentObserver( + new Handler(Looper.getMainLooper())) { + @Override + public void onChange(boolean selfChange, Uri uri) { + // TODO(b/198002034): Content observers currently can still be called back after being + // unregistered, and in this case we can ignore the change if the nav bar has been + // destroyed already + if (mNavigationBarView == null) { + return; + } + updateAssistantEntrypoints(); + } + }; + private final DeviceConfig.OnPropertiesChangedListener mOnPropertiesChangedListener = new DeviceConfig.OnPropertiesChangedListener() { @Override @@ -498,7 +504,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, @Main Handler mainHandler, NavigationBarOverlayController navbarOverlayController, UiEventLogger uiEventLogger, - NavBarHelper navBarHelper, + NavigationBarA11yHelper navigationBarA11yHelper, UserTracker userTracker, LightBarController mainLightBarController, LightBarController.Factory lightBarControllerFactory, @@ -529,7 +535,8 @@ public class NavigationBar implements View.OnAttachStateChangeListener, mHandler = mainHandler; mNavbarOverlayController = navbarOverlayController; mUiEventLogger = uiEventLogger; - mNavBarHelper = navBarHelper; + mNavigationBarA11yHelper = navigationBarA11yHelper; + mUserTracker = userTracker; mNotificationShadeDepthController = notificationShadeDepthController; mMainLightBarController = mainLightBarController; mLightBarControllerFactory = lightBarControllerFactory; @@ -561,9 +568,18 @@ public class NavigationBar implements View.OnAttachStateChangeListener, mIsOnDefaultDisplay = mDisplayId == DEFAULT_DISPLAY; mCommandQueue.addCallback(this); - mLongPressHomeEnabled = mNavBarHelper.getLongPressHomeEnabled(); + mAssistantAvailable = mAssistManagerLazy.get() + .getAssistInfoForUser(UserHandle.USER_CURRENT) != null; mContentResolver = mContext.getContentResolver(); - mNavBarHelper.init(mContext); + mContentResolver.registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.ASSISTANT), + false /* notifyForDescendants */, mAssistContentObserver, UserHandle.USER_ALL); + mContentResolver.registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.ASSIST_LONG_PRESS_HOME_ENABLED), + false, mAssistContentObserver, UserHandle.USER_ALL); + mContentResolver.registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.ASSIST_TOUCH_GESTURE_ENABLED), + false, mAssistContentObserver, UserHandle.USER_ALL); mAllowForceNavBarHandleOpaque = mContext.getResources().getBoolean( R.bool.allow_force_nav_bar_handle_opaque); mForceNavBarHandleOpaque = DeviceConfig.getBoolean( @@ -577,6 +593,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, )).filter(duration -> duration != 0); DeviceConfig.addOnPropertiesChangedListener( DeviceConfig.NAMESPACE_SYSTEMUI, mHandler::post, mOnPropertiesChangedListener); + updateAssistantEntrypoints(); if (savedState != null) { mDisabledFlags1 = savedState.getInt(EXTRA_DISABLE_STATE, 0); @@ -603,8 +620,8 @@ public class NavigationBar implements View.OnAttachStateChangeListener, mWindowManager.removeViewImmediate(mNavigationBarView.getRootView()); mNavigationModeController.removeListener(this); - mNavBarHelper.removeNavTaskStateUpdater(mNavbarTaskbarStateUpdater); - mNavBarHelper.destroy(); + mNavigationBarA11yHelper.removeA11yEventListener(mAccessibilityListener); + mContentResolver.unregisterContentObserver(mAssistContentObserver); mDeviceProvisionedController.removeCallback(mUserSetupListener); mNotificationShadeDepthController.removeListener(mDepthListener); @@ -626,7 +643,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, mNavigationBarView.setWindowVisible(isNavBarWindowVisible()); mNavigationBarView.setBehavior(mBehavior); - mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); + mNavigationBarA11yHelper.registerA11yEventListener(mAccessibilityListener); mSplitScreenOptional.ifPresent(mNavigationBarView::registerDockedListener); mPipOptional.ifPresent(mNavigationBarView::registerPipExclusionBoundsChangeListener); @@ -699,7 +716,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, mHandler.removeCallbacks(mAutoDim); mHandler.removeCallbacks(mOnVariableDurationHomeLongClick); mHandler.removeCallbacks(mEnableLayoutTransitions); - mNavBarHelper.removeNavTaskStateUpdater(mNavbarTaskbarStateUpdater); + mNavigationBarA11yHelper.removeA11yEventListener(mAccessibilityListener); mFrame = null; mNavigationBarView = null; mOrientationHandle = null; @@ -868,6 +885,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, pw.println(" mCurrentRotation=" + mCurrentRotation); pw.println(" mHomeButtonLongPressDurationMs=" + mHomeButtonLongPressDurationMs); pw.println(" mLongPressHomeEnabled=" + mLongPressHomeEnabled); + pw.println(" mAssistantTouchGestureEnabled=" + mAssistantTouchGestureEnabled); pw.println(" mNavigationBarWindowState=" + windowStateToString(mNavigationBarWindowState)); pw.println(" mNavigationBarMode=" @@ -1147,7 +1165,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, ButtonDispatcher accessibilityButton = mNavigationBarView.getAccessibilityButton(); accessibilityButton.setOnClickListener(this::onAccessibilityClick); accessibilityButton.setOnLongClickListener(this::onAccessibilityLongClick); - updateAcessibilityStateFlags(); + updateAccessibilityServicesState(); ButtonDispatcher imeSwitcherButton = mNavigationBarView.getImeSwitchButton(); imeSwitcherButton.setOnClickListener(this::onImeSwitcherClick); @@ -1372,8 +1390,8 @@ public class NavigationBar implements View.OnAttachStateChangeListener, return true; } - void updateAcessibilityStateFlags() { - int a11yFlags = mNavBarHelper.getA11yButtonState(); + void updateAccessibilityServicesState() { + int a11yFlags = mNavigationBarA11yHelper.getA11yButtonState(); if (mNavigationBarView != null) { boolean clickable = (a11yFlags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0; @@ -1385,7 +1403,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, public void updateSystemUiStateFlags(int a11yFlags) { if (a11yFlags < 0) { - a11yFlags = mNavBarHelper.getA11yButtonState(); + a11yFlags = mNavigationBarA11yHelper.getA11yButtonState(); } boolean clickable = (a11yFlags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0; boolean longClickable = (a11yFlags & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE) != 0; @@ -1412,10 +1430,24 @@ public class NavigationBar implements View.OnAttachStateChangeListener, } } - private void updateAssistantEntrypoints(boolean assistantAvailable) { + private void updateAssistantEntrypoints() { + mAssistantAvailable = mAssistManagerLazy.get() + .getAssistInfoForUser(UserHandle.USER_CURRENT) != null; + boolean longPressDefault = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_assistLongPressHomeEnabledDefault); + mLongPressHomeEnabled = Settings.Secure.getIntForUser(mContentResolver, + Settings.Secure.ASSIST_LONG_PRESS_HOME_ENABLED, longPressDefault ? 1 : 0, + mUserTracker.getUserId()) != 0; + boolean gestureDefault = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_assistTouchGestureEnabledDefault); + mAssistantTouchGestureEnabled = Settings.Secure.getIntForUser(mContentResolver, + Settings.Secure.ASSIST_TOUCH_GESTURE_ENABLED, gestureDefault ? 1 : 0, + mUserTracker.getUserId()) != 0; if (mOverviewProxyService.getProxy() != null) { try { - mOverviewProxyService.getProxy().onAssistantAvailable(assistantAvailable); + mOverviewProxyService.getProxy().onAssistantAvailable(mAssistantAvailable + && mAssistantTouchGestureEnabled + && QuickStepContract.isGesturalMode(mNavBarMode)); } catch (RemoteException e) { Log.w(TAG, "Unable to send assistant availability data to launcher"); } @@ -1486,6 +1518,8 @@ public class NavigationBar implements View.OnAttachStateChangeListener, @Override public void onNavigationModeChanged(int mode) { mNavBarMode = mode; + // update assistant entry points on system navigation radio button click + updateAssistantEntrypoints(); if (!QuickStepContract.isGesturalMode(mode)) { // Reset the override alpha @@ -1524,6 +1558,9 @@ public class NavigationBar implements View.OnAttachStateChangeListener, mNavigationBarView.getBarTransitions().finishAnimations(); } + private final NavigationBarA11yHelper.NavA11yEventListener mAccessibilityListener = + this::updateAccessibilityServicesState; + private WindowManager.LayoutParams getBarLayoutParams(int rotation) { WindowManager.LayoutParams lp = getBarLayoutParamsForRotation(rotation); lp.paramsForRotation = new WindowManager.LayoutParams[4]; @@ -1631,7 +1668,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, } if (Intent.ACTION_USER_SWITCHED.equals(action)) { // The accessibility settings may be different for the new user - updateAcessibilityStateFlags(); + updateAccessibilityServicesState(); } } }; @@ -1667,7 +1704,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, private final Handler mMainHandler; private final NavigationBarOverlayController mNavbarOverlayController; private final UiEventLogger mUiEventLogger; - private final NavBarHelper mNavBarHelper; + private final NavigationBarA11yHelper mNavigationBarA11yHelper; private final UserTracker mUserTracker; private final LightBarController mMainLightBarController; private final LightBarController.Factory mLightBarControllerFactory; @@ -1700,7 +1737,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, @Main Handler mainHandler, NavigationBarOverlayController navbarOverlayController, UiEventLogger uiEventLogger, - NavBarHelper navBarHelper, + NavigationBarA11yHelper navigationBarA11yHelper, UserTracker userTracker, LightBarController mainLightBarController, LightBarController.Factory lightBarControllerFactory, @@ -1730,7 +1767,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, mMainHandler = mainHandler; mNavbarOverlayController = navbarOverlayController; mUiEventLogger = uiEventLogger; - mNavBarHelper = navBarHelper; + mNavigationBarA11yHelper = navigationBarA11yHelper; mUserTracker = userTracker; mMainLightBarController = mainLightBarController; mLightBarControllerFactory = lightBarControllerFactory; @@ -1751,7 +1788,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, mSplitScreenOptional, mRecentsOptional, mStatusBarOptionalLazy, mShadeController, mNotificationRemoteInputManager, mNotificationShadeDepthController, mSystemActions, mMainHandler, - mNavbarOverlayController, mUiEventLogger, mNavBarHelper, + mNavbarOverlayController, mUiEventLogger, mNavigationBarA11yHelper, mUserTracker, mMainLightBarController, mLightBarControllerFactory, mMainAutoHideController, mAutoHideControllerFactory, mTelecomManagerOptional, mInputMethodManager); diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarA11yHelper.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarA11yHelper.java new file mode 100644 index 0000000000000..13e6d8b410d68 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarA11yHelper.java @@ -0,0 +1,90 @@ +package com.android.systemui.navigationbar; + +import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU; + +import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE; +import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE; + +import android.view.accessibility.AccessibilityManager; + +import com.android.systemui.accessibility.AccessibilityButtonModeObserver; +import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.shared.system.QuickStepContract; +import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper; + +import java.util.ArrayList; +import java.util.List; + +import javax.inject.Inject; + +/** + * Extracts shared elements of a11y necessary between navbar and taskbar delegate + */ +@SysUISingleton +public final class NavigationBarA11yHelper implements + AccessibilityButtonModeObserver.ModeChangedListener { + private final AccessibilityManager mAccessibilityManager; + private final AccessibilityButtonModeObserver mAccessibilityButtonModeObserver; + private final List mA11yEventListeners = new ArrayList<>(); + + @Inject + public NavigationBarA11yHelper(AccessibilityManager accessibilityManager, + AccessibilityManagerWrapper accessibilityManagerWrapper, + AccessibilityButtonModeObserver accessibilityButtonModeObserver) { + mAccessibilityManager = accessibilityManager; + accessibilityManagerWrapper.addCallback( + accessibilityManager1 -> NavigationBarA11yHelper.this.dispatchEventUpdate()); + mAccessibilityButtonModeObserver = accessibilityButtonModeObserver; + + mAccessibilityButtonModeObserver.addListener(this); + } + + public void registerA11yEventListener(NavA11yEventListener listener) { + mA11yEventListeners.add(listener); + } + + public void removeA11yEventListener(NavA11yEventListener listener) { + mA11yEventListeners.remove(listener); + } + + private void dispatchEventUpdate() { + for (NavA11yEventListener listener : mA11yEventListeners) { + listener.updateAccessibilityServicesState(); + } + } + + @Override + public void onAccessibilityButtonModeChanged(int mode) { + dispatchEventUpdate(); + } + + /** + * See {@link QuickStepContract#SYSUI_STATE_A11Y_BUTTON_CLICKABLE} and + * {@link QuickStepContract#SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE} + * + * @return the a11y button clickable and long_clickable states, or 0 if there is no + * a11y button in the navbar + */ + public int getA11yButtonState() { + // AccessibilityManagerService resolves services for the current user since the local + // AccessibilityManager is created from a Context with the INTERACT_ACROSS_USERS permission + final List a11yButtonTargets = + mAccessibilityManager.getAccessibilityShortcutTargets( + AccessibilityManager.ACCESSIBILITY_BUTTON); + final int requestingServices = a11yButtonTargets.size(); + + // If accessibility button is floating menu mode, click and long click state should be + // disabled. + if (mAccessibilityButtonModeObserver.getCurrentAccessibilityButtonMode() + == ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU) { + return 0; + } + + return (requestingServices >= 1 ? SYSUI_STATE_A11Y_BUTTON_CLICKABLE : 0) + | (requestingServices >= 2 ? SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE : 0); + } + + public interface NavA11yEventListener { + void updateAccessibilityServicesState(); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java index 0429c022234d4..472f1f1245e12 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java @@ -101,7 +101,7 @@ public class NavigationBarController implements CommandQueue commandQueue, @Main Handler mainHandler, ConfigurationController configurationController, - NavBarHelper navBarHelper, + NavigationBarA11yHelper navigationBarA11yHelper, TaskbarDelegate taskbarDelegate, NavigationBar.Factory navigationBarFactory, DumpManager dumpManager, @@ -117,7 +117,7 @@ public class NavigationBarController implements mNavMode = navigationModeController.addListener(this); mTaskbarDelegate = taskbarDelegate; mTaskbarDelegate.setDependencies(commandQueue, overviewProxyService, - navBarHelper, navigationModeController, sysUiFlagsContainer, + navigationBarA11yHelper, navigationModeController, sysUiFlagsContainer, dumpManager, autoHideController, lightBarController); mIsTablet = isTablet(mContext); dumpManager.registerDumpable(this); diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java index 3d58a5a812518..089423fd72861 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java @@ -43,8 +43,6 @@ import android.content.res.Configuration; import android.hardware.display.DisplayManager; import android.inputmethodservice.InputMethodService; import android.os.IBinder; -import android.os.RemoteException; -import android.util.Log; import android.view.Display; import android.view.InsetsVisibilities; import android.view.View; @@ -78,13 +76,12 @@ import javax.inject.Singleton; public class TaskbarDelegate implements CommandQueue.Callbacks, OverviewProxyService.OverviewProxyListener, NavigationModeController.ModeChangedListener, ComponentCallbacks, Dumpable { - private static final String TAG = TaskbarDelegate.class.getSimpleName(); private final EdgeBackGestureHandler mEdgeBackGestureHandler; - private boolean mInitialized; + private CommandQueue mCommandQueue; private OverviewProxyService mOverviewProxyService; - private NavBarHelper mNavBarHelper; + private NavigationBarA11yHelper mNavigationBarA11yHelper; private NavigationModeController mNavigationModeController; private SysUiState mSysUiState; private AutoHideController mAutoHideController; @@ -92,18 +89,8 @@ public class TaskbarDelegate implements CommandQueue.Callbacks, private LightBarTransitionsController mLightBarTransitionsController; private int mDisplayId; private int mNavigationIconHints; - private final NavBarHelper.NavbarTaskbarStateUpdater mNavbarTaskbarStateUpdater = - new NavBarHelper.NavbarTaskbarStateUpdater() { - @Override - public void updateAccessibilityServicesState() { - updateSysuiFlags(); - } - - @Override - public void updateAssistantAvailable(boolean available) { - updateAssistantAvailability(available); - } - }; + private final NavigationBarA11yHelper.NavA11yEventListener mNavA11yEventListener = + this::updateSysuiFlags; private int mDisabledFlags; private @WindowVisibleState int mTaskBarWindowState = WINDOW_STATE_SHOWING; private @Behavior int mBehavior; @@ -143,7 +130,7 @@ public class TaskbarDelegate implements CommandQueue.Callbacks, public void setDependencies(CommandQueue commandQueue, OverviewProxyService overviewProxyService, - NavBarHelper navBarHelper, + NavigationBarA11yHelper navigationBarA11yHelper, NavigationModeController navigationModeController, SysUiState sysUiState, DumpManager dumpManager, AutoHideController autoHideController, @@ -151,7 +138,7 @@ public class TaskbarDelegate implements CommandQueue.Callbacks, // TODO: adding this in the ctor results in a dagger dependency cycle :( mCommandQueue = commandQueue; mOverviewProxyService = overviewProxyService; - mNavBarHelper = navBarHelper; + mNavigationBarA11yHelper = navigationBarA11yHelper; mNavigationModeController = navigationModeController; mSysUiState = sysUiState; dumpManager.registerDumpable(this); @@ -183,16 +170,12 @@ public class TaskbarDelegate implements CommandQueue.Callbacks, } public void init(int displayId) { - if (mInitialized) { - return; - } mDisplayId = displayId; mCommandQueue.addCallback(this); mOverviewProxyService.addCallback(this); mEdgeBackGestureHandler.onNavigationModeChanged( mNavigationModeController.addListener(this)); - mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); - mNavBarHelper.init(mContext); + mNavigationBarA11yHelper.registerA11yEventListener(mNavA11yEventListener); mEdgeBackGestureHandler.onNavBarAttached(); // Initialize component callback Display display = mDisplayManager.getDisplay(displayId); @@ -202,31 +185,29 @@ public class TaskbarDelegate implements CommandQueue.Callbacks, updateSysuiFlags(); mAutoHideController.setNavigationBar(mAutoHideUiElement); mLightBarController.setNavigationBar(mLightBarTransitionsController); - mInitialized = true; } public void destroy() { - if (!mInitialized) { - return; - } mCommandQueue.removeCallback(this); mOverviewProxyService.removeCallback(this); mNavigationModeController.removeListener(this); - mNavBarHelper.removeNavTaskStateUpdater(mNavbarTaskbarStateUpdater); - mNavBarHelper.destroy(); + mNavigationBarA11yHelper.removeA11yEventListener(mNavA11yEventListener); mEdgeBackGestureHandler.onNavBarDetached(); if (mWindowContext != null) { mWindowContext.unregisterComponentCallbacks(this); mWindowContext = null; } mAutoHideController.setNavigationBar(null); +//<<<<<<< HEAD mLightBarTransitionsController.destroy(mContext); mLightBarController.setNavigationBar(null); - mInitialized = false; +// mInitialized = false; +//======= +//>>>>>>> 2d145412fc44 (Revert "Extract assistant logic from NavigationBar to share with Taskbar") } private void updateSysuiFlags() { - int a11yFlags = mNavBarHelper.getA11yButtonState(); + int a11yFlags = mNavigationBarA11yHelper.getA11yButtonState(); boolean clickable = (a11yFlags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0; boolean longClickable = (a11yFlags & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE) != 0; @@ -250,18 +231,6 @@ public class TaskbarDelegate implements CommandQueue.Callbacks, .commitUpdate(mDisplayId); } - private void updateAssistantAvailability(boolean assistantAvailable) { - if (mOverviewProxyService.getProxy() == null) { - return; - } - - try { - mOverviewProxyService.getProxy().onAssistantAvailable(assistantAvailable); - } catch (RemoteException e) { - Log.e(TAG, "onAssistantAvailable() failed, available: " + assistantAvailable, e); - } - } - @Override public void setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition, boolean showImeSwitcher) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java deleted file mode 100644 index 734faec4ec740..0000000000000 --- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (C) 2021 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.systemui.navigationbar; - -import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.content.ComponentName; -import android.view.accessibility.AccessibilityManager; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.systemui.SysuiTestCase; -import com.android.systemui.accessibility.AccessibilityButtonModeObserver; -import com.android.systemui.assist.AssistManager; -import com.android.systemui.dump.DumpManager; -import com.android.systemui.recents.OverviewProxyService; -import com.android.systemui.settings.UserTracker; -import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import dagger.Lazy; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class NavBarHelperTest extends SysuiTestCase { - - @Mock - AccessibilityManager mAccessibilityManager; - @Mock - AccessibilityManagerWrapper mAccessibilityManagerWrapper; - @Mock - AccessibilityButtonModeObserver mAccessibilityButtonModeObserver; - @Mock - OverviewProxyService mOverviewProxyService; - @Mock - Lazy mAssistManagerLazy; - @Mock - AssistManager mAssistManager; - @Mock - NavigationModeController mNavigationModeController; - @Mock - UserTracker mUserTracker; - @Mock - ComponentName mAssistantComponent; - @Mock - DumpManager mDumpManager; - @Mock - NavBarHelper.NavbarTaskbarStateUpdater mNavbarTaskbarStateUpdater; - - private NavBarHelper mNavBarHelper; - - @Before - public void setup() { - MockitoAnnotations.initMocks(this); - when(mAssistManagerLazy.get()).thenReturn(mAssistManager); - when(mAssistManager.getAssistInfoForUser(anyInt())).thenReturn(mAssistantComponent); - when(mUserTracker.getUserId()).thenReturn(1); - - mNavBarHelper = new NavBarHelper(mAccessibilityManager, - mAccessibilityManagerWrapper, mAccessibilityButtonModeObserver, - mOverviewProxyService, mAssistManagerLazy, mNavigationModeController, - mUserTracker, mDumpManager); - - } - - @Test - public void registerListenersInCtor() { - verify(mAccessibilityButtonModeObserver, times(1)).addListener(mNavBarHelper); - verify(mNavigationModeController, times(1)).addListener(mNavBarHelper); - verify(mOverviewProxyService, times(1)).addCallback(mNavBarHelper); - } - - @Test - public void registerAssistantContentObserver() { - mNavBarHelper.init(mContext); - verify(mAssistManager, times(1)).getAssistInfoForUser(anyInt()); - } - - @Test - public void callbacksFiredWhenRegistering() { - mNavBarHelper.init(mContext); - mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); - verify(mNavbarTaskbarStateUpdater, times(1)) - .updateAccessibilityServicesState(); - verify(mNavbarTaskbarStateUpdater, times(1)) - .updateAssistantAvailable(anyBoolean()); - } - - @Test - public void assistantCallbacksFiredAfterConnecting() { - mNavBarHelper.init(mContext); - // 1st set of callbacks get called when registering - mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); - - mNavBarHelper.onConnectionChanged(false); - // assert no more callbacks fired - verify(mNavbarTaskbarStateUpdater, times(1)) - .updateAccessibilityServicesState(); - verify(mNavbarTaskbarStateUpdater, times(1)) - .updateAssistantAvailable(anyBoolean()); - - mNavBarHelper.onConnectionChanged(true); - // assert no more callbacks fired - verify(mNavbarTaskbarStateUpdater, times(1)) - .updateAccessibilityServicesState(); - verify(mNavbarTaskbarStateUpdater, times(2)) - .updateAssistantAvailable(anyBoolean()); - } - - @Test - public void a11yCallbacksFiredAfterModeChange() { - mNavBarHelper.init(mContext); - // 1st set of callbacks get called when registering - mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); - - mNavBarHelper.onAccessibilityButtonModeChanged(0); - verify(mNavbarTaskbarStateUpdater, times(2)) - .updateAccessibilityServicesState(); - verify(mNavbarTaskbarStateUpdater, times(1)) - .updateAssistantAvailable(anyBoolean()); - } - - @Test - public void assistantCallbacksFiredAfterNavModeChange() { - mNavBarHelper.init(mContext); - // 1st set of callbacks get called when registering - mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); - - mNavBarHelper.onNavigationModeChanged(0); - verify(mNavbarTaskbarStateUpdater, times(1)) - .updateAccessibilityServicesState(); - verify(mNavbarTaskbarStateUpdater, times(2)) - .updateAssistantAvailable(anyBoolean()); - } - - @Test - public void removeListenerNoCallbacksFired() { - mNavBarHelper.init(mContext); - // 1st set of callbacks get called when registering - mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); - - // Remove listener - mNavBarHelper.removeNavTaskStateUpdater(mNavbarTaskbarStateUpdater); - - // Would have fired 2nd callback if not removed - mNavBarHelper.onAccessibilityButtonModeChanged(0); - - // assert no more callbacks fired - verify(mNavbarTaskbarStateUpdater, times(1)) - .updateAccessibilityServicesState(); - verify(mNavbarTaskbarStateUpdater, times(1)) - .updateAssistantAvailable(anyBoolean()); - } -} diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java index 9d2541c0150fe..62832205a0979 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java @@ -83,7 +83,7 @@ public class NavigationBarControllerTest extends SysuiTestCase { mCommandQueue, Dependency.get(Dependency.MAIN_HANDLER), mock(ConfigurationController.class), - mock(NavBarHelper.class), + mock(NavigationBarA11yHelper.class), mock(TaskbarDelegate.class), mNavigationBarFactory, mock(DumpManager.class), 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 776b6aa2ef380..223ffbd7bba5e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java @@ -131,7 +131,7 @@ public class NavigationBarTest extends SysuiTestCase { @Mock EdgeBackGestureHandler mEdgeBackGestureHandler; @Mock - NavBarHelper mNavBarHelper; + NavigationBarA11yHelper mNavigationBarA11yHelper; @Mock private LightBarController mLightBarController; @Mock @@ -220,7 +220,6 @@ public class NavigationBarTest extends SysuiTestCase { new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_SYSTEMUI) .setLong(HOME_BUTTON_LONG_PRESS_DURATION_MS, 100) .build()); - when(mNavBarHelper.getLongPressHomeEnabled()).thenReturn(true); mNavigationBar.onViewAttachedToWindow(mNavigationBar.createView(null)); mNavigationBar.onHomeTouch(mNavigationBar.getView(), MotionEvent.obtain( @@ -285,14 +284,14 @@ public class NavigationBarTest extends SysuiTestCase { public void testA11yEventAfterDetach() { View v = mNavigationBar.createView(null); mNavigationBar.onViewAttachedToWindow(v); - verify(mNavBarHelper).registerNavTaskStateUpdater(any( - NavBarHelper.NavbarTaskbarStateUpdater.class)); + verify(mNavigationBarA11yHelper).registerA11yEventListener(any( + NavigationBarA11yHelper.NavA11yEventListener.class)); mNavigationBar.onViewDetachedFromWindow(v); - verify(mNavBarHelper).removeNavTaskStateUpdater(any( - NavBarHelper.NavbarTaskbarStateUpdater.class)); + verify(mNavigationBarA11yHelper).removeA11yEventListener(any( + NavigationBarA11yHelper.NavA11yEventListener.class)); // Should be safe even though the internal view is now null. - mNavigationBar.updateAcessibilityStateFlags(); + mNavigationBar.updateAccessibilityServicesState(); } private NavigationBar createNavBar(Context context) { @@ -322,7 +321,7 @@ public class NavigationBarTest extends SysuiTestCase { mHandler, mock(NavigationBarOverlayController.class), mUiEventLogger, - mNavBarHelper, + mNavigationBarA11yHelper, mock(UserTracker.class), mLightBarController, mLightBarcontrollerFactory,