diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl index 0657c0e1725c4..de9558ebca47b 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl @@ -76,25 +76,18 @@ oneway interface IOverviewProxy { */ void onSplitScreenSecondaryBoundsChanged(in Rect bounds, in Rect insets) = 17; - /** - * Sent when IME status changes - */ - void onImeWindowStatusChanged(int displayId, IBinder token, int vis, int backDisposition, - boolean showImeSwitcher) = 18; - /** * Sent when suggested rotation button could be shown */ - void onRotationProposal(int rotation, boolean isValid) = 19; - + void onRotationProposal(int rotation, boolean isValid) = 18; /** * Sent when disable flags change */ - void disable(int displayId, int state1, int state2, boolean animate) = 20; + void disable(int displayId, int state1, int state2, boolean animate) = 19; /** * Sent when behavior changes. See WindowInsetsController#@Behavior */ - void onSystemBarAttributesChanged(int displayId, int behavior) = 21; + void onSystemBarAttributesChanged(int displayId, int behavior) = 20; } diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java index 7e9832aa34195..a624f06110e61 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java @@ -16,11 +16,14 @@ package com.android.systemui.shared.recents.utilities; +import static android.app.StatusBarManager.NAVIGATION_HINT_BACK_ALT; +import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SHOWN; + import android.graphics.Color; +import android.inputmethodservice.InputMethodService; import android.os.Handler; import android.os.Message; import android.view.Surface; -import android.view.View; /* Common code */ public class Utilities { @@ -77,4 +80,34 @@ public class Utilities { public static float clamp(float value, float min, float max) { return Math.max(min, Math.min(max, value)); } + + /** + * @return updated set of flags from InputMethodService based off {@param oldHints} + * Leaves original hints unmodified + */ + public static int calculateBackDispositionHints(int oldHints, int backDisposition, + boolean imeShown, boolean showImeSwitcher) { + int hints = oldHints; + switch (backDisposition) { + case InputMethodService.BACK_DISPOSITION_DEFAULT: + case InputMethodService.BACK_DISPOSITION_WILL_NOT_DISMISS: + case InputMethodService.BACK_DISPOSITION_WILL_DISMISS: + if (imeShown) { + hints |= NAVIGATION_HINT_BACK_ALT; + } else { + hints &= ~NAVIGATION_HINT_BACK_ALT; + } + break; + case InputMethodService.BACK_DISPOSITION_ADJUST_NOTHING: + hints &= ~NAVIGATION_HINT_BACK_ALT; + break; + } + if (showImeSwitcher) { + hints |= NAVIGATION_HINT_IME_SHOWN; + } else { + hints &= ~NAVIGATION_HINT_IME_SHOWN; + } + + return hints; + } } diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java index c468e416f8a57..153708a19d220 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java @@ -112,6 +112,8 @@ public class QuickStepContract { public static final int SYSUI_STATE_IME_SHOWING = 1 << 18; // The window magnification is overlapped with system gesture insets at the bottom. public static final int SYSUI_STATE_MAGNIFICATION_OVERLAP = 1 << 19; + // ImeSwitcher is showing + public static final int SYSUI_STATE_IME_SWITCHER_SHOWING = 1 << 20; @Retention(RetentionPolicy.SOURCE) @IntDef({SYSUI_STATE_SCREEN_PINNING, @@ -133,7 +135,8 @@ public class QuickStepContract { SYSUI_STATE_ONE_HANDED_ACTIVE, SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY, SYSUI_STATE_IME_SHOWING, - SYSUI_STATE_MAGNIFICATION_OVERLAP + SYSUI_STATE_MAGNIFICATION_OVERLAP, + SYSUI_STATE_IME_SWITCHER_SHOWING }) public @interface SystemUiStateFlags {} @@ -162,6 +165,7 @@ public class QuickStepContract { ? "allow_gesture" : ""); str.add((flags & SYSUI_STATE_IME_SHOWING) != 0 ? "ime_visible" : ""); str.add((flags & SYSUI_STATE_MAGNIFICATION_OVERLAP) != 0 ? "magnification_overlap" : ""); + str.add((flags & SYSUI_STATE_IME_SWITCHER_SHOWING) != 0 ? "ime_switcher_showing" : ""); return str.toString(); } diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java index 746621dfda274..9a121ba8dc2dc 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java @@ -60,6 +60,7 @@ import com.android.systemui.doze.AlwaysOnDisplayPolicy; import com.android.systemui.dump.DumpManager; import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.model.SysUiState; +import com.android.systemui.navigationbar.NavigationBarA11yHelper; import com.android.systemui.navigationbar.NavigationBarController; import com.android.systemui.navigationbar.NavigationBarOverlayController; import com.android.systemui.navigationbar.NavigationModeController; @@ -231,7 +232,8 @@ public class DependencyProvider { @Main Handler mainHandler, UiEventLogger uiEventLogger, NavigationBarOverlayController navBarOverlayController, - ConfigurationController configurationController) { + ConfigurationController configurationController, + NavigationBarA11yHelper navigationBarA11yHelper) { return new NavigationBarController(context, windowManager, assistManagerLazy, @@ -256,7 +258,8 @@ public class DependencyProvider { mainHandler, uiEventLogger, navBarOverlayController, - configurationController); + configurationController, + navigationBarA11yHelper); } /** */ diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java index dda1029f61545..2d65685061b9d 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java @@ -44,6 +44,7 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SHOWING; +import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SWITCHER_SHOWING; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN; import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT; import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT; @@ -54,9 +55,7 @@ import static com.android.systemui.statusbar.phone.BarTransitions.TransitionMode import static com.android.systemui.statusbar.phone.StatusBar.DEBUG_WINDOW_STATE; import static com.android.systemui.statusbar.phone.StatusBar.dumpBarTransitions; -import android.accessibilityservice.AccessibilityServiceInfo; import android.annotation.IdRes; -import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityTaskManager; import android.app.IActivityTaskManager; @@ -101,7 +100,6 @@ import android.view.WindowInsetsController.Behavior; import android.view.WindowManager; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; -import android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener; import android.view.inputmethod.InputMethodManager; import androidx.annotation.VisibleForTesting; @@ -129,6 +127,7 @@ import com.android.systemui.plugins.DarkIconDispatcher; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.recents.OverviewProxyService; import com.android.systemui.recents.Recents; +import com.android.systemui.shared.recents.utilities.Utilities; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.QuickStepContract; import com.android.systemui.statusbar.AutoHideUiElement; @@ -149,7 +148,6 @@ import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; import com.android.wm.shell.pip.Pip; import java.io.PrintWriter; -import java.util.List; import java.util.Locale; import java.util.Optional; import java.util.function.Consumer; @@ -160,8 +158,7 @@ import dagger.Lazy; * Contains logic for a navigation bar view. */ public class NavigationBar implements View.OnAttachStateChangeListener, - Callbacks, NavigationModeController.ModeChangedListener, - AccessibilityButtonModeObserver.ModeChangedListener { + Callbacks, NavigationModeController.ModeChangedListener { public static final String TAG = "NavigationBar"; private static final boolean DEBUG = false; @@ -178,7 +175,6 @@ public class NavigationBar implements View.OnAttachStateChangeListener, private final Context mContext; private final WindowManager mWindowManager; private final AccessibilityManager mAccessibilityManager; - private final AccessibilityManagerWrapper mAccessibilityManagerWrapper; private final DeviceProvisionedController mDeviceProvisionedController; private final StatusBarStateController mStatusBarStateController; private final MetricsLogger mMetricsLogger; @@ -199,6 +195,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, private final Handler mHandler; private final NavigationBarOverlayController mNavbarOverlayController; private final UiEventLogger mUiEventLogger; + private final NavigationBarA11yHelper mNavigationBarA11yHelper; private Bundle mSavedState; private NavigationBarView mNavigationBarView; @@ -232,7 +229,6 @@ public class NavigationBar implements View.OnAttachStateChangeListener, private boolean mTransientShown; private int mNavBarMode = NAV_BAR_MODE_3BUTTON; - private int mA11yBtnMode; private LightBarController mLightBarController; private AutoHideController mAutoHideController; @@ -459,11 +455,11 @@ public class NavigationBar implements View.OnAttachStateChangeListener, SystemActions systemActions, @Main Handler mainHandler, NavigationBarOverlayController navbarOverlayController, - UiEventLogger uiEventLogger) { + UiEventLogger uiEventLogger, + NavigationBarA11yHelper navigationBarA11yHelper) { mContext = context; mWindowManager = windowManager; mAccessibilityManager = accessibilityManager; - mAccessibilityManagerWrapper = accessibilityManagerWrapper; mDeviceProvisionedController = deviceProvisionedController; mStatusBarStateController = statusBarStateController; mMetricsLogger = metricsLogger; @@ -484,10 +480,8 @@ public class NavigationBar implements View.OnAttachStateChangeListener, mHandler = mainHandler; mNavbarOverlayController = navbarOverlayController; mUiEventLogger = uiEventLogger; - + mNavigationBarA11yHelper = navigationBarA11yHelper; mNavBarMode = mNavigationModeController.addListener(this); - mAccessibilityButtonModeObserver.addListener(this); - mA11yBtnMode = mAccessibilityButtonModeObserver.getCurrentAccessibilityButtonMode(); } public NavigationBarView getView() { @@ -578,9 +572,8 @@ public class NavigationBar implements View.OnAttachStateChangeListener, mContext.getSystemService(WindowManager.class).removeViewImmediate( mNavigationBarView.getRootView()); mNavigationModeController.removeListener(this); - mAccessibilityButtonModeObserver.removeListener(this); - mAccessibilityManagerWrapper.removeCallback(mAccessibilityListener); + mNavigationBarA11yHelper.removeA11yEventListener(mAccessibilityListener); mContentResolver.unregisterContentObserver(mAssistContentObserver); mDeviceProvisionedController.removeCallback(mUserSetupListener); @@ -601,7 +594,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, mNavigationBarView.setWindowVisible(isNavBarWindowVisible()); mNavigationBarView.setBehavior(mBehavior); - mAccessibilityManagerWrapper.addCallback(mAccessibilityListener); + mNavigationBarA11yHelper.registerA11yEventListener(mAccessibilityListener); mSplitScreenOptional.ifPresent(mNavigationBarView::registerDockedListener); mPipOptional.ifPresent(mNavigationBarView::registerPipExclusionBoundsChangeListener); @@ -861,26 +854,8 @@ public class NavigationBar implements View.OnAttachStateChangeListener, return; } boolean imeShown = (vis & InputMethodService.IME_VISIBLE) != 0; - int hints = mNavigationIconHints; - switch (backDisposition) { - case InputMethodService.BACK_DISPOSITION_DEFAULT: - case InputMethodService.BACK_DISPOSITION_WILL_NOT_DISMISS: - case InputMethodService.BACK_DISPOSITION_WILL_DISMISS: - if (imeShown) { - hints |= NAVIGATION_HINT_BACK_ALT; - } else { - hints &= ~NAVIGATION_HINT_BACK_ALT; - } - break; - case InputMethodService.BACK_DISPOSITION_ADJUST_NOTHING: - hints &= ~NAVIGATION_HINT_BACK_ALT; - break; - } - if (showImeSwitcher) { - hints |= NAVIGATION_HINT_IME_SHOWN; - } else { - hints &= ~NAVIGATION_HINT_IME_SHOWN; - } + int hints = Utilities.calculateBackDispositionHints(mNavigationIconHints, backDisposition, + imeShown, showImeSwitcher); if (hints == mNavigationIconHints) return; mNavigationIconHints = hints; @@ -1140,7 +1115,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, ButtonDispatcher accessibilityButton = mNavigationBarView.getAccessibilityButton(); accessibilityButton.setOnClickListener(this::onAccessibilityClick); accessibilityButton.setOnLongClickListener(this::onAccessibilityLongClick); - updateAccessibilityServicesState(mAccessibilityManager); + updateAccessibilityServicesState(); ButtonDispatcher imeSwitcherButton = mNavigationBarView.getImeSwitchButton(); imeSwitcherButton.setOnClickListener(this::onImeSwitcherClick); @@ -1361,9 +1336,8 @@ public class NavigationBar implements View.OnAttachStateChangeListener, return true; } - void updateAccessibilityServicesState(AccessibilityManager accessibilityManager) { - boolean[] feedbackEnabled = new boolean[1]; - int a11yFlags = getA11yButtonState(feedbackEnabled); + void updateAccessibilityServicesState() { + int a11yFlags = mNavigationBarA11yHelper.getA11yButtonState(); boolean clickable = (a11yFlags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0; boolean longClickable = (a11yFlags & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE) != 0; @@ -1381,7 +1355,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, public void updateSystemUiStateFlags(int a11yFlags) { if (a11yFlags < 0) { - a11yFlags = getA11yButtonState(null); + a11yFlags = mNavigationBarA11yHelper.getA11yButtonState(); } boolean clickable = (a11yFlags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0; boolean longClickable = (a11yFlags & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE) != 0; @@ -1391,6 +1365,8 @@ public class NavigationBar implements View.OnAttachStateChangeListener, .setFlag(SYSUI_STATE_NAV_BAR_HIDDEN, !isNavBarWindowVisible()) .setFlag(SYSUI_STATE_IME_SHOWING, (mNavigationIconHints & NAVIGATION_HINT_BACK_ALT) != 0) + .setFlag(SYSUI_STATE_IME_SWITCHER_SHOWING, + (mNavigationIconHints & NAVIGATION_HINT_IME_SHOWN) != 0) .setFlag(SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY, allowSystemGestureIgnoringBarVisibility()) .commitUpdate(mDisplayId); @@ -1406,44 +1382,6 @@ public class NavigationBar implements View.OnAttachStateChangeListener, } } - /** - * Returns the system UI flags corresponding the the current accessibility button state - * - * @param outFeedbackEnabled if non-null, sets it to true if accessibility feedback is enabled. - */ - public int getA11yButtonState(@Nullable boolean[] outFeedbackEnabled) { - boolean feedbackEnabled = false; - // AccessibilityManagerService resolves services for the current user since the local - // AccessibilityManager is created from a Context with the INTERACT_ACROSS_USERS permission - final List services = - mAccessibilityManager.getEnabledAccessibilityServiceList( - AccessibilityServiceInfo.FEEDBACK_ALL_MASK); - final List a11yButtonTargets = - mAccessibilityManager.getAccessibilityShortcutTargets( - AccessibilityManager.ACCESSIBILITY_BUTTON); - final int requestingServices = a11yButtonTargets.size(); - for (int i = services.size() - 1; i >= 0; --i) { - AccessibilityServiceInfo info = services.get(i); - if (info.feedbackType != 0 && info.feedbackType != - AccessibilityServiceInfo.FEEDBACK_GENERIC) { - feedbackEnabled = true; - } - } - - if (outFeedbackEnabled != null) { - outFeedbackEnabled[0] = feedbackEnabled; - } - - // If accessibility button is floating menu mode, click and long click state should be - // disabled. - if (mA11yBtnMode == 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); - } - private void updateAssistantEntrypoints() { mAssistantAvailable = mAssistManagerLazy.get() .getAssistInfoForUser(UserHandle.USER_CURRENT) != null; @@ -1539,12 +1477,6 @@ public class NavigationBar implements View.OnAttachStateChangeListener, } } - @Override - public void onAccessibilityButtonModeChanged(int mode) { - mA11yBtnMode = mode; - updateAccessibilityServicesState(mAccessibilityManager); - } - public void disableAnimationsDuringHide(long delay) { mNavigationBarView.setLayoutTransitionsEnabled(false); mHandler.postDelayed(mEnableLayoutTransitions, @@ -1569,7 +1501,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, mNavigationBarView.getBarTransitions().finishAnimations(); } - private final AccessibilityServicesStateChangeListener mAccessibilityListener = + private final NavigationBarA11yHelper.NavA11yEventListener mAccessibilityListener = this::updateAccessibilityServicesState; private boolean canShowSecondaryHandle() { @@ -1600,7 +1532,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, } if (Intent.ACTION_USER_SWITCHED.equals(action)) { // The accessibility settings may be different for the new user - updateAccessibilityServicesState(mAccessibilityManager); + updateAccessibilityServicesState(); } } }; 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..35e1a9dfed334 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarA11yHelper.java @@ -0,0 +1,89 @@ +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 int mA11yBtnMode; + private final AccessibilityManager mAccessibilityManager; + private final List mA11yEventListeners = new ArrayList<>(); + + @Inject + public NavigationBarA11yHelper(AccessibilityManager accessibilityManager, + AccessibilityManagerWrapper accessibilityManagerWrapper, + AccessibilityButtonModeObserver accessibilityButtonModeObserver) { + mAccessibilityManager = accessibilityManager; + mA11yBtnMode = accessibilityButtonModeObserver.getCurrentAccessibilityButtonMode(); + accessibilityManagerWrapper.addCallback( + accessibilityManager1 -> NavigationBarA11yHelper.this.dispatchEventUpdate()); + accessibilityButtonModeObserver.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) { + mA11yBtnMode = 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 (mA11yBtnMode == 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 8b5a537ba2425..30eb645e43928 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java @@ -111,6 +111,7 @@ public class NavigationBarController implements Callbacks, private final SystemActions mSystemActions; private final UiEventLogger mUiEventLogger; private final Handler mHandler; + private final NavigationBarA11yHelper mNavigationBarA11yHelper; private final DisplayManager mDisplayManager; private final NavigationBarOverlayController mNavBarOverlayController; private final TaskbarDelegate mTaskbarDelegate; @@ -151,7 +152,8 @@ public class NavigationBarController implements Callbacks, @Main Handler mainHandler, UiEventLogger uiEventLogger, NavigationBarOverlayController navBarOverlayController, - ConfigurationController configurationController) { + ConfigurationController configurationController, + NavigationBarA11yHelper navigationBarA11yHelper) { mContext = context; mWindowManager = windowManager; mAssistManagerLazy = assistManagerLazy; @@ -175,6 +177,7 @@ public class NavigationBarController implements Callbacks, mSystemActions = systemActions; mUiEventLogger = uiEventLogger; mHandler = mainHandler; + mNavigationBarA11yHelper = navigationBarA11yHelper; mDisplayManager = mContext.getSystemService(DisplayManager.class); commandQueue.addCallback(this); configurationController.addCallback(this); @@ -182,7 +185,8 @@ public class NavigationBarController implements Callbacks, mNavBarOverlayController = navBarOverlayController; mNavMode = mNavigationModeController.addListener(this); mNavigationModeController.addListener(this); - mTaskbarDelegate = new TaskbarDelegate(mOverviewProxyService); + mTaskbarDelegate = new TaskbarDelegate(mOverviewProxyService, + navigationBarA11yHelper, mSysUiFlagsContainer); mIsTablet = isTablet(mContext.getResources().getConfiguration()); } @@ -241,10 +245,12 @@ public class NavigationBarController implements Callbacks, // Remove navigation bar when taskbar is showing, currently only for 3 button mode removeNavigationBar(mContext.getDisplayId()); mCommandQueue.addCallback(mTaskbarDelegate); + mTaskbarDelegate.init(mContext.getDisplayId()); } else if (mNavigationBars.get(mContext.getDisplayId()) == null) { // Add navigation bar after taskbar goes away createNavigationBar(mContext.getDisplay(), null, null); mCommandQueue.removeCallback(mTaskbarDelegate); + mTaskbarDelegate.destroy(); } return true; @@ -361,7 +367,8 @@ public class NavigationBarController implements Callbacks, mSystemActions, mHandler, mNavBarOverlayController, - mUiEventLogger); + mUiEventLogger, + mNavigationBarA11yHelper); mNavigationBars.put(displayId, navBar); View navigationBarView = navBar.createView(savedState); diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java index 5d39ffe91c923..e9674c9acedeb 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java @@ -16,25 +16,76 @@ package com.android.systemui.navigationbar; +import static android.app.StatusBarManager.NAVIGATION_HINT_BACK_ALT; +import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SHOWN; + +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 static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SHOWING; +import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SWITCHER_SHOWING; + +import android.inputmethodservice.InputMethodService; import android.os.IBinder; import com.android.internal.view.AppearanceRegion; +import com.android.systemui.model.SysUiState; import com.android.systemui.recents.OverviewProxyService; +import com.android.systemui.shared.recents.utilities.Utilities; import com.android.systemui.statusbar.CommandQueue; public class TaskbarDelegate implements CommandQueue.Callbacks { private final OverviewProxyService mOverviewProxyService; + private final NavigationBarA11yHelper mNavigationBarA11yHelper; + private final SysUiState mSysUiState; + private int mDisplayId; + private int mNavigationIconHints; + private final NavigationBarA11yHelper.NavA11yEventListener mNavA11yEventListener = + this::updateSysuiFlags; - public TaskbarDelegate(OverviewProxyService overviewProxyService) { + public TaskbarDelegate(OverviewProxyService overviewProxyService, + NavigationBarA11yHelper navigationBarA11yHelper, + SysUiState sysUiState) { mOverviewProxyService = overviewProxyService; + mNavigationBarA11yHelper = navigationBarA11yHelper; + mSysUiState = sysUiState; + } + + public void destroy() { + mNavigationBarA11yHelper.removeA11yEventListener(mNavA11yEventListener); + } + + public void init(int displayId) { + mDisplayId = displayId; + mNavigationBarA11yHelper.registerA11yEventListener(mNavA11yEventListener); + // Set initial state for any listeners + updateSysuiFlags(); + } + + private void updateSysuiFlags() { + int a11yFlags = mNavigationBarA11yHelper.getA11yButtonState(); + boolean clickable = (a11yFlags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0; + boolean longClickable = (a11yFlags & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE) != 0; + + mSysUiState.setFlag(SYSUI_STATE_A11Y_BUTTON_CLICKABLE, clickable) + .setFlag(SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE, longClickable) + .setFlag(SYSUI_STATE_IME_SHOWING, + (mNavigationIconHints & NAVIGATION_HINT_BACK_ALT) != 0) + .setFlag(SYSUI_STATE_IME_SWITCHER_SHOWING, + (mNavigationIconHints & NAVIGATION_HINT_IME_SHOWN) != 0) + .commitUpdate(mDisplayId); } @Override public void setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition, boolean showImeSwitcher) { - mOverviewProxyService.notifyImeWindowStatus(displayId, token, vis, backDisposition, - showImeSwitcher); + boolean imeShown = (vis & InputMethodService.IME_VISIBLE) != 0; + int hints = Utilities.calculateBackDispositionHints(mNavigationIconHints, backDisposition, + imeShown, showImeSwitcher); + if (hints != mNavigationIconHints) { + mNavigationIconHints = hints; + updateSysuiFlags(); + } } @Override diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java index 56d45d3117d69..c0831a4688172 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java +++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java @@ -974,20 +974,6 @@ public class OverviewProxyService extends CurrentUserTracker implements } } - public void notifyImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition, - boolean showImeSwitcher) { - try { - if (mOverviewProxy != null) { - mOverviewProxy.onImeWindowStatusChanged(displayId, token, vis, backDisposition, - showImeSwitcher); - } else { - Log.e(TAG_OPS, "Failed to get overview proxy for setting IME status."); - } - } catch (RemoteException e) { - Log.e(TAG_OPS, "Failed to call notifyImeWindowStatus()", e); - } - } - public void onRotationProposal(int rotation, boolean isValid) { try { if (mOverviewProxy != null) { 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 da63b8a3ca4b5..3b5431f1445ac 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java @@ -108,7 +108,8 @@ public class NavigationBarControllerTest extends SysuiTestCase { Dependency.get(Dependency.MAIN_HANDLER), mock(UiEventLogger.class), mock(NavigationBarOverlayController.class), - mock(ConfigurationController.class))); + mock(ConfigurationController.class), + mock(NavigationBarA11yHelper.class))); initializeNavigationBars(); } 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 4ec45b444c465..6359ca835e8fa 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java @@ -276,7 +276,8 @@ public class NavigationBarTest extends SysuiTestCase { mock(SystemActions.class), mHandler, mock(NavigationBarOverlayController.class), - mUiEventLogger)); + mUiEventLogger, + mock(NavigationBarA11yHelper.class))); } private void processAllMessages() {