From a25070917a62074d3506b0ded058c3e33390c195 Mon Sep 17 00:00:00 2001
From: Yohei Yukawa
Date: Tue, 11 Jan 2022 08:39:58 -0800
Subject: [PATCH] Add a sysprop to disable SysUI's nav buttons when IME is
shown
This CL introduces a new runtime mode where the SysUI no longer
renders the back button and the IME switcher button when the IME is
shown, which is the first milestone to move those buttons to the IME
process.
To enable this mode, run the following commands:
$ adb root
$ adb shell setprop \
persist.sys.ime.can_render_gestural_nav_buttons true
$ adb reboot
Keep in mind that you always need to reboot the device after changing
this sysprop.
Note that only AOSP-based gestural navigation mode is officially
supported by this flag, which is when
com.android.internal.R.integer.config_navBarInteractionMode
is set to
WindowManagerPolicyConstants#NAV_BAR_MODE_GESTURAL.
Note that nav button rendering in the IME process is yet to be done in
subsequent CLs. Hence the expected behavior right now is only one
thing that the SysUI stops rendering the back button and the IME
switcher button any more when the flag takes effect.
The flag is treated as off by default. Hence there should be no
visible behavior changes unless you manually enable it.
Alternatives Considered:
Instead of letting NavigationBarView directly read the sysprop, we
could propagate the information from the InputMethodService to the
SysUI via InputMethodPrivilegedOperations#setImeWindowStatusAsync().
This approach was abandoned because of the following reasons.
* Such a complex mechanism is not necessary for production code.
* There are some ad-hoc invocations of
IMMS#updateSystemUiLocked(0, mBackDisposition),
which makes it difficult to keep IMS and SysUI in sync.
Bug: 205803355
Test: Manually done as follows
1. Build aosp_coral-userdebug and flash it
2. Tap any edit field to show AOSP Keyboard.
3. Confirm that nav buttons are rendered in 3-button nav mode
4. Switch to gestural navigation mode.
5. Confirm that nav buttons are still shown when IME is visible.
6. adb root
7. adb shell setprop \
persist.sys.ime.can_render_gestural_nav_buttons true
8. adb reboot
9. Tap any edit field to show AOSP Keyboard.
10. Confirm that nav buttons are not shown when IME is visible.
11. Switch to 3-button navigation mode.
12. Tap any edit field to show AOSP Keyboard.
13. Confirm that nav buttons are shown again when IME is visible.
14. Switch to gestural navigation mode again.
15. Confirm that nav buttons are not shown when IME is visible.
Change-Id: I7a2e9f08072a97d61b78dddb144282a5728d1407
---
.../InputMethodService.java | 40 +++++++++++++++++++
.../navigationbar/NavigationBarView.java | 24 +++++++++--
2 files changed, 61 insertions(+), 3 deletions(-)
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index afaa085c7cbdd..a5005c5175352 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -54,6 +54,7 @@ import static android.view.WindowInsets.Type.statusBars;
import static java.lang.annotation.RetentionPolicy.SOURCE;
+import android.annotation.AnyThread;
import android.annotation.CallSuper;
import android.annotation.DrawableRes;
import android.annotation.IntDef;
@@ -83,6 +84,7 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.ResultReceiver;
import android.os.SystemClock;
+import android.os.SystemProperties;
import android.os.Trace;
import android.provider.Settings;
import android.text.InputType;
@@ -301,6 +303,44 @@ public class InputMethodService extends AbstractInputMethodService {
static final String TAG = "InputMethodService";
static final boolean DEBUG = false;
+ /**
+ * Key for a boolean value that tells whether {@link InputMethodService} is responsible for
+ * rendering the back button and the IME switcher button or not when the gestural navigation is
+ * enabled.
+ *
+ * This sysprop is just ignored when the gestural navigation mode is not enabled.
+ *
+ *
+ * To avoid complexity that is not necessary for production, you always need to reboot the
+ * device after modifying this flag as follows:
+ *
+ * $ adb root
+ * $ adb shell setprop persist.sys.ime.can_render_gestural_nav_buttons true
+ * $ adb reboot
+ *
+ *
+ */
+ private static final String PROP_CAN_RENDER_GESTURAL_NAV_BUTTONS =
+ "persist.sys.ime.can_render_gestural_nav_buttons";
+
+ /**
+ * Returns whether {@link InputMethodService} is responsible for rendering the back button and
+ * the IME switcher button or not when the gestural navigation is enabled.
+ *
+ * This method is supposed to be used with an assumption that the same value is returned in
+ * other processes. It is developers' responsibility for rebooting the device when the sysprop
+ * is modified.
+ *
+ * @return {@code true} if {@link InputMethodService} is responsible for rendering the back
+ * button and the IME switcher button when the gestural navigation is enabled.
+ *
+ * @hide
+ */
+ @AnyThread
+ public static boolean canImeRenderGesturalNavButtons() {
+ return SystemProperties.getBoolean(PROP_CAN_RENDER_GESTURAL_NAV_BUTTONS, false);
+ }
+
/**
* Allows the system to optimize the back button affordance based on the presence of software
* keyboard.
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
index 5fbdd88b9f668..ac816ba9e8d5c 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
@@ -16,6 +16,7 @@
package com.android.systemui.navigationbar;
+import static android.inputmethodservice.InputMethodService.canImeRenderGesturalNavButtons;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_HOME_DISABLED;
@@ -185,6 +186,17 @@ public class NavigationBarView extends FrameLayout implements
@Nullable
private Rect mOrientedHandleSamplingRegion;
+ /**
+ * {@code true} if the IME can render the back button and the IME switcher button.
+ *
+ * The value must be used when and only when
+ * {@link com.android.systemui.shared.system.QuickStepContract#isGesturalMode(int)} returns
+ * {@code true}
+ *
+ * Cache the value here for better performance.
+ */
+ private final boolean mImeCanRenderGesturalNavButtons = canImeRenderGesturalNavButtons();
+
private class NavTransitionListener implements TransitionListener {
private boolean mBackTransitioning;
private boolean mHomeAppearing;
@@ -760,9 +772,14 @@ public class NavigationBarView extends FrameLayout implements
updateRecentsIcon();
+ boolean isImeRenderingNavButtons = isGesturalMode(mNavBarMode)
+ && mImeCanRenderGesturalNavButtons;
+
// Update IME button visibility, a11y and rotate button always overrides the appearance
- mContextualButtonGroup.setButtonVisibility(R.id.ime_switcher,
- (mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_IME_SHOWN) != 0);
+ boolean disableImeSwitcher =
+ (mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_IME_SHOWN) == 0
+ || isImeRenderingNavButtons;
+ mContextualButtonGroup.setButtonVisibility(R.id.ime_switcher, !disableImeSwitcher);
mBarTransitions.reapplyDarkIntensity();
@@ -777,7 +794,8 @@ public class NavigationBarView extends FrameLayout implements
&& ((mDisabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0);
boolean disableBack = !useAltBack && (mEdgeBackGestureHandler.isHandlingGestures()
- || ((mDisabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0));
+ || ((mDisabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0))
+ || isImeRenderingNavButtons;
// When screen pinning, don't hide back and home when connected service or back and
// recents buttons when disconnected from launcher service in screen pinning mode,