Listen for changes to IME and show/hide nav bar

This feature is configurable and set to false as the default value. It
is overlayed as true for Automotive.

Bug: 138242566
Test: manual
Change-Id: I5dde8adc9d4ce749d895287ccf63017b284caec8
This commit is contained in:
Heemin Seog
2019-08-15 13:18:41 -07:00
parent 92bd450659
commit 26c830dd16
4 changed files with 99 additions and 16 deletions

View File

@@ -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:

View File

@@ -4285,4 +4285,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>

View File

@@ -3847,4 +3847,6 @@
<java-symbol type="string" name="config_factoryResetPackage" />
<java-symbol type="array" name="config_highRefreshRateBlacklist" />
<java-symbol type="bool" name="config_automotiveHideNavBarForKeyboard" />
</resources>

View File

@@ -31,7 +31,10 @@ import android.content.res.Configuration;
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;
@@ -86,8 +89,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;
@@ -168,6 +170,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) -> {
@@ -189,6 +194,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();
@@ -719,6 +730,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);
@@ -757,22 +775,33 @@ public class CarStatusBar extends StatusBar implements
}
private void attachNavBarWindows() {
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);
/**
* 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 (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(
R.dimen.car_left_navigation_bar_width);
@@ -807,7 +836,41 @@ public class CarStatusBar extends StatusBar implements
rightlp.gravity = Gravity.RIGHT;
mWindowManager.addView(mRightNavigationBarWindow, rightlp);
}
}
private 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);
}
private void detachBottomNavBarWindow() {
if (!mShowBottom) {
return;
}
if (!mBottomNavBarVisible) {
return;
}
mBottomNavBarVisible = false;
mWindowManager.removeView(mNavigationBarWindow);
}
private void buildBottomBar(int layout) {