am 1cd3c6b2: Camera2: Replace int[] by MeteringRectangle

* commit '1cd3c6b2cd63b73a0a87a7cfb68fcadc577296fb':
  Camera2: Replace int[] by MeteringRectangle
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraTestUtils.java b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraTestUtils.java
index e157b4c..52a486f 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraTestUtils.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraTestUtils.java
@@ -31,6 +31,7 @@
 import android.hardware.camera2.CaptureResult;
 import android.hardware.camera2.TotalCaptureResult;
 import android.util.Size;
+import android.hardware.camera2.params.MeteringRectangle;
 import android.hardware.camera2.params.StreamConfigurationMap;
 import android.media.Image;
 import android.media.ImageReader;
@@ -881,21 +882,22 @@
     /**
      * Calculate output 3A region from the intersection of input 3A region and cropped region.
      *
-     * @param requestRegion The input 3A region [xmin, ymin, xmax, ymax, weight]
+     * @param requestRegions The input 3A regions
      * @param cropRect The cropped region
-     * @return expected 3A region output in capture result
+     * @return expected 3A regions output in capture result
      */
-    public static int[] getExpectedOutputRegion(int[] requestRegion, Rect cropRect){
-        Rect requestRect = new Rect(requestRegion[0], requestRegion[1],
-                requestRegion[2], requestRegion[3]);
-        Rect resultRect = new Rect();
-        assertTrue("Input 3A region must intersect cropped region",
-                    resultRect.setIntersect(requestRect, cropRect));
-        return new int[] {
-                resultRect.left,
-                resultRect.top,
-                resultRect.right,
-                resultRect.bottom,
-                requestRegion[4]};
+    public static MeteringRectangle[] getExpectedOutputRegion(
+            MeteringRectangle[] requestRegions, Rect cropRect){
+        MeteringRectangle[] resultRegions = new MeteringRectangle[requestRegions.length];
+        for (int i = 0; i < requestRegions.length; i++) {
+            Rect requestRect = requestRegions[i].getRect();
+            Rect resultRect = new Rect();
+            assertTrue("Input 3A region must intersect cropped region",
+                        resultRect.setIntersect(requestRect, cropRect));
+            resultRegions[i] = new MeteringRectangle(
+                    resultRect,
+                    requestRegions[i].getMeteringWeight());
+        }
+        return resultRegions;
     }
 }
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureRequestTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureRequestTest.java
index add91a4..6ff9182 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureRequestTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureRequestTest.java
@@ -30,6 +30,7 @@
 import android.hardware.camera2.cts.CameraTestUtils.SimpleCaptureListener;
 import android.hardware.camera2.cts.testcases.Camera2SurfaceViewTestCase;
 import android.hardware.camera2.params.Face;
+import android.hardware.camera2.params.MeteringRectangle;
 import android.util.Log;
 import android.util.Rational;
 import android.util.Size;
@@ -93,7 +94,6 @@
     private final int INDEX_ALGORITHM_AE = 0;
     private final int INDEX_ALGORITHM_AWB = 1;
     private final int INDEX_ALGORITHM_AF = 2;
-    private final int LENGTH_ALGORITHM_REGION = 5;
 
     @Override
     protected void setUp() throws Exception {
@@ -1518,7 +1518,7 @@
         final float maxZoom = mStaticInfo.getAvailableMaxDigitalZoomChecked();
         final Rect activeArraySize = mStaticInfo.getActiveArraySizeChecked();
         Rect[] cropRegions = new Rect[ZOOM_STEPS];
-        int [][] expectRegions = new int[ZOOM_STEPS][];
+        MeteringRectangle[][] expectRegions = new MeteringRectangle[ZOOM_STEPS][];
         Size maxPreviewSize = mOrderedPreviewSizes.get(0);
         CaptureRequest.Builder requestBuilder =
                 mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
@@ -1528,16 +1528,12 @@
 
         // Set algorithm regions to full active region
         // TODO: test more different 3A regions
-        final int[] algoDefaultRegion = new int[] {
-            0, // xmin
-            0, // ymin
-            activeArraySize.width() - 1,  // xmax
-            activeArraySize.height() - 1, // ymax
-            1, // weight
-        };
+        final MeteringRectangle[] defaultMeteringRect = new MeteringRectangle[] {
+                new MeteringRectangle (
+                        0, 0, activeArraySize.width(), activeArraySize.height(), 1)};
 
         for (int algo = 0; algo < NUM_ALGORITHMS; algo++) {
-            update3aRegion(requestBuilder, algo,  algoDefaultRegion);
+            update3aRegion(requestBuilder, algo,  defaultMeteringRect);
         }
 
         for (PointF center : TEST_ZOOM_CENTERS) {
@@ -1551,7 +1547,7 @@
                 requestBuilder.set(CaptureRequest.SCALER_CROP_REGION, cropRegions[i]);
                 requests[i] = requestBuilder.build();
                 expectRegions[i] = getExpectedOutputRegion(
-                        /*requestRegion*/algoDefaultRegion,
+                        /*requestRegion*/defaultMeteringRect,
                         /*cropRect*/     cropRegions[i]);
                 mCamera.capture(requests[i], listener, mHandler);
             }
@@ -1564,7 +1560,7 @@
                  Rect cropRegion = getValueNotNull(result, CaptureResult.SCALER_CROP_REGION);
                  // Verify Output 3A region is intersection of input 3A region and crop region
                  for (int algo = 0; algo < NUM_ALGORITHMS; algo++) {
-                     validate3aRegion(result,algo,  expectRegions[i]);
+                     validate3aRegion(result, algo, expectRegions[i]);
                  }
                  mCollector.expectEquals(" Request and result crop region should match",
                          cropRegions[i], cropRegion);
@@ -1929,28 +1925,28 @@
      * if the specified 3A region is not supported by camera device.
      * @param requestBuilder The request to be updated
      * @param algoIdx The index to the algorithm. (AE: 0, AWB: 1, AF: 2)
-     * @param region The 3A region to be set
+     * @param regions The 3A regions to be set
      */
-    private void update3aRegion(CaptureRequest.Builder requestBuilder, int algoIdx, int[] region)
+    private void update3aRegion(
+            CaptureRequest.Builder requestBuilder, int algoIdx, MeteringRectangle[] regions)
     {
         int[] maxRegions = mStaticInfo.get3aMaxRegionsChecked();
 
-        if (region.length == 0 ||
-                region.length % LENGTH_ALGORITHM_REGION != 0) {
+        if (regions == null || regions.length == 0) {
             throw new IllegalArgumentException("Invalid input 3A region!");
         }
 
-        if (maxRegions[algoIdx] * LENGTH_ALGORITHM_REGION >= region.length)
+        if (maxRegions[algoIdx] >= regions.length)
         {
             switch (algoIdx) {
                 case INDEX_ALGORITHM_AE:
-                    requestBuilder.set(CaptureRequest.CONTROL_AE_REGIONS, region);
+                    requestBuilder.set(CaptureRequest.CONTROL_AE_REGIONS, regions);
                     break;
                 case INDEX_ALGORITHM_AWB:
-                    requestBuilder.set(CaptureRequest.CONTROL_AWB_REGIONS, region);
+                    requestBuilder.set(CaptureRequest.CONTROL_AWB_REGIONS, regions);
                     break;
                 case INDEX_ALGORITHM_AF:
-                    requestBuilder.set(CaptureRequest.CONTROL_AF_REGIONS, region);
+                    requestBuilder.set(CaptureRequest.CONTROL_AF_REGIONS, regions);
                     break;
                 default:
                     throw new IllegalArgumentException("Unknown 3A Algorithm!");
@@ -1963,17 +1959,13 @@
      * supported. Do nothing if the specified 3A region is not supported by camera device.
      * @param result The capture result to be validated
      * @param algoIdx The index to the algorithm. (AE: 0, AWB: 1, AF: 2)
-     * @param expectRegion The 3A region expected
+     * @param expectRegion The 3A regions expected in capture result
      */
-    private void validate3aRegion(CaptureResult result, int algoIdx, int[] expectRegion)
+    private void validate3aRegion(
+            CaptureResult result, int algoIdx, MeteringRectangle[] expectRegion)
     {
         int[] maxRegions = mStaticInfo.get3aMaxRegionsChecked();
-        int[] actualRegion;
-
-        if (expectRegion.length == 0 ||
-                expectRegion.length % LENGTH_ALGORITHM_REGION != 0) {
-            throw new IllegalArgumentException("Invalid expected 3A region!");
-        }
+        MeteringRectangle[] actualRegion;
 
         if (maxRegions[algoIdx] > 0)
         {
@@ -1993,8 +1985,7 @@
             mCollector.expectEquals(
                     "Expected 3A region: " + Arrays.toString(expectRegion) +
                     " does not match actual one: " + Arrays.toString(actualRegion),
-                    toObject(expectRegion),
-                    toObject(actualRegion));
+                    expectRegion, actualRegion);
         }
     }
 }
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/StillCaptureTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/StillCaptureTest.java
index 9f0af9b..6a5ae9a 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/StillCaptureTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/StillCaptureTest.java
@@ -28,6 +28,7 @@
 import android.hardware.camera2.cts.CameraTestUtils.SimpleImageReaderListener;
 import android.hardware.camera2.cts.helpers.Camera2Focuser;
 import android.hardware.camera2.cts.testcases.Camera2SurfaceViewTestCase;
+import android.hardware.camera2.params.MeteringRectangle;
 import android.media.ExifInterface;
 import android.media.Image;
 import android.os.Build;
@@ -39,6 +40,7 @@
 
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Date;
 import java.util.List;
@@ -46,7 +48,7 @@
 public class StillCaptureTest extends Camera2SurfaceViewTestCase {
     private static final String TAG = "StillCaptureTest";
     private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);;
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
     private static final String JPEG_FILE_NAME = DEBUG_FILE_NAME_BASE + "/test.jpeg";
     // 60 second to accommodate the possible long exposure time.
     private static final int EXIF_DATETIME_ERROR_MARGIN_SEC = 60;
@@ -254,9 +256,9 @@
                     continue;
                 }
 
-                int[][] aeRegions = get3ATestRegionsForCamera();
-                for (int i = 0; i < aeRegions.length; i++) {
-                    takePictureTestByCamera(aeRegions[i], /*awbRegions*/null, /*afRegions*/null);
+                ArrayList<MeteringRectangle[]> aeRegionTestCases = get3ARegionTestCasesForCamera();
+                for (MeteringRectangle[] aeRegions : aeRegionTestCases) {
+                    takePictureTestByCamera(aeRegions, /*awbRegions*/null, /*afRegions*/null);
                 }
             } finally {
                 closeDevice();
@@ -279,9 +281,9 @@
                     continue;
                 }
 
-                int[][] awbRegions = get3ATestRegionsForCamera();
-                for (int i = 0; i < awbRegions.length; i++) {
-                    takePictureTestByCamera(/*aeRegions*/null, awbRegions[i], /*afRegions*/null);
+                ArrayList<MeteringRectangle[]> awbRegionTestCases = get3ARegionTestCasesForCamera();
+                for (MeteringRectangle[] awbRegions : awbRegionTestCases) {
+                    takePictureTestByCamera(/*aeRegions*/null, awbRegions, /*afRegions*/null);
                 }
             } finally {
                 closeDevice();
@@ -304,9 +306,9 @@
                     continue;
                 }
 
-                int[][] afRegions = get3ATestRegionsForCamera();
-                for (int i = 0; i < afRegions.length; i++) {
-                    takePictureTestByCamera(/*aeRegions*/null, /*awbRegions*/null, afRegions[i]);
+                ArrayList<MeteringRectangle[]> afRegionTestCases = get3ARegionTestCasesForCamera();
+                for (MeteringRectangle[] afRegions : afRegionTestCases) {
+                    takePictureTestByCamera(/*aeRegions*/null, /*awbRegions*/null, afRegions);
                 }
             } finally {
                 closeDevice();
@@ -381,8 +383,10 @@
      * @param awbRegions AWB regions for this capture
      * @param afRegions AF regions for this capture
      */
-    private void takePictureTestByCamera(int[] aeRegions, int[] awbRegions, int[] afRegions)
-            throws Exception {
+    private void takePictureTestByCamera(
+            MeteringRectangle[] aeRegions, MeteringRectangle[] awbRegions,
+            MeteringRectangle[] afRegions) throws Exception {
+
         boolean hasFocuser = mStaticInfo.hasFocuser();
 
         Size maxStillSz = mOrderedStillSizes.get(0);
@@ -459,10 +463,10 @@
                 previewRequest.get(CaptureRequest.CONTROL_AWB_MODE),
                 result.get(CaptureResult.CONTROL_AWB_MODE));
         if (canSetAwbRegion) {
-            int[] resultAwbRegions = getValueNotNull(result, CaptureResult.CONTROL_AWB_REGIONS);
+            MeteringRectangle[] resultAwbRegions =
+                    getValueNotNull(result, CaptureResult.CONTROL_AWB_REGIONS);
             mCollector.expectEquals("AWB regions in result and request should be same",
-                    toObject(awbRegions),
-                    toObject(resultAwbRegions));
+                    awbRegions, resultAwbRegions);
         }
 
         /**
@@ -486,10 +490,10 @@
                 previewRequest.get(CaptureRequest.CONTROL_AE_MODE),
                 result.get(CaptureResult.CONTROL_AE_MODE));
         if (canSetAeRegion) {
-            int[] resultAeRegions = getValueNotNull(result, CaptureResult.CONTROL_AE_REGIONS);
+            MeteringRectangle[] resultAeRegions =
+                    getValueNotNull(result, CaptureResult.CONTROL_AE_REGIONS);
             mCollector.expectEquals("AE regions in result and request should be same",
-                    toObject(aeRegions),
-                    toObject(resultAeRegions));
+                    aeRegions, resultAeRegions);
         }
 
         /**
@@ -504,10 +508,10 @@
                 stillRequest.get(CaptureRequest.CONTROL_AF_MODE),
                 result.get(CaptureResult.CONTROL_AF_MODE));
         if (canSetAfRegion) {
-            int[] resultAfRegions = getValueNotNull(result, CaptureResult.CONTROL_AF_REGIONS);
+            MeteringRectangle[] resultAfRegions =
+                    getValueNotNull(result, CaptureResult.CONTROL_AF_REGIONS);
             mCollector.expectEquals("AF regions in result and request should be same",
-                    toObject(afRegions),
-                    toObject(resultAfRegions));
+                    afRegions, resultAfRegions);
         }
 
         if (hasFocuser) {
@@ -535,10 +539,10 @@
         SimpleAutoFocusListener afListener = new SimpleAutoFocusListener();
         Camera2Focuser focuser = new Camera2Focuser(mCamera, mPreviewSurface, afListener,
                 mStaticInfo.getCharacteristics(), mHandler);
-        int[][] testAfRegions = get3ATestRegionsForCamera();
+        ArrayList<MeteringRectangle[]> testAfRegions = get3ARegionTestCasesForCamera();
 
-        for (int i = 0; i < testAfRegions.length; i++) {
-            focuser.touchForAutoFocus(testAfRegions[i]);
+        for (MeteringRectangle[] afRegions : testAfRegions) {
+            focuser.touchForAutoFocus(afRegions);
             afListener.waitForAutoFocusDone(WAIT_FOR_FOCUS_DONE_TIMEOUT_MS);
             focuser.cancelAutoFocus();
         }
@@ -1206,71 +1210,89 @@
     }
 
     /**
-     * Get 5 3A test square regions, one is at center, the other four are at corners of
+     * Get 5 3A region test cases, each with one square region in it.
+     * The first one is at center, the other four are at corners of
      * active array rectangle.
      *
      * @return array of test 3A regions
      */
-    private int[][] get3ATestRegionsForCamera() {
+    private ArrayList<MeteringRectangle[]> get3ARegionTestCasesForCamera() {
         final int TEST_3A_REGION_NUM = 5;
-        final int NUM_ELEMENT_IN_REGION = 5;
         final int DEFAULT_REGION_WEIGHT = 30;
         final int DEFAULT_REGION_SCALE_RATIO = 8;
-        int[][] regions = new int[TEST_3A_REGION_NUM][NUM_ELEMENT_IN_REGION];
+        ArrayList<MeteringRectangle[]> testCases =
+                new ArrayList<MeteringRectangle[]>(TEST_3A_REGION_NUM);
         final Rect activeArraySize = mStaticInfo.getActiveArraySizeChecked();
-        int regionWidth = activeArraySize.width() / DEFAULT_REGION_SCALE_RATIO;
-        int regionHeight = activeArraySize.height() / DEFAULT_REGION_SCALE_RATIO;
+        int regionWidth = activeArraySize.width() / DEFAULT_REGION_SCALE_RATIO - 1;
+        int regionHeight = activeArraySize.height() / DEFAULT_REGION_SCALE_RATIO - 1;
         int centerX = activeArraySize.width() / 2;
         int centerY = activeArraySize.height() / 2;
         int bottomRightX = activeArraySize.width() - 1;
         int bottomRightY = activeArraySize.height() - 1;
 
         // Center region
-        int i = 0;
-        regions[i][0] = centerX - regionWidth / 2;       // xmin
-        regions[i][1] = centerY - regionHeight / 2;      // ymin
-        regions[i][2] = centerX + regionWidth / 2 - 1;   // xmax
-        regions[i][3] = centerY + regionHeight / 2 - 1;  // ymax
-        regions[i][4] = DEFAULT_REGION_WEIGHT;
-        i++;
+        testCases.add(
+                new MeteringRectangle[] {
+                    new MeteringRectangle(
+                            centerX - regionWidth / 2,  // x
+                            centerY - regionHeight / 2, // y
+                            regionWidth,                // width
+                            regionHeight,               // height
+                            DEFAULT_REGION_WEIGHT)});
 
         // Upper left corner
-        regions[i][0] = 0;                // xmin
-        regions[i][1] = 0;                // ymin
-        regions[i][2] = regionWidth - 1;  // xmax
-        regions[i][3] = regionHeight - 1; // ymax
-        regions[i][4] = DEFAULT_REGION_WEIGHT;
-        i++;
+        testCases.add(
+                new MeteringRectangle[] {
+                    new MeteringRectangle(
+                            0,                // x
+                            0,                // y
+                            regionWidth,      // width
+                            regionHeight,     // height
+                            DEFAULT_REGION_WEIGHT)});
 
         // Upper right corner
-        regions[i][0] = activeArraySize.width() - regionWidth; // xmin
-        regions[i][1] = 0;                                     // ymin
-        regions[i][2] = bottomRightX;                          // xmax
-        regions[i][3] = regionHeight - 1;                      // ymax
-        regions[i][4] = DEFAULT_REGION_WEIGHT;
-        i++;
+        testCases.add(
+                new MeteringRectangle[] {
+                    new MeteringRectangle(
+                            bottomRightX - regionWidth, // x
+                            0,                          // y
+                            regionWidth,                // width
+                            regionHeight,               // height
+                            DEFAULT_REGION_WEIGHT)});
 
         // Bootom left corner
-        regions[i][0] = 0;                                       // xmin
-        regions[i][1] = activeArraySize.height() - regionHeight; // ymin
-        regions[i][2] = regionWidth - 1;                         // xmax
-        regions[i][3] = bottomRightY;                            // ymax
-        regions[i][4] = DEFAULT_REGION_WEIGHT;
-        i++;
+        testCases.add(
+                new MeteringRectangle[] {
+                    new MeteringRectangle(
+                            0,                           // x
+                            bottomRightY - regionHeight, // y
+                            regionWidth,                 // width
+                            regionHeight,                // height
+                            DEFAULT_REGION_WEIGHT)});
 
         // Bootom right corner
-        regions[i][0] = activeArraySize.width() - regionWidth;   // xmin
-        regions[i][1] = activeArraySize.height() - regionHeight; // ymin
-        regions[i][2] = bottomRightX;                            // xmax
-        regions[i][3] = bottomRightY;                            // ymax
-        regions[i][4] = DEFAULT_REGION_WEIGHT;
-        i++;
+        testCases.add(
+                new MeteringRectangle[] {
+                    new MeteringRectangle(
+                            bottomRightX - regionWidth,  // x
+                            bottomRightY - regionHeight, // y
+                            regionWidth,                 // width
+                            regionHeight,                // height
+                            DEFAULT_REGION_WEIGHT)});
 
         if (VERBOSE) {
-            Log.v(TAG, "Generated test regions are: " + Arrays.deepToString(regions));
+            StringBuilder sb = new StringBuilder();
+            for (MeteringRectangle[] mr : testCases) {
+                sb.append("{");
+                sb.append(Arrays.toString(mr));
+                sb.append("}, ");
+            }
+            if (sb.length() > 1)
+                sb.setLength(sb.length() - 2); // Remove the redundant comma and space at the end
+            Log.v(TAG, "Generated test regions are: " + sb.toString());
         }
 
-        return regions;
+        return testCases;
     }
 
     private boolean isRegionsSupportedFor3A(int index) {
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/Camera2Focuser.java b/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/Camera2Focuser.java
index b1fd4a1..ff4af2d 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/Camera2Focuser.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/Camera2Focuser.java
@@ -21,6 +21,7 @@
 import android.hardware.camera2.CameraCharacteristics;
 import android.hardware.camera2.CameraDevice;
 import android.hardware.camera2.CameraDevice.CaptureListener;
+import android.hardware.camera2.params.MeteringRectangle;
 import android.hardware.camera2.CaptureRequest;
 import android.hardware.camera2.CaptureResult;
 import android.hardware.camera2.TotalCaptureResult;
@@ -50,11 +51,10 @@
     private final AutoFocusListener mAutoFocusListener;
     private final CameraDevice mCamera;
     private final Surface mRequestSurface;
-    private final int AF_REGION_NUM_ELEMENTS = 5;
     private final CameraCharacteristics mStaticInfo;
 
     private int mAfRun = 0;
-    private int[] mAfRegions; // int x AF_REGION_NUM_ELEMENTS array.
+    private MeteringRectangle[] mAfRegions;
     private boolean mLocked = false;
     private boolean mSuccess = false;
     private CaptureRequest.Builder mRepeatingBuilder;
@@ -165,7 +165,8 @@
      * array size is used if afRegions is null.
      * @throws CameraAccessException
      */
-    public synchronized void touchForAutoFocus(int[] afRegions) throws CameraAccessException {
+    public synchronized void touchForAutoFocus(MeteringRectangle[] afRegions)
+            throws CameraAccessException {
         startAutoFocusLocked(/*active*/true, afRegions);
     }
 
@@ -182,7 +183,8 @@
      *            array size is used if afRegions is null.
      * @throws CameraAccessException
      */
-    public synchronized void startAutoFocus(int[] afRegions) throws CameraAccessException {
+    public synchronized void startAutoFocus(MeteringRectangle[] afRegions)
+            throws CameraAccessException {
         startAutoFocusLocked(/*forceActive*/false, afRegions);
     }
 
@@ -222,7 +224,9 @@
         return mRepeatingBuilder.get(CaptureRequest.CONTROL_AF_MODE);
     }
 
-    private void startAutoFocusLocked(boolean forceActive, int[] afRegions) throws CameraAccessException {
+    private void startAutoFocusLocked(
+            boolean forceActive, MeteringRectangle[] afRegions) throws CameraAccessException {
+
         setAfRegions(afRegions);
         mAfRun++;
 
@@ -282,9 +286,6 @@
      * @throws CameraAccessException
      */
     private CaptureRequest.Builder createRequestBuilder() throws CameraAccessException {
-        if (mAfRegions == null) {
-            throw new IllegalStateException("AF regions are not initialized yet");
-        }
         CaptureRequest.Builder requestBuilder =
                 mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
 
@@ -298,17 +299,16 @@
      * Set AF regions, fall back to default region if afRegions is null.
      *
      * @param afRegions The AF regions to set
-     * @throws IllegalArgumentException if the region is malformed (length is 0
-     *             or not multiple times of {@value #AF_REGION_NUM_ELEMENTS}).
+     * @throws IllegalArgumentException if the region is malformed (length is 0).
      */
-    private void setAfRegions(int[] afRegions) {
+    private void setAfRegions(MeteringRectangle[] afRegions) {
         if (afRegions == null) {
             setDefaultAfRegions();
             return;
         }
         // Throw IAE if AF regions are malformed.
-        if (afRegions.length % AF_REGION_NUM_ELEMENTS != 0 || afRegions.length == 0) {
-            throw new IllegalArgumentException("afRegions is malformed, length: " + afRegions.length);
+        if (afRegions.length == 0) {
+            throw new IllegalArgumentException("afRegions is malformed, length: 0");
         }
 
         mAfRegions = afRegions;
@@ -325,7 +325,8 @@
 
         // Initialize AF regions with all zeros, meaning that it is up to camera device to device
         // the regions used by AF.
-        mAfRegions = new int[]{0, 0, 0, 0, 0};
+        mAfRegions = new MeteringRectangle[] {
+                new MeteringRectangle(0, 0, 0, 0, 0)};
     }
     private CaptureListener createCaptureListener() {