Merge "Cache force-navigation settings state" into main
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
index c207324..2235035 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
@@ -24,6 +24,8 @@
 import android.util.MathUtils;
 import android.util.TimeUtils;
 
+import androidx.annotation.VisibleForTesting;
+
 import com.android.app.animation.Interpolators;
 import com.android.internal.policy.GestureNavigationSettingsObserver;
 import com.android.systemui.Dumpable;
@@ -96,13 +98,14 @@
     private final KeyguardStateController mKeyguardStateController;
     private final StatusBarStateController mStatusBarStateController;
     private final CommandQueue mCommandQueue;
-    private final GestureNavigationSettingsObserver mGestureNavigationSettingsObserver;
+    private GestureNavigationSettingsObserver mGestureNavigationSettingsObserver;
 
     private boolean mTransitionDeferring;
     private long mTransitionDeferringStartTime;
     private long mTransitionDeferringDuration;
     private boolean mTransitionPending;
     private boolean mTintChangePending;
+    private boolean mNavigationButtonsForcedVisible;
     private float mPendingDarkIntensity;
     private ValueAnimator mTintAnimator;
     private float mDarkIntensity;
@@ -137,13 +140,16 @@
         mContext = context;
         mDisplayId = mContext.getDisplayId();
         mGestureNavigationSettingsObserver = new GestureNavigationSettingsObserver(
-                mHandler, mContext, null);
+                mHandler, mContext, this::onNavigationSettingsChanged);
+        mGestureNavigationSettingsObserver.register();
+        onNavigationSettingsChanged();
     }
 
     /** Call to cleanup the LightBarTransitionsController when done with it. */
     public void destroy() {
         mCommandQueue.removeCallback(mCallback);
         mStatusBarStateController.removeCallback(mCallback);
+        mGestureNavigationSettingsObserver.unregister();
     }
 
     public void saveState(Bundle outState) {
@@ -199,6 +205,12 @@
         mTransitionPending = false;
     }
 
+    @VisibleForTesting
+    void setNavigationSettingsObserver(GestureNavigationSettingsObserver observer) {
+        mGestureNavigationSettingsObserver = observer;
+        onNavigationSettingsChanged();
+    }
+
     public void setIconsDark(boolean dark, boolean animate) {
         if (!animate) {
             setIconTintInternal(dark ? 1.0f : 0.0f);
@@ -253,6 +265,28 @@
         mApplier.applyDarkIntensity(MathUtils.lerp(mDarkIntensity, 0f, mDozeAmount));
     }
 
+    public void onDozeAmountChanged(float linear, float eased) {
+        mDozeAmount = eased;
+        dispatchDark();
+    }
+
+    /**
+     * Called when the navigation settings change.
+     */
+    private void onNavigationSettingsChanged() {
+        mNavigationButtonsForcedVisible =
+                mGestureNavigationSettingsObserver.areNavigationButtonForcedVisible();
+    }
+
+    /**
+     * Return whether to use the tint calculated in this class for nav icons.
+     */
+    public boolean supportsIconTintForNavMode(int navigationMode) {
+        // In gesture mode, we already do region sampling to update tint based on content beneath.
+        return !QuickStepContract.isGesturalMode(navigationMode)
+                || mNavigationButtonsForcedVisible;
+    }
+
     @Override
     public void dump(PrintWriter pw, String[] args) {
         pw.print("  mTransitionDeferring="); pw.print(mTransitionDeferring);
@@ -271,20 +305,7 @@
         pw.print("  mPendingDarkIntensity="); pw.print(mPendingDarkIntensity);
         pw.print(" mDarkIntensity="); pw.print(mDarkIntensity);
         pw.print(" mNextDarkIntensity="); pw.println(mNextDarkIntensity);
-    }
-
-    public void onDozeAmountChanged(float linear, float eased) {
-        mDozeAmount = eased;
-        dispatchDark();
-    }
-
-    /**
-     * Return whether to use the tint calculated in this class for nav icons.
-     */
-    public boolean supportsIconTintForNavMode(int navigationMode) {
-        // In gesture mode, we already do region sampling to update tint based on content beneath.
-        return !QuickStepContract.isGesturalMode(navigationMode)
-                || mGestureNavigationSettingsObserver.areNavigationButtonForcedVisible();
+        pw.print(" mAreNavigationButtonForcedVisible="); pw.println(mNavigationButtonsForcedVisible);
     }
 
     /**
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarTransitionsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarTransitionsControllerTest.java
index 0a68406..f71114d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarTransitionsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarTransitionsControllerTest.java
@@ -16,7 +16,14 @@
 
 package com.android.systemui.statusbar.phone;
 
+import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
+import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
@@ -26,6 +33,7 @@
 
 import androidx.test.filters.SmallTest;
 
+import com.android.internal.policy.GestureNavigationSettingsObserver;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.settings.FakeDisplayTracker;
@@ -81,4 +89,39 @@
         verify(mApplier).applyDarkIntensity(eq(0f));
     }
 
+    @Test
+    public void gestureNav_noForceNavButtons_expectNotSupportsIconTint() {
+        GestureNavigationSettingsObserver observer = mock(GestureNavigationSettingsObserver.class);
+        doReturn(false).when(observer).areNavigationButtonForcedVisible();
+        mLightBarTransitionsController.setNavigationSettingsObserver(observer);
+        assertFalse(mLightBarTransitionsController.supportsIconTintForNavMode(
+                NAV_BAR_MODE_GESTURAL));
+    }
+
+    @Test
+    public void gestureNav_forceNavButtons_expectSupportsIconTint() {
+        GestureNavigationSettingsObserver observer = mock(GestureNavigationSettingsObserver.class);
+        doReturn(true).when(observer).areNavigationButtonForcedVisible();
+        mLightBarTransitionsController.setNavigationSettingsObserver(observer);
+        assertTrue(mLightBarTransitionsController.supportsIconTintForNavMode(
+                NAV_BAR_MODE_GESTURAL));
+    }
+
+    @Test
+    public void buttonNav_noForceNavButtons_expectNotSupportsIconTint() {
+        GestureNavigationSettingsObserver observer = mock(GestureNavigationSettingsObserver.class);
+        doReturn(false).when(observer).areNavigationButtonForcedVisible();
+        mLightBarTransitionsController.setNavigationSettingsObserver(observer);
+        assertTrue(mLightBarTransitionsController.supportsIconTintForNavMode(
+                NAV_BAR_MODE_3BUTTON));
+    }
+
+    @Test
+    public void buttonNav_forceNavButtons_expectSupportsIconTint() {
+        GestureNavigationSettingsObserver observer = mock(GestureNavigationSettingsObserver.class);
+        doReturn(true).when(observer).areNavigationButtonForcedVisible();
+        mLightBarTransitionsController.setNavigationSettingsObserver(observer);
+        assertTrue(mLightBarTransitionsController.supportsIconTintForNavMode(
+                NAV_BAR_MODE_3BUTTON));
+    }
 }