Merge "Revert "Bug: 23003511 CTS: AudioManagerTest#testSoundEffects failing"" into mnc-dev
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/CustomDeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/CustomDeviceOwnerTest.java
index adf81a3..e6351c5 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/CustomDeviceOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/CustomDeviceOwnerTest.java
@@ -37,6 +37,24 @@
 
     private static final String ADMIN_RECEIVER_TEST_CLASS =
             DEVICE_OWNER_PKG + ".BaseDeviceOwnerTest$BasicAdminReceiver";
+    private static final String ADMIN_RECEIVER_COMPONENT =
+            DEVICE_OWNER_PKG + "/" + ADMIN_RECEIVER_TEST_CLASS;
+
+    public void setUp() throws Exception {
+        super.setUp();
+
+        if (mHasFeature) {
+            installApp(DEVICE_OWNER_APK);
+        }
+    }
+
+    public void tearDown() throws Exception {
+        if (mHasFeature) {
+            getDevice().uninstallPackage(DEVICE_OWNER_PKG);
+        }
+
+        super.tearDown();
+    }
 
     public void testOwnerChangedBroadcast() throws Exception {
         if (!mHasFeature) {
@@ -44,7 +62,6 @@
         }
         try {
             installApp(INTENT_RECEIVER_APK);
-            installApp(DEVICE_OWNER_APK);
 
             String testClass = INTENT_RECEIVER_PKG + ".OwnerChangedBroadcastTest";
 
@@ -54,15 +71,27 @@
                     "testOwnerChangedBroadcastNotReceived", 0));
 
             // Setting the device owner should send the owner changed broadcast.
-            setDeviceOwner(DEVICE_OWNER_PKG + "/" + ADMIN_RECEIVER_TEST_CLASS);
+            assertTrue(setDeviceOwner(ADMIN_RECEIVER_COMPONENT));
 
             assertTrue(runDeviceTests(INTENT_RECEIVER_PKG, testClass,
                     "testOwnerChangedBroadcastReceived", 0));
         } finally {
+            getDevice().uninstallPackage(INTENT_RECEIVER_PKG);
             assertTrue("Failed to remove device owner.",
                     runDeviceTests(DEVICE_OWNER_PKG, CLEAR_DEVICE_OWNER_TEST_CLASS));
-            getDevice().uninstallPackage(DEVICE_OWNER_PKG);
-            getDevice().uninstallPackage(INTENT_RECEIVER_PKG);
+        }
+    }
+
+    public void testCannotSetDeviceOwnerWhenSecondaryUserPresent() throws Exception {
+        if (!mHasFeature) {
+            return;
+        }
+        int userId = -1;
+        try {
+            userId = createUser();
+            assertFalse(setDeviceOwner(ADMIN_RECEIVER_COMPONENT));
+        } finally {
+            removeUser(userId);
         }
     }
 }
diff --git a/libs/deviceutil/src/android/cts/util/MediaUtils.java b/libs/deviceutil/src/android/cts/util/MediaUtils.java
index c04a2cf..c595e10 100644
--- a/libs/deviceutil/src/android/cts/util/MediaUtils.java
+++ b/libs/deviceutil/src/android/cts/util/MediaUtils.java
@@ -459,12 +459,13 @@
         return avgs;
     }
 
-    public static void logResults(ReportLog log, String prefix,
+    public static String logResults(ReportLog log, String prefix,
             double min, double max, double avg, double stdev) {
         String msg = prefix;
         msg += " min=" + Math.round(min / 1000) + " max=" + Math.round(max / 1000) +
                 " avg=" + Math.round(avg / 1000) + " stdev=" + Math.round(stdev / 1000);
         log.printValue(msg, 1000000000 / min, ResultType.HIGHER_BETTER, ResultUnit.FPS);
+        return msg;
     }
 
     public static VideoCapabilities getVideoCapabilities(String codecName, String mime) {
@@ -512,4 +513,17 @@
         return (measured >= lowerBoundary1 && measured <= upperBoundary1 &&
                 measured >= lowerBoundary2 && measured <= upperBoundary2);
     }
+
+    public static String getErrorMessage(
+            Range<Double> reportedRange, double[] measuredFps, String[] rawData) {
+        String msg = "";
+        if (reportedRange == null) {
+            msg += "Failed to get achievable frame rate.\n";
+        } else {
+            msg += "Expected achievable frame rate range: " + reportedRange + ".\n";
+        }
+        msg += "Measured frame rate: " + Arrays.toString(measuredFps) + ".\n";
+        msg += "Raw data: " + Arrays.toString(rawData) + ".\n";
+        return msg;
+    }
 }
diff --git a/suite/cts/deviceTests/videoperf/src/com/android/cts/videoperf/VideoEncoderDecoderTest.java b/suite/cts/deviceTests/videoperf/src/com/android/cts/videoperf/VideoEncoderDecoderTest.java
index 8fc5a44..62f37c5 100644
--- a/suite/cts/deviceTests/videoperf/src/com/android/cts/videoperf/VideoEncoderDecoderTest.java
+++ b/suite/cts/deviceTests/videoperf/src/com/android/cts/videoperf/VideoEncoderDecoderTest.java
@@ -516,6 +516,8 @@
 
         boolean encTestPassed = false;
         boolean decTestPassed = false;
+        double[] measuredFps = new double[mTestConfig.mNumberOfRepeat];
+        String[] resultRawData = new String[mTestConfig.mNumberOfRepeat];
         for (int i = 0; i < mTestConfig.mNumberOfRepeat; i++) {
             // make sure that rms error is not too big.
             if (decoderRmsErrorResults[i] >= mRmsErrorMargain) {
@@ -542,8 +544,11 @@
                 String prefix = "codec=" + encoderName + " round=" + i +
                         " EncInputFormat=" + mEncInputFormat +
                         " EncOutputFormat=" + mEncOutputFormat;
-                MediaUtils.logResults(mReportLog, prefix, encMin, encMax, encAvg, encStdev);
+                String result =
+                        MediaUtils.logResults(mReportLog, prefix, encMin, encMax, encAvg, encStdev);
                 double measuredEncFps = 1000000000 / encMin;
+                resultRawData[i] = result;
+                measuredFps[i] = measuredEncFps;
                 if (!encTestPassed) {
                     encTestPassed = MediaUtils.verifyResults(
                             encoderName, mimeType, w, h, measuredEncFps);
@@ -565,10 +570,14 @@
                 }
             }
         }
+
         if (mTestConfig.mTestResult) {
             if (!encTestPassed) {
-                fail("Measured fps for " + encoderName +
-                        " doesn't match with reported achievable frame rates.");
+                Range<Double> reportedRange =
+                    MediaUtils.getAchievableFrameRatesFor(encoderName, mimeType, w, h);
+                String failMessage =
+                    MediaUtils.getErrorMessage(reportedRange, measuredFps, resultRawData);
+                fail(failMessage);
             }
             // Decoder result will be verified in VideoDecoderPerfTest
             // if (!decTestPassed) {
@@ -576,6 +585,8 @@
             //             " doesn't match with reported achievable frame rates.");
             // }
         }
+        measuredFps = null;
+        resultRawData = null;
     }
 
     /**
diff --git a/tests/tests/hardware/Android.mk b/tests/tests/hardware/Android.mk
index 9523d87..9c26d8a 100644
--- a/tests/tests/hardware/Android.mk
+++ b/tests/tests/hardware/Android.mk
@@ -34,7 +34,7 @@
     src/android/hardware/cts/SensorIntegrationTests.java \
     src/android/hardware/cts/SensorBatchingTests.java \
     src/android/hardware/cts/SensorTest.java \
-    src/android/hardware/cts/SensorManagerStaticTest.java \
+    src/android/hardware/cts/SensorManagerStaticTest.java
 
 LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil
 
@@ -57,4 +57,4 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
-include $(BUILD_CTS_PACKAGE)
\ No newline at end of file
+include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/hardware/src/android/hardware/cts/SensorParameterRangeTest.java b/tests/tests/hardware/src/android/hardware/cts/SensorParameterRangeTest.java
new file mode 100644
index 0000000..4750b09
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/SensorParameterRangeTest.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2015 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 android.hardware.cts;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.hardware.Sensor;
+import android.hardware.SensorManager;
+import android.hardware.cts.helpers.SensorCtsHelper;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Test min-max frequency, max range parameters for sensors.
+ *
+ * <p>To execute these test cases, the following command can be used:</p>
+ * <pre>
+ * adb shell am instrument -e class android.hardware.cts.SensorParameterRangeTest \
+ *     -w com.android.cts.hardware/android.test.AndroidJUnitRunner
+ * </pre>
+ */
+public class SensorParameterRangeTest extends SensorTestCase {
+
+    private static final double ACCELEROMETER_MAX_RANGE = 8 * 9.81; // 8G
+    private static final int ACCELEROMETER_MIN_FREQUENCY = 5;
+    private static final int ACCELEROMETER_MAX_FREQUENCY = 200;
+
+    private static final double GYRO_MAX_RANGE = 1000/57.295; // 1000 degrees per sec.
+    private static final int GYRO_MIN_FREQUENCY = 5;
+    private static final int GYRO_MAX_FREQUENCY = 200;
+
+    private static final int MAGNETOMETER_MAX_RANGE = 900;   // micro telsa
+    private static final int MAGNETOMETER_MIN_FREQUENCY = 5;
+    private static final int MAGNETOMETER_MAX_FREQUENCY = 50;
+
+    private static final int PRESSURE_MAX_RANGE = 1100;     // hecto-pascal
+    private static final int PRESSURE_MIN_FREQUENCY = 1;
+    private static final int PRESSURE_MAX_FREQUENCY = 10;
+
+    private boolean mHasHifiSensors;
+    private SensorManager mSensorManager;
+
+    @Override
+    public void setUp() {
+        mSensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE);
+        mHasHifiSensors = getContext().getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_HIFI_SENSORS);
+    }
+
+    public void testAccelerometerRange() {
+        checkSensorRangeAndFrequency(
+                mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
+                ACCELEROMETER_MAX_RANGE,
+                ACCELEROMETER_MIN_FREQUENCY,
+                ACCELEROMETER_MAX_FREQUENCY);
+  }
+
+  public void testGyroscopeRange() {
+        checkSensorRangeAndFrequency(
+                mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE),
+                GYRO_MAX_RANGE,
+                GYRO_MIN_FREQUENCY,
+                GYRO_MAX_FREQUENCY);
+  }
+
+    public void testMagnetometerRange() {
+        checkSensorRangeAndFrequency(
+                mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD),
+                MAGNETOMETER_MAX_RANGE,
+                MAGNETOMETER_MIN_FREQUENCY,
+                MAGNETOMETER_MAX_FREQUENCY);
+    }
+
+    public void testPressureRange() {
+        checkSensorRangeAndFrequency(
+                mSensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE),
+                PRESSURE_MAX_RANGE,
+                PRESSURE_MIN_FREQUENCY,
+                PRESSURE_MAX_FREQUENCY);
+    }
+
+    private void checkSensorRangeAndFrequency(
+          Sensor sensor, double maxRange, int minFrequency, int maxFrequency) {
+        if (!mHasHifiSensors) return;
+        assertTrue(String.format("%s Range actual=%.2f expected=%.2f %s",
+                    sensor.getName(), sensor.getMaximumRange(), maxRange,
+                    SensorCtsHelper.getUnitsForSensor(sensor)),
+                sensor.getMaximumRange() >= maxRange);
+        double actualMinFrequency = SensorCtsHelper.getFrequency(sensor.getMaxDelay(),
+                TimeUnit.MICROSECONDS);
+        assertTrue(String.format("%s Min Frequency actual=%.2f expected=%dHz",
+                    sensor.getName(), actualMinFrequency, minFrequency), actualMinFrequency <=
+                minFrequency);
+
+        double actualMaxFrequency = SensorCtsHelper.getFrequency(sensor.getMinDelay(),
+                TimeUnit.MICROSECONDS);
+        assertTrue(String.format("%s Max Frequency actual=%.2f expected=%dHz",
+                    sensor.getName(), actualMaxFrequency, maxFrequency), actualMaxFrequency >=
+                maxFrequency);
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/SensorSupportTest.java b/tests/tests/hardware/src/android/hardware/cts/SensorSupportTest.java
new file mode 100644
index 0000000..2f25c8d
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/SensorSupportTest.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2015 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 android.hardware.cts;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.hardware.Sensor;
+import android.hardware.SensorManager;
+import android.test.AndroidTestCase;
+
+/**
+ * Checks if Hifi sensors are supported. When supported, checks individual support for
+ * Accelerometer, Gyroscope, Gyroscope_uncal, GeoMagneticField, MagneticField_uncal
+ * Pressure, RotationVector, SignificantMotion, StepDetector, StepCounter, TiltDetector.
+ *
+ * <p>To execute these test cases, the following command can be used:</p>
+ * <pre>
+ * adb shell am instrument -e class android.hardware.cts.SensorSupportTest \
+ *     -w com.android.cts.hardware/android.test.AndroidJUnitRunner
+ * </pre>
+ */
+public class SensorSupportTest extends AndroidTestCase {
+    private SensorManager mSensorManager;
+    private boolean mAreHifiSensorsSupported;
+
+    @Override
+    public void setUp() {
+        // Tests will only run if HIFI_SENSORS are supported.
+        mAreHifiSensorsSupported = getContext().getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_HIFI_SENSORS);
+        if (mAreHifiSensorsSupported) {
+            mSensorManager =
+                    (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE);
+        }
+    }
+
+    public void testSupportsAccelerometer() {
+        checkSupportsSensor(Sensor.TYPE_ACCELEROMETER);
+    }
+
+    public void testSupportsGyroscope() {
+        checkSupportsSensor(Sensor.TYPE_GYROSCOPE);
+    }
+
+    public void testSupportsGyroscopeUncalibrated() {
+        checkSupportsSensor(Sensor.TYPE_GYROSCOPE_UNCALIBRATED);
+    }
+
+    public void testSupportsGeoMagneticField() {
+        checkSupportsSensor(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR);
+    }
+
+    public void testSupportsMagneticFieldUncalibrated() {
+        checkSupportsSensor(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED);
+    }
+
+    public void testSupportsPressure() {
+        checkSupportsSensor(Sensor.TYPE_PRESSURE);
+    }
+
+    public void testSupportsRotationVector() {
+        checkSupportsSensor(Sensor.TYPE_ROTATION_VECTOR);
+    }
+
+    public void testSupportsSignificantMotion() {
+        checkSupportsSensor(Sensor.TYPE_SIGNIFICANT_MOTION);
+    }
+
+    public void testSupportsStepDetector() {
+        checkSupportsSensor(Sensor.TYPE_STEP_DETECTOR);
+    }
+
+    public void testSupportsStepCounter() {
+        checkSupportsSensor(Sensor.TYPE_STEP_COUNTER);
+    }
+
+    public void testSupportsTiltDetector() {
+        final int TYPE_TILT_DETECTOR = 22;
+        checkSupportsSensor(TYPE_TILT_DETECTOR);
+    }
+
+    private void checkSupportsSensor(int sensorType) {
+        if (mAreHifiSensorsSupported) {
+            assertTrue(mSensorManager.getDefaultSensor(sensorType) != null);
+        }
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorCtsHelper.java b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorCtsHelper.java
index 490e965..55465ac 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorCtsHelper.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorCtsHelper.java
@@ -15,6 +15,7 @@
  */
 package android.hardware.cts.helpers;
 
+import android.hardware.Sensor;
 import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
@@ -259,4 +260,20 @@
             throw new IllegalStateException("Collection cannot be null or empty");
         }
     }
+
+    public static String getUnitsForSensor(Sensor sensor) {
+        switch(sensor.getType()) {
+            case Sensor.TYPE_ACCELEROMETER:
+                return "m/s^2";
+            case Sensor.TYPE_MAGNETIC_FIELD:
+            case Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED:
+                return "uT";
+            case Sensor.TYPE_GYROSCOPE:
+            case Sensor.TYPE_GYROSCOPE_UNCALIBRATED:
+                return "radians/sec";
+            case Sensor.TYPE_PRESSURE:
+                return "hPa";
+        };
+        return "";
+    }
 }
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/JitterVerification.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/JitterVerification.java
index 6633903..e5a5053 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/JitterVerification.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/JitterVerification.java
@@ -18,6 +18,10 @@
 
 import junit.framework.Assert;
 
+import android.content.Context;
+import android.content.pm.PackageManager;
+
+import android.util.Log;
 import android.hardware.Sensor;
 import android.hardware.cts.helpers.SensorCtsHelper;
 import android.hardware.cts.helpers.SensorStats;
@@ -39,6 +43,8 @@
 
     // sensorType: threshold (% of expected period)
     private static final SparseIntArray DEFAULTS = new SparseIntArray(12);
+    // Max allowed jitter (in percentage).
+    private static final int THRESHOLD_PERCENT_FOR_HIFI_SENSORS = 1;
     static {
         // Use a method so that the @deprecation warning can be set for that method only
         setDefaults();
@@ -68,6 +74,11 @@
         if (threshold == -1) {
             return null;
         }
+        boolean hasHifiSensors = environment.getContext().getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_HIFI_SENSORS);
+        if (hasHifiSensors) {
+           threshold = THRESHOLD_PERCENT_FOR_HIFI_SENSORS;
+        }
         return new JitterVerification(threshold);
     }
 
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/StandardDeviationVerification.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/StandardDeviationVerification.java
index f7c2c53..20dd2d2 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/StandardDeviationVerification.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/StandardDeviationVerification.java
@@ -18,10 +18,13 @@
 
 import junit.framework.Assert;
 
+import android.content.Context;
+import android.content.pm.PackageManager;
 import android.hardware.Sensor;
 import android.hardware.cts.helpers.SensorStats;
 import android.hardware.cts.helpers.TestSensorEnvironment;
 import android.hardware.cts.helpers.TestSensorEvent;
+import android.util.Log;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -66,7 +69,21 @@
         if (!DEFAULTS.containsKey(sensorType)) {
             return null;
         }
+        boolean hasHifiSensors = environment.getContext().getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_HIFI_SENSORS);
 
+        if (hasHifiSensors) {
+            // Max accelerometer deviation: 400uG/√Hz
+            DEFAULTS.put(Sensor.TYPE_ACCELEROMETER, new float[]{0.004f, 0.004f, 0.004f});
+            // Max gyro deviation: 0.014°/s/√Hz
+            float deviationInRadians = (float) (0.014f * (Math.PI / 180));
+            DEFAULTS.put(Sensor.TYPE_GYROSCOPE,
+                    new float[]{deviationInRadians,deviationInRadians, deviationInRadians});
+            // Max magnetometer deviation: 0.1uT/√Hz
+            DEFAULTS.put(Sensor.TYPE_MAGNETIC_FIELD, new float[]{0.1f, 0.1f, 0.1f});
+            // Max pressure deviation: 2Pa/√Hz
+            DEFAULTS.put(Sensor.TYPE_PRESSURE, new float[]{2.0f, 2.0f, 2.0f});
+        }
         return new StandardDeviationVerification(DEFAULTS.get(sensorType));
     }
 
@@ -107,9 +124,9 @@
             if (stdDevs[i] > mThreshold[i]) {
                 failed = true;
             }
-            stddevSb.append(String.format("%.2f", stdDevs[i]));
+            stddevSb.append(String.format("%.3f", stdDevs[i]));
             if (i != stdDevs.length - 1) stddevSb.append(", ");
-            expectedSb.append(String.format("<%.2f", mThreshold[i]));
+            expectedSb.append(String.format("<%.3f", mThreshold[i]));
             if (i != stdDevs.length - 1) expectedSb.append(", ");
         }
         if (stdDevs.length > 1) {
diff --git a/tests/tests/media/src/android/media/cts/VideoDecoderPerfTest.java b/tests/tests/media/src/android/media/cts/VideoDecoderPerfTest.java
index ede5040..f5680f6 100644
--- a/tests/tests/media/src/android/media/cts/VideoDecoderPerfTest.java
+++ b/tests/tests/media/src/android/media/cts/VideoDecoderPerfTest.java
@@ -31,6 +31,7 @@
 import android.media.MediaExtractor;
 import android.media.MediaFormat;
 import android.util.Log;
+import android.util.Range;
 import android.view.Surface;
 
 import com.android.cts.util.ResultType;
@@ -58,6 +59,8 @@
     LinkedList<ByteBuffer> mSamplesInMemory = new LinkedList<ByteBuffer>();
     private static final int MOVING_AVERAGE_NUM = 10;
     private MediaFormat mDecOutputFormat;
+    private double[] mMeasuredFps;
+    private String[] mResultRawData;
 
     private Resources mResources;
     private DeviceReportLog mReportLog;
@@ -104,6 +107,8 @@
             }
 
             boolean pass = false;
+            mMeasuredFps = new double[NUMBER_OF_REPEAT];
+            mResultRawData = new String[NUMBER_OF_REPEAT];
             Log.d(TAG, "testing " + name);
             for (int i = 0; i < NUMBER_OF_REPEAT; ++i) {
                 // Decode to Surface.
@@ -118,7 +123,16 @@
                 Log.d(TAG, "round #" + i + " decode to buffer");
                 doDecode(name, video, width, height, null, i);
             }
-            assertTrue("Measured fps doesn't match with reported achievable frame rates.", pass);
+
+            if (!pass) {
+                Range<Double> reportedRange =
+                    MediaUtils.getAchievableFrameRatesFor(name, mime, width, height);
+                String failMessage =
+                    MediaUtils.getErrorMessage(reportedRange, mMeasuredFps, mResultRawData);
+                fail(failMessage);
+            }
+            mMeasuredFps = null;
+            mResultRawData = null;
         }
         // use 0 for summary line, detail for each test config is in the report.
         mReportLog.printSummary("average fps", 0, ResultType.HIGHER_BETTER, ResultUnit.FPS);
@@ -276,9 +290,15 @@
         double decMax = Stat.getMax(avgs);
         double decAvg = Stat.getAverage(avgs);
         double decStdev = MediaUtils.getStdev(avgs);
-        MediaUtils.logResults(mReportLog, testConfig, decMin, decMax, decAvg, decStdev);
+        String result =
+                MediaUtils.logResults(mReportLog, testConfig, decMin, decMax, decAvg, decStdev);
+        fps = 1000000000 / decMin;
+        if (surface != null) {
+            mMeasuredFps[round] = fps;
+            mResultRawData[round] = result;
+        }
 
-        return MediaUtils.verifyResults(name, mime, w, h, 1000000000 / decMin);
+        return MediaUtils.verifyResults(name, mime, w, h, fps);
     }
 
     public void testH2640320x0240Other() throws Exception {
diff --git a/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java b/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
new file mode 100644
index 0000000..a4d68cb
--- /dev/null
+++ b/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
@@ -0,0 +1,64 @@
+/*
+* Copyright (C) 2015 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 android.permission2.cts;
+
+import android.Manifest;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PermissionInfo;
+import android.test.AndroidTestCase;
+import android.text.TextUtils;
+import android.util.ArraySet;
+
+import java.util.Set;
+
+/**
+ * Tests for permission policy on the platform.
+ */
+public class PermissionPolicyTest extends AndroidTestCase {
+    private static final String PLATFORM_PACKAGE_NAME = "android";
+
+    private static final Set<String> PERMISSION_GROUPS = new ArraySet<>();
+    static {
+        PERMISSION_GROUPS.add(Manifest.permission_group.CALENDAR);
+        PERMISSION_GROUPS.add(Manifest.permission_group.CAMERA);
+        PERMISSION_GROUPS.add(Manifest.permission_group.CONTACTS);
+        PERMISSION_GROUPS.add(Manifest.permission_group.LOCATION);
+        PERMISSION_GROUPS.add(Manifest.permission_group.MICROPHONE);
+        PERMISSION_GROUPS.add(Manifest.permission_group.PHONE);
+        PERMISSION_GROUPS.add(Manifest.permission_group.SENSORS);
+        PERMISSION_GROUPS.add(Manifest.permission_group.SMS);
+        PERMISSION_GROUPS.add(Manifest.permission_group.STORAGE);
+    }
+
+    public void testPlatformDefinedRuntimePermissionValid() throws Exception {
+        PackageManager packageManager = getContext().getPackageManager();
+        PackageInfo packageInfo = packageManager.getPackageInfo(PLATFORM_PACKAGE_NAME,
+                PackageManager.GET_PERMISSIONS);
+        for (PermissionInfo permission : packageInfo.permissions) {
+            if ((permission.protectionLevel & PermissionInfo.PROTECTION_DANGEROUS) == 0) {
+                continue;
+            }
+            assertTrue(permission.name + " must be in one of these groups: " + PERMISSION_GROUPS,
+                    PERMISSION_GROUPS.contains(permission.group));
+            assertFalse(permission.name + " must have non-empty label",
+                    TextUtils.isEmpty(permission.loadLabel(packageManager)));
+            assertFalse(permission.name + " must have non-empty description",
+                    TextUtils.isEmpty(permission.loadDescription(packageManager)));
+        }
+    }
+}
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java b/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java
index e6b656f..592e308 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java
@@ -95,7 +95,7 @@
      * brackets are optional):
      * <p/>
      * Mozilla/5.0 (Linux;[ U;] Android <version>;[ <language>-<country>;]
-     * [<devicemodel>;] Build/<buildID>[; wv]) AppleWebKit/<major>.<minor> (KHTML, like Gecko)
+     * [<devicemodel>;] Build/<buildID>; wv) AppleWebKit/<major>.<minor> (KHTML, like Gecko)
      * Version/<major>.<minor> Chrome/<major>.<minor>.<branch>.<build>[ Mobile]
      * Safari/<major>.<minor>
      */
@@ -107,7 +107,7 @@
         Log.i(LOG_TAG, String.format("Checking user agent string %s", actualUserAgentString));
         final String patternString =
                 "Mozilla/5\\.0 \\(Linux;( U;)? Android ([^;]+);( (\\w+)-(\\w+);)?" +
-                "\\s?(.*)\\sBuild/(.+?)(; wv)?\\) AppleWebKit/(\\d+)\\.(\\d+) " +
+                "\\s?(.*)\\sBuild/(.+); wv\\) AppleWebKit/(\\d+)\\.(\\d+) " +
                 "\\(KHTML, like Gecko\\) " +
                 "Version/\\d+\\.\\d+ Chrome/\\d+\\.\\d+\\.\\d+\\.\\d+( Mobile)? " +
                 "Safari/(\\d+)\\.(\\d+)";
@@ -119,12 +119,11 @@
         //  5   - language
         //  6 - device model (optional)
         //  7 - build ID
-        //  8 - WebView identifier "; wv" (optional)
-        //  9 - AppleWebKit major version number
-        // 10 - AppleWebKit minor version number
-        // 11 - " Mobile" string (optional)
-        // 12 - Safari major version number
-        // 13 - Safari minor version number
+        //  8 - AppleWebKit major version number
+        //  9 - AppleWebKit minor version number
+        // 10 - " Mobile" string (optional)
+        // 11 - Safari major version number
+        // 12 - Safari minor version number
         Log.i(LOG_TAG, String.format("Trying to match pattern %s", patternString));
         final Pattern userAgentExpr = Pattern.compile(patternString);
         Matcher patternMatcher = userAgentExpr.matcher(actualUserAgentString);