Merge "Switch preffered display mode on lock screen" into qt-r1-dev
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 861187f..340cb3a 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -482,4 +482,7 @@
      -->
     <string name="config_rounded_mask" translatable="false">"M8,0C3.6,0,0,3.6,0,8"</string>
 
+    <!-- Preferred refresh rate at keyguard, if supported by the display -->
+    <integer name="config_keyguardRefreshRate">-1</integer>
+
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 57bf536..e9f99ac 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -90,6 +90,7 @@
 import com.android.systemui.statusbar.phone.NotificationPanelView;
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+import com.android.systemui.statusbar.phone.StatusBarWindowController;
 import com.android.systemui.util.InjectionInflationController;
 
 import java.io.FileDescriptor;
@@ -204,6 +205,8 @@
     private AlarmManager mAlarmManager;
     private AudioManager mAudioManager;
     private StatusBarManager mStatusBarManager;
+    private final StatusBarWindowController mStatusBarWindowController =
+            Dependency.get(StatusBarWindowController.class);
     private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
 
     private boolean mSystemReady;
@@ -1779,6 +1782,7 @@
             adjustStatusBarLocked();
             userActivity();
             mUpdateMonitor.setKeyguardGoingAway(false /* away */);
+            mStatusBarWindowController.setKeyguardGoingAway(false /* goingAway */);
             mShowKeyguardWakeLock.release();
         }
         mKeyguardDisplayManager.show();
@@ -1811,6 +1815,7 @@
             }
 
             mUpdateMonitor.setKeyguardGoingAway(true /* goingAway */);
+            mStatusBarWindowController.setKeyguardGoingAway(true /* goingAway */);
 
             // Don't actually hide the Keyguard at the moment, wait for window
             // manager until it tells us it's safe to do so with
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
index d9a9f7c..ebac855 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
@@ -29,7 +29,9 @@
 import android.os.Binder;
 import android.os.RemoteException;
 import android.os.SystemProperties;
+import android.os.Trace;
 import android.util.Log;
+import android.view.Display;
 import android.view.Gravity;
 import android.view.View;
 import android.view.ViewGroup;
@@ -57,6 +59,7 @@
 import java.lang.ref.WeakReference;
 import java.lang.reflect.Field;
 import java.util.ArrayList;
+import java.util.Arrays;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
@@ -76,6 +79,8 @@
     private final WindowManager.LayoutParams mLpChanged;
     private final boolean mKeyguardScreenRotation;
     private final long mLockScreenDisplayTimeout;
+    private final Display.Mode mKeyguardDisplayMode;
+    private final KeyguardBypassController mKeyguardBypassController;
     private ViewGroup mStatusBarView;
     private WindowManager.LayoutParams mLp;
     private boolean mHasTopUi;
@@ -91,14 +96,21 @@
     private final SysuiColorExtractor mColorExtractor = Dependency.get(SysuiColorExtractor.class);
 
     @Inject
-    public StatusBarWindowController(Context context) {
+    public StatusBarWindowController(Context context,
+            StatusBarStateController statusBarStateController,
+            ConfigurationController configurationController,
+            KeyguardBypassController keyguardBypassController) {
         this(context, context.getSystemService(WindowManager.class), ActivityManager.getService(),
-                DozeParameters.getInstance(context));
+                DozeParameters.getInstance(context), statusBarStateController,
+                configurationController, keyguardBypassController);
     }
 
     @VisibleForTesting
     public StatusBarWindowController(Context context, WindowManager windowManager,
-            IActivityManager activityManager, DozeParameters dozeParameters) {
+            IActivityManager activityManager, DozeParameters dozeParameters,
+            StatusBarStateController statusBarStateController,
+            ConfigurationController configurationController,
+            KeyguardBypassController keyguardBypassController) {
         mContext = context;
         mWindowManager = windowManager;
         mActivityManager = activityManager;
@@ -106,12 +118,27 @@
         mDozeParameters = dozeParameters;
         mScreenBrightnessDoze = mDozeParameters.getScreenBrightnessDoze();
         mLpChanged = new WindowManager.LayoutParams();
+        mKeyguardBypassController = keyguardBypassController;
         mLockScreenDisplayTimeout = context.getResources()
                 .getInteger(R.integer.config_lockScreenDisplayTimeout);
-        ((SysuiStatusBarStateController) Dependency.get(StatusBarStateController.class))
+        ((SysuiStatusBarStateController) statusBarStateController)
                 .addCallback(mStateListener,
                         SysuiStatusBarStateController.RANK_STATUS_BAR_WINDOW_CONTROLLER);
-        Dependency.get(ConfigurationController.class).addCallback(this);
+        configurationController.addCallback(this);
+
+        Display.Mode[] supportedModes = context.getDisplay().getSupportedModes();
+        Display.Mode currentMode = context.getDisplay().getMode();
+        // Running on the highest frame rate available can be expensive.
+        // Let's specify a preferred refresh rate, and allow higher FPS only when we
+        // know that we're not falsing (because we unlocked.)
+        int keyguardRefreshRate = context.getResources()
+                .getInteger(R.integer.config_keyguardRefreshRate);
+        // Find supported display mode with the same resolution and requested refresh rate.
+        mKeyguardDisplayMode = Arrays.stream(supportedModes).filter(mode ->
+                (int) mode.getRefreshRate() == keyguardRefreshRate
+                        && mode.getPhysicalWidth() == currentMode.getPhysicalWidth()
+                        && mode.getPhysicalHeight() == currentMode.getPhysicalHeight())
+                .findFirst().orElse(null);
     }
 
     /**
@@ -209,6 +236,18 @@
         } else {
             mLpChanged.privateFlags &= ~LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
         }
+
+        if (mKeyguardDisplayMode != null) {
+            boolean bypassOnKeyguard = mKeyguardBypassController.getBypassEnabled()
+                    && state.statusBarState == StatusBarState.KEYGUARD && !state.keyguardFadingAway
+                    && !state.keyguardGoingAway;
+            if (state.dozing || bypassOnKeyguard) {
+                mLpChanged.preferredDisplayModeId = mKeyguardDisplayMode.getModeId();
+            } else {
+                mLpChanged.preferredDisplayModeId = 0;
+            }
+            Trace.setCounter("display_mode_id", mLpChanged.preferredDisplayModeId);
+        }
     }
 
     private void adjustScreenOrientation(State state) {
@@ -575,7 +614,8 @@
     }
 
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        pw.println("StatusBarWindowController state:");
+        pw.println("StatusBarWindowController:");
+        pw.println("  mKeyguardDisplayMode=" + mKeyguardDisplayMode);
         pw.println(mCurrentState);
     }
 
@@ -594,6 +634,14 @@
         setKeyguardDark(useDarkText);
     }
 
+    /**
+     * When keyguard will be dismissed but didn't start animation yet.
+     */
+    public void setKeyguardGoingAway(boolean goingAway) {
+        mCurrentState.keyguardGoingAway = goingAway;
+        apply(mCurrentState);
+    }
+
     private static class State {
         boolean keyguardShowing;
         boolean keyguardOccluded;
@@ -603,6 +651,7 @@
         boolean statusBarFocusable;
         boolean bouncerShowing;
         boolean keyguardFadingAway;
+        boolean keyguardGoingAway;
         boolean qsExpanded;
         boolean headsUpShowing;
         boolean forceStatusBarVisible;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
index b3f6f4e..2221915 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -60,6 +60,7 @@
 import com.android.systemui.statusbar.NotificationPresenter;
 import com.android.systemui.statusbar.NotificationRemoveInterceptor;
 import com.android.systemui.statusbar.NotificationTestHelper;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
 import com.android.systemui.statusbar.notification.NotificationEntryListener;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
@@ -67,6 +68,7 @@
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.statusbar.phone.KeyguardBypassController;
 import com.android.systemui.statusbar.phone.StatusBarWindowController;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
@@ -105,6 +107,10 @@
     private ZenModeController mZenModeController;
     @Mock
     private ZenModeConfig mZenModeConfig;
+    @Mock
+    private SysuiStatusBarStateController mStatusBarStateController;
+    @Mock
+    private KeyguardBypassController mKeyguardBypassController;
 
     private FrameLayout mStatusBarView;
     @Captor
@@ -143,7 +149,8 @@
 
         // Bubbles get added to status bar window view
         mStatusBarWindowController = new StatusBarWindowController(mContext, mWindowManager,
-                mActivityManager, mDozeParameters);
+                mActivityManager, mDozeParameters, mStatusBarStateController,
+                mConfigurationController, mKeyguardBypassController);
         mStatusBarWindowController.add(mStatusBarView, 120 /* height */);
 
         // Need notifications for bubbles
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java
index fea41a4..4ffaeae 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java
@@ -33,6 +33,8 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
+import com.android.systemui.statusbar.policy.ConfigurationController;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -54,6 +56,12 @@
     private ViewGroup mStatusBarView;
     @Mock
     private IActivityManager mActivityManager;
+    @Mock
+    private SysuiStatusBarStateController mStatusBarStateController;
+    @Mock
+    private ConfigurationController mConfigurationController;
+    @Mock
+    private KeyguardBypassController mKeyguardBypassController;
 
     private StatusBarWindowController mStatusBarWindowController;
 
@@ -63,7 +71,8 @@
         when(mDozeParameters.getAlwaysOn()).thenReturn(true);
 
         mStatusBarWindowController = new StatusBarWindowController(mContext, mWindowManager,
-                mActivityManager, mDozeParameters);
+                mActivityManager, mDozeParameters, mStatusBarStateController,
+                mConfigurationController, mKeyguardBypassController);
         mStatusBarWindowController.add(mStatusBarView, 100 /* height */);
     }
 
@@ -88,7 +97,8 @@
     @Test
     public void testOnThemeChanged_doesntCrash() {
         mStatusBarWindowController = new StatusBarWindowController(mContext, mWindowManager,
-                mActivityManager, mDozeParameters);
+                mActivityManager, mDozeParameters, mStatusBarStateController,
+                mConfigurationController, mKeyguardBypassController);
         mStatusBarWindowController.onThemeChanged();
     }
 
@@ -100,7 +110,8 @@
     @Test
     public void testSetForcePluginOpen_beforeStatusBarInitialization() {
         mStatusBarWindowController = new StatusBarWindowController(mContext, mWindowManager,
-                mActivityManager, mDozeParameters);
+                mActivityManager, mDozeParameters, mStatusBarStateController,
+                mConfigurationController, mKeyguardBypassController);
         mStatusBarWindowController.setForcePluginOpen(true);
     }
 }