From c98b9c8f407f8acc98490c017ff3862f449c45ba Mon Sep 17 00:00:00 2001 From: Yohei Yukawa Date: Mon, 31 Jan 2022 18:56:59 -0800 Subject: [PATCH] Support floating IMEs even when IMEs render the nav buttons As discussed in Bug 201375975, the nevigation bar handling for floating IMEs is a bit tricky. This CL tweaks DecorView behabior only when InputMethodService#canImeRenderGesturalNavButtons(), is true and the IME is floating in the gestural navigation mode. Fix: 215550296 Test: Manually tested with ThemedNavBarKeyboard sample 1. Build aosp_coral-userdebug and flash it 2. adb root 3. adb shell setprop \ persist.sys.ime.can_render_gestural_nav_buttons true 4. adb reboot 5. make -j ThemedNavBarKeyboard 6. adb install -r \ $OUT/system/app/ThemedNavBarKeyboard/ThemedNavBarKeyboard.apk 7. adb shell ime enable \ com.example.android.themednavbarkeyboard/.ThemedNavBarKeyboard 8. adb shell ime set \ com.example.android.themednavbarkeyboard/.ThemedNavBarKeyboard 9. Open the Dialer app 10. Focus in the top edit field. 11. Tap "FLOATING MODE" mode 12. Make sure that the navigation buttons are visible. Change-Id: Ia54499a3c2ac6e33e72f625eba3477fd81649d32 --- .../NavigationBarController.java | 42 ++++++++++++++++--- core/java/android/view/Window.java | 28 +++++++++++++ .../android/internal/policy/DecorView.java | 8 +++- 3 files changed, 71 insertions(+), 7 deletions(-) diff --git a/core/java/android/inputmethodservice/NavigationBarController.java b/core/java/android/inputmethodservice/NavigationBarController.java index 9cea82b91f5a3..e5c22e4de08e1 100644 --- a/core/java/android/inputmethodservice/NavigationBarController.java +++ b/core/java/android/inputmethodservice/NavigationBarController.java @@ -29,6 +29,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.res.Resources; +import android.graphics.Color; import android.graphics.Insets; import android.graphics.Rect; import android.graphics.Region; @@ -158,6 +159,8 @@ final class NavigationBarController { @Nullable private ValueAnimator mTintAnimator; + private boolean mDrawLegacyNavigationBarBackground; + Impl(@NonNull InputMethodService inputMethodService) { mService = inputMethodService; } @@ -226,9 +229,14 @@ final class NavigationBarController { mLastInsets = systemInsets; } - mNavigationBarFrame.setBackground(null); + if (mDrawLegacyNavigationBarBackground) { + mNavigationBarFrame.setBackgroundColor(Color.BLACK); + } else { + mNavigationBarFrame.setBackground(null); + } - setIconTintInternal(calculateTargetDarkIntensity(mAppearance)); + setIconTintInternal(calculateTargetDarkIntensity(mAppearance, + mDrawLegacyNavigationBarBackground)); } private void uninstallNavigationBarFrameIfNecessary() { @@ -478,7 +486,8 @@ final class NavigationBarController { return; } - final float targetDarkIntensity = calculateTargetDarkIntensity(mAppearance); + final float targetDarkIntensity = calculateTargetDarkIntensity(mAppearance, + mDrawLegacyNavigationBarBackground); if (mTintAnimator != null) { mTintAnimator.cancel(); @@ -506,11 +515,33 @@ final class NavigationBarController { } @FloatRange(from = 0.0f, to = 1.0f) - private static float calculateTargetDarkIntensity(@Appearance int appearance) { - final boolean lightNavBar = (appearance & APPEARANCE_LIGHT_NAVIGATION_BARS) != 0; + private static float calculateTargetDarkIntensity(@Appearance int appearance, + boolean drawLegacyNavigationBarBackground) { + final boolean lightNavBar = !drawLegacyNavigationBarBackground + && (appearance & APPEARANCE_LIGHT_NAVIGATION_BARS) != 0; return lightNavBar ? 1.0f : 0.0f; } + @Override + public boolean onDrawLegacyNavigationBarBackgroundChanged( + boolean drawLegacyNavigationBarBackground) { + if (mDestroyed) { + return false; + } + + if (drawLegacyNavigationBarBackground != mDrawLegacyNavigationBarBackground) { + mDrawLegacyNavigationBarBackground = drawLegacyNavigationBarBackground; + if (mDrawLegacyNavigationBarBackground) { + mNavigationBarFrame.setBackgroundColor(Color.BLACK); + } else { + mNavigationBarFrame.setBackground(null); + } + scheduleRelayout(); + onSystemBarAppearanceChanged(mAppearance); + } + return drawLegacyNavigationBarBackground; + } + @Override public String toDebugString() { return "{mRenderGesturalNavButtons=" + mRenderGesturalNavButtons @@ -518,6 +549,7 @@ final class NavigationBarController { + " mShouldShowImeSwitcherWhenImeIsShown" + mShouldShowImeSwitcherWhenImeIsShown + " mAppearance=0x" + Integer.toHexString(mAppearance) + " mDarkIntensity=" + mDarkIntensity + + " mDrawLegacyNavigationBarBackground=" + mDrawLegacyNavigationBarBackground + "}"; } } diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java index 2f969086360bc..8401b7cdb2432 100644 --- a/core/java/android/view/Window.java +++ b/core/java/android/view/Window.java @@ -673,6 +673,24 @@ public abstract class Window { * @param appearance The newly applied appearance. */ void onSystemBarAppearanceChanged(@WindowInsetsController.Appearance int appearance); + + /** + * Called from + * {@link com.android.internal.policy.DecorView#updateColorViews(WindowInsets, boolean)} + * when {@link com.android.internal.policy.DecorView#mDrawLegacyNavigationBarBackground} is + * being updated. + * + * @param drawLegacyNavigationBarBackground the new value that is being set to + * {@link com.android.internal.policy.DecorView#mDrawLegacyNavigationBarBackground}. + * @return The value to be set to + * {@link com.android.internal.policy.DecorView#mDrawLegacyNavigationBarBackgroundHandled} + * on behalf of the {@link com.android.internal.policy.DecorView}. + * {@code true} to tell that the Window can render the legacy navigation bar + * background on behalf of the {@link com.android.internal.policy.DecorView}. + * {@code false} to let {@link com.android.internal.policy.DecorView} handle it. + */ + boolean onDrawLegacyNavigationBarBackgroundChanged( + boolean drawLegacyNavigationBarBackground); } /** @@ -1019,6 +1037,16 @@ public abstract class Window { } } + /** @hide */ + public final boolean onDrawLegacyNavigationBarBackgroundChanged( + boolean drawLegacyNavigationBarBackground) { + if (mDecorCallback == null) { + return false; + } + return mDecorCallback.onDrawLegacyNavigationBarBackgroundChanged( + drawLegacyNavigationBarBackground); + } + /** * Set a callback for changes of area where caption will draw its content. * diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java index 58645ec7ad7d1..2925341cd9488 100644 --- a/core/java/com/android/internal/policy/DecorView.java +++ b/core/java/com/android/internal/policy/DecorView.java @@ -285,6 +285,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind private Insets mBackgroundInsets = Insets.NONE; private Insets mLastBackgroundInsets = Insets.NONE; private boolean mDrawLegacyNavigationBarBackground; + private boolean mDrawLegacyNavigationBarBackgroundHandled; private PendingInsetsController mPendingInsetsController = new PendingInsetsController(); @@ -1171,6 +1172,9 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind mDrawLegacyNavigationBarBackground = mNavigationColorViewState.visible && (mWindow.getAttributes().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0; if (oldDrawLegacy != mDrawLegacyNavigationBarBackground) { + mDrawLegacyNavigationBarBackgroundHandled = + mWindow.onDrawLegacyNavigationBarBackgroundChanged( + mDrawLegacyNavigationBarBackground); if (viewRoot != null) { viewRoot.requestInvalidateRootRenderNode(); } @@ -1263,7 +1267,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind } } - if (forceConsumingNavBar) { + if (forceConsumingNavBar && !mDrawLegacyNavigationBarBackgroundHandled) { mBackgroundInsets = Insets.of(mLastLeftInset, 0, mLastRightInset, mLastBottomInset); } else { mBackgroundInsets = Insets.NONE; @@ -2488,7 +2492,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind } private void drawLegacyNavigationBarBackground(RecordingCanvas canvas) { - if (!mDrawLegacyNavigationBarBackground) { + if (!mDrawLegacyNavigationBarBackground || mDrawLegacyNavigationBarBackgroundHandled) { return; } View v = mNavigationColorViewState.view;