Merge "Fix bindToLifecycleCamera IllegalArgumentatException issue caused by abnormally small display size" into androidx-main
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2UseCaseConfigFactory.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2UseCaseConfigFactory.java
index 1c8859f..3d271cd 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2UseCaseConfigFactory.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2UseCaseConfigFactory.java
@@ -93,7 +93,10 @@
                             resolutionStrategy).build());
         }
 
-        int targetRotation = mDisplayInfoManager.getMaxSizeDisplay().getRotation();
+        // The default rotation value should be determined by the max non-state-off display.
+        // Calling getMaxSizeDisplay() function with parameter `true` can skips the displays with
+        // off state.
+        int targetRotation = mDisplayInfoManager.getMaxSizeDisplay(true).getRotation();
         mutableConfig.insertOption(OPTION_TARGET_ROTATION, targetRotation);
 
         if (captureType == CaptureType.VIDEO_CAPTURE || captureType == CaptureType.STREAM_SHARING) {
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/DisplayInfoManager.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/DisplayInfoManager.java
index 8be1ac2..fdf264a 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/DisplayInfoManager.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/DisplayInfoManager.java
@@ -23,24 +23,35 @@
 import android.view.Display;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
 import androidx.annotation.VisibleForTesting;
+import androidx.camera.camera2.internal.compat.workaround.DisplaySizeCorrector;
 import androidx.camera.camera2.internal.compat.workaround.MaxPreviewSize;
+import androidx.camera.core.internal.utils.SizeUtil;
 
 /**
  * A singleton class to retrieve display related information.
  */
 @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public class DisplayInfoManager {
-
-    private static final String TAG = "DisplayInfoManager";
     private static final Size MAX_PREVIEW_SIZE = new Size(1920, 1080);
+    /**
+     * This is the smallest size from a device which had issue reported to CameraX.
+     */
+    private static final Size ABNORMAL_DISPLAY_SIZE_THRESHOLD = new Size(320, 240);
+    /**
+     * The fallback display size for the case that the retrieved display size is abnormally small
+     * and no correct display size can be retrieved from DisplaySizeCorrector.
+     */
+    private static final Size FALLBACK_DISPLAY_SIZE = new Size(640, 480);
     private static final Object INSTANCE_LOCK = new Object();
     private static volatile DisplayInfoManager sInstance;
     @NonNull
     private final DisplayManager mDisplayManager;
     private volatile Size mPreviewSize = null;
     private final MaxPreviewSize mMaxPreviewSize = new MaxPreviewSize();
+    private final DisplaySizeCorrector mDisplaySizeCorrector = new DisplaySizeCorrector();
 
     private DisplayInfoManager(@NonNull Context context) {
         mDisplayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
@@ -78,50 +89,56 @@
 
     /**
      * Retrieves the display which has the max size among all displays.
+     *
+     * @param skipStateOffDisplay true to skip the displays with off state
      */
-    @SuppressWarnings("deprecation") /* getRealSize */
     @NonNull
-    public Display getMaxSizeDisplay() {
+    public Display getMaxSizeDisplay(boolean skipStateOffDisplay) {
         Display[] displays = mDisplayManager.getDisplays();
         if (displays.length == 1) {
             return displays[0];
         }
 
-        Display maxDisplayWhenStateOn = null;
-        int maxDisplaySizeWhenStateOn = -1;
+        // Try to find the max size display according to the skipStateOffDisplay parameter
+        Display maxDisplay = getMaxSizeDisplayInternal(displays, skipStateOffDisplay);
+
+        // Try to find the max size display from all displays again if no display can be found
+        // when only checking the non-state-off displays.
+        if (maxDisplay == null && skipStateOffDisplay) {
+            maxDisplay = getMaxSizeDisplayInternal(displays, false);
+        }
+
+        // If still no display found, throw IllegalArgumentException.
+        if (maxDisplay == null) {
+            throw new IllegalArgumentException("No display can be found from the input display "
+                    + "manager!");
+        }
+
+        return maxDisplay;
+    }
+
+    @Nullable
+    @SuppressWarnings("deprecation") /* getRealSize */
+    private Display getMaxSizeDisplayInternal(@NonNull Display[] displays,
+            boolean skipStateOffDisplay) {
+        Display maxDisplay = null;
+        int maxDisplaySize = -1;
+
         for (Display display : displays) {
-            if (display.getState() != Display.STATE_OFF) {
-                Point displaySize = new Point();
-                display.getRealSize(displaySize);
-                if (displaySize.x * displaySize.y > maxDisplaySizeWhenStateOn) {
-                    maxDisplaySizeWhenStateOn = displaySize.x * displaySize.y;
-                    maxDisplayWhenStateOn = display;
-                }
+            // Skips displays with state off if the input skipStateOffDisplay parameter is true
+            if (skipStateOffDisplay && display.getState() == Display.STATE_OFF) {
+                continue;
+            }
+
+            Point displaySize = new Point();
+            display.getRealSize(displaySize);
+            if (displaySize.x * displaySize.y > maxDisplaySize) {
+                maxDisplaySize = displaySize.x * displaySize.y;
+                maxDisplay = display;
             }
         }
 
-        if (maxDisplayWhenStateOn == null) {
-            // If there is no display found with state on, search display with state off as well.
-            // If still no display found, throw IllegalArgumentException.
-            Display maxDisplay = null;
-            int maxDisplaySize = -1;
-            for (Display display : displays) {
-                Point displaySize = new Point();
-                display.getRealSize(displaySize);
-                if (displaySize.x * displaySize.y > maxDisplaySize) {
-                    maxDisplaySize = displaySize.x * displaySize.y;
-                    maxDisplay = display;
-                }
-            }
-
-            if (maxDisplay == null) {
-                throw new IllegalArgumentException("No display can be found from the input display "
-                        + "manager!");
-            }
-
-            return maxDisplay;
-        }
-        return maxDisplayWhenStateOn;
+        return maxDisplay;
     }
 
     /**
@@ -139,22 +156,46 @@
         return mPreviewSize;
     }
 
-    @SuppressWarnings("deprecation") /* getRealSize */
     private Size calculatePreviewSize() {
-        Point displaySize = new Point();
-        Display display = getMaxSizeDisplay();
-        display.getRealSize(displaySize);
-        Size displayViewSize;
-        if (displaySize.x > displaySize.y) {
-            displayViewSize = new Size(displaySize.x, displaySize.y);
-        } else {
-            displayViewSize = new Size(displaySize.y, displaySize.x);
-        }
-
+        Size displayViewSize = getCorrectedDisplaySize();
         if (displayViewSize.getWidth() * displayViewSize.getHeight()
                 > MAX_PREVIEW_SIZE.getWidth() * MAX_PREVIEW_SIZE.getHeight()) {
             displayViewSize = MAX_PREVIEW_SIZE;
         }
         return mMaxPreviewSize.getMaxPreviewResolution(displayViewSize);
     }
+
+    @NonNull
+    @SuppressWarnings("deprecation") /* getRealSize */
+    private Size getCorrectedDisplaySize() {
+        Point displaySize = new Point();
+        // The PREVIEW size should be determined by the max display size among all displays on
+        // the device no matter its state is on or off. The PREVIEW size is used for the
+        // guaranteed configurations tables which are related to the camera's capability. The
+        // PREVIEW size should not be affected by the display state.
+        Display display = getMaxSizeDisplay(false);
+        display.getRealSize(displaySize);
+        Size displayViewSize = new Size(displaySize.x, displaySize.y);
+
+        // Checks whether the display size is abnormally small.
+        if (SizeUtil.isSmallerByArea(displayViewSize, ABNORMAL_DISPLAY_SIZE_THRESHOLD)) {
+            // Gets the display size from DisplaySizeCorrector if the display size retrieved from
+            // DisplayManager is abnormally small.
+            displayViewSize = mDisplaySizeCorrector.getDisplaySize();
+
+            // Falls back the display size to 640x480 if DisplaySizeCorrector doesn't contain the
+            // device's display size info.
+            if (displayViewSize == null) {
+                displayViewSize = FALLBACK_DISPLAY_SIZE;
+            }
+        }
+
+        // Flips the size to landscape orientation
+        if (displayViewSize.getHeight() > displayViewSize.getWidth()) {
+            displayViewSize = new Size(/* width= */ displayViewSize.getHeight(), /* height=
+            */ displayViewSize.getWidth());
+        }
+
+        return displayViewSize;
+    }
 }
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/DeviceQuirksLoader.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/DeviceQuirksLoader.java
index ed4d62e..695c99d 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/DeviceQuirksLoader.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/DeviceQuirksLoader.java
@@ -89,6 +89,9 @@
         if (InvalidVideoProfilesQuirk.load()) {
             quirks.add(new InvalidVideoProfilesQuirk());
         }
+        if (SmallDisplaySizeQuirk.load()) {
+            quirks.add(new SmallDisplaySizeQuirk());
+        }
 
         return quirks;
     }
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/SmallDisplaySizeQuirk.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/SmallDisplaySizeQuirk.java
new file mode 100644
index 0000000..fd868c1
--- /dev/null
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/SmallDisplaySizeQuirk.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.camera2.internal.compat.quirk;
+
+import android.os.Build;
+import android.util.Size;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+import androidx.camera.core.impl.Quirk;
+
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+/**
+ * <p>QuirkSummary
+ *     Bug Id: b/287341266
+ *     Description: Quirk required to return the display size for problematic devices. Some
+ *                  devices might return abnormally small display size (16x16). This might cause
+ *                  PREVIEW size to be incorrectly determined and all supported output sizes are
+ *                  filtered out.
+ *     Device(s): Redmi Note8, Redmi Note 7, SM-A207M (see b/287341266 for the devices list)
+ */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
+public class SmallDisplaySizeQuirk implements Quirk {
+
+    private static final String TAG = "SmallDisplaySizeQuirk";
+
+    private static final Map<String, Size> MODEL_TO_DISPLAY_SIZE_MAP =
+            new HashMap<>();
+
+    static {
+        MODEL_TO_DISPLAY_SIZE_MAP.put("REDMI NOTE 8", new Size(1080, 2340));
+        MODEL_TO_DISPLAY_SIZE_MAP.put("REDMI NOTE 7", new Size(1080, 2340));
+        MODEL_TO_DISPLAY_SIZE_MAP.put("SM-A207M", new Size(720, 1560));
+        MODEL_TO_DISPLAY_SIZE_MAP.put("REDMI NOTE 7S", new Size(1080, 2340));
+        MODEL_TO_DISPLAY_SIZE_MAP.put("SM-A127F", new Size(720, 1600));
+        MODEL_TO_DISPLAY_SIZE_MAP.put("SM-A536E", new Size(1080, 2400));
+        MODEL_TO_DISPLAY_SIZE_MAP.put("220233L2I", new Size(720, 1600));
+        MODEL_TO_DISPLAY_SIZE_MAP.put("V2149", new Size(720, 1600));
+        MODEL_TO_DISPLAY_SIZE_MAP.put("VIVO 1920", new Size(1080, 2340));
+        MODEL_TO_DISPLAY_SIZE_MAP.put("CPH2223", new Size(1080, 2400));
+        MODEL_TO_DISPLAY_SIZE_MAP.put("V2029", new Size(720, 1600));
+        MODEL_TO_DISPLAY_SIZE_MAP.put("CPH1901", new Size(720, 1520));
+        MODEL_TO_DISPLAY_SIZE_MAP.put("REDMI Y3", new Size(720, 1520));
+        MODEL_TO_DISPLAY_SIZE_MAP.put("SM-A045M", new Size(720, 1600));
+        MODEL_TO_DISPLAY_SIZE_MAP.put("SM-A146U", new Size(1080, 2408));
+        MODEL_TO_DISPLAY_SIZE_MAP.put("CPH1909", new Size(720, 1520));
+        MODEL_TO_DISPLAY_SIZE_MAP.put("NOKIA 4.2", new Size(720, 1520));
+        MODEL_TO_DISPLAY_SIZE_MAP.put("SM-G960U1", new Size(1440, 2960));
+        MODEL_TO_DISPLAY_SIZE_MAP.put("SM-A137F", new Size(1080, 2408));
+        MODEL_TO_DISPLAY_SIZE_MAP.put("VIVO 1816", new Size(720, 1520));
+        MODEL_TO_DISPLAY_SIZE_MAP.put("INFINIX X6817", new Size(720, 1612));
+        MODEL_TO_DISPLAY_SIZE_MAP.put("SM-A037F", new Size(720, 1600));
+        MODEL_TO_DISPLAY_SIZE_MAP.put("NOKIA 2.4", new Size(720, 1600));
+        MODEL_TO_DISPLAY_SIZE_MAP.put("SM-A125M", new Size(720, 1600));
+        MODEL_TO_DISPLAY_SIZE_MAP.put("INFINIX X670", new Size(1080, 2400));
+    }
+
+    static boolean load() {
+        return MODEL_TO_DISPLAY_SIZE_MAP.containsKey(Build.MODEL.toUpperCase(Locale.US));
+    }
+
+    @NonNull
+    public Size getDisplaySize() {
+        return MODEL_TO_DISPLAY_SIZE_MAP.get(Build.MODEL.toUpperCase(Locale.US));
+    }
+}
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/workaround/DisplaySizeCorrector.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/workaround/DisplaySizeCorrector.java
new file mode 100644
index 0000000..ff0bc23
--- /dev/null
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/workaround/DisplaySizeCorrector.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.camera2.internal.compat.workaround;
+
+import android.util.Size;
+
+import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
+import androidx.camera.camera2.internal.compat.quirk.DeviceQuirks;
+import androidx.camera.camera2.internal.compat.quirk.SmallDisplaySizeQuirk;
+
+/**
+ * Provides the correct display size for the problematic devices which might return abnormally
+ * small display size.
+ */
+@RequiresApi(21)
+public class DisplaySizeCorrector {
+
+    @Nullable
+    private final SmallDisplaySizeQuirk mSmallDisplaySizeQuirk;
+
+    /**
+     * Constructor.
+     */
+    public DisplaySizeCorrector() {
+        mSmallDisplaySizeQuirk = DeviceQuirks.get(SmallDisplaySizeQuirk.class);
+    }
+
+    /**
+     * Returns the device's correct display size if it is included in the SmallDisplaySizeQuirk.
+     */
+    @Nullable
+    public Size getDisplaySize() {
+        return mSmallDisplaySizeQuirk != null ? mSmallDisplaySizeQuirk.getDisplaySize() : null;
+    }
+}
diff --git a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/DisplayInfoManagerTest.kt b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/DisplayInfoManagerTest.kt
index 8fff586..980dfe6 100644
--- a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/DisplayInfoManagerTest.kt
+++ b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/DisplayInfoManagerTest.kt
@@ -22,6 +22,7 @@
 import android.os.Build
 import android.util.Size
 import android.view.Display
+import android.view.WindowManager
 import androidx.test.core.app.ApplicationProvider
 import com.google.common.truth.Truth.assertThat
 import org.junit.After
@@ -31,12 +32,14 @@
 import org.mockito.Mockito.times
 import org.mockito.Mockito.verify
 import org.robolectric.RobolectricTestRunner
+import org.robolectric.Shadows
 import org.robolectric.annotation.Config
 import org.robolectric.annotation.internal.DoNotInstrument
 import org.robolectric.shadow.api.Shadow
 import org.robolectric.shadows.ShadowDisplay
 import org.robolectric.shadows.ShadowDisplayManager
 import org.robolectric.shadows.ShadowDisplayManager.removeDisplay
+import org.robolectric.util.ReflectionHelpers
 
 @RunWith(RobolectricTestRunner::class)
 @DoNotInstrument
@@ -71,7 +74,7 @@
         val displayInfoManager = DisplayInfoManager
             .getInstance(ApplicationProvider.getApplicationContext())
         val size = Point()
-        displayInfoManager.maxSizeDisplay.getRealSize(size)
+        displayInfoManager.getMaxSizeDisplay(false).getRealSize(size)
 
         // Assert
         assertThat(size).isEqualTo(currentDisplaySize)
@@ -87,7 +90,7 @@
         val displayInfoManager = DisplayInfoManager
             .getInstance(ApplicationProvider.getApplicationContext())
         val size = Point()
-        displayInfoManager.maxSizeDisplay.getRealSize(size)
+        displayInfoManager.getMaxSizeDisplay(false).getRealSize(size)
 
         // Assert
         assertThat(size).isEqualTo(Point(2000, 3000))
@@ -104,7 +107,7 @@
         val displayInfoManager = DisplayInfoManager
             .getInstance(ApplicationProvider.getApplicationContext())
         val size = Point()
-        displayInfoManager.maxSizeDisplay.getRealSize(size)
+        displayInfoManager.getMaxSizeDisplay(true).getRealSize(size)
 
         // Assert
         assertThat(size).isEqualTo(Point(480, 640))
@@ -119,7 +122,7 @@
         val displayInfoManager = DisplayInfoManager
             .getInstance(ApplicationProvider.getApplicationContext())
         val size = Point()
-        displayInfoManager.maxSizeDisplay.getRealSize(size)
+        displayInfoManager.getMaxSizeDisplay(false).getRealSize(size)
     }
 
     @Test
@@ -134,7 +137,7 @@
         val displayInfoManager = DisplayInfoManager
             .getInstance(ApplicationProvider.getApplicationContext())
         val size = Point()
-        displayInfoManager.maxSizeDisplay.getRealSize(size)
+        displayInfoManager.getMaxSizeDisplay(true).getRealSize(size)
 
         // Assert
         assertThat(size).isEqualTo(Point(2000, 3000))
@@ -176,6 +179,38 @@
         displayInfoManager.previewSize
 
         // Assert
-        verify(displayInfoManager, times(2)).maxSizeDisplay
+        verify(displayInfoManager, times(2)).getMaxSizeDisplay(false)
+    }
+
+    @Test
+    fun canReturnFallbackPreviewSize640x480_displaySmallerThan320x240() {
+        // Arrange
+        DisplayInfoManager.releaseInstance()
+        val windowManager = ApplicationProvider.getApplicationContext<Context>()
+            .getSystemService(Context.WINDOW_SERVICE) as WindowManager
+        Shadows.shadowOf(windowManager.defaultDisplay).setRealWidth(16)
+        Shadows.shadowOf(windowManager.defaultDisplay).setRealHeight(16)
+
+        // Act & Assert
+        val displayInfoManager = DisplayInfoManager
+            .getInstance(ApplicationProvider.getApplicationContext())
+        assertThat(displayInfoManager.previewSize).isEqualTo(Size(640, 480))
+    }
+
+    @Test
+    fun canReturnCorrectPreviewSize_fromDisplaySizeCorrector() {
+        // Arrange
+        DisplayInfoManager.releaseInstance()
+        val windowManager = ApplicationProvider.getApplicationContext<Context>()
+            .getSystemService(Context.WINDOW_SERVICE) as WindowManager
+        Shadows.shadowOf(windowManager.defaultDisplay).setRealWidth(16)
+        Shadows.shadowOf(windowManager.defaultDisplay).setRealHeight(16)
+
+        ReflectionHelpers.setStaticField(Build::class.java, "MODEL", "SM-A127F")
+
+        // Act & Assert
+        val displayInfoManager = DisplayInfoManager
+            .getInstance(ApplicationProvider.getApplicationContext())
+        assertThat(displayInfoManager.previewSize).isEqualTo(Size(1600, 720))
     }
 }
\ No newline at end of file
diff --git a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/compat/workaround/DisplaySizeCorrectorTest.kt b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/compat/workaround/DisplaySizeCorrectorTest.kt
new file mode 100644
index 0000000..e50212b
--- /dev/null
+++ b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/compat/workaround/DisplaySizeCorrectorTest.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.camera2.internal.compat.workaround
+
+import android.os.Build
+import android.util.Size
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
+import org.robolectric.annotation.Config
+import org.robolectric.annotation.internal.DoNotInstrument
+import org.robolectric.util.ReflectionHelpers
+
+@RunWith(RobolectricTestRunner::class)
+@DoNotInstrument
+@Config(minSdk = Build.VERSION_CODES.LOLLIPOP)
+class DisplaySizeCorrectorTest {
+    @Test
+    fun returnCorrectDisplaySizeForProblematicDevice() {
+        ReflectionHelpers.setStaticField(Build::class.java, "MODEL", "REDMI NOTE 8")
+        // See SmallDisplaySizeQuirk for the device display size
+        assertThat(DisplaySizeCorrector().displaySize).isEqualTo(Size(1080, 2340))
+    }
+
+    @Test
+    fun returnNullDisplaySizeForProblematicDevice() {
+        ReflectionHelpers.setStaticField(Build::class.java, "MODEL", "Fake-Model")
+        // See SmallDisplaySizeQuirk for the device display size
+        assertThat(DisplaySizeCorrector().displaySize).isNull()
+    }
+}
\ No newline at end of file
diff --git a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/camera2/PreviewTest.kt b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/camera2/PreviewTest.kt
index 3cc62cf..00a4ae3 100644
--- a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/camera2/PreviewTest.kt
+++ b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/camera2/PreviewTest.kt
@@ -397,7 +397,8 @@
 
     @Test
     fun targetRotationReturnsDisplayRotationIfNotSet() {
-        val displayRotation = DisplayInfoManager.getInstance(context!!).maxSizeDisplay.rotation
+        val displayRotation =
+            DisplayInfoManager.getInstance(context!!).getMaxSizeDisplay(true).rotation
         val useCase = defaultBuilder!!.build()
         camera = CameraUtil.createCameraAndAttachUseCase(context!!, cameraSelector, useCase)