Merge tag 'android-6.0.1_r3' into 601r3

Android 6.0.1 release 3

* tag 'android-6.0.1_r3': (61 commits)
  DO NOT MERGE ANYWHERE: bumping CTS 5.1 to R4
  DO NOT MERGE: Add FEATURE_CAMERA_EXTERNAL to front-facing camera condition
  Add FEATURE_CAMERA_EXTERNAL to front-facing camera condition
  DO NOT MERGE: Fix ION memory leak for camera2 testStillPreviewCombination tstcase
  DO NOT MERGE: Camera: add testAllOutputYUVResolutions back to known failure
  Increase wait timeout for ContextWrapperTest
  Change CTS verifier HifiUltrasound Tests text to be consistent with CDD text
  CTS: DO tests for DISALLOW_CONFIG_VPN
  Fix CameraManagerTest logic.
  cts: Skip encodeDecode tests when there is no needed encoder
  Stop android.print tests from executing if the device does not support print.
  DO NOT MERGE Add running time hints to CTS package config
  CameraITS: use linear tonemap in test_exposure
  TIF: Make sure that Cursor.moveToNext() is called before using Cursor
  DO NOT MERGE: Adding testConnectivityConstraintExecutes_withMobile to knownfailure list.
  Adding testConnectivityConstraintExecutes_withMobile to knownfailure list.
  DO NOT MERGE CTS version is now 6.0_r1.5
  AudioRecordTest: Remove assert check on cold input start time
  Stop android.print tests from executing if the device does not support print.
  Restrict telephony.cts.CellInfoTest to Devices with FEATURE_TELEPHONY
  ...

Change-Id: I8d670f35346bc28ec4176ae8b20ca8dc3a0d823a
diff --git a/CtsBuild.mk b/CtsBuild.mk
index c745885..ba158ce 100644
--- a/CtsBuild.mk
+++ b/CtsBuild.mk
@@ -40,6 +40,10 @@
 	$(foreach executable,$(1),$(CTS_TESTCASES_OUT)/$(executable))
 endef
 
+define cts-get-deqp-api-test-xmls
+	$(foreach file,$(call find-files-in-subdirs, external/deqp/android/cts/master, 'com.drawelements.deqp.$(1).*xml', .),$(CTS_TESTCASES_OUT)/$(file))
+endef
+
 define cts-get-deqp-test-xmls
-	$(foreach api,$(1),$(CTS_TESTCASES_OUT)/com.drawelements.deqp.$(api).xml)
+	$(foreach api,$(1),$(call cts-get-deqp-api-test-xmls,$(api)))
 endef
diff --git a/apps/CameraITS/tests/scene1/test_exposure.py b/apps/CameraITS/tests/scene1/test_exposure.py
index 89bc724..94bd002 100644
--- a/apps/CameraITS/tests/scene1/test_exposure.py
+++ b/apps/CameraITS/tests/scene1/test_exposure.py
@@ -62,7 +62,7 @@
             s_test = round(s*m)
             e_test = s_e_product / s_test
             print "Testsing s:", s_test, "e:", e_test
-            req = its.objects.manual_capture_request(s_test, e_test)
+            req = its.objects.manual_capture_request(s*m, e/m, True)
             cap = cam.do_capture(req)
             s_res = cap["metadata"]["android.sensor.sensitivity"]
             e_res = cap["metadata"]["android.sensor.exposureTime"]
diff --git a/apps/CtsVerifier/Android.mk b/apps/CtsVerifier/Android.mk
index 34246cc..924524b 100644
--- a/apps/CtsVerifier/Android.mk
+++ b/apps/CtsVerifier/Android.mk
@@ -41,7 +41,7 @@
 
 LOCAL_PACKAGE_NAME := CtsVerifier
 
-LOCAL_AAPT_FLAGS += --version-name "6.0_r1 $(BUILD_NUMBER)"
+LOCAL_AAPT_FLAGS += --version-name "6.0_r1.5 $(BUILD_NUMBER)"
 
 LOCAL_JNI_SHARED_LIBRARIES := libctsverifier_jni libaudioloopback_jni
 
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index ea16821..5e8ab90 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -1709,15 +1709,12 @@
         </activity>
 
         <activity android:name=".audio.AudioOutputDeviceNotificationsActivity"
-                  android:label="@string/audio_in_devices_notifications_test">
+                  android:label="@string/audio_out_devices_notifications_test">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.cts.intent.category.MANUAL_TEST" />
             </intent-filter>
             <meta-data android:name="test_category" android:value="@string/test_category_audio" />
-            <!--
-            <meta-data android:name="test_required_features" android:value="android.hardware.microphone" />
-            -->
             <meta-data android:name="test_required_features" android:value="android.hardware.audio.output" />
         </activity>
 
@@ -1739,7 +1736,7 @@
             </intent-filter>
             <meta-data android:name="test_category" android:value="@string/test_category_audio" />
             <meta-data android:name="test_required_features" android:value="android.hardware.audio.output" />
-        </activity>
+            </activity>
 
         <activity android:name=".audio.AudioInputRoutingNotificationsActivity"
                   android:label="@string/audio_input_routingnotifications_test">
@@ -1749,7 +1746,7 @@
             </intent-filter>
             <meta-data android:name="test_category" android:value="@string/test_category_audio" />
             <meta-data android:name="test_required_features" android:value="android.hardware.microphone" />
-        </activity>
+            </activity>
 
         <activity android:name=".audio.AudioLoopbackActivity"
                   android:label="@string/audio_loopback_test">
diff --git a/apps/CtsVerifier/res/layout/audio_dev_notify.xml b/apps/CtsVerifier/res/layout/audio_dev_notify.xml
index 0975ab9..ceedf1c 100644
--- a/apps/CtsVerifier/res/layout/audio_dev_notify.xml
+++ b/apps/CtsVerifier/res/layout/audio_dev_notify.xml
@@ -13,13 +13,46 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:id="@+id/scrollView"
+    >
+
+<LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:padding="10dip"
+        android:padding="20dp"
         android:orientation="vertical">
 
-  <TextView
+        <TextView
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:scrollbars="vertical"
+            android:gravity="bottom"
+            android:id="@+id/audio_general_headset_port_exists"
+            android:text="@string/audio_general_headset_port_exists" />
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal">
+
+            <Button
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:id="@+id/audio_general_headset_no"
+                android:text="@string/audio_general_headset_no" />
+
+            <Button
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:id="@+id/audio_general_headset_yes"
+                android:text="@string/audio_general_headset_yes" />
+        </LinearLayout>
+
+    <TextView
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:scrollbars="vertical"
@@ -50,4 +83,5 @@
 
   <include layout="@layout/pass_fail_buttons" />
 
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
+</ScrollView>
diff --git a/apps/CtsVerifier/res/layout/audio_input_routingnotifications_test.xml b/apps/CtsVerifier/res/layout/audio_input_routingnotifications_test.xml
index ca7dd19..60a12ef 100644
--- a/apps/CtsVerifier/res/layout/audio_input_routingnotifications_test.xml
+++ b/apps/CtsVerifier/res/layout/audio_input_routingnotifications_test.xml
@@ -14,13 +14,45 @@
      limitations under the License.
 -->
 
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:id="@+id/scrollView"
+    >
+
+<LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:padding="10dip"
+        android:padding = "20dp"
         android:orientation="vertical">
 
-  <TextView
+        <TextView
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:scrollbars="vertical"
+            android:gravity="bottom"
+            android:id="@+id/audio_general_headset_port_exists"
+            android:text="@string/audio_general_headset_port_exists" />
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal">
+
+            <Button
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:id="@+id/audio_general_headset_no"
+                android:text="@string/audio_general_headset_no" />
+
+            <Button
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:id="@+id/audio_general_headset_yes"
+                android:text="@string/audio_general_headset_yes" />
+        </LinearLayout>
+
+    <TextView
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:scrollbars="vertical"
@@ -63,4 +95,5 @@
 
   <include layout="@layout/pass_fail_buttons" />
 
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
+</ScrollView>
diff --git a/apps/CtsVerifier/res/layout/audio_output_routingnotifications_test.xml b/apps/CtsVerifier/res/layout/audio_output_routingnotifications_test.xml
index b321000..d039691 100644
--- a/apps/CtsVerifier/res/layout/audio_output_routingnotifications_test.xml
+++ b/apps/CtsVerifier/res/layout/audio_output_routingnotifications_test.xml
@@ -14,13 +14,46 @@
      limitations under the License.
 -->
 
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:id="@+id/scrollView"
+    >
+
+    <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:padding="10dip"
+        android:padding="20dp"
         android:orientation="vertical">
 
-  <TextView
+        <TextView
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:scrollbars="vertical"
+            android:gravity="bottom"
+            android:id="@+id/audio_general_headset_port_exists"
+            android:text="@string/audio_general_headset_port_exists" />
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal">
+
+            <Button
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:id="@+id/audio_general_headset_no"
+                android:text="@string/audio_general_headset_no" />
+
+            <Button
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:id="@+id/audio_general_headset_yes"
+                android:text="@string/audio_general_headset_yes" />
+
+        </LinearLayout>
+
+    <TextView
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:scrollbars="vertical"
@@ -63,4 +96,5 @@
 
   <include layout="@layout/pass_fail_buttons" />
 
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
+</ScrollView>
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index d8a96eb..f4d7825 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -339,8 +339,7 @@
     <string name="hifi_ultrasound_test_default_false_string">false</string>
     <string name="hifi_ultrasound_test_mic_no_support">
         Device does not support near-ultrasound recording.\n
-        All new phones and tablets MUST support near-ultrasound recording.\n
-        Report FAIL if this is a new device, report PASS if this is an updating device.\n</string>
+        Please report PASS.\n</string>
     <string name="hifi_ultrasound_test_spkr_no_support">
         Device does not support near-ultrasound playback.\n
         If this is your reference device, please use a different reference device.\n</string>
@@ -360,8 +359,7 @@
         If this is your reference device, please use a different reference device.\n</string>
     <string name="hifi_ultrasound_speaker_test_spkr_no_support">
         Device does not support near-ultrasound playback.\n
-        All new phones and tablets MUST support near-ultrasound playback.\n
-        Report FAIL if this is a new device, report PASS if this is an updating device.\n</string>
+        Please report PASS.\n</string>
     <string name="hifi_ultrasound_speaker_test_test_side">
         Please wait for the result on the reference device then report here.</string>
     <string name="hifi_ultrasound_speaker_test_reference_side">
@@ -1732,7 +1730,7 @@
     <string name="device_owner_wifi_lockdown_info">
             Please enter the SSID and auth method of an available WiFi Access Point and press the button to create a
             WiFi configuration. This configuration can be seen on Settings &gt; WiFi. The test cases
-            are going use this config. Please go through test cases in order (from top to bottom).
+            are going to use this config. Please go through test cases in order (from top to bottom).
     </string>
     <string name="switch_wifi_lockdown_off_button">WiFi config lockdown off</string>
     <string name="switch_wifi_lockdown_on_button">WiFi config lockdown on</string>
@@ -1854,6 +1852,18 @@
     <string name="device_owner_user_restriction_set">Set restriction</string>
     <string name="device_owner_settings_go">Go</string>
 
+    <string name="device_owner_disallow_config_vpn">Disallow configuring VPN</string>
+    <string name="device_owner_disallow_config_vpn_info">
+        Please press the Set VPN restriction button to set the VPN restriction.
+        Then press Go to open the VPN page.\n\n
+        Confirm that:\n
+        - You cannot add a new VPN network.\n
+        - You cannot edit, add or remove any existing VPNs.\n
+        \n
+        Use the Back button to return to this page.
+    </string>
+    <string name="device_owner_user_vpn_restriction_set">Set VPN restriction</string>
+
     <!-- Strings for JobScheduler Tests -->
     <string name="js_test_description">This test is mostly automated, but requires some user interaction. You can pass this test once the list items below are checked.</string>
 
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInputDeviceNotificationsActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInputDeviceNotificationsActivity.java
index 3513774..e253635 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInputDeviceNotificationsActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInputDeviceNotificationsActivity.java
@@ -16,7 +16,6 @@
 
 package com.android.cts.verifier.audio;
 
-import com.android.cts.verifier.PassFailButtons;
 import com.android.cts.verifier.R;
 
 import android.content.Context;
@@ -37,7 +36,7 @@
  * Tests Audio Device Connection events for output by prompting the user to insert/remove a
  * wired headset (or microphone) and noting the presence (or absence) of notifications.
  */
-public class AudioInputDeviceNotificationsActivity extends PassFailButtons.Activity {
+public class AudioInputDeviceNotificationsActivity extends HeadsetHonorSystemActivity {
     Context mContext;
 
     TextView mConnectView;
@@ -62,6 +61,11 @@
     }
 
     @Override
+    protected void enableTestButtons(boolean enabled) {
+        // Nothing to do.
+    }
+
+    @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.audio_dev_notify);
@@ -85,6 +89,9 @@
         AudioManager audioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
         audioManager.registerAudioDeviceCallback(new TestAudioDeviceCallback(), null);
 
+        // "Honor System" buttons
+        super.setup();
+
         setPassFailButtonClickListeners();
     }
 }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInputRoutingNotificationsActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInputRoutingNotificationsActivity.java
index cdc8199..eefa9e4 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInputRoutingNotificationsActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInputRoutingNotificationsActivity.java
@@ -16,7 +16,6 @@
 
 package com.android.cts.verifier.audio;
 
-import com.android.cts.verifier.PassFailButtons;
 import com.android.cts.verifier.R;
 
 import android.content.Context;
@@ -40,9 +39,12 @@
 /**
  * Tests AudioRecord (re)Routing messages.
  */
-public class AudioInputRoutingNotificationsActivity extends PassFailButtons.Activity {
+public class AudioInputRoutingNotificationsActivity extends HeadsetHonorSystemActivity {
     private static final String TAG = "AudioInputRoutingNotificationsActivity";
 
+    Button recordBtn;
+    Button stopBtn;
+
     Context mContext;
 
     int mNumRecordNotifications = 0;
@@ -82,16 +84,21 @@
         }
     }
 
+    protected void enableTestButtons(boolean enabled) {
+        recordBtn.setEnabled(enabled);
+        stopBtn.setEnabled(enabled);
+    }
+
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.audio_input_routingnotifications_test);
 
         Button btn;
-        btn = (Button)findViewById(R.id.audio_routingnotification_recordBtn);
-        btn.setOnClickListener(mBtnClickListener);
-        btn = (Button)findViewById(R.id.audio_routingnotification_recordStopBtn);
-        btn.setOnClickListener(mBtnClickListener);
+        recordBtn = (Button)findViewById(R.id.audio_routingnotification_recordBtn);
+        recordBtn.setOnClickListener(mBtnClickListener);
+        stopBtn = (Button)findViewById(R.id.audio_routingnotification_recordStopBtn);
+        stopBtn.setOnClickListener(mBtnClickListener);
 
         mContext = this;
 
@@ -99,6 +106,9 @@
         audioRecord.addOnRoutingChangedListener(
             new AudioRecordRoutingChangeListener(), new Handler());
 
+        // "Honor System" buttons
+        super.setup();
+
         setPassFailButtonClickListeners();
     }
 
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutputDeviceNotificationsActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutputDeviceNotificationsActivity.java
index a64ddc4..ad8ba68 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutputDeviceNotificationsActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutputDeviceNotificationsActivity.java
@@ -16,7 +16,6 @@
 
 package com.android.cts.verifier.audio;
 
-import com.android.cts.verifier.PassFailButtons;
 import com.android.cts.verifier.R;
 
 import android.content.Context;
@@ -37,7 +36,7 @@
  * Tests Audio Device Connection events for output devices by prompting the user to
  * insert/remove a wired headset and noting the presence (or absence) of notifications.
  */
-public class AudioOutputDeviceNotificationsActivity extends PassFailButtons.Activity {
+public class AudioOutputDeviceNotificationsActivity extends HeadsetHonorSystemActivity {
     Context mContext;
 
     TextView mConnectView;
@@ -62,6 +61,11 @@
     }
 
     @Override
+    protected void enableTestButtons(boolean enabled) {
+        // Nothing to do.
+    }
+
+    @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.audio_dev_notify);
@@ -85,6 +89,9 @@
         AudioManager audioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
         audioManager.registerAudioDeviceCallback(new TestAudioDeviceCallback(), null);
 
+        // "Honor System" buttons
+        super.setup();
+
         setPassFailButtonClickListeners();
     }
 }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutputRoutingNotificationsActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutputRoutingNotificationsActivity.java
index bfc3d45..a6d8846 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutputRoutingNotificationsActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutputRoutingNotificationsActivity.java
@@ -16,7 +16,6 @@
 
 package com.android.cts.verifier.audio;
 
-import com.android.cts.verifier.PassFailButtons;
 import com.android.cts.verifier.R;
 
 import android.content.Context;
@@ -40,12 +39,15 @@
 /**
  * Tests AudioTrack and AudioRecord (re)Routing messages.
  */
-public class AudioOutputRoutingNotificationsActivity extends PassFailButtons.Activity {
+public class AudioOutputRoutingNotificationsActivity extends HeadsetHonorSystemActivity {
     private static final String TAG = "AudioOutputRoutingNotificationsActivity";
 
     Context mContext;
 
-    OnBtnClickListener mBtnClickListener = new OnBtnClickListener();
+    Button playBtn;
+    Button stopBtn;
+
+    private OnBtnClickListener mBtnClickListener = new OnBtnClickListener();
 
     int mNumTrackNotifications = 0;
 
@@ -83,22 +85,30 @@
     }
 
     @Override
+    protected void enableTestButtons(boolean enabled) {
+        playBtn.setEnabled(enabled);
+        stopBtn.setEnabled(enabled);
+    }
+
+    @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.audio_output_routingnotifications_test);
 
-        Button btn;
-        btn = (Button)findViewById(R.id.audio_routingnotification_playBtn);
-        btn.setOnClickListener(mBtnClickListener);
-        btn = (Button)findViewById(R.id.audio_routingnotification_playStopBtn);
-        btn.setOnClickListener(mBtnClickListener);
-
         mContext = this;
 
+        playBtn = (Button)findViewById(R.id.audio_routingnotification_playBtn);
+        playBtn.setOnClickListener(mBtnClickListener);
+        stopBtn = (Button)findViewById(R.id.audio_routingnotification_playStopBtn);
+        stopBtn.setOnClickListener(mBtnClickListener);
+
         AudioTrack audioTrack = mAudioPlayer.getAudioTrack();
         audioTrack.addOnRoutingChangedListener(
             new AudioTrackRoutingChangeListener(), new Handler());
 
+        // "Honor System" buttons
+        super.setup();
+
         setPassFailButtonClickListeners();
     }
 
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/HeadsetHonorSystemActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/HeadsetHonorSystemActivity.java
new file mode 100644
index 0000000..a82b994
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/HeadsetHonorSystemActivity.java
@@ -0,0 +1,83 @@
+/*
+ * 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 com.android.cts.verifier.audio;
+
+import com.android.cts.verifier.PassFailButtons;
+import com.android.cts.verifier.R;
+
+import com.android.compatibility.common.util.ReportLog;
+import com.android.compatibility.common.util.ResultType;
+import com.android.compatibility.common.util.ResultUnit;
+
+import android.content.Context;
+
+import android.os.Bundle;
+import android.os.Handler;
+
+import android.util.Log;
+
+import android.view.View;
+import android.view.View.OnClickListener;
+
+import android.widget.Button;
+//import android.widget.TextView;
+
+abstract class HeadsetHonorSystemActivity extends PassFailButtons.Activity {
+    private static final String TAG = "HeadsetHonorSystemActivity";
+
+    private OnBtnClickListener mBtnClickListener = new OnBtnClickListener();
+
+    abstract protected void enableTestButtons(boolean enabled);
+
+    private void recordHeadsetPortFound(boolean found) {
+        getReportLog().addValue(
+                "User Reported Headset Port",
+                found ? 1.0 : 0,
+                ResultType.NEUTRAL,
+                ResultUnit.NONE);
+    }
+
+    protected void setup() {
+        // The "Honor" system buttons
+        ((Button)findViewById(R.id.audio_general_headset_no)).
+            setOnClickListener(mBtnClickListener);
+        ((Button)findViewById(R.id.audio_general_headset_yes)).
+            setOnClickListener(mBtnClickListener);
+
+        enableTestButtons(false);
+    }
+
+    private class OnBtnClickListener implements OnClickListener {
+        @Override
+        public void onClick(View v) {
+            switch (v.getId()) {
+                case R.id.audio_general_headset_no:
+                    Log.i(TAG, "User denies Headset Port existence");
+                    enableTestButtons(false);
+                    recordHeadsetPortFound(false);
+                    break;
+
+                case R.id.audio_general_headset_yes:
+                    Log.i(TAG, "User confirms Headset Port existence");
+                    enableTestButtons(true);
+                    recordHeadsetPortFound(true);
+                    break;
+            }
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java
index b129665..a5022a3 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java
@@ -347,6 +347,9 @@
         adapter.add(mKeyguardDisabledFeaturesTest);
         adapter.add(mAuthenticationBoundKeyTest);
 
+        /* If there is an application that handles ACTION_IMAGE_CAPTURE, test that it handles it
+         * well.
+         */
         if (canResolveIntent(ByodHelperActivity.getCaptureImageIntent())) {
             // Capture image intent can be resolved in primary profile, so test.
             mCrossProfileImageCaptureSupportTest = new DialogTestListItem(this,
@@ -362,6 +365,9 @@
                     .show();
         }
 
+        /* If there is an application that handles ACTION_VIDEO_CAPTURE, test that it handles it
+         * well.
+         */
         if (canResolveIntent(ByodHelperActivity.getCaptureVideoIntent())) {
             // Capture video intent can be resolved in primary profile, so test.
             mCrossProfileVideoCaptureSupportTest = new DialogTestListItem(this,
@@ -409,7 +415,9 @@
             adapter.add(mDisableNfcBeamTest);
         }
 
-        /* TODO: reinstate when bug b/20131958 is fixed
+        /* If there is an application that handles RECORD_SOUND_ACTION, test that it handles it
+         * well.
+         */
         if (canResolveIntent(ByodHelperActivity.getCaptureAudioIntent())) {
             // Capture audio intent can be resolved in primary profile, so test.
             mCrossProfileAudioCaptureSupportTest = new DialogTestListItem(this,
@@ -424,7 +432,6 @@
                     R.string.provisioning_byod_no_audio_capture_resolver, Toast.LENGTH_SHORT)
                     .show();
         }
-        */
     }
 
     // Return whether the intent can be resolved in the current profile
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java
index a6a5e5a..79b9933 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java
@@ -75,6 +75,9 @@
             PermissionLockdownTestActivity.class.getName();
     private static final String DISALLOW_CONFIG_BT_ID = "DISALLOW_CONFIG_BT";
     private static final String DISALLOW_CONFIG_WIFI_ID = "DISALLOW_CONFIG_WIFI";
+    private static final String DISALLOW_CONFIG_VPN_ID = "DISALLOW_CONFIG_VPN";
+    //TODO(rgl): This symbol should be available in android.provider.settings
+    private static final String ACTION_VPN_SETTINGS = "android.net.vpn.SETTINGS";
     private static final String REMOVE_DEVICE_OWNER_TEST_ID = "REMOVE_DEVICE_OWNER";
 
     @Override
@@ -166,6 +169,19 @@
                                     new Intent(Settings.ACTION_WIFI_SETTINGS))}));
         }
 
+        // DISALLOW_CONFIG_VPN
+        adapter.add(createInteractiveTestItem(this, DISALLOW_CONFIG_VPN_ID,
+                R.string.device_owner_disallow_config_vpn,
+                R.string.device_owner_disallow_config_vpn_info,
+                new ButtonInfo[] {
+                        new ButtonInfo(
+                                R.string.device_owner_user_vpn_restriction_set,
+                                createSetUserRestrictionIntent(
+                                        UserManager.DISALLOW_CONFIG_VPN)),
+                        new ButtonInfo(
+                                R.string.device_owner_settings_go,
+                                new Intent(ACTION_VPN_SETTINGS))}));
+
         // DISALLOW_CONFIG_BLUETOOTH
         if (packageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)) {
             adapter.add(createInteractiveTestItem(this, DISALLOW_CONFIG_BT_ID,
@@ -326,6 +342,7 @@
             dpm.setKeyguardDisabled(admin, false);
             dpm.clearUserRestriction(admin, UserManager.DISALLOW_CONFIG_BLUETOOTH);
             dpm.clearUserRestriction(admin, UserManager.DISALLOW_CONFIG_WIFI);
+            dpm.clearUserRestriction(admin, UserManager.DISALLOW_CONFIG_VPN);
             dpm.clearDeviceOwnerApp(getPackageName());
         }
     }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/screenpinning/ScreenPinningTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/screenpinning/ScreenPinningTestActivity.java
index 8e72ebb..0728fb5 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/screenpinning/ScreenPinningTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/screenpinning/ScreenPinningTestActivity.java
@@ -31,6 +31,8 @@
 
     private static final String TAG = "ScreenPinningTestActivity";
     private static final String KEY_CURRENT_TEST = "keyCurrentTest";
+    private static final long TASK_MODE_CHECK_DELAY = 200;
+    private static final int MAX_TASK_MODE_CHECK_COUNT = 5;
 
     private Test[] mTests;
     private int mTestIndex;
@@ -203,10 +205,18 @@
                 return;
             }
             stopLockTask();
-            if (!mActivityManager.isInLockTaskMode()) {
-                succeed();
-            } else {
-                error(R.string.error_screen_pinning_couldnt_exit);
+            for (int retry = MAX_TASK_MODE_CHECK_COUNT; retry > 0; retry--) {
+                try {
+                    Thread.sleep(TASK_MODE_CHECK_DELAY);
+                } catch (InterruptedException e) {
+                }
+                Log.d(TAG, "Check unpin ... " + retry);
+                if (!mActivityManager.isInLockTaskMode()) {
+                    succeed();
+                    break;
+                } else if (retry == 1) {
+                    error(R.string.error_screen_pinning_couldnt_exit);
+                }
             }
         };
     };
diff --git a/build/test_deqp_package.mk b/build/test_deqp_package.mk
index 8fbae26..650875c 100644
--- a/build/test_deqp_package.mk
+++ b/build/test_deqp_package.mk
@@ -18,15 +18,14 @@
 
 CTS_DEQP_CONFIG_PATH := $(call my-dir)
 
-cts_library_xml := $(CTS_TESTCASES_OUT)/com.drawelements.deqp.$(DEQP_API).xml
-$(cts_library_xml): MUSTPASS_XML_FILE := external/deqp/android/cts/master/com.drawelements.deqp.$(DEQP_API).xml
-$(cts_library_xml): PRIVATE_TEST_NAME := $(DEQP_TEST_NAME)
-$(cts_library_xml): PRIVATE_TEST_PACKAGE := com.drawelements.deqp.$(DEQP_API)
-$(cts_library_xml): PRIVATE_DUMMY_CASELIST := $(CTS_DEQP_CONFIG_PATH)/deqp_dummy_test_list
-$(cts_library_xml): external/deqp/android/cts/master/com.drawelements.deqp.$(DEQP_API).xml $(CTS_EXPECTATIONS) $(CTS_UNSUPPORTED_ABIS) $(CTS_XML_GENERATOR)
-	$(hide) echo Generating test description for $(PRIVATE_TEST_NAME)
+cts_library_xmls:=$(foreach xml_file, $(call find-files-in-subdirs, external/deqp/android/cts/master, 'com.drawelements.deqp.$(DEQP_API).*xml', .), $(CTS_TESTCASES_OUT)/$(xml_file))
+$(cts_library_xmls) : PRIVATE_API := $(DEQP_API)
+$(cts_library_xmls) : PRIVATE_TEST_NAME := $(DEQP_TEST_NAME)
+$(cts_library_xmls) : PRIVATE_TEST_PACKAGE := com.drawelements.deqp.$(DEQP_API)
+$(cts_library_xmls) : PRIVATE_DUMMY_CASELIST := $(CTS_DEQP_CONFIG_PATH)/deqp_dummy_test_list
+$(cts_library_xmls) : $(CTS_TESTCASES_OUT)/%.xml: external/deqp/android/cts/master/%.xml $(CTS_EXPECTATIONS) $(CTS_UNSUPPORTED_ABIS) $(CTS_XML_GENERATOR)
+	$(hide) echo Generating test description $@
 	$(hide) mkdir -p $(CTS_TESTCASES_OUT)
-
 # Query build ABIs by routing a dummy test list through xml generator and parse result
 	$(hide) $(eval supported_abi_attr := $(shell $(CTS_XML_GENERATOR) -t dummyTest \
 										-n dummyName \
@@ -36,8 +35,7 @@
 										-a $(CTS_TARGET_ARCH) \
 										< $(PRIVATE_DUMMY_CASELIST) \
 										| grep --only-matching -e " abis=\"[^\"]*\""))
-
 # Patch xml caselist with supported abi
 	$(hide) $(SED_EXTENDED) -e 's:^(\s*)<Test ((.[^/]|[^/])*)(/?)>$$:\1<Test \2 $(supported_abi_attr)\4>:' \
-				< $(MUSTPASS_XML_FILE) \
+				< $< \
 				> $@
diff --git a/build/test_package.mk b/build/test_package.mk
index c6b0865..13e582e 100644
--- a/build/test_package.mk
+++ b/build/test_package.mk
@@ -39,6 +39,11 @@
 else
 PRIVATE_CTS_TEST_PACKAGE_NAME_ := android.$(notdir $(LOCAL_PATH))
 endif
+ifeq ($(cts_runtime_hint),)
+$(cts_package_xml): PRIVATE_CTS_RUNTIME_HINT := "0"
+else
+$(cts_package_xml): PRIVATE_CTS_RUNTIME_HINT := $(cts_runtime_hint)
+endif
 $(cts_package_xml): PRIVATE_TEST_PACKAGE := $(PRIVATE_CTS_TEST_PACKAGE_NAME_)
 $(cts_package_xml): PRIVATE_MANIFEST := $(LOCAL_PATH)/AndroidManifest.xml
 $(cts_package_xml): PRIVATE_TEST_TYPE := $(if $(LOCAL_CTS_TEST_RUNNER),$(LOCAL_CTS_TEST_RUNNER),'')
@@ -56,9 +61,13 @@
 						-i "$(PRIVATE_INSTRUMENTATION)" \
 						-n $(PRIVATE_PACKAGE) \
 						-p $(PRIVATE_TEST_PACKAGE) \
+						-x "runtimeHint->$(PRIVATE_CTS_RUNTIME_HINT)" \
 						-e $(CTS_EXPECTATIONS) \
 						-b $(CTS_UNSUPPORTED_ABIS) \
 						-a $(CTS_TARGET_ARCH) \
 						-o $@
 # Have the module name depend on the cts files; so the cts files get generated when you run mm/mmm/mma/mmma.
 $(my_register_name) : $(cts_package_xml) $(cts_module_test_config)
+
+# Make sure we clear cts_runtime_hint, so other parents will use the default if they do not set cts_runtime_hint.
+cts_runtime_hint :=
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/GenericDeviceInfo.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/GenericDeviceInfo.java
index f6e7c57..decf6dd 100644
--- a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/GenericDeviceInfo.java
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/GenericDeviceInfo.java
@@ -68,6 +68,8 @@
     public static final String BUILD_SERIAL = "build_serial";
     public static final String BUILD_VERSION_RELEASE = "build_version_release";
     public static final String BUILD_VERSION_SDK = "build_version_sdk";
+    public static final String BUILD_VERSION_BASE_OS = "build_version_base_os";
+    public static final String BUILD_VERSION_SECURITY_PATH = "build_version_security_patch";
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
@@ -93,5 +95,7 @@
         addResult(BUILD_SERIAL, Build.SERIAL);
         addResult(BUILD_VERSION_RELEASE, Build.VERSION.RELEASE);
         addResult(BUILD_VERSION_SDK, Build.VERSION.SDK);
+        addResult(BUILD_VERSION_BASE_OS, Build.VERSION.BASE_OS);
+        addResult(BUILD_VERSION_SECURITY_PATH, Build.VERSION.SECURITY_PATCH);
     }
-}
\ No newline at end of file
+}
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/CaCertManagementTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/CaCertManagementTest.java
index 9127dab..51c575c 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/CaCertManagementTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/CaCertManagementTest.java
@@ -15,69 +15,143 @@
  */
 package com.android.cts.deviceowner;
 
-import static com.android.cts.deviceowner.FakeKeys.FAKE_RSA_1;
-import static com.android.cts.deviceowner.FakeKeys.FAKE_DSA_1;
-
 import java.io.ByteArrayInputStream;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.security.cert.Certificate;
 import java.security.cert.CertificateException;
 import java.security.cert.CertificateFactory;
-import java.security.cert.Certificate;
+import java.util.Arrays;
 import java.util.List;
 
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509TrustManager;
+
+import static com.android.cts.deviceowner.FakeKeys.FAKE_DSA_1;
+import static com.android.cts.deviceowner.FakeKeys.FAKE_RSA_1;
+
 public class CaCertManagementTest extends BaseDeviceOwnerTest {
+    /**
+     * Test: device admins should be able to list all installed certs.
+     *
+     * <p>The list of certificates must never be {@code null}.
+     */
     public void testCanRetrieveListOfInstalledCaCerts() {
         List<byte[]> caCerts = mDevicePolicyManager.getInstalledCaCerts(getWho());
         assertNotNull(caCerts);
     }
 
+    /**
+     * Test: a valid cert should be installable and also removable.
+     */
     public void testCanInstallAndUninstallACaCert()
-    throws CertificateException {
-        assertFalse(hasCaCertInstalled(FAKE_RSA_1.caCertificate));
-        assertFalse(hasCaCertInstalled(FAKE_DSA_1.caCertificate));
+            throws CertificateException, GeneralSecurityException {
+        assertUninstalled(FAKE_RSA_1.caCertificate);
+        assertUninstalled(FAKE_DSA_1.caCertificate);
+
         assertTrue(mDevicePolicyManager.installCaCert(getWho(), FAKE_RSA_1.caCertificate));
-        assertTrue(hasCaCertInstalled(FAKE_RSA_1.caCertificate));
-        assertFalse(hasCaCertInstalled(FAKE_DSA_1.caCertificate));
+        assertInstalled(FAKE_RSA_1.caCertificate);
+        assertUninstalled(FAKE_DSA_1.caCertificate);
+
         mDevicePolicyManager.uninstallCaCert(getWho(), FAKE_RSA_1.caCertificate);
-        assertFalse(hasCaCertInstalled(FAKE_RSA_1.caCertificate));
-        assertFalse(hasCaCertInstalled(FAKE_DSA_1.caCertificate));
+        assertUninstalled(FAKE_RSA_1.caCertificate);
+        assertUninstalled(FAKE_DSA_1.caCertificate);
     }
 
-    public void testUninstallationIsSelective() throws CertificateException {
+    /**
+     * Test: removing one certificate must not remove any others.
+     */
+    public void testUninstallationIsSelective()
+            throws CertificateException, GeneralSecurityException {
         assertTrue(mDevicePolicyManager.installCaCert(getWho(), FAKE_RSA_1.caCertificate));
         assertTrue(mDevicePolicyManager.installCaCert(getWho(), FAKE_DSA_1.caCertificate));
+
         mDevicePolicyManager.uninstallCaCert(getWho(), FAKE_DSA_1.caCertificate);
-        assertTrue(hasCaCertInstalled(FAKE_RSA_1.caCertificate));
-        assertFalse(hasCaCertInstalled(FAKE_DSA_1.caCertificate));
+        assertInstalled(FAKE_RSA_1.caCertificate);
+        assertUninstalled(FAKE_DSA_1.caCertificate);
+
         mDevicePolicyManager.uninstallCaCert(getWho(), FAKE_RSA_1.caCertificate);
     }
 
-    public void testCanUninstallAllUserCaCerts() throws CertificateException {
+    /**
+     * Test: uninstallAllUserCaCerts should be equivalent to calling uninstallCaCert on every
+     * supplementary installed certificate.
+     */
+    public void testCanUninstallAllUserCaCerts()
+            throws CertificateException, GeneralSecurityException {
         assertTrue(mDevicePolicyManager.installCaCert(getWho(), FAKE_RSA_1.caCertificate));
         assertTrue(mDevicePolicyManager.installCaCert(getWho(), FAKE_DSA_1.caCertificate));
+
         mDevicePolicyManager.uninstallAllUserCaCerts(getWho());
-        assertFalse(hasCaCertInstalled(FAKE_RSA_1.caCertificate));
-        assertFalse(hasCaCertInstalled(FAKE_DSA_1.caCertificate));
+        assertUninstalled(FAKE_RSA_1.caCertificate);
+        assertUninstalled(FAKE_DSA_1.caCertificate);
     }
 
-    private boolean hasCaCertInstalled(byte [] caCert) throws CertificateException {
-        boolean result = mDevicePolicyManager.hasCaCertInstalled(getWho(), caCert);
-        assertEquals(result, containsCertificate(
-            mDevicePolicyManager.getInstalledCaCerts(getWho()), caCert));
-        return result;
+    private void assertInstalled(byte[] caBytes)
+            throws CertificateException, GeneralSecurityException {
+        Certificate caCert = readCertificate(caBytes);
+        assertTrue(isCaCertInstalledAndTrusted(caCert));
     }
 
-    private static boolean containsCertificate(List<byte[]> certificates, byte [] toMatch)
-            throws CertificateException {
-        Certificate certificateToMatch = readCertificate(toMatch);
-        for (byte[] certBuffer : certificates) {
-            Certificate cert = readCertificate(certBuffer);
-            if (certificateToMatch.equals(cert)) {
-                return true;
+    private void assertUninstalled(byte[] caBytes)
+            throws CertificateException, GeneralSecurityException {
+        Certificate caCert = readCertificate(caBytes);
+        assertFalse(isCaCertInstalledAndTrusted(caCert));
+    }
+
+    /**
+     * Whether a given cert, or one a lot like it, has been installed system-wide and is available
+     * to all apps.
+     *
+     * <p>A CA certificate is "installed" if it matches all of the following conditions:
+     * <ul>
+     *   <li>{@link DevicePolicyManager#hasCaCertInstalled} returns {@code true}.</li>
+     *   <li>{@link DevicePolicyManager#getInstalledCaCerts} lists a matching certificate (not
+     *       necessarily exactly the same) in its response.</li>
+     *   <li>Any new instances of {@link TrustManager} should report the certificate among their
+     *       accepted issuer list -- older instances may keep the set of issuers they were created
+     *       with until explicitly refreshed.</li>
+     *
+     * @return {@code true} if installed by all metrics, {@code false} if not installed by any
+     *         metric. In any other case an {@link AssertionError} will be thrown.
+     */
+    private boolean isCaCertInstalledAndTrusted(Certificate caCert)
+            throws GeneralSecurityException, CertificateException {
+        boolean installed = mDevicePolicyManager.hasCaCertInstalled(getWho(), caCert.getEncoded());
+
+        boolean listed = false;
+        for (byte[] certBuffer : mDevicePolicyManager.getInstalledCaCerts(getWho())) {
+            if (caCert.equals(readCertificate(certBuffer))) {
+                listed = true;
             }
         }
-        return false;
+
+        boolean trusted = false;
+        final TrustManagerFactory tmf =
+                TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+        tmf.init((KeyStore) null);
+        for (TrustManager trustManager : tmf.getTrustManagers()) {
+             if (trustManager instanceof X509TrustManager) {
+                final X509TrustManager tm = (X509TrustManager) trustManager;
+                if (Arrays.asList(tm.getAcceptedIssuers()).contains(caCert)) {
+                    trusted = true;
+                }
+            }
+        }
+
+        // All three responses should match - if an installed certificate isn't trusted or (worse)
+        // a trusted certificate isn't even installed we should 
+        assertEquals(installed, listed);
+        assertEquals(installed, trusted);
+        return installed;
     }
 
+    /**
+     * Convert an encoded certificate back into a {@link Certificate}.
+     *
+     * Instantiates a fresh CertificateFactory every time for repeatability.
+     */
     private static Certificate readCertificate(byte[] certBuffer) throws CertificateException {
         final CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
         return certFactory.generateCertificate(new ByteArrayInputStream(certBuffer));
diff --git a/libs/deviceutil/src/android/cts/util/MediaUtils.java b/libs/deviceutil/src/android/cts/util/MediaUtils.java
index b3ebbad..0a454b6 100755
--- a/libs/deviceutil/src/android/cts/util/MediaUtils.java
+++ b/libs/deviceutil/src/android/cts/util/MediaUtils.java
@@ -160,6 +160,14 @@
         return null;
     }
 
+    public static boolean canEncode(MediaFormat format) {
+        if (sMCL.findEncoderForFormat(format) == null) {
+            Log.i(TAG, "no encoder for " + format);
+            return false;
+        }
+        return true;
+    }
+
     public static boolean canDecode(MediaFormat format) {
         if (sMCL.findDecoderForFormat(format) == null) {
             Log.i(TAG, "no decoder for " + format);
@@ -407,6 +415,10 @@
         return canDecode(format);
     }
 
+    public static boolean checkEncoderForFormat(MediaFormat format) {
+        return check(canEncode(format), "no encoder for " + format);
+    }
+
     public static boolean checkDecoderForFormat(MediaFormat format) {
         return check(canDecode(format), "no decoder for " + format);
     }
diff --git a/suite/cts/deviceTests/filesystemperf/Android.mk b/suite/cts/deviceTests/filesystemperf/Android.mk
index 843d21a..7ee93de 100644
--- a/suite/cts/deviceTests/filesystemperf/Android.mk
+++ b/suite/cts/deviceTests/filesystemperf/Android.mk
@@ -26,5 +26,7 @@
 
 LOCAL_SDK_VERSION := 16
 
+cts_runtime_hint := 28
+
 include $(BUILD_CTS_PACKAGE)
 
diff --git a/suite/cts/deviceTests/tvproviderperf/src/com/android/cts/tvproviderperf/TvProviderPerfTest.java b/suite/cts/deviceTests/tvproviderperf/src/com/android/cts/tvproviderperf/TvProviderPerfTest.java
index f9daa3c..8eef86d 100644
--- a/suite/cts/deviceTests/tvproviderperf/src/com/android/cts/tvproviderperf/TvProviderPerfTest.java
+++ b/suite/cts/deviceTests/tvproviderperf/src/com/android/cts/tvproviderperf/TvProviderPerfTest.java
@@ -157,12 +157,12 @@
         // Query a channel
         try (final Cursor cursor = mContentResolver.query(Channels.CONTENT_URI,
                 projection, null, null, null)) {
-            final Uri channelUri = TvContract.buildChannelUri(cursor.getLong(0));
             applyBatchTimes = MeasureTime.measure(QUERY_RUNS, new MeasureRun() {
                 @Override
                 public void run(int i) {
                     assertTrue(cursor.moveToNext());
-                    try (Cursor c = mContentResolver.query(channelUri, null, null, null, null)) {
+                    try (Cursor c = mContentResolver.query(TvContract.buildChannelUri(
+                            cursor.getLong(0)), null, null, null, null)) {
                         while (c.moveToNext()) {
                             // Do nothing. Just iterate all the items.
                         }
@@ -321,12 +321,12 @@
         // Query a program
         try (final Cursor cursor = mContentResolver.query(Programs.CONTENT_URI,
                 projection, null, null, null)) {
-            final Uri programUri = TvContract.buildProgramUri(cursor.getLong(0));
             applyBatchTimes = MeasureTime.measure(QUERY_RUNS, new MeasureRun() {
                 @Override
                 public void run(int i) {
                     assertTrue(cursor.moveToNext());
-                    try (Cursor c = mContentResolver.query(programUri, null, null, null, null)) {
+                    try (Cursor c = mContentResolver.query(TvContract.buildProgramUri(
+                            cursor.getLong(0)), null, null, null, null)) {
                         while (c.moveToNext()) {
                             // Do nothing. Just iterate all the items.
                         }
diff --git a/suite/cts/deviceTests/videoperf/Android.mk b/suite/cts/deviceTests/videoperf/Android.mk
index a393683..b589475 100644
--- a/suite/cts/deviceTests/videoperf/Android.mk
+++ b/suite/cts/deviceTests/videoperf/Android.mk
@@ -33,5 +33,7 @@
 
 LOCAL_SDK_VERSION := current
 
+cts_runtime_hint := 50
+
 include $(BUILD_CTS_PACKAGE)
 
diff --git a/tests/expectations/knownfailures.txt b/tests/expectations/knownfailures.txt
index 5165544..274a73d 100644
--- a/tests/expectations/knownfailures.txt
+++ b/tests/expectations/knownfailures.txt
@@ -310,7 +310,8 @@
   description: "ConnectivityConstraintTest job scheduler not working.",
   names: [
      "android.jobscheduler.cts.ConnectivityConstraintTest#testConnectivityConstraintExecutes_withWifi",
-     "android.jobscheduler.cts.ConnectivityConstraintTest#testUnmeteredConstraintExecutes_withWifi"
+     "android.jobscheduler.cts.ConnectivityConstraintTest#testUnmeteredConstraintExecutes_withWifi",
+     "android.jobscheduler.cts.ConnectivityConstraintTest#testConnectivityConstraintExecutes_withMobile"
   ],
   bug: 21262226
 },
diff --git a/tests/tests/accessibilityservice/res/layout/accessibility_text_traversal_test.xml b/tests/tests/accessibilityservice/res/layout/accessibility_text_traversal_test.xml
index 229dbfe..9906227 100644
--- a/tests/tests/accessibilityservice/res/layout/accessibility_text_traversal_test.xml
+++ b/tests/tests/accessibilityservice/res/layout/accessibility_text_traversal_test.xml
@@ -42,13 +42,13 @@
 
    <EditText
        android:id="@+id/edit"
-       android:layout_width="64dip"
+       android:layout_width="80dip"
        android:layout_height="80dip"
        android:maxLines="1000"
        android:scrollbars="vertical"
        android:focusable="false"
        android:includeFontPadding="false"
-       android:textSize="8dip"
+       android:textSize="10dip"
        android:textStyle="normal"
        android:fontFamily="sans-serif"
        android:visibility="gone"
diff --git a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java
index ca20549..f5b29cf 100644
--- a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java
+++ b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java
@@ -332,6 +332,9 @@
                 .setTicker(message)
                 .setContentTitle("")
                 .setContentText("")
+                // Mark the notification as "interruptive" by specifying a vibration pattern. This
+                // ensures it's announced properly on watch-type devices.
+                .setVibrate(new long[] {})
                 .build();
 
         // create and populate the expected event
diff --git a/tests/tests/alarmclock/src/android/alarmclock/cts/AlarmClockTestBase.java b/tests/tests/alarmclock/src/android/alarmclock/cts/AlarmClockTestBase.java
index 0d434f2..f41100a 100644
--- a/tests/tests/alarmclock/src/android/alarmclock/cts/AlarmClockTestBase.java
+++ b/tests/tests/alarmclock/src/android/alarmclock/cts/AlarmClockTestBase.java
@@ -55,16 +55,22 @@
 
     @Override
     protected void tearDown() throws Exception {
-        mContext.unregisterReceiver(mActivityDoneReceiver);
+        if (mActivityDoneReceiver != null) {
+            try {
+                mContext.unregisterReceiver(mActivityDoneReceiver);
+            } catch (IllegalArgumentException e) {
+                // This exception is thrown if mActivityDoneReceiver in
+                // the above call to unregisterReceiver is never registered.
+                // If so, no harm done by ignoring this exception.
+            }
+            mActivityDoneReceiver = null;
+        }
         super.tearDown();
     }
 
     private void registerBroadcastReceiver(TestcaseType testCaseType) throws Exception {
         mTestCaseType = testCaseType;
         mLatch = new CountDownLatch(1);
-        if (mActivityDoneReceiver != null) {
-            mContext.unregisterReceiver(mActivityDoneReceiver);
-        }
         mActivityDoneReceiver = new ActivityDoneReceiver();
         mContext.registerReceiver(mActivityDoneReceiver,
                 new IntentFilter(Utils.BROADCAST_INTENT + testCaseType.toString()));
diff --git a/tests/tests/app.usage/src/android/app/usage/cts/NetworkUsageStatsTest.java b/tests/tests/app.usage/src/android/app/usage/cts/NetworkUsageStatsTest.java
index a889c02..bd96d76 100644
--- a/tests/tests/app.usage/src/android/app/usage/cts/NetworkUsageStatsTest.java
+++ b/tests/tests/app.usage/src/android/app/usage/cts/NetworkUsageStatsTest.java
@@ -51,22 +51,62 @@
     private static final String APPOPS_GET_SHELL_COMMAND = "appops get {0} {1}";
 
     private static final long MINUTE = 1000 * 60;
+    private static final int TIMEOUT_MILLIS = 15000;
 
-    private static final int[] sNetworkTypesToTest = new int[] {
-        ConnectivityManager.TYPE_WIFI,
-        ConnectivityManager.TYPE_MOBILE,
-    };
+    private interface NetworkInterfaceToTest {
+        int getNetworkType();
+        int getTransportType();
+        String getSystemFeature();
+        String getErrorMessage();
+    }
 
-    private static final String[] sSystemFeaturesToTest = new String[] {
-        PackageManager.FEATURE_WIFI,
-        PackageManager.FEATURE_TELEPHONY,
-    };
+    private static final NetworkInterfaceToTest[] sNetworkInterfacesToTest =
+            new NetworkInterfaceToTest[] {
+                    new NetworkInterfaceToTest() {
+                        @Override
+                        public int getNetworkType() {
+                            return ConnectivityManager.TYPE_WIFI;
+                        }
 
-    private static final String[] sFeatureNotConnectedCause = new String[] {
-        " Please make sure you are connected to a WiFi access point.",
-        " Please make sure you have added a SIM card with data plan to your phone, have enabled " +
-                "data over cellular and in case of dual SIM devices, have selected the right SIM " +
-                "for data connection."
+                        @Override
+                        public int getTransportType() {
+                            return NetworkCapabilities.TRANSPORT_WIFI;
+                        }
+
+                        @Override
+                        public String getSystemFeature() {
+                            return PackageManager.FEATURE_WIFI;
+                        }
+
+                        @Override
+                        public String getErrorMessage() {
+                            return " Please make sure you are connected to a WiFi access point.";
+                        }
+                    },
+                    new NetworkInterfaceToTest() {
+                        @Override
+                        public int getNetworkType() {
+                            return ConnectivityManager.TYPE_MOBILE;
+                        }
+
+                        @Override
+                        public int getTransportType() {
+                            return NetworkCapabilities.TRANSPORT_CELLULAR;
+                        }
+
+                        @Override
+                        public String getSystemFeature() {
+                            return PackageManager.FEATURE_TELEPHONY;
+                        }
+
+                        @Override
+                        public String getErrorMessage() {
+                            return " Please make sure you have added a SIM card with data plan to" +
+                                    " your phone, have enabled data over cellular and in case of" +
+                                    " dual SIM devices, have selected the right SIM " +
+                                    "for data connection.";
+                        }
+                    }
     };
 
     private NetworkStatsManager mNsm;
@@ -80,7 +120,6 @@
     private String mUsageStatsMode;
 
     private void exerciseRemoteHost(Network network) throws Exception {
-        final int timeout = 15000;
         NetworkInfo networkInfo = mCm.getNetworkInfo(network);
         if (networkInfo == null) {
             Log.w(LOG_TAG, "Network info is null");
@@ -94,7 +133,7 @@
         try {
             urlc = (HttpURLConnection) network.openConnection(new URL(
                     "http://www.265.com/"));
-            urlc.setConnectTimeout(timeout);
+            urlc.setConnectTimeout(TIMEOUT_MILLIS);
             urlc.setUseCaches(false);
             urlc.connect();
             boolean ping = urlc.getResponseCode() == 200;
@@ -188,31 +227,65 @@
         }
     }
 
-    private boolean shouldTestThisNetworkType(int networkTypeIndex, long tolerance)
-            throws Exception {
-        Network[] networks = mCm.getAllNetworks();
-        for (Network network : networks) {
-            NetworkInfo networkInfo = mCm.getNetworkInfo(network);
-            if (networkInfo != null && networkInfo.isConnected() &&
-                    networkInfo.getType() == sNetworkTypesToTest[networkTypeIndex]) {
-                NetworkCapabilities capabilities = mCm.getNetworkCapabilities(network);
-                if (capabilities != null && capabilities.hasCapability(
-                        NetworkCapabilities.NET_CAPABILITY_INTERNET)) {
-                    mStartTime = System.currentTimeMillis() - tolerance;
-                    exerciseRemoteHost(network);
-                    mEndTime = System.currentTimeMillis() + tolerance;
-                    return true;
+    private class NetworkCallback extends ConnectivityManager.NetworkCallback {
+        private long mTolerance;
+        public boolean success;
+
+        NetworkCallback(long tolerance) {
+            mTolerance = tolerance;
+            success = false;
+        }
+
+        @Override
+        public void onAvailable(Network network) {
+            try {
+                mStartTime = System.currentTimeMillis() - mTolerance;
+                exerciseRemoteHost(network);
+                mEndTime = System.currentTimeMillis() + mTolerance;
+                success = true;
+                synchronized(NetworkUsageStatsTest.this) {
+                    NetworkUsageStatsTest.this.notify();
                 }
+            } catch (Exception e) {
+                Log.w(LOG_TAG, "exercising remote host failed.", e);
+                success = false;
             }
         }
-        assertFalse (sSystemFeaturesToTest[networkTypeIndex] + " is a reported system feature, " +
-                "however no corresponding connected network interface was found. " +
-                sFeatureNotConnectedCause[networkTypeIndex],
-                mPm.hasSystemFeature(sSystemFeaturesToTest[networkTypeIndex]));
+    }
+
+    private boolean shouldTestThisNetworkType(int networkTypeIndex, final long tolerance)
+            throws Exception {
+        boolean hasFeature = mPm.hasSystemFeature(
+                sNetworkInterfacesToTest[networkTypeIndex].getSystemFeature());
+        if (!hasFeature) {
+            return false;
+        }
+        NetworkCallback callback = new NetworkCallback(tolerance);
+        mCm.requestNetwork(new NetworkRequest.Builder()
+                .addTransportType(sNetworkInterfacesToTest[networkTypeIndex].getTransportType())
+                .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+                .build(), callback);
+        synchronized(this) {
+            try {
+                wait((int)(TIMEOUT_MILLIS * 1.2));
+            } catch (InterruptedException e) {
+            }
+        }
+        if (callback.success) {
+            return true;
+        }
+
+        // This will always fail at this point as we know 'hasFeature' is true.
+        assertFalse (sNetworkInterfacesToTest[networkTypeIndex].getSystemFeature() +
+                " is a reported system feature, " +
+                "however no corresponding connected network interface was found or the attempt " +
+                "to connect has timed out (timeout = " + TIMEOUT_MILLIS + "ms)." +
+                sNetworkInterfacesToTest[networkTypeIndex].getErrorMessage(), hasFeature);
         return false;
     }
 
-    private String getSubscriberId(int networkType) {
+    private String getSubscriberId(int networkIndex) {
+        int networkType = sNetworkInterfacesToTest[networkIndex].getNetworkType();
         if (ConnectivityManager.TYPE_MOBILE == networkType) {
             TelephonyManager tm = (TelephonyManager) getInstrumentation().getContext()
                     .getSystemService(Context.TELEPHONY_SERVICE);
@@ -222,7 +295,7 @@
     }
 
     public void testDeviceSummary() throws Exception {
-        for (int i = 0; i < sNetworkTypesToTest.length; ++i) {
+        for (int i = 0; i < sNetworkInterfacesToTest.length; ++i) {
             if (!shouldTestThisNetworkType(i, MINUTE/2)) {
                 continue;
             }
@@ -230,7 +303,7 @@
             NetworkStats.Bucket bucket = null;
             try {
                 bucket = mNsm.querySummaryForDevice(
-                        sNetworkTypesToTest[i], getSubscriberId(sNetworkTypesToTest[i]),
+                        sNetworkInterfacesToTest[i].getNetworkType(), getSubscriberId(i),
                         mStartTime, mEndTime);
             } catch (RemoteException | SecurityException e) {
                 fail("testDeviceSummary fails with exception: " + e.toString());
@@ -242,7 +315,7 @@
             setAppOpsMode(AppOpsManager.OPSTR_GET_USAGE_STATS, "deny");
             try {
                 bucket = mNsm.querySummaryForDevice(
-                        sNetworkTypesToTest[i], getSubscriberId(sNetworkTypesToTest[i]),
+                        sNetworkInterfacesToTest[i].getNetworkType(), getSubscriberId(i),
                         mStartTime, mEndTime);
                 fail("negative testDeviceSummary fails: no exception thrown.");
             } catch (RemoteException e) {
@@ -254,7 +327,7 @@
     }
 
     public void testUserSummary() throws Exception {
-        for (int i = 0; i < sNetworkTypesToTest.length; ++i) {
+        for (int i = 0; i < sNetworkInterfacesToTest.length; ++i) {
             if (!shouldTestThisNetworkType(i, MINUTE/2)) {
                 continue;
             }
@@ -262,7 +335,7 @@
             NetworkStats.Bucket bucket = null;
             try {
                 bucket = mNsm.querySummaryForUser(
-                        sNetworkTypesToTest[i], getSubscriberId(sNetworkTypesToTest[i]),
+                        sNetworkInterfacesToTest[i].getNetworkType(), getSubscriberId(i),
                         mStartTime, mEndTime);
             } catch (RemoteException | SecurityException e) {
                 fail("testUserSummary fails with exception: " + e.toString());
@@ -274,7 +347,7 @@
             setAppOpsMode(AppOpsManager.OPSTR_GET_USAGE_STATS, "deny");
             try {
                 bucket = mNsm.querySummaryForUser(
-                        sNetworkTypesToTest[i], getSubscriberId(sNetworkTypesToTest[i]),
+                        sNetworkInterfacesToTest[i].getNetworkType(), getSubscriberId(i),
                         mStartTime, mEndTime);
                 fail("negative testUserSummary fails: no exception thrown.");
             } catch (RemoteException e) {
@@ -286,7 +359,7 @@
     }
 
     public void testAppSummary() throws Exception {
-        for (int i = 0; i < sNetworkTypesToTest.length; ++i) {
+        for (int i = 0; i < sNetworkInterfacesToTest.length; ++i) {
             if (!shouldTestThisNetworkType(i, MINUTE/2)) {
                 continue;
             }
@@ -294,7 +367,7 @@
             NetworkStats result = null;
             try {
                 result = mNsm.querySummary(
-                        sNetworkTypesToTest[i], getSubscriberId(sNetworkTypesToTest[i]),
+                        sNetworkInterfacesToTest[i].getNetworkType(), getSubscriberId(i),
                         mStartTime, mEndTime);
                 assertTrue(result != null);
                 NetworkStats.Bucket bucket = new NetworkStats.Bucket();
@@ -327,7 +400,7 @@
             setAppOpsMode(AppOpsManager.OPSTR_GET_USAGE_STATS, "deny");
             try {
                 result = mNsm.querySummary(
-                        sNetworkTypesToTest[i], getSubscriberId(sNetworkTypesToTest[i]),
+                        sNetworkInterfacesToTest[i].getNetworkType(), getSubscriberId(i),
                         mStartTime, mEndTime);
                 fail("negative testAppSummary fails: no exception thrown.");
             } catch (RemoteException e) {
@@ -339,7 +412,7 @@
     }
 
     public void testAppDetails() throws Exception {
-        for (int i = 0; i < sNetworkTypesToTest.length; ++i) {
+        for (int i = 0; i < sNetworkInterfacesToTest.length; ++i) {
             // Relatively large tolerance to accommodate for history bucket size.
             if (!shouldTestThisNetworkType(i, MINUTE * 120)) {
                 continue;
@@ -348,7 +421,7 @@
             NetworkStats result = null;
             try {
                 result = mNsm.queryDetails(
-                        sNetworkTypesToTest[i], getSubscriberId(sNetworkTypesToTest[i]),
+                        sNetworkInterfacesToTest[i].getNetworkType(), getSubscriberId(i),
                         mStartTime, mEndTime);
                 assertTrue(result != null);
                 NetworkStats.Bucket bucket = new NetworkStats.Bucket();
@@ -382,7 +455,7 @@
             setAppOpsMode(AppOpsManager.OPSTR_GET_USAGE_STATS, "deny");
             try {
                 result = mNsm.queryDetails(
-                        sNetworkTypesToTest[i], getSubscriberId(sNetworkTypesToTest[i]),
+                        sNetworkInterfacesToTest[i].getNetworkType(), getSubscriberId(i),
                         mStartTime, mEndTime);
                 fail("negative testAppDetails fails: no exception thrown.");
             } catch (RemoteException e) {
@@ -394,7 +467,7 @@
     }
 
     public void testUidDetails() throws Exception {
-        for (int i = 0; i < sNetworkTypesToTest.length; ++i) {
+        for (int i = 0; i < sNetworkInterfacesToTest.length; ++i) {
             // Relatively large tolerance to accommodate for history bucket size.
             if (!shouldTestThisNetworkType(i, MINUTE * 120)) {
                 continue;
@@ -403,7 +476,7 @@
             NetworkStats result = null;
             try {
                 result = mNsm.queryDetailsForUid(
-                        sNetworkTypesToTest[i], getSubscriberId(sNetworkTypesToTest[i]),
+                        sNetworkInterfacesToTest[i].getNetworkType(), getSubscriberId(i),
                         mStartTime, mEndTime, Process.myUid());
                 assertTrue(result != null);
                 NetworkStats.Bucket bucket = new NetworkStats.Bucket();
@@ -436,7 +509,7 @@
             setAppOpsMode(AppOpsManager.OPSTR_GET_USAGE_STATS, "deny");
             try {
                 result = mNsm.queryDetailsForUid(
-                        sNetworkTypesToTest[i], getSubscriberId(sNetworkTypesToTest[i]),
+                        sNetworkInterfacesToTest[i].getNetworkType(), getSubscriberId(i),
                         mStartTime, mEndTime, Process.myUid());
                 fail("negative testUidDetails fails: no exception thrown.");
             } catch (RemoteException e) {
diff --git a/tests/tests/content/src/android/content/cts/ContextWrapperTest.java b/tests/tests/content/src/android/content/cts/ContextWrapperTest.java
index 672d3ed..9d9e166 100644
--- a/tests/tests/content/src/android/content/cts/ContextWrapperTest.java
+++ b/tests/tests/content/src/android/content/cts/ContextWrapperTest.java
@@ -82,7 +82,7 @@
     public static final String PERMISSION_GRANTED = "android.content.cts.permission.TEST_GRANTED";
     public static final String PERMISSION_DENIED = "android.content.cts.permission.TEST_DENIED";
 
-    private static final int BROADCAST_TIMEOUT = 10000;
+    private static final int BROADCAST_TIMEOUT = 15000;
 
     private Context mContext;
 
@@ -216,13 +216,13 @@
 
         // Test unwanted intent(action = MOCK_ACTION2)
         broadcastReceiver.reset();
-        waitForFilteredIntent(mContextWrapper, broadcastReceiver, MOCK_ACTION2);
+        waitForFilteredIntent(mContextWrapper, MOCK_ACTION2);
         assertFalse(broadcastReceiver.hadReceivedBroadCast1());
         assertFalse(broadcastReceiver.hadReceivedBroadCast2());
 
         // Send wanted intent(action = MOCK_ACTION1)
         broadcastReceiver.reset();
-        waitForFilteredIntent(mContextWrapper, broadcastReceiver, MOCK_ACTION1);
+        waitForFilteredIntent(mContextWrapper, MOCK_ACTION1);
         assertTrue(broadcastReceiver.hadReceivedBroadCast1());
         assertFalse(broadcastReceiver.hadReceivedBroadCast2());
 
@@ -235,13 +235,13 @@
 
         // Test unwanted intent(action = MOCK_ACTION2)
         broadcastReceiver2.reset();
-        waitForFilteredIntent(mContextWrapper, broadcastReceiver2, MOCK_ACTION2);
+        waitForFilteredIntent(mContextWrapper, MOCK_ACTION2);
         assertFalse(broadcastReceiver2.hadReceivedBroadCast1());
         assertFalse(broadcastReceiver2.hadReceivedBroadCast2());
 
         // Send wanted intent(action = MOCK_ACTION1), but the receiver is unregistered.
         broadcastReceiver2.reset();
-        waitForFilteredIntent(mContextWrapper, broadcastReceiver2, MOCK_ACTION1);
+        waitForFilteredIntent(mContextWrapper, MOCK_ACTION1);
         assertFalse(broadcastReceiver2.hadReceivedBroadCast1());
         assertFalse(broadcastReceiver2.hadReceivedBroadCast2());
     }
@@ -256,13 +256,13 @@
 
         // Test unwanted intent(action = MOCK_ACTION2)
         broadcastReceiver.reset();
-        waitForFilteredIntent(mContextWrapper, broadcastReceiver, MOCK_ACTION2);
+        waitForFilteredIntent(mContextWrapper, MOCK_ACTION2);
         assertFalse(broadcastReceiver.hadReceivedBroadCast1());
         assertFalse(broadcastReceiver.hadReceivedBroadCast2());
 
         // Send wanted intent(action = MOCK_ACTION1)
         broadcastReceiver.reset();
-        waitForFilteredIntent(mContextWrapper, broadcastReceiver, MOCK_ACTION1);
+        waitForFilteredIntent(mContextWrapper, MOCK_ACTION1);
         assertTrue(broadcastReceiver.hadReceivedBroadCast1());
         assertFalse(broadcastReceiver.hadReceivedBroadCast2());
 
@@ -792,8 +792,8 @@
         waitForCondition(con);
     }
 
-    private void waitForFilteredIntent(ContextWrapper contextWrapper,
-            final FilteredReceiver receiver, final String action) throws InterruptedException {
+    private void waitForFilteredIntent(ContextWrapper contextWrapper, final String action)
+            throws InterruptedException {
         contextWrapper.sendOrderedBroadcast(new Intent(action), null);
 
         synchronized (mLockObj) {
diff --git a/tests/tests/graphics/src/android/graphics/cts/Bitmap_ConfigTest.java b/tests/tests/graphics/src/android/graphics/cts/Bitmap_ConfigTest.java
index 7fc5917..e097b5a 100644
--- a/tests/tests/graphics/src/android/graphics/cts/Bitmap_ConfigTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/Bitmap_ConfigTest.java
@@ -31,7 +31,7 @@
     public void testValues(){
         Config[] config = Config.values();
 
-        assertEquals(4, config.length);
+        assertTrue(config.length >= 4);
         assertEquals(Config.ALPHA_8, config[0]);
         assertEquals(Config.RGB_565, config[1]);
         assertEquals(Config.ARGB_4444, config[2]);
diff --git a/tests/tests/hardware/Android.mk b/tests/tests/hardware/Android.mk
index 9c26d8a..07d5de9 100644
--- a/tests/tests/hardware/Android.mk
+++ b/tests/tests/hardware/Android.mk
@@ -57,4 +57,6 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
+cts_runtime_hint := 120
+
 include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraManagerTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraManagerTest.java
index 77a0c8e..67c08fe 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraManagerTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraManagerTest.java
@@ -149,7 +149,8 @@
             assertNotNull("Can't get lens facing info", lensFacing);
             if (lensFacing == CameraCharacteristics.LENS_FACING_FRONT) {
                 assertTrue("System doesn't have front camera feature",
-                        mPackageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT));
+                        mPackageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT) ||
+                        mPackageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_EXTERNAL));
             } else if (lensFacing == CameraCharacteristics.LENS_FACING_BACK) {
                 assertTrue("System doesn't have back camera feature",
                         mPackageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA));
@@ -534,7 +535,7 @@
                     java.util.concurrent.TimeUnit.MILLISECONDS);
             assertTrue(String.format("Received unavailability notice for wrong ID " +
                             "(expected %s, got %s)", id, candidateId),
-                    id == candidateId);
+                    id.equals(candidateId));
             assertTrue("Availability events received unexpectedly",
                     availableEventQueue.size() == 0);
 
@@ -549,7 +550,7 @@
                     java.util.concurrent.TimeUnit.MILLISECONDS);
             assertTrue(String.format("Received availability notice for wrong ID " +
                             "(expected %s, got %s)", id, candidateId),
-                    id == candidateId);
+                    id.equals(candidateId));
             assertTrue("Unavailability events received unexpectedly",
                     unavailableEventQueue.size() == 0);
 
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureRequestTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureRequestTest.java
index e0a1d4e..dd4e3e3 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureRequestTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureRequestTest.java
@@ -1712,9 +1712,10 @@
         // video stabilization test.
         List<Key<?>> keys = mStaticInfo.getCharacteristics().getKeys();
 
-        int[] videoStabModes = (keys.contains(CameraCharacteristics.
+        Integer[] videoStabModes = (keys.contains(CameraCharacteristics.
                 CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES)) ?
-                mStaticInfo.getAvailableVideoStabilizationModesChecked() : new int[0];
+                CameraTestUtils.toObject(mStaticInfo.getAvailableVideoStabilizationModesChecked()) :
+                    new Integer[0];
         int[] opticalStabModes = (keys.contains(
                 CameraCharacteristics.LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION)) ?
                 mStaticInfo.getAvailableOpticalStabilizationChecked() : new int[0];
@@ -1725,13 +1726,14 @@
         SimpleCaptureCallback listener = new SimpleCaptureCallback();
         startPreview(requestBuilder, maxPreviewSize, listener);
 
-        for (int mode : videoStabModes) {
+        for (Integer mode : videoStabModes) {
             listener = new SimpleCaptureCallback();
             requestBuilder.set(CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE, mode);
             mSession.setRepeatingRequest(requestBuilder.build(), listener, mHandler);
             waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
-            verifyCaptureResultForKey(CaptureResult.CONTROL_VIDEO_STABILIZATION_MODE, mode,
-                    listener, NUM_FRAMES_VERIFIED);
+            // Video stabilization could return any modes.
+            verifyAnyCaptureResultForKey(CaptureResult.CONTROL_VIDEO_STABILIZATION_MODE,
+                    videoStabModes, listener, NUM_FRAMES_VERIFIED);
         }
 
         for (int mode : opticalStabModes) {
@@ -2162,6 +2164,30 @@
     }
 
     /**
+     * Basic verification that the value of a capture result key should be one of the expected
+     * values.
+     *
+     * @param key The capture result key to be verified against
+     * @param expectedModes The list of any possible expected modes for this result
+     * @param listener The capture listener to get capture results
+     * @param numFramesVerified The number of capture results to be verified
+     */
+    private <T> void verifyAnyCaptureResultForKey(CaptureResult.Key<T> key, T[] expectedModes,
+            SimpleCaptureCallback listener, int numFramesVerified) {
+        for (int i = 0; i < numFramesVerified; i++) {
+            CaptureResult result = listener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
+            validatePipelineDepth(result);
+            T resultMode = getValueNotNull(result, key);
+            if (VERBOSE) {
+                Log.v(TAG, "Expect values: " + Arrays.toString(expectedModes) + " result value: "
+                        + resultMode.toString());
+            }
+            // Capture result should be one of the expected values.
+            mCollector.expectContains(expectedModes, resultMode);
+        }
+    }
+
+    /**
      * Verify if the fps is slow down for given input request with certain
      * controls inside.
      * <p>
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
index 6d62067..28693c6 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
@@ -178,9 +178,10 @@
 
             if (activeArraySize.getWidth() >= FULLHD.getWidth() &&
                     activeArraySize.getHeight() >= FULLHD.getHeight()) {
-                assertArrayContains(String.format(
+                assertArrayContainsAnyOf(String.format(
                         "Required FULLHD size not found for format %x for: ID %s",
-                        ImageFormat.JPEG, mIds[counter]), jpegSizes, FULLHD);
+                        ImageFormat.JPEG, mIds[counter]), jpegSizes,
+                        new Size[] {FULLHD, FULLHD_ALT});
             }
 
             if (activeArraySize.getWidth() >= HD.getWidth() &&
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/ImageReaderTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/ImageReaderTest.java
index 155f9dd..f1115c4 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/ImageReaderTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/ImageReaderTest.java
@@ -794,7 +794,7 @@
                                     getValueNotNull(result, CaptureResult.SENSOR_EXPOSURE_TIME),
                                     TEST_EXPOSURE_TIME_NS),
                             exposureTimeDiff < EXPOSURE_TIME_ERROR_MARGIN_NS &&
-                            exposureTimeDiff > 0);
+                            exposureTimeDiff >= 0);
 
                     mCollector.expectTrue(
                             String.format("Long processing frame %d format %d size %s " +
diff --git a/tests/tests/keystore/Android.mk b/tests/tests/keystore/Android.mk
index eaf5389..e51bc04 100644
--- a/tests/tests/keystore/Android.mk
+++ b/tests/tests/keystore/Android.mk
@@ -26,6 +26,8 @@
 
 LOCAL_SDK_VERSION := current
 
+cts_runtime_hint := 28
+
 include $(BUILD_CTS_PACKAGE)
 
 include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/media/Android.mk b/tests/tests/media/Android.mk
index 13daca6..ea7256d 100644
--- a/tests/tests/media/Android.mk
+++ b/tests/tests/media/Android.mk
@@ -51,6 +51,8 @@
 #LOCAL_SDK_VERSION := current
 LOCAL_JAVA_LIBRARIES += android.test.runner org.apache.http.legacy
 
+cts_runtime_hint := 265
+
 include $(BUILD_CTS_PACKAGE)
 
 include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/media/res/raw/id3v2_3_extended_header_overflow_padding.mp3 b/tests/tests/media/res/raw/id3v2_3_extended_header_overflow_padding.mp3
new file mode 100644
index 0000000..7e8d38c
--- /dev/null
+++ b/tests/tests/media/res/raw/id3v2_3_extended_header_overflow_padding.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/video_176x144_mp4_mpeg4_300kbps_25fps_aac_stereo_128kbps_44100hz.mp4 b/tests/tests/media/res/raw/video_176x144_mp4_mpeg4_300kbps_25fps_aac_stereo_128kbps_44100hz.mp4
new file mode 100644
index 0000000..6b6040f
--- /dev/null
+++ b/tests/tests/media/res/raw/video_176x144_mp4_mpeg4_300kbps_25fps_aac_stereo_128kbps_44100hz.mp4
Binary files differ
diff --git a/tests/tests/media/res/raw/video_1920x1080_mp4_h264_20480kbps_60fps_aac_stereo_128kbps_44100hz.mp4 b/tests/tests/media/res/raw/video_1920x1080_mp4_h264_20480kbps_60fps_aac_stereo_128kbps_44100hz.mp4
old mode 100644
new mode 100755
index b837dc2..f88fe7a
--- a/tests/tests/media/res/raw/video_1920x1080_mp4_h264_20480kbps_60fps_aac_stereo_128kbps_44100hz.mp4
+++ b/tests/tests/media/res/raw/video_1920x1080_mp4_h264_20480kbps_60fps_aac_stereo_128kbps_44100hz.mp4
Binary files differ
diff --git a/tests/tests/media/src/android/media/cts/AudioRecordTest.java b/tests/tests/media/src/android/media/cts/AudioRecordTest.java
index b1ee3f5..1865bb2 100644
--- a/tests/tests/media/src/android/media/cts/AudioRecordTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioRecordTest.java
@@ -696,10 +696,12 @@
         long firstSampleTime = 0;
 
         // blank final variables: all successful paths will initialize the times.
+        // this must be declared here for visibility as they are set within the try block.
         final long endTime;
         final long startTime;
         final long stopRequestTime;
         final long stopTime;
+        final long coldInputStartTime;
 
         try {
             if (markerPeriodsPerSecond != 0) {
@@ -839,11 +841,21 @@
 
             // We've read all the frames, now check the record timing.
             endTime = System.currentTimeMillis();
-            //Log.d(TAG, "first sample time " + (firstSampleTime - startTime)
+
+            coldInputStartTime = firstSampleTime - startTime;
+            //Log.d(TAG, "first sample time " + coldInputStartTime
             //        + " test time " + (endTime - firstSampleTime));
-            // Verify recording starts within 200 ms of record.startRecording() (typical 100ms)
+
+            if (coldInputStartTime > 200) {
+                Log.w(TAG, "cold input start time way too long "
+                        + coldInputStartTime + " > 200ms");
+            } else if (coldInputStartTime > 100) {
+                Log.w(TAG, "cold input start time too long "
+                        + coldInputStartTime + " > 100ms");
+            }
+            assertTrue(coldInputStartTime < 5000); // must start within 5 seconds.
+
             // Verify recording completes within 50 ms of expected test time (typical 20ms)
-            assertEquals(0, firstSampleTime - startTime, 200);
             assertEquals(TEST_TIME_MS, endTime - firstSampleTime, auditRecording ? 1000 : 50);
 
             // Even though we've read all the frames we want, the events may not be sent to
@@ -945,7 +957,7 @@
 
         // report this
         ReportLog log = getReportLog();
-        log.printValue(reportName + ": startRecording lag", firstSampleTime - startTime,
+        log.printValue(reportName + ": startRecording lag", coldInputStartTime,
                 ResultType.LOWER_BETTER, ResultUnit.MS);
         log.printValue(reportName + ": stop execution time", stopTime - stopRequestTime,
                 ResultType.LOWER_BETTER, ResultUnit.MS);
diff --git a/tests/tests/media/src/android/media/cts/EncodeDecodeTest.java b/tests/tests/media/src/android/media/cts/EncodeDecodeTest.java
index 40934f5..7c4d1fb 100644
--- a/tests/tests/media/src/android/media/cts/EncodeDecodeTest.java
+++ b/tests/tests/media/src/android/media/cts/EncodeDecodeTest.java
@@ -16,6 +16,7 @@
 
 package android.media.cts;
 
+import android.cts.util.MediaUtils;
 import android.graphics.ImageFormat;
 import android.media.Image;
 import android.media.MediaCodec;
@@ -284,6 +285,10 @@
 
         @Override
         public void run() {
+            if (mTest.shouldSkip()) {
+                return;
+            }
+
             InputSurface inputSurface = null;
             try {
                 if (!mUsePersistentInput) {
@@ -339,6 +344,22 @@
         mAllowBT709 = allowBT709;
     }
 
+    private boolean shouldSkip() {
+        if (!MediaUtils.hasEncoder(mMimeType)) {
+            return true;
+        }
+
+        MediaFormat format = MediaFormat.createVideoFormat(mMimeType, mWidth, mHeight);
+        format.setInteger(MediaFormat.KEY_BIT_RATE, mBitRate);
+        format.setInteger(MediaFormat.KEY_FRAME_RATE, FRAME_RATE);
+        format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, IFRAME_INTERVAL);
+        if (!MediaUtils.checkEncoderForFormat(format)) {
+            return true;
+        }
+
+        return false;
+    }
+
     /**
      * Tests encoding and subsequently decoding video from frames generated into a buffer.
      * <p>
@@ -348,6 +369,10 @@
      * See http://b.android.com/37769 for a discussion of input format pitfalls.
      */
     private void encodeDecodeVideoFromBuffer(boolean toSurface) throws Exception {
+        if (shouldSkip()) {
+            return;
+        }
+
         MediaCodec encoder = null;
         MediaCodec decoder = null;
 
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecTest.java b/tests/tests/media/src/android/media/cts/MediaCodecTest.java
index bb05ea0..d3ab54f 100644
--- a/tests/tests/media/src/android/media/cts/MediaCodecTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaCodecTest.java
@@ -467,22 +467,32 @@
     }
 
     public void testReleaseAfterFlush() throws IOException, InterruptedException {
+        String mimes[] = new String[] { MIME_TYPE, MIME_TYPE_AUDIO};
+        for (String mime : mimes) {
+            if (!MediaUtils.checkEncoder(mime)) {
+                continue;
+            }
+            testReleaseAfterFlush(mime);
+        }
+    }
+
+    private void testReleaseAfterFlush(String mime) throws IOException, InterruptedException {
         CountDownLatch buffersExhausted = null;
         CountDownLatch codecFlushed = null;
         AtomicInteger numBuffers = null;
 
         // sync flush from same thread
-        MediaCodec encoder = MediaCodec.createEncoderByType(MIME_TYPE);
-        runReleaseAfterFlush(encoder, buffersExhausted, codecFlushed, numBuffers);
+        MediaCodec encoder = MediaCodec.createEncoderByType(mime);
+        runReleaseAfterFlush(mime, encoder, buffersExhausted, codecFlushed, numBuffers);
 
         // sync flush from different thread
-        encoder = MediaCodec.createEncoderByType(MIME_TYPE);
+        encoder = MediaCodec.createEncoderByType(mime);
         buffersExhausted = new CountDownLatch(1);
         codecFlushed = new CountDownLatch(1);
         numBuffers = new AtomicInteger();
         Thread flushThread = new FlushThread(encoder, buffersExhausted, codecFlushed);
         flushThread.start();
-        runReleaseAfterFlush(encoder, buffersExhausted, codecFlushed, numBuffers);
+        runReleaseAfterFlush(mime, encoder, buffersExhausted, codecFlushed, numBuffers);
         flushThread.join();
 
         // async
@@ -495,19 +505,19 @@
         Handler handler = new Handler(callbackThread.getLooper());
 
         // async flush from same thread
-        encoder = MediaCodec.createEncoderByType(MIME_TYPE);
+        encoder = MediaCodec.createEncoderByType(mime);
         buffersExhausted = null;
         codecFlushed = null;
         ReleaseAfterFlushCallback callback =
-                new ReleaseAfterFlushCallback(encoder, buffersExhausted, codecFlushed, nBuffs);
+                new ReleaseAfterFlushCallback(mime, encoder, buffersExhausted, codecFlushed, nBuffs);
         encoder.setCallback(callback, handler); // setCallback before configure, which is called in run
         callback.run(); // drive input on main thread
 
         // async flush from different thread
-        encoder = MediaCodec.createEncoderByType(MIME_TYPE);
+        encoder = MediaCodec.createEncoderByType(mime);
         buffersExhausted = new CountDownLatch(1);
         codecFlushed = new CountDownLatch(1);
-        callback = new ReleaseAfterFlushCallback(encoder, buffersExhausted, codecFlushed, nBuffs);
+        callback = new ReleaseAfterFlushCallback(mime, encoder, buffersExhausted, codecFlushed, nBuffs);
         encoder.setCallback(callback, handler);
         flushThread = new FlushThread(encoder, buffersExhausted, codecFlushed);
         flushThread.start();
@@ -544,17 +554,21 @@
     }
 
     private static class ReleaseAfterFlushCallback extends MediaCodec.Callback implements Runnable {
+        final String mMime;
         final MediaCodec mEncoder;
         final CountDownLatch mBuffersExhausted, mCodecFlushed;
         final int mNumBuffersBeforeFlush;
 
         CountDownLatch mStopInput = new CountDownLatch(1);
+        List<Integer> mInputBufferIndices = new ArrayList<>();
         List<Integer> mOutputBufferIndices = new ArrayList<>();
 
-        ReleaseAfterFlushCallback(MediaCodec encoder,
+        ReleaseAfterFlushCallback(String mime,
+                MediaCodec encoder,
                 CountDownLatch buffersExhausted,
                 CountDownLatch codecFlushed,
                 int numBuffersBeforeFlush) {
+            mMime = mime;
             mEncoder = encoder;
             mBuffersExhausted = buffersExhausted;
             mCodecFlushed = codecFlushed;
@@ -563,7 +577,10 @@
 
         @Override
         public void onInputBufferAvailable(MediaCodec codec, int index) {
-            fail(codec + " onInputBufferAvailable " + index);
+            assertTrue("video onInputBufferAvailable " + index, mMime.startsWith("audio/"));
+            synchronized (mInputBufferIndices) {
+                mInputBufferIndices.add(index);
+            };
         }
 
         @Override
@@ -590,11 +607,20 @@
         public void run() {
             InputSurface inputSurface = null;
             try {
-                inputSurface = initCodecAndSurface(mEncoder);
+                inputSurface = initCodecAndSurface(mMime, mEncoder);
                 do {
-                    GLES20.glClearColor(0.0f, 0.5f, 0.0f, 1.0f);
-                    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
-                    inputSurface.swapBuffers();
+                    int inputIndex = -1;
+                    if (inputSurface == null) {
+                        // asynchronous audio codec
+                        synchronized (mInputBufferIndices) {
+                            if (mInputBufferIndices.isEmpty()) {
+                                continue;
+                            } else {
+                                inputIndex = mInputBufferIndices.remove(0);
+                            }
+                        }
+                    }
+                    feedEncoder(mEncoder, inputSurface, inputIndex);
                 } while (!mStopInput.await(TIMEOUT_USEC, TimeUnit.MICROSECONDS));
             } catch (InterruptedException e) {
                 Thread.currentThread().interrupt();
@@ -606,13 +632,14 @@
     }
 
     private static void runReleaseAfterFlush(
+            String mime,
             MediaCodec encoder,
             CountDownLatch buffersExhausted,
             CountDownLatch codecFlushed,
             AtomicInteger numBuffers) {
         InputSurface inputSurface = null;
         try {
-            inputSurface = initCodecAndSurface(encoder);
+            inputSurface = initCodecAndSurface(mime, encoder);
             List<Integer> outputBufferIndices = getOutputBufferIndices(encoder, inputSurface);
             if (numBuffers != null) {
                 numBuffers.set(outputBufferIndices.size());
@@ -623,19 +650,29 @@
         }
     }
 
-    private static InputSurface initCodecAndSurface(MediaCodec encoder) {
-        InputSurface inputSurface;
-        CodecInfo info = getAvcSupportedFormatInfo();
-        MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, info.mMaxW, info.mMaxH);
-        format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
-                MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
-        format.setInteger(MediaFormat.KEY_BIT_RATE, info.mBitRate);
-        format.setInteger(MediaFormat.KEY_FRAME_RATE, info.mFps);
-        format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, IFRAME_INTERVAL);
-        OutputSurface outputSurface = new OutputSurface(1, 1);
-        encoder.configure(format, outputSurface.getSurface(), null, MediaCodec.CONFIGURE_FLAG_ENCODE);
-        inputSurface = new InputSurface(encoder.createInputSurface());
-        inputSurface.makeCurrent();
+    private static InputSurface initCodecAndSurface(String mime, MediaCodec encoder) {
+        MediaFormat format;
+        InputSurface inputSurface = null;
+        if (mime.startsWith("audio/")) {
+            format = MediaFormat.createAudioFormat(mime, AUDIO_SAMPLE_RATE, AUDIO_CHANNEL_COUNT);
+            format.setInteger(MediaFormat.KEY_AAC_PROFILE, AUDIO_AAC_PROFILE);
+            format.setInteger(MediaFormat.KEY_BIT_RATE, AUDIO_BIT_RATE);
+            encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
+        } else if (MIME_TYPE.equals(mime)) {
+            CodecInfo info = getAvcSupportedFormatInfo();
+            format = MediaFormat.createVideoFormat(mime, info.mMaxW, info.mMaxH);
+            format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
+                    MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
+            format.setInteger(MediaFormat.KEY_BIT_RATE, info.mBitRate);
+            format.setInteger(MediaFormat.KEY_FRAME_RATE, info.mFps);
+            format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, IFRAME_INTERVAL);
+            OutputSurface outputSurface = new OutputSurface(1, 1);
+            encoder.configure(format, outputSurface.getSurface(), null, MediaCodec.CONFIGURE_FLAG_ENCODE);
+            inputSurface = new InputSurface(encoder.createInputSurface());
+            inputSurface.makeCurrent();
+        } else {
+            throw new IllegalArgumentException("unsupported mime type: " + mime);
+        }
         encoder.start();
         return inputSurface;
     }
@@ -657,9 +694,7 @@
         List<Integer> indices = new ArrayList<>();
         do {
             feedMoreFrames = indices.isEmpty();
-            GLES20.glClearColor(0.0f, 0.5f, 0.0f, 1.0f);
-            GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
-            inputSurface.swapBuffers();
+            feedEncoder(encoder, inputSurface, -1);
             // dequeue buffers until not available
             int index = encoder.dequeueOutputBuffer(bufferInfo, TIMEOUT_USEC);
             while (index >= 0) {
@@ -672,6 +707,31 @@
         return indices;
     }
 
+    /**
+     * @param encoder audio/video encoder
+     * @param inputSurface null for and only for audio encoders
+     * @param inputIndex only used for audio; if -1 the function would attempt to dequeue from encoder;
+     * do not use -1 for asynchronous encoders
+     */
+    private static void feedEncoder(MediaCodec encoder, InputSurface inputSurface, int inputIndex) {
+        if (inputSurface == null) {
+            // audio
+            while (inputIndex == -1) {
+                inputIndex = encoder.dequeueInputBuffer(TIMEOUT_USEC);
+            }
+            ByteBuffer inputBuffer = encoder.getInputBuffer(inputIndex);;
+            for (int i = 0; i < inputBuffer.capacity() / 2; i++) {
+                inputBuffer.putShort((short)i);
+            }
+            encoder.queueInputBuffer(inputIndex, 0, inputBuffer.limit(), 0, 0);
+        } else {
+            // video
+            GLES20.glClearColor(0.0f, 0.5f, 0.0f, 1.0f);
+            GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
+            inputSurface.swapBuffers();
+        }
+    }
+
     private static void releaseAfterFlush(
             MediaCodec encoder,
             List<Integer> outputBufferIndices,
@@ -798,6 +858,11 @@
     }
 
     public void testDecodeAfterFlush() throws InterruptedException {
+        testDecodeAfterFlush(true /* audio */);
+        testDecodeAfterFlush(false /* audio */);
+    }
+
+    private void testDecodeAfterFlush(final boolean audio) throws InterruptedException {
         final int INPUT_RESOURCE_ID =
                 R.raw.video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_192kbps_44100hz;
 
@@ -806,23 +871,27 @@
         final int DECODING_TIMEOUT_MS = 10000;
 
         final AtomicBoolean completed = new AtomicBoolean(false);
-        Thread videoDecodingThread = new Thread(new Runnable() {
+        Thread decodingThread = new Thread(new Runnable() {
             @Override
             public void run() {
                 OutputSurface outputSurface = null;
                 MediaExtractor mediaExtractor = null;
                 MediaCodec mediaCodec = null;
                 try {
-                    outputSurface = new OutputSurface(1, 1);
-                    mediaExtractor = getMediaExtractorForMimeType(INPUT_RESOURCE_ID, "video/");
+                    String mimeTypePrefix  = audio ? "audio/" : "video/";
+                    if (!audio) {
+                        outputSurface = new OutputSurface(1, 1);
+                    }
+                    mediaExtractor = getMediaExtractorForMimeType(INPUT_RESOURCE_ID, mimeTypePrefix);
                     MediaFormat mediaFormat =
                             mediaExtractor.getTrackFormat(mediaExtractor.getSampleTrackIndex());
                     if (!MediaUtils.checkDecoderForFormat(mediaFormat)) {
+                        completed.set(true);
                         return; // skip
                     }
                     String mimeType = mediaFormat.getString(MediaFormat.KEY_MIME);
                     mediaCodec = MediaCodec.createDecoderByType(mimeType);
-                    mediaCodec.configure(mediaFormat, outputSurface.getSurface(),
+                    mediaCodec.configure(mediaFormat, outputSurface == null ? null : outputSurface.getSurface(),
                             null /* crypto */, 0 /* flags */);
                     mediaCodec.start();
 
@@ -851,10 +920,10 @@
                 }
             }
         });
-        videoDecodingThread.start();
-        videoDecodingThread.join(DECODING_TIMEOUT_MS);
+        decodingThread.start();
+        decodingThread.join(DECODING_TIMEOUT_MS);
         // In case it's timed out, need to stop the thread and have all resources released.
-        videoDecodingThread.interrupt();
+        decodingThread.interrupt();
         if (!completed.get()) {
             throw new RuntimeException("timed out decoding to end-of-stream");
         }
diff --git a/tests/tests/media/src/android/media/cts/MediaMetadataRetrieverTest.java b/tests/tests/media/src/android/media/cts/MediaMetadataRetrieverTest.java
index 54e6ef1..ddb717c 100644
--- a/tests/tests/media/src/android/media/cts/MediaMetadataRetrieverTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaMetadataRetrieverTest.java
@@ -26,8 +26,11 @@
 import android.test.AndroidTestCase;
 
 import java.io.IOException;
+import android.util.Log;
 
 public class MediaMetadataRetrieverTest extends AndroidTestCase {
+    private static final String LOG_TAG = "MediaMetadataRetrieverTest";
+
     protected Resources mResources;
     protected MediaMetadataRetriever mRetriever;
 
@@ -116,6 +119,13 @@
                 mRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_WRITER));
     }
 
+    public void testID3v2EmbeddedPicture() {
+        setDataSourceFd(R.raw.id3v2_3_extended_header_overflow_padding);
+
+        assertEquals("EmbeddedPicture was other than expected null array",
+                null, mRetriever.getEmbeddedPicture());
+    }
+
     public void testSetDataSourceNullPath() {
         try {
             mRetriever.setDataSource((String)null);
diff --git a/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java b/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
index 7497da2..ce61d76 100644
--- a/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
+++ b/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
@@ -312,6 +312,11 @@
     }
 
     public void testPlayHlsStreamWithTimedId3() throws Throwable {
+        if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_AVC)) {
+            Log.d(TAG, "Device doesn't have video codec, skipping test");
+            return;
+        }
+
         mServer = new CtsTestServer(mContext);
         try {
             // counter must be final if we want to access it inside onTimedMetaData;
diff --git a/tests/tests/media/src/android/media/cts/VideoDecoderPerfTest.java b/tests/tests/media/src/android/media/cts/VideoDecoderPerfTest.java
index f5680f6..8797b9b 100644
--- a/tests/tests/media/src/android/media/cts/VideoDecoderPerfTest.java
+++ b/tests/tests/media/src/android/media/cts/VideoDecoderPerfTest.java
@@ -61,6 +61,7 @@
     private MediaFormat mDecOutputFormat;
     private double[] mMeasuredFps;
     private String[] mResultRawData;
+    private boolean mVerifyResults;
 
     private Resources mResources;
     private DeviceReportLog mReportLog;
@@ -68,6 +69,7 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
+        mVerifyResults = true;
         mResources = mContext.getResources();
         mReportLog = new DeviceReportLog();
     }
@@ -298,6 +300,10 @@
             mResultRawData[round] = result;
         }
 
+        if (!mVerifyResults) {
+            return true;
+        }
+
         return MediaUtils.verifyResults(name, mime, w, h, fps);
     }
 
@@ -541,6 +547,20 @@
                352, 288, true /* isGoog */);
     }
 
+    public void testMPEG40176x0144Other() throws Exception {
+        mVerifyResults = false;
+        decode(VIDEO_MPEG4,
+               R.raw.video_176x144_mp4_mpeg4_300kbps_25fps_aac_stereo_128kbps_44100hz,
+               176, 144, false /* isGoog */);
+    }
+
+    public void testMPEG40176x0144Goog() throws Exception {
+        mVerifyResults = false;
+        decode(VIDEO_MPEG4,
+               R.raw.video_176x144_mp4_mpeg4_300kbps_25fps_aac_stereo_128kbps_44100hz,
+               176, 144, true /* isGoog */);
+    }
+
     public void testMPEG40480x0360Other() throws Exception {
         decode(VIDEO_MPEG4,
                R.raw.video_480x360_mp4_mpeg4_860kbps_25fps_aac_stereo_128kbps_44100hz,
diff --git a/tests/tests/mediastress/Android.mk b/tests/tests/mediastress/Android.mk
index 5bb23d0..d78ddac 100644
--- a/tests/tests/mediastress/Android.mk
+++ b/tests/tests/mediastress/Android.mk
@@ -33,6 +33,8 @@
 
 LOCAL_SDK_VERSION := current
 
+cts_runtime_hint := 170
+
 include $(BUILD_CTS_PACKAGE)
 
 include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/print/src/android/print/cts/BasePrintTest.java b/tests/tests/print/src/android/print/cts/BasePrintTest.java
index 1378bdb..8a59c14 100644
--- a/tests/tests/print/src/android/print/cts/BasePrintTest.java
+++ b/tests/tests/print/src/android/print/cts/BasePrintTest.java
@@ -139,6 +139,14 @@
     }
 
     @Override
+    protected void runTest() throws Throwable {
+        // Do nothing if the device does not support printing.
+        if (supportsPrinting()) {
+            super.runTest();
+        }
+    }
+
+    @Override
     public void setUp() throws Exception {
         super.setUp();
         if (!supportsPrinting()) {
@@ -181,25 +189,28 @@
 
     @Override
     public void tearDown() throws Exception {
-        if (supportsPrinting()) {
-            // Done with the activity.
-            getActivity().finish();
-            enableImes();
-
-            // Restore the locale if needed.
-            if (mOldLocale != null) {
-                Resources resources = getInstrumentation().getTargetContext().getResources();
-                DisplayMetrics displayMetrics = resources.getDisplayMetrics();
-                Configuration newConfiguration = new Configuration(resources.getConfiguration());
-                newConfiguration.locale = mOldLocale;
-                mOldLocale = null;
-                resources.updateConfiguration(newConfiguration, displayMetrics);
-            }
-
-            disablePrintServices();
-            // Make sure the spooler is cleaned.
-            clearPrintSpoolerData();
+        if (!supportsPrinting()) {
+            return;
         }
+
+        // Done with the activity.
+        getActivity().finish();
+        enableImes();
+
+        // Restore the locale if needed.
+        if (mOldLocale != null) {
+            Resources resources = getInstrumentation().getTargetContext().getResources();
+            DisplayMetrics displayMetrics = resources.getDisplayMetrics();
+            Configuration newConfiguration = new Configuration(resources.getConfiguration());
+            newConfiguration.locale = mOldLocale;
+            mOldLocale = null;
+            resources.updateConfiguration(newConfiguration, displayMetrics);
+        }
+
+        disablePrintServices();
+        // Make sure the spooler is cleaned.
+        clearPrintSpoolerData();
+
         super.tearDown();
     }
 
@@ -549,6 +560,7 @@
     }
 
     protected boolean supportsPrinting() {
-        return getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_PRINTING);
+        return getInstrumentation().getContext().getPackageManager()
+                .hasSystemFeature(PackageManager.FEATURE_PRINTING);
     }
 }
diff --git a/tests/tests/security/jni/Android.mk b/tests/tests/security/jni/Android.mk
index e61d787..327eefc 100644
--- a/tests/tests/security/jni/Android.mk
+++ b/tests/tests/security/jni/Android.mk
@@ -34,11 +34,12 @@
 		android_security_cts_EncryptionTest.cpp \
 		android_security_cts_MediaPlayerInfoLeakTest.cpp \
 		android_security_cts_AudioEffectBinderTest.cpp \
-		android_security_cts_AudioFlingerBinderTest.cpp
+		android_security_cts_AudioFlingerBinderTest.cpp \
+		android_security_cts_StagefrightFoundationTest.cpp
 
 LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
 
-LOCAL_SHARED_LIBRARIES := libnativehelper liblog libbinder libutils libmedia libselinux libdl libcutils libcrypto
+LOCAL_SHARED_LIBRARIES := libnativehelper liblog libbinder libutils libmedia libselinux libdl libcutils libcrypto libstagefright_foundation
 
 LOCAL_C_INCLUDES += ndk/sources/cpufeatures
 LOCAL_STATIC_LIBRARIES := cpufeatures
diff --git a/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp b/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
index 2f749b7..b09821c 100644
--- a/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
+++ b/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
@@ -29,6 +29,7 @@
 extern int register_android_security_cts_EncryptionTest(JNIEnv* env);
 extern int register_android_security_cts_MediaPlayerInfoLeakTest(JNIEnv* env);
 extern int register_android_security_cts_AudioEffectBinderTest(JNIEnv* env);
+extern int register_android_security_cts_StagefrightFoundationTest(JNIEnv* env);
 
 jint JNI_OnLoad(JavaVM *vm, void *reserved) {
     JNIEnv *env = NULL;
@@ -85,5 +86,9 @@
         return JNI_ERR;
     }
 
+    if (register_android_security_cts_StagefrightFoundationTest(env)) {
+        return JNI_ERR;
+    }
+
     return JNI_VERSION_1_4;
 }
diff --git a/tests/tests/security/jni/android_security_cts_StagefrightFoundationTest.cpp b/tests/tests/security/jni/android_security_cts_StagefrightFoundationTest.cpp
new file mode 100644
index 0000000..d16bd38
--- /dev/null
+++ b/tests/tests/security/jni/android_security_cts_StagefrightFoundationTest.cpp
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "AudioEffectBinderTest-JNI"
+
+#include <cstdio>
+#include <jni.h>
+#include <binder/Parcel.h>
+#include <media/stagefright/foundation/AMessage.h>
+
+using namespace android;
+
+/*
+ * Native methods used by
+ * cts/tests/tests/security/src/android/security/cts/StagefrightFoundationTest.java
+ */
+
+static jboolean android_security_cts_StagefrightFoundation_test_aMessageFromParcel(
+        JNIEnv* env __unused, jobject thiz __unused)
+{
+    const int kMaxNumItems = 64;
+    const int kNumItems = kMaxNumItems + 1 + 1000;
+    char name[128];
+
+    Parcel data;
+    data.writeInt32(0);  // what
+    data.writeInt32(kNumItems);  // numItems
+    for (int i = 0; i < kMaxNumItems; ++i) {
+        snprintf(name, sizeof(name), "item-%d", i);
+        data.writeCString(name);  // name
+        data.writeInt32(0);  // kTypeInt32
+        data.writeInt32(i);  // value
+    }
+    data.writeCString("evil");  // name
+    data.writeInt32(0);  // kTypeInt32
+    data.writeInt32(0);  // value
+    // NOTE: This could overwrite mNumItems!
+
+    for (int i = 0; i < 1000; ++i) {
+        snprintf(name, sizeof(name), "evil-%d", i);
+        data.writeCString(name);  // name
+        data.writeInt32(0);  // kTypeInt32
+        data.writeInt32(0);  // value
+    }
+
+    data.setDataPosition(0);
+    sp<AMessage> msg = AMessage::FromParcel(data);
+
+    for (int i = 0; i < kMaxNumItems; ++i) {
+        snprintf(name, sizeof(name), "item-%d", i);
+        int32_t value;
+        if (!msg->findInt32(name, &value)) {
+            ALOGE("cannot find value for %s", name);
+            return JNI_FALSE;
+        }
+        if (value != i) {
+            ALOGE("value is changed: expected %d actual %d", i, value);
+            return JNI_FALSE;
+        }
+    }
+    return JNI_TRUE;
+}
+
+int register_android_security_cts_StagefrightFoundationTest(JNIEnv *env)
+{
+    static JNINativeMethod methods[] = {
+        { "native_test_aMessageFromParcel", "()Z",
+                (void *) android_security_cts_StagefrightFoundation_test_aMessageFromParcel},
+    };
+
+    jclass clazz = env->FindClass("android/security/cts/StagefrightFoundationTest");
+    return env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof(methods[0]));
+}
diff --git a/tests/tests/security/res/raw/cve_2015_1538_1.mp4 b/tests/tests/security/res/raw/cve_2015_1538_1.mp4
new file mode 100644
index 0000000..9e665ea
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2015_1538_1.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2015_1538_2.mp4 b/tests/tests/security/res/raw/cve_2015_1538_2.mp4
new file mode 100644
index 0000000..e01cae6
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2015_1538_2.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2015_1538_3.mp4 b/tests/tests/security/res/raw/cve_2015_1538_3.mp4
new file mode 100644
index 0000000..9838036
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2015_1538_3.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2015_1538_4.mp4 b/tests/tests/security/res/raw/cve_2015_1538_4.mp4
new file mode 100644
index 0000000..14f88d8
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2015_1538_4.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2015_1539.mp4 b/tests/tests/security/res/raw/cve_2015_1539.mp4
new file mode 100644
index 0000000..de871b6
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2015_1539.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2015_3824.mp4 b/tests/tests/security/res/raw/cve_2015_3824.mp4
new file mode 100644
index 0000000..4ff2220
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2015_3824.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2015_3826.mp4 b/tests/tests/security/res/raw/cve_2015_3826.mp4
new file mode 100644
index 0000000..e0d2300
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2015_3826.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2015_3827.mp4 b/tests/tests/security/res/raw/cve_2015_3827.mp4
new file mode 100644
index 0000000..7b58cf9
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2015_3827.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2015_3828.mp4 b/tests/tests/security/res/raw/cve_2015_3828.mp4
new file mode 100644
index 0000000..033902d
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2015_3828.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2015_3829.mp4 b/tests/tests/security/res/raw/cve_2015_3829.mp4
new file mode 100644
index 0000000..71062bc
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2015_3829.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2015_3864.mp4 b/tests/tests/security/res/raw/cve_2015_3864.mp4
new file mode 100644
index 0000000..fc0af68
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2015_3864.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2015_6598.mp3 b/tests/tests/security/res/raw/cve_2015_6598.mp3
new file mode 100644
index 0000000..ee709e4
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2015_6598.mp3
Binary files differ
diff --git a/tests/tests/security/res/raw/midi_crash.midi b/tests/tests/security/res/raw/midi_crash.midi
new file mode 100644
index 0000000..1880229
--- /dev/null
+++ b/tests/tests/security/res/raw/midi_crash.midi
Binary files differ
diff --git a/tests/tests/security/src/android/security/cts/ListeningPortsTest.java b/tests/tests/security/src/android/security/cts/ListeningPortsTest.java
index 76c53c1..54fa406 100644
--- a/tests/tests/security/src/android/security/cts/ListeningPortsTest.java
+++ b/tests/tests/security/src/android/security/cts/ListeningPortsTest.java
@@ -18,11 +18,14 @@
 
 import android.content.pm.PackageManager;
 import android.test.AndroidTestCase;
+import android.util.Log;
 import junit.framework.AssertionFailedError;
 
 import java.io.File;
 import java.io.IOException;
 import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
 import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -37,6 +40,9 @@
  * is considered a security best practice.
  */
 public class ListeningPortsTest extends AndroidTestCase {
+    private static final String TAG = "ListeningPortsTest";
+
+    private static final int CONN_TIMEOUT_IN_MS = 5000;
 
     /** Ports that are allowed to be listening. */
     private static final List<String> EXCEPTION_PATTERNS = new ArrayList<String>(6);
@@ -202,8 +208,12 @@
             String addrPortUid = addrPort + ' ' + entry.uid;
 
             if (isPortListening(entry.state, isTcp)
-                && !(isException(addrPort) || isException(addrUid) || isException(addrPortUid))
-                && (!entry.localAddress.isLoopbackAddress() ^ loopback)) {
+                    && !(isException(addrPort) || isException(addrUid) || isException(addrPortUid))
+                    && (!entry.localAddress.isLoopbackAddress() ^ loopback)) {
+                if (isTcp && !isTcpConnectable(entry.localAddress, entry.port)) {
+                    continue;
+                }
+
                 errors += "\nFound port listening on addr="
                         + entry.localAddress.getHostAddress() + ", port="
                         + entry.port + ", UID=" + entry.uid
@@ -225,6 +235,33 @@
         return Arrays.asList(packages).toString();
     }
 
+    private boolean isTcpConnectable(InetAddress address, int port) {
+        Socket socket = new Socket();
+
+        try {
+            if (Log.isLoggable(TAG, Log.DEBUG)) {
+                Log.d(TAG, "Trying to connect " + address + ":" + port);
+            }
+            socket.connect(new InetSocketAddress(address, port), CONN_TIMEOUT_IN_MS);
+        } catch (IOException ioe) {
+            if (Log.isLoggable(TAG, Log.DEBUG)) {
+                Log.d(TAG, "Unable to connect:" + ioe);
+            }
+            return false;
+        } finally {
+            try {
+                socket.close();
+            } catch (IOException closeError) {
+                Log.e(TAG, "Unable to close socket: " + closeError);
+            }
+        }
+
+        if (Log.isLoggable(TAG, Log.DEBUG)) {
+            Log.d(TAG, address + ":" + port + " is connectable.");
+        }
+        return true;
+    }
+
     private static boolean isException(String localAddress) {
         return isPatternMatch(EXCEPTION_PATTERNS, localAddress);
     }
diff --git a/tests/tests/security/src/android/security/cts/MediaServerCrashTest.java b/tests/tests/security/src/android/security/cts/MediaServerCrashTest.java
new file mode 100644
index 0000000..4dc6783
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/MediaServerCrashTest.java
@@ -0,0 +1,86 @@
+/*
+ * 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.security.cts;
+
+import android.content.res.AssetFileDescriptor;
+import android.media.MediaPlayer;
+import android.os.ConditionVariable;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import com.android.cts.security.R;
+
+public class MediaServerCrashTest extends AndroidTestCase {
+    private static final String TAG = "MediaServerCrashTest";
+
+    public void testInvalidMidiNullPointerAccess() throws Exception {
+        testIfMediaServerDied(R.raw.midi_crash);
+    }
+
+    private void testIfMediaServerDied(int res) throws Exception {
+        final MediaPlayer mediaPlayer = new MediaPlayer();
+        final ConditionVariable onPrepareCalled = new ConditionVariable();
+        final ConditionVariable onCompletionCalled = new ConditionVariable();
+
+        onPrepareCalled.close();
+        onCompletionCalled.close();
+        mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
+            @Override
+            public boolean onError(MediaPlayer mp, int what, int extra) {
+                assertTrue(mp == mediaPlayer);
+                assertTrue("mediaserver process died", what != MediaPlayer.MEDIA_ERROR_SERVER_DIED);
+                Log.w(TAG, "onError " + what);
+                return false;
+            }
+        });
+
+        mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
+            @Override
+            public void onPrepared(MediaPlayer mp) {
+                assertTrue(mp == mediaPlayer);
+                onPrepareCalled.open();
+            }
+        });
+
+        mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
+            @Override
+            public void onCompletion(MediaPlayer mp) {
+                assertTrue(mp == mediaPlayer);
+                onCompletionCalled.open();
+            }
+        });
+
+        AssetFileDescriptor afd = getContext().getResources().openRawResourceFd(res);
+        mediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
+        afd.close();
+        try {
+            mediaPlayer.prepareAsync();
+            if (!onPrepareCalled.block(5000)) {
+                Log.w(TAG, "testIfMediaServerDied: Timed out waiting for prepare");
+                return;
+            }
+            mediaPlayer.start();
+            if (!onCompletionCalled.block(5000)) {
+                Log.w(TAG, "testIfMediaServerDied: Timed out waiting for Error/Completion");
+            }
+        } catch (Exception e) {
+            Log.w(TAG, "playback failed", e);
+        } finally {
+            mediaPlayer.release();
+        }
+    }
+}
diff --git a/tests/tests/security/src/android/security/cts/StagefrightFoundationTest.java b/tests/tests/security/src/android/security/cts/StagefrightFoundationTest.java
new file mode 100644
index 0000000..9999d88
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/StagefrightFoundationTest.java
@@ -0,0 +1,35 @@
+/*
+ * 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.security.cts;
+
+import junit.framework.TestCase;
+
+public class StagefrightFoundationTest extends TestCase {
+
+    static {
+        System.loadLibrary("ctssecurity_jni");
+    }
+
+    /**
+     * Checks that IEffect::command() cannot leak data.
+     */
+    public void test_aMessageFromParcel() throws Exception {
+        assertTrue(native_test_aMessageFromParcel());
+    }
+
+    private static native boolean native_test_aMessageFromParcel();
+}
diff --git a/tests/tests/security/src/android/security/cts/StagefrightTest.java b/tests/tests/security/src/android/security/cts/StagefrightTest.java
new file mode 100644
index 0000000..0f79860
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/StagefrightTest.java
@@ -0,0 +1,172 @@
+/*
+ * 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.
+ *
+ *
+ * This code was provided to AOSP by Zimperium Inc and was
+ * written by:
+ *
+ * Simone "evilsocket" Margaritelli
+ * Joshua "jduck" Drake
+ */
+package android.security.cts;
+
+import android.content.Context;
+import android.content.res.AssetFileDescriptor;
+import android.media.MediaPlayer;
+import android.os.Looper;
+import android.test.InstrumentationTestCase;
+import android.util.Log;
+
+import java.io.IOException;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
+
+import com.android.cts.security.R;
+
+
+/**
+ * Verify that the device is not vulnerable to any known Stagefright
+ * vulnerabilities.
+ */
+public class StagefrightTest extends InstrumentationTestCase {
+    static final String TAG = "StagefrightTest";
+
+    public StagefrightTest() {
+    }
+
+    public void testStagefright_cve_2015_1538_1() throws Exception {
+        doStagefrightTest(R.raw.cve_2015_1538_1);
+    }
+
+    public void testStagefright_cve_2015_1538_2() throws Exception {
+        doStagefrightTest(R.raw.cve_2015_1538_2);
+    }
+
+    public void testStagefright_cve_2015_1538_3() throws Exception {
+        doStagefrightTest(R.raw.cve_2015_1538_3);
+    }
+
+    public void testStagefright_cve_2015_1538_4() throws Exception {
+        doStagefrightTest(R.raw.cve_2015_1538_4);
+    }
+
+    public void testStagefright_cve_2015_1539() throws Exception {
+        doStagefrightTest(R.raw.cve_2015_1539);
+    }
+
+    public void testStagefright_cve_2015_3824() throws Exception {
+        doStagefrightTest(R.raw.cve_2015_3824);
+    }
+
+    public void testStagefright_cve_2015_3826() throws Exception {
+        doStagefrightTest(R.raw.cve_2015_3826);
+    }
+
+    public void testStagefright_cve_2015_3827() throws Exception {
+        doStagefrightTest(R.raw.cve_2015_3827);
+    }
+
+    public void testStagefright_cve_2015_3828() throws Exception {
+        doStagefrightTest(R.raw.cve_2015_3828);
+    }
+
+    public void testStagefright_cve_2015_3829() throws Exception {
+        doStagefrightTest(R.raw.cve_2015_3829);
+    }
+
+    public void testStagefright_cve_2015_3864() throws Exception {
+        doStagefrightTest(R.raw.cve_2015_3864);
+    }
+
+    public void testStagefright_cve_2015_6598() throws Exception {
+        doStagefrightTest(R.raw.cve_2015_6598);
+    }
+
+    private void doStagefrightTest(final int rid) throws Exception {
+        class MediaPlayerCrashListener
+                implements MediaPlayer.OnErrorListener,
+                    MediaPlayer.OnPreparedListener,
+                    MediaPlayer.OnCompletionListener {
+            @Override
+            public boolean onError(MediaPlayer mp, int newWhat, int extra) {
+                what = newWhat;
+                lock.lock();
+                condition.signal();
+                lock.unlock();
+
+                return true; // don't call oncompletion
+            }
+
+            @Override
+            public void onPrepared(MediaPlayer mp) {
+                mp.start();
+            }
+
+            @Override
+            public void onCompletion(MediaPlayer mp) {
+                what = 0;
+                lock.lock();
+                condition.signal();
+                lock.unlock();
+            }
+
+            public int waitForError() throws InterruptedException {
+                lock.lock();
+                condition.await();
+                lock.unlock();
+                return what;
+            }
+
+            ReentrantLock lock = new ReentrantLock();
+            Condition condition = lock.newCondition();
+            int what;
+        }
+
+        final MediaPlayerCrashListener mpcl = new MediaPlayerCrashListener();
+
+        Thread t = new Thread(new Runnable() {
+            @Override
+            public void run() {
+                Looper.prepare();
+
+                MediaPlayer mp = new MediaPlayer();
+                mp.setOnErrorListener(mpcl);
+                mp.setOnPreparedListener(mpcl);
+                mp.setOnCompletionListener(mpcl);
+                try {
+                    AssetFileDescriptor fd = getInstrumentation().getContext().getResources()
+                        .openRawResourceFd(rid);
+
+                    mp.setDataSource(fd.getFileDescriptor(),
+                                     fd.getStartOffset(),
+                                     fd.getLength());
+
+                    mp.prepareAsync();
+                } catch (Exception e) {
+                }
+
+                Looper.loop();
+                mp.release();
+            }
+        });
+
+        t.start();
+        String name = getInstrumentation().getContext().getResources().getResourceEntryName(rid);
+        String cve = name.replace("_", "-").toUpperCase();
+        assertFalse("Device *IS* vulnerable to " + cve,
+                    mpcl.waitForError() == MediaPlayer.MEDIA_ERROR_SERVER_DIED);
+        t.interrupt();
+    }
+}
diff --git a/tests/tests/telephony/src/android/telephony/cts/CellInfoTest.java b/tests/tests/telephony/src/android/telephony/cts/CellInfoTest.java
index 9a93a60..b7caabb 100644
--- a/tests/tests/telephony/src/android/telephony/cts/CellInfoTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/CellInfoTest.java
@@ -16,6 +16,7 @@
 package android.telephony.cts;
 
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.net.ConnectivityManager;
 import android.telephony.CellInfo;
 import android.telephony.CellInfoGsm;
@@ -41,6 +42,7 @@
     // Maximum and minimum possible RSSI values(in dbm).
     private static final int MAX_RRSI = -10;
     private static final int MIN_RSSI = -150;
+    private PackageManager mPm;
 
     @Override
     protected void setUp() throws Exception {
@@ -48,9 +50,16 @@
         mTelephonyManager =
                 (TelephonyManager)getContext().getSystemService(Context.TELEPHONY_SERVICE);
         mCm = (ConnectivityManager)getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
+        mPm = getContext().getPackageManager();
     }
 
     public void testCellInfo() throws Throwable {
+
+        if(! (mPm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY))) {
+            Log.d(TAG, "Skipping test that requires FEATURE_TELEPHONY");
+            return;
+        }
+
         if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
             Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
             return;
diff --git a/tests/tests/view/src/android/view/cts/MotionEventTest.java b/tests/tests/view/src/android/view/cts/MotionEventTest.java
index cdedca4..10ea33a 100644
--- a/tests/tests/view/src/android/view/cts/MotionEventTest.java
+++ b/tests/tests/view/src/android/view/cts/MotionEventTest.java
@@ -180,6 +180,40 @@
         assertEquals(mMotionEvent2.getDeviceId(), motionEvent.getDeviceId());
     }
 
+    public void testReadFromParcelWithInvalidPointerCountSize() {
+        Parcel parcel = Parcel.obtain();
+        mMotionEvent2.writeToParcel(parcel, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+
+        // Move to pointer id count.
+        parcel.setDataPosition(4);
+        parcel.writeInt(17);
+
+        parcel.setDataPosition(0);
+        try {
+            MotionEvent.CREATOR.createFromParcel(parcel);
+            fail("deserialized invalid parcel");
+        } catch (RuntimeException e) {
+            // Expected.
+        }
+    }
+
+    public void testReadFromParcelWithInvalidSampleSize() {
+        Parcel parcel = Parcel.obtain();
+        mMotionEvent2.writeToParcel(parcel, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+
+        // Move to sample count.
+        parcel.setDataPosition(2 * 4);
+        parcel.writeInt(0x000f0000);
+
+        parcel.setDataPosition(0);
+        try {
+            MotionEvent.CREATOR.createFromParcel(parcel);
+            fail("deserialized invalid parcel");
+        } catch (RuntimeException e) {
+            // Expected.
+        }
+    }
+
     public void testToString() {
         // make sure this method never throw exception.
         mMotionEvent2.toString();
diff --git a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/VoiceInteractionTest.java b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/VoiceInteractionTest.java
index 0fa89e1..6b47eb4 100644
--- a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/VoiceInteractionTest.java
+++ b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/VoiceInteractionTest.java
@@ -59,7 +59,16 @@
 
     @Override
     protected void tearDown() throws Exception {
-        mContext.unregisterReceiver(mReceiver);
+        if (mReceiver != null) {
+            try {
+                mContext.unregisterReceiver(mReceiver);
+            } catch (IllegalArgumentException e) {
+                // This exception is thrown if mReceiver in
+                // the above call to unregisterReceiver is never registered.
+                // If so, no harm done by ignoring this exception.
+            }
+            mReceiver = null;
+        }
         super.tearDown();
     }
 
diff --git a/tests/tests/voicesettings/src/android/voicesettings/cts/VoiceSettingsTestBase.java b/tests/tests/voicesettings/src/android/voicesettings/cts/VoiceSettingsTestBase.java
index 98b9c29..529c160 100644
--- a/tests/tests/voicesettings/src/android/voicesettings/cts/VoiceSettingsTestBase.java
+++ b/tests/tests/voicesettings/src/android/voicesettings/cts/VoiceSettingsTestBase.java
@@ -55,7 +55,14 @@
     @Override
     protected void tearDown() throws Exception {
         if (mActivityDoneReceiver != null) {
-            mContext.unregisterReceiver(mActivityDoneReceiver);
+            try {
+                mContext.unregisterReceiver(mActivityDoneReceiver);
+            } catch (IllegalArgumentException e) {
+                // This exception is thrown if mActivityDoneReceiver in
+                // the above call to unregisterReceiver is never registered.
+                // If so, no harm done by ignoring this exception.
+            }
+            mActivityDoneReceiver = null;
         }
         super.tearDown();
     }
@@ -83,9 +90,6 @@
     protected void registerBroadcastReceiver(Utils.TestcaseType testCaseType) throws Exception {
         mTestCaseType = testCaseType;
         mLatch = new CountDownLatch(1);
-        if (mActivityDoneReceiver != null) {
-            mContext.unregisterReceiver(mActivityDoneReceiver);
-        }
         mActivityDoneReceiver = new ActivityDoneReceiver();
         mContext.registerReceiver(mActivityDoneReceiver,
                 new IntentFilter(Utils.BROADCAST_INTENT + testCaseType.toString()));
diff --git a/tests/tests/widget/src/android/widget/cts/TextViewTest.java b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
index 3130a26..01938c2 100644
--- a/tests/tests/widget/src/android/widget/cts/TextViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
@@ -24,6 +24,7 @@
 import android.app.Instrumentation;
 import android.app.Instrumentation.ActivityMonitor;
 import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.content.res.ColorStateList;
 import android.content.res.Resources.NotFoundException;
 import android.cts.util.PollingCheck;
@@ -4416,9 +4417,18 @@
     public void testSetGetBreakStrategy() {
         TextView tv = new TextView(mActivity);
 
+        final PackageManager pm = getInstrumentation().getTargetContext().getPackageManager();
+
         // The default value is from the theme, here the default is BREAK_STRATEGY_HIGH_QUALITY for
-        // TextView.
-        assertEquals(Layout.BREAK_STRATEGY_HIGH_QUALITY, tv.getBreakStrategy());
+        // TextView except for Android Wear. The default value for Android Wear is
+        // BREAK_STRATEGY_BALANCED.
+        if (pm.hasSystemFeature(PackageManager.FEATURE_WATCH)) {
+            // Android Wear
+            assertEquals(Layout.BREAK_STRATEGY_BALANCED, tv.getBreakStrategy());
+        } else {
+            // All other form factor.
+            assertEquals(Layout.BREAK_STRATEGY_HIGH_QUALITY, tv.getBreakStrategy());
+        }
 
         tv.setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE);
         assertEquals(Layout.BREAK_STRATEGY_SIMPLE, tv.getBreakStrategy());
diff --git a/tools/cts-media/get_achievable_rates.py b/tools/cts-media/get_achievable_rates.py
new file mode 100755
index 0000000..81412da
--- /dev/null
+++ b/tools/cts-media/get_achievable_rates.py
@@ -0,0 +1,396 @@
+#!/usr/bin/python
+# 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.
+#
+
+import argparse, math, re, sys
+import xml.etree.ElementTree as ET
+from collections import defaultdict, namedtuple
+import itertools
+
+
+def createLookup(values, key):
+  """Creates a lookup table for a collection of values based on keys.
+
+  Arguments:
+    values: a collection of arbitrary values. Must be iterable.
+    key: a function of one argument that returns the key for a value.
+
+  Returns:
+    A dict mapping keys (as generated by the key argument) to lists of
+    values. All values in the lists have the same key, and are in the order
+    they appeared in the collection.
+  """
+  lookup = defaultdict(list)
+  for v in values:
+    lookup[key(v)].append(v)
+  return lookup
+
+
+def _intify(value):
+  """Returns a value converted to int if possible, else the original value."""
+  try:
+    return int(value)
+  except ValueError:
+    return value
+
+
+class Size(namedtuple('Size', ['width', 'height'])):
+  """A namedtuple with width and height fields."""
+  def __str__(self):
+    return '%dx%d' % (self.width, self.height)
+
+
+class _VideoResultBase(object):
+  """Helper methods for results. Not for use by applications.
+
+  Attributes:
+    codec: The name of the codec (string) or None
+    size: Size representing the video size or None
+    mime: The mime-type of the codec (string) or None
+    rates: The measured achievable frame rates
+    is_decoder: True iff codec is a decoder.
+  """
+
+  def __init__(self, is_decoder):
+    self.codec = None
+    self.mime = None
+    self.size = None
+    self._rates_from_failure = []
+    self._rates_from_message = []
+    self.is_decoder = is_decoder
+
+  def _inited(self):
+    """Returns true iff codec, mime and size was set."""
+    return None not in (self.codec, self.mime, self.size)
+
+  def __len__(self):
+    # don't report any result if codec name, mime type and size is unclear
+    if not self._inited():
+      return 0
+    return len(self.rates)
+
+  @property
+  def rates(self):
+    return self._rates_from_failure or self._rates_from_message
+
+  def _parseDict(self, value):
+    """Parses a MediaFormat from its string representation sans brackets."""
+    return dict((k, _intify(v))
+                for k, v in re.findall(r'([^ =]+)=([^ [=]+(?:|\[[^\]]+\]))(?:, |$)', value))
+
+  def _cleanFormat(self, format):
+    """Removes internal fields from a parsed MediaFormat."""
+    format.pop('what', None)
+    format.pop('image-data', None)
+
+  MESSAGE_PATTERN = r'(?P<key>\w+)=(?P<value>\{[^}]*\}|[^ ,{}]+)'
+
+  def _parsePartialResult(self, message_match):
+    """Parses a partial test result conforming to the message pattern.
+
+    Returns:
+      A tuple of string key and int, string or dict value, where dict has
+      string keys mapping to int or string values.
+    """
+    key, value = message_match.group('key', 'value')
+    if value.startswith('{'):
+      value = self._parseDict(value[1:-1])
+      if key.endswith('Format'):
+        self._cleanFormat(value)
+    else:
+      value = _intify(value)
+    return key, value
+
+  def _parseValuesFromBracket(self, line):
+    """Returns the values enclosed in brackets without the brackets.
+
+    Parses a line matching the pattern "<tag>: [<values>]" and returns <values>.
+
+    Raises:
+      ValueError: if the line does not match the pattern.
+    """
+    try:
+      return re.match(r'^[^:]+: *\[(?P<values>.*)\]\.$', line).group('values')
+    except AttributeError:
+      raise ValueError('line does not match "tag: [value]": %s' % line)
+
+  def _parseRawData(self, line):
+    """Parses the raw data line for video performance tests.
+
+    Yields:
+      Dict objects corresponding to parsed results, mapping string keys to
+      int, string or dict values.
+    """
+    try:
+      values = self._parseValuesFromBracket(line)
+      result = {}
+      for m in re.finditer(self.MESSAGE_PATTERN + r'(?P<sep>,? +|$)', values):
+        key, value = self._parsePartialResult(m)
+        result[key] = value
+        if m.group('sep') != ' ':
+          yield result
+          result = {}
+    except ValueError:
+      print >> sys.stderr, 'could not parse line %s' % repr(line)
+
+  def _tryParseMeasuredFrameRate(self, line):
+    """Parses a line starting with 'Measured frame rate:'."""
+    if line.startswith('Measured frame rate: '):
+      try:
+        values = self._parseValuesFromBracket(line)
+        values = re.split(r' *, *', values)
+        self._rates_from_failure = list(map(float, values))
+      except ValueError:
+        print >> sys.stderr, 'could not parse line %s' % repr(line)
+
+  def parse(self, test):
+    """Parses the ValueArray and FailedScene lines of a test result.
+
+    Arguments:
+      test: An ElementTree <Test> element.
+    """
+    failure = test.find('FailedScene')
+    if failure is not None:
+      trace = failure.find('StackTrace')
+      if trace is not None:
+        for line in re.split(r'[\r\n]+', trace.text):
+          self._parseFailureLine(line)
+    details = test.find('Details')
+    if details is not None:
+      for array in details.iter('ValueArray'):
+        message = array.get('message')
+        self._parseMessage(message, array)
+
+  def _parseFailureLine(self, line):
+    raise NotImplementedError
+
+  def _parseMessage(self, message, array):
+    raise NotImplementedError
+
+  def getData(self):
+    """Gets the parsed test result data.
+
+    Yields:
+       Result objects containing at least codec, size, mime and rates attributes."""
+    yield self
+
+
+class VideoEncoderDecoderTestResult(_VideoResultBase):
+  """Represents a result from a VideoEncoderDecoderTest performance case."""
+
+  def __init__(self, unused_m):
+    super(VideoEncoderDecoderTestResult, self).__init__(is_decoder=False)
+
+  # If a VideoEncoderDecoderTest succeeds, it provides the results in the
+  # message of a ValueArray. If fails, it provides the results in the failure
+  # using raw data. (For now it also includes some data in the ValueArrays even
+  # if it fails, which we ignore.)
+
+  def _parseFailureLine(self, line):
+    """Handles parsing a line from the failure log."""
+    self._tryParseMeasuredFrameRate(line)
+
+  def _parseMessage(self, message, array):
+    """Handles parsing a message from ValueArrays."""
+    if message.startswith('codec='):
+      result = dict(self._parsePartialResult(m)
+                  for m in re.finditer(self.MESSAGE_PATTERN + '(?: |$)', message))
+      if 'EncInputFormat' in result:
+        self.codec = result['codec']
+        fmt = result['EncInputFormat']
+        self.size = Size(fmt['width'], fmt['height'])
+        self.mime = result['EncOutputFormat']['mime']
+        self._rates_from_message.append(1000000./result['min'])
+
+
+class VideoDecoderPerfTestResult(_VideoResultBase):
+  """Represents a result from a VideoDecoderPerfTest performance case."""
+
+  # If a VideoDecoderPerfTest succeeds, it provides the results in the message
+  # of a ValueArray. If fails, it provides the results in the failure only
+  # using raw data.
+
+  def __init__(self, unused_m):
+    super(VideoDecoderPerfTestResult, self).__init__(is_decoder=True)
+
+  def _parseFailureLine(self, line):
+    """Handles parsing a line from the failure log."""
+    self._tryParseMeasuredFrameRate(line)
+    # if the test failed, we can only get the codec/size/mime from the raw data.
+    if line.startswith('Raw data: '):
+      for result in self._parseRawData(line):
+        fmt = result['DecOutputFormat']
+        self.size = Size(fmt['width'], fmt['height'])
+        self.codec = result['codec']
+        self.mime = result['mime']
+
+  def _parseMessage(self, message, array):
+    """Handles parsing a message from ValueArrays."""
+    if message.startswith('codec='):
+      result = dict(self._parsePartialResult(m)
+                  for m in re.finditer(self.MESSAGE_PATTERN + '(?: |$)', message))
+      if result.get('decodeto') == 'surface':
+        self.codec = result['codec']
+        fmt = result['DecOutputFormat']
+        self.size = Size(fmt['width'], fmt['height'])
+        self.mime = result['mime']
+        self._rates_from_message.append(1000000. / result['min'])
+
+
+class Results(object):
+  """Container that keeps all test results."""
+  def __init__(self):
+      self._results = [] # namedtuples
+      self._device = None
+
+  VIDEO_ENCODER_DECODER_TEST_REGEX = re.compile(
+      'test(.*)(\d{4})x(\d{4})(Goog|Other)$')
+
+  VIDEO_DECODER_PERF_TEST_REGEX = re.compile(
+      'test(VP[89]|H26[34]|MPEG4|HEVC)(\d+)x(\d+)(.*)$')
+
+  TestCaseSpec = namedtuple('TestCaseSpec', 'package path class_ regex result_class')
+
+  def _getTestCases(self):
+    return [
+      self.TestCaseSpec(package='CtsDeviceVideoPerf',
+                   path='TestSuite/TestSuite/TestSuite/TestSuite/TestCase',
+                   class_='VideoEncoderDecoderTest',
+                   regex=self.VIDEO_ENCODER_DECODER_TEST_REGEX,
+                   result_class=VideoEncoderDecoderTestResult),
+      self.TestCaseSpec(package='CtsMediaTestCases',
+                   path='TestSuite/TestSuite/TestSuite/TestCase',
+                   class_='VideoDecoderPerfTest',
+                   regex=self.VIDEO_DECODER_PERF_TEST_REGEX,
+                   result_class=VideoDecoderPerfTestResult)
+    ]
+
+  def _verifyDeviceInfo(self, device):
+    assert self._device in (None, device), "expected %s device" % self._device
+    self._device = device
+
+  def importXml(self, xml):
+    self._verifyDeviceInfo(xml.find('DeviceInfo/BuildInfo').get('buildName'))
+
+    packages = createLookup(self._getTestCases(), lambda tc: tc.package)
+
+    for pkg in xml.iter('TestPackage'):
+      tests_in_package = packages.get(pkg.get('name'))
+      if not tests_in_package:
+        continue
+      paths = createLookup(tests_in_package, lambda tc: tc.path)
+      for path, tests_in_path in paths.items():
+        classes = createLookup(tests_in_path, lambda tc: tc.class_)
+        for tc in pkg.iterfind(path):
+          tests_in_class = classes.get(tc.get('name'))
+          if not tests_in_class:
+            continue
+          for test in tc.iter('Test'):
+            for tc in tests_in_class:
+              m = tc.regex.match(test.get('name'))
+              if m:
+                result = tc.result_class(m)
+                result.parse(test)
+                self._results.append(result)
+
+  def importFile(self, path):
+    print >> sys.stderr, 'Importing "%s"...' % path
+    try:
+      return self.importXml(ET.parse(path))
+    except ET.ParseError:
+      raise ValueError('not a valid XML file')
+
+  def getData(self):
+    for result in self._results:
+      for data in result.getData():
+        yield data
+
+  def dumpXml(self, results):
+    yield '<?xml version="1.0" encoding="utf-8" ?>'
+    yield '<!-- Copyright 2015 The Android Open Source Project'
+    yield ''
+    yield '     Licensed under the Apache License, Version 2.0 (the "License");'
+    yield '     you may not use this file except in compliance with the License.'
+    yield '     You may obtain a copy of the License at'
+    yield ''
+    yield '          http://www.apache.org/licenses/LICENSE-2.0'
+    yield ''
+    yield '     Unless required by applicable law or agreed to in writing, software'
+    yield '     distributed under the License is distributed on an "AS IS" BASIS,'
+    yield '     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.'
+    yield '     See the License for the specific language governing permissions and'
+    yield '     limitations under the License.'
+    yield '-->'
+    yield ''
+    yield '<MediaCodecs>'
+    last_section = None
+    Comp = namedtuple('Comp', 'is_decoder google mime name')
+    by_comp = createLookup(results,
+                           lambda e: Comp(is_decoder=e.is_decoder, google='.google.' in e.codec, mime=e.mime, name=e.codec))
+    for comp in sorted(by_comp):
+      section = 'Decoders' if comp.is_decoder else 'Encoders'
+      if section != last_section:
+        if last_section:
+          yield '    </%s>' % last_section
+        yield '    <%s>' % section
+        last_section = section
+      yield '        <MediaCodec name="%s" type="%s" update="true">' % (comp.name, comp.mime)
+      by_size = createLookup(by_comp[comp], lambda e: e.size)
+      for size in sorted(by_size):
+        values = list(itertools.chain(*(e.rates for e in by_size[size])))
+        min_, max_ = min(values), max(values)
+        med_ = int(math.sqrt(min_ * max_))
+        yield '            <Limit name="measured-frame-rate-%s" range="%d-%d" />' % (size, med_, med_)
+      yield '        </MediaCodec>'
+    if last_section:
+      yield '    </%s>' % last_section
+    yield '</MediaCodecs>'
+
+
+class Main(object):
+  """Executor of this utility."""
+
+  def __init__(self):
+    self._result = Results()
+
+    self._parser = argparse.ArgumentParser('get_achievable_framerates')
+    self._parser.add_argument('result_xml', nargs='+')
+
+  def _parseArgs(self):
+    self._args = self._parser.parse_args()
+
+  def _importXml(self, xml):
+    self._result.importFile(xml)
+
+  def _report(self):
+    for line in self._result.dumpXml(r for r in self._result.getData() if r):
+      print line
+
+  def run(self):
+    self._parseArgs()
+    try:
+      for xml in self._args.result_xml:
+        try:
+          self._importXml(xml)
+        except (ValueError, IOError, AssertionError) as e:
+          print >> sys.stderr, e
+          raise KeyboardInterrupt
+      self._report()
+    except KeyboardInterrupt:
+      print >> sys.stderr, 'Interrupted.'
+
+if __name__ == '__main__':
+  Main().run()
+
diff --git a/tools/tradefed-host/.classpath b/tools/tradefed-host/.classpath
index e716219..dbeeb01 100644
--- a/tools/tradefed-host/.classpath
+++ b/tools/tradefed-host/.classpath
@@ -7,5 +7,6 @@
 	<classpathentry exported="true" kind="var" path="CTS_SRC_ROOT/out/host/common/obj/JAVA_LIBRARIES/ctsdeviceinfolib_intermediates/javalib.jar"/>
 	<classpathentry kind="var" path="CTS_SRC_ROOT/out/host/common/obj/JAVA_LIBRARIES/hosttestlib_intermediates/javalib.jar"/>
 	<classpathentry kind="var" path="CTS_SRC_ROOT/prebuilts/misc/common/tradefed/tradefed-prebuilt.jar"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/cts-commonutil"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
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 782e6ab..854fce6 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
@@ -31,7 +31,7 @@
     @Option(name="cts-install-path", description="the path to the cts installation to use")
     private String mCtsRootDirPath = System.getProperty("CTS_ROOT");
 
-    public static final String CTS_BUILD_VERSION = "6.0_r1";
+    public static final String CTS_BUILD_VERSION = "6.0_r1.5";
     public static final String CTS_PACKAGE = "com.android.cts.tradefed.testtype";
 
     /**
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/CtsTest.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/CtsTest.java
index d74cce5..244f348 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/CtsTest.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/CtsTest.java
@@ -64,6 +64,7 @@
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashSet;
@@ -251,6 +252,20 @@
         }
     }
 
+
+    /**
+     * A {@link Comparator} for sorting {@link TestPackage}s by running time hint.
+     */
+    static class RuntimeHintComparator implements Comparator<TestPackage> {
+
+        @Override
+        public int compare(TestPackage left, TestPackage right) {
+            return Long.compare(left.getPackageDef().getRuntimeHint(),
+                    right.getPackageDef().getRuntimeHint());
+        }
+
+    }
+
     /**
      * A {@link ResultForwarder} that will forward a bugreport on each failed test.
      */
@@ -811,6 +826,10 @@
             int numTestPackages = testPackageList.size();
             int totalShards = Math.min(mTotalShards, numTestPackages);
 
+            // Sort test packages by running time hint, to force packages with large expected
+            // running times to different shards if possible.
+            Collections.sort(testPackageList, new RuntimeHintComparator());
+
             List<TestPackage> shardTestPackageList = new ArrayList<>();
             for (int i = mShardAssignment; i < numTestPackages; i += totalShards) {
                 shardTestPackageList.add(testPackageList.get(i));
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/ITestPackageDef.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/ITestPackageDef.java
index 13f3572..630dee3 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/ITestPackageDef.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/ITestPackageDef.java
@@ -72,6 +72,11 @@
     public IAbi getAbi();
 
     /**
+     * @return the estimated running time of this test package.
+     */
+    public long getRuntimeHint();
+
+    /**
      * Set the filter to use for tests
      *
      * @param testFilter
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageDef.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageDef.java
index 12c3ddd..d08c0bc 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageDef.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageDef.java
@@ -66,6 +66,7 @@
     private String mRunTimeArgs = null;
     private String mTestPackageName = null;
     private String mDigest = null;
+    private long mRuntimeHint = 0;
     private IAbi mAbi = null;
     private List<ITargetPreparer> mPreparers = null;
 
@@ -137,6 +138,18 @@
      * {@inheritDoc}
      */
     @Override
+    public long getRuntimeHint() {
+        return mRuntimeHint;
+    }
+
+    void setRuntimeHint(long runtimeHint) {
+        mRuntimeHint = runtimeHint;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
     public String getName() {
         return mName;
     }
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageXmlParser.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageXmlParser.java
index 649dd9e..951c461 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageXmlParser.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageXmlParser.java
@@ -86,6 +86,10 @@
                 final String targetNameSpace = attributes.getValue("targetNameSpace");
                 final String runTimeArgs = attributes.getValue("runtimeArgs");
                 final String testType = getTestType(attributes);
+                long runTimeHint = 0;
+                if (attributes.getValue("runtimeHint") != null) {
+                    runTimeHint = Long.parseLong(attributes.getValue("runtimeHint"));
+                }
 
                 for (String abiName : AbiUtils.getAbisSupportedByCts()) {
                     Abi abi = new Abi(abiName, AbiUtils.getBitness(abiName));
@@ -102,6 +106,7 @@
                     }
                     packageDef.setTargetBinaryName(targetBinaryName);
                     packageDef.setTargetNameSpace(targetNameSpace);
+                    packageDef.setRuntimeHint(runTimeHint);
                     packageDef.setAbi(abi);
                     mPackageDefs.put(abiName, packageDef);
                 }