Reland WebViewClientTest testOnReceivedLoginRequest test fix am: 739bdc291f  -s ours
am: b1c43bb655

Change-Id: I7df847fa5f06c008ea9c05bd333dbd8da11997ba
diff --git a/apps/CameraITS/pymodules/its/device.py b/apps/CameraITS/pymodules/its/device.py
index 692a62d..351b03c 100644
--- a/apps/CameraITS/pymodules/its/device.py
+++ b/apps/CameraITS/pymodules/its/device.py
@@ -67,17 +67,9 @@
     PACKAGE = 'com.android.cts.verifier.camera.its'
     INTENT_START = 'com.android.cts.verifier.camera.its.START'
     ACTION_ITS_RESULT = 'com.android.cts.verifier.camera.its.ACTION_ITS_RESULT'
-    EXTRA_VERSION = 'camera.its.extra.VERSION'
-    CURRENT_ITS_VERSION = '1.0' # version number to sync with CtsVerifier
     EXTRA_CAMERA_ID = 'camera.its.extra.CAMERA_ID'
-    EXTRA_RESULTS = 'camera.its.extra.RESULTS'
-
-    RESULT_PASS = 'PASS'
-    RESULT_FAIL = 'FAIL'
-    RESULT_NOT_EXECUTED = 'NOT_EXECUTED'
-    RESULT_VALUES = {RESULT_PASS, RESULT_FAIL, RESULT_NOT_EXECUTED}
-    RESULT_KEY = 'result'
-    SUMMARY_KEY = 'summary'
+    EXTRA_SUCCESS = 'camera.its.extra.SUCCESS'
+    EXTRA_SUMMARY = 'camera.its.extra.SUMMARY'
 
     adb = "adb -d"
     device_id = ""
@@ -789,43 +781,34 @@
 
     return device_id
 
-def report_result(device_id, camera_id, results):
+def report_result(device_id, camera_id, success, summary_path=None):
     """Send a pass/fail result to the device, via an intent.
 
     Args:
         device_id: The ID string of the device to report the results to.
         camera_id: The ID string of the camera for which to report pass/fail.
-        results: a dictionary contains all ITS scenes as key and result/summary
-                 of current ITS run. See test_report_result unit test for
-                 an example.
+        success: Boolean, indicating if the result was pass or fail.
+        summary_path: (Optional) path to ITS summary file on host PC
+
     Returns:
         Nothing.
     """
     adb = "adb -s " + device_id
-    # Validate/process results argument
-    for scene in results:
-        result_key = ItsSession.RESULT_KEY
-        summary_key = ItsSession.SUMMARY_KEY
-        if result_key not in results[scene]:
-            raise its.error.Error('ITS result not found for ' + scene)
-        if results[scene][result_key] not in ItsSession.RESULT_VALUES:
-            raise its.error.Error('Unknown ITS result for %s: %s' % (
-                    scene, results[result_key]))
-        if summary_key in results[scene]:
-            device_summary_path = "/sdcard/its_camera%s_%s.txt" % (
-                    camera_id, scene)
-            _run("%s push %s %s" % (
-                    adb, results[scene][summary_key], device_summary_path))
-            results[scene][summary_key] = device_summary_path
-    json_results = json.dumps(results)
-    cmd = "%s shell am broadcast -a %s --es %s %s --es %s %s --es %s \'%s\'" % (
-            adb, ItsSession.ACTION_ITS_RESULT,
-            ItsSession.EXTRA_VERSION, ItsSession.CURRENT_ITS_VERSION,
-            ItsSession.EXTRA_CAMERA_ID, camera_id,
-            ItsSession.EXTRA_RESULTS, json_results)
-    if len(cmd) > 4095:
-        print "ITS command string might be too long! len:", len(cmd)
-    _run(cmd)
+    device_summary_path = "/sdcard/camera_" + camera_id + "_its_summary.txt"
+    if summary_path is not None:
+        _run("%s push %s %s" % (
+                adb, summary_path, device_summary_path))
+        _run("%s shell am broadcast -a %s --es %s %s --es %s %s --es %s %s" % (
+                adb, ItsSession.ACTION_ITS_RESULT,
+                ItsSession.EXTRA_CAMERA_ID, camera_id,
+                ItsSession.EXTRA_SUCCESS, 'True' if success else 'False',
+                ItsSession.EXTRA_SUMMARY, device_summary_path))
+    else:
+        _run("%s shell am broadcast -a %s --es %s %s --es %s %s --es %s %s" % (
+                adb, ItsSession.ACTION_ITS_RESULT,
+                ItsSession.EXTRA_CAMERA_ID, camera_id,
+                ItsSession.EXTRA_SUCCESS, 'True' if success else 'False',
+                ItsSession.EXTRA_SUMMARY, "null"))
 
 def _run(cmd):
     """Replacement for os.system, with hiding of stdout+stderr messages.
@@ -838,20 +821,8 @@
     """Run a suite of unit tests on this module.
     """
 
-    """
-    # TODO: this test currently needs connected device to pass
-    #       Need to remove that dependency before enabling the test
-    def test_report_result(self):
-        device_id = get_device_id()
-        camera_id = "1"
-        result_key = ItsSession.RESULT_KEY
-        results = {"scene0":{result_key:"PASS"},
-                   "scene1":{result_key:"PASS"},
-                   "scene2":{result_key:"PASS"},
-                   "scene3":{result_key:"PASS"},
-                   "sceneNotExist":{result_key:"FAIL"}}
-        report_result(device_id, camera_id, results)
-    """
+    # TODO: Add some unit tests.
+    None
 
 if __name__ == '__main__':
     unittest.main()
diff --git a/apps/CameraITS/tests/scene5/test_lens_shading_and_color_uniformity.py b/apps/CameraITS/tests/scene5/test_lens_shading_and_color_uniformity.py
index 1307680..8e9f740 100644
--- a/apps/CameraITS/tests/scene5/test_lens_shading_and_color_uniformity.py
+++ b/apps/CameraITS/tests/scene5/test_lens_shading_and_color_uniformity.py
@@ -52,7 +52,6 @@
 
     with its.device.ItsSession() as cam:
         props = cam.get_camera_properties()
-        its.caps.skip_unless(its.caps.read_3a(props))
         # Converge 3A and get the estimates.
         sens, exp, gains, xform, focus = cam.do_3a(get_results=True,
                                                    do_af=False,
diff --git a/apps/CameraITS/tools/run_all_tests.py b/apps/CameraITS/tools/run_all_tests.py
index 678c35c..301ea73 100644
--- a/apps/CameraITS/tools/run_all_tests.py
+++ b/apps/CameraITS/tools/run_all_tests.py
@@ -20,20 +20,12 @@
 import sys
 import textwrap
 import its.device
-from its.device import ItsSession
 
 def main():
     """Run all the automated tests, saving intermediate files, and producing
     a summary/report of the results.
 
     Script should be run from the top-level CameraITS directory.
-
-    Command line Arguments:
-        camera: the camera(s) to be tested. Use comma to separate multiple
-                camera Ids. Ex: "camera=0,1" or "camera=1"
-        scenes: the test scene(s) to be executed. Use comma to separate multiple
-                scenes. Ex: "scenes=scene0,scene1" or "scenes=0,1,sensor_fusion"
-                (sceneX can be abbreviated by X where X is a integer)
     """
 
     SKIP_RET_CODE = 101
@@ -57,7 +49,9 @@
         "sensor_fusion":[]
     }
 
-    all_scenes = ["scene0", "scene1", "scene2", "scene3", "scene4", "scene5"]
+    # Get all the scene0 and scene1 tests, which can be run using the same
+    # physical setup.
+    scenes = ["scene0", "scene1", "scene2", "scene3", "scene4", "scene5"]
 
     scene_req = {
         "scene0" : None,
@@ -80,48 +74,12 @@
     scene_extra_args = {
         "scene5" : ["doAF=False"]
     }
-
-    camera_ids = []
-    scenes = []
-    for s in sys.argv[1:]:
-        if s[:7] == "camera=" and len(s) > 7:
-            camera_ids = s[7:].split(',')
-        elif s[:7] == "scenes=" and len(s) > 7:
-            scenes = s[7:].split(',')
-
-    # Run through all scenes if user does not supply one
-    if not scenes:
-        scenes = all_scenes
-    else:
-        # Validate user input scene names
-        valid_scenes = True
-        temp_scenes = []
-        for s in scenes:
-            if s in all_scenes:
-                temp_scenes.append(s)
-            else:
-                try:
-                    # Try replace "X" to "sceneX"
-                    scene_num = int(s)
-                    scene_str = "scene" + s
-                    if scene_str not in all_scenes:
-                        valid_scenes = False
-                        break
-                    temp_scenes.append(scene_str)
-                except ValueError:
-                    valid_scenes = False
-                    break
-
-        if not valid_scenes:
-            print "Unknown scene specifiied:", s
-            assert(False)
-        scenes = temp_scenes
-
-    # Initialize test results
-    results = {}
-    result_key = ItsSession.RESULT_KEY
-    for s in all_scenes:
-        results[s] = {result_key: ItsSession.RESULT_NOT_EXECUTED}
+    tests = []
+    for d in scenes:
+        tests += [(d,s[:-3],os.path.join("tests", d, s))
+                  for s in os.listdir(os.path.join("tests",d))
+                  if s[-3:] == ".py"]
+    tests.sort()
 
     # Make output directories to hold the generated files.
     topdir = tempfile.mkdtemp()
@@ -131,6 +89,11 @@
     device_id_arg = "device=" + device_id
     print "Testing device " + device_id
 
+    camera_ids = []
+    for s in sys.argv[1:]:
+        if s[:7] == "camera=" and len(s) > 7:
+            camera_ids.append(s[7:])
+
     # user doesn't specify camera id, run through all cameras
     if not camera_ids:
         camera_ids_path = os.path.join(topdir, "camera_ids.txt")
@@ -144,7 +107,7 @@
             for line in f:
                 camera_ids.append(line.replace('\n', ''))
 
-    print "Running ITS on camera: %s, scene %s" % (camera_ids, scenes)
+    print "Running ITS on the following cameras:", camera_ids
 
     for camera_id in camera_ids:
         # Loop capturing images until user confirm test scene is correct
@@ -155,18 +118,17 @@
         for d in scenes:
             os.mkdir(os.path.join(topdir, camera_id, d))
 
-        for scene in scenes:
-            tests = [(s[:-3],os.path.join("tests", scene, s))
-                     for s in os.listdir(os.path.join("tests",scene))
-                     if s[-3:] == ".py" and s[:4] == "test"]
-            tests.sort()
+        print "Start running ITS on camera: ", camera_id
+        # Run each test, capturing stdout and stderr.
+        summary = "ITS test result summary for camera " + camera_id + "\n"
+        numpass = 0
+        numskip = 0
+        numnotmandatedfail = 0
+        numfail = 0
 
-            summary = "Cam" + camera_id + " " + scene + "\n"
-            numpass = 0
-            numskip = 0
-            num_not_mandated_fail = 0
-            numfail = 0
-            if scene_req[scene] != None:
+        prev_scene = ""
+        for (scene,testname,testpath) in tests:
+            if scene != prev_scene and scene_req[scene] != None:
                 out_path = os.path.join(topdir, camera_id, scene+".jpg")
                 out_arg = "out=" + out_path
                 scene_arg = "scene=" + scene_req[scene]
@@ -177,71 +139,64 @@
                         extra_args
                 retcode = subprocess.call(cmd,cwd=topdir)
                 assert(retcode == 0)
-            print "Start running ITS on camera %s, %s" % (camera_id, scene)
+                print "Start running tests for", scene
+            prev_scene = scene
+            cmd = ['python', os.path.join(os.getcwd(),testpath)] + \
+                  sys.argv[1:] + [camera_id_arg]
+            outdir = os.path.join(topdir,camera_id,scene)
+            outpath = os.path.join(outdir,testname+"_stdout.txt")
+            errpath = os.path.join(outdir,testname+"_stderr.txt")
+            t0 = time.time()
+            with open(outpath,"w") as fout, open(errpath,"w") as ferr:
+                retcode = subprocess.call(cmd,stderr=ferr,stdout=fout,cwd=outdir)
+            t1 = time.time()
 
-            # Run each test, capturing stdout and stderr.
-            for (testname,testpath) in tests:
-                cmd = ['python', os.path.join(os.getcwd(),testpath)] + \
-                      sys.argv[1:] + [camera_id_arg]
-                outdir = os.path.join(topdir,camera_id,scene)
-                outpath = os.path.join(outdir,testname+"_stdout.txt")
-                errpath = os.path.join(outdir,testname+"_stderr.txt")
-                t0 = time.time()
-                with open(outpath,"w") as fout, open(errpath,"w") as ferr:
-                    retcode = subprocess.call(
-                            cmd,stderr=ferr,stdout=fout,cwd=outdir)
-                t1 = time.time()
-
-                test_failed = False
-                if retcode == 0:
-                    retstr = "PASS "
-                    numpass += 1
-                elif retcode == SKIP_RET_CODE:
-                    retstr = "SKIP "
-                    numskip += 1
-                elif retcode != 0 and testname in NOT_YET_MANDATED[scene]:
-                    retstr = "FAIL*"
-                    num_not_mandated_fail += 1
-                else:
-                    retstr = "FAIL "
-                    numfail += 1
-                    test_failed = True
-
-                msg = "%s %s/%s [%.1fs]" % (retstr, scene, testname, t1-t0)
-                print msg
-                msg_short = "%s %s [%.1fs]" % (retstr, testname, t1-t0)
-                if test_failed:
-                    summary += msg_short + "\n"
-
-            if numskip > 0:
-                skipstr = ", %d test%s skipped" % (
-                        numskip, "s" if numskip > 1 else "")
+            if retcode == 0:
+                retstr = "PASS "
+                numpass += 1
+            elif retcode == SKIP_RET_CODE:
+                retstr = "SKIP "
+                numskip += 1
+            elif retcode != 0 and testname in NOT_YET_MANDATED[scene]:
+                retstr = "FAIL*"
+                numnotmandatedfail += 1
             else:
-                skipstr = ""
+                retstr = "FAIL "
+                numfail += 1
 
-            test_result = "\n%d / %d tests passed (%.1f%%)%s" % (
-                    numpass + num_not_mandated_fail, len(tests) - numskip,
-                    100.0 * float(numpass + num_not_mandated_fail) /
-                            (len(tests) - numskip)
-                            if len(tests) != numskip else 100.0,
-                    skipstr)
-            print test_result
+            msg = "%s %s/%s [%.1fs]" % (retstr, scene, testname, t1-t0)
+            print msg
+            summary += msg + "\n"
+            if retcode != 0 and retcode != SKIP_RET_CODE:
+                # Dump the stderr if the test fails
+                with open (errpath, "r") as error_file:
+                    errors = error_file.read()
+                    summary += errors + "\n"
 
-            if num_not_mandated_fail > 0:
-                msg = "(*) tests are not yet mandated"
-                print msg
+        if numskip > 0:
+            skipstr = ", %d test%s skipped" % (numskip, "s" if numskip > 1 else "")
+        else:
+            skipstr = ""
 
-            summary_path = os.path.join(topdir, camera_id, scene, "summary.txt")
-            with open(summary_path, "w") as f:
-                f.write(summary)
+        test_result = "\n%d / %d tests passed (%.1f%%)%s" % (
+                numpass + numnotmandatedfail, len(tests) - numskip,
+                100.0 * float(numpass + numnotmandatedfail) / (len(tests) - numskip)
+                    if len(tests) != numskip else 100.0,
+                skipstr)
+        print test_result
+        summary += test_result + "\n"
 
-            passed = numfail == 0
-            results[scene][result_key] = (ItsSession.RESULT_PASS if passed
-                    else ItsSession.RESULT_FAIL)
-            results[scene][ItsSession.SUMMARY_KEY] = summary_path
+        if numnotmandatedfail > 0:
+            msg = "(*) tests are not yet mandated"
+            print msg
+            summary += msg + "\n"
 
+        result = numfail == 0
         print "Reporting ITS result to CtsVerifier"
-        its.device.report_result(device_id, camera_id, results)
+        summary_path = os.path.join(topdir, camera_id, "summary.txt")
+        with open(summary_path, "w") as f:
+            f.write(summary)
+        its.device.report_result(device_id, camera_id, result, summary_path)
 
     print "ITS tests finished. Please go back to CtsVerifier and proceed"
 
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 7815c33..db42422 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -18,7 +18,7 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
       package="com.android.cts.verifier"
       android:versionCode="5"
-      android:versionName="7.0_r5">
+      android:versionName="7.0_r0">
 
     <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="24"/>
 
diff --git a/apps/CtsVerifier/res/layout/its_main.xml b/apps/CtsVerifier/res/layout/its_main.xml
index 26f15bb..2f5eade 100644
--- a/apps/CtsVerifier/res/layout/its_main.xml
+++ b/apps/CtsVerifier/res/layout/its_main.xml
@@ -21,14 +21,4 @@
 
     <include layout="@layout/pass_fail_buttons" />
 
-    <TextView
-        android:id="@+id/its_progress"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:gravity="bottom"
-        android:padding="2dp"
-        android:scrollbars = "vertical"
-        android:text="@string/its_test_progress"
-        android:textSize="16sp" />
-
 </LinearLayout>
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 6cb4778..0486455 100755
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -985,10 +985,6 @@
     </string>
     <string name="its_test_passed">All Camera ITS tests passed.  Pass button enabled!</string>
     <string name="its_test_failed">Some Camera ITS tests failed.</string>
-    <string name="its_version_mismatch">
-        CtsVerifier and ITS script version mismatch. Please update CtsVerifier and ITS script.
-    </string>
-    <string name="its_test_progress">ITS test progress will be shown here.</string>
 
     <!-- Strings for the Camera Flashlight test activity -->
     <string name="camera_flashlight_test">Camera Flashlight</string>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsTestActivity.java
index a8affcd..0c39a9e 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsTestActivity.java
@@ -25,21 +25,15 @@
 import android.hardware.camera2.CameraCharacteristics;
 import android.hardware.camera2.CameraManager;
 import android.os.Bundle;
-import android.text.method.ScrollingMovementMethod;
 import android.util.Log;
 import android.view.WindowManager;
-import android.widget.TextView;
 import android.widget.Toast;
 
 import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Comparator;
 import java.util.HashSet;
 import java.util.HashMap;
-import java.util.Iterator;
+import java.util.Arrays;
 import java.util.List;
-import java.util.Set;
-import java.util.TreeSet;
 import java.io.BufferedReader;
 import java.io.FileReader;
 import java.io.FileNotFoundException;
@@ -50,8 +44,6 @@
 import com.android.cts.verifier.PassFailButtons;
 import com.android.cts.verifier.R;
 
-import org.json.JSONArray;
-import org.json.JSONObject;
 
 /**
  * Test for Camera features that require that the camera be aimed at a specific test scene.
@@ -61,216 +53,48 @@
 public class ItsTestActivity extends PassFailButtons.Activity {
     private static final String TAG = "ItsTestActivity";
     private static final String EXTRA_CAMERA_ID = "camera.its.extra.CAMERA_ID";
-    private static final String EXTRA_RESULTS = "camera.its.extra.RESULTS";
-    private static final String EXTRA_VERSION = "camera.its.extra.VERSION";
-    private static final String CURRENT_VERSION = "1.0";
+    private static final String EXTRA_SUCCESS = "camera.its.extra.SUCCESS";
+    private static final String EXTRA_SUMMARY = "camera.its.extra.SUMMARY";
     private static final String ACTION_ITS_RESULT =
             "com.android.cts.verifier.camera.its.ACTION_ITS_RESULT";
 
-    private static final String RESULT_PASS = "PASS";
-    private static final String RESULT_FAIL = "FAIL";
-    private static final String RESULT_NOT_EXECUTED = "NOT_EXECUTED";
-    private static final Set<String> RESULT_VALUES = new HashSet<String>(
-            Arrays.asList(new String[] {RESULT_PASS, RESULT_FAIL, RESULT_NOT_EXECUTED}));
-    private static final int MAX_SUMMARY_LEN = 200;
-
-    private final ResultReceiver mResultsReceiver = new ResultReceiver();
-
-    // Initialized in onCreate
-    ArrayList<String> mNonLegacyCameraIds = null;
-
-    // TODO: cache the following in saved bundle
-    private Set<ResultKey> mAllScenes = null;
-    // (camera, scene) -> (pass, fail)
-    private final HashMap<ResultKey, Boolean> mExecutedScenes = new HashMap<>();
-    // map camera id to ITS summary report path
-    private final HashMap<ResultKey, String> mSummaryMap = new HashMap<>();
-
-    final class ResultKey {
-        public final String cameraId;
-        public final String sceneId;
-
-        public ResultKey(String cameraId, String sceneId) {
-            this.cameraId = cameraId;
-            this.sceneId = sceneId;
-        }
-
-        @Override
-        public boolean equals(final Object o) {
-            if (o == null) return false;
-            if (this == o) return true;
-            if (o instanceof ResultKey) {
-                final ResultKey other = (ResultKey) o;
-                return cameraId.equals(other.cameraId) && sceneId.equals(other.sceneId);
-            }
-            return false;
-        }
-
-        @Override
-        public int hashCode() {
-            int h = cameraId.hashCode();
-            h = ((h << 5) - h) ^ sceneId.hashCode();
-            return h;
-        }
-    }
-
-    private final Comparator<ResultKey> mComparator = new Comparator<ResultKey>() {
-        @Override
-        public int compare(ResultKey k1, ResultKey k2) {
-            if (k1.cameraId.equals(k2.cameraId))
-                return k1.sceneId.compareTo(k2.sceneId);
-            return k1.cameraId.compareTo(k2.cameraId);
-        }
-    };
-
-    class ResultReceiver extends BroadcastReceiver {
+    class SuccessReceiver extends BroadcastReceiver {
         @Override
         public void onReceive(Context context, Intent intent) {
             Log.i(TAG, "Received result for Camera ITS tests");
             if (ACTION_ITS_RESULT.equals(intent.getAction())) {
-                String version = intent.getStringExtra(EXTRA_VERSION);
-                if (version == null || !version.equals(CURRENT_VERSION)) {
-                    Log.e(TAG, "Its result version mismatch: expect " + CURRENT_VERSION +
-                            ", got " + ((version == null) ? "null" : version));
-                    ItsTestActivity.this.showToast(R.string.its_version_mismatch);
-                    return;
-                }
-
                 String cameraId = intent.getStringExtra(EXTRA_CAMERA_ID);
-                String results = intent.getStringExtra(EXTRA_RESULTS);
-                if (cameraId == null || results == null) {
-                    Log.e(TAG, "cameraId = " + ((cameraId == null) ? "null" : cameraId) +
-                            ", results = " + ((results == null) ? "null" : results));
-                    return;
-                }
-
+                String result = intent.getStringExtra(EXTRA_SUCCESS);
+                String summaryPath = intent.getStringExtra(EXTRA_SUMMARY);
                 if (!mNonLegacyCameraIds.contains(cameraId)) {
                     Log.e(TAG, "Unknown camera id " + cameraId + " reported to ITS");
                     return;
                 }
 
-                try {
-                    /* Sample JSON results string
-                    {
-                       "scene0":{
-                          "result":"PASS",
-                          "summary":"/sdcard/cam0_scene0.txt"
-                       },
-                       "scene1":{
-                          "result":"NOT_EXECUTED"
-                       },
-                       "scene2":{
-                          "result":"FAIL",
-                          "summary":"/sdcard/cam0_scene2.txt"
-                       }
-                    }
-                    */
-                    JSONObject jsonResults = new JSONObject(results);
-                    Set<String> scenes = new HashSet<>();
-                    Iterator<String> keys = jsonResults.keys();
-                    while (keys.hasNext()) {
-                        scenes.add(keys.next());
-                    }
-                    boolean newScenes = false;
-                    if (mAllScenes == null) {
-                        mAllScenes = new TreeSet<>(mComparator);
-                        newScenes = true;
-                    } else { // See if scene lists changed
-                        for (String scene : scenes) {
-                            if (!mAllScenes.contains(new ResultKey(cameraId, scene))) {
-                                // Scene list changed. Cleanup previous test results
-                                newScenes = true;
-                                break;
-                            }
-                        }
-                        for (ResultKey k : mAllScenes) {
-                            if (!scenes.contains(k.sceneId)) {
-                                newScenes = true;
-                                break;
-                            }
-                        }
-                    }
-                    if (newScenes) {
-                        mExecutedScenes.clear();
-                        mAllScenes.clear();
-                        for (String scene : scenes) {
-                            for (String c : mNonLegacyCameraIds) {
-                                mAllScenes.add(new ResultKey(c, scene));
-                            }
-                        }
-                    }
-
-                    // Update test execution results
-                    for (String scene : scenes) {
-                        JSONObject sceneResult = jsonResults.getJSONObject(scene);
-                        String result = sceneResult.getString("result");
-                        if (result == null) {
-                            Log.e(TAG, "Result for " + scene + " is null");
-                            return;
-                        }
-                        Log.i(TAG, "ITS camera" + cameraId + " " + scene + ": result:" + result);
-                        if (!RESULT_VALUES.contains(result)) {
-                            Log.e(TAG, "Unknown result for " + scene + ": " + result);
-                            return;
-                        }
-                        ResultKey key = new ResultKey(cameraId, scene);
-                        if (result.equals(RESULT_PASS) || result.equals(RESULT_FAIL)) {
-                            boolean pass = result.equals(RESULT_PASS);
-                            mExecutedScenes.put(key, pass);
-                            String summary = sceneResult.optString("summary");
-                            if (!summary.equals("")) {
-                                mSummaryMap.put(key, summary);
-                            }
-                        } // do nothing for NOT_EXECUTED scenes
-                    }
-                } catch (org.json.JSONException e) {
-                    Log.e(TAG, "Error reading json result string:" + results , e);
-                    return;
-                }
-
-                // Set summary if all scenes reported
-                if (mSummaryMap.keySet().containsAll(mAllScenes)) {
+                Log.i(TAG, "ITS summary path is: " + summaryPath);
+                mSummaryMap.put(cameraId, summaryPath);
+                // Create summary report
+                if (mSummaryMap.keySet().containsAll(mNonLegacyCameraIds)) {
                     StringBuilder summary = new StringBuilder();
-                    for (String path : mSummaryMap.values()) {
+                    for (String id : mNonLegacyCameraIds) {
+                        String path = mSummaryMap.get(id);
                         appendFileContentToSummary(summary, path);
                     }
-                    if (summary.length() > MAX_SUMMARY_LEN) {
-                        Log.w(TAG, "ITS summary report too long: len: " + summary.length());
-                    }
                     ItsTestActivity.this.getReportLog().setSummary(
                             summary.toString(), 1.0, ResultType.NEUTRAL, ResultUnit.NONE);
                 }
-
-                // Display current progress
-                StringBuilder progress = new StringBuilder();
-                for (ResultKey k : mAllScenes) {
-                    String status = RESULT_NOT_EXECUTED;
-                    if (mExecutedScenes.containsKey(k)) {
-                        status = mExecutedScenes.get(k) ? RESULT_PASS : RESULT_FAIL;
+                boolean pass = result.equals("True");
+                if(pass) {
+                    Log.i(TAG, "Received Camera " + cameraId + " ITS SUCCESS from host.");
+                    mITSPassedCameraIds.add(cameraId);
+                    if (mNonLegacyCameraIds != null && mNonLegacyCameraIds.size() != 0 &&
+                            mITSPassedCameraIds.containsAll(mNonLegacyCameraIds)) {
+                        ItsTestActivity.this.showToast(R.string.its_test_passed);
+                        ItsTestActivity.this.getPassButton().setEnabled(true);
                     }
-                    progress.append(String.format("Cam %s, %s: %s\n",
-                            k.cameraId, k.sceneId, status));
-                }
-                TextView progressView = (TextView) findViewById(R.id.its_progress);
-                progressView.setMovementMethod(new ScrollingMovementMethod());
-                progressView.setText(progress.toString());
-
-
-                // Enable pass button if all scenes pass
-                boolean allScenesPassed = true;
-                for (ResultKey k : mAllScenes) {
-                    Boolean pass = mExecutedScenes.get(k);
-                    if (pass == null || pass == false) {
-                        allScenesPassed = false;
-                        break;
-                    }
-                }
-                if (allScenesPassed) {
-                    // Enable pass button
-                    ItsTestActivity.this.showToast(R.string.its_test_passed);
-                    ItsTestActivity.this.getPassButton().setEnabled(true);
                 } else {
-                    ItsTestActivity.this.getPassButton().setEnabled(false);
+                    Log.i(TAG, "Received Camera " + cameraId + " ITS FAILURE from host.");
+                    ItsTestActivity.this.showToast(R.string.its_test_failed);
                 }
             }
         }
@@ -303,6 +127,12 @@
         }
     }
 
+    private final SuccessReceiver mSuccessReceiver = new SuccessReceiver();
+    private final HashSet<String> mITSPassedCameraIds = new HashSet<>();
+    // map camera id to ITS summary report path
+    private final HashMap<String, String> mSummaryMap = new HashMap<>();
+    ArrayList<String> mNonLegacyCameraIds = null;
+
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -338,7 +168,6 @@
                     "Received error from camera service while checking device capabilities: "
                             + e, Toast.LENGTH_SHORT).show();
         }
-
         getPassButton().setEnabled(false);
     }
 
@@ -351,7 +180,7 @@
         } else {
             Log.d(TAG, "register ITS result receiver");
             IntentFilter filter = new IntentFilter(ACTION_ITS_RESULT);
-            registerReceiver(mResultsReceiver, filter);
+            registerReceiver(mSuccessReceiver, filter);
         }
     }
 
@@ -359,7 +188,7 @@
     protected void onPause() {
         super.onPause();
         Log.d(TAG, "unregister ITS result receiver");
-        unregisterReceiver(mResultsReceiver);
+        unregisterReceiver(mSuccessReceiver);
     }
 
     @Override
diff --git a/common/device-side/preconditions/src/com/android/compatibility/common/preconditions/ScreenLockHelper.java b/common/device-side/preconditions/src/com/android/compatibility/common/preconditions/ScreenLockHelper.java
index 385f22f..d2380af 100644
--- a/common/device-side/preconditions/src/com/android/compatibility/common/preconditions/ScreenLockHelper.java
+++ b/common/device-side/preconditions/src/com/android/compatibility/common/preconditions/ScreenLockHelper.java
@@ -18,7 +18,6 @@
 
 import android.app.KeyguardManager;
 import android.content.Context;
-import android.os.Build;
 
 /**
  * ScreenLockHelper is used to check whether the device is protected by a locked screen.
@@ -30,9 +29,6 @@
      * is no way to programmatically distinguish between the two.
      */
     public static boolean isDeviceSecure(Context context) {
-        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
-            return true; // KeyguardManager.isDeviceSecure() added in M, skip this check
-        }
         KeyguardManager km = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
         return km.isDeviceSecure();
     }
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/ReportLogCollector.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/ReportLogCollector.java
index a1c8a4a..ccb9faf 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/ReportLogCollector.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/ReportLogCollector.java
@@ -17,6 +17,7 @@
 package com.android.compatibility.common.tradefed.targetprep;
 
 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.android.compatibility.common.tradefed.util.CollectorUtil;
 import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.config.Option;
 import com.android.tradefed.device.DeviceNotAvailableException;
@@ -27,18 +28,8 @@
 import com.android.tradefed.targetprep.TargetSetupError;
 import com.android.tradefed.util.FileUtil;
 
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
 import java.io.File;
 import java.io.FileNotFoundException;
-import java.io.FileReader;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 
 /**
  * An {@link ITargetCleaner} that prepares and pulls report logs.
@@ -59,12 +50,12 @@
 
     @Override
     public void setUp(ITestDevice device, IBuildInfo buildInfo) throws TargetSetupError,
-            BuildError, DeviceNotAvailableException {
+        BuildError, DeviceNotAvailableException {
         prepareReportLogContainers(device, buildInfo);
     }
 
     private void addBuildInfo(ITestDevice device, IBuildInfo buildInfo, String key, String value)
-            throws DeviceNotAvailableException {
+        throws DeviceNotAvailableException {
     }
 
     private void prepareReportLogContainers(ITestDevice device, IBuildInfo buildInfo) {
@@ -103,93 +94,12 @@
                 CLog.e("%s is not a directory", hostReportDir.getAbsolutePath());
                 return;
             }
-            pull(device, mSrcDir, hostReportDir, resultDir);
-            reformatRepeatedStreams(resultDir);
+            String resultPath = resultDir.getAbsolutePath();
+            CollectorUtil.pullFromDevice(device, mSrcDir, resultPath);
+            CollectorUtil.pullFromHost(hostReportDir, resultDir);
+            CollectorUtil.reformatRepeatedStreams(resultDir);
         } catch (Exception exception) {
             exception.printStackTrace();
         }
     }
-
-    private void pull(ITestDevice device, String deviceSrc, File hostDir, File destDir) {
-        String hostSrc = hostDir.getAbsolutePath();
-        String dest = destDir.getAbsolutePath();
-        String deviceSideCommand = String.format("adb -s %s pull %s %s", device.getSerialNumber(),
-                deviceSrc, dest);
-        try {
-            if (device.doesFileExist(deviceSrc)) {
-                Process deviceProcess = Runtime.getRuntime().exec(new String[]{"/bin/bash", "-c",
-                        deviceSideCommand});
-                if (deviceProcess.waitFor() != 0) {
-                    CLog.e("Failed to run %s", deviceSideCommand);
-                }
-            }
-            FileUtil.recursiveCopy(hostDir, destDir);
-            FileUtil.recursiveDelete(hostDir);
-        } catch (Exception e) {
-            CLog.e("Caught exception during pull.");
-            CLog.e(e);
-        }
-    }
-
-    private void reformatRepeatedStreams(File resultDir) throws IOException, FileNotFoundException {
-        File[] reportLogs = resultDir.listFiles();
-        // Sometimes report logs are in a sub-directory.
-        if (reportLogs.length == 1 && reportLogs[0].isDirectory()) {
-            reportLogs = reportLogs[0].listFiles();
-        }
-        for (File reportLog : reportLogs) {
-            try (BufferedReader metricsReader = new BufferedReader(new FileReader(reportLog))) {
-                // Get metrics as string.
-                StringBuilder metricBuilder = new StringBuilder();
-                String line;
-                while ((line = metricsReader.readLine()) != null) {
-                    metricBuilder.append(line);
-                }
-                String metrics = metricBuilder.toString();
-                // Create map of stream names and metrics.
-                HashMap<String, List<String>> metricsMap = new HashMap<>();
-                String pattern = "\\\"([a-z0-9_]*)\\\":(\\{[^{}]*\\})";
-                Pattern p = Pattern.compile(pattern);
-                Matcher m = p.matcher(metrics);
-                while (m.find()) {
-                    String key = m.group(1);
-                    String value = m.group(2);
-                    if (!metricsMap.containsKey(key)) {
-                        metricsMap.put(key, new ArrayList<String>());
-                    }
-                    metricsMap.get(key).add(value);
-                }
-                // Rewrite metrics as arrays.
-                StringBuilder newMetricsBuilder = new StringBuilder();
-                newMetricsBuilder.append("{");
-                boolean firstLine = true;
-                for (String key: metricsMap.keySet()) {
-                    if (!firstLine) {
-                        newMetricsBuilder.append(",");
-                    } else {
-                        firstLine = false;
-                    }
-                    newMetricsBuilder.append("\"").append(key).append("\":[");
-                    boolean firstValue = true;
-                    for (String stream : metricsMap.get(key)) {
-                        if (!firstValue) {
-                            newMetricsBuilder.append(",");
-                        }
-                        else {
-                            firstValue = false;
-                        }
-                        newMetricsBuilder.append(stream);
-                    }
-                    newMetricsBuilder.append("]");
-                }
-                newMetricsBuilder.append("}");
-                reportLog.createNewFile();
-                try (BufferedWriter metricsWriter = new BufferedWriter(new
-                        FileWriter(reportLog))) {
-                    String newMetrics = newMetricsBuilder.toString();
-                    metricsWriter.write(newMetrics, 0, newMetrics.length());
-                }
-            }
-        }
-    }
 }
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/CompatibilityTest.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/CompatibilityTest.java
index bc7a29b..0397a42 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/CompatibilityTest.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/CompatibilityTest.java
@@ -96,6 +96,7 @@
     private static final String SHARD_OPTION = "shards";
     public static final String SKIP_DEVICE_INFO_OPTION = "skip-device-info";
     public static final String SKIP_PRECONDITIONS_OPTION = "skip-preconditions";
+    public static final String PRIMARY_ABI_RUN = "primary-abi-only";
     public static final String DEVICE_TOKEN_OPTION = "device-token";
     public static final String LOGCAT_ON_FAILURE_SIZE_OPTION = "logcat-on-failure-size";
     private static final String URL = "dynamic-config-url";
@@ -193,6 +194,11 @@
             description = "Whether preconditions should be skipped")
     private boolean mSkipPreconditions = false;
 
+    @Option(name = PRIMARY_ABI_RUN,
+            description = "Whether to run tests with only the device primary abi. "
+                    + "This override the --abi option.")
+    private boolean mPrimaryAbiRun = false;
+
     @Option(name = DEVICE_TOKEN_OPTION,
             description = "Holds the devices' tokens, used when scheduling tests that have"
                     + "prerequisites such as requiring a SIM card. Format is <serial>:<token>",
@@ -413,7 +419,9 @@
                 }
 
                 // execute pre module execution checker
-                runPreModuleCheck(module.getName(), checkers, mDevice, listener);
+                if (checkers != null && !checkers.isEmpty()) {
+                    runPreModuleCheck(module.getName(), checkers, mDevice, listener);
+                }
                 try {
                     module.run(listener);
                 } catch (DeviceUnresponsiveException due) {
@@ -443,7 +451,9 @@
                             TimeUtil.formatElapsedTime(expected),
                             TimeUtil.formatElapsedTime(duration));
                 }
-                runPostModuleCheck(module.getName(), checkers, mDevice, listener);
+                if (checkers != null && !checkers.isEmpty()) {
+                    runPostModuleCheck(module.getName(), checkers, mDevice, listener);
+                }
             }
         } catch (FileNotFoundException fnfe) {
             throw new RuntimeException("Failed to initialize modules", fnfe);
@@ -459,6 +469,15 @@
     Set<IAbi> getAbis() throws DeviceNotAvailableException {
         Set<IAbi> abis = new HashSet<>();
         Set<String> archAbis = AbiUtils.getAbisForArch(SuiteInfo.TARGET_ARCH);
+        if (mPrimaryAbiRun) {
+            if (mAbiName == null) {
+                // Get the primary from the device and make it the --abi to run.
+                mAbiName = mDevice.getProperty("ro.product.cpu.abi").trim();
+            } else {
+                CLog.d("Option --%s supersedes the option --%s, using abi: %s", ABI_OPTION,
+                        PRIMARY_ABI_RUN, mAbiName);
+            }
+        }
         for (String abi : AbiFormatter.getSupportedAbis(mDevice, "")) {
             // Only test against ABIs supported by Compatibility, and if the
             // --abi option was given, it must match.
@@ -467,7 +486,7 @@
                 abis.add(new Abi(abi, AbiUtils.getBitness(abi)));
             }
         }
-        if (abis == null || abis.isEmpty()) {
+        if (abis.isEmpty()) {
             if (mAbiName == null) {
                 throw new IllegalArgumentException("Could not get device's ABIs");
             } else {
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityTests.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityTests.java
index 00acdf5..e500b00 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityTests.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityTests.java
@@ -25,9 +25,17 @@
 import com.android.tradefed.testtype.IAbi;
 import com.android.tradefed.testtype.IAbiReceiver;
 import com.android.tradefed.testtype.IBuildReceiver;
+import com.android.tradefed.util.RunUtil;
 
+import java.io.BufferedReader;
+import java.io.EOFException;
 import java.io.File;
 import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * Set of tests that verify various security checks involving multiple apps are
@@ -289,6 +297,26 @@
         }
     }
 
+    /**
+     * Tests that an arbitrary file cannot be installed using the 'cmd' command.
+     */
+    public void testAdbInstallFile() throws Exception {
+        final List<String> output = AdbOutputReader.getOutput(5000L, new String[] {
+                "adb",
+                "-s",
+                getDevice().getSerialNumber(),
+                "shell",
+                "cmd",
+                "package",
+                "install",
+                "-S",
+                "1024",
+                "/data/local/tmp/foo.apk",
+        });
+        assertEquals("Line count", 1, output.size());
+        assertEquals("Error text", "Error: APK content must be streamed", output.get(0));
+    }
+
     private void runDeviceTests(String packageName) throws DeviceNotAvailableException {
         Utils.runDeviceTests(getDevice(), packageName);
     }
@@ -297,4 +325,66 @@
             throws DeviceNotAvailableException {
         Utils.runDeviceTests(getDevice(), packageName, testClassName, testMethodName);
     }
+
+    /** Helper class to collect the output from a command. */
+    private static class AdbOutputReader {
+        public static List<String> getOutput(long timeout, String... command) throws Exception {
+            final Process adbProcess = RunUtil.getDefault().runCmdInBackground(command);
+            final InputStream in = adbProcess.getInputStream();
+            final List<String> lines = new ArrayList<>();
+            final Object threadLock = new Object();
+            final Thread t = new Thread(new Runnable() {
+                @Override
+                public void run() {
+                    synchronized (threadLock) {
+                        readLines(in, lines);
+                        threadLock.notify();
+                    }
+                }
+            });
+            final long end = System.currentTimeMillis() + timeout;
+            synchronized (threadLock) {
+                t.start();
+                long now = System.currentTimeMillis();
+                while (now < end) {
+                    try {
+                        threadLock.wait(end - now);
+                    } catch (InterruptedException e) {
+                        now = System.currentTimeMillis();
+                        continue;
+                    }
+                    break;
+                }
+            }
+            adbProcess.destroy();
+            t.join();
+            return lines;
+        }
+
+        private static void readLines(InputStream in, List<String> lines) {
+            BufferedReader br = null;
+            try {
+                br = new BufferedReader(new InputStreamReader(in));
+                String line;
+                while ((line = readLineIgnoreException(br)) != null) {
+                    lines.add(line);
+                }
+            } catch (IOException ignore) {
+            } finally {
+                if (br != null) {
+                    try {
+                        br.close();
+                    } catch (IOException ignore) { }
+                }
+            }
+        }
+
+        private static String readLineIgnoreException(BufferedReader reader) throws IOException {
+            try {
+                return reader.readLine();
+            } catch (EOFException ignore) {
+                return null;
+            }
+        }
+    }
 }
diff --git a/hostsidetests/services/windowmanager/src/android/wm/cts/CrossAppDragAndDropTests.java b/hostsidetests/services/windowmanager/src/android/wm/cts/CrossAppDragAndDropTests.java
index ccdba15..8fc3264 100644
--- a/hostsidetests/services/windowmanager/src/android/wm/cts/CrossAppDragAndDropTests.java
+++ b/hostsidetests/services/windowmanager/src/android/wm/cts/CrossAppDragAndDropTests.java
@@ -209,16 +209,8 @@
         mDevice.executeShellCommand(AM_STACK_LIST, outputReceiver);
         final String output = outputReceiver.getOutput();
         for (String line : output.split("\\n")) {
-            final String truncatedLine;
-            // Only look for the activity name before the "topActivity" string.
-            final int pos = line.indexOf("topActivity");
-            if (pos > 0) {
-                truncatedLine = line.substring(0, pos);
-            } else {
-                truncatedLine = line;
-            }
-            if (truncatedLine.contains(name)) {
-                return truncatedLine;
+            if (line.contains(name)) {
+                return line;
             }
         }
         return "";
diff --git a/tests/tests/location/src/android/location/cts/LocationManagerTest.java b/tests/tests/location/src/android/location/cts/LocationManagerTest.java
index 7fcc2aa..f829bf3 100644
--- a/tests/tests/location/src/android/location/cts/LocationManagerTest.java
+++ b/tests/tests/location/src/android/location/cts/LocationManagerTest.java
@@ -993,6 +993,19 @@
         }
     }
 
+    /**
+     * Test case for bug 33091107.
+     */
+    public void testLocationShouldStillBeMarkedMockWhenProvidersDoNotMatch()
+        throws InterruptedException {
+        double latitude = 20;
+        double longitude = 40;
+
+        // Register a listener for the location we are about to set.
+        updateLocationAndWait(
+                TEST_MOCK_PROVIDER_NAME, LocationManager.GPS_PROVIDER, latitude, longitude);
+    }
+
     @UiThreadTest
     public void testGpsStatusListener() {
         MockGpsStatusListener listener = new MockGpsStatusListener();
@@ -1152,22 +1165,38 @@
 
     private void updateLocationAndWait(String providerName, double latitude, double longitude)
             throws InterruptedException {
+        updateLocationAndWait(providerName, providerName, latitude, longitude);
+    }
+
+    /**
+     * Like {@link #updateLocationAndWait(String, double, double)}, but allows inconsistent providers
+     * to be used in the calls to {@link Location#Location(String)} and {@link
+     * LocationManager#setTestProviderLocation(String, Location)}
+     *
+     * @param testProviderName used in {@link LocationManager#setTestProviderLocation(String,
+     * Location)}
+     * @param locationProviderName used in {@link Location#Location(String)}
+     */
+    private void updateLocationAndWait(String testProviderName, String locationProviderName,
+        double latitude, double longitude) throws InterruptedException {
+
         // Register a listener for the location we are about to set.
         MockLocationListener listener = new MockLocationListener();
         HandlerThread handlerThread = new HandlerThread("updateLocationAndWait");
         handlerThread.start();
-        mManager.requestLocationUpdates(providerName, 0, 0, listener, handlerThread.getLooper());
+        mManager.requestLocationUpdates(locationProviderName, 0, 0, listener,
+                handlerThread.getLooper());
 
         // Set the location.
-        updateLocation(providerName, latitude, longitude);
+        updateLocation(testProviderName, locationProviderName, latitude, longitude);
 
         // Make sure we received the location, and it is the right one.
-        assertTrue(listener.hasCalledOnLocationChanged(TEST_TIME_OUT));
+        assertTrue("Listener not called", listener.hasCalledOnLocationChanged(TEST_TIME_OUT));
         Location location = listener.getLocation();
-        assertEquals(providerName, location.getProvider());
-        assertEquals(latitude, location.getLatitude());
-        assertEquals(longitude, location.getLongitude());
-        assertEquals(true, location.isFromMockProvider());
+        assertEquals("Bad provider name", locationProviderName, location.getProvider());
+        assertEquals("Bad latitude", latitude, location.getLatitude());
+        assertEquals("Bad longitude", longitude, location.getLongitude());
+        assertTrue("Bad isMock", location.isFromMockProvider());
 
         // Remove the listener.
         mManager.removeUpdates(listener);
@@ -1220,13 +1249,23 @@
 
     private void updateLocation(final String providerName, final double latitude,
             final double longitude) {
-        Location location = new Location(providerName);
+        updateLocation(providerName, providerName, latitude, longitude);
+    }
+
+    /**
+     * Like {@link #updateLocation(String, double, double)}, but allows inconsistent providers to be
+     * used in the calls to {@link Location#Location(String)} and
+     * {@link LocationManager#setTestProviderLocation(String, Location)}.
+     */
+    private void updateLocation(String testProviderName, String locationProviderName,
+        double latitude, double longitude) {
+        Location location = new Location(locationProviderName);
         location.setLatitude(latitude);
         location.setLongitude(longitude);
         location.setAccuracy(1.0f);
-        location.setTime(java.lang.System.currentTimeMillis());
+        location.setTime(System.currentTimeMillis());
         location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
-        mManager.setTestProviderLocation(providerName, location);
+        mManager.setTestProviderLocation(testProviderName, location);
     }
 
     private void updateLocation(final double latitude, final double longitude) {
diff --git a/tests/tests/media/src/android/media/cts/MediaRecorderTest.java b/tests/tests/media/src/android/media/cts/MediaRecorderTest.java
index 32d9eaa..dffb653 100644
--- a/tests/tests/media/src/android/media/cts/MediaRecorderTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaRecorderTest.java
@@ -424,6 +424,17 @@
         return 1;
     }
 
+    public void testRecordAudioFromAudioSourceUnprocessed() throws Exception {
+        if (!hasMicrophone()) {
+            return; // skip
+        }
+        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.UNPROCESSED);
+        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
+        mMediaRecorder.setOutputFile(OUTPUT_PATH);
+        mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
+        recordMedia(MAX_FILE_SIZE, mOutFile);
+    }
+
     public void testGetAudioSourceMax() throws Exception {
         final int max = MediaRecorder.getAudioSourceMax();
         assertTrue(MediaRecorder.AudioSource.DEFAULT <= max);
diff --git a/tests/tests/os/src/android/os/cts/SecurityPatchTest.java b/tests/tests/os/src/android/os/cts/SecurityPatchTest.java
index 4531aa6..a857670 100644
--- a/tests/tests/os/src/android/os/cts/SecurityPatchTest.java
+++ b/tests/tests/os/src/android/os/cts/SecurityPatchTest.java
@@ -31,8 +31,8 @@
             "ro.build.version.security_patch should be in the format \"YYYY-MM-DD\". Found \"%s\"";
     private static final String SECURITY_PATCH_DATE_ERROR =
             "ro.build.version.security_patch should be \"%d-%02d\" or later. Found \"%s\"";
-    private static final int SECURITY_PATCH_YEAR = 2016;
-    private static final int SECURITY_PATCH_MONTH = 12;
+    private static final int SECURITY_PATCH_YEAR = 2017;
+    private static final int SECURITY_PATCH_MONTH = 01;
 
     private boolean mSkipTests = false;
 
diff --git a/tests/tests/permission2/res/raw/android_manifest.xml b/tests/tests/permission2/res/raw/android_manifest.xml
index 4ebe527..2bee7a6 100644
--- a/tests/tests/permission2/res/raw/android_manifest.xml
+++ b/tests/tests/permission2/res/raw/android_manifest.xml
@@ -3022,7 +3022,7 @@
     <!-- @SystemApi Allows access to MAC addresses of WiFi and Bluetooth peer devices.
         @hide -->
     <permission android:name="android.permission.PEERS_MAC_ADDRESS"
-                android:protectionLevel="signature" />
+                android:protectionLevel="signature|setup" />
 
     <!-- Allows the Nfc stack to dispatch Nfc messages to applications. Applications
         can use this permission to ensure incoming Nfc messages are from the Nfc stack
diff --git a/tests/tests/security/AndroidManifest.xml b/tests/tests/security/AndroidManifest.xml
index 7468d68..7b87851 100644
--- a/tests/tests/security/AndroidManifest.xml
+++ b/tests/tests/security/AndroidManifest.xml
@@ -25,6 +25,7 @@
     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
     <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.RECORD_AUDIO" />
 
     <application>
         <uses-library android:name="android.test.runner" />
diff --git a/tests/tests/security/jni/android_security_cts_NativeCodeTest.cpp b/tests/tests/security/jni/android_security_cts_NativeCodeTest.cpp
index 25dcc9b..12c3517 100644
--- a/tests/tests/security/jni/android_security_cts_NativeCodeTest.cpp
+++ b/tests/tests/security/jni/android_security_cts_NativeCodeTest.cpp
@@ -303,14 +303,18 @@
      * set up to overflow iov[OVERFLOW_BUF] on non-atomic redo in kernel
      * function pipe_iov_copy_to_user
      */
-    bufs[OVERFLOW_BUF] = mmap((void*)(FIXED_ADDR), PAGE_SIZE, PROT_READ | PROT_WRITE,
-            MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
+    iovs[OVERFLOW_BUF - 1].iov_len = IOV_LEN*10;
+    iovs[OVERFLOW_BUF].iov_base = bufs[OVERFLOW_BUF];
+    iovs[OVERFLOW_BUF].iov_len = IOV_LEN;
+
+    overflow_addr = mmap((void *) FIXED_ADDR, PAGE_SIZE, PROT_READ | PROT_WRITE,
+            MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+
+    bufs[OVERFLOW_BUF] = overflow_addr;
     if (bufs[OVERFLOW_BUF] == MAP_FAILED) {
         ALOGE("mmap fixed addr failed:%s", strerror(errno));
         goto __close_pipe;
     }
-    iovs[OVERFLOW_BUF].iov_base = bufs[OVERFLOW_BUF];
-    iovs[OVERFLOW_BUF].iov_len = IOV_LEN;
 
     for (i = 0; i < BUFS; i++) {
         if (i == OVERFLOW_BUF) {
diff --git a/tests/tests/security/res/raw/bug_27855419.mp4 b/tests/tests/security/res/raw/bug_27855419.mp4
deleted file mode 100644
index 51bfa74..0000000
--- a/tests/tests/security/res/raw/bug_27855419.mp4
+++ /dev/null
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_31647370.ogg b/tests/tests/security/res/raw/bug_31647370.ogg
new file mode 100644
index 0000000..31f602a
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_31647370.ogg
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_32322258.mp4 b/tests/tests/security/res/raw/bug_32322258.mp4
new file mode 100644
index 0000000..6fcab5e
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_32322258.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_32577290.mp3 b/tests/tests/security/res/raw/bug_32577290.mp3
new file mode 100644
index 0000000..1098bb0
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_32577290.mp3
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_32873375.mp4 b/tests/tests/security/res/raw/bug_32873375.mp4
new file mode 100644
index 0000000..71e9c7b
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_32873375.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_32915871.mp4 b/tests/tests/security/res/raw/bug_32915871.mp4
new file mode 100644
index 0000000..9e50aaa
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_32915871.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2016_2429_b_27211885.mp3 b/tests/tests/security/res/raw/cve_2016_2429_b_27211885.mp3
new file mode 100644
index 0000000..0232e70
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2016_2429_b_27211885.mp3
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2016_3755.mp4 b/tests/tests/security/res/raw/cve_2016_3755.mp4
new file mode 100644
index 0000000..014bd06
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2016_3755.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2016_3878_b_29493002.mp4 b/tests/tests/security/res/raw/cve_2016_3878_b_29493002.mp4
new file mode 100644
index 0000000..469a1b3
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2016_3878_b_29493002.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/onekhzsine_90sec.mp3 b/tests/tests/security/res/raw/onekhzsine_90sec.mp3
new file mode 100644
index 0000000..3049011
--- /dev/null
+++ b/tests/tests/security/res/raw/onekhzsine_90sec.mp3
Binary files differ
diff --git a/tests/tests/security/src/android/security/cts/EffectBundleTest.java b/tests/tests/security/src/android/security/cts/EffectBundleTest.java
new file mode 100644
index 0000000..c844fbb
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/EffectBundleTest.java
@@ -0,0 +1,339 @@
+/*
+ * Copyright (C) 2016 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.security.cts;
+
+import android.media.audiofx.AudioEffect;
+import android.media.audiofx.Equalizer;
+import android.media.MediaPlayer;
+import android.test.InstrumentationTestCase;
+import android.util.Log;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+
+public class EffectBundleTest extends InstrumentationTestCase {
+    private static final String TAG = "EffectBundleTest";
+    private static final int[] INVALID_BAND_ARRAY = {Integer.MIN_VALUE, -10000, -100, -2, -1};
+    private static final int mValue0 = 9999; //unlikely values. Should not change
+    private static final int mValue1 = 13877;
+    private static final int PRESET_CUSTOM = -1; //keep in sync AudioEqualizer.h
+
+    private static final int MEDIA_SHORT = 0;
+    private static final int MEDIA_LONG = 1;
+
+    //Testing security bug: 32436341
+    public void testEqualizer_getParamCenterFreq() throws Exception {
+        testGetParam(MEDIA_SHORT, Equalizer.PARAM_CENTER_FREQ, INVALID_BAND_ARRAY, mValue0,
+                mValue1);
+    }
+
+    //Testing security bug: 32588352
+    public void testEqualizer_getParamCenterFreq_long() throws Exception {
+        testGetParam(MEDIA_LONG, Equalizer.PARAM_CENTER_FREQ, INVALID_BAND_ARRAY, mValue0, mValue1);
+    }
+
+    //Testing security bug: 32438598
+    public void testEqualizer_getParamBandLevel() throws Exception {
+        testGetParam(MEDIA_SHORT, Equalizer.PARAM_BAND_LEVEL, INVALID_BAND_ARRAY, mValue0, mValue1);
+    }
+
+    //Testing security bug: 32584034
+    public void testEqualizer_getParamBandLevel_long() throws Exception {
+        testGetParam(MEDIA_LONG, Equalizer.PARAM_BAND_LEVEL, INVALID_BAND_ARRAY, mValue0, mValue1);
+    }
+
+    //Testing security bug: 32247948
+    public void testEqualizer_getParamFreqRange() throws Exception {
+        testGetParam(MEDIA_SHORT, Equalizer.PARAM_BAND_FREQ_RANGE, INVALID_BAND_ARRAY, mValue0,
+                mValue1);
+    }
+
+    //Testing security bug: 32588756
+    public void testEqualizer_getParamFreqRange_long() throws Exception {
+        testGetParam(MEDIA_LONG, Equalizer.PARAM_BAND_FREQ_RANGE, INVALID_BAND_ARRAY, mValue0,
+                mValue1);
+    }
+
+    //Testing security bug: 32448258
+    public void testEqualizer_getParamPresetName() throws Exception {
+        testParamPresetName(MEDIA_SHORT);
+    }
+
+    //Testing security bug: 32588016
+    public void testEqualizer_getParamPresetName_long() throws Exception {
+        testParamPresetName(MEDIA_LONG);
+    }
+
+    private void testParamPresetName(int media) {
+        final int command = Equalizer.PARAM_GET_PRESET_NAME;
+        for (int invalidBand : INVALID_BAND_ARRAY)
+        {
+            final byte testValue = 7;
+            byte reply[] = new byte[Equalizer.PARAM_STRING_SIZE_MAX];
+            Arrays.fill(reply, testValue);
+            if (!eqGetParam(media, command, invalidBand, reply)) {
+                fail("getParam PARAM_GET_PRESET_NAME did not complete successfully");
+            }
+            //Compare
+            if (invalidBand == PRESET_CUSTOM) {
+                final String expectedName = "Custom";
+                int length = 0;
+                while (reply[length] != 0) length++;
+                try {
+                    final String presetName =  new String(reply, 0, length,
+                            StandardCharsets.ISO_8859_1.name());
+                    assertEquals("getPresetName custom preset name failed", expectedName,
+                            presetName);
+                } catch (Exception e) {
+                    Log.w(TAG,"Problem creating reply string.");
+                }
+            } else {
+                for (int i = 0; i < reply.length; i++) {
+                    assertEquals(String.format("getParam should not change reply at byte %d", i),
+                            testValue, reply[i]);
+                }
+            }
+        }
+    }
+
+    //testing security bug: 32095626
+    public void testEqualizer_setParamBandLevel() throws Exception {
+        final int command = Equalizer.PARAM_BAND_LEVEL;
+        short[] value = { 1000 };
+        for (int invalidBand : INVALID_BAND_ARRAY)
+        {
+            if (!eqSetParam(MEDIA_SHORT, command, invalidBand, value)) {
+                fail("setParam PARAM_BAND_LEVEL did not complete successfully");
+            }
+        }
+    }
+
+    //testing security bug: 32585400
+    public void testEqualizer_setParamBandLevel_long() throws Exception {
+        final int command = Equalizer.PARAM_BAND_LEVEL;
+        short[] value = { 1000 };
+        for (int invalidBand : INVALID_BAND_ARRAY)
+        {
+            if (!eqSetParam(MEDIA_LONG, command, invalidBand, value)) {
+                fail("setParam PARAM_BAND_LEVEL did not complete successfully");
+            }
+        }
+    }
+
+    //testing security bug: 32705438
+    public void testEqualizer_getParamFreqRangeCommand_short() throws Exception {
+        assertTrue("testEqualizer_getParamFreqRangeCommand_short did not complete successfully",
+                eqGetParamFreqRangeCommand(MEDIA_SHORT));
+    }
+
+    //testing security bug: 32703959
+    public void testEqualizer_getParamFreqRangeCommand_long() throws Exception {
+        assertTrue("testEqualizer_getParamFreqRangeCommand_long did not complete successfully",
+                eqGetParamFreqRangeCommand(MEDIA_LONG));
+    }
+
+    private boolean eqGetParamFreqRangeCommand(int media) {
+        MediaPlayer mp = null;
+        Equalizer eq = null;
+        boolean status = false;
+        try {
+            mp = MediaPlayer.create(getInstrumentation().getContext(), getMediaId(media));
+            eq = new Equalizer(0 /*priority*/, mp.getAudioSessionId());
+
+            short band = 2;
+            int intSize = 4; //bytes
+
+            //baseline
+            int cmdCode = 8; // EFFECT_CMD_GET_PARAM
+            byte command[] = concatArrays(/*status*/ intToByteArray(0),
+                    /*psize*/ intToByteArray(2 * intSize),
+                    /*vsize*/ intToByteArray(2 * intSize),
+                    /*data[0]*/ intToByteArray(Equalizer.PARAM_BAND_FREQ_RANGE),
+                    /*data[1]*/ intToByteArray((int) band));
+
+            byte reply[] = new byte[command.length];
+
+            AudioEffect af = eq;
+            Object o = AudioEffect.class.getDeclaredMethod("command", int.class, byte[].class,
+                    byte[].class).invoke(af, cmdCode, command, reply);
+
+            int methodStatus = AudioEffect.ERROR;
+            if (o != null) {
+                methodStatus = Integer.valueOf(o.toString()).intValue();
+            }
+
+            assertTrue("Command expected to fail", methodStatus <= 0);
+            int sum = 0;
+            for (int i = 0; i < reply.length; i++) {
+                sum += Math.abs(reply[i]);
+            }
+
+            assertEquals("reply expected to be all zeros", sum, 0);
+            status = true;
+        } catch (Exception e) {
+            Log.w(TAG,"Problem testing eqGetParamFreqRangeCommand");
+            status = false;
+        } finally {
+            if (eq != null) {
+                eq.release();
+            }
+            if (mp != null) {
+                mp.release();
+            }
+        }
+        return status;
+    }
+
+    private boolean eqGetParam(int media, int command, int band, byte[] reply) {
+        MediaPlayer mp = null;
+        Equalizer eq = null;
+        boolean status = false;
+        try {
+            mp = MediaPlayer.create(getInstrumentation().getContext(), getMediaId(media));
+            eq = new Equalizer(0 /*priority*/, mp.getAudioSessionId());
+
+            AudioEffect af = eq;
+            int cmd[] = {command, band};
+
+            AudioEffect.class.getDeclaredMethod("getParameter", int[].class,
+                    byte[].class).invoke(af, cmd, reply);
+            status = true;
+        } catch (Exception e) {
+            Log.w(TAG,"Problem testing equalizer");
+            status = false;
+        } finally {
+            if (eq != null) {
+                eq.release();
+            }
+            if (mp != null) {
+                mp.release();
+            }
+        }
+        return status;
+    }
+
+    private boolean eqGetParam(int media, int command, int band, int[] reply) {
+        MediaPlayer mp = null;
+        Equalizer eq = null;
+        boolean status = false;
+        try {
+            mp = MediaPlayer.create(getInstrumentation().getContext(), getMediaId(media));
+            eq = new Equalizer(0 /*priority*/, mp.getAudioSessionId());
+
+            AudioEffect af = eq;
+            int cmd[] = {command, band};
+
+            AudioEffect.class.getDeclaredMethod("getParameter", int[].class,
+                    int[].class).invoke(af, cmd, reply);
+            status = true;
+        } catch (Exception e) {
+            Log.w(TAG,"Problem getting parameter from equalizer");
+            status = false;
+        } finally {
+            if (eq != null) {
+                eq.release();
+            }
+            if (mp != null) {
+                mp.release();
+            }
+        }
+        return status;
+    }
+
+    private void testGetParam(int media, int command, int[] bandArray, int value0, int value1) {
+        int reply[] = {value0, value1};
+        for (int invalidBand : INVALID_BAND_ARRAY)
+        {
+            if (!eqGetParam(media, command, invalidBand, reply)) {
+                fail(String.format("getParam for command %d did not complete successfully",
+                        command));
+            }
+            assertEquals("getParam should not change value0", value0, reply[0]);
+            assertEquals("getParam should not change value1", value1, reply[1]);
+        }
+    }
+
+    private boolean eqSetParam(int media, int command, int band, short[] value) {
+        MediaPlayer mp = null;
+        Equalizer eq = null;
+        boolean status = false;
+        try {
+            mp = MediaPlayer.create(getInstrumentation().getContext(),  getMediaId(media));
+            eq = new Equalizer(0 /*priority*/, mp.getAudioSessionId());
+
+            AudioEffect af = eq;
+            int cmd[] = {command, band};
+
+            AudioEffect.class.getDeclaredMethod("setParameter", int[].class,
+                    short[].class).invoke(af, cmd, value);
+            status = true;
+        } catch (Exception e) {
+            Log.w(TAG,"Problem setting parameter in equalizer");
+            status = false;
+        } finally {
+            if (eq != null) {
+                eq.release();
+            }
+            if (mp != null) {
+                mp.release();
+            }
+        }
+        return status;
+    }
+
+    private int getMediaId(int media) {
+        switch (media) {
+            default:
+            case MEDIA_SHORT:
+                return R.raw.good;
+            case MEDIA_LONG:
+                return R.raw.onekhzsine_90sec;
+        }
+    }
+
+    private static byte[] intToByteArray(int value) {
+        ByteBuffer converter = ByteBuffer.allocate(4);
+        converter.order(ByteOrder.nativeOrder());
+        converter.putInt(value);
+        return converter.array();
+    }
+
+    private static byte[] shortToByteArray(short value) {
+        ByteBuffer converter = ByteBuffer.allocate(2);
+        converter.order(ByteOrder.nativeOrder());
+        short sValue = (short) value;
+        converter.putShort(sValue);
+        return converter.array();
+    }
+
+    private static  byte[] concatArrays(byte[]... arrays) {
+        int len = 0;
+        for (byte[] a : arrays) {
+            len += a.length;
+        }
+        byte[] b = new byte[len];
+
+        int offs = 0;
+        for (byte[] a : arrays) {
+            System.arraycopy(a, 0, b, offs, a.length);
+            offs += a.length;
+        }
+        return b;
+    }
+}
diff --git a/tests/tests/security/src/android/security/cts/StagefrightTest.java b/tests/tests/security/src/android/security/cts/StagefrightTest.java
index 8205c22..9ca409d 100644
--- a/tests/tests/security/src/android/security/cts/StagefrightTest.java
+++ b/tests/tests/security/src/android/security/cts/StagefrightTest.java
@@ -62,6 +62,14 @@
     public StagefrightTest() {
     }
 
+    public void testStagefright_bug_31647370() throws Exception {
+        doStagefrightTest(R.raw.bug_31647370);
+    }
+
+    public void testStagefright_bug_32577290() throws Exception {
+        doStagefrightTest(R.raw.bug_32577290);
+    }
+
     public void testStagefright_cve_2015_1538_1() throws Exception {
         doStagefrightTest(R.raw.cve_2015_1538_1);
     }
@@ -110,6 +118,10 @@
         doStagefrightTest(R.raw.cve_2015_6598);
     }
 
+    public void testStagefright_bug_32873375() throws Exception {
+        doStagefrightTest(R.raw.bug_32873375);
+    }
+
     public void testStagefright_bug_26366256() throws Exception {
         doStagefrightTest(R.raw.bug_26366256);
     }
@@ -134,6 +146,10 @@
         doStagefrightTest(R.raw.cve_2015_3869);
     }
 
+    public void testStagefright_bug_32322258() throws Exception {
+        doStagefrightTest(R.raw.bug_32322258);
+    }
+
     public void testStagefright_cve_2015_3873_b_23248776() throws Exception {
         doStagefrightTest(R.raw.cve_2015_3873_b_23248776);
     }
@@ -154,16 +170,28 @@
         doStagefrightTest(R.raw.cve_2015_3873_b_21814993);
     }
 
+    public void testStagefright_bug_32915871() throws Exception {
+        doStagefrightTest(R.raw.bug_32915871);
+    }
+
     public void testStagefright_bug_28333006() throws Exception {
         doStagefrightTest(R.raw.bug_28333006);
     }
 
-   public void testStagefright_bug_14388161() throws Exception {
+    public void testStagefright_bug_14388161() throws Exception {
         doStagefrightTestMediaPlayer(R.raw.bug_14388161);
     }
 
-    public void testStagefright_bug_27855419_CVE_2016_2463() throws Exception {
-        doStagefrightTest(R.raw.bug_27855419);
+    public void testStagefright_cve_2016_3755() throws Exception {
+        doStagefrightTest(R.raw.cve_2016_3755);
+    }
+
+    public void testStagefright_cve_2016_3878_b_29493002() throws Exception {
+        doStagefrightTest(R.raw.cve_2016_3878_b_29493002);
+    }
+
+    public void testStagefright_cve_2016_2429_b_27211885() throws Exception {
+        doStagefrightTest(R.raw.cve_2016_2429_b_27211885);
     }
 
     private void doStagefrightTest(final int rid) throws Exception {
@@ -307,6 +335,7 @@
         assertFalse("Device *IS* vulnerable to " + cve,
                     mpcl.waitForError() == MediaPlayer.MEDIA_ERROR_SERVER_DIED);
         t.stopLooper();
+        t.join(); // wait for thread to exit so we're sure the player was released
     }
 
     private void doStagefrightTestMediaCodec(final int rid) throws Exception {
diff --git a/tests/tests/security/src/android/security/cts/VisualizerEffectTest.java b/tests/tests/security/src/android/security/cts/VisualizerEffectTest.java
new file mode 100644
index 0000000..a17bf96
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/VisualizerEffectTest.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2016 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.security.cts;
+
+import junit.framework.TestCase;
+
+import android.content.Context;
+import android.media.audiofx.AudioEffect;
+import android.media.MediaPlayer;
+import android.media.audiofx.Visualizer;
+import android.test.AndroidTestCase;
+import android.test.InstrumentationTestCase;
+import android.util.Log;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.util.UUID;
+
+public class VisualizerEffectTest extends InstrumentationTestCase {
+    private String TAG = "VisualizerEffectTest";
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    //Testing security bug: 30229821
+    public void testVisualizer_MalformedConstructor() throws Exception {
+        final String VISUALIZER_TYPE = "e46b26a0-dddd-11db-8afd-0002a5d5c51b";
+        final int VISUALIZER_CMD_MEASURE = 0x10001;
+
+        AudioEffect.Descriptor[] descriptors = AudioEffect.queryEffects();
+        int i, visualizerIndex = -1;
+        for (i = 0; i < descriptors.length; ++i) {
+            AudioEffect.Descriptor descriptor = descriptors[i];
+            if (descriptor.type.compareTo(UUID.fromString(VISUALIZER_TYPE)) == 0) {
+                visualizerIndex = i;
+
+                AudioEffect ae = null;
+                MediaPlayer mp = null;
+                try {
+                    mp = MediaPlayer.create(getInstrumentation().getContext(), R.raw.good);
+                    Constructor ct = AudioEffect.class.getConstructor(UUID.class, UUID.class,
+                            int.class, int.class);
+                    ae = (AudioEffect) ct.newInstance(descriptors[visualizerIndex].type,
+                            descriptors[visualizerIndex].uuid, 0, mp.getAudioSessionId());
+                    Method command = AudioEffect.class.getDeclaredMethod("command", int.class,
+                            byte[].class, byte[].class);
+                    Integer ret = (Integer) command.invoke(ae, new Object[]{VISUALIZER_CMD_MEASURE,
+                            new byte[0], new byte[0]});
+                    assertTrue("Audio server might have crashed", ret != -7);
+                } catch (Exception e) {
+                    Log.w(TAG,"Problem testing visualizer");
+                } finally {
+                    if (ae != null) {
+                        ae.release();
+                    }
+                    if (mp != null) {
+                        mp.release();
+                    }
+                }
+            }
+        }
+
+        if (visualizerIndex == -1) {
+            Log.w(TAG,"No visualizer found to test");
+        }
+    }
+}
diff --git a/tools/cts-tradefed/Android.mk b/tools/cts-tradefed/Android.mk
index fbf63d7..55bf524 100644
--- a/tools/cts-tradefed/Android.mk
+++ b/tools/cts-tradefed/Android.mk
@@ -25,7 +25,7 @@
 LOCAL_SUITE_TARGET_ARCH := $(TARGET_ARCH)
 LOCAL_SUITE_NAME := CTS
 LOCAL_SUITE_FULLNAME := "Compatibility Test Suite"
-LOCAL_SUITE_VERSION := 7.0_r5
+LOCAL_SUITE_VERSION := 7.0_r201702s
 
 LOCAL_MODULE := cts-tradefed
 
diff --git a/tools/cts-tradefed/res/config/cts-dev.xml b/tools/cts-tradefed/res/config/cts-dev.xml
new file mode 100644
index 0000000..0cf53ca
--- /dev/null
+++ b/tools/cts-tradefed/res/config/cts-dev.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+<configuration description="Runs CTS with common options set developer workflow: skips most checks">
+
+    <include name="cts" />
+
+    <option name="log-level" value="verbose" />
+    <option name="skip-preconditions" value="true" />
+    <option name="skip-device-info" value="true" />
+
+    <option name="compatibility:plan" value="cts-dev" />
+    <option name="compatibility:skip-all-system-status-check" value="true" />
+    <option name="compatibility:primary-abi-only" value="true" />
+
+</configuration>
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java b/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java
index 6385139..2463f87 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java
@@ -48,7 +48,7 @@
     @Option(name="branch", description="build branch name to supply.")
     private String mBranch = null;
 
-    public static final String CTS_BUILD_VERSION = "7.0_r3";
+    public static final String CTS_BUILD_VERSION = "7.0_r201701s";
     public static final String CTS_PACKAGE = "com.android.cts.tradefed.testtype";
 
     /**
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/util/ReportLogUtil.java b/tools/tradefed-host/src/com/android/cts/tradefed/util/ReportLogUtil.java
index 6ab175f..9233a4a 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/util/ReportLogUtil.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/util/ReportLogUtil.java
@@ -43,7 +43,6 @@
             // Delete earlier report logs if present on device.
             String command = String.format("adb -s %s shell rm -rf %s", device.getSerialNumber(),
                     SRC_DIR);
-            CLog.e(command);
             if (device.doesFileExist(SRC_DIR)) {
                 Process process = Runtime.getRuntime().exec(new String[]{"/bin/bash", "-c",
                         command});