DecorView#mNavigationGuard is gone

With this CL, DecorView#mNavigationGuard that handles navigation bar
only for IME windows [1] is finally gone and replaced with the
standard mechanism to handle navigation bar layout padding /
background color.

This CL addresses multiple anomalies regarding how the following APIs
work for IME windows.

 * Window#setNavigationBarColor()
   * Previous behavior:
    - Only works for Color#TRANSPARENT [2].
    - Ignores FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS.
   * New behavior:
    - Works as documented.
    - Requires FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS to work.

 * SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION flag
   * Previous behavior:
    - The system automatically sets
      SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION to the IME windows [3].
    - Does not work as documented. Content area is not extended to the
      navigation bar area.
    - Manually unsetting SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION can cause
      unexpected layout, because the system expects that this flag is
      always set to the IME window.
    - Had a special logic for FLAG_LAYOUT_IN_OVERSCAN [4].
   * New behavior:
    - Works as documented.
    - Can set/unset as necessary.

From the viewpoint of IME developers, this CL enables IME windows to
 * correctly extend the input view to the navigation bar region by
   using SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION as documented, instead of
   relying on a special hack with FLAG_LAYOUT_IN_OVERSCAN hack.
 * use Window#setNavigationBarColor() to easily change the navigation
   bar background color, like other non-floating windows.

Note that SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR is not yet supported for
IME windows, which will be implemented in a subsequent CL.

 [1]: I6a93f30aec83f1cecfb854073046cbc87ab4aa66
      ae3349e1c34f7aceddc526cd11d9ac44951e97b6
 [2]: Iea77915ecc55eedaf19899e72c44f704ba9d852c
      0a9d1ea015af24056018ec02f6d9afd2f62243ba
 [3]: I460912ee7c117480c57b947ed31eca330819f32c
      c68d577f29604d205573ee4253704c5b2c5e4f81
 [4]: Ic38f204a892bf34e8dae65990d5aa8c95af555d8
      9b32a35aa7d47d39da919e777e2fe271cc83fa1c
 [5]: I4b10a19641bd3ce6c43e7629404b6f202d4186e8

Fix: 25706186
Bug: 69002467
Test: ThemedNavBarKeyboard sample [5] works for the following cases
      * Extended Dark Navigation Bar
      * Separate Dark Navigation Bar
      * Floating Mode (if the target app uses dark navigation bar)
Change-Id: I664630099b6eb3fe31675444ba94944cb0eb98b0
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 02b1c65..8937490 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -18,6 +18,7 @@
 
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
 
 import android.annotation.CallSuper;
 import android.annotation.DrawableRes;
@@ -852,6 +853,11 @@
                 Context.LAYOUT_INFLATER_SERVICE);
         mWindow = new SoftInputWindow(this, "InputMethod", mTheme, null, null, mDispatcherState,
                 WindowManager.LayoutParams.TYPE_INPUT_METHOD, Gravity.BOTTOM, false);
+        // For ColorView in DecorView to work, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS needs to be set
+        // by default (but IME developers can opt this out later if they want a new behavior).
+        mWindow.getWindow().setFlags(
+                FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
+
         initViews();
         mWindow.getWindow().setLayout(MATCH_PARENT, WRAP_CONTENT);
     }
@@ -882,8 +888,6 @@
         mThemeAttrs = obtainStyledAttributes(android.R.styleable.InputMethodService);
         mRootView = mInflater.inflate(
                 com.android.internal.R.layout.input_method, null);
-        mRootView.setSystemUiVisibility(
-                View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
         mWindow.setContentView(mRootView);
         mRootView.getViewTreeObserver().removeOnComputeInternalInsetsListener(mInsetsComputer);
         mRootView.getViewTreeObserver().addOnComputeInternalInsetsListener(mInsetsComputer);
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 5fddfba..95bc352 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -101,7 +101,6 @@
 import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
 import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
-import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN;
 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
 import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
 import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
@@ -194,8 +193,6 @@
 
     // View added at runtime to draw under the status bar area
     private View mStatusGuard;
-    // View added at runtime to draw under the navigation bar area
-    private View mNavigationGuard;
 
     private final ColorViewState mStatusColorViewState =
             new ColorViewState(STATUS_BAR_COLOR_VIEW_ATTRIBUTES);
@@ -1002,7 +999,6 @@
         mFrameOffsets.set(insets.getSystemWindowInsets());
         insets = updateColorViews(insets, true /* animate */);
         insets = updateStatusGuard(insets);
-        insets = updateNavigationGuard(insets);
         if (getForeground() != null) {
             drawableChanged();
         }
@@ -1062,7 +1058,10 @@
         WindowManager.LayoutParams attrs = mWindow.getAttributes();
         int sysUiVisibility = attrs.systemUiVisibility | getWindowSystemUiVisibility();
 
-        if (!mWindow.mIsFloating) {
+        // IME is an exceptional floating window that requires color view.
+        final boolean isImeWindow =
+                mWindow.getAttributes().type == WindowManager.LayoutParams.TYPE_INPUT_METHOD;
+        if (!mWindow.mIsFloating || isImeWindow) {
             boolean disallowAnimate = !isLaidOut();
             disallowAnimate |= ((mLastWindowFlags ^ attrs.flags)
                     & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
@@ -1363,7 +1362,7 @@
                         if (mStatusGuard == null) {
                             mStatusGuard = new View(mContext);
                             mStatusGuard.setBackgroundColor(mContext.getColor(
-                                    R.color.input_method_navigation_guard));
+                                    R.color.decor_view_status_guard));
                             addView(mStatusGuard, indexOfChild(mStatusColorViewState.view),
                                     new LayoutParams(LayoutParams.MATCH_PARENT,
                                             mlp.topMargin, Gravity.START | Gravity.TOP));
@@ -1407,51 +1406,6 @@
         return insets;
     }
 
-    private WindowInsets updateNavigationGuard(WindowInsets insets) {
-        // IME windows lay out below the nav bar, but the content view must not (for back compat)
-        // Only make this adjustment if the window is not requesting layout in overscan
-        if (mWindow.getAttributes().type == WindowManager.LayoutParams.TYPE_INPUT_METHOD
-                && (mWindow.getAttributes().flags & FLAG_LAYOUT_IN_OVERSCAN) == 0) {
-            // prevent the content view from including the nav bar height
-            if (mWindow.mContentParent != null) {
-                if (mWindow.mContentParent.getLayoutParams() instanceof MarginLayoutParams) {
-                    MarginLayoutParams mlp =
-                            (MarginLayoutParams) mWindow.mContentParent.getLayoutParams();
-                    mlp.bottomMargin = insets.getSystemWindowInsetBottom();
-                    mWindow.mContentParent.setLayoutParams(mlp);
-                }
-            }
-            // position the navigation guard view, creating it if necessary
-            if (mNavigationGuard == null) {
-                mNavigationGuard = new View(mContext);
-                mNavigationGuard.setBackgroundColor(mContext.getColor(
-                        R.color.input_method_navigation_guard));
-                addView(mNavigationGuard, indexOfChild(mNavigationColorViewState.view),
-                        new LayoutParams(LayoutParams.MATCH_PARENT,
-                                insets.getSystemWindowInsetBottom(),
-                                Gravity.START | Gravity.BOTTOM));
-            } else {
-                LayoutParams lp = (LayoutParams) mNavigationGuard.getLayoutParams();
-                lp.height = insets.getSystemWindowInsetBottom();
-                mNavigationGuard.setLayoutParams(lp);
-            }
-            updateNavigationGuardColor();
-            insets = insets.consumeSystemWindowInsets(
-                    false, false, false, true /* bottom */);
-        }
-        return insets;
-    }
-
-    void updateNavigationGuardColor() {
-        if (mNavigationGuard != null) {
-            // Make navigation bar guard invisible if the transparent color is specified.
-            // Only TRANSPARENT is sufficient for hiding the navigation bar if the no software
-            // keyboard is shown by IMS.
-            mNavigationGuard.setVisibility(mWindow.getNavigationBarColor() == Color.TRANSPARENT ?
-                    View.INVISIBLE : View.VISIBLE);
-        }
-    }
-
     /**
      * Overrides the view outline when the activity enters picture-in-picture to ensure that it has
      * an opaque shadow even if the window background is completely transparent. This only applies
@@ -2103,7 +2057,7 @@
             for (int i = getChildCount() - 1; i >= 0; i--) {
                 View v = getChildAt(i);
                 if (v != mStatusColorViewState.view && v != mNavigationColorViewState.view
-                        && v != mStatusGuard && v != mNavigationGuard) {
+                        && v != mStatusGuard) {
                     removeViewAt(i);
                 }
             }
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index b13560c..e8ee29d 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -3807,7 +3807,6 @@
         mForcedNavigationBarColor = true;
         if (mDecor != null) {
             mDecor.updateColorViews(null, false /* animate */);
-            mDecor.updateNavigationGuardColor();
         }
     }
 
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index fd78500..a078d8b 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -73,7 +73,7 @@
     <drawable name="editbox_dropdown_light_frame">@drawable/editbox_dropdown_background</drawable>
 
     <drawable name="input_method_fullscreen_background">#fff9f9f9</drawable>
-    <color name="input_method_navigation_guard">#ff000000</color>
+    <color name="decor_view_status_guard">#ff000000</color>
 
     <!-- For date picker widget -->
     <drawable name="selected_day_background">#ff0092f4</drawable>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 4343ba0..7eb1597 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1812,7 +1812,7 @@
   <java-symbol type="bool" name="config_wimaxEnabled" />
   <java-symbol type="bool" name="show_ongoing_ime_switcher" />
   <java-symbol type="color" name="config_defaultNotificationColor" />
-  <java-symbol type="color" name="input_method_navigation_guard" />
+  <java-symbol type="color" name="decor_view_status_guard" />
   <java-symbol type="drawable" name="ic_notification_ime_default" />
   <java-symbol type="drawable" name="ic_menu_refresh" />
   <java-symbol type="drawable" name="ic_settings" />