Merge "DO NOT MERGE: Bump CTS and CTS Verifier to 8.1_r16" into oreo-mr1-cts-dev
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/RVCVXCheckAnalyzer.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/RVCVXCheckAnalyzer.java
index 260ffbf..c15d2ac 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/RVCVXCheckAnalyzer.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/RVCVXCheckAnalyzer.java
@@ -30,6 +30,7 @@
 import org.opencv.core.MatOfFloat;
 import org.opencv.core.MatOfPoint2f;
 import org.opencv.core.MatOfPoint3f;
+import org.opencv.core.Point;
 import org.opencv.core.Size;
 import org.opencv.imgcodecs.Imgcodecs;
 import org.opencv.imgproc.Imgproc;
@@ -65,7 +66,7 @@
 
     private static final boolean OUTPUT_DEBUG_IMAGE = false;
     private static final double VALID_FRAME_THRESHOLD = 0.8;
-    private static final double REPROJECTION_THREASHOLD_RATIO = 0.008;
+    private static final double REPROJECTION_THRESHOLD_RATIO = 0.01;
     private static final boolean FORCE_CV_ANALYSIS  = false;
     private static final boolean TRACE_VIDEO_ANALYSIS = false;
     private static final double DECIMATION_FPS_TARGET = 15.0;
@@ -811,7 +812,9 @@
             Debug.startMethodTracing("cvprocess");
         }
 
-        Size patternSize = new Size(4,11);
+        final int patternWidth = 4;
+        final int patternHeight = 11;
+        Size patternSize = new Size(patternWidth, patternHeight);
 
         float fc = (float)(meta.frameWidth/2.0/Math.tan(meta.fovWidth/2.0));
         Mat camMat = cameraMatrix(fc, new Size(frameSize.width/2, frameSize.height/2));
@@ -877,16 +880,36 @@
             // reproject points to for evaluation of result accuracy of solvePnP
             Calib3d.projectPoints(grid, rvec, tvec, camMat, coeff, reprojCenters);
 
-            // error is evaluated in norm2, which is real error in pixel distance / sqrt(2)
-            double error = Core.norm(centers, reprojCenters, Core.NORM_L2);
+            // Calculate the average distance between opposite corners of the pattern in pixels
+            Point[] centerPoints = centers.toArray();
+            Point bottomLeftPos = centerPoints[0];
+            Point bottomRightPos = centerPoints[patternWidth - 1];
+            Point topLeftPos = centerPoints[(patternHeight * patternWidth) - patternWidth];
+            Point topRightPos = centerPoints[(patternHeight * patternWidth) - 1];
+            double avgPixelDist = (getDistanceBetweenPoints(bottomLeftPos, topRightPos)
+                    + getDistanceBetweenPoints(bottomRightPos, topLeftPos)) / 2;
+
+            // Calculate the average pixel error between the circle centers from the video and the
+            // reprojected circle centers based on the estimated camera position. The error provides
+            // a way to estimate how accurate the assumed test device's position is. If the error
+            // is high, then the frame should be discarded to prevent an inaccurate test device's
+            // position from being compared against the rotation vector sample at that time.
+            Point[] reprojectedPointsArray = reprojCenters.toArray();
+            double avgCenterError = 0.0;
+            for (int curCenter = 0; curCenter < reprojectedPointsArray.length; curCenter++) {
+                avgCenterError += getDistanceBetweenPoints(
+                        reprojectedPointsArray[curCenter], centerPoints[curCenter]);
+            }
+            avgCenterError /= reprojectedPointsArray.length;
 
             if (LOCAL_LOGV) {
-                Log.v(TAG, "Found attitude, re-projection error = " + error);
+                Log.v(TAG, "Found attitude, re-projection error = " + avgCenterError);
             }
 
-            // if error is reasonable, add it into the results. use ratio to frame height to avoid
-            // discriminating higher definition videos
-            if (error < REPROJECTION_THREASHOLD_RATIO * frameSize.height) {
+            // if error is reasonable, add it into the results. Use a dynamic threshold based on
+            // the pixel distance of opposite corners of the pattern to prevent higher resolution
+            // video or the distance between the camera and the test pattern from impacting the test
+            if (avgCenterError < REPROJECTION_THRESHOLD_RATIO * avgPixelDist) {
                 double [] rv = new double[3];
                 double timestamp;
 
@@ -1325,6 +1348,10 @@
     private static double [] rodr2rpy( double [] r) {
         return quat2rpy(rodr2quat(r));
     }
+
+    private double getDistanceBetweenPoints(Point a, Point b) {
+        return Math.sqrt(Math.pow(a.x - b.x, 2) + Math.pow(a.y - b.y, 2));
+    }
     //////////////////
 
 }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/RVCVXCheckTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/RVCVXCheckTestActivity.java
index 789de68..fec593c 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/RVCVXCheckTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/RVCVXCheckTestActivity.java
@@ -301,10 +301,8 @@
 
         String message = "Test Roll Axis Accuracy";
 
-        Assert.assertEquals("Roll RMS error", 0.0, mReport.roll_rms_error,
-                Criterion.roll_rms_error);
-        Assert.assertEquals("Roll max error", 0.0, mReport.roll_max_error,
-                Criterion.roll_max_error);
+        assertLessThan("Roll RMS error", mReport.roll_rms_error, Criterion.roll_rms_error);
+        assertLessThan("Roll max error", mReport.roll_max_error, Criterion.roll_max_error);
         return message;
     }
 
@@ -316,10 +314,8 @@
 
         String message = "Test Pitch Axis Accuracy";
 
-        Assert.assertEquals("Pitch RMS error", 0.0, mReport.pitch_rms_error,
-                Criterion.pitch_rms_error);
-        Assert.assertEquals("Pitch max error", 0.0, mReport.pitch_max_error,
-                Criterion.pitch_max_error);
+        assertLessThan("Pitch RMS error", mReport.pitch_rms_error, Criterion.pitch_rms_error);
+        assertLessThan("Pitch max error", mReport.pitch_max_error, Criterion.pitch_max_error);
         return message;
     }
 
@@ -331,13 +327,16 @@
 
         String message = "Test Yaw Axis Accuracy";
 
-        Assert.assertEquals("Yaw RMS error", 0.0, mReport.yaw_rms_error,
-                Criterion.yaw_rms_error);
-        Assert.assertEquals("Yaw max error", 0.0, mReport.yaw_max_error,
-                Criterion.yaw_max_error);
+        assertLessThan("Yaw RMS error", mReport.yaw_rms_error, Criterion.yaw_rms_error);
+        assertLessThan("Yaw max error", mReport.yaw_max_error, Criterion.yaw_max_error);
         return message;
     }
 
+    private void assertLessThan(String message, double lhs, double rhs) {
+        Assert.assertTrue(String.format("%s - expected %.4f < %.4f", message, lhs, rhs),
+                lhs < rhs);
+    }
+
     private void loadOpenCVSuccessfulOrSkip() throws SensorTestStateNotSupportedException {
         if (!mOpenCVLoadSuccessful)
             throw new SensorTestStateNotSupportedException("Skipped due to OpenCV cannot be loaded");
diff --git a/tests/filesystem/src/android/filesystem/cts/FileUtil.java b/tests/filesystem/src/android/filesystem/cts/FileUtil.java
index 386679a..5afaac0 100755
--- a/tests/filesystem/src/android/filesystem/cts/FileUtil.java
+++ b/tests/filesystem/src/android/filesystem/cts/FileUtil.java
@@ -143,16 +143,15 @@
     public static File createNewFilledFile(Context context, String dirName, long length)
             throws IOException {
         File file = createNewFile(context, dirName);
-        FileOutputStream out = new FileOutputStream(file);
+        final RandomAccessFile randomFile = new RandomAccessFile(file, "rwd"); // force O_SYNC
         byte[] data = generateRandomData(BUFFER_SIZE);
-        long written = 0;
-        while (written < length) {
-            int toWrite = (int) Math.min(BUFFER_SIZE, length - written);
-            out.write(data, 0, toWrite);
-            written += toWrite;
+
+        while (file.length() < length) {
+            int toWrite = (int) Math.min(BUFFER_SIZE, length - file.length());
+            randomFile.write(data, 0, toWrite);
         }
-        out.flush();
-        out.close();
+
+        randomFile.close();
         return file;
     }
 
diff --git a/tools/cts-tradefed/res/config/cts-known-failures.xml b/tools/cts-tradefed/res/config/cts-known-failures.xml
index b68ed93..5d43956 100644
--- a/tools/cts-tradefed/res/config/cts-known-failures.xml
+++ b/tools/cts-tradefed/res/config/cts-known-failures.xml
@@ -207,7 +207,4 @@
     <!-- test fails if usb charging is disabled which is not mandatory -->
     <option name="compatibility:exclude-filter" value="CtsDumpsysHostTestCases  android.dumpsys.cts.StoragedDumpsysTest#testStoragedOutput" />
 
-    <!-- b/126515980 -->
-    <!-- fails on some devices because the IME blocks the screen, causing UIAutomator queries to fail -->
-    <option name="compatibility:exclude-filter" value="CtsAutoFillServiceTestCases android.autofillservice.cts.SimpleSaveActivityTest#testTapLink_changeOrientationThenTapBack" />
 </configuration>