diff options
-rw-r--r-- | core/java/android/inputmethodservice/SoftInputWindow.java | 13 | ||||
-rw-r--r-- | core/res/res/values/config.xml | 5 | ||||
-rw-r--r-- | core/res/res/values/symbols.xml | 1 | ||||
-rw-r--r-- | packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java | 101 |
4 files changed, 105 insertions, 15 deletions
diff --git a/core/java/android/inputmethodservice/SoftInputWindow.java b/core/java/android/inputmethodservice/SoftInputWindow.java index 0513feef801f..356b3448430a 100644 --- a/core/java/android/inputmethodservice/SoftInputWindow.java +++ b/core/java/android/inputmethodservice/SoftInputWindow.java @@ -21,6 +21,7 @@ import static java.lang.annotation.RetentionPolicy.SOURCE; import android.annotation.IntDef; import android.app.Dialog; import android.content.Context; +import android.content.pm.PackageManager; import android.graphics.Rect; import android.os.Debug; import android.os.IBinder; @@ -50,6 +51,7 @@ public class SoftInputWindow extends Dialog { final int mWindowType; final int mGravity; final boolean mTakesFocus; + final boolean mAutomotiveHideNavBarForKeyboard; private final Rect mBounds = new Rect(); @Retention(SOURCE) @@ -134,6 +136,8 @@ public class SoftInputWindow extends Dialog { mWindowType = windowType; mGravity = gravity; mTakesFocus = takesFocus; + mAutomotiveHideNavBarForKeyboard = context.getResources().getBoolean( + com.android.internal.R.bool.config_automotiveHideNavBarForKeyboard); initDockWindow(); } @@ -247,6 +251,11 @@ public class SoftInputWindow extends Dialog { windowModFlags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; } + if (isAutomotive() && mAutomotiveHideNavBarForKeyboard) { + windowSetFlags |= WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS; + windowModFlags |= WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS; + } + getWindow().setFlags(windowSetFlags, windowModFlags); } @@ -338,6 +347,10 @@ public class SoftInputWindow extends Dialog { mWindowState = newState; } + private boolean isAutomotive() { + return getContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE); + } + private static String stateToString(@SoftInputWindowState int state) { switch (state) { case SoftInputWindowState.TOKEN_PENDING: diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 1577a227ff67..bfcc8d4a566e 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -4255,4 +4255,9 @@ <!-- The list of packages to automatically opt out of refresh rates higher than 60hz because of known compatibility issues. --> <string-array name="config_highRefreshRateBlacklist"></string-array> + + <!-- Whether or not to hide the navigation bar when the soft keyboard is visible in order to + create additional screen real estate outside beyond the keyboard. Note that the user needs + to have a confirmed way to dismiss the keyboard when desired. --> + <bool name="config_automotiveHideNavBarForKeyboard">false</bool> </resources> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 0d9c4b39fea0..f06b17eb6f1d 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -3835,4 +3835,5 @@ <java-symbol type="drawable" name="android_logotype" /> <java-symbol type="layout" name="platlogo_layout" /> + <java-symbol type="bool" name="config_automotiveHideNavBarForKeyboard" /> </resources> diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java index 146bfe02498b..da42d4f015ff 100644 --- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java @@ -30,7 +30,10 @@ import android.content.Context; import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.drawable.Drawable; +import android.inputmethodservice.InputMethodService; +import android.os.IBinder; import android.util.Log; +import android.view.Display; import android.view.GestureDetector; import android.view.Gravity; import android.view.MotionEvent; @@ -85,8 +88,7 @@ import java.util.Map; /** * A status bar (and navigation bar) tailored for the automotive use case. */ -public class CarStatusBar extends StatusBar implements - CarBatteryController.BatteryViewHandler { +public class CarStatusBar extends StatusBar implements CarBatteryController.BatteryViewHandler { private static final String TAG = "CarStatusBar"; // used to calculate how fast to open or close the window private static final float DEFAULT_FLING_VELOCITY = 0; @@ -167,6 +169,9 @@ public class CarStatusBar extends StatusBar implements private boolean mIsSwipingVerticallyToClose; // Whether heads-up notifications should be shown when shade is open. private boolean mEnableHeadsUpNotificationWhenNotificationShadeOpen; + // If the nav bar should be hidden when the soft keyboard is visible. + private boolean mHideNavBarForKeyboard; + private boolean mBottomNavBarVisible; private final CarPowerStateListener mCarPowerStateListener = (int state) -> { @@ -188,6 +193,12 @@ public class CarStatusBar extends StatusBar implements // builds the nav bar mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class); mDeviceIsProvisioned = mDeviceProvisionedController.isDeviceProvisioned(); + + // Keyboard related setup, before nav bars are created. + mHideNavBarForKeyboard = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_automotiveHideNavBarForKeyboard); + mBottomNavBarVisible = false; + super.start(); mTaskStackListener = new TaskStackListenerImpl(); mActivityManagerWrapper = ActivityManagerWrapper.getInstance(); @@ -718,6 +729,13 @@ public class CarStatusBar extends StatusBar implements buildNavBarContent(); attachNavBarWindows(); + // Try setting up the initial state of the nav bar if applicable. + if (result != null) { + setImeWindowStatus(Display.DEFAULT_DISPLAY, result.mImeToken, + result.mImeWindowVis, result.mImeBackDisposition, + result.mShowImeSwitcher); + } + // There has been a car customized nav bar on the default display, so just create nav bars // on external displays. mNavigationBarController.createNavigationBars(false /* includeDefaultDisplay */, result); @@ -756,21 +774,32 @@ public class CarStatusBar extends StatusBar implements } - private void attachNavBarWindows() { + /** + * We register for soft keyboard visibility events such that we can hide the navigation bar + * giving more screen space to the IME. Note: this is optional and controlled by + * {@code com.android.internal.R.bool.config_automotiveHideNavBarForKeyboard}. + */ + @Override + public void setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition, + boolean showImeSwitcher) { + if (!mHideNavBarForKeyboard) { + return; + } - if (mShowBottom) { - WindowManager.LayoutParams lp = new WindowManager.LayoutParams( - LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, - WindowManager.LayoutParams.TYPE_NAVIGATION_BAR, - WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE - | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL - | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH - | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH, - PixelFormat.TRANSLUCENT); - lp.setTitle("CarNavigationBar"); - lp.windowAnimations = 0; - mWindowManager.addView(mNavigationBarWindow, lp); + if (mContext.getDisplay().getDisplayId() != displayId) { + return; + } + + boolean isKeyboardVisible = (vis & InputMethodService.IME_VISIBLE) != 0; + if (!isKeyboardVisible) { + attachBottomNavBarWindow(); + } else { + detachBottomNavBarWindow(); } + } + + private void attachNavBarWindows() { + attachBottomNavBarWindow(); if (mShowLeft) { int width = mContext.getResources().getDimensionPixelSize( @@ -806,7 +835,49 @@ public class CarStatusBar extends StatusBar implements rightlp.gravity = Gravity.RIGHT; mWindowManager.addView(mRightNavigationBarWindow, rightlp); } + } + + /** + * Attaches the bottom nav bar window. Can be extended to modify the specific behavior of + * attaching the bottom nav bar. + */ + protected void attachBottomNavBarWindow() { + if (!mShowBottom) { + return; + } + + if (mBottomNavBarVisible) { + return; + } + mBottomNavBarVisible = true; + + WindowManager.LayoutParams lp = new WindowManager.LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, + WindowManager.LayoutParams.TYPE_NAVIGATION_BAR, + WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE + | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL + | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH + | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH, + PixelFormat.TRANSLUCENT); + lp.setTitle("CarNavigationBar"); + lp.windowAnimations = 0; + mWindowManager.addView(mNavigationBarWindow, lp); + } + + /** + * Detaches the bottom nav bar window. Can be extended to modify the specific behavior of + * detaching the bottom nav bar. + */ + protected void detachBottomNavBarWindow() { + if (!mShowBottom) { + return; + } + if (!mBottomNavBarVisible) { + return; + } + mBottomNavBarVisible = false; + mWindowManager.removeView(mNavigationBarWindow); } private void buildBottomBar(int layout) { |