Update the IME nav UI when gesture navigation mode changes
With this CL, nav buttons rendered by InputMethodService can be
dynamically enabled or disabled when the gesture navigation mode is
updated.
Note that the feature is still disabled by default behind the flag.
Hence there should be no observable behavior changes unless the
feature is explicitly enabled with setprop.
Fix: 215552600
Test: Manually done as follows
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. Tap any edit field to show AOSP Keyboard.
6. adb shell dumpsys input_method | grep mNavigationBarController
-> Confirm mRenderGesturalNavButtons is false.
-> Confirm mNavigationBarFrame is null.
7. Switch to gestural navigation mode.
8. adb shell dumpsys input_method | grep mNavigationBarController
-> Confirm mRenderGesturalNavButtons is true.
-> Confirm mNavigationBarFrame is not null.
9. Switch to 3-button navigation mode again.
10. adb shell dumpsys input_method | grep mNavigationBarController
-> Confirm mRenderGesturalNavButtons is false.
-> Confirm mNavigationBarFrame is null.
Change-Id: Id0cfa44cce5de515dc5d28254e1d41bdfc01e201
diff --git a/core/java/android/inputmethodservice/NavigationBarController.java b/core/java/android/inputmethodservice/NavigationBarController.java
index 7295b72..7bc9573 100644
--- a/core/java/android/inputmethodservice/NavigationBarController.java
+++ b/core/java/android/inputmethodservice/NavigationBarController.java
@@ -16,19 +16,27 @@
package android.inputmethodservice;
+import static android.content.Intent.ACTION_OVERLAY_CHANGED;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.StatusBarManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.content.res.Resources;
import android.graphics.Insets;
import android.graphics.Rect;
import android.graphics.Region;
import android.inputmethodservice.navigationbar.NavigationBarFrame;
import android.inputmethodservice.navigationbar.NavigationBarView;
+import android.os.PatternMatcher;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewParent;
import android.view.ViewTreeObserver;
import android.view.Window;
import android.view.WindowInsets;
@@ -109,6 +117,9 @@
@Nullable
Insets mLastInsets;
+ @Nullable
+ private BroadcastReceiver mSystemOverlayChangedReceiver;
+
Impl(@NonNull InputMethodService inputMethodService) {
mService = inputMethodService;
}
@@ -136,6 +147,9 @@
if (!mRenderGesturalNavButtons) {
return;
}
+ if (mNavigationBarFrame != null) {
+ return;
+ }
final View rawDecorView = mService.mWindow.getWindow().getDecorView();
if (!(rawDecorView instanceof ViewGroup)) {
return;
@@ -175,6 +189,17 @@
mNavigationBarFrame.setBackground(null);
}
+ private void uninstallNavigationBarFrameIfNecessary() {
+ if (mNavigationBarFrame == null) {
+ return;
+ }
+ final ViewParent parent = mNavigationBarFrame.getParent();
+ if (parent instanceof ViewGroup) {
+ ((ViewGroup) parent).removeView(mNavigationBarFrame);
+ }
+ mNavigationBarFrame = null;
+ }
+
@Override
public void updateTouchableInsets(@NonNull InputMethodService.Insets originalInsets,
@NonNull ViewTreeObserver.InternalInsetsInfo dest) {
@@ -284,11 +309,38 @@
return;
}
mRenderGesturalNavButtons = isGesturalNavigationEnabled();
+ if (mSystemOverlayChangedReceiver == null) {
+ final IntentFilter intentFilter = new IntentFilter(ACTION_OVERLAY_CHANGED);
+ intentFilter.addDataScheme(IntentFilter.SCHEME_PACKAGE);
+ intentFilter.addDataSchemeSpecificPart("android", PatternMatcher.PATTERN_LITERAL);
+ mSystemOverlayChangedReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (mDestroyed) {
+ return;
+ }
+ mRenderGesturalNavButtons = isGesturalNavigationEnabled();
+ if (mRenderGesturalNavButtons) {
+ installNavigationBarFrameIfNecessary();
+ } else {
+ uninstallNavigationBarFrameIfNecessary();
+ }
+ }
+ };
+ mService.registerReceiver(mSystemOverlayChangedReceiver, intentFilter);
+ }
installNavigationBarFrameIfNecessary();
}
@Override
public void onDestroy() {
+ if (mDestroyed) {
+ return;
+ }
+ if (mSystemOverlayChangedReceiver != null) {
+ mService.unregisterReceiver(mSystemOverlayChangedReceiver);
+ mSystemOverlayChangedReceiver = null;
+ }
mDestroyed = true;
}
@@ -322,7 +374,9 @@
@Override
public String toDebugString() {
- return "{mRenderGesturalNavButtons=" + mRenderGesturalNavButtons + "}";
+ return "{mRenderGesturalNavButtons=" + mRenderGesturalNavButtons
+ + " mNavigationBarFrame=" + mNavigationBarFrame
+ + "}";
}
}
}