Fix the preview is stretched on Nexus 4

There is a Camera1/HAL1 issue on the Nexus 4. The preview will be stretched when configuring a JPEG that doesn't actually have the same aspect ratio as the maximum JPEG resolution.

Workaround the issue by only configuring the size has the same aspect ratio as the maximum JPEG resolution to all the UseCases on Nexus 4.

Relnote:"Fixed an issue where the preview was stretched on Nexus 4 devices running Android L (API levels 21 and 22)."

Bug: b/158749159
Test: run TargetAspectRatioTest
Change-Id: I4d407ee366c978de4e518995e97d5946fc19e29a
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 343bbda..3bfcddb 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
@@ -45,6 +45,9 @@
         if (SamsungPreviewTargetAspectRatioQuirk.load()) {
             quirks.add(new SamsungPreviewTargetAspectRatioQuirk());
         }
+        if (Nexus4AndroidLTargetAspectRatioQuirk.load()) {
+            quirks.add(new Nexus4AndroidLTargetAspectRatioQuirk());
+        }
         if (ExcludedSupportedSizesQuirk.load()) {
             quirks.add(new ExcludedSupportedSizesQuirk());
         }
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/Nexus4AndroidLTargetAspectRatioQuirk.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/Nexus4AndroidLTargetAspectRatioQuirk.java
new file mode 100644
index 0000000..0f16efd
--- /dev/null
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/Nexus4AndroidLTargetAspectRatioQuirk.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2020 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 androidx.camera.camera2.internal.compat.workaround.TargetAspectRatio;
+import androidx.camera.core.impl.Quirk;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Quirk that produces stretched preview on Nexus 4 devices running Android L(API levels 21 and 22).
+ *
+ * <p> There is a Camera1/HAL1 issue on the Nexus 4. The preview will be stretched when
+ * configuring a JPEG that doesn't actually have the same aspect ratio as the maximum JPEG
+ * resolution. See: b/19606058.
+ */
+public class Nexus4AndroidLTargetAspectRatioQuirk implements Quirk {
+    // List of devices with the issue.
+    private static final List<String> DEVICE_MODELS = Arrays.asList(
+            "NEXUS 4" // b/158749159
+    );
+
+    static boolean load() {
+        return "GOOGLE".equals(Build.BRAND.toUpperCase()) && Build.VERSION.SDK_INT < 23
+                && DEVICE_MODELS.contains(android.os.Build.MODEL.toUpperCase());
+    }
+
+    /**
+     * Get the corrected aspect ratio.
+     */
+    @TargetAspectRatio.Ratio
+    public int getCorrectedAspectRatio() {
+        return TargetAspectRatio.RATIO_MAX_JPEG;
+    }
+}
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/SamsungPreviewTargetAspectRatioQuirk.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/SamsungPreviewTargetAspectRatioQuirk.java
index f256dab..c5637ee 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/SamsungPreviewTargetAspectRatioQuirk.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/SamsungPreviewTargetAspectRatioQuirk.java
@@ -41,7 +41,7 @@
     );
 
     static boolean load() {
-        return "SAMSUNG".equals(Build.MANUFACTURER.toUpperCase())
+        return "SAMSUNG".equals(Build.BRAND.toUpperCase())
                 && DEVICE_MODELS.contains(android.os.Build.MODEL.toUpperCase());
     }
 
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/workaround/TargetAspectRatio.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/workaround/TargetAspectRatio.java
index 13936af..6583a0b 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/workaround/TargetAspectRatio.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/workaround/TargetAspectRatio.java
@@ -23,6 +23,7 @@
 import androidx.camera.camera2.internal.compat.quirk.AspectRatioLegacyApi21Quirk;
 import androidx.camera.camera2.internal.compat.quirk.CameraQuirks;
 import androidx.camera.camera2.internal.compat.quirk.DeviceQuirks;
+import androidx.camera.camera2.internal.compat.quirk.Nexus4AndroidLTargetAspectRatioQuirk;
 import androidx.camera.camera2.internal.compat.quirk.SamsungPreviewTargetAspectRatioQuirk;
 import androidx.camera.core.impl.ImageOutputConfig;
 
@@ -33,6 +34,7 @@
  * Workaround to get corrected target aspect ratio.
  *
  * @see SamsungPreviewTargetAspectRatioQuirk
+ * @see Nexus4AndroidLTargetAspectRatioQuirk
  * @see AspectRatioLegacyApi21Quirk
  */
 public class TargetAspectRatio {
@@ -56,6 +58,11 @@
         if (samsungQuirk != null && samsungQuirk.require16_9(imageOutputConfig)) {
             return TargetAspectRatio.RATIO_16_9;
         }
+        final Nexus4AndroidLTargetAspectRatioQuirk nexus4AndroidLQuirk =
+                DeviceQuirks.get(Nexus4AndroidLTargetAspectRatioQuirk.class);
+        if (nexus4AndroidLQuirk != null) {
+            return nexus4AndroidLQuirk.getCorrectedAspectRatio();
+        }
 
         final AspectRatioLegacyApi21Quirk quirk = CameraQuirks.get(cameraId,
                 cameraCharacteristicsCompat).get(AspectRatioLegacyApi21Quirk.class);
diff --git a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/compat/workaround/TargetAspectRatioTest.java b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/compat/workaround/TargetAspectRatioTest.java
index 1311ac6..1541f10 100644
--- a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/compat/workaround/TargetAspectRatioTest.java
+++ b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/compat/workaround/TargetAspectRatioTest.java
@@ -86,6 +86,19 @@
         data.add(new Object[]{new Config("Samsung", "SM-T580", false,
                 INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED, RATIO_16_9, RATIO_ORIGINAL,
                 ALL_API_LEVELS)});
+        data.add(new Object[]{new Config("Google", "Nexus 4", true,
+                INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY, RATIO_4_3, RATIO_MAX_JPEG,
+                new Range<>(21, 22))});
+        data.add(new Object[]{new Config("Google", "Nexus 4", true,
+                INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY, RATIO_16_9, RATIO_MAX_JPEG,
+                new Range<>(21, 22))});
+        data.add(new Object[]{new Config("Google", "Nexus 4", false,
+                INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY, RATIO_4_3, RATIO_MAX_JPEG,
+                new Range<>(21, 22))});
+        data.add(new Object[]{new Config("Google", "Nexus 4", false,
+                INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY, RATIO_16_9, RATIO_MAX_JPEG,
+                new Range<>(21, 22))});
+
         data.add(new Object[]{new Config(null, null, true,
                 INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED, RATIO_4_3, RATIO_ORIGINAL, ALL_API_LEVELS)});
         data.add(new Object[]{new Config(null, null, true,
@@ -119,8 +132,8 @@
     @Test
     public void getCorrectedRatio() {
         // Set up device properties
-        if (mConfig.mManufacturer != null) {
-            ReflectionHelpers.setStaticField(Build.class, "MANUFACTURER", mConfig.mManufacturer);
+        if (mConfig.mBrand != null) {
+            ReflectionHelpers.setStaticField(Build.class, "BRAND", mConfig.mBrand);
             ReflectionHelpers.setStaticField(Build.class, "MODEL", mConfig.mModel);
         }
 
@@ -161,7 +174,7 @@
 
     static class Config {
         @Nullable
-        final String mManufacturer;
+        final String mBrand;
         @Nullable
         final String mModel;
         final boolean mIsPreview;
@@ -172,11 +185,11 @@
         final int mHardwareLevel;
         final Range<Integer> mAffectedApiLevels;
 
-        Config(@Nullable String manufacturer, @Nullable String model, boolean isPreview,
-                int hardwareLevel, @AspectRatio.Ratio int inputAspectRatio,
+        Config(@Nullable String brand, @Nullable String model, boolean isPreview, int hardwareLevel,
+                @AspectRatio.Ratio int inputAspectRatio,
                 @TargetAspectRatio.Ratio int expectedAspectRatio,
                 @NonNull Range<Integer> affectedApiLevels) {
-            mManufacturer = manufacturer;
+            mBrand = brand;
             mModel = model;
             mIsPreview = isPreview;
             mHardwareLevel = hardwareLevel;