diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 4fd375177d6f9..da6babd8c8276 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -475,7 +475,7 @@ public class InputMethodService extends AbstractInputMethodService { private InputMethodPrivilegedOperations mPrivOps = new InputMethodPrivilegedOperations(); @NonNull - private final NavigationBarController mNavigationBarController = + final NavigationBarController mNavigationBarController = new NavigationBarController(this); @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) diff --git a/core/java/android/inputmethodservice/NavigationBarController.java b/core/java/android/inputmethodservice/NavigationBarController.java index a6e475aeb813c..2484cf079c562 100644 --- a/core/java/android/inputmethodservice/NavigationBarController.java +++ b/core/java/android/inputmethodservice/NavigationBarController.java @@ -17,7 +17,9 @@ package android.inputmethodservice; import static android.content.Intent.ACTION_OVERLAY_CHANGED; +import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS; +import android.annotation.FloatRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.StatusBarManager; @@ -40,6 +42,7 @@ import android.view.ViewParent; import android.view.ViewTreeObserver; import android.view.Window; import android.view.WindowInsets; +import android.view.WindowInsetsController.Appearance; import android.view.WindowManagerPolicyConstants; import android.widget.FrameLayout; @@ -68,6 +71,9 @@ final class NavigationBarController { default void onDestroy() { } + default void onSystemBarAppearanceChanged(@Appearance int appearance) { + } + default String toDebugString() { return "No-op implementation"; } @@ -100,6 +106,10 @@ final class NavigationBarController { mImpl.onDestroy(); } + void onSystemBarAppearanceChanged(@Appearance int appearance) { + mImpl.onSystemBarAppearanceChanged(appearance); + } + String toDebugString() { return mImpl.toDebugString(); } @@ -120,6 +130,9 @@ final class NavigationBarController { @Nullable private BroadcastReceiver mSystemOverlayChangedReceiver; + @Appearance + private int mAppearance; + Impl(@NonNull InputMethodService inputMethodService) { mService = inputMethodService; } @@ -187,6 +200,8 @@ final class NavigationBarController { } mNavigationBarFrame.setBackground(null); + + setIconTintInternal(calculateTargetDarkIntensity(mAppearance)); } private void uninstallNavigationBarFrameIfNecessary() { @@ -388,10 +403,42 @@ final class NavigationBarController { } } + @Override + public void onSystemBarAppearanceChanged(@Appearance int appearance) { + if (mDestroyed) { + return; + } + + mAppearance = appearance; + + if (mNavigationBarFrame == null) { + return; + } + + final float targetDarkIntensity = calculateTargetDarkIntensity(mAppearance); + setIconTintInternal(targetDarkIntensity); + } + + private void setIconTintInternal(float darkIntensity) { + final NavigationBarView navigationBarView = + mNavigationBarFrame.findViewByPredicate(NavigationBarView.class::isInstance); + if (navigationBarView == null) { + return; + } + navigationBarView.setDarkIntensity(darkIntensity); + } + + @FloatRange(from = 0.0f, to = 1.0f) + private static float calculateTargetDarkIntensity(@Appearance int appearance) { + final boolean lightNavBar = (appearance & APPEARANCE_LIGHT_NAVIGATION_BARS) != 0; + return lightNavBar ? 1.0f : 0.0f; + } + @Override public String toDebugString() { return "{mRenderGesturalNavButtons=" + mRenderGesturalNavButtons + " mNavigationBarFrame=" + mNavigationBarFrame + + " mAppearance=0x" + Integer.toHexString(mAppearance) + "}"; } } diff --git a/core/java/android/inputmethodservice/SoftInputWindow.java b/core/java/android/inputmethodservice/SoftInputWindow.java index 6c8eb41d8724f..0893d2aad7408 100644 --- a/core/java/android/inputmethodservice/SoftInputWindow.java +++ b/core/java/android/inputmethodservice/SoftInputWindow.java @@ -23,7 +23,6 @@ import static java.lang.annotation.RetentionPolicy.SOURCE; import android.annotation.IntDef; import android.app.Dialog; -import android.content.Context; import android.graphics.Rect; import android.os.Debug; import android.os.IBinder; @@ -32,6 +31,7 @@ import android.util.proto.ProtoOutputStream; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; +import android.view.WindowInsetsController; import android.view.WindowManager; import java.lang.annotation.Retention; @@ -47,6 +47,7 @@ final class SoftInputWindow extends Dialog { private final KeyEvent.DispatcherState mDispatcherState; private final Rect mBounds = new Rect(); + private final InputMethodService mService; @Retention(SOURCE) @IntDef(value = {WindowState.TOKEN_PENDING, WindowState.TOKEN_SET, @@ -120,7 +121,7 @@ final class SoftInputWindow extends Dialog { /** * Create a SoftInputWindow that uses a custom style. * - * @param context The Context in which the DockWindow should run. In + * @param service The {@link InputMethodService} in which the DockWindow should run. In * particular, it uses the window manager and theme from this context * to present its UI. * @param theme A style resource describing the theme to use for the window. @@ -129,8 +130,10 @@ final class SoftInputWindow extends Dialog { * using styles. This theme is applied on top of the current theme in * context. If 0, the default dialog theme will be used. */ - SoftInputWindow(Context context, int theme, KeyEvent.DispatcherState dispatcherState) { - super(context, theme); + SoftInputWindow(InputMethodService service, int theme, + KeyEvent.DispatcherState dispatcherState) { + super(service, theme); + mService = service; mDispatcherState = dispatcherState; } @@ -261,6 +264,11 @@ final class SoftInputWindow extends Dialog { } } + @Override + public void onSystemBarAppearanceChanged(@WindowInsetsController.Appearance int appearance) { + mService.mNavigationBarController.onSystemBarAppearanceChanged(appearance); + } + void dumpDebug(ProtoOutputStream proto, long fieldId) { final long token = proto.start(fieldId); mBounds.dumpDebug(proto, BOUNDS); diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java index aa9ea19b025e0..039b50a637be4 100644 --- a/core/java/android/view/Window.java +++ b/core/java/android/view/Window.java @@ -607,6 +607,17 @@ public abstract class Window { * @param hasCapture True if the window has pointer capture. */ default public void onPointerCaptureChanged(boolean hasCapture) { }; + + /** + * Called from + * {@link com.android.internal.policy.DecorView#onSystemBarAppearanceChanged(int)}. + * + * @param appearance The newly applied appearance. + * @hide + */ + default void onSystemBarAppearanceChanged( + @WindowInsetsController.Appearance int appearance) { + } } /** @hide */ diff --git a/core/java/android/view/WindowCallbackWrapper.java b/core/java/android/view/WindowCallbackWrapper.java index 02c8945d9fce1..115e9e891408b 100644 --- a/core/java/android/view/WindowCallbackWrapper.java +++ b/core/java/android/view/WindowCallbackWrapper.java @@ -163,5 +163,10 @@ public class WindowCallbackWrapper implements Window.Callback { public void onPointerCaptureChanged(boolean hasCapture) { mWrapped.onPointerCaptureChanged(hasCapture); } + + @Override + public void onSystemBarAppearanceChanged(@WindowInsetsController.Appearance int appearance) { + mWrapped.onSystemBarAppearanceChanged(appearance); + } } diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java index d7eeb7b8dec0d..a50282ee0aa6d 100644 --- a/core/java/com/android/internal/policy/DecorView.java +++ b/core/java/com/android/internal/policy/DecorView.java @@ -1034,6 +1034,12 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind @Override public void onSystemBarAppearanceChanged(@WindowInsetsController.Appearance int appearance) { updateColorViews(null /* insets */, true /* animate */); + if (mWindow != null) { + final Window.Callback callback = mWindow.getCallback(); + if (callback != null) { + callback.onSystemBarAppearanceChanged(appearance); + } + } } @Override