Merge "Connect WebView Async Cookie APIs"
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/video/CameraVideoActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/video/CameraVideoActivity.java
index b010f79..f93723c 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/video/CameraVideoActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/video/CameraVideoActivity.java
@@ -449,7 +449,8 @@
                 CamcorderProfile.QUALITY_CIF,
                 CamcorderProfile.QUALITY_480P,
                 CamcorderProfile.QUALITY_720P,
-                CamcorderProfile.QUALITY_1080P
+                CamcorderProfile.QUALITY_1080P,
+                CamcorderProfile.QUALITY_2160P
         };
 
         String[] nameArray = {
@@ -460,7 +461,8 @@
                 "CIF",
                 "480P",
                 "720P",
-                "1080P"
+                "1080P",
+                "2160P"
         };
 
         ArrayList<VideoSizeNamePair> availableSizes =
@@ -499,7 +501,8 @@
                 CamcorderProfile.QUALITY_CIF,
                 CamcorderProfile.QUALITY_480P,
                 CamcorderProfile.QUALITY_720P,
-                CamcorderProfile.QUALITY_1080P
+                CamcorderProfile.QUALITY_1080P,
+                CamcorderProfile.QUALITY_2160P
         };
 
         ArrayList<ResolutionQuality> qualityList = new ArrayList<ResolutionQuality>();
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/streamquality/StreamingVideoActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/streamquality/StreamingVideoActivity.java
index d575e5f..66168a1 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/streamquality/StreamingVideoActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/streamquality/StreamingVideoActivity.java
@@ -91,35 +91,38 @@
                + "cid=0x271de9756065677e&fmt=13&user=android-device-test"),
         new Stream("MPEG4 SP Video, AAC Audio", "rtsp_mpeg4_aac",
                 "rtsp://v2.cache7.c.youtube.com/video.3gp?"
-                + "cid=0x271de9756065677e&fmt=13&user=android-device-test"),
+                + "cid=0x271de9756065677e&fmt=17&user=android-device-test"),
         new Stream("H264 Base Video, AAC Audio", "rtsp_h264_aac",
                 "rtsp://v2.cache7.c.youtube.com/video.3gp?"
-                + "cid=0x271de9756065677e&fmt=13&user=android-device-test"),
+                + "cid=0x271de9756065677e&fmt=18&user=android-device-test"),
     };
 
     private static final Stream[] HTTP_STREAMS = {
-        new Stream("H263 Video, AMR Audio", "http_h263_amr", "http://v20.lscache8.c.youtube.com/"
+        new Stream("H263 Video, AMR Audio", "http_h263_amr", "http://redirector.c.play.google.com/"
                 + "videoplayback?id=271de9756065677e"
                 + "&itag=13&ip=0.0.0.0&ipbits=0&expire=999999999999999999"
                 + "&sparams=ip,ipbits,expire,ip,ipbits,expire,id,itag"
                 + "&signature=372FA4C532AA49D14EAF049BCDA66460EEE161E9"
                 + ".6D8BF096B73B7A68A7032CA8685053CFB498D30A"
+                + "&source=youtube"
                 + "&key=test_key1&user=android-device-test"),
         new Stream("MPEG4 SP Video, AAC Audio", "http_mpeg4_aac",
-                "http://v20.lscache8.c.youtube.com/"
+                "http://redirector.c.play.google.com/"
                 + "videoplayback?id=271de9756065677e"
                 + "&itag=17&ip=0.0.0.0&ipbits=0&expire=999999999999999999"
                 + "&sparams=ip,ipbits,expire,ip,ipbits,expire,id,itag"
                 + "&signature=3DCD3F79E045F95B6AF661765F046FB0440FF016"
                 + ".06A42661B3AF6BAF046F012549CC9BA34EBC80A9"
+                + "&source=youtube"
                 + "&key=test_key1&user=android-device-test"),
         new Stream("H264 Base Video, AAC Audio", "http_h264_aac",
-                "http://v20.lscache8.c.youtube.com/"
+                "http://redirector.c.play.google.com/"
                 + "videoplayback?id=271de9756065677e"
                 + "&itag=18&ip=0.0.0.0&ipbits=0&expire=999999999999999999"
                 + "&sparams=ip,ipbits,expire,ip,ipbits,expire,id,itag"
                 + "&signature=1219C2B07AF0638C27916307A6093C0E43CB894E"
                 + ".126B6B916BD57157782738AA7C03E59F21DBC168"
+                + "&source=youtube"
                 + "&key=test_key1&user=android-device-test"),
     };
 
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
index 522eb6e..aedce10 100644
--- a/tests/AndroidManifest.xml
+++ b/tests/AndroidManifest.xml
@@ -74,6 +74,7 @@
     <uses-permission android:name="android.permission.NFC" />
     <uses-permission android:name="android.permission.SET_WALLPAPER_HINTS" />
     <uses-permission android:name="com.android.voicemail.permission.ADD_VOICEMAIL" />
+    <uses-permission android:name="android.permission.BLUETOOTH" />
 
     <!-- Used for PackageManager test, don't delete this INTERNET permission -->
     <uses-permission android:name="android.permission.INTERNET" />
@@ -674,7 +675,8 @@
         </activity>
 
         <activity android:name="android.app.cts.InstrumentationTestActivity"
-            android:label="InstrumentationTestActivity">
+                  android:theme="@style/Theme_NoSwipeDismiss"
+                  android:label="InstrumentationTestActivity">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.DEFAULT" />
@@ -866,7 +868,8 @@
         </activity>
 
         <activity android:name="android.app.cts.DialogStubActivity"
-            android:label="DialogStubActivity">
+                  android:theme="@style/Theme_NoSwipeDismiss"
+                  android:label="DialogStubActivity">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
diff --git a/tests/core/libcore/okhttp/Android.mk b/tests/core/libcore/okhttp/Android.mk
new file mode 100644
index 0000000..4fe50ff
--- /dev/null
+++ b/tests/core/libcore/okhttp/Android.mk
@@ -0,0 +1,24 @@
+# Copyright (C) 2014 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+ifeq ($(BUILD_CTSCORE_PACKAGE),)
+    $(error BUILD_CTSCORE_PACKAGE must be defined)
+endif
+
+include $(CLEAR_VARS)
+LOCAL_PACKAGE_NAME := android.core.tests.libcore.package.okhttp
+LOCAL_STATIC_JAVA_LIBRARIES := okhttp-nojarjar junit4-target bouncycastle-nojarjar okhttp-tests-nojarjar
+include $(BUILD_CTSCORE_PACKAGE)
diff --git a/tests/core/libcore/okhttp/AndroidManifest.xml b/tests/core/libcore/okhttp/AndroidManifest.xml
new file mode 100644
index 0000000..f69bc83
--- /dev/null
+++ b/tests/core/libcore/okhttp/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2014 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.core.tests.libcore.package.okhttp">
+    <uses-permission android:name="android.permission.INTERNET" />
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="android.core.tests.runner"
+                     android:label="cts framework tests">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
+
+</manifest>
diff --git a/tests/core/runner/src/com/android/cts/runner/CtsTestRunListener.java b/tests/core/runner/src/com/android/cts/runner/CtsTestRunListener.java
index 21ef195..5196df1 100644
--- a/tests/core/runner/src/com/android/cts/runner/CtsTestRunListener.java
+++ b/tests/core/runner/src/com/android/cts/runner/CtsTestRunListener.java
@@ -61,15 +61,7 @@
 
         // We might want to move this to /sdcard, if is is mounted/writable.
         File cacheDir = getInstrumentation().getTargetContext().getCacheDir();
-
-        // Set some properties that the core tests absolutely need.
-        System.setProperty("user.language", "en");
-        System.setProperty("user.region", "US");
-
-        System.setProperty("java.home", cacheDir.getAbsolutePath());
-        System.setProperty("user.home", cacheDir.getAbsolutePath());
         System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath());
-        System.setProperty("user.dir", cacheDir.getAbsolutePath());
 
         // attempt to disable keyguard, if current test has permission to do so
         // TODO: move this to a better place, such as InstrumentationTestRunner
@@ -157,7 +149,6 @@
     static class TestEnvironment {
         private final Locale mDefaultLocale;
         private final TimeZone mDefaultTimeZone;
-        private final String mUserHome;
         private final String mJavaIoTmpDir;
         private final HostnameVerifier mHostnameVerifier;
         private final SSLSocketFactory mSslSocketFactory;
@@ -165,17 +156,16 @@
         TestEnvironment() {
             mDefaultLocale = Locale.getDefault();
             mDefaultTimeZone = TimeZone.getDefault();
-            mUserHome = System.getProperty("user.home");
             mJavaIoTmpDir = System.getProperty("java.io.tmpdir");
             mHostnameVerifier = HttpsURLConnection.getDefaultHostnameVerifier();
             mSslSocketFactory = HttpsURLConnection.getDefaultSSLSocketFactory();
         }
 
         void reset() {
+            System.setProperties(null);
+            System.setProperty("java.io.tmpdir", mJavaIoTmpDir);
             Locale.setDefault(mDefaultLocale);
             TimeZone.setDefault(mDefaultTimeZone);
-            System.setProperty("user.home", mUserHome);
-            System.setProperty("java.io.tmpdir", mJavaIoTmpDir);
             Authenticator.setDefault(null);
             CookieHandler.setDefault(null);
             ResponseCache.setDefault(null);
diff --git a/tests/expectations/knownfailures.txt b/tests/expectations/knownfailures.txt
index 9b089df..2497eed 100644
--- a/tests/expectations/knownfailures.txt
+++ b/tests/expectations/knownfailures.txt
@@ -29,5 +29,131 @@
   name: "android.hardware.cts.SensorIntegrationTests#testSensorsWithSeveralClients",
   name: "android.hardware.cts.SensorIntegrationTests#testSensorsMovingRates",
   bug: 11352697
+},
+{
+  name: "android.provider.cts.ContactsContract_PinnedPositionsTest",
+  bug: 15430304
+},
+{
+  name: "android.app.cts.DownloadManagerTest#testDownloadManager",
+  name: "android.app.cts.DownloadManagerTest#testDownloadManagerDestination",
+  name: "android.app.cts.DownloadManagerTest#testDownloadManagerDestinationExtension",
+  name: "android.app.cts.DownloadManagerTest#testMinimumDownload",
+  name: "android.content.cts.ContentResolverSyncTestCase#testCallMultipleAccounts",
+  name: "android.content.cts.ContentResolverSyncTestCase#testCancelSync",
+  name: "android.content.cts.ContentResolverSyncTestCase#testRequestSync",
+  bug: 14657953
+},
+{
+  name: "android.database.sqlite.cts.SQLiteQueryBuilderTest#testSetProjectionMap",
+  bug: 12475524
+},
+{
+  name: "android.keystore.cts.KeyChainTest#testIsBoundKeyAlgorithm_RequiredAlgorithmsSupported",
+  bug: 15314696
+},
+{
+  name: "android.media.cts.AudioEffectTest",
+  bug: 15081808
+},
+{
+  name: "android.media.cts.AudioManagerTest#testMusicActive",
+  name: "android.media.cts.AudioManagerTest#testVolume",
+  bug: 15319269
+},
+{
+  name: "android.media.cts.AudioTrackTest#testGetTimestamp",
+  bug: 15320704
+},
+{
+  name: "android.media.cts.BassBoostTest",
+  name: "android.media.cts.EnvReverbTest",
+  name: "android.media.cts.EqualizerTest",
+  bug: 15163233
+},
+{
+  name: "android.media.cts.DecoderTest",
+  bug: 15163143
+},
+{
+  name: "android.media.cts.MediaPlayerFlakyNetworkTest",
+  bug: 15350295
+},
+{
+  name: "android.media.cts.MediaPlayerTest",
+  bug: 15321806
+},
+{
+  name: "android.media.cts.PresetReverbTest",
+  bug: 15338282
+},
+{
+  name: "android.media.cts.RingtoneManagerTest",
+  bug: 15343572
+},
+{
+  name: "android.media.cts.SoundPoolAacTest",
+  name: "android.media.cts.SoundPoolOggTest",
+  bug: 15350147
+},
+{
+  name: "android.media.cts.StreamingMediaPlayerTest",
+  bug: 15321207
+},
+{
+  name: "android.media.cts.VirtualizerTest",
+  bug: 15381765
+},
+{
+  name: "android.mediastress.cts.H263QcifLongPlayerTest",
+  name: "android.mediastress.cts.H264R480x360AacShortPlayerTest",
+  name: "android.mediastress.cts.Vp8R480x360LongPlayerTest",
+  bug: 15081769
+},
+{
+  name: "android.net.cts.ConnectivityManagerTest#testGetActiveNetworkInfo",
+  bug: 15087784
+},
+{
+  name: "android.media.cts.MediaCodecListTest#testIsAVCBaselineProfileSupported",
+  name: "android.media.cts.MediaCodecListTest#testIsH263BaselineProfileSupported",
+  name: "android.media.cts.MediaCodecListTest#testIsM4VSimpleProfileSupported",
+  name: "android.media.cts.MediaCodecListTest#testRequiredMediaCodecList",
+  bug: 15433903
+},
+{
+  name: "com.android.cts.uiautomatortest.CtsUiAutomatorTest",
+  bug: 15093828
+},
+{
+  name: "android.media.cts.RingtoneTest#testRingtone",
+  bug: 15343572
+},
+{
+  name: "android.media.cts.VisualizerTest",
+  bug: 15381765
+},
+{
+  name: "android.mediastress.cts.H263QcifShortPlayerTest",
+  name: "android.mediastress.cts.Vp8R480x360ShortPlayerTest",
+  bug: 15081769
+},
+{
+  name: "android.speech.tts.cts.TextToSpeechTest",
+  bug: 15082733
+},
+{
+  name: "android.net.cts.DnsTest#testDnsWorks",
+  name: "android.net.cts.SSLCertificateSocketFactoryTest",
+  name: "android.net.wifi.cts.NsdManagerTest#testAndroidTestCaseSetupProperly",
+  bug: 15004618
+},
+{
+  name: "android.media.cts.AudioRecord_BufferSizeTest#testGetMinBufferSize",
+  bug: 15319578
+},
+{
+  name: "android.text.cts.BoringLayoutTest#testScale",
+  bug: 15134518
 }
 ]
diff --git a/tests/plans/CTS-flaky.xml b/tests/plans/CTS-flaky.xml
deleted file mode 100644
index 62afa69..0000000
--- a/tests/plans/CTS-flaky.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<TestPlan version="1.0">
-  <Entry uri="android.app" exclude="android.app.cts.SystemFeaturesTest#testTelephonyFeatures;android.app.cts.InstrumentationTest#testCallActivityOnResume;android.app.cts.ActivityManagerRecentTaskInfoTest#testWriteToParcel;android.app.cts.InstrumentationTest#testMisc;android.app.cts.DialogTest#testSetContentView;android.app.cts.ServiceTest#testLocalBindAutoClassPermissionGranted;android.app.cts.ActivityManager_RunningAppProcessInfoTest#testAndroidTestCaseSetupProperly;android.app.cts.AlertDialog_BuilderTest#testSetSingleChoiceItemsWithParamInt;android.app.cts.LocalActivityManagerTest#testConstructor;android.app.cts.ActivityManager_RunningServiceInfoTest#testDescribeContents;android.app.cts.DialogTest#testTakeKeyEvents;android.app.cts.LifecycleTest#testBasic;android.app.cts.NotificationTest#testConstructor;android.app.cts.ActivityManagerMemoryInfoTest#testWriteToParcel;android.app.cts.DialogTest#testConstructor_protectedCancellable;android.app.cts.ProgressDialogTest#testIncrementProgressBy;android.app.cts.ApplicationTest#testApplication;android.app.cts.InstrumentationTest#testSendKeySync;android.app.cts.LocalActivityManagerTest#testDispatchCreate;android.app.cts.AlertDialogTest#testAlertDialogDeprecatedAPI;android.app.cts.AlertDialog_BuilderTest#testSetSingleChoiceItemsWithParamCursor;android.app.cts.InstrumentationTest#testCallActivityOnRestart;android.app.backup.cts.BackupAgentTest#testBackupAgent;android.app.cts.AlertDialog_BuilderTest#testSetSingleChoiceItemsWithParamCharSequence;android.app.cts.ActivityManager_RunningServiceInfoTest#testAndroidTestCaseSetupProperly;android.app.cts.ServiceTest#testLocalBindAutoAction;android.app.cts.DialogTest#testSetFeatureDrawableUri;android.app.cts.KeyguardManagerKeyguardLockTest#testDisableKeyguard;android.app.cts.LaunchTest#testClearTopWhilResumed;android.app.cts.WallpaperManagerTest#testSuggestDesiredDimensions;android.app.cts.SystemFeaturesTest#testLiveWallpaperFeature;android.app.cts.InstrumentationTest#testCallActivityOnUserLeaving;android.app.cts.AlertDialog_BuilderTest#testSetCancelable;android.app.cts.AlertDialogTest#testAlertDialogTheme;android.app.cts.PendingIntentTest#testGetBroadcast;android.app.cts.ActivityManager_RunningServiceInfoTest#testWriteToParcel;android.app.cts.InstrumentationTest#testGetComponentName;android.app.backup.cts.FileBackupHelperTest#testAndroidTestCaseSetupProperly;android.app.cts.DownloadManagerTest#testAndroidTestCaseSetupProperly;android.app.cts.SystemFeaturesTest#testTouchScreenFeatures;android.app.cts.AlarmManagerTest#testAlarmTriggersImmediatelyIfSetTimeIsNegative;android.app.cts.ActivityManagerMemoryInfoTest#testReadFromParcel;android.app.cts.NotificationTest#testAndroidTestCaseSetupProperly;android.app.cts.AlertDialog_BuilderTest#testSetOnCancelListener;android.app.cts.ServiceTest#testLocalBindClass;android.app.cts.ServiceTest#testLocalStartClass;android.app.cts.LauncherActivity_ListItemTest#testConstructor;android.app.cts.InstrumentationTest#testCallActivityOnCreate;android.app.cts.PendingIntentTest#testSendWithParamContextIntIntent;android.app.cts.InstrumentationTest#testSendPointerSync;android.app.cts.DialogTest#testRequestWindowFeature;android.app.cts.LocalActivityManagerTest#testDispatchPauseFalse;android.app.cts.Instrumentation_ActivityResultTest#testActivityResultOp;android.app.cts.ProgressDialogTest#testOnStartCreateStop;android.app.cts.AlertDialog_BuilderTest#testSetNegativeButtonWithParamInt;android.app.cts.KeyguardManagerKeyguardLockTest#testReenableKeyguard;android.app.cts.DialogTest#testShow;android.app.cts.ActivityManagerMemoryInfoTest#testDescribeContents;android.app.cts.SystemFeaturesTest#testFeatureNamespaces;android.app.cts.PendingIntent_CanceledExceptionTest#testConstructor;android.app.cts.AlertDialog_BuilderTest#testSetPositiveButtonWithParamInt;android.app.cts.PendingIntentTest#testSendWithParamInt;android.app.cts.PendingIntentTest#testGetActivity;android.app.cts.AlertDialog_BuilderTest#testSetCursor;android.app.cts.ActivityManagerProcessErrorStateInfoTest#testWriteToParcel;android.app.cts.AlertDialog_BuilderTest#testConstructor;android.app.cts.LocalActivityManagerTest#testDispatchDestroy;android.app.cts.DownloadManagerTest#testDownloadManager;android.app.cts.ServiceTest#testLocalBindAction;android.app.cts.LocalActivityManagerTest#testSaveInstanceState;android.app.cts.LifecycleTest#testTabDialog;android.app.cts.LaunchTest#testLocalActivity;android.app.cts.AlertDialog_BuilderTest#testSetInverseBackgroundForced;android.app.cts.SystemFeaturesTest#testLocationFeatures;android.app.cts.DialogTest#testOnStartCreateStop;android.app.cts.ActivityManagerRecentTaskInfoTest#testReadFromParcel;android.app.cts.ServiceTest#testLocalStartClassPermissions;android.app.cts.ServiceTest#testLocalUnbindTwice;android.app.cts.ActivityManagerProcessErrorStateInfoTest#testConstructor;android.app.cts.DialogTest#testSetFeatureDrawableResource;android.app.cts.ProgressDialogTest#testAccessProgress;android.app.cts.DialogTest#testTrackballEvent;android.app.cts.AlertDialog_BuilderTest#testSetSingleChoiceItems;android.app.cts.LaunchTest#testColdActivity;android.app.cts.ActivityManagerTest#testGetMemoryInfo;android.app.cts.PendingIntentTest#testAndroidTestCaseSetupProperly;android.app.cts.DialogTest#testOnContentChanged;android.app.cts.SearchManagerTest#testSetOnDismissListener;android.app.cts.InstrumentationTest#testContext;android.app.cts.LauncherActivity_IconResizerTest#testIconResizer;android.app.cts.DialogTest#testCancel_listener;android.app.cts.ActivityManagerTest#testIsUserAMonkey;android.app.cts.NotificationManagerTest#testCancelAll;android.app.cts.ActivityGroupTest#testAndroidTestCaseSetupProperly;android.app.cts.AlertDialog_BuilderTest#testCreate;android.app.cts.SystemFeaturesTest#testUsbAccessory;android.app.cts.ActivityManagerRecentTaskInfoTest#testDescribeContents;android.app.cts.ActivityManagerRunningTaskInfoTest#testDescribeContents;android.app.cts.AlertDialog_BuilderTest#testDisableCancelable;android.app.cts.InstrumentationTest#testSendKeyDownUpSync;android.app.cts.ActivityManagerRunningTaskInfoTest#testConstructor;android.app.cts.TimePickerDialogTest#testUpdateTime;android.app.cts.ActivityManagerRunningTaskInfoTest#testReadFromParcel;android.app.cts.ProgressDialogTest#testSetProgressStyle;android.app.cts.InstrumentationTest#testMonitor;android.app.cts.AliasActivityTest#testAliasActivity;android.app.cts.InstrumentationTest#testSendTrackballEventSync;android.app.cts.LifecycleTest#testScreen;android.app.cts.AlarmManagerTest#testCancel;android.app.cts.ActivityGroupTest#testTabDialog;android.app.cts.PendingIntentTest#testDescribeContents;android.app.cts.DialogTest#testOnSearchRequested;android.app.cts.SearchManagerTest#testSetOnCancelListener;android.app.cts.ProgressDialogTest#testAccessMax;android.app.cts.PendingIntentTest#testGetTargetPackage;android.app.cts.SystemFeaturesTest#testWifiFeature;android.app.cts.ActivityManagerRecentTaskInfoTest#testAndroidTestCaseSetupProperly;android.app.cts.DialogTest#testSetFeatureDrawableAlpha;android.app.cts.DialogTest#testSetTitle;android.app.cts.FragmentTest#testInstantiateNonFragment;android.app.cts.DialogTest#testSetDismissMessage;android.app.cts.PendingIntentTest#testWriteToParcel;android.app.cts.ActivityManagerMemoryInfoTest#testAndroidTestCaseSetupProperly;android.app.cts.AlertDialog_BuilderTest#testSetNeutralButtonWithParamCharSequence;android.app.cts.NotificationTest#testToString;android.app.cts.LaunchTest#testColdScreen;android.app.cts.AlertDialogTest#testAlertDialog;android.app.cts.SystemFeaturesTest#testSensorFeatures;android.app.cts.ProgressDialogTest#testShow1;android.app.cts.AlertDialog_BuilderTest#testSetNeutralButtonWithParamInt;android.app.cts.ActivityManagerRunningTaskInfoTest#testWriteToParcel;android.app.cts.ProgressDialogTest#testShow2;android.app.cts.ProgressDialogTest#testShow3;android.app.cts.ProgressDialogTest#testShow4;android.app.cts.InstrumentationTest#testCallActivityOnStart;android.app.cts.PendingIntentTest#testCancel;android.app.cts.InstrumentationTest#testConstructor;android.app.cts.ProgressDialogTest#testSetIndeterminate;android.app.cts.AlertDialog_BuilderTest#testShow;android.app.cts.AlertDialog_BuilderTest#testSetIconWithParamDrawable;android.app.cts.AlarmManagerTest#testSetTypes;android.app.cts.AlarmManagerTest#testSetInexactRepeating;android.app.cts.PendingIntentTest#testSendWithParamIntOnFinishedHandler;android.app.backup.cts.FileBackupHelperTest#testConstructor;android.app.cts.Instrumentation_ActivityResultTest#testAndroidTestCaseSetupProperly;android.app.cts.DownloadManagerTest#testDownloadManagerDestinationExtension;android.app.cts.LaunchTest#testClearTopInCreate;android.app.cts.InstrumentationTest#testRunOnMainSync;android.app.cts.DialogTest#testOnKeyDownKeyUp;android.app.cts.ServiceTest#testLocalStartActionPermissions;android.app.cts.KeyguardManagerTest#testInKeyguardRestrictedInputMode;android.app.cts.DialogTest#testConstructor;android.app.cts.AlertDialogTest#testCallback;android.app.cts.ActivityManagerTest#testGetRunningTasks;android.app.cts.ProgressDialogTest#testIncrementSecondaryProgressBy;android.app.cts.DialogTest#testAccessOwnerActivity;android.app.cts.LifecycleTest#testTabScreen;android.app.cts.TimePickerDialogTest#testOnRestoreInstanceState;android.app.cts.ActivityGroupTest#testTabBasic;android.app.cts.ServiceTest#testAndroidTestCaseSetupProperly;android.app.cts.PendingIntentTest#testSendWithParamContextIntIntentOnFinishedHandler;android.app.backup.cts.BackupManagerTest#testBackupManager;android.app.cts.ActivityManagerRecentTaskInfoTest#testConstructor;android.app.cts.DialogTest#testOnWindowFocusChanged;android.app.cts.DialogTest#testGetCurrentFocus;android.app.cts.TabActivityTest#testChildTitleCallback;android.app.cts.DialogTest#testSetOnDismissListener_listener;android.app.cts.ServiceTest#testLocalStartAction;android.app.cts.AlertDialog_BuilderTest#testSetMultiChoiceItemsWithParamInt;android.app.cts.DialogTest#testGetLayoutInflater;android.app.cts.InstrumentationTest#testInvokeContextMenuAction;android.app.cts.InstrumentationTest#testProfiling;android.app.cts.IntentServiceTest#testIntentServiceLifeCycle;android.app.cts.ProgressDialogTest#testAccessSecondaryProgress;android.app.cts.NotificationManagerTest#testAndroidTestCaseSetupProperly;android.app.backup.cts.BackupAgentTest#testAndroidTestCaseSetupProperly;android.app.cts.ActivityManagerTest#testGetProcessInErrorState;android.app.cts.SearchManagerTest#testStopSearch;android.app.cts.NotificationTest#testSetLatestEventInfo;android.app.cts.DialogTest#testSetCancellable_false;android.app.cts.PendingIntentTest#testSend;android.app.cts.LocalActivityManagerTest#testDispatchResume;android.app.cts.AlertDialog_BuilderTest#testSetViewCustom;android.app.cts.InstrumentationTest#testInvokeMenuActionSync;android.app.cts.DialogTest#testOnSaveInstanceState;android.app.cts.DialogTest#testOnKeyMultiple;android.app.cts.ActivityGroupTest#testTabScreen;android.app.cts.InstrumentationTest#testCallActivityOnSaveInstanceState;android.app.cts.ActivityManagerTest#testGetDeviceConfigurationInfo;android.app.cts.NotificationTest#testWriteToParcel;android.app.cts.InstrumentationTest#testWaitForIdle;android.app.cts.InstrumentationTest#testCallActivityOnStop;android.app.cts.InstrumentationTest#testSendCharacterSync;android.app.cts.TimePickerDialogTest#testOnTimeChanged;android.app.cts.PendingIntentTest#testEquals;android.app.cts.AlertDialog_BuilderTest#testSetIconWithParamInt;android.app.cts.DialogTest#testContextMenu;android.app.cts.SystemFeaturesTest#testBluetoothFeature;android.app.cts.ExpandableListActivityTest#testView;android.app.cts.AlarmManagerTest#testSetRepeating;android.app.cts.ActivityManager_RunningServiceInfoTest#testReadFromParcel;android.app.cts.ServiceTest#testLocalBindActionPermissions;android.app.cts.LocalActivityManagerTest#testDispatchStop;android.app.cts.LauncherActivity_ListItemTest#testAndroidTestCaseSetupProperly;android.app.cts.InstrumentationTest#testNewApplication;android.app.cts.LaunchTest#testForwardResult;android.app.cts.ProgressDialogTest#testSetMessage;android.app.cts.ActivityManagerTest#testGetRunningServices;android.app.cts.AlertDialogTest#testCustomAlertDialogView;android.app.backup.cts.SharedPreferencesBackupHelperTest#testConstructor;android.app.cts.LifecycleTest#testTabBasic;android.app.cts.FragmentTest#testInstantiateFragment;android.app.cts.ActivityManager_RunningAppProcessInfoTest#testRunningAppProcessInfo;android.app.cts.AlertDialogTest#testAlertDialogNotCancelable;android.app.cts.AlertDialog_BuilderTest#testSetItemsWithParamCharSequence;android.app.cts.ActivityManagerProcessErrorStateInfoTest#testDescribeContents;android.app.cts.DialogTest#testConstructor_protectedNotCancellable;android.app.cts.ExpandableListActivityTest#testSelect;android.app.cts.SystemFeaturesTest#testScreenFeatures;android.app.cts.LauncherActivityTest#testLaunchActivity;android.app.cts.LaunchTest#testAndroidTestCaseSetupProperly;android.app.cts.LifecycleTest#testAndroidTestCaseSetupProperly;android.app.cts.NotificationTest#testDescribeContents;android.app.cts.DialogTest#testOnWindowAttributesChanged;android.app.cts.ServiceTest#testLocalBindAutoActionPermissionGranted;android.app.cts.InstrumentationTest#testCallActivityOnPostCreate;android.app.cts.AlertDialogTest#testAlertDialogDeprecatedAPIWithMessage;android.app.cts.AlertDialog_BuilderTest#testSetPositiveButtonWithParamCharSequence;android.app.cts.AlarmManagerTest#testAndroidTestCaseSetupProperly;android.app.cts.AlertDialog_BuilderTest#testSetView;android.app.cts.ActivityManager_RunningServiceInfoTest#testConstructor;android.app.cts.InstrumentationTest#testPerformanceSnapshot;android.app.cts.InstrumentationTest#testCallApplicationOnCreate;android.app.cts.DialogTest#testSetFeatureDrawable;android.app.cts.AliasActivityTest#testAndroidTestCaseSetupProperly;android.app.cts.PendingIntentTest#testGetService;android.app.cts.IntentServiceTest#testIntents;android.app.cts.AlertDialog_BuilderTest#testSetOnItemSelectedListener;android.app.cts.LifecycleTest#testDialog;android.app.cts.DownloadManagerTest#testDownloadManagerDestination;android.app.cts.WallpaperManagerTest#testAndroidTestCaseSetupProperly;android.app.cts.ExpandableListActivityTest#testAndroidTestCaseSetupProperly;android.app.cts.InstrumentationTest#testNewActivity;android.app.cts.ProgressDialogTest#testSetProgressDrawable;android.app.backup.cts.BackupManagerTest#testAndroidTestCaseSetupProperly;android.app.cts.InstrumentationTest#testAllocCounting;android.app.cts.LocalActivityManagerTest#testRemoveAllActivities;android.app.cts.ServiceTest#testLocalBindAutoClass;android.app.backup.cts.BackupAgentHelperTest#testBackupAgentHelper;android.app.cts.ActivityManagerProcessErrorStateInfoTest#testReadFromParcel;android.app.cts.PendingIntent_CanceledExceptionTest#testAndroidTestCaseSetupProperly;android.app.cts.TimePickerDialogTest#testOnClick;android.app.cts.AlertDialog_BuilderTest#testSetOnKeyListener;android.app.cts.DialogTest#testTouchEvent;android.app.cts.ProgressDialogTest#testProgressDialog1;android.app.cts.InstrumentationTest#testCallActivityOnRestoreInstanceState;android.app.cts.ProgressDialogTest#testProgressDialog2;android.app.cts.InstrumentationTest#testCallActivityOnPause;android.app.cts.AlertDialog_BuilderTest#testSetMultiChoiceItemsWithParamCharSequence;android.app.cts.SystemFeaturesTest#testCameraFeatures;android.app.cts.ServiceTest#testLocalBindClassPermissions;android.app.cts.ActivityManagerTest#testGetRecentTasks;android.app.cts.SystemFeaturesTest#testNfcFeatures;android.app.cts.AlertDialogTest#testCustomAlertDialog;android.app.cts.SystemFeaturesTest#testSipFeatures;android.app.cts.InstrumentationTest#testSendStringSync;android.app.cts.ActivityManagerRunningTaskInfoTest#testAndroidTestCaseSetupProperly;android.app.cts.TabActivityTest#testTabActivity;android.app.cts.KeyguardManagerTest#testNewKeyguardLock;android.app.cts.NotificationManagerTest#testCancel;android.app.cts.AlertDialog_BuilderTest#testSetMultiChoiceItemsWithParamCursor;android.app.cts.ActivityManagerMemoryClassTest#testGetMemoryClass;android.app.cts.ActivityManagerTest#testGetRunningAppProcesses;android.app.cts.AlertDialog_BuilderTest#testSetAdapter;android.app.cts.AlertDialog_BuilderTest#testSetItemsWithParamInt;android.app.cts.DialogTest#testCancel_noListener;android.app.cts.DialogTest#testDispatchKeyEvent;android.app.cts.LaunchTest#testLocalScreen;android.app.cts.ActivityManagerTest#testRestartPackage;android.app.cts.FragmentTest#testAndroidTestCaseSetupProperly;android.app.cts.InstrumentationTest#testCallActivityOnNewIntent;android.app.cts.NotificationManagerTest#testNotify;android.app.cts.LocalActivityManagerTest#testDispatchPauseTrue;android.app.cts.ActivityManagerProcessErrorStateInfoTest#testAndroidTestCaseSetupProperly;android.app.backup.cts.BackupAgentHelperTest#testAndroidTestCaseSetupProperly;android.app.cts.ProgressDialogTest#testSetIndeterminateDrawable;android.app.backup.cts.SharedPreferencesBackupHelperTest#testAndroidTestCaseSetupProperly;android.app.cts.DownloadManagerTest#testMinimumDownload;android.app.cts.PendingIntentTest#testReadAndWritePendingIntentOrNullToParcel;android.app.cts.DialogTest#testSetOnDismissListener_noListener;android.app.cts.KeyguardManagerTest#testExitKeyguardSecurely;android.app.cts.AlertDialog_BuilderTest#testSetNegativeButtonWithParamCharSequence;android.app.cts.DialogTest#testSetCancelable_true;android.app.cts.Instrumentation_ActivityMonitorTest#testActivityMonitor;android.app.cts.LocalActivityManagerTest#testStartActivity;android.app.cts.IntentServiceTest#testAndroidTestCaseSetupProperly;android.app.cts.ActionBarTest#testAddTab;android.app.cts.DialogTest#testSetCancelMessage;android.app.cts.TimePickerDialogTest#testSaveInstanceState" />
-  <Entry uri="android.hardware" exclude="android.hardware.consumerir.cts.ConsumerIrTest#test_hasIrEmitter;android.hardware.consumerir.cts.ConsumerIrTest#test_getCarrierFrequencies;android.hardware.consumerir.cts.ConsumerIrTest#test_transmit;android.hardware.camera2.cts.CameraDeviceTest#testCameraDeviceCaptureBurst;android.hardware.camera2.cts.CameraDeviceTest#testCameraDeviceRepeatingBurst;android.hardware.cts.CameraGLTest#testSetPreviewTextureTextureCallback;android.hardware.cts.CameraTest#test3ALockInteraction;android.hardware.cts.CameraTest#testAutoExposureLock;android.hardware.cts.CameraTest#testAutoWhiteBalanceLock;android.hardware.cts.CameraTest#testCancelAutofocus;android.hardware.cts.CameraTest#testDisplayOrientation;android.hardware.cts.CameraTest#testEnableShutterSound;android.hardware.cts.CameraTest#testFaceDetection;android.hardware.cts.CameraTest#testFocusAreas;android.hardware.cts.CameraTest#testFocusDistances;android.hardware.cts.CameraTest#testGetParameterDuringFocus;android.hardware.cts.CameraTest#testInvalidParameters;android.hardware.cts.CameraTest#testJpegCallbackStartPreview;android.hardware.cts.CameraTest#testJpegExif;android.hardware.cts.CameraTest#testJpegThumbnailSize;android.hardware.cts.CameraTest#testLockUnlock;android.hardware.cts.CameraTest#testMeteringAreas;android.hardware.cts.CameraTest#testMultiCameraRelease;android.hardware.cts.CameraTest#testMultipleCameras;android.hardware.cts.CameraTest#testParameters;android.hardware.cts.CameraTest#testPreviewCallbackWithBuffer;android.hardware.cts.CameraTest#testPreviewCallbackWithPicture;android.hardware.cts.CameraTest#testPreviewFormats;android.hardware.cts.CameraTest#testPreviewFpsRange;android.hardware.cts.CameraTest#testPreviewPictureSizesCombination;android.hardware.cts.CameraTest#testRecordingHint;android.hardware.cts.CameraTest#testSceneMode;android.hardware.cts.CameraTest#testSetOneShotPreviewCallback;android.hardware.cts.CameraTest#testSetPreviewDisplay;android.hardware.cts.CameraTest#testTakePicture;android.hardware.camera2.cts.ImageReaderTest#testImageReaderInvalidAccessTest;android.hardware.cts.SensorAccelerometerTest#testEventJittering;android.hardware.cts.SensorGyroscopeTest#testEventsArriveInOrder;android.hardware.camera2.cts.CameraCharacteristicsTest#testCameraCharacteristicsAndroidScalerAvailableJpegSizes;android.hardware.cts.SensorAccelerometerTest#testCanReceiveBatchEvents;android.hardware.camera2.cts.CameraCharacteristicsTest#testCameraCharacteristicsAndroidSensorOrientation;android.hardware.camera2.cts.CameraCharacteristicsTest#testAndroidTestCaseSetupProperly;android.hardware.cts.SensorMagneticFieldTest#testUpdateRate;android.hardware.cts.SensorAccelerometerTest#testNotTriggerSensor;android.hardware.cts.SensorAccelerometerTest#testAndroidTestCaseSetupProperly;android.hardware.cts.SensorAccelerometerTest#testCanReceiveEvents;android.hardware.cts.SensorMagneticFieldTest#testVarianceWhileStatic;android.hardware.camera2.cts.CameraCharacteristicsTest#testCameraCharacteristicsAndroidLensInfoHyperfocalDistance;android.hardware.camera2.cts.CameraManagerTest#testCameraManagerOpenCamerasSerially;android.hardware.camera2.cts.CameraDeviceTest#testCameraDeviceCreateCaptureBuilder;android.hardware.camera2.cts.CameraCharacteristicsTest#testCameraCharacteristicsAndroidScalerAvailableProcessedMinDurations;android.hardware.camera2.cts.CameraCharacteristicsTest#testCameraCharacteristicsAndroidFlashInfoAvailable;android.hardware.camera2.cts.CameraCharacteristicsTest#testCameraCharacteristicsAndroidLensInfoShadingMapSize;android.hardware.cts.LowRamDeviceTest#testAndroidTestCaseSetupProperly;android.hardware.cts.SensorTest#testSensorOperations;android.hardware.camera2.cts.CameraCharacteristicsTest#testCameraCharacteristicsAndroidControlAwbAvailableModes;android.hardware.camera2.cts.CameraCharacteristicsTest#testCameraCharacteristicsAndroidSensorBaseGainFactor;android.hardware.camera2.cts.CameraCharacteristicsTest#testCameraCharacteristicsAndroidSensorInfoPhysicalSize;android.hardware.camera2.cts.CameraCharacteristicsTest#testCameraCharacteristicsAndroidInfoSupportedHardwareLevel;android.hardware.camera2.cts.CameraCharacteristicsTest#testCameraCharacteristicsAndroidJpegAvailableThumbnailSizes;android.hardware.cts.SensorGyroscopeTest#testNotTriggerSensor;android.hardware.camera2.cts.CameraCharacteristicsTest#testCameraCharacteristicsAndroidLensFacing;android.hardware.cts.Camera_ParametersTest#testAccessMethods;android.hardware.cts.SensorMagneticFieldTest#testCanRegisterListener;android.hardware.camera2.cts.CameraCharacteristicsTest#testCameraCharacteristicsAndroidScalerAvailableFormats;android.hardware.cts.SensorTest#testBatchAndFlush;android.hardware.cts.SensorGyroscopeTest#testAndroidTestCaseSetupProperly;android.hardware.cts.SensorMagneticFieldTest#testCanReceiveEvents;android.hardware.camera2.cts.CameraCharacteristicsTest#testCameraCharacteristicsAndroidControlAvailableEffects;android.hardware.camera2.cts.CameraManagerTest#testAndroidTestCaseSetupProperly;android.hardware.cts.SensorGyroscopeTest#testSeveralClientsBatching;android.hardware.camera2.cts.CameraCharacteristicsTest#testCameraCharacteristicsAndroidControlAeAvailableAntibandingModes;android.hardware.cts.GeomagneticFieldTest#testAndroidTestCaseSetupProperly;android.hardware.cts.SensorAccelerometerTest#testStartStopRepeatedly;android.hardware.camera2.cts.CameraCharacteristicsTest#testCameraCharacteristicsAndroidControlAfAvailableModes;android.hardware.camera2.cts.CameraCharacteristicsTest#testCameraCharacteristicsAndroidSensorMaxAnalogSensitivity;android.hardware.cts.SensorTest#testRequestTriggerWithNonTriggerSensor;android.hardware.cts.SensorMagneticFieldTest#testBatchEventsArriveInOrder;android.hardware.camera2.cts.CameraCharacteristicsTest#testCameraCharacteristicsAndroidLensInfoMinimumFocusDistance;android.hardware.cts.SensorTest#testValuesForAllSensors;android.hardware.cts.SensorMagneticFieldTest#testCanReceiveBatchEvents;android.hardware.cts.SensorAccelerometerTest#testUpdateRate;android.hardware.cts.SensorMagneticFieldTest#testStartStopRepeatedly;android.hardware.camera2.cts.CameraCharacteristicsTest#testCameraCharacteristicsAndroidControlMaxRegions;android.hardware.cts.SensorMagneticFieldTest#testAndroidTestCaseSetupProperly;android.hardware.camera2.cts.CameraCharacteristicsTest#testCameraCharacteristicsAndroidControlAeCompensationRange;android.hardware.camera2.cts.CameraCharacteristicsTest#testCameraCharacteristicsAndroidRequestMaxNumOutputStreams;android.hardware.camera2.cts.CameraCharacteristicsTest#testCameraCharacteristicsAndroidSensorInfoSensitivityRange;android.hardware.cts.SensorMagneticFieldTest#testNotTriggerSensor;android.hardware.cts.SensorGyroscopeTest#testBatchEventsArriveInOrder;android.hardware.camera2.cts.CameraManagerTest#testCameraManagerInvalidDevice;android.hardware.cts.LowRamDeviceTest#testLowRamProductProperty;android.hardware.cts.SensorTest#testCancelTriggerWithNonTriggerSensor;android.hardware.cts.SensorMagneticFieldTest#testEventsArriveInOrder;android.hardware.cts.SensorMagneticFieldTest#testMaxFrequency;android.hardware.cts.SensorAccelerometerTest#testSeveralClientsBatching;android.hardware.cts.SensorMagneticFieldTest#testEventJittering;android.hardware.cts.SensorGyroscopeTest#testEventValidity;android.hardware.camera2.cts.ImageReaderTest#testImageReaderFromCameraRaw;android.hardware.camera2.cts.CameraCharacteristicsTest#testCameraCharacteristicsAndroidControlAeCompensationStep;android.hardware.cts.SensorMagneticFieldTest#testSeveralClientsBatching;android.hardware.camera2.cts.CameraManagerTest#testCameraManagerGetCameraCharacteristics;android.hardware.cts.SensorAccelerometerTest#testCanRegisterListener;android.hardware.camera2.cts.ImageReaderTest#testImageReaderFromCameraFlexibleYuv;android.hardware.camera2.cts.CameraCharacteristicsTest#testCameraCharacteristicsAndroidControlAvailableVideoStabilizationModes;android.hardware.cts.SensorGyroscopeTest#testStartStopRepeatedly;android.hardware.cts.SensorAccelerometerTest#testEventsArriveInOrder;android.hardware.cts.SensorMagneticFieldTest#testRegisterForBatchingZeroReport;android.hardware.cts.SensorGyroscopeTest#testCanRegisterListener;android.hardware.cts.SensorGyroscopeTest#testMaxFrequency;android.hardware.camera2.cts.CameraCharacteristicsTest#testCameraCharacteristicsAndroidScalerAvailableProcessedSizes;android.hardware.camera2.cts.CameraCharacteristicsTest#testCameraCharacteristicsAndroidControlAeAvailableTargetFpsRanges;android.hardware.camera2.cts.CameraCharacteristicsTest#testCameraCharacteristicsAndroidTonemapMaxCurvePoints;android.hardware.cts.SensorGyroscopeTest#testCanReceiveEvents;android.hardware.cts.SensorTest#testRegisterTwiceWithSameSensor;android.hardware.camera2.cts.CameraCharacteristicsTest#testCameraCharacteristicsAndroidLensInfoAvailableOpticalStabilization;android.hardware.camera2.cts.ImageReaderTest#testAndroidTestCaseSetupProperly;android.hardware.cts.SensorMagneticFieldTest#testSeveralClients;android.hardware.camera2.cts.CameraManagerTest#testCameraManagerOpenCameraTwice;android.hardware.cts.SensorMagneticFieldTest#testStartStopBatchingRepeatedly;android.hardware.camera2.cts.CameraCharacteristicsTest#testCameraCharacteristicsAndroidScalerAvailableMaxDigitalZoom;android.hardware.cts.SensorAccelerometerTest#testBatchEventsArriveInOrder;android.hardware.camera2.cts.CameraDeviceTest#testAndroidTestCaseSetupProperly;android.hardware.cts.SensorAccelerometerTest#testRegisterForBatchingZeroReport;android.hardware.camera2.cts.CameraCharacteristicsTest#testCameraCharacteristicsAndroidStatisticsInfoMaxFaceCount;android.hardware.camera2.cts.CameraCharacteristicsTest#testCameraCharacteristicsAndroidControlAvailableSceneModes;android.hardware.camera2.cts.CameraCharacteristicsTest#testCameraCharacteristicsAndroidSensorInfoActiveArraySize;android.hardware.camera2.cts.CameraCharacteristicsTest#testCameraCharacteristicsAndroidSensorInfoMaxFrameDuration;android.hardware.cts.SensorAccelerometerTest#testStartStopBatchingRepeatedly;android.hardware.cts.SensorGyroscopeTest#testEventJittering;android.hardware.camera2.cts.CameraDeviceTest#testCameraDeviceCapture;android.hardware.camera2.cts.CameraCharacteristicsTest#testCameraCharacteristicsAndroidSensorInfoExposureTimeRange;android.hardware.camera2.cts.CameraCharacteristicsTest#testCameraCharacteristicsAndroidLensInfoAvailableFocalLengths;android.hardware.cts.SensorGyroscopeTest#testCanReceiveBatchEvents;android.hardware.cts.SensorTest#testLegacySensorOperations;android.hardware.camera2.cts.CameraManagerTest#testCameraManagerListener;android.hardware.cts.GeomagneticFieldTest#testGeomagneticField;android.hardware.cts.SensorGyroscopeTest#testSeveralClients;android.hardware.cts.SensorGyroscopeTest#testStartStopBatchingRepeatedly;android.hardware.camera2.cts.CameraCharacteristicsTest#testCameraCharacteristicsAndroidLensInfoAvailableFilterDensities;android.hardware.camera2.cts.CameraDeviceTest#testCameraDeviceSetErrorListener;android.hardware.cts.SensorGyroscopeTest#testRegisterForBatchingZeroReport;android.hardware.camera2.cts.CameraManagerTest#testCameraManagerGetDeviceIdList;android.hardware.cts.SensorAccelerometerTest#testMaxFrequency;android.hardware.camera2.cts.CameraManagerTest#testCameraManagerOpenAllCameras;android.hardware.cts.SensorAccelerometerTest#testSeveralClients;android.hardware.cts.SensorGyroscopeTest#testVarianceWhileStatic;android.hardware.camera2.cts.CameraCharacteristicsTest#testCameraCharacteristicsAndroidScalerAvailableJpegMinDurations;android.hardware.cts.SensorTest#testAndroidTestCaseSetupProperly;android.hardware.camera2.cts.CameraCharacteristicsTest#testCameraCharacteristicsAndroidStatisticsInfoAvailableFaceDetectModes;android.hardware.camera2.cts.CameraCharacteristicsTest#testCameraCharacteristicsAndroidLensInfoAvailableApertures;android.hardware.cts.SensorAccelerometerTest#testEventValidity;android.hardware.cts.SensorAccelerometerTest#testUpdateBatchRate;android.hardware.cts.SensorAccelerometerTest#testVarianceWhileStatic;android.hardware.cts.SensorGyroscopeTest#testUpdateBatchRate;android.hardware.cts.SensorGyroscopeTest#testUpdateRate;android.hardware.cts.SensorMagneticFieldTest#testEventValidity;android.hardware.cts.SensorMagneticFieldTest#testUpdateBatchRate;android.hardware.cts.SensorTest#testRegisterWithTriggerSensor;android.hardware.cts.Camera_SizeTest#testConstructor" />
-  <Entry uri="android.media" exclude="android.media.cts.MediaPlayerTest#testLocalVideo_3gp_H263_176x144_300kbps_12fps_AAC_Stereo_24kbps_22050Hz;android.media.cts.AudioPreProcessingTest#test2_1AecCreateAndRelease;android.media.cts.MediaCodecTest#testConcurrentAudioVideoEncodings;android.media.cts.EnvReverbTest#test2_0SetEnabledGetEnabled;android.media.cts.EncodeDecodeTest#testEncodeDecodeVideoFromBufferToBufferQVGA;android.media.cts.AudioTrackTest#testSetLoopPointsStartTooFar;android.media.cts.RingtoneManagerTest#testStopPreviousRingtone;android.media.cts.EnvReverbTest#test1_3Reflections;android.media.cts.MediaPlayerTest#testGapless3;android.media.cts.MediaPlayerTest#testGapless2;android.media.cts.MediaPlayerTest#testGapless1;android.media.cts.BassBoostTest#testAndroidTestCaseSetupProperly;android.media.cts.EnvReverbTest#test3_1EnableStatusListener;android.media.cts.ExtractDecodeEditEncodeMuxTest#testExtractDecodeEditEncodeMuxQVGA;android.media.cts.MediaRecorderTest#testRecorderCamera;android.media.cts.MediaPlayerTest#testGetTrackInfo;android.media.cts.MediaDrmMockTest#testIsCryptoSchemeNotSupported;android.media.cts.AudioPreProcessingTest#testAndroidTestCaseSetupProperly;android.media.cts.DecodeEditEncodeTest#testVideoEditQCIF;android.media.cts.MediaPlayerTest#testDeselectTrack;android.media.cts.AudioEffectTest#test3_7SetParameterAfterRelease;android.media.cts.MediaPlayerTest#testLocalVideo_3gp_H263_176x144_56kbps_12fps_AAC_Mono_24kbps_22050Hz;android.media.cts.AudioEffectTest#test4_2ControlStatusListener;android.media.cts.StreamingMediaPlayerTest#testHTTP_MPEG4SP_AAC_Video1;android.media.cts.StreamingMediaPlayerTest#testHTTP_MPEG4SP_AAC_Video2;android.media.cts.JetPlayerTest#testLoadJetFromFd;android.media.cts.MediaDrmMockTest#testProvideProvisionResponse;android.media.cts.JetPlayerTest#testQueueJetSegmentMuteArray;android.media.cts.StreamingMediaPlayerTest#testPlayOggStream;android.media.cts.MediaPlayerTest#testLocalVideo_MP4_H264_480x360_1350kbps_25fps_AAC_Stereo_128kbps_44110Hz;android.media.cts.SoundPoolAacTest#testAndroidTestCaseSetupProperly;android.media.cts.PresetReverbTest#test3_2ParameterChangedListener;android.media.cts.MediaDrmMockTest#testNullPropertyString;android.media.cts.AudioEffectTest#test3_2SetParameterIntShort;android.media.cts.AudioRecord_BufferSizeTest#testGetMinBufferSize;android.media.cts.AudioEffectTest#test3_0SetParameterByteArrayByteArray;android.media.cts.MediaScannerConnectionTest#testAndroidTestCaseSetupProperly;android.media.cts.MediaPlayerTest#testLocalVideo_MP4_H264_480x360_1000kbps_30fps_AAC_Stereo_128kbps_44110Hz;android.media.cts.AudioTrackTest#testWriteShortSizeTooBig;android.media.cts.AudioTrackTest#testGetMinBufferSizeTooLowSR;android.media.cts.AudioEffectTest#test1_1ConstructorFromUuid;android.media.cts.ToneGeneratorTest#testSyncGenerate;android.media.cts.AudioEffectTest#test1_3GetEnabledAfterRelease;android.media.cts.BassBoostTest#test1_1Properties;android.media.cts.SoundPoolOggTest#testLoadMore;android.media.cts.AudioEffectTest#test1_7AuxiliaryOnAudioTrack;android.media.cts.MediaPlayerTest#testLocalVideo_3gp_H263_176x144_300kbps_12fps_AAC_Stereo_128kbps_11025Hz;android.media.cts.MediaCodecListTest#testMediaCodecXmlFileExist;android.media.cts.MediaPlayerTest#testLocalVideo_MP4_H264_480x360_1000kbps_25fps_AAC_Stereo_128kbps_44110Hz;android.media.cts.VisualizerTest#test2_1ListenerCapture;android.media.cts.MediaPlayerTest#testLocalVideo_3gp_H263_176x144_56kbps_25fps_AAC_Stereo_24kbps_11025Hz;android.media.cts.StreamingMediaPlayerTest#testPlayMp3Stream2;android.media.cts.StreamingMediaPlayerTest#testPlayMp3Stream1;android.media.cts.MediaPlayerTest#testPlayNullSource;android.media.cts.VirtualizerTest#testAndroidTestCaseSetupProperly;android.media.cts.EncodeVirtualDisplayWithCompositionTest#testSingleVirtualDisplay;android.media.cts.DecoderTest#testDecodeOgg;android.media.cts.MediaRecorderTest#testOnErrorListener;android.media.cts.EnvReverbTest#test2_1SetEnabledAfterRelease;android.media.cts.AudioTrackTest#testSetPlaybackRate;android.media.cts.AudioManagerTest#testVibrateNotification;android.media.cts.AudioManagerTest#testAccessMode;android.media.cts.EqualizerTest#test1_4SetBandLevelAfterRelease;android.media.cts.MediaPlayerTest#testPlayVideo;android.media.cts.MediaCodecTest#testSignalSurfaceEOS;android.media.cts.VisualizerTest#test0_0ConstructorAndRelease;android.media.cts.DecoderTest#testDecodeFlac;android.media.cts.MediaDrmMockTest#testEventWithSessionAndData;android.media.cts.MediaScannerConnectionTest#testMediaScannerConnection;android.media.cts.AudioTrackTest#testConstructorMono8MusicStatic;android.media.cts.AudioManagerTest#testMicrophoneMute;android.media.cts.MediaDrmMockTest#testMissingPropertyString;android.media.cts.MediaPlayerTest#testLocalVideo_3gp_H263_176x144_300kbps_25fps_AAC_Stereo_128kbps_22050Hz;android.media.cts.AudioTrackTest#testConstructorStereo16MusicStream;android.media.cts.Vp8EncoderTest#testAndroidTestCaseSetupProperly;android.media.cts.MediaDrmMockTest#testQueryKeyStatus;android.media.cts.BassBoostTest#test3_2ParameterChangedListener;android.media.cts.AudioManagerTest#testVibrateRinger;android.media.cts.AudioManagerTest#testMusicActive;android.media.cts.DecoderTest#testCodecResetsVP8WithoutSurface;android.media.cts.MediaPlayerTest#testRecordedVideoPlayback90;android.media.cts.MediaPlayerFlakyNetworkTest#test_S3P00001;android.media.cts.AudioTrackTest#testGetMinBufferSizeTooHighSR;android.media.cts.CamcorderProfileTest#testAndroidTestCaseSetupProperly;android.media.cts.MediaPlayerTest#testLocalVideo_3gp_H263_176x144_56kbps_25fps_AAC_Stereo_128kbps_11025Hz;android.media.cts.AudioManagerTest#testVolume;android.media.cts.MediaMuxerTest#testAudioOnly;android.media.cts.MediaPlayerTest#testLocalVideo_3gp_H263_176x144_56kbps_12fps_AAC_Stereo_128kbps_22050Hz;android.media.cts.AudioEffectTest#test1_6AuxiliaryOnMediaPlayerFailure;android.media.cts.DecoderTest#testCodecResetsMpeg4WithSurface;android.media.cts.AudioEffectTest#test4_1setParameterLowerPriority;android.media.cts.MediaPlayerTest#testLocalVideo_MP4_H264_480x360_500kbps_30fps_AAC_Stereo_128kbps_44110Hz;android.media.cts.DecoderTest#testCodecResetsVP8WithSurface;android.media.cts.CamcorderProfileTest#testGet;android.media.cts.DecoderTest#testDecodeMonoM4a;android.media.cts.MediaRecorderTest#testSetCamera;android.media.cts.AudioTrackTest#testSetGetPlaybackRate;android.media.cts.EncodeDecodeTest#testEncodeDecodeVideoFromSurfaceToSurfaceQVGA;android.media.cts.EnvReverbTest#testAndroidTestCaseSetupProperly;android.media.cts.DecoderTest#testFlush;android.media.cts.AudioEffectTest#testAndroidTestCaseSetupProperly;android.media.cts.MediaPlayerTest#testLocalVideo_3gp_H263_176x144_300kbps_12fps_AAC_Mono_24kbps_11025Hz;android.media.cts.DecoderTest#testDecodeMp3Lame;android.media.cts.EncoderTest#testAMRNBEncoders;android.media.cts.MediaScannerTest#testAndroidTestCaseSetupProperly;android.media.cts.MediaCodecListTest#testRequiredMediaCodecList;android.media.cts.DecoderTest#testCodecResetsMpeg4WithoutSurface;android.media.cts.MediaRecorderTest#testGetAudioSourceMax;android.media.cts.MediaPlayerTest#testLocalVideo_MP4_H264_480x360_500kbps_25fps_AAC_Stereo_128kbps_44110Hz;android.media.cts.AudioTrackTest#testSetLoopPointsLoopTooLong;android.media.cts.EqualizerTest#test1_1BandFrequency;android.media.cts.EncoderTest#testAMRWBEncoders;android.media.cts.AudioTrackTest#testWriteShortNegativeSize;android.media.cts.AudioTrackTest#testConstructorStreamType;android.media.cts.MediaPlayerTest#testCallback;android.media.cts.BassBoostTest#test2_0SetEnabledGetEnabled;android.media.cts.MediaPlayerFlakyNetworkTest#test_S2P00001;android.media.cts.EncodeVirtualDisplayTest#testEncodeVirtualDisplay;android.media.cts.EncodeDecodeTest#testEncodeDecodeVideoFromSurfaceToSurfaceQCIF;android.media.cts.DecoderTest#testCodecEarlyEOSVP9;android.media.cts.MediaPlayerTest#testLocalVideo_MP4_H264_480x360_1350kbps_30fps_AAC_Stereo_192kbps_44110Hz;android.media.cts.DecoderTest#testCodecEarlyEOSVP8;android.media.cts.MediaPlayerFlakyNetworkTest#test_S5P00001;android.media.cts.MediaRandomTest#testRecorderRandomAction;android.media.cts.MediaDrmMockTest#testBadSession;android.media.cts.MediaPlayerTest#testLocalVideo_3gp_H263_176x144_56kbps_12fps_AAC_Stereo_128kbps_11025Hz;android.media.cts.CameraProfileTest#testGetWithId;android.media.cts.EnvReverbTest#test1_0Room;android.media.cts.StreamingMediaPlayerTest#testPlayMp3StreamNoLength;android.media.cts.SoundPoolAacTest#testMultiSound;android.media.cts.AudioTrackTest#testReloadStaticData;android.media.cts.MediaDrmMockTest#testAndroidTestCaseSetupProperly;android.media.cts.MediaPlayerTest#testPlayAudio;android.media.cts.MediaDrmMockTest#testGetKeyRequestNoOptionalParameters;android.media.cts.MediaRecorderTest#testSetMaxDuration;android.media.cts.AudioPreProcessingTest#test2_2AecSetEnabledGetEnabled;android.media.cts.AsyncPlayerTest#testAsyncPlayer;android.media.cts.DecoderTest#testCodecBasicVP8;android.media.cts.DecoderTest#testCodecBasicVP9;android.media.cts.AudioTrackTest#testSetLoopPointsStream;android.media.cts.AudioTrackTest#testConstructorStereo8MusicStatic;android.media.cts.MediaCodecTest#testDequeueSurface;android.media.cts.EncodeDecodeTest#testEncodeDecodeVideoFromBufferToBuffer720p;android.media.cts.MediaRecorderTest#testRecorderTimelapsedVideo;android.media.cts.MediaCodecTest#testAndroidTestCaseSetupProperly;android.media.cts.AudioTrackTest#testSetPlaybackHeadPositionStopped;android.media.cts.AudioTrackTest#testWriteByteSizeTooBig;android.media.cts.MediaMuxerTest#testAndroidTestCaseSetupProperly;android.media.cts.EnvReverbTest#test1_1Decay;android.media.cts.MediaPlayerTest#testLocalVideo_3gp_H263_176x144_300kbps_12fps_AAC_Stereo_128kbps_22050Hz;android.media.cts.DecoderTest#testDecodeWav;android.media.cts.DecoderTest#testCodecEarlyEOSH263;android.media.cts.SoundPoolOggTest#testSoundPoolOp;android.media.cts.DecoderTest#testCodecEarlyEOSH264;android.media.cts.MediaPlayerFlakyNetworkTest#test_S6P00002;android.media.cts.EnvReverbTest#test1_2Reverb;android.media.cts.AudioManagerTest#testSoundEffects;android.media.cts.ToneGeneratorTest#testAndroidTestCaseSetupProperly;android.media.cts.MediaCodecTest#testReconfigureWithoutSurface;android.media.cts.RingtoneManagerTest#testConstructors;android.media.cts.MediaCodecListTest#testGetCapabilities;android.media.cts.MediaDrmMockTest#testIsMimeTypeSupported;android.media.cts.DecoderTest#testDecodeMonoMp3;android.media.cts.DecoderTest#testCodecResetsH263WithoutSurface;android.media.cts.MediaScannerNotificationTest#testMediaScannerNotification;android.media.cts.VisualizerTest#testAndroidTestCaseSetupProperly;android.media.cts.VirtualizerTest#test0_0ConstructorAndRelease;android.media.cts.MediaPlayerTest#testLocalVideo_3gp_H263_176x144_56kbps_25fps_AAC_Mono_24kbps_22050Hz;android.media.cts.AudioTrackTest#testWriteShort;android.media.cts.AudioRecordTest#testAndroidTestCaseSetupProperly;android.media.cts.ExtractDecodeEditEncodeMuxTest#testExtractDecodeEditEncodeMux720p;android.media.cts.EqualizerTest#test3_0ControlStatusListener;android.media.cts.MediaDrmMockTest#testRestoreKeys;android.media.cts.MediaMuxerTest#testVideoAudio;android.media.cts.MediaPlayerTest#testLocalVideo_3gp_H263_176x144_56kbps_25fps_AAC_Mono_24kbps_11025Hz;android.media.cts.AudioTrackTest#testConstructorStereo8MusicStream;android.media.cts.MediaPlayerTest#testSetNextMediaPlayerWithRelease;android.media.cts.VisualizerTest#test1_0CaptureRates;android.media.cts.CameraProfileTest#testAndroidTestCaseSetupProperly;android.media.cts.EncodeVirtualDisplayWithCompositionTest#testAndroidTestCaseSetupProperly;android.media.cts.EncodeDecodeTest#testEncodeDecodeVideoFromBufferToSurfaceQVGA;android.media.cts.VirtualizerTest#test1_1Properties;android.media.cts.AudioManagerTest#testRouting;android.media.cts.EqualizerTest#test3_1EnableStatusListener;android.media.cts.PresetReverbTest#test3_1EnableStatusListener;android.media.cts.EnvReverbTest#test0_0ConstructorAndRelease;android.media.cts.MediaPlayerTest#testChangeSubtitleTrack;android.media.cts.JetPlayerTest#testClone;android.media.cts.AudioEffectTest#test1_5AuxiliaryOnMediaPlayer;android.media.cts.MediaPlayerTest#testSetNextMediaPlayerWithReset;android.media.cts.AudioEffectTest#test2_0SetEnabledGetEnabled;android.media.cts.VisualizerTest#test1_1CaptureSize;android.media.cts.AudioTrackTest#testPlaybackHeadPositionAfterInit;android.media.cts.EqualizerTest#test1_3Properties;android.media.cts.AudioTrackTest#testWriteByte;android.media.cts.VirtualizerTest#test2_1SetEnabledAfterRelease;android.media.cts.AudioTrackTest#testSetStereoVolumeMin;android.media.cts.MediaRecorderTest#testRecorderVideo;android.media.cts.ExtractDecodeEditEncodeMuxTest#testExtractDecodeEditEncodeMuxAudioVideo;android.media.cts.EqualizerTest#test2_0SetEnabledGetEnabled;android.media.cts.MediaPlayerTest#testSetNextMediaPlayer;android.media.cts.AudioTrackTest#testSetStereoVolumeMid;android.media.cts.VirtualizerTest#test1_0Strength;android.media.cts.EncodeDecodeTest#testAndroidTestCaseSetupProperly;android.media.cts.AudioTrackTest#testAudioTrackProperties;android.media.cts.AudioTrackTest#testSetPlaybackHeadPositionPaused;android.media.cts.SoundPoolAacTest#testLoadMore;android.media.cts.ExtractDecodeEditEncodeMuxTest#testExtractDecodeEditEncodeMuxQCIF;android.media.cts.EncodeVirtualDisplayTest#testAndroidTestCaseSetupProperly;android.media.cts.RingtoneManagerTest#testSetType;android.media.cts.MediaDrmMockTest#testMultipleSessions;android.media.cts.MediaPlayerFlakyNetworkTest#test_S0P0;android.media.cts.SoundPoolOggTest#testLoad;android.media.cts.PresetReverbTest#test0_0ConstructorAndRelease;android.media.cts.RingtoneManagerTest#testAccessMethods;android.media.cts.EnvReverbTest#test1_4DiffusionAndDensity;android.media.cts.MediaPlayerTest#testLocalVideo_3gp_H263_176x144_56kbps_12fps_AAC_Stereo_24kbps_22050Hz;android.media.cts.MediaPlayerTest#testLocalVideo_3gp_H263_176x144_300kbps_25fps_AAC_Stereo_24kbps_22050Hz;android.media.cts.MediaDrmMockTest#testGetProvisionRequest;android.media.cts.CamcorderProfileTest#testGetWithId;android.media.cts.AudioEffectTest#test1_2ConstructorUnknownType;android.media.cts.SoundPoolOggTest#testAndroidTestCaseSetupProperly;android.media.cts.AudioTrackTest#testWriteByte8bit;android.media.cts.PresetReverbTest#testAndroidTestCaseSetupProperly;android.media.cts.EncoderTest#testAACEncoders;android.media.cts.ExtractDecodeEditEncodeMuxTest#testExtractDecodeEditEncodeMuxAudio;android.media.cts.DecoderTest#testCodecBasicH263;android.media.cts.DecoderTest#testCodecBasicH264;android.media.cts.AudioTrackTest#testSetLoopPointsSuccess;android.media.cts.MediaDrmMockTest#testRemoveKeys;android.media.cts.FaceDetectorTest#testFindFaces;android.media.cts.MediaDrmMockTest#testGetKeyRequest;android.media.cts.MediaCodecListTest#testIsAVCBaselineProfileSupported;android.media.cts.AudioEffectTest#test3_4SetParameterIntArrayIntArray;android.media.cts.MediaCodecListTest#testIsH263BaselineProfileSupported;android.media.cts.EqualizerTest#test0_0ConstructorAndRelease;android.media.cts.EqualizerTest#test3_2ParameterChangedListener;android.media.cts.AudioTrackTest#testSetPlaybackRateZero;android.media.cts.MediaDrmMockTest#testGetSecureStops;android.media.cts.EnvReverbTest#test3_2ParameterChangedListener;android.media.cts.StreamingMediaPlayerTest#testHTTP_H263_AMR_Video2;android.media.cts.MediaDrmMockTest#testGetKeyRequestRelease;android.media.cts.StreamingMediaPlayerTest#testHTTP_H263_AMR_Video1;android.media.cts.EqualizerTest#testAndroidTestCaseSetupProperly;android.media.cts.ExtractDecodeEditEncodeMuxTest#testAndroidTestCaseSetupProperly;android.media.cts.MediaDrmMockTest#testNullSession;android.media.cts.PresetReverbTest#test1_1Properties;android.media.cts.BassBoostTest#test3_1EnableStatusListener;android.media.cts.AudioTrack_ListenerTest#testAudioTrackCallbackWithHandler;android.media.cts.VirtualizerTest#test3_2ParameterChangedListener;android.media.cts.MediaPlayerTest#testLocalVideo_MP4_H264_480x360_1350kbps_30fps_AAC_Stereo_128kbps_44110Hz;android.media.cts.BassBoostTest#test1_0Strength;android.media.cts.AudioTrackTest#testPlaybackHeadPositionAfterFlushAndPlay;android.media.cts.PresetReverbTest#test2_1SetEnabledAfterRelease;android.media.cts.AudioTrackTest#testWriteShortNegativeOffset;android.media.cts.DecoderTest#testCodecResetsMp3;android.media.cts.AudioTrackTest#testPlaybackHeadPositionAfterFlush;android.media.cts.MediaScannerTest#testCanonicalize;android.media.cts.MediaDrmMockTest#testMediaDrmConstructorFails;android.media.cts.PresetReverbTest#test2_0SetEnabledGetEnabled;android.media.cts.MediaDrmMockTest#testCryptoSession;android.media.cts.DecoderTest#testCodecResetsH263WithSurface;android.media.cts.AudioPreProcessingTest#test1_1NsCreateAndRelease;android.media.cts.DecodeEditEncodeTest#testAndroidTestCaseSetupProperly;android.media.cts.AudioEffectTest#test3_6SetParameterIntArrayByteArray;android.media.cts.AudioTrackTest#testPlaybackHeadPositionAfterStop;android.media.cts.AsyncPlayerTest#testAndroidTestCaseSetupProperly;android.media.cts.AudioPreProcessingTest#test3_2AgcSetEnabledGetEnabled;android.media.cts.MediaDrmMockTest#testGetKeyRequestOffline;android.media.cts.MediaDrmMockTest#testReleaseSecureStops;android.media.cts.MediaPlayerFlakyNetworkTest#test_S4P00001;android.media.cts.MediaDrmMockTest#testNullPropertyByteArray;android.media.cts.EqualizerTest#test1_2Presets;android.media.cts.EnvReverbTest#test1_5Properties;android.media.cts.CameraProfileTest#testGetImageEncodingQualityParameter;android.media.cts.VirtualizerTest#test3_0ControlStatusListener;android.media.cts.AudioTrackTest#testWriteByteNegativeOffset;android.media.cts.StreamingMediaPlayerTest#testPlayMp3StreamRedirect;android.media.cts.DecoderTest#testCodecEarlyEOSMpeg4;android.media.cts.EnvReverbTest#test3_0ControlStatusListener;android.media.cts.EncodeDecodeTest#testEncodeDecodeVideoFromBufferToSurfaceQCIF;android.media.cts.EncodeDecodeTest#testEncodeDecodeVideoFromBufferToSurface720p;android.media.cts.MediaDrmMockTest#testCryptoSessionEncrypt;android.media.cts.EqualizerTest#test1_0BandLevel;android.media.cts.EncodeVirtualDisplayWithCompositionTest#testMultipleVirtualDisplays;android.media.cts.AudioTrack_ListenerTest#testAudioTrackCallback;android.media.cts.DecoderTest#testCodecResetsVP9WithoutSurface;android.media.cts.DecodeEditEncodeTest#testVideoEdit720p;android.media.cts.AudioEffectTest#test1_0ConstructorFromType;android.media.cts.AudioTrackTest#testPlayStreamData;android.media.cts.MediaDrmMockTest#testCryptoSessionSign;android.media.cts.MediaDrmMockTest#testMediaDrmConstructor;android.media.cts.AudioTrackTest#testSetStereoVolumeMax;android.media.cts.MediaMuxerTest#testIllegalStateExceptions;android.media.cts.MediaCodecTest#testCreateInputSurfaceErrors;android.media.cts.AudioTrackTest#testConstructorMono16MusicStatic;android.media.cts.MediaDrmMockTest#testOpenCloseSession;android.media.cts.AudioManagerTest#testAndroidTestCaseSetupProperly;android.media.cts.DecoderTest#testEOSBehaviorMpeg4;android.media.cts.SoundPoolOggTest#testMultiSound;android.media.cts.AudioTrackTest#testConstructorMono8MusicStream;android.media.cts.MediaCodecListTest#testIsM4VSimpleProfileSupported;android.media.cts.VirtualizerTest#test1_2SetStrengthAfterRelease;android.media.cts.MediaDrmMockTest#testCryptoSessionVerify;android.media.cts.MediaMuxerTest#testVideoOnly;android.media.cts.AudioTrackTest#testWriteShortOffsetTooBig;android.media.cts.AudioManagerTest#testSetInvalidRingerMode;android.media.cts.MediaDrmMockTest#testIsMimeTypeNotSupported;android.media.cts.StreamingMediaPlayerTest#testPlayOggStreamNoLength;android.media.cts.MediaPlayerFlakyNetworkTest#test_S1P000005;android.media.cts.MediaRandomTest#testPlayerRandomAction;android.media.cts.EncoderTest#testAndroidTestCaseSetupProperly;android.media.cts.MediaPlayerTest#testRecordedVideoPlayback0;android.media.cts.AudioRecordTest#testAudioRecordProperties;android.media.cts.AudioTrackTest#testWriteByteOffsetTooBig;android.media.cts.PresetReverbTest#test3_0ControlStatusListener;android.media.cts.DecodeEditEncodeTest#testVideoEditQVGA;android.media.cts.MediaDrmMockTest#testMissingPropertyByteArray;android.media.cts.MediaPlayerTest#testRecordAndPlay;android.media.cts.PresentationSyncTest#testThroughput;android.media.cts.MediaPlayerTest#testVideoSurfaceResetting;android.media.cts.AudioTrack_ListenerTest#testAndroidTestCaseSetupProperly;android.media.cts.EncodeDecodeTest#testEncodeDecodeVideoFromBufferToBufferQCIF;android.media.cts.MediaPlayerTest#testRecordedVideoPlayback180;android.media.cts.MediaRecorderTest#testRecorderAudio;android.media.cts.EqualizerTest#test2_1SetEnabledAfterRelease;android.media.cts.AudioTrackTest#testPlaybackHeadPositionAfterPause;android.media.cts.MediaPlayerTest#testLocalVideo_3gp_H263_176x144_300kbps_25fps_AAC_Stereo_128kbps_11025Hz;android.media.cts.MediaRecorderTest#testSetMaxFileSize;android.media.cts.Vp8EncoderTest#testBasic;android.media.cts.AudioTrackTest#testPlaybackHeadPositionIncrease;android.media.cts.AudioTrackTest#testAndroidTestCaseSetupProperly;android.media.cts.MediaDrmMockTest#testEventNoSessionNoData;android.media.cts.MediaDrmMockTest#testByteArrayProperties;android.media.cts.DecoderTest#testCodecResetsM4a;android.media.cts.RingtoneTest#testAndroidTestCaseSetupProperly;android.media.cts.AudioPreProcessingTest#test3_1AgcCreateAndRelease;android.media.cts.AudioTrackTest#testSetPlaybackRateTwiceOutputSR;android.media.cts.PresetReverbTest#test1_0Presets;android.media.cts.StreamingMediaPlayerTest#testPlayOggStreamRedirect;android.media.cts.MediaCodecListTest#testAndroidTestCaseSetupProperly;android.media.cts.AudioTrackTest#testSetLoopPointsStartAfterEnd;android.media.cts.MediaRecorderTest#testOnInfoListener;android.media.cts.VirtualizerTest#test3_1EnableStatusListener;android.media.cts.DecoderTest#testCodecResetsH264WithoutSurface;android.media.cts.MediaPlayerTest#testLocalVideo_3gp_H263_176x144_300kbps_12fps_AAC_Stereo_24kbps_11025Hz;android.media.cts.MediaPlayerTest#testRecordedVideoPlayback270;android.media.cts.BassBoostTest#test3_0ControlStatusListener;android.media.cts.EncodeDecodeTest#testEncodeDecodeVideoFromSurfaceToSurface720p;android.media.cts.AudioTrackTest#testSetPlaybackRateUninit;android.media.cts.BassBoostTest#test2_1SetEnabledAfterRelease;android.media.cts.AudioEffectTest#test0_0QueryEffects;android.media.cts.VisualizerTest#test2_0PollingCapture;android.media.cts.MediaDrmMockTest#testStringProperties;android.media.cts.BassBoostTest#test0_0ConstructorAndRelease;android.media.cts.MediaScannerNotificationTest#testAndroidTestCaseSetupProperly;android.media.cts.AudioTrackTest#testConstructorMono16MusicStream;android.media.cts.MediaRecorderTest#testRecordingAudioInRawFormats;android.media.cts.AudioEffectTest#test3_1SetParameterIntInt;android.media.cts.DecoderTest#testEOSBehaviorVP8;android.media.cts.StreamingMediaPlayerTest#testHTTP_H264Base_AAC_Video2;android.media.cts.AudioEffectTest#test1_4InsertOnMediaPlayer;android.media.cts.StreamingMediaPlayerTest#testHTTP_H264Base_AAC_Video1;android.media.cts.DecoderTest#testCodecResetsVP9WithSurface;android.media.cts.JetPlayerTest#testLoadJetFromPath;android.media.cts.DecoderTest#testEOSBehaviorVP9;android.media.cts.MediaDrmMockTest#testProvideKeyResponse;android.media.cts.DecoderTest#testDecodeM4a;android.media.cts.AudioTrackTest#testWriteByteNegativeSize;android.media.cts.AudioEffectTest#test4_0setEnabledLowerPriority;android.media.cts.MediaPlayerTest#testLocalVideo_3gp_H263_176x144_300kbps_12fps_AAC_Mono_24kbps_22050Hz;android.media.cts.DecoderTest#testEOSBehaviorH264;android.media.cts.DecoderTest#testEOSBehaviorH263;android.media.cts.DecoderTest#testDecodeMonoOgg;android.media.cts.MediaPlayerTest#testLocalVideo_3gp_H263_176x144_56kbps_12fps_AAC_Stereo_24kbps_11025Hz;android.media.cts.MediaPlayerTest#testLocalVideo_3gp_H263_176x144_56kbps_25fps_AAC_Stereo_24kbps_22050Hz;android.media.cts.AudioTrackTest#testSetPlaybackHeadPositionTooFar;android.media.cts.AudioRecord_BufferSizeTest#testAndroidTestCaseSetupProperly;android.media.cts.MediaPlayerTest#testLocalVideo_3gp_H263_176x144_56kbps_12fps_AAC_Mono_24kbps_11025Hz;android.media.cts.MediaCodecListTest#testComponentInstantiation;android.media.cts.BassBoostTest#test1_2SetStrengthAfterRelease;android.media.cts.MediaPlayerTest#testLocalVideo_3gp_H263_176x144_300kbps_25fps_AAC_Stereo_24kbps_11025Hz;android.media.cts.AudioTrackTest#testSetLoopPointsEndTooFar;android.media.cts.MediaPlayerTest#testLocalVideo_3gp_H263_176x144_300kbps_25fps_AAC_Mono_24kbps_11025Hz;android.media.cts.MediaScannerTest#testMediaScanner;android.media.cts.RingtoneTest#testRingtone;android.media.cts.AudioEffectTest#test5_0Command;android.media.cts.DecoderTest#testDecodeMp3Smpb;android.media.cts.AudioTrackTest#testWriteShort8bit;android.media.cts.AudioEffectTest#test3_3SetParameterIntByteArray;android.media.cts.AudioEffectTest#test4_3EnableStatusListener;android.media.cts.MediaPlayerTest#testLocalVideo_3gp_H263_176x144_300kbps_25fps_AAC_Mono_24kbps_22050Hz;android.media.cts.JetPlayerTest#testAndroidTestCaseSetupProperly;android.media.cts.Vp8EncoderTest#testSyncFrame;android.media.cts.VirtualizerTest#test2_0SetEnabledGetEnabled;android.media.cts.MediaPlayerSurfaceTest#testSetSurface;android.media.cts.SoundPoolAacTest#testLoad;android.media.cts.AudioEffectTest#test3_5SetParameterIntArrayShortArray;android.media.cts.MediaDrmMockTest#testBadCryptoSession;android.media.cts.AudioTrackTest#testConstructorStereo16MusicStatic;android.media.cts.AudioPreProcessingTest#test1_2NsSetEnabledGetEnabled;android.media.cts.AudioEffectTest#test2_1SetEnabledAfterRelease;android.media.cts.AudioManagerTest#testAccessRingMode;android.media.cts.SoundPoolAacTest#testSoundPoolOp;android.media.cts.AudioEffectTest#test4_4ParameterChangedListener;android.media.cts.DecoderTest#testCodecBasicMpeg4;android.media.cts.AudioTrackTest#testSetPlaybackHeadPositionPlaying;android.media.cts.AudioRecordTest#testAudioRecordOP;android.media.cts.MediaScannerTest#testWildcardPaths;android.media.cts.AudioEffectTest#test3_8GetParameterAfterRelease;android.media.cts.FaceDetector_FaceTest#testFaceProperties;android.media.cts.MediaPlayerTest#testLocalVideo_3gp_H263_176x144_56kbps_25fps_AAC_Stereo_128kbps_22050Hz;android.media.cts.MediaDrmMockTest#testCryptoSessionDecrypt" />
-  <Entry uri="android.mediastress" exclude="android.mediastress.cts.H264R720pAacShortPlayerTest#testPlay00;android.mediastress.cts.Vp8R480x360ShortPlayerTest#testPlay10;android.mediastress.cts.Vp8R480x360ShortPlayerTest#testPlay11;android.mediastress.cts.H264R720pAacShortPlayerTest#testPlay07;android.mediastress.cts.H264R720pAacShortPlayerTest#testPlay08;android.mediastress.cts.H264R480pAacShortPlayerTest#testPlay10;android.mediastress.cts.H264R720pAacShortPlayerTest#testPlay05;android.mediastress.cts.H264R480pAacShortPlayerTest#testPlay11;android.mediastress.cts.H264R720pAacShortPlayerTest#testPlay06;android.mediastress.cts.H264R720pAacShortPlayerTest#testPlay03;android.mediastress.cts.H264R720pAacShortPlayerTest#testPlay04;android.mediastress.cts.MediaRecorderStressTest#testStressRecorder;android.mediastress.cts.H264R720pAacShortPlayerTest#testPlay01;android.mediastress.cts.H264R720pAacShortPlayerTest#testPlay02;android.mediastress.cts.H263QcifShortPlayerTest#testPlay07;android.mediastress.cts.MediaRecorderStressTest#testStressCamera;android.mediastress.cts.H263QcifShortPlayerTest#testPlay08;android.mediastress.cts.H263QcifShortPlayerTest#testPlay05;android.mediastress.cts.H263QcifShortPlayerTest#testPlay06;android.mediastress.cts.H263QcifShortPlayerTest#testPlay03;android.mediastress.cts.H263QcifShortPlayerTest#testPlay04;android.mediastress.cts.H263QcifShortPlayerTest#testPlay01;android.mediastress.cts.H263QcifShortPlayerTest#testPlay02;android.mediastress.cts.H264R720pAacLongPlayerTest#testPlay01;android.mediastress.cts.H264R720pAacLongPlayerTest#testPlay00;android.mediastress.cts.MediaRecorderStressTest#testStressCameraSwitchRecorder;android.mediastress.cts.H263QcifShortPlayerTest#testPlay09;android.mediastress.cts.H264R480x360AacShortPlayerTest#testPlay06;android.mediastress.cts.NativeMediaTest#test1080pPlay;android.mediastress.cts.H264R480x360AacShortPlayerTest#testPlay05;android.mediastress.cts.NativeMediaTest#testDefaultPlay;android.mediastress.cts.H264R480x360AacShortPlayerTest#testPlay08;android.mediastress.cts.H264R480x360AacShortPlayerTest#testPlay07;android.mediastress.cts.Vp8R480x360ShortPlayerTest#testPlay02;android.mediastress.cts.Vp8R480x360ShortPlayerTest#testPlay03;android.mediastress.cts.H264R480x360AacShortPlayerTest#testPlay09;android.mediastress.cts.Vp8R480x360ShortPlayerTest#testPlay00;android.mediastress.cts.Vp8R480x360ShortPlayerTest#testPlay01;android.mediastress.cts.Vp8R480x360ShortPlayerTest#testPlay06;android.mediastress.cts.H263QcifShortPlayerTest#testPlay00;android.mediastress.cts.H264R1080pAacShortPlayerTest#testPlay00;android.mediastress.cts.Vp8R480x360ShortPlayerTest#testPlay07;android.mediastress.cts.Vp8R480x360ShortPlayerTest#testPlay04;android.mediastress.cts.H264R480x360AacShortPlayerTest#testPlay00;android.mediastress.cts.Vp8R480x360ShortPlayerTest#testPlay05;android.mediastress.cts.H264R480x360AacShortPlayerTest#testPlay02;android.mediastress.cts.H264R480x360AacShortPlayerTest#testPlay01;android.mediastress.cts.Vp8R480x360ShortPlayerTest#testPlay08;android.mediastress.cts.H264R1080pAacShortPlayerTest#testPlay02;android.mediastress.cts.H264R480x360AacShortPlayerTest#testPlay04;android.mediastress.cts.Vp8R480x360ShortPlayerTest#testPlay09;android.mediastress.cts.H264R1080pAacShortPlayerTest#testPlay01;android.mediastress.cts.H264R480x360AacShortPlayerTest#testPlay03;android.mediastress.cts.H264R1080pAacRepeatedPlayerTest#testPlay00;android.mediastress.cts.H263QcifShortPlayerTest#testPlay13;android.mediastress.cts.H263QcifShortPlayerTest#testPlay12;android.mediastress.cts.H263QcifShortPlayerTest#testPlay15;android.mediastress.cts.H263QcifShortPlayerTest#testPlay14;android.mediastress.cts.H263QcifLongPlayerTest#testPlay00;android.mediastress.cts.H263QcifShortPlayerTest#testPlay17;android.mediastress.cts.H264R480pAacLongPlayerTest#testPlay00;android.mediastress.cts.H263QcifShortPlayerTest#testPlay16;android.mediastress.cts.H263QcifShortPlayerTest#testPlay19;android.mediastress.cts.H263QcifShortPlayerTest#testPlay18;android.mediastress.cts.H263QcifShortPlayerTest#testPlay10;android.mediastress.cts.H263QcifShortPlayerTest#testPlay11;android.mediastress.cts.H264R480x360AacShortPlayerTest#testPlay11;android.mediastress.cts.H264R480x360AacShortPlayerTest#testPlay10;android.mediastress.cts.NativeMediaTest#test720pPlay;android.mediastress.cts.H264R1080pAacLongPlayerTest#testPlay00;android.mediastress.cts.H264R720pAacShortPlayerTest#testPlay12;android.mediastress.cts.H264R480pAacShortPlayerTest#testPlay01;android.mediastress.cts.H264R480pAacShortPlayerTest#testPlay00;android.mediastress.cts.H263QcifShortPlayerTest#testPlay23;android.mediastress.cts.H264R720pAacShortPlayerTest#testPlay11;android.mediastress.cts.H264R720pAacShortPlayerTest#testPlay10;android.mediastress.cts.H263QcifShortPlayerTest#testPlay21;android.mediastress.cts.H263QcifShortPlayerTest#testPlay22;android.mediastress.cts.H263QcifShortPlayerTest#testPlay20;android.mediastress.cts.H264R480pAacShortPlayerTest#testPlay02;android.mediastress.cts.H264R480pAacShortPlayerTest#testPlay03;android.mediastress.cts.MediaRecorderStressTest#testStressRecordVideoAndPlayback;android.mediastress.cts.H264R720pAacShortPlayerTest#testPlay09;android.mediastress.cts.H264R480pAacShortPlayerTest#testPlay04;android.mediastress.cts.H264R480pAacShortPlayerTest#testPlay05;android.mediastress.cts.Vp8R480x360LongPlayerTest#testPlay00;android.mediastress.cts.H264R480pAacShortPlayerTest#testPlay06;android.mediastress.cts.H264R480pAacShortPlayerTest#testPlay07;android.mediastress.cts.H264R480pAacShortPlayerTest#testPlay08;android.mediastress.cts.H264R480pAacShortPlayerTest#testPlay09" />
-  <Entry uri="android.net" exclude="android.net.wifi.cts.ScanResultTest#testScanResultProperties;android.net.wifi.cts.WifiManagerTest#testWifiManagerActions;android.net.cts.UriTest#testStringUri;android.net.cts.UrlQuerySanitizer_IllegalCharacterValueSanitizerTest#testAndroidTestCaseSetupProperly;android.net.rtp.cts.AudioGroupTest#testAdd;android.net.rtp.cts.AudioGroupTest#testAndroidTestCaseSetupProperly;android.net.rtp.cts.AudioGroupTest#testRemove;android.net.cts.LocalSocketTest#testAccessors;android.net.http.cts.SslErrorTest#testConstructorIgnoresInvalidValues;android.net.cts.UriTest#testCompareTo;android.net.http.cts.SslErrorTest#testAddErrorIgnoresInvalidValues;android.net.cts.VpnServiceTest#testProtect_DatagramSocket;android.net.wifi.cts.WifiConfigurationTest#testAndroidTestCaseSetupProperly;android.net.rtp.cts.AudioCodecTest#testGetCodecs;android.net.http.cts.ApacheHttpClientTest#testExecute_withWifi;android.net.cts.DnsTest#testAndroidTestCaseSetupProperly;android.net.cts.VpnServiceTest#testAndroidTestCaseSetupProperly;android.net.wifi.cts.SupplicantStateTest#testAndroidTestCaseSetupProperly;android.net.cts.NetworkInfo_StateTest#testValues;android.net.cts.UriTest#testAndroidTestCaseSetupProperly;android.net.cts.LocalSocketTest#testLocalConnections;android.net.wifi.cts.WifiManager_WifiLockTest#testAndroidTestCaseSetupProperly;android.net.wifi.cts.WifiManagerTest#testWifiManagerNetWork;android.net.cts.ConnectivityManagerTest#testGetAllNetworkInfo;android.net.rtp.cts.AudioGroupTest#testTraffic;android.net.cts.Uri_BuilderTest#testBuilderOperations;android.net.cts.UriTest#testBuildUpon;android.net.cts.TrafficStatsTest#testAndroidTestCaseSetupProperly;android.net.cts.ProxyTest#testConstructor;android.net.rtp.cts.AudioCodecTest#testGetCodec;android.net.cts.DhcpInfoTest#testConstructor;android.net.cts.LocalSocketAddress_NamespaceTest#testValues;android.net.cts.ConnectivityManagerTest#testRequestRouteToHost;android.net.cts.ConnectivityManagerTest#testSetNetworkPreference;android.net.http.cts.SslCertificateTest#testState;android.net.cts.NetworkInfo_DetailedStateTest#testAndroidTestCaseSetupProperly;android.net.rtp.cts.AudioCodecTest#testConstants;android.net.http.cts.SslCertificateTest#testSslCertificate;android.net.cts.ProxyTest#testAccessProperties;android.net.cts.CredentialsTest#testCredentials;android.net.rtp.cts.AudioStreamTest#testDoubleRelease;android.net.cts.TrafficStatsTest#testValidMobileStats;android.net.http.cts.SslErrorTest#testGetUrlWithDeprecatedConstructor;android.net.cts.VpnServiceTest#testProtect_int;android.net.cts.ConnectivityManagerTest#testGetNetworkInfo;android.net.cts.MailToTest#testAndroidTestCaseSetupProperly;android.net.cts.LocalSocketTest#testAndroidTestCaseSetupProperly;android.net.cts.LocalSocketAddress_NamespaceTest#testAndroidTestCaseSetupProperly;android.net.cts.NetworkInfo_DetailedStateTest#testValueOf;android.net.cts.DhcpInfoTest#testAndroidTestCaseSetupProperly;android.net.cts.UriTest#testPathOperations;android.net.rtp.cts.AudioStreamTest#testAndroidTestCaseSetupProperly;android.net.http.cts.SslCertificate_DNameTest#testDName;android.net.wifi.cts.WifiManagerTest#testSignal;android.net.cts.UrlQuerySanitizerTest#testUrlQuerySanitizer;android.net.wifi.cts.WifiManager_WifiLockTest#testWifiLock;android.net.rtp.cts.AudioStreamTest#testSetCodec;android.net.cts.MailToTest#testParseMailToURI;android.net.cts.UriTest#testParcelling;android.net.cts.UrlQuerySanitizerTest#testAndroidTestCaseSetupProperly;android.net.wifi.cts.WifiConfigurationTest#testWifiConfiguration;android.net.cts.NetworkInfoTest#testAccessNetworkInfoProperties;android.net.cts.ConnectivityManagerTest#testTest;android.net.http.cts.SslErrorTest#testGetPrimaryError;android.net.cts.NetworkInfo_StateTest#testValueOf;android.net.cts.UriTest#testFromFile;android.net.cts.VpnServiceTest#testTunDevice;android.net.rtp.cts.AudioStreamTest#testSetDtmfType;android.net.cts.SSLCertificateSocketFactoryTest#testAndroidTestCaseSetupProperly;android.net.http.cts.SslCertificateTest#testConstructor;android.net.http.cts.SslErrorTest#testAddError;android.net.cts.UriTest#testNormalizeScheme;android.net.wifi.cts.WifiInfoTest#testAndroidTestCaseSetupProperly;android.net.cts.ConnectivityManagerTest#testStartUsingNetworkFeature;android.net.cts.UriTest#testHierarchicalUris;android.net.cts.DhcpInfoTest#testToString;android.net.rtp.cts.AudioStreamTest#testV6Stream;android.net.cts.LocalSocketAddressTest#testAndroidTestCaseSetupProperly;android.net.cts.UrlQuerySanitizer_IllegalCharacterValueSanitizerTest#testSanitize;android.net.rtp.cts.AudioStreamTest#testV4Stream;android.net.wifi.cts.ConcurrencyTest#testConcurrency;android.net.cts.LocalSocketAddress_NamespaceTest#testValueOf;android.net.wifi.cts.WifiManagerTest#testWifiWatchdog;android.net.cts.UriTest#testEqualsAndHashCode;android.net.cts.VpnServiceTest#testPrepare;android.net.cts.UriTest#testOpaqueUri;android.net.cts.UriTest#testQueryParameters;android.net.cts.TrafficStatsTest#testThreadStatsTag;android.net.wifi.cts.SupplicantStateTest#testIsValidState;android.net.http.cts.SslErrorTest#testHasError;android.net.cts.SSLCertificateSocketFactoryTest#testAccessProperties;android.net.cts.VpnServiceTest#testEstablish;android.net.ipv6.cts.PingTest#testAndroidTestCaseSetupProperly;android.net.cts.NetworkInfoTest#testAndroidTestCaseSetupProperly;android.net.cts.ConnectivityManagerTest#testAndroidTestCaseSetupProperly;android.net.cts.UriTest#testEncodeAndDecode;android.net.rtp.cts.AudioGroupTest#testClear;android.net.cts.NetworkInfo_StateTest#testAndroidTestCaseSetupProperly;android.net.cts.UrlQuerySanitizer_ParameterValuePairTest#testAndroidTestCaseSetupProperly;android.net.cts.ProxyTest#testAndroidTestCaseSetupProperly;android.net.cts.LocalServerSocketTest#testLocalServerSocket;android.net.cts.CredentialsTest#testAndroidTestCaseSetupProperly;android.net.rtp.cts.AudioCodecTest#testAndroidTestCaseSetupProperly;android.net.cts.UrlQuerySanitizer_ParameterValuePairTest#testConstructor;android.net.cts.NetworkInfo_DetailedStateTest#testValues;android.net.http.cts.SslErrorTest#testGetPrimaryErrorWithEmptySet;android.net.rtp.cts.AudioGroupTest#testSetMode;android.net.wifi.cts.WifiInfoTest#testWifiInfoProperties;android.net.wifi.cts.ConcurrencyTest#testAndroidTestCaseSetupProperly;android.net.http.cts.ApacheHttpClientTest#testAndroidTestCaseSetupProperly;android.net.wifi.cts.WifiManagerTest#testWifiManagerProperties;android.net.rtp.cts.AudioGroupTest#testDoubleClear;android.net.wifi.cts.WifiManagerTest#testAndroidTestCaseSetupProperly;android.net.cts.ConnectivityManagerTest#testGetActiveNetworkInfo;android.net.cts.LocalSocketAddressTest#testNewLocalSocketAddressWithDefaultNamespace;android.net.http.cts.SslErrorTest#testGetUrl;android.net.ipv6.cts.PingTest#testLoopbackPing;android.net.cts.TrafficStatsTest#testValidTotalStats;android.net.wifi.cts.WifiEnterpriseConfigTest#testAddEapNetwork;android.net.cts.VpnServiceTest#testProtect_Socket;android.net.wifi.cts.WifiEnterpriseConfigTest#testAndroidTestCaseSetupProperly;android.net.cts.ConnectivityManagerTest#testIsNetworkTypeValid;android.net.cts.ConnectivityManagerTest#testIsNetworkSupported;android.net.cts.LocalServerSocketTest#testAndroidTestCaseSetupProperly;android.net.wifi.cts.WifiEnterpriseConfigTest#testSettersAndGetters;android.net.http.cts.ApacheHttpClientTest#testExecute_withMobile" />
-  <Entry uri="android.provider" exclude="android.provider.cts.ContactsContract_CommonDataKinds_EventTest#testGetTypeLabel;android.provider.cts.MediaStore_Audio_Genres_MembersTest#testStoreAudioGenresMembersInternal;android.provider.cts.ContactsContract_DataTest#testDataInsert_updatesContactLastUpdatedTimestamp;android.provider.cts.ContactsContract_CommonDataKinds_EmailTest#testGetTypeLabel;android.provider.cts.Settings_NameValueTableTest#testPutString;android.provider.cts.CalendarTest#testCalendarEntityQuery;android.provider.cts.ContactsContract_DataUsageTest#testSingleDataUsageFeedback_incrementsCorrectDataItems;android.provider.cts.BrowserTest#testSendString;android.provider.cts.MediaStore_Video_MediaTest#testStoreVideoMediaInternal;android.provider.cts.UserDictionary_WordsTest#testAddWord_deprecated;android.provider.cts.MediaStoreIntentsTest#testAndroidTestCaseSetupProperly;android.provider.cts.ContactsContract_DeletedContacts#testQuerySinceTimestamp;android.provider.cts.BrowserTest#testRequestAllIcons;android.provider.cts.ContactsContract_CommonDataKinds_EmailTest#testAndroidTestCaseSetupProperly;android.provider.cts.CalendarTest#testReminders;android.provider.cts.MediaStore_Audio_ArtistsTest#testStoreAudioArtistsExternal;android.provider.cts.ContactsContractIntentsTest#testViewContactDir;android.provider.cts.CalendarTest#testBulkUpdate;android.provider.cts.ContactsContract_PhotoTest#testAddPhoto;android.provider.cts.Settings_NameValueTableTest#testAndroidTestCaseSetupProperly;android.provider.cts.ContactsProvider2_AccountRemovalTest#testAccountRemovalWithMergedContact_hasDeleteLogsForContacts;android.provider.cts.ContactsContract_PhotoTest#testAddEmptyPhoto;android.provider.cts.Settings_SecureTest#testGetPutFloat;android.provider.cts.MediaStore_Images_MediaTest#testGetContentUri;android.provider.cts.ContactsContract_DeletedContacts#testDelete_isUnsupported;android.provider.cts.CalendarTest#testCalendarCreationAndDeletion;android.provider.cts.BrowserTest#testBookmarksTable;android.provider.cts.Settings_SecureTest#testGetUriFor;android.provider.cts.ContactsContract_StatusUpdatesTest#testGetPresenceIconresourceId;android.provider.cts.MediaStore_Audio_Playlists_MembersTest#testStoreAudioPlaylistsMembersInternal;android.provider.cts.ContactsContract_CommonDataKinds_EventTest#testAndroidTestCaseSetupProperly;android.provider.cts.Contacts_PhonesTest#testGetDisplayLabel;android.provider.cts.ContactsContract_DeletedContacts#testInsert_isUnsupported;android.provider.cts.MediaStore_Audio_AlbumsTest#testStoreAudioAlbumsExternal;android.provider.cts.ContactsContract_DeletedContacts#testAndroidTestCaseSetupProperly;android.provider.cts.BrowserTest#testGetAllVisitedUrls;android.provider.cts.Contacts_ContactMethodsTest#testEncodeAndDecodeProtocol;android.provider.cts.ContactsContract_DeletedContacts#testQueryAll;android.provider.cts.MediaStore_Audio_MediaTest#testStoreAudioMediaInternal;android.provider.cts.ContactsContract_RawContactsTest#testRawContactPsuedoDelete_hasDeleteLogForContact;android.provider.cts.MediaStore_FilesTest#testAndroidTestCaseSetupProperly;android.provider.cts.MediaStore_Images_MediaTest#testStoreImagesMediaInternal;android.provider.cts.MediaStore_Audio_AlbumsTest#testAlbumArt;android.provider.cts.ContactsContract_ContactsTest#testLookupUri;android.provider.cts.MediaStoreIntentsTest#testPickVideoDir;android.provider.cts.MediaStore_Images_MediaTest#testInsertImageWithBitmap;android.provider.cts.MediaStoreIntentsTest#testViewAudioFile;android.provider.cts.MediaStore_Audio_Genres_MembersTest#testStoreAudioGenresMembersExternal;android.provider.cts.ContactsContract_CommonDataKinds_StructuredPostalTest#testAndroidTestCaseSetupProperly;android.provider.cts.CalendarTest#testInstanceSearch;android.provider.cts.VoicemailContractTest#testStatusTablePermissions;android.provider.cts.ContactsContract_CommonDataKinds_OrganizationTest#testAndroidTestCaseSetupProperly;android.provider.cts.SettingsTest#testAndroidTestCaseSetupProperly;android.provider.cts.MediaStore_Audio_PlaylistsTest#testStoreAudioPlaylistsInternal;android.provider.cts.ContactsContract_DumpFileProviderTest#testQuery_worksWithValidFileName;android.provider.cts.Settings_SecureTest#testAndroidTestCaseSetupProperly;android.provider.cts.MediaStore_Video_MediaTest#testAndroidTestCaseSetupProperly;android.provider.cts.BrowserTest#testAccessHistory;android.provider.cts.ContactsContract_DataTest#testContactablesFilterByPhonePrefix_returnsCorrectDataRows;android.provider.cts.MediaStore_Images_ThumbnailsTest#testStoreImagesMediaInternal;android.provider.cts.ContactsTest#testCallsTable;android.provider.cts.CalendarTest#testEventCreationAndDeletion;android.provider.cts.VoicemailContractTest#testVoicemailTablePermissions;android.provider.cts.CalendarTest#testEventsUid2445;android.provider.cts.MediaStore_VideoTest#testQuery;android.provider.cts.CalendarTest#testDefaultProjections;android.provider.cts.MediaStoreIntentsTest#testViewVideoDir;android.provider.cts.MediaStore_FilesTest#testGetContentUri;android.provider.cts.ContactsContract_ContactsTest#testInsert_isUnsupported;android.provider.cts.ContactsContract_CommonDataKinds_PhoneTest#testGetTypeLabel;android.provider.cts.VoicemailContractTest#testVoicemailsTable;android.provider.cts.ContactsContract_CommonDataKinds_RelationTest#testGetTypeLabel;android.provider.cts.Settings_SystemTest#testGetDefaultValues;android.provider.cts.ContactsContract_RawContactsTest#testAndroidTestCaseSetupProperly;android.provider.cts.MediaStoreTest#testGetMediaScannerUri;android.provider.cts.ContactsContract_RawContactsTest#testRawContactDelete_removesRecord;android.provider.cts.Settings_SecureTest#testGetPutString;android.provider.cts.ContactsTest#testGroupMembershipTable;android.provider.cts.MediaStore_Audio_MediaTest#testGetContentUri;android.provider.cts.CalendarTest#testFullRecurrenceUpdate;android.provider.cts.MediaStore_FilesTest#testCaseSensitivity;android.provider.cts.MediaStore_Audio_AlbumsTest#testAndroidTestCaseSetupProperly;android.provider.cts.MediaStore_Audio_ArtistsTest#testStoreAudioArtistsInternal;android.provider.cts.ContactsContract_ContactsTest#testContactDelete_hasDeleteLog;android.provider.cts.ContactsContract_DataUsageTest#testMultiIdDataUsageFeedback_incrementsCorrectDataItems;android.provider.cts.CalendarTest#testSyncOnlyInsertEnforcement;android.provider.cts.VoicemailContractTest#testDataColumnUpdate_throwsIllegalArgumentException;android.provider.cts.CalendarTest#testColorWriteRequirements;android.provider.cts.CalendarTest#testWhenByDayQuery;android.provider.cts.ContactsContract_StreamItemsTest#testAndroidTestCaseSetupProperly;android.provider.cts.ContactsContract_CommonDataKinds_ImTest#testAndroidTestCaseSetupProperly;android.provider.cts.MediaStore_AudioTest#testKeyFor;android.provider.cts.ContactsContract_ContactsTest#testAndroidTestCaseSetupProperly;android.provider.cts.MediaStore_Images_ThumbnailsTest#testQueryInternalThumbnails;android.provider.cts.ContactsContract_DumpFileProviderTest#testOpenFileDescriptor_throwsErrorWithIllegalFileName;android.provider.cts.CalendarTest#testEventColors;android.provider.cts.SettingsTest#testBluetoothDevicesTable;android.provider.cts.ContactsContract_RawContactsTest#testRawContactUpdate_updatesContactUpdatedTimestamp;android.provider.cts.ContactsContract_CommonDataKinds_RelationTest#testAndroidTestCaseSetupProperly;android.provider.cts.MediaStoreTest#testGetVersion;android.provider.cts.MediaStore_Audio_GenresTest#testGetContentUri;android.provider.cts.ContactsContract_DataTest#testDataDelete_updatesContactLastUpdatedTimestamp;android.provider.cts.ContactsContract_CommonDataKinds_SipAddressTest#testGetTypeLabel;android.provider.cts.BrowserTest#testSaveBookmark;android.provider.cts.ContactsProvider2_AccountRemovalTest#testAndroidTestCaseSetupProperly;android.provider.cts.MediaStore_Video_MediaTest#testGetContentUri;android.provider.cts.CalendarTest#testExtendedProperties;android.provider.cts.Settings_SystemTest#testAndroidTestCaseSetupProperly;android.provider.cts.CalendarTest#testNonAdapterRecurrenceExceptions;android.provider.cts.CalendarTest#testOutOfOrderRecurrenceExceptions;android.provider.cts.CalendarTest#testConversionToRecurring;android.provider.cts.MediaStore_Audio_Playlists_MembersTest#testStoreAudioPlaylistsMembersExternal;android.provider.cts.CalendarTest#testMultiRuleRecurrence;android.provider.cts.MediaStoreIntentsTest#testPickAudioDir;android.provider.cts.MediaStore_Audio_GenresTest#testStoreAudioGenresExternal;android.provider.cts.MediaStoreIntentsTest#testViewVideoFile;android.provider.cts.ContactsProvider2_AccountRemovalTest#testAccountRemoval_deletesContacts;android.provider.cts.Contacts_ContactMethodsTest#testAndroidTestCaseSetupProperly;android.provider.cts.ContactsContract_GroupMembershipTest#testAddGroupMembershipWithGroupRowId;android.provider.cts.TelephonyProviderTest#testOpeningAnyFile;android.provider.cts.MediaStore_Audio_GenresTest#testGetContentUriForAudioId;android.provider.cts.ContactsContract_CommonDataKinds_PhoneTest#testAndroidTestCaseSetupProperly;android.provider.cts.Contacts_PeopleTest#testMarkAsContacted;android.provider.cts.MediaStore_FilesTest#testAccess;android.provider.cts.ContactsContract_CommonDataKinds_ImTest#testGetTypeLabel;android.provider.cts.SearchRecentSuggestionsTest#testSuggestionsTable;android.provider.cts.CalendarTest#testAttendees;android.provider.cts.SettingsTest#testAccessNonTable;android.provider.cts.MediaStoreIntentsTest#testPickImageDir;android.provider.cts.BrowserTest#testSearchesTable;android.provider.cts.Contacts_SettingsTest#testAccessSetting;android.provider.cts.ContactsContract_StreamItemPhotosTest#testContentPhotoUri;android.provider.cts.ContactsContract_DataTest#testGetLookupUriByDisplayName;android.provider.cts.ContactsContract_StatusUpdatesTest#testInsertStatus;android.provider.cts.MediaStore_Video_ThumbnailsTest#testGetContentUri;android.provider.cts.MediaStore_Audio_GenresTest#testStoreAudioGenresInternal;android.provider.cts.MediaStore_Images_MediaTest#testInsertImageWithImagePath;android.provider.cts.CalendarTest#testForwardRecurrenceExceptions;android.provider.cts.Settings_SecureTest#testUnknownSourcesOffByDefault;android.provider.cts.CalendarTest#testBadRequests;android.provider.cts.ContactsTest#testSettingsTable;android.provider.cts.VoicemailContractTest#testInsert_doesNotUpdateDataColumn;android.provider.cts.ContactsContract_RawContactsTest#testRawContactCreate_updatesContactUpdatedTimestamp;android.provider.cts.MediaStoreIntentsTest#testViewImageDir;android.provider.cts.ContactsContract_ContactsTest#testContactDelete_removesContactRecord;android.provider.cts.MediaStore_Images_ThumbnailsTest#testQueryExternalMiniThumbnails;android.provider.cts.ContactsContract_ContactsTest#testContactUpdate_updatesContactUpdatedTimestamp;android.provider.cts.Settings_SettingNotFoundExceptionTest#testAndroidTestCaseSetupProperly;android.provider.cts.ContactsContract_RawContactsTest#testGetLookupUriByDisplayName;android.provider.cts.BrowserTest#testAccessSearches;android.provider.cts.ContactsContract_CommonDataKinds_SipAddressTest#testAndroidTestCaseSetupProperly;android.provider.cts.ContactsContract_GroupMembershipTest#testAddGroupMembershipWithUnknownGroupSourceId;android.provider.cts.MediaStore_Audio_MediaTest#testStoreAudioMediaExternal;android.provider.cts.MediaStore_Audio_PlaylistsTest#testGetContentUri;android.provider.cts.ContactsTest#testGroupsTable;android.provider.cts.MediaStore_Audio_AlbumsTest#testGetContentUri;android.provider.cts.Settings_SystemTest#testGetUriFor;android.provider.cts.ContactsContract_StreamItemPhotosTest#testContentDirectoryUri;android.provider.cts.SearchRecentSuggestionsTest#testSearchRecentSuggestions;android.provider.cts.Contacts_ContactMethodsTest#testAddPostalLocation;android.provider.cts.MediaStore_Audio_Artists_AlbumsTest#testGetContentUri;android.provider.cts.SearchRecentSuggestionsTest#testConstructor;android.provider.cts.ContactsContract_ContactsTest#testMarkAsContacted;android.provider.cts.ContactsTest#testPeopleTable;android.provider.cts.CalendarTest#testCalendarColors;android.provider.cts.CalendarTest#testCalendarIsPrimary;android.provider.cts.ContactsContract_RawContactsTest#testRawContactDelete_hasDeleteLogForContact;android.provider.cts.Settings_SystemTest#testSystemSettings;android.provider.cts.CalendarTest#testRecurrence;android.provider.cts.ContactsContract_GroupMembershipTest#testAddGroupMembershipWithGroupSourceId;android.provider.cts.MediaStore_Audio_Genres_MembersTest#testGetContentUri;android.provider.cts.VoicemailContractTest#testStatusTable;android.provider.cts.ContactsContract_DataTest#testContactablesFilterByFirstName_returnsCorrectDataRows;android.provider.cts.Settings_NameValueTableTest#testGetUriFor;android.provider.cts.ContactsContract_DumpFileProviderTest#testQuery_throwsErrorWithIllegalFileName;android.provider.cts.ContactsTest#testContactMethodsTable;android.provider.cts.ContactsContractIntentsTest#testPickContactDir;android.provider.cts.MediaStore_Audio_AlbumsTest#testStoreAudioAlbumsInternal;android.provider.cts.Contacts_PeopleTest#testAddToGroup;android.provider.cts.ContactsContract_DataTest#testContactablesFilterByEmailPrefix_returnsCorrectDataRows;android.provider.cts.ContactsContract_StatusUpdatesTest#testGetPresencePrecedence;android.provider.cts.BrowserTest#testUpdateVisitedHistory;android.provider.cts.SettingsTest#testSecureTable;android.provider.cts.ContactsContract_StreamItemsTest#testContentUri;android.provider.cts.MediaStore_Audio_Artists_AlbumsTest#testStoreAudioArtistsAlbumsInternal;android.provider.cts.MediaStore_Video_ThumbnailsTest#testGetThumbnail;android.provider.cts.ContactsContractIntentsTest#testGetContentContactDir;android.provider.cts.SettingsTest#testSystemTable;android.provider.cts.CalendarTest#testEventUpdateAsApp;android.provider.cts.MediaStore_Images_MediaTest#testStoreImagesMediaExternal;android.provider.cts.CalendarTest#testEventsEntityQuery;android.provider.cts.ContactsContractIntentsTest#testAndroidTestCaseSetupProperly;android.provider.cts.CalendarTest#testSyncState;android.provider.cts.MediaStore_Video_ThumbnailsTest#testAndroidTestCaseSetupProperly;android.provider.cts.ContactsContract_DataTest#testGetLookupUriBySourceId;android.provider.cts.UserDictionary_WordsTest#testAndroidTestCaseSetupProperly;android.provider.cts.ContactsTest#testExtensionsTable;android.provider.cts.ContactsContract_DataTest#testContactablesUri;android.provider.cts.ContactsContract_CommonDataKinds_ImTest#testGetProtocolLabel;android.provider.cts.Settings_SettingNotFoundExceptionTest#testConstructor;android.provider.cts.CalendarTest#testEventsIsOrganizer;android.provider.cts.ContactsContract_StreamItemsTest#testContentDirectoryUri;android.provider.cts.Contacts_PeopleTest#testAccessPhotoData;android.provider.cts.UserDictionary_WordsTest#testAddWord;android.provider.cts.CalendarTest#testSingleRecurrenceExceptions;android.provider.cts.BrowserTest#testGetAllBookmarks;android.provider.cts.ContactsContract_RawContactsTest#testRawContactDelete_setsDeleteFlag;android.provider.cts.MediaStoreIntentsTest#testViewImageFile;android.provider.cts.Settings_SecureTest#testGetPutLong;android.provider.cts.ContactsContract_DataTest#testContactablesFilterByLastName_returnsCorrectDataRows;android.provider.cts.SearchRecentSuggestionsTest#testAndroidTestCaseSetupProperly;android.provider.cts.Contacts_PhonesTest#testGetDisplayLabelCharSequenceArray;android.provider.cts.SettingsTest#testUserDictionarySettingsExists;android.provider.cts.Contacts_OrganizationsTest#testGetDisplayLabel;android.provider.cts.Settings_SecureTest#testGetDefaultValues;android.provider.cts.ContactsContract_ContactsTest#testContactDelete_marksRawContactsForDeletion;android.provider.cts.ContactsTest#testPhotosTable;android.provider.cts.ContactsContract_ContactsTest#testContentUri;android.provider.cts.MediaStore_Audio_Artists_AlbumsTest#testStoreAudioArtistsAlbumsExternal;android.provider.cts.Contacts_PhonesTest#testAndroidTestCaseSetupProperly;android.provider.cts.ContactsProvider2_AccountRemovalTest#testAccountRemovalWithMergedContact_doesNotDeleteContactAndTimestampUpdated;android.provider.cts.ContactsTest#testOrganizationsTable;android.provider.cts.MediaStore_Audio_Playlists_MembersTest#testGetContentUri;android.provider.cts.MediaStore_Audio_PlaylistsTest#testStoreAudioPlaylistsExternal;android.provider.cts.Contacts_OrganizationsTest#testAndroidTestCaseSetupProperly;android.provider.cts.ContactsTest#testPhonesTable;android.provider.cts.Settings_SecureTest#testGetPutInt;android.provider.cts.ContactsContract_StatusUpdatesTest#testAndroidTestCaseSetupProperly;android.provider.cts.MediaStore_Audio_MediaTest#testGetContentUriForPath;android.provider.cts.CalendarTest#testCalendarUpdateAsApp;android.provider.cts.ContactsContract_DeletedContacts#testQueryByContactId;android.provider.cts.ContactsProvider2_AccountRemovalTest#testAccountRemoval_hasDeleteLogsForContacts;android.provider.cts.ContactsContract_StreamItemPhotosTest#testAndroidTestCaseSetupProperly;android.provider.cts.MediaStore_Audio_ArtistsTest#testGetContentUri;android.provider.cts.ContactsContract_DumpFileProviderTest#testAndroidTestCaseSetupProperly;android.provider.cts.ContactsContract_DataTest#testDataUpdate_updatesContactLastUpdatedTimestamp;android.provider.cts.ContactsProvider2_AccountRemovalTest#testAccountRemovalWithMergedContact_deletesContacts;android.provider.cts.ContactsContract_RawContactsTest#testGetLookupUriBySourceId;android.provider.cts.MediaStore_Images_ThumbnailsTest#testGetContentUri;android.provider.cts.ContactsContract_DumpFileProviderTest#testOpenFileDescriptor_worksWithValidFileName;android.provider.cts.ContactsContract_CommonDataKinds_StructuredPostalTest#testGetTypeLabel;android.provider.cts.ContactsContract_DataUsageTest#testAndroidTestCaseSetupProperly;android.provider.cts.Contacts_ContactMethodsTest#test;android.provider.cts.MediaStore_Video_MediaTest#testStoreVideoMediaExternal;android.provider.cts.ContactsContract_CommonDataKinds_OrganizationTest#testGetTypeLabel;android.provider.cts.MediaStore_Images_ThumbnailsTest#testStoreImagesMediaExternal;android.provider.cts.ContactsContract_DataTest#testContactablesFilter_doesNotExist_returnsCorrectDataRows;android.provider.cts.ContactsContract_DeletedContacts#testQuery_returnsProperColumns" />
-  <Entry uri="android.security" exclude="android.security.cts.KeystoreExploitTest#testAndroidTestCaseSetupProperly;android.security.cts.CharDeviceTest#testExynosKernelMemoryRead;android.security.cts.VoldExploitTest#testAndroidTestCaseSetupProperly;android.security.cts.LoadEffectLibraryTest#testLoadLibrary;android.security.cts.BrowserTest#testAndroidTestCaseSetupProperly;android.security.cts.LinuxRngTest#testDevUrandomMajorMinor;android.security.cts.ServicePermissionsTest#testDumpProtected;android.security.cts.BannedFilesTest#testNoSetuidTcpdump;android.security.cts.SqliteJournalLeakTest#testShm;android.security.cts.LinuxRngTest#testDevRandomMajorMinor;android.security.cts.ClonedSecureRandomTest#testCheckForDuplicateOutput;android.security.cts.BrowserTest#testBrowserPrivateDataAccess;android.security.cts.BrowserTest#testTabExhaustion;android.security.cts.KeystoreExploitTest#testKeystoreCrash;android.security.cts.SqliteJournalLeakTest#testJournal;android.security.cts.BannedFilesTest#testNoCmdClient;android.security.cts.BannedFilesTest#testNoSetuidIp;android.security.cts.BannedFilesTest#testNoSyncAgent;android.security.cts.BannedFilesTest#testNoRootCmdSocket;android.security.cts.ListeningPortsTest#testNoListeningLoopbackTcp6Ports;android.security.cts.KernelSettingsTest#testKptrRestrict;android.security.cts.AslrTest#testVaRandomize;android.security.cts.KernelSettingsTest#testMmapMinAddr;android.security.cts.CertificateTest#testBlockCertificates;android.security.cts.BrowserTest#testTabReuse;android.security.cts.KernelSettingsTest#testSELinuxEnforcing;android.security.cts.ListeningPortsTest#testNoListeningLoopbackUdp6Ports;android.security.cts.NativeCodeTest#testPerfEvent;android.security.cts.KernelSettingsTest#testSetuidDumpable;android.security.cts.PackageSignatureTest#testAndroidTestCaseSetupProperly;android.security.cts.ServicePermissionsTest#testAndroidTestCaseSetupProperly;android.security.cts.CertificateTest#testCertificates;android.security.cts.KernelSettingsTest#testNoConfigGz;android.security.cts.KernelSettingsTest#testDmesgRestrict;android.security.cts.ListeningPortsTest#testAndroidTestCaseSetupProperly;android.security.cts.SqliteJournalLeakTest#testAndroidTestCaseSetupProperly;android.security.cts.ListeningPortsTest#testNoRemotelyAccessibleListeningTcp6Ports;android.security.cts.ListeningPortsTest#testNoListeningLoopbackTcpPorts;android.security.cts.ClonedSecureRandomTest#testAndroidTestCaseSetupProperly;android.security.cts.VoldExploitTest#testTryCommandInjection;android.security.cts.VoldExploitTest#testZergRushCrash;android.security.cts.AslrTest#testOneExecutableIsPie;android.security.cts.VoldExploitTest#testTryToCrashVold;android.security.cts.ListeningPortsTest#testNoListeningLoopbackUdpPorts;android.security.cts.CertificateTest#testAndroidTestCaseSetupProperly;android.security.cts.SqliteJournalLeakTest#testWal;android.security.cts.ListeningPortsTest#testNoRemotelyAccessibleListeningTcpPorts;android.security.cts.CharDeviceTest#testExynosRootingVuln" />
-  <Entry uri="android.webkit" exclude="android.webkit.cts.WebViewTest#testDocumentHasImages;android.webkit.cts.WebViewTest#testScrollBarOverlay;android.webkit.cts.WebViewTest#testGoBackAndForward;android.webkit.cts.WebViewTest#testGetContentHeight;android.webkit.cts.WebChromeClientTest#testOnJsConfirm;android.webkit.cts.WebChromeClientTest#testOnProgressChanged;android.webkit.cts.WebViewTest#testAddJavascriptInterfaceNullObject;android.webkit.cts.WebViewTest#testConstructor;android.webkit.cts.WebViewTest#testInvokeZoomPicker;android.webkit.cts.WebSettingsTest#testAccessMinimumLogicalFontSize;android.webkit.cts.WebViewStartupTest#testCookieManagerBlockingUiThread;android.webkit.cts.WebViewTest#testInternals;android.webkit.cts.WebViewClientTest#testShouldOverrideUrlLoading;android.webkit.cts.GeolocationTest#testSimpleGeolocationRequestAcceptOnce;android.webkit.cts.WebSettingsTest#testDatabaseDisabled;android.webkit.cts.WebView_WebViewTransportTest#testAccessWebView;android.webkit.cts.WebSettingsTest#testAccessJavaScriptCanOpenWindowsAutomatically;android.webkit.cts.WebSettingsTest#testAppCacheEnabled;android.webkit.cts.WebSettingsTest#testAccessUserAgentString;android.webkit.cts.WebViewTest#testClearHistory;android.webkit.cts.WebSettingsTest#testAccessSerifFontFamily;android.webkit.cts.WebSettingsTest#testAccessLayoutAlgorithm;android.webkit.cts.WebSettingsTest#testAccessFantasyFontFamily;android.webkit.cts.WebViewTest#testAddJavascriptInterface;android.webkit.cts.WebSettingsTest#testAccessCacheMode;android.webkit.cts.WebViewTest#testDebugDump;android.webkit.cts.WebViewTest#testSslErrorProceedResponseNotReusedForDifferentHost;android.webkit.cts.WebSettingsTest#testLocalImageLoads;android.webkit.cts.WebViewTest#testSslErrorProceedResponseReusedForSameHost;android.webkit.cts.HttpAuthHandlerTest#testUseHttpAuthUsernamePassword;android.webkit.cts.WebViewTest#testSetLayoutParams;android.webkit.cts.WebViewTest#testAppInjectedXRequestedWithHeaderIsNotOverwritten;android.webkit.cts.WebSettingsTest#testAccessUseDoubleTree;android.webkit.cts.WebViewTest#testOnReceivedSslErrorCancel;android.webkit.cts.URLUtilTest#testIsHttpUrl;android.webkit.cts.DateSorterTest#testConstants;android.webkit.cts.WebSettingsTest#testAccessFixedFontFamily;android.webkit.cts.WebSettingsTest#testSetRenderPriority;android.webkit.cts.WebViewTest#testRemoveJavascriptInterface;android.webkit.cts.WebViewTest#testAndroidAssetAnchor;android.webkit.cts.WebViewTest#testOnReceivedSslError;android.webkit.cts.CookieTest#testEmptyValue;android.webkit.cts.WebViewTest#testPauseResumeTimers;android.webkit.cts.URLUtilTest#testIsContentUrl;android.webkit.cts.WebChromeClientTest#testBlockWindowsAsync;android.webkit.cts.WebViewTest#testGetVisibleTitleHeight;android.webkit.cts.WebBackForwardListTest#testClone;android.webkit.cts.WebSettingsTest#testAccessDefaultTextEncodingName;android.webkit.cts.URLUtilTest#testGuessUrl;android.webkit.cts.MimeTypeMapTest#testAndroidTestCaseSetupProperly;android.webkit.cts.WebChromeClientTest#testOnReceivedIcon;android.webkit.cts.CookieTest#testAndroidTestCaseSetupProperly;android.webkit.cts.CookieManagerTest#testRemoveCookies;android.webkit.cts.WebSettingsTest#testAccessPluginsPath;android.webkit.cts.WebSettingsTest#testAccessAllowFileAccess;android.webkit.cts.WebSettingsTest#testAccessSupportMultipleWindows;android.webkit.cts.WebViewTest#testAppCanInjectHeadersViaImmutableMap;android.webkit.cts.WebViewTest#testSecureSiteSetsCertificate;android.webkit.cts.WebViewTest#testSetWebViewClient;android.webkit.cts.WebViewTest#testSetScrollBarStyle;android.webkit.cts.CookieTest#testDomain;android.webkit.cts.WebViewTest#testZoom;android.webkit.cts.URLUtilTest#testIsDataUrl;android.webkit.cts.CookieManagerTest#testAcceptCookie;android.webkit.cts.WebChromeClientTest#testOnReceivedTitle;android.webkit.cts.URLUtilTest#testIsFileUrl;android.webkit.cts.WebSettingsTest#testAccessJavaScriptEnabled;android.webkit.cts.URLUtilTest#testIsNetworkUrl;android.webkit.cts.WebViewTest#testFindAddress;android.webkit.cts.WebViewTest#testSetNetworkAvailable;android.webkit.cts.WebViewTest#testClearSslPreferences;android.webkit.cts.URLUtilTest#testIsHttpsUrl;android.webkit.cts.MimeTypeMapTest#testGetFileExtensionFromUrl;android.webkit.cts.WebViewTest#testGetOriginalUrl;android.webkit.cts.WebChromeClientTest#testBlockWindowsSync;android.webkit.cts.WebViewTest#testLoadData;android.webkit.cts.WebViewTest#testInsecureSiteClearsCertificate;android.webkit.cts.WebBackForwardListTest#testGetCurrentItem;android.webkit.cts.URLUtilTest#testStripAnchor;android.webkit.cts.URLUtilTest#testGuessFileName;android.webkit.cts.URLUtilTest#testAndroidTestCaseSetupProperly;android.webkit.cts.WebViewTest#testEvaluateJavascript;android.webkit.cts.DateSorterTest#testConstructor;android.webkit.cts.WebViewTest#testPageScroll;android.webkit.cts.WebSettingsTest#testIframesWhenAccessFromFileURLsEnabled;android.webkit.cts.WebViewTest#testFlingScroll;android.webkit.cts.WebSettingsTest#testXHRWhenAccessFromFileURLsEnabled;android.webkit.cts.WebChromeClientTest#testOnJsPrompt;android.webkit.cts.WebSettingsTest#testAccessSupportZoom;android.webkit.cts.WebSettingsTest#testLoadsImagesAutomatically;android.webkit.cts.URLUtilTest#testIsValidUrl;android.webkit.cts.WebViewTest#testRequestFocusNodeHref;android.webkit.cts.WebViewTest#testLoadDataWithBaseUrl;android.webkit.cts.WebChromeClientTest#testOnJsAlert;android.webkit.cts.WebSettingsTest#testAccessSansSerifFontFamily;android.webkit.cts.CookieManagerTest#testCookieManager;android.webkit.cts.WebViewTest#testSetMapTrackballToArrowKeys;android.webkit.cts.WebViewTest#testCreatingWebViewCreatesCookieSyncManager;android.webkit.cts.DateSorterTest#testGetIndex;android.webkit.cts.GeolocationTest#testGeolocationPermissions;android.webkit.cts.WebChromeClientTest#testOnJsBeforeUnload;android.webkit.cts.CookieManagerTest#testClone;android.webkit.cts.CookieManagerTest#testGetInstance;android.webkit.cts.WebViewTest#testGetZoomControls;android.webkit.cts.CookieTest#testSubDomain;android.webkit.cts.WebSettingsTest#testUserAgentString_default;android.webkit.cts.MimeTypeMapTest#testGetMimeTypeFromExtension;android.webkit.cts.WebSettingsTest#testBlockNetworkImage;android.webkit.cts.WebViewTest#testPlatformNotifications;android.webkit.cts.URLUtilTest#testIsAboutUrl;android.webkit.cts.WebViewTest#testSetPictureListener;android.webkit.cts.MimeTypeMapTest#testHasMimeType;android.webkit.cts.WebViewTest#testOnReceivedSslErrorProceed;android.webkit.cts.DateSorterTest#testGetLabel;android.webkit.cts.GeolocationTest#testSimpleGeolocationRequestAcceptAlways;android.webkit.cts.URLUtilTest#testDecode;android.webkit.cts.HttpAuthHandlerTest#testProceed;android.webkit.cts.WebSettingsTest#testSetNeedInitialFocus;android.webkit.cts.WebSettingsTest#testIframesWhenAccessFromFileURLsDisabled;android.webkit.cts.WebSettingsTest#testAccessCursiveFontFamily;android.webkit.cts.WebViewTest#testFindAll;android.webkit.cts.WebViewTest#testStopLoading;android.webkit.cts.DateSorterTest#testAndroidTestCaseSetupProperly;android.webkit.cts.WebSettingsTest#testAccessDefaultFixedFontSize;android.webkit.cts.CookieManagerTest#testb3167208;android.webkit.cts.WebSettingsTest#testAccessMinimumFontSize;android.webkit.cts.WebSettingsTest#testAccessUseWideViewPort;android.webkit.cts.WebSettingsTest#testAccessSaveFormData;android.webkit.cts.WebViewTest#testRequestChildRectangleOnScreen;android.webkit.cts.URLUtilTest#testIsJavaScriptUrl;android.webkit.cts.WebViewTest#testFindNext;android.webkit.cts.MimeTypeMapTest#testHasExtension;android.webkit.cts.WebViewTest#testSetDownloadListener;android.webkit.cts.WebSettingsTest#testXHRWhenAccessFromFileURLsDisabled;android.webkit.cts.WebViewTest#testDestroy;android.webkit.cts.MimeTypeMapTest#testGetSingleton;android.webkit.cts.WebViewTest#testAndroidAssetQueryParam;android.webkit.cts.WebViewTest#testAccessPluginList;android.webkit.cts.CookieTest#testPath;android.webkit.cts.WebViewTest#testAccessHttpAuthUsernamePassword;android.webkit.cts.WebViewTest#testUseRemovedJavascriptInterface;android.webkit.cts.WebSettingsTest#testAccessTextSize;android.webkit.cts.URLUtilTest#testIsAssetUrl;android.webkit.cts.CookieTest#testInvalidDomain;android.webkit.cts.CookieSyncManagerTest#testCookieSyncManager;android.webkit.cts.URLUtilTest#testComposeSearchUrl;android.webkit.cts.WebChromeClientTest#testWindows;android.webkit.cts.WebViewTest#testRequestImageRef;android.webkit.cts.WebSettingsTest#testAccessDefaultFontSize;android.webkit.cts.WebViewClientTest#testShouldOverrideKeyEvent;android.webkit.cts.WebHistoryItemTest#testWebHistoryItem;android.webkit.cts.WebSettingsTest#testAccessBuiltInZoomControls;android.webkit.cts.WebSettingsTest#testAppCacheDisabled;android.webkit.cts.WebViewTest#testSetWebChromeClient;android.webkit.cts.WebViewTest#testGetHitTestResult;android.webkit.cts.WebSettingsTest#testAccessStandardFontFamily;android.webkit.cts.GeolocationTest#testSimpleGeolocationRequestReject;android.webkit.cts.WebSettingsTest#testBlockNetworkLoads;android.webkit.cts.DateSorterTest#testGetBoundary;android.webkit.cts.WebViewTest#testCapturePicture;android.webkit.cts.WebSettingsTest#testAccessPluginsEnabled;android.webkit.cts.WebViewTest#testSaveAndRestoreState;android.webkit.cts.WebViewTest#testLoadUrl;android.webkit.cts.HttpAuthHandlerTest#testCancel;android.webkit.cts.URLUtilTest#testIsCookielessProxyUrl;android.webkit.cts.WebViewTest#testGetFavicon;android.webkit.cts.MimeTypeMapTest#testGetExtensionFromMimeType" />
-  <Entry uri="android.display"/>
-</TestPlan>
diff --git a/tests/plans/CTS-stable.xml b/tests/plans/CTS-stable.xml
deleted file mode 100644
index 5dba751..0000000
--- a/tests/plans/CTS-stable.xml
+++ /dev/null
@@ -1,96 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<TestPlan version="1.0">
-  <Entry uri="android.aadb"/>
-  <Entry uri="android.acceleration"/>
-  <Entry uri="android.accessibility"/>
-  <Entry uri="android.accessibilityservice"/>
-  <Entry uri="android.accounts"/>
-  <Entry uri="android.admin"/>
-  <Entry uri="android.animation"/>
-  <Entry uri="android.app" exclude="android.app.cts.ActivityManagerTest#testIsRunningInTestHarness;android.app.cts.AlertDialogTest#testAlertDialogCancelable;android.app.cts.ExpandableListActivityTest#testCallback" />
-  <Entry uri="android.bionic"/>
-  <Entry uri="android.bluetooth"/>
-  <Entry uri="android.calendarcommon"/>
-  <Entry uri="android.content"/>
-  <Entry uri="android.core.tests.libcore.package.com"/>
-  <Entry uri="android.core.tests.libcore.package.conscrypt"/>
-  <Entry uri="android.core.tests.libcore.package.dalvik"/>
-  <Entry uri="android.core.tests.libcore.package.harmony_annotation"/>
-  <Entry uri="android.core.tests.libcore.package.harmony_beans"/>
-  <Entry uri="android.core.tests.libcore.package.harmony_java_io"/>
-  <Entry uri="android.core.tests.libcore.package.harmony_java_lang"/>
-  <Entry uri="android.core.tests.libcore.package.harmony_java_math"/>
-  <Entry uri="android.core.tests.libcore.package.harmony_java_net"/>
-  <Entry uri="android.core.tests.libcore.package.harmony_java_nio"/>
-  <Entry uri="android.core.tests.libcore.package.harmony_java_text"/>
-  <Entry uri="android.core.tests.libcore.package.harmony_java_util"/>
-  <Entry uri="android.core.tests.libcore.package.harmony_javax_security"/>
-  <Entry uri="android.core.tests.libcore.package.harmony_logging"/>
-  <Entry uri="android.core.tests.libcore.package.harmony_prefs"/>
-  <Entry uri="android.core.tests.libcore.package.harmony_sql"/>
-  <Entry uri="android.core.tests.libcore.package.jsr166"/>
-  <Entry uri="android.core.tests.libcore.package.libcore"/>
-  <Entry uri="android.core.tests.libcore.package.org"/>
-  <Entry uri="android.core.tests.libcore.package.sun"/>
-  <Entry uri="android.core.tests.libcore.package.tests"/>
-  <Entry uri="android.core.vm-tests-tf"/>
-  <Entry uri="android.database"/>
-  <Entry uri="android.dpi"/>
-  <Entry uri="android.dpi2"/>
-  <Entry uri="android.dreams"/>
-  <Entry uri="android.drm"/>
-  <Entry uri="android.effect"/>
-  <Entry uri="android.gesture"/>
-  <Entry uri="android.graphics"/>
-  <Entry uri="android.graphics2"/>
-  <Entry uri="android.hardware" exclude="android.hardware.camera2.cts.CameraDeviceTest#testCameraDeviceRepeatingRequest;android.hardware.camera2.cts.ImageReaderTest#testImageReaderFromCameraJpeg;android.hardware.cts.CameraGLTest#testCameraToSurfaceTextureMetadata;android.hardware.cts.CameraTest#testImmediateZoom;android.hardware.cts.CameraTest#testPreviewCallback;android.hardware.cts.CameraTest#testSmoothZoom;android.hardware.cts.CameraTest#testVideoSnapshot;android.hardware.cts.CameraGLTest#testSetPreviewTextureBothCallbacks;android.hardware.cts.CameraGLTest#testSetPreviewTexturePreviewCallback" />
-  <Entry uri="android.host.holo"/>
-  <Entry uri="android.holo"/>
-  <Entry uri="android.jni"/>
-  <Entry uri="android.keystore"/>
-  <Entry uri="android.location"/>
-  <Entry uri="android.media" exclude="android.media.cts.StreamingMediaPlayerTest#testHLS;android.media.cts.DecoderTest#testCodecResetsH264WithSurface" />
-  <Entry uri="android.mediastress" exclude="android.mediastress.cts.NativeMediaTest#test480pPlay" />
-  <Entry uri="android.nativemedia.sl"/>
-  <Entry uri="android.nativemedia.xa"/>
-  <Entry uri="android.nativeopengl"/>
-  <Entry uri="android.ndef"/>
-  <Entry uri="android.net" exclude="android.net.cts.ConnectivityManagerTest#testStartUsingNetworkFeature_enableHipri;android.net.wifi.cts.ScanResultTest#testScanResultTimeStamp;android.net.cts.DnsTest#testDnsWorks;android.net.cts.TrafficStatsTest#testTrafficStatsForLocalhost;android.net.wifi.cts.ScanResultTest#testAndroidTestCaseSetupProperly;android.net.wifi.cts.NsdManagerTest#testAndroidTestCaseSetupProperly;android.net.cts.SSLCertificateSocketFactoryTest#testCreateSocket;android.net.cts.SSLCertificateSocketFactoryTest#test_createSocket_bind;android.net.cts.SSLCertificateSocketFactoryTest#test_createSocket_simple;android.net.cts.SSLCertificateSocketFactoryTest#test_createSocket_wrapping" />
-  <Entry uri="android.opengl"/>
-  <Entry uri="android.openglperf"/>
-  <Entry uri="android.os"/>
-  <Entry uri="android.permission"/>
-  <Entry uri="android.permission2"/>
-  <Entry uri="android.preference"/>
-  <Entry uri="android.preference2"/>
-  <Entry uri="android.print"/>
-  <Entry uri="android.provider"/>
-  <Entry uri="android.renderscript"/>
-  <Entry uri="android.rscpp"/>
-  <Entry uri="android.rsg"/>
-  <Entry uri="android.sax"/>
-  <Entry uri="android.security" exclude="android.security.cts.ListeningPortsTest#testNoRemotelyAccessibleListeningUdp6Ports;android.security.cts.ListeningPortsTest#testNoRemotelyAccessibleListeningUdpPorts;android.security.cts.BannedFilesTest#testNoSu;android.security.cts.BannedFilesTest#testNoSuInPath;android.security.cts.PackageSignatureTest#testPackageSignatures" />
-  <Entry uri="android.speech"/>
-  <Entry uri="android.telephony"/>
-  <Entry uri="android.tests.appsecurity"/>
-  <Entry uri="android.tests.sigtest"/>
-  <Entry uri="android.text"/>
-  <Entry uri="android.textureview"/>
-  <Entry uri="android.theme"/>
-  <Entry uri="android.uiautomator"/>
-  <Entry uri="android.usb"/>
-  <Entry uri="android.util"/>
-  <Entry uri="android.view"/>
-  <Entry uri="android.webkit" exclude="android.webkit.cts.WebViewClientTest#testDoUpdateVisitedHistory;android.webkit.cts.WebViewClientTest#testLoadPage;android.webkit.cts.WebViewClientTest#testOnFormResubmission;android.webkit.cts.WebViewClientTest#testOnReceivedError;android.webkit.cts.WebViewClientTest#testOnReceivedHttpAuthRequest;android.webkit.cts.WebViewClientTest#testOnScaleChanged;android.webkit.cts.WebViewClientTest#testOnUnhandledKeyEvent;android.webkit.cts.WebViewTest#testSetInitialScale" />
-  <Entry uri="android.widget"/>
-  <Entry uri="com.android.cts.browserbench"/>
-  <Entry uri="com.android.cts.dram"/>
-  <Entry uri="com.android.cts.filesystemperf"/>
-  <Entry uri="com.android.cts.jank"/>
-  <Entry uri="com.android.cts.opengl"/>
-  <Entry uri="com.android.cts.simplecpu"/>
-  <Entry uri="com.android.cts.ui"/>
-  <Entry uri="com.android.cts.uihost"/>
-  <Entry uri="com.android.cts.videoperf"/>
-  <Entry uri="zzz.android.monkey"/>
-</TestPlan>
diff --git a/tests/print/src/android/print/cts/PrintInstrument.java b/tests/print/src/android/print/cts/PrintInstrument.java
index b154901..1c568a1 100644
--- a/tests/print/src/android/print/cts/PrintInstrument.java
+++ b/tests/print/src/android/print/cts/PrintInstrument.java
@@ -131,7 +131,7 @@
 
         args.putIBinder(ARG_PRIVILEGED_OPS, new PrivilegedOperations(mAm));
 
-        if (!mAm.startInstrumentation(cn, profileFile, 0, args, watcher, connection, userId)) {
+        if (!mAm.startInstrumentation(cn, profileFile, 0, args, watcher, connection, userId, null)) {
             throw new AndroidException("INSTRUMENTATION_FAILED: " + cn.flattenToString());
         }
 
diff --git a/tests/res/drawable-nodpi/vector_icon_clip_path_1_golden.png b/tests/res/drawable-nodpi/vector_icon_clip_path_1_golden.png
new file mode 100644
index 0000000..78dddaa
--- /dev/null
+++ b/tests/res/drawable-nodpi/vector_icon_clip_path_1_golden.png
Binary files differ
diff --git a/tests/res/drawable/vector_icon_create_golden.png b/tests/res/drawable-nodpi/vector_icon_create_golden.png
similarity index 100%
rename from tests/res/drawable/vector_icon_create_golden.png
rename to tests/res/drawable-nodpi/vector_icon_create_golden.png
Binary files differ
diff --git a/tests/res/drawable/vector_icon_delete_golden.png b/tests/res/drawable-nodpi/vector_icon_delete_golden.png
similarity index 100%
rename from tests/res/drawable/vector_icon_delete_golden.png
rename to tests/res/drawable-nodpi/vector_icon_delete_golden.png
Binary files differ
diff --git a/tests/res/drawable/vector_icon_heart_golden.png b/tests/res/drawable-nodpi/vector_icon_heart_golden.png
similarity index 100%
rename from tests/res/drawable/vector_icon_heart_golden.png
rename to tests/res/drawable-nodpi/vector_icon_heart_golden.png
Binary files differ
diff --git a/tests/res/drawable/vector_icon_random_path_1_golden.png b/tests/res/drawable-nodpi/vector_icon_random_path_1_golden.png
similarity index 100%
rename from tests/res/drawable/vector_icon_random_path_1_golden.png
rename to tests/res/drawable-nodpi/vector_icon_random_path_1_golden.png
Binary files differ
diff --git a/tests/res/drawable/vector_icon_random_path_2_golden.png b/tests/res/drawable-nodpi/vector_icon_random_path_2_golden.png
similarity index 100%
rename from tests/res/drawable/vector_icon_random_path_2_golden.png
rename to tests/res/drawable-nodpi/vector_icon_random_path_2_golden.png
Binary files differ
diff --git a/tests/res/drawable/vector_icon_repeated_a_1_golden.png b/tests/res/drawable-nodpi/vector_icon_repeated_a_1_golden.png
similarity index 100%
rename from tests/res/drawable/vector_icon_repeated_a_1_golden.png
rename to tests/res/drawable-nodpi/vector_icon_repeated_a_1_golden.png
Binary files differ
diff --git a/tests/res/drawable/vector_icon_repeated_a_2_golden.png b/tests/res/drawable-nodpi/vector_icon_repeated_a_2_golden.png
similarity index 100%
rename from tests/res/drawable/vector_icon_repeated_a_2_golden.png
rename to tests/res/drawable-nodpi/vector_icon_repeated_a_2_golden.png
Binary files differ
diff --git a/tests/res/drawable/vector_icon_repeated_cq_golden.png b/tests/res/drawable-nodpi/vector_icon_repeated_cq_golden.png
similarity index 100%
rename from tests/res/drawable/vector_icon_repeated_cq_golden.png
rename to tests/res/drawable-nodpi/vector_icon_repeated_cq_golden.png
Binary files differ
diff --git a/tests/res/drawable/vector_icon_repeated_st_golden.png b/tests/res/drawable-nodpi/vector_icon_repeated_st_golden.png
similarity index 100%
rename from tests/res/drawable/vector_icon_repeated_st_golden.png
rename to tests/res/drawable-nodpi/vector_icon_repeated_st_golden.png
Binary files differ
diff --git a/tests/res/drawable/vector_icon_schedule_golden.png b/tests/res/drawable-nodpi/vector_icon_schedule_golden.png
similarity index 100%
rename from tests/res/drawable/vector_icon_schedule_golden.png
rename to tests/res/drawable-nodpi/vector_icon_schedule_golden.png
Binary files differ
diff --git a/tests/res/drawable/vector_icon_settings_golden.png b/tests/res/drawable-nodpi/vector_icon_settings_golden.png
similarity index 100%
rename from tests/res/drawable/vector_icon_settings_golden.png
rename to tests/res/drawable-nodpi/vector_icon_settings_golden.png
Binary files differ
diff --git a/tests/res/drawable-nodpi/vector_icon_transformation_1_golden.png b/tests/res/drawable-nodpi/vector_icon_transformation_1_golden.png
new file mode 100644
index 0000000..6f659c3
--- /dev/null
+++ b/tests/res/drawable-nodpi/vector_icon_transformation_1_golden.png
Binary files differ
diff --git a/tests/res/drawable-nodpi/vector_icon_transformation_2_golden.png b/tests/res/drawable-nodpi/vector_icon_transformation_2_golden.png
new file mode 100644
index 0000000..e0e14f3
--- /dev/null
+++ b/tests/res/drawable-nodpi/vector_icon_transformation_2_golden.png
Binary files differ
diff --git a/tests/res/drawable-nodpi/vector_icon_transformation_3_golden.png b/tests/res/drawable-nodpi/vector_icon_transformation_3_golden.png
new file mode 100644
index 0000000..b6798c2
--- /dev/null
+++ b/tests/res/drawable-nodpi/vector_icon_transformation_3_golden.png
Binary files differ
diff --git a/tests/res/drawable-nodpi/vector_icon_transformation_4_golden.png b/tests/res/drawable-nodpi/vector_icon_transformation_4_golden.png
new file mode 100644
index 0000000..a5d4d33
--- /dev/null
+++ b/tests/res/drawable-nodpi/vector_icon_transformation_4_golden.png
Binary files differ
diff --git a/tests/res/drawable-nodpi/vector_icon_transformation_5_golden.png b/tests/res/drawable-nodpi/vector_icon_transformation_5_golden.png
new file mode 100644
index 0000000..0d8ded1
--- /dev/null
+++ b/tests/res/drawable-nodpi/vector_icon_transformation_5_golden.png
Binary files differ
diff --git a/tests/res/drawable-nodpi/vector_icon_transformation_6_golden.png b/tests/res/drawable-nodpi/vector_icon_transformation_6_golden.png
new file mode 100644
index 0000000..64d07fa
--- /dev/null
+++ b/tests/res/drawable-nodpi/vector_icon_transformation_6_golden.png
Binary files differ
diff --git a/tests/res/drawable/statelist_testimage.jpg b/tests/res/drawable/statelist_testimage.jpg
new file mode 100644
index 0000000..754df0c
--- /dev/null
+++ b/tests/res/drawable/statelist_testimage.jpg
Binary files differ
diff --git a/tests/res/drawable/statelistdrawable.xml b/tests/res/drawable/statelistdrawable.xml
index 9d9aa3b..b867904 100644
--- a/tests/res/drawable/statelistdrawable.xml
+++ b/tests/res/drawable/statelistdrawable.xml
@@ -16,7 +16,7 @@
  -->
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-   <item android:state_focused="true" android:drawable="@drawable/testimage"/>
-   <item android:state_enabled="false" android:drawable="@drawable/testimage"/>
+   <item android:state_focused="true" android:drawable="@drawable/statelist_testimage"/>
+   <item android:state_enabled="false" android:drawable="@drawable/statelist_testimage"/>
 </selector>
 
diff --git a/tests/res/drawable/vector_icon_clip_path_1.xml b/tests/res/drawable/vector_icon_clip_path_1.xml
new file mode 100644
index 0000000..5b4c4ab
--- /dev/null
+++ b/tests/res/drawable/vector_icon_clip_path_1.xml
@@ -0,0 +1,77 @@
+<!--
+ Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <size
+        android:height="64dp"
+        android:width="64dp" />
+
+    <viewport
+        android:viewportHeight="12.25"
+        android:viewportWidth="7.30625" />
+
+    <group
+        android:pivotX="3.65"
+        android:pivotY="6.125"
+        android:rotation="-30" >
+        <path
+            android:name="clip1"
+            android:clipToPath="true"
+            android:pathData="
+                M 0, 6.125
+                l 7.3, 0
+                l 0, 12.25
+                l -7.3, 0
+                z" />
+    </group>
+    <group>
+        <path
+            android:name="one"
+            android:fill="#ff88ff"
+            android:pathData="M 1.215625,9.5l 1.9375,0.0 0.0,-6.671875 -2.109375,0.421875 0.0,-1.078125
+                l 2.09375,-0.421875 1.1874998,0.0 0.0,7.75 1.9375,0.0 0.0,1.0
+                l -5.046875,0.0 0.0,-1.0Z" />
+    </group>
+    <group
+        android:pivotX="3.65"
+        android:pivotY="6.125"
+        android:rotation="-30" >
+        <path
+            android:name="clip2"
+            android:clipToPath="true"
+            android:pathData="
+                M 0, 0
+                l 7.3, 0
+                l 0, 6.125
+                l -7.3, 0
+                z" />
+    </group>
+    <group>
+        <path
+            android:name="two"
+            android:fill="#ff88ff"
+            android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0 -5.5625,0.0 0.0,-1.0q 0.671875,-0.6875 1.828125,-1.859375
+                        q 1.1718752,-1.1875 1.4687502,-1.53125 0.578125,-0.625 0.796875,-1.0625
+                        q 0.234375,-0.453125 0.234375,-0.875 0.0,-0.703125 -0.5,-1.140625
+                        q -0.484375,-0.4375 -1.2656252,-0.4375 -0.5625,0.0 -1.1875,0.1875
+                        q -0.609375,0.1875 -1.3125,0.59375l 0.0,-1.203125q 0.71875,-0.28125 1.328125,-0.421875
+                        q 0.625,-0.15625 1.140625,-0.15625 1.3593752,0.0 2.1718752,0.6875
+                        q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125 -0.203125,1.015625
+                        q -0.203125,0.484375 -0.734375,1.140625 -0.15625,0.171875 -0.9375,0.984375
+                        q -0.78125024,0.8125 -2.2187502,2.265625Z" />
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/tests/res/drawable/vector_icon_transformation_1.xml b/tests/res/drawable/vector_icon_transformation_1.xml
new file mode 100644
index 0000000..5fb665d
--- /dev/null
+++ b/tests/res/drawable/vector_icon_transformation_1.xml
@@ -0,0 +1,42 @@
+<!--
+ Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <size
+        android:height="64dp"
+        android:width="64dp" />
+
+    <viewport
+        android:viewportHeight="500"
+        android:viewportWidth="800" />
+
+    <group
+        android:pivotX="90"
+        android:pivotY="100"
+        android:rotation="20">
+        <path
+            android:name="pie2"
+            android:pathData="M200,350 l 50,-25
+           a25,12 -30 0,1 100,-50 l 50,-25
+           a25,25 -30 0,1 100,-50 l 50,-25
+           a25,37 -30 0,1 100,-50 l 50,-25
+           a25,50 -30 0,1 100,-50 l 50,-25"
+           android:fill="#00000000"
+            android:stroke="#FF00FF00"
+            android:strokeWidth="10" />
+    </group>
+
+</vector>
diff --git a/tests/res/drawable/vector_icon_transformation_2.xml b/tests/res/drawable/vector_icon_transformation_2.xml
new file mode 100644
index 0000000..649f33f
--- /dev/null
+++ b/tests/res/drawable/vector_icon_transformation_2.xml
@@ -0,0 +1,52 @@
+<!--
+ Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <size
+        android:height="64dp"
+        android:width="64dp" />
+
+    <viewport
+        android:viewportHeight="200"
+        android:viewportWidth="200" />
+
+    <group>
+        <path
+            android:name="background1"
+            android:pathData="M 0,0 l 100,0 l 0, 100 l -100, 0 z"
+            android:fill="#FF000000"/>
+        <path
+            android:name="background2"
+            android:pathData="M 100,100 l 100,0 l 0, 100 l -100, 0 z"
+            android:fill="#FF000000"/>
+    </group>
+    <group
+        android:pivotX="100"
+        android:pivotY="100"
+        android:rotation="90"
+        android:scaleX="0.75"
+        android:scaleY="0.5"
+        android:translateX="0.0"
+        android:translateY="100.0">
+        <path
+            android:name="twoLines"
+            android:pathData="M 100,10 v 90 M 10,100 h 90"
+            android:fill="#00000000"
+            android:stroke="#FF00FF00"
+            android:strokeWidth="10" />
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/tests/res/drawable/vector_icon_transformation_3.xml b/tests/res/drawable/vector_icon_transformation_3.xml
new file mode 100644
index 0000000..ae11124
--- /dev/null
+++ b/tests/res/drawable/vector_icon_transformation_3.xml
@@ -0,0 +1,52 @@
+<!--
+ Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <size
+        android:height="64dp"
+        android:width="64dp" />
+
+    <viewport
+        android:viewportHeight="200"
+        android:viewportWidth="200" />
+
+    <group>
+        <path
+            android:name="background1"
+            android:pathData="M 0,0 l 100,0 l 0, 100 l -100, 0 z"
+            android:fill="#FF000000"/>
+        <path
+            android:name="background2"
+            android:pathData="M 100,100 l 100,0 l 0, 100 l -100, 0 z"
+            android:fill="#FF000000"/>
+    </group>
+    <group
+        android:pivotX="0"
+        android:pivotY="0"
+        android:rotation="90"
+        android:scaleX="0.75"
+        android:scaleY="0.5"
+        android:translateX="100.0"
+        android:translateY="100.0">
+        <path
+            android:name="twoLines"
+            android:pathData="M 100,10 v 90 M 10,100 h 90"
+            android:fill="#00000000"
+            android:stroke="#FF00FF00"
+            android:strokeWidth="10" />
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/tests/res/drawable/vector_icon_transformation_4.xml b/tests/res/drawable/vector_icon_transformation_4.xml
new file mode 100644
index 0000000..8d38cb5
--- /dev/null
+++ b/tests/res/drawable/vector_icon_transformation_4.xml
@@ -0,0 +1,72 @@
+<!--
+ Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <size
+        android:height="64dp"
+        android:width="64dp" />
+
+    <viewport
+        android:viewportHeight="400"
+        android:viewportWidth="400" />
+
+    <group android:name="backgroundGroup" >
+        <path
+            android:name="background1"
+            android:fill="#80000000"
+            android:pathData="M 0,0 l 200,0 l 0, 200 l -200, 0 z" />
+        <path
+            android:name="background2"
+            android:fill="#80000000"
+            android:pathData="M 200,200 l 200,0 l 0, 200 l -200, 0 z" />
+    </group>
+    <group
+        android:name="translateToCenterGroup"
+        android:translateX="50.0"
+        android:translateY="90.0" >
+        <path
+            android:name="twoLines"
+            android:pathData="M 0,0 v 100 M 0,0 h 100"
+            android:stroke="#FFFF0000"
+            android:strokeWidth="20" />
+
+        <group
+            android:name="rotationGroup"
+            android:pivotX="0.0"
+            android:pivotY="0.0"
+            android:rotation="-45.0" >
+            <path
+                android:name="twoLines1"
+                android:pathData="M 0,0 v 100 M 0,0 h 100"
+                android:stroke="#FF00FF00"
+                android:strokeWidth="20" />
+
+            <group
+                android:name="translateGroup"
+                android:translateX="130.0"
+                android:translateY="160.0" >
+                <group android:name="scaleGroup" >
+                    <path
+                        android:name="twoLines2"
+                        android:pathData="M 0,0 v 100 M 0,0 h 100"
+                        android:stroke="#FF0000FF"
+                        android:strokeWidth="20" />
+                </group>
+            </group>
+        </group>
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/tests/res/drawable/vector_icon_transformation_5.xml b/tests/res/drawable/vector_icon_transformation_5.xml
new file mode 100644
index 0000000..8088578
--- /dev/null
+++ b/tests/res/drawable/vector_icon_transformation_5.xml
@@ -0,0 +1,85 @@
+<!--
+ Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <size
+        android:height="64dp"
+        android:width="64dp" />
+
+    <viewport
+        android:viewportHeight="400"
+        android:viewportWidth="400" />
+
+    <group android:name="backgroundGroup" >
+        <path
+            android:name="background1"
+            android:fill="#80000000"
+            android:pathData="M 0,0 l 200,0 l 0, 200 l -200, 0 z" />
+        <path
+            android:name="background2"
+            android:fill="#80000000"
+            android:pathData="M 200,200 l 200,0 l 0, 200 l -200, 0 z" />
+    </group>
+    <group
+        android:name="translateToCenterGroup"
+        android:translateX="50.0"
+        android:translateY="90.0" >
+        <path
+            android:name="twoLines"
+            android:pathData="M 0,0 v 150 M 0,0 h 150"
+            android:stroke="#FFFF0000"
+            android:strokeWidth="20" />
+
+        <group
+            android:name="rotationGroup"
+            android:pivotX="0.0"
+            android:pivotY="0.0"
+            android:rotation="-45.0" >
+            <path
+                android:name="twoLines1"
+                android:pathData="M 0,0 v 100 M 0,0 h 100"
+                android:stroke="#FF00FF00"
+                android:strokeWidth="20" />
+
+            <group
+                android:name="translateGroup"
+                android:translateX="130.0"
+                android:translateY="160.0" >
+                <group android:name="scaleGroup" >
+                    <path
+                        android:name="twoLines3"
+                        android:pathData="M 0,0 v 100 M 0,0 h 100"
+                        android:stroke="#FF0000FF"
+                        android:strokeWidth="20" />
+                </group>
+            </group>
+
+            <group
+                android:name="translateGroupHalf"
+                android:translateX="65.0"
+                android:translateY="80.0" >
+                <group android:name="scaleGroup" >
+                    <path
+                        android:name="twoLines2"
+                        android:pathData="M 0,0 v 100 M 0,0 h 100"
+                        android:stroke="#FF0000FF"
+                        android:strokeWidth="20" />
+                </group>
+            </group>
+        </group>
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/tests/res/drawable/vector_icon_transformation_6.xml b/tests/res/drawable/vector_icon_transformation_6.xml
new file mode 100644
index 0000000..f2f8881
--- /dev/null
+++ b/tests/res/drawable/vector_icon_transformation_6.xml
@@ -0,0 +1,90 @@
+<!--
+ Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <size
+        android:height="64dp"
+        android:width="64dp" />
+
+    <viewport
+        android:viewportHeight="400"
+        android:viewportWidth="400" />
+
+    <group android:name="backgroundGroup"
+        android:alpha = "0.5" >
+        <path
+            android:name="background1"
+            android:fill="#FF000000"
+            android:pathData="M 0,0 l 200,0 l 0, 200 l -200, 0 z" />
+        <path
+            android:name="background2"
+            android:fill="#FF000000"
+            android:pathData="M 200,200 l 200,0 l 0, 200 l -200, 0 z" />
+    </group>
+    <group
+        android:name="translateToCenterGroup"
+        android:translateX="50.0"
+        android:translateY="90.0"
+        android:alpha = "0.5" >
+        <path
+            android:name="twoLines"
+            android:pathData="M 0,0 v 100 M 0,0 h 100"
+            android:stroke="#FFFF0000"
+            android:strokeWidth="20" />
+
+        <group
+            android:name="rotationGroup"
+            android:pivotX="0.0"
+            android:pivotY="0.0"
+            android:rotation="-45.0"
+            android:alpha = "0.5" >
+            <path
+                android:name="twoLines1"
+                android:pathData="M 0,0 v 100 M 0,0 h 100"
+                android:stroke="#FF00FF00"
+                android:strokeWidth="20" />
+
+            <group
+                android:name="translateGroup"
+                android:translateX="130.0"
+                android:translateY="160.0"
+                android:alpha = "0.5">
+                <group android:name="scaleGroup" >
+                    <path
+                        android:name="twoLines3"
+                        android:pathData="M 0,0 v 100 M 0,0 h 100"
+                        android:stroke="#FF0000FF"
+                        android:strokeWidth="20" />
+                </group>
+            </group>
+
+            <group
+                android:name="translateGroupHalf"
+                android:translateX="65.0"
+                android:translateY="80.0"
+                android:alpha = "0.5">
+                <group android:name="scaleGroup" >
+                    <path
+                        android:name="twoLines2"
+                        android:pathData="M 0,0 v 100 M 0,0 h 100"
+                        android:stroke="#FF0000FF"
+                        android:strokeWidth="20" />
+                </group>
+            </group>
+        </group>
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/tests/res/layout/framelayout_layout.xml b/tests/res/layout/framelayout_layout.xml
index 1048d1b..c6d1a83 100644
--- a/tests/res/layout/framelayout_layout.xml
+++ b/tests/res/layout/framelayout_layout.xml
@@ -23,8 +23,8 @@
                 android:orientation="vertical">
 
     <FrameLayout
-        android:layout_width="200dip"
-        android:layout_height="200dip"
+        android:layout_width="100dip"
+        android:layout_height="100dip"
         android:background="@drawable/yellow"
         android:id="@+id/framelayout">
     </FrameLayout>
@@ -37,7 +37,7 @@
 
         <TextView android:id="@+id/framelayout_textview"
             android:background="@drawable/blue"
-            android:layout_width="100dip"
+            android:layout_width="60dip"
             android:layout_height="30dip"
             android:text="@string/hello_world"/>
 
diff --git a/tests/res/values/styles.xml b/tests/res/values/styles.xml
index 47238a3..20c80f8 100644
--- a/tests/res/values/styles.xml
+++ b/tests/res/values/styles.xml
@@ -165,4 +165,8 @@
         <item name="themeTileMode">2</item>
     </style>
 
+    <style name="Theme_NoSwipeDismiss">
+        <item name="android:windowSwipeToDismiss">false</item>
+    </style>
+
 </resources>
diff --git a/tests/src/android/renderscript/cts/AtomicTest.rs b/tests/src/android/renderscript/cts/AtomicTest.rs
new file mode 100644
index 0000000..2a78ffd
--- /dev/null
+++ b/tests/src/android/renderscript/cts/AtomicTest.rs
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "shared.rsh"
+#include "rs_atomic.rsh"
+
+volatile int32_t gISum;
+volatile uint32_t gUSum;
+
+
+void __attribute__((kernel)) test_Inc(int32_t v) {
+    rsAtomicInc(&gISum);
+}
+void __attribute__((kernel)) test_uInc(uint32_t v) {
+    rsAtomicInc(&gUSum);
+}
+
+void __attribute__((kernel)) test_Dec(int32_t v) {
+    rsAtomicDec(&gISum);
+}
+void __attribute__((kernel)) test_uDec(uint32_t v) {
+    rsAtomicDec(&gUSum);
+}
+
+#define TEST_OP(op)                                     \
+void __attribute__((kernel)) test_##op(int32_t v) {     \
+    rsAtomic##op(&gISum, v);                            \
+}                                                       \
+void __attribute__((kernel)) test_u##op(uint32_t v) {   \
+    rsAtomic##op(&gUSum, v);                            \
+}
+
+TEST_OP(Add)
+TEST_OP(Sub)
+TEST_OP(And)
+TEST_OP(Or)
+TEST_OP(Xor)
+TEST_OP(Min)
+TEST_OP(Max)
+
+// the folowing functions copy the global to an allocation
+// to allow the calling code to read it back.
+void getValueS(rs_allocation v) {
+    rsSetElementAt_int(v, gISum, 0);
+}
+
+void getValueU(rs_allocation v) {
+    rsSetElementAt_uint(v, gUSum, 0);
+}
+
+void computeReference_Min(rs_allocation a, rs_allocation result) {
+    uint32_t dimX = rsAllocationGetDimX(a);
+    uint32_t dimY = rsAllocationGetDimY(a);
+    for (uint32_t y = 0; y < dimY; y++) {
+        for (uint32_t x = 0; x < dimX; x++) {
+            int v = rsGetElementAt_int(a, x, y);
+            gISum = min(gISum, v);
+        }
+    }
+    rsSetElementAt_int(result, gISum, 0);
+}
+
+void computeReference_uMin(rs_allocation a, rs_allocation result) {
+    uint32_t dimX = rsAllocationGetDimX(a);
+    uint32_t dimY = rsAllocationGetDimY(a);
+    for (uint32_t y = 0; y < dimY; y++) {
+        for (uint32_t x = 0; x < dimX; x++) {
+            uint v = rsGetElementAt_uint(a, x, y);
+            gUSum = min(gUSum, v);
+        }
+    }
+    rsSetElementAt_uint(result, gUSum, 0);
+}
+
+void computeReference_Max(rs_allocation a, rs_allocation result) {
+    uint32_t dimX = rsAllocationGetDimX(a);
+    uint32_t dimY = rsAllocationGetDimY(a);
+    for (uint32_t y = 0; y < dimY; y++) {
+        for (uint32_t x = 0; x < dimX; x++) {
+            int v = rsGetElementAt_int(a, x, y);
+            gISum = max(gISum, v);
+        }
+    }
+    rsSetElementAt_int(result, gISum, 0);
+}
+
+void computeReference_uMax(rs_allocation a, rs_allocation result) {
+    uint32_t dimX = rsAllocationGetDimX(a);
+    uint32_t dimY = rsAllocationGetDimY(a);
+    for (uint32_t y = 0; y < dimY; y++) {
+        for (uint32_t x = 0; x < dimX; x++) {
+            uint v = rsGetElementAt_uint(a, x, y);
+            gUSum = max(gUSum, v);
+        }
+    }
+    rsSetElementAt_uint(result, gUSum, 0);
+}
+
+
+void __attribute__((kernel)) test_Cas(int32_t v) {
+    int tmp = gISum;
+    int retryCount = 10000;
+    while (retryCount && (rsAtomicCas(&gISum, tmp, tmp + 1) != tmp)) {
+        retryCount--;
+        tmp = gISum;
+    }
+}
+void __attribute__((kernel)) test_uCas(uint32_t v) {
+    uint tmp = gUSum;
+    int retryCount = 10000;
+    while (retryCount && (rsAtomicCas(&gUSum, tmp, tmp + 1) != tmp)) {
+        retryCount--;
+        tmp = gUSum;
+    }
+}
+
+
diff --git a/tests/tests/display/src/android/display/cts/VirtualDisplayTest.java b/tests/tests/display/src/android/display/cts/VirtualDisplayTest.java
index f452f50..f2f859a 100644
--- a/tests/tests/display/src/android/display/cts/VirtualDisplayTest.java
+++ b/tests/tests/display/src/android/display/cts/VirtualDisplayTest.java
@@ -29,6 +29,7 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
+import android.os.HandlerThread;
 import android.os.SystemClock;
 import android.test.AndroidTestCase;
 import android.util.DisplayMetrics;
@@ -72,6 +73,8 @@
     private ImageReader mImageReader;
     private Surface mSurface;
     private ImageListener mImageListener;
+    private HandlerThread mCheckThread;
+    private Handler mCheckHandler;
 
     @Override
     protected void setUp() throws Exception {
@@ -80,11 +83,15 @@
         mDisplayManager = (DisplayManager)mContext.getSystemService(Context.DISPLAY_SERVICE);
         mHandler = new Handler(Looper.getMainLooper());
         mImageListener = new ImageListener();
+        // thread for image checking
+        mCheckThread = new HandlerThread("TestHandler");
+        mCheckThread.start();
+        mCheckHandler = new Handler(mCheckThread.getLooper());
 
         mImageReaderLock.lock();
         try {
             mImageReader = ImageReader.newInstance(WIDTH, HEIGHT, PixelFormat.RGBA_8888, 2);
-            mImageReader.setOnImageAvailableListener(mImageListener, mHandler);
+            mImageReader.setOnImageAvailableListener(mImageListener, mCheckHandler);
             mSurface = mImageReader.getSurface();
         } finally {
             mImageReaderLock.unlock();
@@ -94,7 +101,6 @@
     @Override
     protected void tearDown() throws Exception {
         super.tearDown();
-
         mImageReaderLock.lock();
         try {
             mImageReader.close();
@@ -103,6 +109,7 @@
         } finally {
             mImageReaderLock.unlock();
         }
+        mCheckThread.quit();
     }
 
     /**
diff --git a/tests/tests/graphics/Android.mk b/tests/tests/graphics/Android.mk
index cad81b2..b65bb1b 100644
--- a/tests/tests/graphics/Android.mk
+++ b/tests/tests/graphics/Android.mk
@@ -16,10 +16,7 @@
 
 include $(CLEAR_VARS)
 
-# don't include this package in any target
-LOCAL_MODULE_TAGS := optional
-# and when built explicitly put it in the data partition
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+LOCAL_MODULE_TAGS := tests
 
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
 
diff --git a/tests/tests/graphics/src/android/graphics/cts/CanvasTest.java b/tests/tests/graphics/src/android/graphics/cts/CanvasTest.java
index 6e86563..76eeee3 100644
--- a/tests/tests/graphics/src/android/graphics/cts/CanvasTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/CanvasTest.java
@@ -987,6 +987,30 @@
         assertFalse(mCanvas.clipRegion(r, Op.XOR));
     }
 
+    public void testClipRegion3() {
+        assertTrue(mCanvas.clipRegion(new Region(0, 0, 10, 10)));
+        final Rect clip = mCanvas.getClipBounds();
+        assertEquals(0, clip.left);
+        assertEquals(0, clip.top);
+        assertEquals(10, clip.right);
+        assertEquals(10, clip.bottom);
+    }
+
+    public void testClipRegion4() {
+        mCanvas.translate(10, 10);
+        mCanvas.scale(2, 2);
+
+        final Matrix beforeMatrix = mCanvas.getMatrix();
+        assertTrue(mCanvas.clipRegion(new Region(0, 0, 10, 10)));
+        assertEquals(beforeMatrix, mCanvas.getMatrix());
+
+        Rect clip = mCanvas.getClipBounds();
+        assertEquals(-5, clip.left);
+        assertEquals(-5, clip.top);
+        assertEquals(0, clip.right);
+        assertEquals(0, clip.bottom);
+    }
+
     public void testGetDrawFilter() {
         assertNull(mCanvas.getDrawFilter());
         final DrawFilter dF = new DrawFilter();
diff --git a/tests/tests/graphics/src/android/graphics/cts/PictureTest.java b/tests/tests/graphics/src/android/graphics/cts/PictureTest.java
index 81f053d..912c5a7 100644
--- a/tests/tests/graphics/src/android/graphics/cts/PictureTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/PictureTest.java
@@ -24,18 +24,90 @@
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Color;
+import android.graphics.Matrix;
 import android.graphics.Paint;
 import android.graphics.Picture;
+import android.graphics.Rect;
 import android.graphics.Paint.Style;
-
+import android.graphics.Region.Op;
 
 public class PictureTest extends TestCase {
 
     private static final int TEST_WIDTH = 4; // must be >= 2
     private static final int TEST_HEIGHT = 3; // must >= 2
 
-    public void testPicture() throws Exception {
+    private final Rect mClipRect = new Rect(0, 0, 2, 2);
 
+    // This method tests out some edge cases w.r.t. Picture creation.
+    // In particular, this test verifies that, in the following situations,
+    // the created picture (effectively) has balanced saves and restores:
+    //   - copy constructed picture from actively recording picture
+    //   - writeToStream/createFromStream created picture from actively recording picture
+    //   - actively recording picture after draw call
+    public void testSaveRestoreBalance() throws Exception {
+        Picture original = new Picture();
+        Canvas canvas = original.beginRecording(TEST_WIDTH, TEST_HEIGHT);
+        assertNotNull(canvas);
+        createImbalance(canvas);
+
+        int expectedSaveCount = canvas.getSaveCount();
+
+        Picture copy = new Picture(original);
+        checkBalance(copy);
+
+        assertEquals(expectedSaveCount, canvas.getSaveCount());
+
+        ByteArrayOutputStream bout = new ByteArrayOutputStream();
+        original.writeToStream(bout);
+
+        assertEquals(expectedSaveCount, canvas.getSaveCount());
+
+        Picture serialized = Picture.createFromStream(new ByteArrayInputStream(bout.toByteArray()));
+        // The serialization/deserialization process will balance the saves and restores
+        checkBalance(serialized);
+
+        assertEquals(expectedSaveCount, canvas.getSaveCount());
+
+        Bitmap bitmap = Bitmap.createBitmap(TEST_WIDTH, TEST_HEIGHT, Bitmap.Config.ARGB_8888);
+        Canvas drawDest = new Canvas(bitmap);
+        original.draw(drawDest);
+        checkBalance(original);
+    }
+
+    // Add an extra save with a transform and clip
+    private void createImbalance(Canvas canvas) {
+        canvas.save();
+        canvas.clipRect(mClipRect, Op.REPLACE);
+        canvas.translate(1.0f, 1.0f);
+        Paint paint = new Paint();
+        paint.setColor(Color.GREEN);
+        canvas.drawRect(0, 0, 10, 10, paint);
+    }
+
+    private void checkBalance(Picture picture) {
+        Bitmap bitmap = Bitmap.createBitmap(TEST_WIDTH, TEST_HEIGHT, Bitmap.Config.ARGB_8888);
+        Canvas canvas = new Canvas(bitmap);
+
+        int beforeSaveCount = canvas.getSaveCount();
+
+        final Matrix beforeMatrix = canvas.getMatrix();
+
+        Rect beforeClip = new Rect();
+        assertTrue(canvas.getClipBounds(beforeClip));
+
+        canvas.drawPicture(picture);
+
+        assertEquals(beforeSaveCount, canvas.getSaveCount());
+
+        assertTrue(beforeMatrix.equals(canvas.getMatrix()));
+
+        Rect afterClip = new Rect();
+
+        assertTrue(canvas.getClipBounds(afterClip));
+        assertEquals(beforeClip, afterClip);
+    }
+
+    public void testPicture() throws Exception {
         Picture picture = new Picture();
         ByteArrayOutputStream bout = new ByteArrayOutputStream();
 
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/BitmapDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/BitmapDrawableTest.java
index c84510d..b415386 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/BitmapDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/BitmapDrawableTest.java
@@ -18,19 +18,21 @@
 
 import com.android.cts.stub.R;
 
-
 import org.xmlpull.v1.XmlPullParserException;
 
 import android.content.Context;
+import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.Color;
 import android.graphics.ColorFilter;
 import android.graphics.Paint;
 import android.graphics.PixelFormat;
 import android.graphics.Shader;
 import android.graphics.Bitmap.Config;
+import android.graphics.PorterDuff.Mode;
 import android.graphics.Shader.TileMode;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable.ConstantState;
@@ -240,6 +242,16 @@
         assertNull(bitmapDrawable.getPaint().getColorFilter());
     }
 
+    public void testSetTint() {
+        final InputStream source = mContext.getResources().openRawResource(R.raw.testimage);
+        final BitmapDrawable d = new BitmapDrawable(source);
+
+        d.setTint(ColorStateList.valueOf(Color.BLACK), Mode.SRC_OVER);
+        assertEquals("Nine-patch is tinted", Color.BLACK, DrawableTestingUtils.getPixel(d, 0, 0));
+
+        d.setTint(null, null);
+    }
+
     public void testGetOpacity() {
         BitmapDrawable bitmapDrawable = new BitmapDrawable();
         assertEquals(Gravity.FILL, bitmapDrawable.getGravity());
@@ -343,6 +355,7 @@
         attrs = DrawableTestUtils.getAttributeSet(
                 mContext.getResources().getXml(R.xml.bitmapdrawable), "bitmap_wrongsrc");
         try {
+            bitmapDrawable = new BitmapDrawable();
             bitmapDrawable.inflate(mContext.getResources(), parser, attrs);
             fail("Should throw XmlPullParserException if the bitmap source can't be decoded.");
         } catch (XmlPullParserException e) {
@@ -351,20 +364,23 @@
         attrs = DrawableTestUtils.getAttributeSet(
                 mContext.getResources().getXml(R.xml.bitmapdrawable), "bitmap_nosrc");
         try {
+            bitmapDrawable = new BitmapDrawable();
             bitmapDrawable.inflate(mContext.getResources(), parser, attrs);
-            fail("Should throw XmlPullParserException if the bitmap src doesn't be defined.");
+            fail("Should throw XmlPullParserException if the bitmap src is not defined.");
         } catch (XmlPullParserException e) {
         }
 
         attrs = DrawableTestUtils.getAttributeSet(
                 mContext.getResources().getXml(R.xml.bitmapdrawable), "bitmap_allattrs");
         try {
+            bitmapDrawable = new BitmapDrawable();
             bitmapDrawable.inflate(null, parser, attrs);
             fail("Should throw NullPointerException if resource is null");
         } catch (NullPointerException e) {
         }
 
         try {
+            bitmapDrawable = new BitmapDrawable();
             bitmapDrawable.inflate(mContext.getResources(), parser, null);
             fail("Should throw NullPointerException if attribute set is null");
         } catch (NullPointerException e) {
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/ColorDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/ColorDrawableTest.java
index 1267885..b4237d7 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/ColorDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/ColorDrawableTest.java
@@ -16,22 +16,21 @@
 
 package android.graphics.drawable.cts;
 
-import com.android.cts.stub.R;
-
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.content.res.Resources;
+import android.content.res.ColorStateList;
 import android.content.res.XmlResourceParser;
-import android.graphics.Canvas;
-import android.graphics.ColorFilter;
+import android.graphics.Color;
 import android.graphics.PixelFormat;
+import android.graphics.PorterDuff.Mode;
 import android.graphics.drawable.ColorDrawable;
 import android.test.AndroidTestCase;
 import android.util.AttributeSet;
 import android.util.Xml;
 
+import com.android.cts.stub.R;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
 import java.io.IOException;
 
 public class ColorDrawableTest extends AndroidTestCase {
@@ -120,9 +119,19 @@
     }
 
     public void testSetColorFilter() {
-        final ColorDrawable colorDrawable = new ColorDrawable();
+        final ColorDrawable d = new ColorDrawable(Color.WHITE);
+        assertEquals(Color.WHITE, DrawableTestingUtils.getPixel(d, 0, 0));
 
-        // setColorFilter(ColorFilter) is a non-operation function.
-        colorDrawable.setColorFilter(null);
+        d.setColorFilter(Color.BLACK, Mode.SRC_OVER);
+        assertEquals(Color.BLACK, DrawableTestingUtils.getPixel(d, 0, 0));
+        
+    }
+
+    public void testSetTint() {
+        final ColorDrawable d = new ColorDrawable(Color.WHITE);
+        assertEquals(Color.WHITE, DrawableTestingUtils.getPixel(d, 0, 0));
+
+        d.setTint(ColorStateList.valueOf(Color.BLACK), Mode.SRC_OVER);
+        assertEquals(Color.BLACK, DrawableTestingUtils.getPixel(d, 0, 0));
     }
 }
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableContainerTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableContainerTest.java
index 26cdbb6..5a81feb 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableContainerTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableContainerTest.java
@@ -20,9 +20,12 @@
 
 import java.util.Arrays;
 
+import android.content.res.ColorStateList;
 import android.graphics.Canvas;
+import android.graphics.Color;
 import android.graphics.ColorFilter;
 import android.graphics.PixelFormat;
+import android.graphics.PorterDuff.Mode;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.DrawableContainer;
@@ -204,6 +207,23 @@
         assertTrue(dr.hasSetColorFilterCalled());
     }
 
+    public void testSetTint() {
+        assertConstantStateNotSet();
+        assertNull(mDrawableContainer.getCurrent());
+
+        mDrawableContainer.setConstantState(mDrawableContainerState);
+        mDrawableContainer.setTint(ColorStateList.valueOf(Color.BLACK), Mode.SRC_OVER);
+
+        MockDrawable dr = new MockDrawable();
+        addAndSelectDrawable(dr);
+
+        assertEquals("Initial tint propagates", Mode.SRC_OVER, dr.getTintMode());
+
+        dr.reset();
+        mDrawableContainer.setTint(null, null);
+        assertTrue("setTint() propagates", dr.hasSetTintCalled());
+    }
+
     public void testOnBoundsChange() {
         assertConstantStateNotSet();
         assertNull(mDrawableContainer.getCurrent());
@@ -753,35 +773,29 @@
 
     private class MockDrawable extends Drawable {
         private boolean mHasCalledDraw;
-
         private boolean mHasCalledSetAlpha;
-
         private boolean mHasCalledSetColorFilter;
-
         private boolean mHasCalledSetDither;
-
+        private boolean mHasCalledSetTint;
         private boolean mHasCalledOnBoundsChanged;
-
         private boolean mHasCalledOnStateChanged;
-
         private boolean mHasCalledOnLevelChanged;
-
         private boolean mHasCalledMutate;
 
-        private boolean mIsStatful;
+        private boolean mIsStateful;
 
         private Rect mPadding;
 
         private int mIntrinsicHeight;
-
         private int mIntrinsicWidth;
 
         private int mMinimumHeight;
-
         private int mMinimumWidth;
 
         private int mOpacity;
 
+        private Mode mTintMode;
+
         @Override
         public int getOpacity() {
             return mOpacity;
@@ -789,11 +803,15 @@
 
         @Override
         public boolean isStateful() {
-            return mIsStatful;
+            return mIsStateful;
         }
 
         public void setStateful(boolean isStateful) {
-            mIsStatful = isStateful;
+            mIsStateful = isStateful;
+        }
+
+        public Mode getTintMode() {
+            return mTintMode;
         }
 
         public void setPadding(Rect rect) {
@@ -832,11 +850,18 @@
             return mIntrinsicWidth;
         }
 
+        @Override
         public Drawable mutate() {
             mHasCalledMutate = true;
             return this;
         }
 
+        @Override
+        public void setTint(ColorStateList tint, Mode tintMode) {
+            mTintMode = tintMode;
+            mHasCalledSetTint = true;
+        }
+
         public void setMinimumHeight(int h) {
             mMinimumHeight = h;
         }
@@ -873,6 +898,10 @@
             return mHasCalledSetDither;
         }
 
+        public boolean hasSetTintCalled() {
+            return mHasCalledSetTint;
+        }
+
         public boolean hasOnBoundsChangedCalled() {
             return mHasCalledOnBoundsChanged;
         }
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableTestingUtils.java b/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableTestingUtils.java
new file mode 100644
index 0000000..d560906
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableTestingUtils.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2014 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.graphics.drawable.cts;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Bitmap.Config;
+import android.graphics.drawable.Drawable;
+
+public class DrawableTestingUtils {
+    public static int getPixel(Drawable d, int x, int y) {
+        final int w = Math.max(d.getIntrinsicWidth(), x + 1);
+        final int h = Math.max(d.getIntrinsicHeight(), y + 1);
+        final Bitmap b = Bitmap.createBitmap(w, h, Config.ARGB_8888);
+        final Canvas c = new Canvas(b);
+        d.setBounds(0, 0, w, h);
+        d.draw(c);
+
+        final int pixel = b.getPixel(x, y);
+        b.recycle();
+        return pixel;
+    }
+}
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/LayerDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/LayerDrawableTest.java
index 4e4648f..86772cc 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/LayerDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/LayerDrawableTest.java
@@ -301,6 +301,7 @@
 
         cb.reset();
         layerDrawable.scheduleDrawable(new BitmapDrawable(), new Runnable() {
+            @Override
             public void run() {
             }
         }, 1000L);
@@ -324,6 +325,7 @@
 
         cb.reset();
         layerDrawable.unscheduleDrawable(new BitmapDrawable(), new Runnable() {
+            @Override
             public void run() {
             }
         });
@@ -340,14 +342,17 @@
         private boolean mCalledSchedule;
         private boolean mCalledUnschedule;
 
+        @Override
         public void invalidateDrawable(Drawable who) {
             mCalledInvalidate = true;
         }
 
+        @Override
         public void scheduleDrawable(Drawable who, Runnable what, long when) {
             mCalledSchedule = true;
         }
 
+        @Override
         public void unscheduleDrawable(Drawable who, Runnable what) {
             mCalledUnschedule = true;
         }
@@ -542,7 +547,7 @@
         LayerDrawable layerDrawable = new LayerDrawable(array);
         assertFalse(layerDrawable.isStateful());
 
-        array = new Drawable[] { new BitmapDrawable(), new MockDrawable() };
+        array = new Drawable[] { new BitmapDrawable(), new MockDrawable(false) };
         layerDrawable = new LayerDrawable(array);
         assertFalse(layerDrawable.isStateful());
 
@@ -552,8 +557,8 @@
     }
 
     public void testOnStateChange() {
-        MockDrawable mockDrawable1 = new MockDrawable();
-        MockDrawable mockDrawable2 = new MockDrawable();
+        MockDrawable mockDrawable1 = new MockDrawable(true);
+        MockDrawable mockDrawable2 = new MockDrawable(true);
         Drawable[] array = new Drawable[] { mockDrawable1, mockDrawable2 };
         MockLayerDrawable layerDrawable = new MockLayerDrawable(array);
 
@@ -730,10 +735,20 @@
 
         private boolean mCalledDraw = false;
 
+        private boolean mIsStateful = false;
+
         private int mOpacity = PixelFormat.OPAQUE;
 
         Rect mPadding = null;
 
+        public MockDrawable() {
+            this(false);
+        }
+
+        public MockDrawable(boolean isStateful) {
+            mIsStateful = isStateful;
+        }
+
         @Override
         public void draw(Canvas canvas) {
             mCalledDraw = true;
@@ -813,10 +828,16 @@
             return true;
         }
 
+        @Override
+        public boolean isStateful() {
+            return mIsStateful;
+        }
+
         public boolean hasCalledSetState() {
             return mCalledSetState;
         }
 
+        @Override
         public boolean setState(final int[] stateSet) {
             increasePadding();
             mCalledSetState = true;
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/NinePatchDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/NinePatchDrawableTest.java
index 84cf41b..d02a297 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/NinePatchDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/NinePatchDrawableTest.java
@@ -21,6 +21,7 @@
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
+import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
 import android.graphics.Bitmap;
@@ -34,8 +35,11 @@
 import android.graphics.Rect;
 import android.graphics.Region;
 import android.graphics.Bitmap.Config;
+import android.graphics.PorterDuff.Mode;
 import android.graphics.drawable.NinePatchDrawable;
+import android.graphics.drawable.ShapeDrawable;
 import android.graphics.drawable.Drawable.ConstantState;
+import android.graphics.drawable.shapes.RectShape;
 import android.test.InstrumentationTestCase;
 import android.util.AttributeSet;
 import android.util.Xml;
@@ -178,6 +182,14 @@
         assertNull(mNinePatchDrawable.getPaint().getColorFilter());
     }
 
+    public void testSetTint() {
+        mNinePatchDrawable.setTint(ColorStateList.valueOf(Color.BLACK), Mode.SRC_OVER);
+        assertEquals("Nine-patch is tinted", Color.BLACK,
+                DrawableTestingUtils.getPixel(mNinePatchDrawable, 0, 0));
+
+        mNinePatchDrawable.setTint(null, null);
+    }
+
     public void testSetDither() {
         mNinePatchDrawable.setDither(false);
         assertFalse(mNinePatchDrawable.getPaint().isDither());
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/ShapeDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/ShapeDrawableTest.java
index d92b8cb..0243f24 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/ShapeDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/ShapeDrawableTest.java
@@ -16,21 +16,18 @@
 
 package android.graphics.drawable.cts;
 
-import com.android.cts.stub.R;
-
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
+import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.graphics.Canvas;
+import android.graphics.Color;
 import android.graphics.ColorFilter;
 import android.graphics.Paint;
 import android.graphics.PixelFormat;
+import android.graphics.PorterDuff.Mode;
 import android.graphics.Rect;
 import android.graphics.Shader;
-import android.graphics.drawable.ShapeDrawable;
 import android.graphics.drawable.Drawable.ConstantState;
+import android.graphics.drawable.ShapeDrawable;
 import android.graphics.drawable.ShapeDrawable.ShaderFactory;
 import android.graphics.drawable.shapes.RectShape;
 import android.graphics.drawable.shapes.Shape;
@@ -38,6 +35,11 @@
 import android.util.AttributeSet;
 import android.util.Xml;
 
+import com.android.cts.stub.R;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
 import java.io.IOException;
 
 public class ShapeDrawableTest extends AndroidTestCase {
@@ -314,6 +316,12 @@
         assertNull(shapeDrawable.getPaint().getColorFilter());
     }
 
+    public void testSetTint() {
+        final ShapeDrawable d = new ShapeDrawable(new RectShape());
+        d.setTint(ColorStateList.valueOf(Color.BLACK), Mode.SRC_OVER);
+        assertEquals("Shape is tinted", Color.BLACK, DrawableTestingUtils.getPixel(d, 0, 0));
+    }
+
     public void testSetDither() {
         ShapeDrawable shapeDrawable = new ShapeDrawable();
 
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/VectorDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/VectorDrawableTest.java
index 94c87cb..2f67560 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/VectorDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/VectorDrawableTest.java
@@ -49,6 +49,13 @@
             R.drawable.vector_icon_repeated_st,
             R.drawable.vector_icon_repeated_a_1,
             R.drawable.vector_icon_repeated_a_2,
+            R.drawable.vector_icon_clip_path_1,
+            R.drawable.vector_icon_transformation_1,
+            R.drawable.vector_icon_transformation_2,
+            R.drawable.vector_icon_transformation_3,
+            R.drawable.vector_icon_transformation_4,
+            R.drawable.vector_icon_transformation_5,
+            R.drawable.vector_icon_transformation_6,
     };
 
     private int[] mGoldenImages = new int[] {
@@ -63,6 +70,13 @@
             R.drawable.vector_icon_repeated_st_golden,
             R.drawable.vector_icon_repeated_a_1_golden,
             R.drawable.vector_icon_repeated_a_2_golden,
+            R.drawable.vector_icon_clip_path_1_golden,
+            R.drawable.vector_icon_transformation_1_golden,
+            R.drawable.vector_icon_transformation_2_golden,
+            R.drawable.vector_icon_transformation_3_golden,
+            R.drawable.vector_icon_transformation_4_golden,
+            R.drawable.vector_icon_transformation_5_golden,
+            R.drawable.vector_icon_transformation_6_golden,
     };
 
     private static final int IMAGE_WIDTH = 64;
@@ -77,7 +91,6 @@
 
     private Resources mResources;
     private VectorDrawable mVectorDrawable;
-    private BitmapFactory.Options mOptions;
     private Bitmap mBitmap;
     private Canvas mCanvas;
 
@@ -93,9 +106,6 @@
         mVectorDrawable.setBounds(0, 0, width, height);
 
         mResources = mContext.getResources();
-
-        mOptions = new BitmapFactory.Options();
-        mOptions.inScaled = false;
     }
 
     public void testSimpleVectorDrawables() throws Exception {
@@ -119,7 +129,7 @@
                 saveVectorDrawableIntoPNG(mBitmap, resIds, i);
             } else {
                 // Start to compare
-                Bitmap golden = BitmapFactory.decodeResource(mResources, goldenImages[i], mOptions);
+                Bitmap golden = BitmapFactory.decodeResource(mResources, goldenImages[i]);
                 compareImages(mBitmap, golden, mResources.getString(resIds[i]));
             }
         }
@@ -130,11 +140,16 @@
         // Save the image to the disk.
         FileOutputStream out = null;
         try {
+            String outputFolder = "/sdcard/temp/";
+            File folder = new File(outputFolder);
+            if (!folder.exists()) {
+                folder.mkdir();
+            }
             String originalFilePath = mResources.getString(resIds[index]);
             File originalFile = new File(originalFilePath);
             String fileFullName = originalFile.getName();
             String fileTitle = fileFullName.substring(0, fileFullName.lastIndexOf("."));
-            String outputFilename = "/sdcard/temp/" + fileTitle + "_golden.png";
+            String outputFilename = outputFolder + fileTitle + "_golden.png";
             File outputFile = new File(outputFilename);
             if (!outputFile.exists()) {
                 outputFile.createNewFile();
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/AllocationTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/AllocationTest.java
index f09b1f1..4caaaba 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/AllocationTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/AllocationTest.java
@@ -33,6 +33,9 @@
 import android.hardware.camera2.CaptureRequest;
 import android.hardware.camera2.CaptureResult;
 import android.hardware.camera2.TotalCaptureResult;
+import android.hardware.camera2.params.ColorSpaceTransform;
+import android.hardware.camera2.params.RggbChannelVector;
+import android.hardware.camera2.params.StreamConfigurationMap;
 import android.util.Size;
 import android.hardware.camera2.cts.helpers.MaybeNull;
 import android.hardware.camera2.cts.helpers.StaticMetadata;
@@ -149,14 +152,15 @@
 
         // Identity transform
         request.set(CaptureRequest.COLOR_CORRECTION_TRANSFORM,
-            new Rational[] {
+            new ColorSpaceTransform(new Rational[] {
                 ONE, ZERO, ZERO,
                 ZERO, ONE, ZERO,
                 ZERO, ZERO, ONE
-            });
+            }));
 
         // Identity gains
-        request.set(CaptureRequest.COLOR_CORRECTION_GAINS, new float[] { 1.0f, 1.0f, 1.0f, 1.0f });
+        request.set(CaptureRequest.COLOR_CORRECTION_GAINS,
+                new RggbChannelVector(1.0f, 1.0f, 1.0f, 1.0f ));
         request.set(CaptureRequest.TONEMAP_MODE, CaptureRequest.TONEMAP_MODE_FAST);
     }
 
@@ -766,13 +770,15 @@
 
             assertNotNull("Can't get camera properties!", properties);
 
-            int[] availableFormats = properties.get(CameraCharacteristics.SCALER_AVAILABLE_FORMATS);
-            assertArrayNotEmpty(availableFormats,
-                    "availableFormats should not be empty");
-            Arrays.sort(availableFormats);
+            StreamConfigurationMap config =
+                    properties.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
+            int[] availableOutputFormats = config.getOutputFormats();
+            assertArrayNotEmpty(availableOutputFormats,
+                    "availableOutputFormats should not be empty");
+            Arrays.sort(availableOutputFormats);
             assertTrue("Can't find the format " + format + " in supported formats " +
-                    Arrays.toString(availableFormats),
-                    Arrays.binarySearch(availableFormats, format) >= 0);
+                    Arrays.toString(availableOutputFormats),
+                    Arrays.binarySearch(availableOutputFormats, format) >= 0);
 
             Size[] availableSizes = getSupportedSizeForFormat(format, mCamera.getId(),
                     mCameraManager);
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraCharacteristicsTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraCharacteristicsTest.java
index ac5c889..bdc9198 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraCharacteristicsTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraCharacteristicsTest.java
@@ -68,10 +68,9 @@
 
                 assertNotNull("Invalid property: android.control.aeAvailableAntibandingModes",
                         props.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_ANTIBANDING_MODES));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.control.aeAvailableAntibandingModes", allKeys.contains(
                         CameraCharacteristics.CONTROL_AE_AVAILABLE_ANTIBANDING_MODES));
 
@@ -91,10 +90,9 @@
 
                 assertNotNull("Invalid property: android.control.aeAvailableModes",
                         props.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_MODES));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.control.aeAvailableModes", allKeys.contains(
                         CameraCharacteristics.CONTROL_AE_AVAILABLE_MODES));
 
@@ -114,10 +112,9 @@
 
                 assertNotNull("Invalid property: android.control.aeAvailableTargetFpsRanges",
                         props.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.control.aeAvailableTargetFpsRanges", allKeys.contains(
                         CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES));
 
@@ -137,10 +134,9 @@
 
                 assertNotNull("Invalid property: android.control.aeCompensationRange",
                         props.get(CameraCharacteristics.CONTROL_AE_COMPENSATION_RANGE));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.control.aeCompensationRange", allKeys.contains(
                         CameraCharacteristics.CONTROL_AE_COMPENSATION_RANGE));
 
@@ -160,10 +156,9 @@
 
                 assertNotNull("Invalid property: android.control.aeCompensationStep",
                         props.get(CameraCharacteristics.CONTROL_AE_COMPENSATION_STEP));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.control.aeCompensationStep", allKeys.contains(
                         CameraCharacteristics.CONTROL_AE_COMPENSATION_STEP));
 
@@ -183,10 +178,9 @@
 
                 assertNotNull("Invalid property: android.control.afAvailableModes",
                         props.get(CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.control.afAvailableModes", allKeys.contains(
                         CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES));
 
@@ -206,10 +200,9 @@
 
                 assertNotNull("Invalid property: android.control.availableEffects",
                         props.get(CameraCharacteristics.CONTROL_AVAILABLE_EFFECTS));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.control.availableEffects", allKeys.contains(
                         CameraCharacteristics.CONTROL_AVAILABLE_EFFECTS));
 
@@ -229,10 +222,9 @@
 
                 assertNotNull("Invalid property: android.control.availableSceneModes",
                         props.get(CameraCharacteristics.CONTROL_AVAILABLE_SCENE_MODES));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.control.availableSceneModes", allKeys.contains(
                         CameraCharacteristics.CONTROL_AVAILABLE_SCENE_MODES));
 
@@ -252,10 +244,9 @@
 
                 assertNotNull("Invalid property: android.control.availableVideoStabilizationModes",
                         props.get(CameraCharacteristics.CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.control.availableVideoStabilizationModes", allKeys.contains(
                         CameraCharacteristics.CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES));
 
@@ -275,10 +266,9 @@
 
                 assertNotNull("Invalid property: android.control.awbAvailableModes",
                         props.get(CameraCharacteristics.CONTROL_AWB_AVAILABLE_MODES));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.control.awbAvailableModes", allKeys.contains(
                         CameraCharacteristics.CONTROL_AWB_AVAILABLE_MODES));
 
@@ -287,7 +277,7 @@
         }
     }
 
-    public void testCameraCharacteristicsAndroidControlMaxRegions() throws Exception {
+    public void testCameraCharacteristicsAndroidControlMaxRegionsAe() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
             CameraCharacteristics props = mCameraManager.getCameraCharacteristics(ids[i]);
@@ -296,14 +286,57 @@
 
             {
 
-                assertNotNull("Invalid property: android.control.maxRegions",
-                        props.get(CameraCharacteristics.CONTROL_MAX_REGIONS));
-
+                assertNotNull("Invalid property: android.control.maxRegionsAe",
+                        props.get(CameraCharacteristics.CONTROL_MAX_REGIONS_AE));
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
-                assertTrue("Key not in keys list: android.control.maxRegions", allKeys.contains(
-                        CameraCharacteristics.CONTROL_MAX_REGIONS));
+                        ids[i]), allKeys);
+                assertTrue("Key not in keys list: android.control.maxRegionsAe", allKeys.contains(
+                        CameraCharacteristics.CONTROL_MAX_REGIONS_AE));
+
+            }
+
+        }
+    }
+
+    public void testCameraCharacteristicsAndroidControlMaxRegionsAwb() throws Exception {
+        String[] ids = mCameraManager.getCameraIdList();
+        for (int i = 0; i < ids.length; i++) {
+            CameraCharacteristics props = mCameraManager.getCameraCharacteristics(ids[i]);
+            assertNotNull(String.format("Can't get camera characteristics from: ID %s", ids[i]),
+                                        props);
+
+            {
+
+                assertNotNull("Invalid property: android.control.maxRegionsAwb",
+                        props.get(CameraCharacteristics.CONTROL_MAX_REGIONS_AWB));
+                List<Key<?>> allKeys = props.getKeys();
+                assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
+                        ids[i]), allKeys);
+                assertTrue("Key not in keys list: android.control.maxRegionsAwb", allKeys.contains(
+                        CameraCharacteristics.CONTROL_MAX_REGIONS_AWB));
+
+            }
+
+        }
+    }
+
+    public void testCameraCharacteristicsAndroidControlMaxRegionsAf() throws Exception {
+        String[] ids = mCameraManager.getCameraIdList();
+        for (int i = 0; i < ids.length; i++) {
+            CameraCharacteristics props = mCameraManager.getCameraCharacteristics(ids[i]);
+            assertNotNull(String.format("Can't get camera characteristics from: ID %s", ids[i]),
+                                        props);
+
+            {
+
+                assertNotNull("Invalid property: android.control.maxRegionsAf",
+                        props.get(CameraCharacteristics.CONTROL_MAX_REGIONS_AF));
+                List<Key<?>> allKeys = props.getKeys();
+                assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
+                        ids[i]), allKeys);
+                assertTrue("Key not in keys list: android.control.maxRegionsAf", allKeys.contains(
+                        CameraCharacteristics.CONTROL_MAX_REGIONS_AF));
 
             }
 
@@ -321,10 +354,9 @@
 
                 assertNotNull("Invalid property: android.edge.availableEdgeModes",
                         props.get(CameraCharacteristics.EDGE_AVAILABLE_EDGE_MODES));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.edge.availableEdgeModes", allKeys.contains(
                         CameraCharacteristics.EDGE_AVAILABLE_EDGE_MODES));
 
@@ -344,10 +376,9 @@
 
                 assertNotNull("Invalid property: android.flash.info.available",
                         props.get(CameraCharacteristics.FLASH_INFO_AVAILABLE));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.flash.info.available", allKeys.contains(
                         CameraCharacteristics.FLASH_INFO_AVAILABLE));
 
@@ -367,10 +398,9 @@
 
                 assertNotNull("Invalid property: android.hotPixel.availableHotPixelModes",
                         props.get(CameraCharacteristics.HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.hotPixel.availableHotPixelModes", allKeys.contains(
                         CameraCharacteristics.HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES));
 
@@ -390,10 +420,9 @@
 
                 assertNotNull("Invalid property: android.jpeg.availableThumbnailSizes",
                         props.get(CameraCharacteristics.JPEG_AVAILABLE_THUMBNAIL_SIZES));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.jpeg.availableThumbnailSizes", allKeys.contains(
                         CameraCharacteristics.JPEG_AVAILABLE_THUMBNAIL_SIZES));
 
@@ -413,10 +442,9 @@
 
                 assertNotNull("Invalid property: android.lens.facing",
                         props.get(CameraCharacteristics.LENS_FACING));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.lens.facing", allKeys.contains(
                         CameraCharacteristics.LENS_FACING));
 
@@ -436,10 +464,9 @@
 
                 assertNotNull("Invalid property: android.lens.info.availableApertures",
                         props.get(CameraCharacteristics.LENS_INFO_AVAILABLE_APERTURES));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.lens.info.availableApertures", allKeys.contains(
                         CameraCharacteristics.LENS_INFO_AVAILABLE_APERTURES));
 
@@ -459,10 +486,9 @@
 
                 assertNotNull("Invalid property: android.lens.info.availableFilterDensities",
                         props.get(CameraCharacteristics.LENS_INFO_AVAILABLE_FILTER_DENSITIES));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.lens.info.availableFilterDensities", allKeys.contains(
                         CameraCharacteristics.LENS_INFO_AVAILABLE_FILTER_DENSITIES));
 
@@ -482,10 +508,9 @@
 
                 assertNotNull("Invalid property: android.lens.info.availableFocalLengths",
                         props.get(CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.lens.info.availableFocalLengths", allKeys.contains(
                         CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS));
 
@@ -505,10 +530,9 @@
 
                 assertNotNull("Invalid property: android.lens.info.availableOpticalStabilization",
                         props.get(CameraCharacteristics.LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.lens.info.availableOpticalStabilization", allKeys.contains(
                         CameraCharacteristics.LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION));
 
@@ -532,10 +556,9 @@
 
                 assertNotNull("Invalid property: android.lens.info.hyperfocalDistance",
                         props.get(CameraCharacteristics.LENS_INFO_HYPERFOCAL_DISTANCE));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.lens.info.hyperfocalDistance", allKeys.contains(
                         CameraCharacteristics.LENS_INFO_HYPERFOCAL_DISTANCE));
 
@@ -555,10 +578,9 @@
 
                 assertNotNull("Invalid property: android.lens.info.minimumFocusDistance",
                         props.get(CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.lens.info.minimumFocusDistance", allKeys.contains(
                         CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE));
 
@@ -567,29 +589,6 @@
         }
     }
 
-    public void testCameraCharacteristicsAndroidLensInfoShadingMapSize() throws Exception {
-        String[] ids = mCameraManager.getCameraIdList();
-        for (int i = 0; i < ids.length; i++) {
-            CameraCharacteristics props = mCameraManager.getCameraCharacteristics(ids[i]);
-            assertNotNull(String.format("Can't get camera characteristics from: ID %s", ids[i]),
-                                        props);
-
-            {
-
-                assertNotNull("Invalid property: android.lens.info.shadingMapSize",
-                        props.get(CameraCharacteristics.LENS_INFO_SHADING_MAP_SIZE));
-
-                List<Key<?>> allKeys = props.getKeys();
-                assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
-                assertTrue("Key not in keys list: android.lens.info.shadingMapSize", allKeys.contains(
-                        CameraCharacteristics.LENS_INFO_SHADING_MAP_SIZE));
-
-            }
-
-        }
-    }
-
     public void testCameraCharacteristicsAndroidLensInfoFocusDistanceCalibration() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
@@ -601,10 +600,9 @@
 
                 assertNotNull("Invalid property: android.lens.info.focusDistanceCalibration",
                         props.get(CameraCharacteristics.LENS_INFO_FOCUS_DISTANCE_CALIBRATION));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.lens.info.focusDistanceCalibration", allKeys.contains(
                         CameraCharacteristics.LENS_INFO_FOCUS_DISTANCE_CALIBRATION));
 
@@ -624,10 +622,9 @@
 
                 assertNotNull("Invalid property: android.noiseReduction.availableNoiseReductionModes",
                         props.get(CameraCharacteristics.NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.noiseReduction.availableNoiseReductionModes", allKeys.contains(
                         CameraCharacteristics.NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES));
 
@@ -636,7 +633,7 @@
         }
     }
 
-    public void testCameraCharacteristicsAndroidRequestMaxNumOutputStreams() throws Exception {
+    public void testCameraCharacteristicsAndroidRequestMaxNumOutputRaw() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
             CameraCharacteristics props = mCameraManager.getCameraCharacteristics(ids[i]);
@@ -645,21 +642,20 @@
 
             {
 
-                assertNotNull("Invalid property: android.request.maxNumOutputStreams",
-                        props.get(CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_STREAMS));
-
+                assertNotNull("Invalid property: android.request.maxNumOutputRaw",
+                        props.get(CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_RAW));
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
-                assertTrue("Key not in keys list: android.request.maxNumOutputStreams", allKeys.contains(
-                        CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_STREAMS));
+                        ids[i]), allKeys);
+                assertTrue("Key not in keys list: android.request.maxNumOutputRaw", allKeys.contains(
+                        CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_RAW));
 
             }
 
         }
     }
 
-    public void testCameraCharacteristicsAndroidRequestMaxNumInputStreams() throws Exception {
+    public void testCameraCharacteristicsAndroidRequestMaxNumOutputProc() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
             CameraCharacteristics props = mCameraManager.getCameraCharacteristics(ids[i]);
@@ -668,14 +664,35 @@
 
             {
 
-                assertNotNull("Invalid property: android.request.maxNumInputStreams",
-                        props.get(CameraCharacteristics.REQUEST_MAX_NUM_INPUT_STREAMS));
-
+                assertNotNull("Invalid property: android.request.maxNumOutputProc",
+                        props.get(CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_PROC));
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
-                assertTrue("Key not in keys list: android.request.maxNumInputStreams", allKeys.contains(
-                        CameraCharacteristics.REQUEST_MAX_NUM_INPUT_STREAMS));
+                        ids[i]), allKeys);
+                assertTrue("Key not in keys list: android.request.maxNumOutputProc", allKeys.contains(
+                        CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_PROC));
+
+            }
+
+        }
+    }
+
+    public void testCameraCharacteristicsAndroidRequestMaxNumOutputProcStalling() throws Exception {
+        String[] ids = mCameraManager.getCameraIdList();
+        for (int i = 0; i < ids.length; i++) {
+            CameraCharacteristics props = mCameraManager.getCameraCharacteristics(ids[i]);
+            assertNotNull(String.format("Can't get camera characteristics from: ID %s", ids[i]),
+                                        props);
+
+            {
+
+                assertNotNull("Invalid property: android.request.maxNumOutputProcStalling",
+                        props.get(CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_PROC_STALLING));
+                List<Key<?>> allKeys = props.getKeys();
+                assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
+                        ids[i]), allKeys);
+                assertTrue("Key not in keys list: android.request.maxNumOutputProcStalling", allKeys.contains(
+                        CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_PROC_STALLING));
 
             }
 
@@ -693,10 +710,9 @@
 
                 assertNotNull("Invalid property: android.request.pipelineMaxDepth",
                         props.get(CameraCharacteristics.REQUEST_PIPELINE_MAX_DEPTH));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.request.pipelineMaxDepth", allKeys.contains(
                         CameraCharacteristics.REQUEST_PIPELINE_MAX_DEPTH));
 
@@ -716,10 +732,9 @@
 
                 assertNotNull("Invalid property: android.request.partialResultCount",
                         props.get(CameraCharacteristics.REQUEST_PARTIAL_RESULT_COUNT));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.request.partialResultCount", allKeys.contains(
                         CameraCharacteristics.REQUEST_PARTIAL_RESULT_COUNT));
 
@@ -739,10 +754,9 @@
 
                 assertNotNull("Invalid property: android.request.availableCapabilities",
                         props.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.request.availableCapabilities", allKeys.contains(
                         CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES));
 
@@ -762,10 +776,9 @@
 
                 assertNotNull("Invalid property: android.scaler.availableMaxDigitalZoom",
                         props.get(CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.scaler.availableMaxDigitalZoom", allKeys.contains(
                         CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM));
 
@@ -785,10 +798,9 @@
 
                 assertNotNull("Invalid property: android.scaler.streamConfigurationMap",
                         props.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.scaler.streamConfigurationMap", allKeys.contains(
                         CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP));
 
@@ -808,10 +820,9 @@
 
                 assertNotNull("Invalid property: android.scaler.croppingType",
                         props.get(CameraCharacteristics.SCALER_CROPPING_TYPE));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.scaler.croppingType", allKeys.contains(
                         CameraCharacteristics.SCALER_CROPPING_TYPE));
 
@@ -831,10 +842,9 @@
 
                 assertNotNull("Invalid property: android.sensor.referenceIlluminant1",
                         props.get(CameraCharacteristics.SENSOR_REFERENCE_ILLUMINANT1));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.sensor.referenceIlluminant1", allKeys.contains(
                         CameraCharacteristics.SENSOR_REFERENCE_ILLUMINANT1));
 
@@ -854,10 +864,9 @@
 
                 assertNotNull("Invalid property: android.sensor.referenceIlluminant2",
                         props.get(CameraCharacteristics.SENSOR_REFERENCE_ILLUMINANT2));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.sensor.referenceIlluminant2", allKeys.contains(
                         CameraCharacteristics.SENSOR_REFERENCE_ILLUMINANT2));
 
@@ -881,10 +890,9 @@
 
                 assertNotNull("Invalid property: android.sensor.calibrationTransform1",
                         props.get(CameraCharacteristics.SENSOR_CALIBRATION_TRANSFORM1));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.sensor.calibrationTransform1", allKeys.contains(
                         CameraCharacteristics.SENSOR_CALIBRATION_TRANSFORM1));
 
@@ -908,10 +916,9 @@
 
                 assertNotNull("Invalid property: android.sensor.calibrationTransform2",
                         props.get(CameraCharacteristics.SENSOR_CALIBRATION_TRANSFORM2));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.sensor.calibrationTransform2", allKeys.contains(
                         CameraCharacteristics.SENSOR_CALIBRATION_TRANSFORM2));
 
@@ -935,10 +942,9 @@
 
                 assertNotNull("Invalid property: android.sensor.colorTransform1",
                         props.get(CameraCharacteristics.SENSOR_COLOR_TRANSFORM1));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.sensor.colorTransform1", allKeys.contains(
                         CameraCharacteristics.SENSOR_COLOR_TRANSFORM1));
 
@@ -962,10 +968,9 @@
 
                 assertNotNull("Invalid property: android.sensor.colorTransform2",
                         props.get(CameraCharacteristics.SENSOR_COLOR_TRANSFORM2));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.sensor.colorTransform2", allKeys.contains(
                         CameraCharacteristics.SENSOR_COLOR_TRANSFORM2));
 
@@ -989,10 +994,9 @@
 
                 assertNotNull("Invalid property: android.sensor.forwardMatrix1",
                         props.get(CameraCharacteristics.SENSOR_FORWARD_MATRIX1));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.sensor.forwardMatrix1", allKeys.contains(
                         CameraCharacteristics.SENSOR_FORWARD_MATRIX1));
 
@@ -1016,10 +1020,9 @@
 
                 assertNotNull("Invalid property: android.sensor.forwardMatrix2",
                         props.get(CameraCharacteristics.SENSOR_FORWARD_MATRIX2));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.sensor.forwardMatrix2", allKeys.contains(
                         CameraCharacteristics.SENSOR_FORWARD_MATRIX2));
 
@@ -1043,10 +1046,9 @@
 
                 assertNotNull("Invalid property: android.sensor.blackLevelPattern",
                         props.get(CameraCharacteristics.SENSOR_BLACK_LEVEL_PATTERN));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.sensor.blackLevelPattern", allKeys.contains(
                         CameraCharacteristics.SENSOR_BLACK_LEVEL_PATTERN));
 
@@ -1070,10 +1072,9 @@
 
                 assertNotNull("Invalid property: android.sensor.maxAnalogSensitivity",
                         props.get(CameraCharacteristics.SENSOR_MAX_ANALOG_SENSITIVITY));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.sensor.maxAnalogSensitivity", allKeys.contains(
                         CameraCharacteristics.SENSOR_MAX_ANALOG_SENSITIVITY));
 
@@ -1093,10 +1094,9 @@
 
                 assertNotNull("Invalid property: android.sensor.orientation",
                         props.get(CameraCharacteristics.SENSOR_ORIENTATION));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.sensor.orientation", allKeys.contains(
                         CameraCharacteristics.SENSOR_ORIENTATION));
 
@@ -1120,10 +1120,9 @@
 
                 assertNotNull("Invalid property: android.sensor.availableTestPatternModes",
                         props.get(CameraCharacteristics.SENSOR_AVAILABLE_TEST_PATTERN_MODES));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.sensor.availableTestPatternModes", allKeys.contains(
                         CameraCharacteristics.SENSOR_AVAILABLE_TEST_PATTERN_MODES));
 
@@ -1143,10 +1142,9 @@
 
                 assertNotNull("Invalid property: android.sensor.info.activeArraySize",
                         props.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.sensor.info.activeArraySize", allKeys.contains(
                         CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE));
 
@@ -1166,10 +1164,9 @@
 
                 assertNotNull("Invalid property: android.sensor.info.sensitivityRange",
                         props.get(CameraCharacteristics.SENSOR_INFO_SENSITIVITY_RANGE));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.sensor.info.sensitivityRange", allKeys.contains(
                         CameraCharacteristics.SENSOR_INFO_SENSITIVITY_RANGE));
 
@@ -1189,10 +1186,9 @@
 
                 assertNotNull("Invalid property: android.sensor.info.colorFilterArrangement",
                         props.get(CameraCharacteristics.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.sensor.info.colorFilterArrangement", allKeys.contains(
                         CameraCharacteristics.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT));
 
@@ -1212,10 +1208,9 @@
 
                 assertNotNull("Invalid property: android.sensor.info.exposureTimeRange",
                         props.get(CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.sensor.info.exposureTimeRange", allKeys.contains(
                         CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE));
 
@@ -1235,10 +1230,9 @@
 
                 assertNotNull("Invalid property: android.sensor.info.maxFrameDuration",
                         props.get(CameraCharacteristics.SENSOR_INFO_MAX_FRAME_DURATION));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.sensor.info.maxFrameDuration", allKeys.contains(
                         CameraCharacteristics.SENSOR_INFO_MAX_FRAME_DURATION));
 
@@ -1258,10 +1252,9 @@
 
                 assertNotNull("Invalid property: android.sensor.info.physicalSize",
                         props.get(CameraCharacteristics.SENSOR_INFO_PHYSICAL_SIZE));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.sensor.info.physicalSize", allKeys.contains(
                         CameraCharacteristics.SENSOR_INFO_PHYSICAL_SIZE));
 
@@ -1281,10 +1274,9 @@
 
                 assertNotNull("Invalid property: android.sensor.info.pixelArraySize",
                         props.get(CameraCharacteristics.SENSOR_INFO_PIXEL_ARRAY_SIZE));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.sensor.info.pixelArraySize", allKeys.contains(
                         CameraCharacteristics.SENSOR_INFO_PIXEL_ARRAY_SIZE));
 
@@ -1304,10 +1296,9 @@
 
                 assertNotNull("Invalid property: android.sensor.info.whiteLevel",
                         props.get(CameraCharacteristics.SENSOR_INFO_WHITE_LEVEL));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.sensor.info.whiteLevel", allKeys.contains(
                         CameraCharacteristics.SENSOR_INFO_WHITE_LEVEL));
 
@@ -1316,6 +1307,28 @@
         }
     }
 
+    public void testCameraCharacteristicsAndroidSensorInfoTimestampCalibration() throws Exception {
+        String[] ids = mCameraManager.getCameraIdList();
+        for (int i = 0; i < ids.length; i++) {
+            CameraCharacteristics props = mCameraManager.getCameraCharacteristics(ids[i]);
+            assertNotNull(String.format("Can't get camera characteristics from: ID %s", ids[i]),
+                                        props);
+
+            {
+
+                assertNotNull("Invalid property: android.sensor.info.timestampCalibration",
+                        props.get(CameraCharacteristics.SENSOR_INFO_TIMESTAMP_CALIBRATION));
+                List<Key<?>> allKeys = props.getKeys();
+                assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
+                        ids[i]), allKeys);
+                assertTrue("Key not in keys list: android.sensor.info.timestampCalibration", allKeys.contains(
+                        CameraCharacteristics.SENSOR_INFO_TIMESTAMP_CALIBRATION));
+
+            }
+
+        }
+    }
+
     public void testCameraCharacteristicsAndroidStatisticsInfoAvailableFaceDetectModes() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
@@ -1327,10 +1340,9 @@
 
                 assertNotNull("Invalid property: android.statistics.info.availableFaceDetectModes",
                         props.get(CameraCharacteristics.STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.statistics.info.availableFaceDetectModes", allKeys.contains(
                         CameraCharacteristics.STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES));
 
@@ -1350,10 +1362,9 @@
 
                 assertNotNull("Invalid property: android.statistics.info.maxFaceCount",
                         props.get(CameraCharacteristics.STATISTICS_INFO_MAX_FACE_COUNT));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.statistics.info.maxFaceCount", allKeys.contains(
                         CameraCharacteristics.STATISTICS_INFO_MAX_FACE_COUNT));
 
@@ -1373,10 +1384,9 @@
 
                 assertNotNull("Invalid property: android.statistics.info.availableHotPixelMapModes",
                         props.get(CameraCharacteristics.STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.statistics.info.availableHotPixelMapModes", allKeys.contains(
                         CameraCharacteristics.STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES));
 
@@ -1396,10 +1406,9 @@
 
                 assertNotNull("Invalid property: android.tonemap.maxCurvePoints",
                         props.get(CameraCharacteristics.TONEMAP_MAX_CURVE_POINTS));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.tonemap.maxCurvePoints", allKeys.contains(
                         CameraCharacteristics.TONEMAP_MAX_CURVE_POINTS));
 
@@ -1419,10 +1428,9 @@
 
                 assertNotNull("Invalid property: android.tonemap.availableToneMapModes",
                         props.get(CameraCharacteristics.TONEMAP_AVAILABLE_TONE_MAP_MODES));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.tonemap.availableToneMapModes", allKeys.contains(
                         CameraCharacteristics.TONEMAP_AVAILABLE_TONE_MAP_MODES));
 
@@ -1442,10 +1450,9 @@
 
                 assertNotNull("Invalid property: android.info.supportedHardwareLevel",
                         props.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.info.supportedHardwareLevel", allKeys.contains(
                         CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL));
 
@@ -1465,10 +1472,9 @@
 
                 assertNotNull("Invalid property: android.sync.maxLatency",
                         props.get(CameraCharacteristics.SYNC_MAX_LATENCY));
-
                 List<Key<?>> allKeys = props.getKeys();
                 assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
+                        ids[i]), allKeys);
                 assertTrue("Key not in keys list: android.sync.maxLatency", allKeys.contains(
                         CameraCharacteristics.SYNC_MAX_LATENCY));
 
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraDeviceTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraDeviceTest.java
index d7cacd3..07a93bd 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraDeviceTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraDeviceTest.java
@@ -18,11 +18,14 @@
 
 import static android.hardware.camera2.cts.CameraTestUtils.*;
 import static com.android.ex.camera2.blocking.BlockingStateListener.*;
+import static com.android.ex.camera2.blocking.BlockingSessionListener.*;
 import static org.mockito.Mockito.*;
 import static android.hardware.camera2.CaptureRequest.*;
 
 import android.content.Context;
 import android.graphics.ImageFormat;
+import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CameraCaptureSession;
 import android.hardware.camera2.CameraCharacteristics;
 import android.hardware.camera2.CameraDevice;
 import android.hardware.camera2.CaptureFailure;
@@ -30,11 +33,15 @@
 import android.hardware.camera2.CaptureResult;
 import android.hardware.camera2.TotalCaptureResult;
 import android.hardware.camera2.cts.testcases.Camera2AndroidTestCase;
+import android.os.Handler;
 import android.os.SystemClock;
 import android.util.Log;
+import android.util.Range;
 import android.view.Surface;
 
+import com.android.ex.camera2.blocking.BlockingSessionListener;
 import com.android.ex.camera2.blocking.BlockingStateListener;
+import com.android.ex.camera2.utils.StateWaiter;
 
 import org.mockito.ArgumentMatcher;
 
@@ -52,12 +59,14 @@
     private static final int REPEATING_CAPTURE_EXPECTED_RESULT_COUNT = 5;
     private static final int MAX_NUM_IMAGES = 5;
     private static final int MIN_FPS_REQUIRED_FOR_STREAMING = 20;
-    private static final int AE_REGION_INDEX = 0;
-    private static final int AWB_REGION_INDEX = 1;
-    private static final int AF_REGION_INDEX = 2;
+
+    private CameraCaptureSession mSession;
 
     private BlockingStateListener mCameraMockListener;
-    private int mLatestState = STATE_UNINITIALIZED;
+    private int mLatestDeviceState = STATE_UNINITIALIZED;
+    private BlockingSessionListener mSessionMockListener;
+    private StateWaiter mSessionWaiter;
+    private int mLatestSessionState = -1; // uninitialized
 
     private static int[] mTemplates = new int[] {
             CameraDevice.TEMPLATE_PREVIEW,
@@ -246,7 +255,11 @@
                 }
             }
             finally {
-                closeDevice(mCameraIds[i], mCameraMockListener);
+                try {
+                    closeSession();
+                } finally {
+                    closeDevice(mCameraIds[i], mCameraMockListener);
+                }
             }
         }
     }
@@ -266,7 +279,11 @@
                                 anyInt());
             }
             finally {
-                closeDevice(mCameraIds[i], mCameraMockListener);
+                try {
+                    closeSession();
+                } finally {
+                    closeDevice(mCameraIds[i], mCameraMockListener);
+                }
             }
         }
     }
@@ -323,19 +340,27 @@
         for (int i = 0; i < mCameraIds.length; i++) {
             try {
                 openDevice(mCameraIds[i], mCameraMockListener);
-                waitForState(STATE_UNCONFIGURED, CAMERA_OPEN_TIMEOUT_MS);
+                waitForDeviceState(STATE_OPENED, CAMERA_OPEN_TIMEOUT_MS);
 
                 prepareCapture();
 
                 invalidRequestCaptureTestByCamera();
+
+                closeSession();
             }
             finally {
-                closeDevice(mCameraIds[i], mCameraMockListener);
+                try {
+
+                } finally {
+                    closeDevice(mCameraIds[i], mCameraMockListener);
+                }
             }
         }
     }
 
     private void invalidRequestCaptureTestByCamera() throws Exception {
+        if (VERBOSE) Log.v(TAG, "invalidRequestCaptureTestByCamera");
+
         List<CaptureRequest> emptyRequests = new ArrayList<CaptureRequest>();
         CaptureRequest.Builder requestBuilder =
                 mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
@@ -344,8 +369,8 @@
         unConfiguredRequests.add(unConfiguredRequest);
 
         try {
-            // Test: CameraDevice capture should throw IAE for null request.
-            mCamera.capture(/*request*/null, /*listener*/null, mHandler);
+            // Test: CameraCaptureSession capture should throw IAE for null request.
+            mSession.capture(/*request*/null, /*listener*/null, mHandler);
             mCollector.addMessage(
                     "CameraDevice capture should throw IllegalArgumentException for null request");
         } catch (IllegalArgumentException e) {
@@ -353,9 +378,9 @@
         }
 
         try {
-            // Test: CameraDevice capture should throw IAE for request
+            // Test: CameraCaptureSession capture should throw IAE for request
             // without surface configured.
-            mCamera.capture(unConfiguredRequest, /*listener*/null, mHandler);
+            mSession.capture(unConfiguredRequest, /*listener*/null, mHandler);
             mCollector.addMessage("CameraDevice capture should throw " +
                     "IllegalArgumentException for request without surface configured");
         } catch (IllegalArgumentException e) {
@@ -363,8 +388,8 @@
         }
 
         try {
-            // Test: CameraDevice setRepeatingRequest should throw IAE for null request.
-            mCamera.setRepeatingRequest(/*request*/null, /*listener*/null, mHandler);
+            // Test: CameraCaptureSession setRepeatingRequest should throw IAE for null request.
+            mSession.setRepeatingRequest(/*request*/null, /*listener*/null, mHandler);
             mCollector.addMessage("CameraDevice setRepeatingRequest should throw" +
                     "IllegalArgumentException for null request");
         } catch (IllegalArgumentException e) {
@@ -372,9 +397,9 @@
         }
 
         try {
-            // Test: CameraDevice setRepeatingRequest should throw IAE for for request
+            // Test: CameraCaptureSession setRepeatingRequest should throw IAE for for request
             // without surface configured.
-            mCamera.setRepeatingRequest(unConfiguredRequest, /*listener*/null, mHandler);
+            mSession.setRepeatingRequest(unConfiguredRequest, /*listener*/null, mHandler);
             mCollector.addMessage("Capture zero burst should throw IllegalArgumentException" +
                     "for request without surface configured");
         } catch (IllegalArgumentException e) {
@@ -382,8 +407,8 @@
         }
 
         try {
-            // Test: CameraDevice captureBurst should throw IAE for null request list.
-            mCamera.captureBurst(/*requests*/null, /*listener*/null, mHandler);
+            // Test: CameraCaptureSession captureBurst should throw IAE for null request list.
+            mSession.captureBurst(/*requests*/null, /*listener*/null, mHandler);
             mCollector.addMessage("CameraDevice captureBurst should throw" +
                     "IllegalArgumentException for null request list");
         } catch (IllegalArgumentException e) {
@@ -391,8 +416,8 @@
         }
 
         try {
-            // Test: CameraDevice captureBurst should throw IAE for empty request list.
-            mCamera.captureBurst(emptyRequests, /*listener*/null, mHandler);
+            // Test: CameraCaptureSession captureBurst should throw IAE for empty request list.
+            mSession.captureBurst(emptyRequests, /*listener*/null, mHandler);
             mCollector.addMessage("CameraDevice captureBurst should throw" +
                     " IllegalArgumentException for empty request list");
         } catch (IllegalArgumentException e) {
@@ -400,9 +425,9 @@
         }
 
         try {
-            // Test: CameraDevice captureBurst should throw IAE for request
+            // Test: CameraCaptureSession captureBurst should throw IAE for request
             // without surface configured.
-            mCamera.captureBurst(unConfiguredRequests, /*listener*/null, mHandler);
+            mSession.captureBurst(unConfiguredRequests, /*listener*/null, mHandler);
             fail("CameraDevice captureBurst should throw IllegalArgumentException" +
                     "for null request list");
         } catch (IllegalArgumentException e) {
@@ -410,8 +435,8 @@
         }
 
         try {
-            // Test: CameraDevice setRepeatingBurst should throw IAE for null request list.
-            mCamera.setRepeatingBurst(/*requests*/null, /*listener*/null, mHandler);
+            // Test: CameraCaptureSession setRepeatingBurst should throw IAE for null request list.
+            mSession.setRepeatingBurst(/*requests*/null, /*listener*/null, mHandler);
             mCollector.addMessage("CameraDevice setRepeatingBurst should throw" +
                     "IllegalArgumentException for null request list");
         } catch (IllegalArgumentException e) {
@@ -419,8 +444,8 @@
         }
 
         try {
-            // Test: CameraDevice setRepeatingBurst should throw IAE for empty request list.
-            mCamera.setRepeatingBurst(emptyRequests, /*listener*/null, mHandler);
+            // Test: CameraCaptureSession setRepeatingBurst should throw IAE for empty request list.
+            mSession.setRepeatingBurst(emptyRequests, /*listener*/null, mHandler);
             mCollector.addMessage("CameraDevice setRepeatingBurst should throw" +
                     "IllegalArgumentException for empty request list");
         } catch (IllegalArgumentException e) {
@@ -428,9 +453,9 @@
         }
 
         try {
-            // Test: CameraDevice setRepeatingBurst should throw IAE for request
+            // Test: CameraCaptureSession setRepeatingBurst should throw IAE for request
             // without surface configured.
-            mCamera.setRepeatingBurst(unConfiguredRequests, /*listener*/null, mHandler);
+            mSession.setRepeatingBurst(unConfiguredRequests, /*listener*/null, mHandler);
             mCollector.addMessage("CameraDevice setRepeatingBurst should throw" +
                     "IllegalArgumentException for request without surface configured");
         } catch (IllegalArgumentException e) {
@@ -469,7 +494,7 @@
         for (int i = 0; i < mCameraIds.length; i++) {
             try {
                 openDevice(mCameraIds[i], mCameraMockListener);
-                waitForState(STATE_UNCONFIGURED, CAMERA_OPEN_TIMEOUT_MS);
+                waitForDeviceState(STATE_OPENED, CAMERA_OPEN_TIMEOUT_MS);
 
                 prepareCapture();
 
@@ -504,7 +529,11 @@
                                 anyInt());
             }
             finally {
-                closeDevice(mCameraIds[i], mCameraMockListener);
+                try {
+                    closeSession();
+                } finally {
+                    closeDevice(mCameraIds[i], mCameraMockListener);
+                }
             }
         }
     }
@@ -515,13 +544,13 @@
             boolean repeating, boolean flush) throws Exception {
 
         assertEquals("Bad initial state for preparing to capture",
-                mLatestState, STATE_IDLE);
+                mLatestSessionState, SESSION_READY);
 
         CaptureRequest.Builder requestBuilder = mCamera.createCaptureRequest(template);
         assertNotNull("Failed to create capture request", requestBuilder);
         requestBuilder.addTarget(mReaderSurface);
-        CameraDevice.CaptureListener mockCaptureListener =
-                mock(CameraDevice.CaptureListener.class);
+        CameraCaptureSession.CaptureListener mockCaptureListener =
+                mock(CameraCaptureSession.CaptureListener.class);
 
         if (VERBOSE) {
             Log.v(TAG, String.format("Capturing shot for device %s, template %d",
@@ -529,19 +558,19 @@
         }
 
         startCapture(requestBuilder.build(), repeating, mockCaptureListener, mHandler);
-        waitForState(STATE_ACTIVE, CAMERA_CONFIGURE_TIMEOUT_MS);
+        waitForSessionState(SESSION_ACTIVE, SESSION_ACTIVE_TIMEOUT_MS);
 
         int expectedCaptureResultCount = repeating ? REPEATING_CAPTURE_EXPECTED_RESULT_COUNT : 1;
         verifyCaptureResults(mockCaptureListener, expectedCaptureResultCount);
 
         if (repeating) {
             if (flush) {
-                mCamera.flush();
+                mSession.abortCaptures();
             } else {
-                mCamera.stopRepeating();
+                mSession.stopRepeating();
             }
         }
-        waitForState(STATE_IDLE, CAMERA_CONFIGURE_TIMEOUT_MS);
+        waitForSessionState(SESSION_READY, SESSION_READY_TIMEOUT_MS);
     }
 
     private void captureBurstShot(
@@ -552,7 +581,7 @@
             boolean flush) throws Exception {
 
         assertEquals("Bad initial state for preparing to capture",
-                mLatestState, STATE_IDLE);
+                mLatestSessionState, SESSION_READY);
 
         assertTrue("Invalid args to capture function", len <= templates.length);
         List<CaptureRequest> requests = new ArrayList<CaptureRequest>();
@@ -562,20 +591,20 @@
             requestBuilder.addTarget(mReaderSurface);
             requests.add(requestBuilder.build());
         }
-        CameraDevice.CaptureListener mockCaptureListener =
-                mock(CameraDevice.CaptureListener.class);
+        CameraCaptureSession.CaptureListener mockCaptureListener =
+                mock(CameraCaptureSession.CaptureListener.class);
 
         if (VERBOSE) {
             Log.v(TAG, String.format("Capturing burst shot for device %s", id));
         }
 
         if (!repeating) {
-            mCamera.captureBurst(requests, mockCaptureListener, mHandler);
+            mSession.captureBurst(requests, mockCaptureListener, mHandler);
         }
         else {
-            mCamera.setRepeatingBurst(requests, mockCaptureListener, mHandler);
+            mSession.setRepeatingBurst(requests, mockCaptureListener, mHandler);
         }
-        waitForState(STATE_ACTIVE, CAMERA_CONFIGURE_TIMEOUT_MS);
+        waitForSessionState(SESSION_ACTIVE, SESSION_READY_TIMEOUT_MS);
 
         int expectedResultCount = len;
         if (repeating) {
@@ -586,83 +615,96 @@
 
         if (repeating) {
             if (flush) {
-                mCamera.flush();
+                mSession.abortCaptures();
             } else {
-                mCamera.stopRepeating();
+                mSession.stopRepeating();
             }
         }
-        waitForState(STATE_IDLE, CAMERA_CONFIGURE_TIMEOUT_MS);
+        waitForSessionState(SESSION_READY, SESSION_READY_TIMEOUT_MS);
     }
 
-    // Precondition: Device must be in known IDLE/UNCONFIGURED state (has been waited for)
+    /**
+     * Precondition: Device must be in known OPENED state (has been waited for).
+     *
+     * <p>Creates a new capture session and waits until it is in the {@code SESSION_READY} state.
+     * </p>
+     *
+     * <p>Any existing capture session will be closed as a result of calling this.</p>
+     * */
     private void prepareCapture() throws Exception {
-        assertTrue("Bad initial state for preparing to capture",
-                mLatestState == STATE_IDLE || mLatestState == STATE_UNCONFIGURED);
+        if (VERBOSE) Log.v(TAG, "prepareCapture");
 
-        List<Surface> outputSurfaces = new ArrayList<Surface>(1);
-        outputSurfaces.add(mReaderSurface);
-        mCamera.configureOutputs(outputSurfaces);
-        waitForState(STATE_BUSY, CAMERA_BUSY_TIMEOUT_MS);
-        waitForState(STATE_IDLE, CAMERA_IDLE_TIMEOUT_MS);
+        assertTrue("Bad initial state for preparing to capture",
+                mLatestDeviceState == STATE_OPENED);
+
+        if (mSession != null) {
+            if (VERBOSE) Log.v(TAG, "prepareCapture - closing existing session");
+            closeSession();
+        }
+
+        // Create a new session listener each time, it's not reusable across cameras
+        mSessionMockListener = spy(new BlockingSessionListener());
+        mSessionWaiter = mSessionMockListener.getStateWaiter();
+
+        List<Surface> outputSurfaces = new ArrayList<>(Arrays.asList(mReaderSurface));
+        mCamera.createCaptureSession(outputSurfaces, mSessionMockListener, mHandler);
+
+        mSession = mSessionMockListener.waitAndGetSession(SESSION_CONFIGURE_TIMEOUT_MS);
+        waitForSessionState(SESSION_CONFIGURED, SESSION_CONFIGURE_TIMEOUT_MS);
+        waitForSessionState(SESSION_READY, SESSION_READY_TIMEOUT_MS);
 }
 
-    private void waitForState(int state, long timeout) {
-        mCameraMockListener.waitForState(state, timeout);
-        mLatestState = state;
+    private void waitForDeviceState(int state, long timeoutMs) {
+        mCameraMockListener.waitForState(state, timeoutMs);
+        mLatestDeviceState = state;
+    }
+
+    private void waitForSessionState(int state, long timeoutMs) {
+        mSessionWaiter.waitForState(state, timeoutMs);
+        mLatestSessionState = state;
     }
 
     private void verifyCaptureResults(
-            CameraDevice.CaptureListener mockListener,
+            CameraCaptureSession.CaptureListener mockListener,
             int expectResultCount) {
         // Should receive expected number of capture results.
         verify(mockListener,
                 timeout(CAPTURE_WAIT_TIMEOUT_MS).atLeast(expectResultCount))
                         .onCaptureCompleted(
-                                eq(mCamera),
+                                eq(mSession),
                                 isA(CaptureRequest.class),
                                 argThat(new IsCaptureResultNotEmpty()));
         // Should not receive any capture failed callbacks.
         verify(mockListener, never())
                         .onCaptureFailed(
-                                eq(mCamera),
+                                eq(mSession),
                                 isA(CaptureRequest.class),
                                 isA(CaptureFailure.class));
         // Should receive expected number of capture shutter calls
         verify(mockListener,
                 atLeast(expectResultCount))
                         .onCaptureStarted(
-                               eq(mCamera),
+                               eq(mSession),
                                isA(CaptureRequest.class),
                                anyLong());
-
     }
 
     private void checkFpsRange(CaptureRequest.Builder request, int template,
             CameraCharacteristics props) {
-        CaptureRequest.Key<int[]> fpsRangeKey = CONTROL_AE_TARGET_FPS_RANGE;
-        int[] fpsRange;
+        CaptureRequest.Key<Range<Integer>> fpsRangeKey = CONTROL_AE_TARGET_FPS_RANGE;
+        Range<Integer> fpsRange;
         if ((fpsRange = mCollector.expectKeyValueNotNull(request, fpsRangeKey)) == null) {
             return;
         }
 
-        // TODO: Use generated array dimensions
-        final int CONTROL_AE_TARGET_FPS_RANGE_SIZE = 2;
-        final int CONTROL_AE_TARGET_FPS_RANGE_MIN = 0;
-        final int CONTROL_AE_TARGET_FPS_RANGE_MAX = 1;
-
-        String cause = "Failed with fps range size check";
-        if (!mCollector.expectEquals(cause, CONTROL_AE_TARGET_FPS_RANGE_SIZE, fpsRange.length)) {
-            return;
-        }
-
-        int minFps = fpsRange[CONTROL_AE_TARGET_FPS_RANGE_MIN];
-        int maxFps = fpsRange[CONTROL_AE_TARGET_FPS_RANGE_MAX];
-        int[] availableFpsRange = props
+        int minFps = fpsRange.getLower();
+        int maxFps = fpsRange.getUpper();
+        Range<Integer>[] availableFpsRange = props
                 .get(CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES);
         boolean foundRange = false;
-        for (int i = 0; i < availableFpsRange.length; i += CONTROL_AE_TARGET_FPS_RANGE_SIZE) {
-            if (minFps == availableFpsRange[i + CONTROL_AE_TARGET_FPS_RANGE_MIN]
-                    && maxFps == availableFpsRange[i + CONTROL_AE_TARGET_FPS_RANGE_MAX]) {
+        for (int i = 0; i < availableFpsRange.length; i += 1) {
+            if (minFps == availableFpsRange[i].getLower()
+                    && maxFps == availableFpsRange[i].getUpper()) {
                 foundRange = true;
                 break;
             }
@@ -700,7 +742,7 @@
         }
 
         int targetAfMode = CaptureRequest.CONTROL_AF_MODE_AUTO;
-        byte[] availableAfMode = props.get(CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES);
+        int[] availableAfMode = props.get(CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES);
         if (template == CameraDevice.TEMPLATE_PREVIEW ||
                 template == CameraDevice.TEMPLATE_STILL_CAPTURE ||
                 template == CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG) {
@@ -742,21 +784,24 @@
             CameraCharacteristics props) {
         // 3A settings--control.mode.
         if (template != CameraDevice.TEMPLATE_MANUAL) {
-            mCollector
-                    .expectKeyValueEquals(request, CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO);
+            mCollector.expectKeyValueEquals(request, CONTROL_MODE,
+                    CaptureRequest.CONTROL_MODE_AUTO);
         }
 
         // 3A settings--AE/AWB/AF.
-        int[] maxRegions = props.get(CameraCharacteristics.CONTROL_MAX_REGIONS);
+        int maxRegionsAe = props.get(CameraCharacteristics.CONTROL_MAX_REGIONS_AE);
+        int maxRegionsAwb = props.get(CameraCharacteristics.CONTROL_MAX_REGIONS_AWB);
+        int maxRegionsAf = props.get(CameraCharacteristics.CONTROL_MAX_REGIONS_AF);
+
         checkAfMode(request, template, props);
         checkFpsRange(request, template, props);
+
         if (template == CameraDevice.TEMPLATE_MANUAL) {
             mCollector.expectKeyValueEquals(request, CONTROL_MODE, CaptureRequest.CONTROL_MODE_OFF);
             mCollector.expectKeyValueEquals(request, CONTROL_AE_MODE,
                     CaptureRequest.CONTROL_AE_MODE_OFF);
             mCollector.expectKeyValueEquals(request, CONTROL_AWB_MODE,
                     CaptureRequest.CONTROL_AWB_MODE_OFF);
-
         } else {
             mCollector.expectKeyValueEquals(request, CONTROL_AE_MODE,
                     CaptureRequest.CONTROL_AE_MODE_ON);
@@ -776,15 +821,16 @@
 
             // Check 3A regions.
             if (VERBOSE) {
-                Log.v(TAG, "maxRegions is: " + Arrays.toString(maxRegions));
+                Log.v(TAG, String.format("maxRegions is: {AE: %s, AWB: %s, AF: %s}",
+                        maxRegionsAe, maxRegionsAwb, maxRegionsAf));
             }
-            if (maxRegions[AE_REGION_INDEX] > 0) {
+            if (maxRegionsAe > 0) {
                 mCollector.expectKeyValueNotNull(request, CONTROL_AE_REGIONS);
             }
-            if (maxRegions[AWB_REGION_INDEX] > 0) {
+            if (maxRegionsAwb > 0) {
                 mCollector.expectKeyValueNotNull(request, CONTROL_AWB_REGIONS);
             }
-            if (maxRegions[AF_REGION_INDEX] > 0) {
+            if (maxRegionsAf > 0) {
                 mCollector.expectKeyValueNotNull(request, CONTROL_AF_REGIONS);
             }
         }
@@ -808,7 +854,7 @@
             mCollector.expectKeyValueNotNull(request, LENS_FOCAL_LENGTH);
         }
 
-        byte[] availableOIS =
+        int[] availableOIS =
                 props.get(CameraCharacteristics.LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION);
         if (availableOIS.length > 1) {
             mCollector.expectKeyValueNotNull(request, LENS_OPTICAL_STABILIZATION_MODE);
@@ -835,26 +881,26 @@
                     request, COLOR_CORRECTION_MODE,
                     CaptureRequest.COLOR_CORRECTION_MODE_TRANSFORM_MATRIX);
 
-            List<Byte> availableEdgeModes =
+            List<Integer> availableEdgeModes =
                     Arrays.asList(toObject(mStaticInfo.getAvailableEdgeModesChecked()));
-            if (availableEdgeModes.contains((byte) CaptureRequest.EDGE_MODE_HIGH_QUALITY)) {
+            if (availableEdgeModes.contains(CaptureRequest.EDGE_MODE_HIGH_QUALITY)) {
                 mCollector.expectKeyValueEquals(request, EDGE_MODE,
                         CaptureRequest.EDGE_MODE_HIGH_QUALITY);
-            } else if (availableEdgeModes.contains((byte) CaptureRequest.EDGE_MODE_FAST)) {
+            } else if (availableEdgeModes.contains(CaptureRequest.EDGE_MODE_FAST)) {
                 mCollector.expectKeyValueEquals(request, EDGE_MODE, CaptureRequest.EDGE_MODE_FAST);
             } else {
                 mCollector.expectKeyValueEquals(request, EDGE_MODE, CaptureRequest.EDGE_MODE_OFF);
             }
 
-            List<Byte> availableNoiseReductionModes =
+            List<Integer> availableNoiseReductionModes =
                     Arrays.asList(toObject(mStaticInfo.getAvailableNoiseReductionModesChecked()));
             if (availableNoiseReductionModes
-                    .contains((byte) CaptureRequest.NOISE_REDUCTION_MODE_HIGH_QUALITY)) {
+                    .contains(CaptureRequest.NOISE_REDUCTION_MODE_HIGH_QUALITY)) {
                 mCollector.expectKeyValueEquals(
                         request, NOISE_REDUCTION_MODE,
                         CaptureRequest.NOISE_REDUCTION_MODE_HIGH_QUALITY);
             } else if (availableNoiseReductionModes
-                    .contains((byte) CaptureRequest.NOISE_REDUCTION_MODE_FAST)) {
+                    .contains(CaptureRequest.NOISE_REDUCTION_MODE_FAST)) {
                 mCollector.expectKeyValueEquals(
                         request, NOISE_REDUCTION_MODE, CaptureRequest.NOISE_REDUCTION_MODE_FAST);
             } else {
@@ -862,9 +908,9 @@
                         request, NOISE_REDUCTION_MODE, CaptureRequest.NOISE_REDUCTION_MODE_OFF);
             }
 
-            List<Byte> availableToneMapModes =
+            List<Integer> availableToneMapModes =
                     Arrays.asList(toObject(mStaticInfo.getAvailableToneMapModesChecked()));
-            if (availableToneMapModes.contains((byte) CaptureRequest.TONEMAP_MODE_HIGH_QUALITY)) {
+            if (availableToneMapModes.contains(CaptureRequest.TONEMAP_MODE_HIGH_QUALITY)) {
                 mCollector.expectKeyValueEquals(request, TONEMAP_MODE,
                         CaptureRequest.TONEMAP_MODE_HIGH_QUALITY);
             } else {
@@ -900,7 +946,48 @@
             checkRequestForTemplate(request, template, props);
         }
         finally {
-            closeDevice(cameraId, mCameraMockListener);
+            try {
+                closeSession();
+            } finally {
+                closeDevice(cameraId, mCameraMockListener);
+            }
         }
     }
+
+    /**
+     * Start capture with given {@link #CaptureRequest}.
+     *
+     * @param request The {@link #CaptureRequest} to be captured.
+     * @param repeating If the capture is single capture or repeating.
+     * @param listener The {@link #CaptureListener} camera device used to notify callbacks.
+     * @param handler The handler camera device used to post callbacks.
+     */
+    protected void startCapture(CaptureRequest request, boolean repeating,
+            CameraCaptureSession.CaptureListener listener, Handler handler)
+                    throws CameraAccessException {
+        if (VERBOSE) Log.v(TAG, "Starting capture from session");
+
+        if (repeating) {
+            mSession.setRepeatingRequest(request, listener, handler);
+        } else {
+            mSession.capture(request, listener, handler);
+        }
+    }
+
+    /**
+     * Close a {@link #CameraCaptureSession capture session}; blocking until
+     * the close finishes with a transition to {@link CameraCaptureSession.StateListener#onClosed}.
+     */
+    protected void closeSession() {
+        if (mSession == null) {
+            return;
+        }
+
+        mSession.close();
+        waitForSessionState(SESSION_CLOSED, SESSION_CLOSE_TIMEOUT_MS);
+        mSession = null;
+
+        mSessionMockListener = null;
+        mSessionWaiter = null;
+    }
 }
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 9719278..0a28275 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraManagerTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraManagerTest.java
@@ -235,6 +235,7 @@
 
         List<CameraDevice> cameraList = new ArrayList<CameraDevice>();
         List<MockStateListener> listenerList = new ArrayList<MockStateListener>();
+        List<BlockingStateListener> blockingListenerList = new ArrayList<BlockingStateListener>();
         try {
             for (int i = 0; i < ids.length; i++) {
                 // Ignore state changes from other cameras
@@ -320,11 +321,17 @@
                 // Keep track of cameras so we can close it later
                 cameraList.add(camera);
                 listenerList.add(mockListener);
+                blockingListenerList.add(mCameraListener);
             }
         } finally {
             for (CameraDevice camera : cameraList) {
                 camera.close();
             }
+            for (BlockingStateListener blockingListener : blockingListenerList) {
+                blockingListener.waitForState(
+                        BlockingStateListener.STATE_CLOSED,
+                        CameraTestUtils.CAMERA_IDLE_TIMEOUT_MS);
+            }
         }
 
         /*
@@ -337,6 +344,7 @@
 
             verify(listener).onClosed(eq(camera));
             verifyNoMoreInteractions(listener);
+            i++;
             // Only a #close can happen on the camera since we were done with it.
             // Also nothing else should've happened between the close and the open.
         }
@@ -415,7 +423,7 @@
                 mCameraManager.openCamera(ids[i], successListener, mHandler);
 
                 try {
-                    mCameraManager.openCamera(ids[i], mCameraListener,
+                    mCameraManager.openCamera(ids[i], failListener,
                             mHandler);
                 } catch (CameraAccessException e) {
                     // Optional (but common). Camera might fail asynchronously only.
@@ -434,7 +442,6 @@
                 ArgumentCaptor<CameraDevice> argument =
                         ArgumentCaptor.forClass(CameraDevice.class);
                 verify(mockSuccessListener, atLeastOnce()).onOpened(argument.capture());
-                successCamera = argument.getValue();
                 successListener.waitForState(BlockingStateListener.STATE_UNCONFIGURED,
                         CameraTestUtils.CAMERA_IDLE_TIMEOUT_MS);
 
@@ -446,8 +453,8 @@
 
                 verify(mockFailListener)
                         .onError(
-                                and(notNull(CameraDevice.class), not(successCamera)),
-                                StateListener.ERROR_CAMERA_IN_USE);
+                                and(notNull(CameraDevice.class), not(eq(successCamera))),
+                                eq(StateListener.ERROR_CAMERA_IN_USE));
                 verifyNoMoreInteractions(mockFailListener);
             } finally {
                 if (successCamera != null) {
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraTestUtils.java b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraTestUtils.java
index e157b4c..16a6609 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraTestUtils.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraTestUtils.java
@@ -31,6 +31,7 @@
 import android.hardware.camera2.CaptureResult;
 import android.hardware.camera2.TotalCaptureResult;
 import android.util.Size;
+import android.hardware.camera2.params.MeteringRectangle;
 import android.hardware.camera2.params.StreamConfigurationMap;
 import android.media.Image;
 import android.media.ImageReader;
@@ -80,6 +81,10 @@
     public static final int CAPTURE_RESULT_TIMEOUT_MS = 3000;
     public static final int CAPTURE_IMAGE_TIMEOUT_MS = 3000;
 
+    public static final int SESSION_CONFIGURE_TIMEOUT_MS = 2000;
+    public static final int SESSION_CLOSE_TIMEOUT_MS = 2000;
+    public static final int SESSION_READY_TIMEOUT_MS = 2000;
+    public static final int SESSION_ACTIVE_TIMEOUT_MS = 1000;
     /**
      * Dummy listener that release the image immediately once it is available.
      *
@@ -201,6 +206,11 @@
             throw new TimeoutRuntimeException("Unable to get the expected capture result after "
                     + "waiting for " + numResultsWait + " results");
         }
+
+        public boolean hasMoreResults()
+        {
+            return mQueue.isEmpty();
+        }
     }
 
     /**
@@ -333,8 +343,9 @@
         if (format == ImageFormat.JPEG) {
             buffer = planes[0].getBuffer();
             assertNotNull("Fail to get jpeg ByteBuffer", buffer);
-            data = new byte[buffer.capacity()];
+            data = new byte[buffer.remaining()];
             buffer.get(data);
+            buffer.rewind();
             return data;
         }
 
@@ -881,21 +892,22 @@
     /**
      * Calculate output 3A region from the intersection of input 3A region and cropped region.
      *
-     * @param requestRegion The input 3A region [xmin, ymin, xmax, ymax, weight]
+     * @param requestRegions The input 3A regions
      * @param cropRect The cropped region
-     * @return expected 3A region output in capture result
+     * @return expected 3A regions output in capture result
      */
-    public static int[] getExpectedOutputRegion(int[] requestRegion, Rect cropRect){
-        Rect requestRect = new Rect(requestRegion[0], requestRegion[1],
-                requestRegion[2], requestRegion[3]);
-        Rect resultRect = new Rect();
-        assertTrue("Input 3A region must intersect cropped region",
-                    resultRect.setIntersect(requestRect, cropRect));
-        return new int[] {
-                resultRect.left,
-                resultRect.top,
-                resultRect.right,
-                resultRect.bottom,
-                requestRegion[4]};
+    public static MeteringRectangle[] getExpectedOutputRegion(
+            MeteringRectangle[] requestRegions, Rect cropRect){
+        MeteringRectangle[] resultRegions = new MeteringRectangle[requestRegions.length];
+        for (int i = 0; i < requestRegions.length; i++) {
+            Rect requestRect = requestRegions[i].getRect();
+            Rect resultRect = new Rect();
+            assertTrue("Input 3A region must intersect cropped region",
+                        resultRect.setIntersect(requestRect, cropRect));
+            resultRegions[i] = new MeteringRectangle(
+                    resultRect,
+                    requestRegions[i].getMeteringWeight());
+        }
+        return resultRegions;
     }
 }
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureRequestTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureRequestTest.java
index add91a4..6da1fa5 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureRequestTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureRequestTest.java
@@ -29,8 +29,15 @@
 import android.hardware.camera2.CaptureResult;
 import android.hardware.camera2.cts.CameraTestUtils.SimpleCaptureListener;
 import android.hardware.camera2.cts.testcases.Camera2SurfaceViewTestCase;
+import android.hardware.camera2.params.ColorSpaceTransform;
 import android.hardware.camera2.params.Face;
+import android.hardware.camera2.params.LensShadingMap;
+import android.hardware.camera2.params.MeteringRectangle;
+import android.hardware.camera2.params.RggbChannelVector;
+import android.hardware.camera2.params.TonemapCurve;
+
 import android.util.Log;
+import android.util.Range;
 import android.util.Rational;
 import android.util.Size;
 
@@ -93,7 +100,6 @@
     private final int INDEX_ALGORITHM_AE = 0;
     private final int INDEX_ALGORITHM_AWB = 1;
     private final int INDEX_ALGORITHM_AF = 2;
-    private final int LENGTH_ALGORITHM_REGION = 5;
 
     @Override
     protected void setUp() throws Exception {
@@ -186,14 +192,13 @@
                 requestBuilder.set(CaptureRequest.STATISTICS_LENS_SHADING_MAP_MODE,
                         STATISTICS_LENS_SHADING_MAP_MODE_ON);
 
-                Size mapSz = mStaticInfo.getCharacteristics().get(LENS_INFO_SHADING_MAP_SIZE);
                 Size previewSz =
                         getMaxPreviewSize(mCamera.getId(), mCameraManager, PREVIEW_SIZE_BOUND);
 
                 listener = new SimpleCaptureListener();
                 startPreview(requestBuilder, previewSz, listener);
 
-                verifyShadingMap(listener, NUM_FRAMES_VERIFIED, mapSz, SHADING_MODE_OFF);
+                verifyShadingMap(listener, NUM_FRAMES_VERIFIED, SHADING_MODE_OFF);
 
                 // Shading map mode FAST, lensShadingMapMode ON, camera device
                 // should output valid maps.
@@ -203,7 +208,7 @@
                 startPreview(requestBuilder, previewSz, listener);
 
                 // Allow at most one lock OFF state as the exposure is changed once.
-                verifyShadingMap(listener, NUM_FRAMES_VERIFIED, mapSz, SHADING_MODE_FAST);
+                verifyShadingMap(listener, NUM_FRAMES_VERIFIED, SHADING_MODE_FAST);
 
                 // Shading map mode HIGH_QUALITY, lensShadingMapMode ON, camera device
                 // should output valid maps.
@@ -212,7 +217,7 @@
                 listener = new SimpleCaptureListener();
                 startPreview(requestBuilder, previewSz, listener);
 
-                verifyShadingMap(listener, NUM_FRAMES_VERIFIED, mapSz, SHADING_MODE_HIGH_QUALITY);
+                verifyShadingMap(listener, NUM_FRAMES_VERIFIED, SHADING_MODE_HIGH_QUALITY);
 
                 stopPreview();
             } finally {
@@ -237,12 +242,12 @@
                     continue;
                 }
 
-                byte[] modes = mStaticInfo.getAeAvailableAntiBandingModesChecked();
+                int[] modes = mStaticInfo.getAeAvailableAntiBandingModesChecked();
 
                 Size previewSz =
                         getMaxPreviewSize(mCamera.getId(), mCameraManager, PREVIEW_SIZE_BOUND);
 
-                for (byte mode : modes) {
+                for (int mode : modes) {
                     antiBandingTestByMode(previewSz, mode);
                 }
             } finally {
@@ -278,8 +283,8 @@
                 updatePreviewSurface(maxPreviewSz);
 
                 // Test aeMode and lock
-                byte[] aeModes = mStaticInfo.getAeAvailableModesChecked();
-                for (byte mode : aeModes) {
+                int[] aeModes = mStaticInfo.getAeAvailableModesChecked();
+                for (int mode : aeModes) {
                     aeModeAndLockTestByMode(mode);
                 }
             } finally {
@@ -481,6 +486,7 @@
 
     /**
      * Test digitalZoom (center wise and non-center wise), validate the returned crop regions.
+     * The max preview size is used for each camera.
      */
     public void testDigitalZoom() throws Exception {
         for (String id : mCameraIds) {
@@ -490,8 +496,28 @@
                     Log.i(TAG, "Camera " + id + "Doesn't support per frame control");
                     continue;
                 }
+                Size maxPreviewSize = mOrderedPreviewSizes.get(0);
+                digitalZoomTestByCamera(maxPreviewSize);
+            } finally {
+                closeDevice();
+            }
+        }
+    }
 
-                digitalZoomTestByCamera();
+    /**
+     * Test digital zoom and all preview size combinations.
+     * TODO: this and above test should all be moved to preview test class.
+     */
+    public void testDigitalZoomPreviewCombinations() throws Exception {
+        for (String id : mCameraIds) {
+            try {
+                openDevice(id);
+                if (!mStaticInfo.isPerFrameControlSupported()) {
+                    Log.i(TAG, "Camera " + id + "Doesn't support per frame control");
+                    continue;
+                }
+
+                digitalZoomPreviewCombinationTestByCamera();
             } finally {
                 closeDevice();
             }
@@ -542,12 +568,12 @@
         Size maxPrevSize = mOrderedPreviewSizes.get(0);
         CaptureRequest.Builder requestBuilder =
                 mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
-        byte[] availableModes = mStaticInfo.getAvailableNoiseReductionModesChecked();
+        int[] availableModes = mStaticInfo.getAvailableNoiseReductionModesChecked();
         SimpleCaptureListener resultListener = new SimpleCaptureListener();
         startPreview(requestBuilder, maxPrevSize, resultListener);
 
-        for (byte mode : availableModes) {
-            requestBuilder.set(CaptureRequest.NOISE_REDUCTION_MODE, (int)mode);
+        for (int mode : availableModes) {
+            requestBuilder.set(CaptureRequest.NOISE_REDUCTION_MODE, mode);
             resultListener = new SimpleCaptureListener();
             mCamera.setRepeatingRequest(requestBuilder.build(), resultListener, mHandler);
 
@@ -659,14 +685,14 @@
      */
     private void edgeModesTestByCamera() throws Exception {
         Size maxPrevSize = mOrderedPreviewSizes.get(0);
-        byte[] edgeModes = mStaticInfo.getAvailableEdgeModesChecked();
+        int[] edgeModes = mStaticInfo.getAvailableEdgeModesChecked();
         CaptureRequest.Builder requestBuilder =
                 mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
         SimpleCaptureListener resultListener = new SimpleCaptureListener();
         startPreview(requestBuilder, maxPrevSize, resultListener);
 
-        for (byte mode : edgeModes) {
-            requestBuilder.set(CaptureRequest.EDGE_MODE, (int)mode);
+        for (int mode : edgeModes) {
+            requestBuilder.set(CaptureRequest.EDGE_MODE, mode);
             resultListener = new SimpleCaptureListener();
             mCamera.setRepeatingRequest(requestBuilder.build(), resultListener, mHandler);
 
@@ -702,74 +728,84 @@
 
         // Default preview result should give valid color correction metadata.
         result = listener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
-        validateColorCorrectionResult(result);
+        validateColorCorrectionResult(result,
+                previewRequestBuilder.get(CaptureRequest.COLOR_CORRECTION_MODE));
 
         // TRANSFORM_MATRIX mode
         // Only test unit gain and identity transform
-        float[] UNIT_GAIN = {1.0f, 1.0f, 1.0f, 1.0f};
-        Rational[] IDENTITY_TRANSFORM = {
+        RggbChannelVector UNIT_GAIN = new RggbChannelVector(1.0f, 1.0f, 1.0f, 1.0f);
+
+        ColorSpaceTransform IDENTITY_TRANSFORM = new ColorSpaceTransform(
+            new Rational[] {
                 ONE_R, ZERO_R, ZERO_R,
                 ZERO_R, ONE_R, ZERO_R,
                 ZERO_R, ZERO_R, ONE_R
-        };
+            });
+
+        int colorCorrectionMode = CaptureRequest.COLOR_CORRECTION_MODE_TRANSFORM_MATRIX;
         manualRequestBuilder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_OFF);
-        manualRequestBuilder.set(CaptureRequest.COLOR_CORRECTION_MODE,
-                CaptureRequest.COLOR_CORRECTION_MODE_TRANSFORM_MATRIX);
+        manualRequestBuilder.set(CaptureRequest.COLOR_CORRECTION_MODE, colorCorrectionMode);
         manualRequestBuilder.set(CaptureRequest.COLOR_CORRECTION_GAINS, UNIT_GAIN);
         manualRequestBuilder.set(CaptureRequest.COLOR_CORRECTION_TRANSFORM, IDENTITY_TRANSFORM);
         request = manualRequestBuilder.build();
         mCamera.capture(request, listener, mHandler);
         result = listener.getCaptureResultForRequest(request, NUM_RESULTS_WAIT_TIMEOUT);
-        float[] gains = result.get(CaptureResult.COLOR_CORRECTION_GAINS);
-        Rational[] transform = result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM);
-        validateColorCorrectionResult(result);
+        RggbChannelVector gains = result.get(CaptureResult.COLOR_CORRECTION_GAINS);
+        ColorSpaceTransform transform = result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM);
+        validateColorCorrectionResult(result, colorCorrectionMode);
+        mCollector.expectEquals("control mode result/request mismatch",
+                CaptureResult.CONTROL_MODE_OFF, result.get(CaptureResult.CONTROL_MODE));
         mCollector.expectEquals("Color correction gain result/request mismatch",
-                CameraTestUtils.toObject(UNIT_GAIN), CameraTestUtils.toObject(gains));
+                UNIT_GAIN, gains);
         mCollector.expectEquals("Color correction gain result/request mismatch",
                 IDENTITY_TRANSFORM, transform);
 
         // FAST mode
+        colorCorrectionMode = CaptureRequest.COLOR_CORRECTION_MODE_FAST;
         manualRequestBuilder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO);
-        manualRequestBuilder.set(CaptureRequest.COLOR_CORRECTION_MODE,
-                CaptureRequest.COLOR_CORRECTION_MODE_FAST);
+        manualRequestBuilder.set(CaptureRequest.COLOR_CORRECTION_MODE, colorCorrectionMode);
         request = manualRequestBuilder.build();
         mCamera.capture(request, listener, mHandler);
         result = listener.getCaptureResultForRequest(request, NUM_RESULTS_WAIT_TIMEOUT);
-        validateColorCorrectionResult(result);
+        validateColorCorrectionResult(result, colorCorrectionMode);
+        mCollector.expectEquals("control mode result/request mismatch",
+                CaptureResult.CONTROL_MODE_AUTO, result.get(CaptureResult.CONTROL_MODE));
 
         // HIGH_QUALITY mode
+        colorCorrectionMode = CaptureRequest.COLOR_CORRECTION_MODE_HIGH_QUALITY;
         manualRequestBuilder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO);
-        manualRequestBuilder.set(CaptureRequest.COLOR_CORRECTION_MODE,
-                CaptureRequest.COLOR_CORRECTION_MODE_FAST);
+        manualRequestBuilder.set(CaptureRequest.COLOR_CORRECTION_MODE, colorCorrectionMode);
         request = manualRequestBuilder.build();
         mCamera.capture(request, listener, mHandler);
         result = listener.getCaptureResultForRequest(request, NUM_RESULTS_WAIT_TIMEOUT);
-        validateColorCorrectionResult(result);
+        validateColorCorrectionResult(result, colorCorrectionMode);
+        mCollector.expectEquals("control mode result/request mismatch",
+                CaptureResult.CONTROL_MODE_AUTO, result.get(CaptureResult.CONTROL_MODE));
     }
 
-    private void validateColorCorrectionResult(CaptureResult result) {
-        float[] ZERO_GAINS = {0, 0, 0, 0};
+    private void validateColorCorrectionResult(CaptureResult result, int colorCorrectionMode) {
+        final RggbChannelVector ZERO_GAINS = new RggbChannelVector(0, 0, 0, 0);
         final int TRANSFORM_SIZE = 9;
         Rational[] zeroTransform = new Rational[TRANSFORM_SIZE];
         Arrays.fill(zeroTransform, ZERO_R);
+        final ColorSpaceTransform ZERO_TRANSFORM = new ColorSpaceTransform(zeroTransform);
 
-        float[] resultGain;
+        RggbChannelVector resultGain;
         if ((resultGain = mCollector.expectKeyValueNotNull(result,
                 CaptureResult.COLOR_CORRECTION_GAINS)) != null) {
-            mCollector.expectEquals("Color correction gain size in incorrect",
-                    ZERO_GAINS.length, resultGain.length);
             mCollector.expectKeyValueNotEquals(result,
                     CaptureResult.COLOR_CORRECTION_GAINS, ZERO_GAINS);
         }
 
-        Rational[] resultTransform;
+        ColorSpaceTransform resultTransform;
         if ((resultTransform = mCollector.expectKeyValueNotNull(result,
                 CaptureResult.COLOR_CORRECTION_TRANSFORM)) != null) {
-            mCollector.expectEquals("Color correction transform size is incorrect",
-                    zeroTransform.length, resultTransform.length);
             mCollector.expectKeyValueNotEquals(result,
-                    CaptureResult.COLOR_CORRECTION_TRANSFORM, zeroTransform);
+                    CaptureResult.COLOR_CORRECTION_TRANSFORM, ZERO_TRANSFORM);
         }
+
+        mCollector.expectEquals("color correction mode result/request mismatch",
+                colorCorrectionMode, result.get(CaptureResult.COLOR_CORRECTION_MODE));
     }
 
     /**
@@ -1101,19 +1137,18 @@
      * Verify shading map for different shading modes.
      */
     private void verifyShadingMap(SimpleCaptureListener listener, int numFramesVerified,
-            Size mapSize, int shadingMode) throws Exception {
-        int numElementsInMap = mapSize.getWidth() * mapSize.getHeight() * RGGB_COLOR_CHANNEL_COUNT;
-        float[] unityMap = new float[numElementsInMap];
-        Arrays.fill(unityMap, 1.0f);
+            int shadingMode) throws Exception {
 
         for (int i = 0; i < numFramesVerified; i++) {
             CaptureResult result = listener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
             mCollector.expectEquals("Shading mode result doesn't match request",
                     shadingMode, result.get(CaptureResult.SHADING_MODE));
-            float[] map = result.get(CaptureResult.STATISTICS_LENS_SHADING_MAP);
+            LensShadingMap mapObj = result.get(CaptureResult.STATISTICS_LENS_SHADING_CORRECTION_MAP);
+            assertNotNull("Map object must not be null", mapObj);
+            int numElementsInMap = mapObj.getGainFactorCount();
+            float[] map = new float[numElementsInMap];
+            mapObj.copyGainFactors(map, /*offset*/0);
             assertNotNull("Map must not be null", map);
-            assertTrue("Map size " + map.length + " must be " + numElementsInMap,
-                    map.length == numElementsInMap);
             assertFalse(String.format(
                     "Map size %d should be less than %d", numElementsInMap, MAX_SHADING_MAP_SIZE),
                     numElementsInMap >= MAX_SHADING_MAP_SIZE);
@@ -1135,6 +1170,8 @@
                 assertEquals("Number of value in the map is " + badValueCnt + " out of "
                         + numElementsInMap, /*expected*/0, /*actual*/badValueCnt);
             } else if (shadingMode == CaptureRequest.SHADING_MODE_OFF) {
+                float[] unityMap = new float[numElementsInMap];
+                Arrays.fill(unityMap, 1.0f);
                 // shading mode is OFF, expect to receive a unity map.
                 assertTrue("Result map " + Arrays.toString(map) + " must be an unity map",
                         Arrays.equals(unityMap, map));
@@ -1151,15 +1188,15 @@
         if (!mStaticInfo.isHardwareLevelFull()) {
             return;
         }
-        byte[] faceDetectModes = mStaticInfo.getAvailableFaceDetectModesChecked();
+        int[] faceDetectModes = mStaticInfo.getAvailableFaceDetectModesChecked();
 
         SimpleCaptureListener listener;
         CaptureRequest.Builder requestBuilder =
                 mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
 
         Size maxPreviewSz = mOrderedPreviewSizes.get(0); // Max preview size.
-        for (byte mode : faceDetectModes) {
-            requestBuilder.set(CaptureRequest.STATISTICS_FACE_DETECT_MODE, (int)mode);
+        for (int mode : faceDetectModes) {
+            requestBuilder.set(CaptureRequest.STATISTICS_FACE_DETECT_MODE, mode);
             if (VERBOSE) {
                 Log.v(TAG, "Start testing face detection mode " + mode);
             }
@@ -1272,17 +1309,17 @@
 
         Size maxPreviewSz = mOrderedPreviewSizes.get(0); // Max preview size.
 
-        byte[] toneMapModes = mStaticInfo.getAvailableToneMapModesChecked();
-        for (byte mode : toneMapModes) {
-            requestBuilder.set(CaptureRequest.TONEMAP_MODE, (int)mode);
+        int[] toneMapModes = mStaticInfo.getAvailableToneMapModesChecked();
+        for (int mode : toneMapModes) {
+            requestBuilder.set(CaptureRequest.TONEMAP_MODE, mode);
             if (VERBOSE) {
                 Log.v(TAG, "Testing tonemap mode " + mode);
             }
 
             if (mode == CaptureRequest.TONEMAP_MODE_CONTRAST_CURVE) {
-                requestBuilder.set(CaptureRequest.TONEMAP_CURVE_RED, TONEMAP_CURVE_LINEAR);
-                requestBuilder.set(CaptureRequest.TONEMAP_CURVE_GREEN, TONEMAP_CURVE_LINEAR);
-                requestBuilder.set(CaptureRequest.TONEMAP_CURVE_BLUE, TONEMAP_CURVE_LINEAR);
+                TonemapCurve tcLinear = new TonemapCurve(
+                        TONEMAP_CURVE_LINEAR, TONEMAP_CURVE_LINEAR, TONEMAP_CURVE_LINEAR);
+                requestBuilder.set(CaptureRequest.TONEMAP_CURVE, tcLinear);
                 // Create a new listener for each run to avoid the results from one run spill
                 // into another run.
                 listener = new SimpleCaptureListener();
@@ -1290,9 +1327,9 @@
                 verifyToneMapModeResults(listener, NUM_FRAMES_VERIFIED, mode,
                         TONEMAP_CURVE_LINEAR);
 
-                requestBuilder.set(CaptureRequest.TONEMAP_CURVE_RED, TONEMAP_CURVE_SRGB);
-                requestBuilder.set(CaptureRequest.TONEMAP_CURVE_GREEN, TONEMAP_CURVE_SRGB);
-                requestBuilder.set(CaptureRequest.TONEMAP_CURVE_BLUE, TONEMAP_CURVE_SRGB);
+                TonemapCurve tcSrgb = new TonemapCurve(
+                        TONEMAP_CURVE_SRGB, TONEMAP_CURVE_SRGB, TONEMAP_CURVE_SRGB);
+                requestBuilder.set(CaptureRequest.TONEMAP_CURVE, tcSrgb);
                 // Create a new listener for each run to avoid the results from one run spill
                 // into another run.
                 listener = new SimpleCaptureListener();
@@ -1335,18 +1372,16 @@
             CaptureResult result = listener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
             mCollector.expectEquals("Capture result tonemap mode should match request", tonemapMode,
                     result.get(CaptureResult.TONEMAP_MODE));
-            float[] mapRed = result.get(CaptureResult.TONEMAP_CURVE_RED);
-            float[] mapGreen = result.get(CaptureResult.TONEMAP_CURVE_GREEN);
-            float[] mapBlue = result.get(CaptureResult.TONEMAP_CURVE_BLUE);
-            boolean redAvailable =
-                    mCollector.expectTrue("Tonemap curve red shouldn't be null for mode "
-                            + tonemapMode, mapRed != null);
-            boolean greenAvailable =
-                    mCollector.expectTrue("Tonemap curve red shouldn't be null for mode "
-                            + tonemapMode, mapGreen != null);
-            boolean blueAvailable =
-                    mCollector.expectTrue("Tonemap curve red shouldn't be null for mode "
-                            + tonemapMode, mapBlue != null);
+            TonemapCurve tc = getValueNotNull(result, CaptureResult.TONEMAP_CURVE);
+            int pointCount = tc.getPointCount(TonemapCurve.CHANNEL_RED);
+            float[] mapRed = new float[pointCount * TonemapCurve.POINT_SIZE];
+            pointCount = tc.getPointCount(TonemapCurve.CHANNEL_GREEN);
+            float[] mapGreen = new float[pointCount * TonemapCurve.POINT_SIZE];
+            pointCount = tc.getPointCount(TonemapCurve.CHANNEL_BLUE);
+            float[] mapBlue = new float[pointCount * TonemapCurve.POINT_SIZE];
+            tc.copyColorCurve(TonemapCurve.CHANNEL_RED, mapRed, 0);
+            tc.copyColorCurve(TonemapCurve.CHANNEL_GREEN, mapGreen, 0);
+            tc.copyColorCurve(TonemapCurve.CHANNEL_BLUE, mapBlue, 0);
             if (tonemapMode == CaptureResult.TONEMAP_MODE_CONTRAST_CURVE) {
                 /**
                  * TODO: need figure out a good way to measure the difference
@@ -1356,24 +1391,18 @@
             }
 
             // Tonemap curve result availability and basic sanity check for all modes.
-            if (redAvailable) {
-                mCollector.expectValuesInRange("Tonemap curve red values are out of range",
-                        CameraTestUtils.toObject(mapRed), /*min*/ZERO, /*max*/ONE);
-                mCollector.expectInRange("Tonemap curve red length is out of range",
-                        mapRed.length, MIN_TONEMAP_CURVE_POINTS, maxCurvePoints * 2);
-            }
-            if (greenAvailable) {
-                mCollector.expectValuesInRange("Tonemap curve green values are out of range",
-                        CameraTestUtils.toObject(mapGreen), /*min*/ZERO, /*max*/ONE);
-                mCollector.expectInRange("Tonemap curve green length is out of range",
-                        mapGreen.length, MIN_TONEMAP_CURVE_POINTS, maxCurvePoints * 2);
-            }
-            if (blueAvailable) {
-                mCollector.expectValuesInRange("Tonemap curve blue values are out of range",
-                        CameraTestUtils.toObject(mapBlue), /*min*/ZERO, /*max*/ONE);
-                mCollector.expectInRange("Tonemap curve blue length is out of range",
-                        mapBlue.length, MIN_TONEMAP_CURVE_POINTS, maxCurvePoints * 2);
-            }
+            mCollector.expectValuesInRange("Tonemap curve red values are out of range",
+                    CameraTestUtils.toObject(mapRed), /*min*/ZERO, /*max*/ONE);
+            mCollector.expectInRange("Tonemap curve red length is out of range",
+                    mapRed.length, MIN_TONEMAP_CURVE_POINTS, maxCurvePoints * 2);
+            mCollector.expectValuesInRange("Tonemap curve green values are out of range",
+                    CameraTestUtils.toObject(mapGreen), /*min*/ZERO, /*max*/ONE);
+            mCollector.expectInRange("Tonemap curve green length is out of range",
+                    mapGreen.length, MIN_TONEMAP_CURVE_POINTS, maxCurvePoints * 2);
+            mCollector.expectValuesInRange("Tonemap curve blue values are out of range",
+                    CameraTestUtils.toObject(mapBlue), /*min*/ZERO, /*max*/ONE);
+            mCollector.expectInRange("Tonemap curve blue length is out of range",
+                    mapBlue.length, MIN_TONEMAP_CURVE_POINTS, maxCurvePoints * 2);
         }
     }
 
@@ -1386,20 +1415,20 @@
      * </p>
      */
     private void awbModeAndLockTestByCamera() throws Exception {
-        byte[] awbModes = mStaticInfo.getAwbAvailableModesChecked();
+        int[] awbModes = mStaticInfo.getAwbAvailableModesChecked();
         Size maxPreviewSize = mOrderedPreviewSizes.get(0);
         CaptureRequest.Builder requestBuilder =
                 mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
         startPreview(requestBuilder, maxPreviewSize, /*listener*/null);
 
-        for (byte mode : awbModes) {
+        for (int mode : awbModes) {
             SimpleCaptureListener listener;
-            requestBuilder.set(CaptureRequest.CONTROL_AWB_MODE, (int)mode);
+            requestBuilder.set(CaptureRequest.CONTROL_AWB_MODE, mode);
             listener = new SimpleCaptureListener();
             mCamera.setRepeatingRequest(requestBuilder.build(), listener, mHandler);
 
             // Verify AWB mode in capture result.
-            verifyCaptureResultForKey(CaptureResult.CONTROL_AWB_MODE, (int)mode, listener,
+            verifyCaptureResultForKey(CaptureResult.CONTROL_AWB_MODE, mode, listener,
                     NUM_FRAMES_VERIFIED);
 
             // Verify color correction transform and gains stay unchanged after a lock.
@@ -1415,19 +1444,21 @@
     private void verifyAwbCaptureResultUnchanged(SimpleCaptureListener listener,
             int numFramesVerified) {
         CaptureResult result = listener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
-        float[] lockedGains = getValueNotNull(result, CaptureResult.COLOR_CORRECTION_GAINS);
-        Rational[] lockedTransform =
+        RggbChannelVector lockedGains =
+                getValueNotNull(result, CaptureResult.COLOR_CORRECTION_GAINS);
+        ColorSpaceTransform lockedTransform =
                 getValueNotNull(result, CaptureResult.COLOR_CORRECTION_TRANSFORM);
 
         for (int i = 0; i < numFramesVerified; i++) {
             result = listener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
-            validateColorCorrectionResult(result);
+            // Color correction mode check is skipped here, as it is checked in colorCorrectionTest.
+            validateColorCorrectionResult(result, result.get(CaptureResult.COLOR_CORRECTION_MODE));
 
-            float[] gains = getValueNotNull(result, CaptureResult.COLOR_CORRECTION_GAINS);
-            Rational[] transform =
+            RggbChannelVector gains = getValueNotNull(result, CaptureResult.COLOR_CORRECTION_GAINS);
+            ColorSpaceTransform transform =
                     getValueNotNull(result, CaptureResult.COLOR_CORRECTION_TRANSFORM);
             mCollector.expectEquals("Color correction gains should remain unchanged after awb lock",
-                    toObject(lockedGains), toObject(gains));
+                    lockedGains, gains);
             mCollector.expectEquals("Color correction transform should remain unchanged after"
                     + " awb lock", lockedTransform, transform);
         }
@@ -1443,20 +1474,20 @@
      * </p>
      */
     private void afModeTestByCamera() throws Exception {
-        byte[] afModes = mStaticInfo.getAfAvailableModesChecked();
+        int[] afModes = mStaticInfo.getAfAvailableModesChecked();
         Size maxPreviewSize = mOrderedPreviewSizes.get(0);
         CaptureRequest.Builder requestBuilder =
                 mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
         startPreview(requestBuilder, maxPreviewSize, /*listener*/null);
 
-        for (byte mode : afModes) {
+        for (int mode : afModes) {
             SimpleCaptureListener listener;
-            requestBuilder.set(CaptureRequest.CONTROL_AF_MODE, (int)mode);
+            requestBuilder.set(CaptureRequest.CONTROL_AF_MODE, mode);
             listener = new SimpleCaptureListener();
             mCamera.setRepeatingRequest(requestBuilder.build(), listener, mHandler);
 
             // Verify AF mode in capture result.
-            verifyCaptureResultForKey(CaptureResult.CONTROL_AF_MODE, (int)mode, listener,
+            verifyCaptureResultForKey(CaptureResult.CONTROL_AF_MODE, mode, listener,
                     NUM_FRAMES_VERIFIED);
 
             // Verify AF can finish a scan for CONTROL_AF_MODE_CONTINUOUS_* modes
@@ -1476,23 +1507,20 @@
      */
     private void stabilizationTestByCamera() throws Exception {
         // video stabilization test.
-        byte[] videoStabModes = mStaticInfo.getAvailableVideoStabilizationModesChecked();
-        byte[] opticalStabModes = mStaticInfo.getAvailableOpticalStabilizationChecked();
+        int[] videoStabModes = mStaticInfo.getAvailableVideoStabilizationModesChecked();
+        int[] opticalStabModes = mStaticInfo.getAvailableOpticalStabilizationChecked();
         Size maxPreviewSize = mOrderedPreviewSizes.get(0);
         CaptureRequest.Builder requestBuilder =
                 mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
         SimpleCaptureListener listener = new SimpleCaptureListener();
         startPreview(requestBuilder, maxPreviewSize, listener);
 
-        for ( byte mode : videoStabModes) {
+        for (int mode : videoStabModes) {
             listener = new SimpleCaptureListener();
-            requestBuilder.set(CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE, (int) mode);
+            requestBuilder.set(CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE, mode);
             mCamera.setRepeatingRequest(requestBuilder.build(), listener, mHandler);
-            // TODO: enable below code when b/14059883 is fixed.
-            /*
             verifyCaptureResultForKey(CaptureResult.CONTROL_VIDEO_STABILIZATION_MODE, (int)mode,
                     listener, NUM_FRAMES_VERIFIED);
-            */
         }
 
         for (int mode : opticalStabModes) {
@@ -1506,7 +1534,7 @@
         stopPreview();
     }
 
-    private void digitalZoomTestByCamera() throws Exception {
+    private void digitalZoomTestByCamera(Size previewSize) throws Exception {
         final int ZOOM_STEPS = 30;
         final PointF[] TEST_ZOOM_CENTERS = new PointF[] {
                 new PointF(0.5f, 0.5f),   // Center point
@@ -1518,26 +1546,21 @@
         final float maxZoom = mStaticInfo.getAvailableMaxDigitalZoomChecked();
         final Rect activeArraySize = mStaticInfo.getActiveArraySizeChecked();
         Rect[] cropRegions = new Rect[ZOOM_STEPS];
-        int [][] expectRegions = new int[ZOOM_STEPS][];
-        Size maxPreviewSize = mOrderedPreviewSizes.get(0);
+        MeteringRectangle[][] expectRegions = new MeteringRectangle[ZOOM_STEPS][];
         CaptureRequest.Builder requestBuilder =
                 mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
         SimpleCaptureListener listener = new SimpleCaptureListener();
-        startPreview(requestBuilder, maxPreviewSize, listener);
+        startPreview(requestBuilder, previewSize, listener);
         CaptureRequest[] requests = new CaptureRequest[ZOOM_STEPS];
 
         // Set algorithm regions to full active region
         // TODO: test more different 3A regions
-        final int[] algoDefaultRegion = new int[] {
-            0, // xmin
-            0, // ymin
-            activeArraySize.width() - 1,  // xmax
-            activeArraySize.height() - 1, // ymax
-            1, // weight
-        };
+        final MeteringRectangle[] defaultMeteringRect = new MeteringRectangle[] {
+                new MeteringRectangle (
+                        0, 0, activeArraySize.width(), activeArraySize.height(), 1)};
 
         for (int algo = 0; algo < NUM_ALGORITHMS; algo++) {
-            update3aRegion(requestBuilder, algo,  algoDefaultRegion);
+            update3aRegion(requestBuilder, algo,  defaultMeteringRect);
         }
 
         for (PointF center : TEST_ZOOM_CENTERS) {
@@ -1546,12 +1569,13 @@
                 cropRegions[i] = getCropRegionForZoom(zoomFactor, center, maxZoom, activeArraySize);
                 if (VERBOSE) {
                     Log.v(TAG, "Testing Zoom for factor " + zoomFactor + " and center " +
-                            center.toString() + " The cropRegion is " + cropRegions[i].toString());
+                            center + " The cropRegion is " + cropRegions[i] +
+                            " Preview size is " + previewSize);
                 }
                 requestBuilder.set(CaptureRequest.SCALER_CROP_REGION, cropRegions[i]);
                 requests[i] = requestBuilder.build();
                 expectRegions[i] = getExpectedOutputRegion(
-                        /*requestRegion*/algoDefaultRegion,
+                        /*requestRegion*/defaultMeteringRect,
                         /*cropRect*/     cropRegions[i]);
                 mCamera.capture(requests[i], listener, mHandler);
             }
@@ -1564,7 +1588,7 @@
                  Rect cropRegion = getValueNotNull(result, CaptureResult.SCALER_CROP_REGION);
                  // Verify Output 3A region is intersection of input 3A region and crop region
                  for (int algo = 0; algo < NUM_ALGORITHMS; algo++) {
-                     validate3aRegion(result,algo,  expectRegions[i]);
+                     validate3aRegion(result, algo, expectRegions[i]);
                  }
                  mCollector.expectEquals(" Request and result crop region should match",
                          cropRegions[i], cropRegion);
@@ -1574,8 +1598,18 @@
         stopPreview();
     }
 
+    private void digitalZoomPreviewCombinationTestByCamera() throws Exception {
+        for (Size size : mOrderedPreviewSizes) {
+            if (VERBOSE) {
+                Log.v(TAG, "Test preview size " + size.toString() + " digital zoom");
+            }
+
+            digitalZoomTestByCamera(size);
+        }
+    }
+
     private void sceneModeTestByCamera() throws Exception {
-        byte[] sceneModes = mStaticInfo.getAvailableSceneModesChecked();
+        int[] sceneModes = mStaticInfo.getAvailableSceneModesChecked();
         Size maxPreviewSize = mOrderedPreviewSizes.get(0);
         CaptureRequest.Builder requestBuilder =
                 mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
@@ -1583,15 +1617,12 @@
         requestBuilder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_USE_SCENE_MODE);
         startPreview(requestBuilder, maxPreviewSize, listener);
 
-        for(byte mode : sceneModes) {
-            requestBuilder.set(CaptureRequest.CONTROL_SCENE_MODE, (int)mode);
+        for(int mode : sceneModes) {
+            requestBuilder.set(CaptureRequest.CONTROL_SCENE_MODE, mode);
             listener = new SimpleCaptureListener();
             mCamera.setRepeatingRequest(requestBuilder.build(), listener, mHandler);
-            // Enable below check  when b/14059883 is fixed.
-            /*
             verifyCaptureResultForKey(CaptureResult.CONTROL_SCENE_MODE,
-                    CaptureRequest.CONTROL_SCENE_MODE, listener, NUM_FRAMES_VERIFIED);
-            */
+                    mode, listener, NUM_FRAMES_VERIFIED);
             // This also serves as purpose of showing preview for NUM_FRAMES_VERIFIED
             verifyCaptureResultForKey(CaptureResult.CONTROL_MODE,
                     CaptureRequest.CONTROL_MODE_USE_SCENE_MODE, listener, NUM_FRAMES_VERIFIED);
@@ -1599,7 +1630,7 @@
     }
 
     private void effectModeTestByCamera() throws Exception {
-        byte[] effectModes = mStaticInfo.getAvailableEffectModesChecked();
+        int[] effectModes = mStaticInfo.getAvailableEffectModesChecked();
         Size maxPreviewSize = mOrderedPreviewSizes.get(0);
         CaptureRequest.Builder requestBuilder =
                 mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
@@ -1607,15 +1638,12 @@
         SimpleCaptureListener listener = new SimpleCaptureListener();
         startPreview(requestBuilder, maxPreviewSize, listener);
 
-        for(byte mode : effectModes) {
-            requestBuilder.set(CaptureRequest.CONTROL_EFFECT_MODE, (int)mode);
+        for(int mode : effectModes) {
+            requestBuilder.set(CaptureRequest.CONTROL_EFFECT_MODE, mode);
             listener = new SimpleCaptureListener();
             mCamera.setRepeatingRequest(requestBuilder.build(), listener, mHandler);
-            // Enable below check  when b/14059883 is fixed.
-            /*
-            verifyCaptureResultForKey(CaptureResult.CONTROL_SCENE_MODE,
-                    CaptureRequest.CONTROL_SCENE_MODE, listener, NUM_FRAMES_VERIFIED);
-            */
+            verifyCaptureResultForKey(CaptureResult.CONTROL_EFFECT_MODE,
+                    mode, listener, NUM_FRAMES_VERIFIED);
             // This also serves as purpose of showing preview for NUM_FRAMES_VERIFIED
             verifyCaptureResultForKey(CaptureResult.CONTROL_MODE,
                     CaptureRequest.CONTROL_MODE_AUTO, listener, NUM_FRAMES_VERIFIED);
@@ -1820,26 +1848,24 @@
      */
     private void verifyFpsNotSlowDown(CaptureRequest.Builder requestBuilder,
             int numFramesVerified)  throws Exception {
-        int[] fpsRanges = mStaticInfo.getAeAvailableTargetFpsRangesChecked();
+        Range<Integer>[] fpsRanges = mStaticInfo.getAeAvailableTargetFpsRangesChecked();
         boolean antiBandingOffIsSupported = mStaticInfo.isAntiBandingOffModeSupported();
-        final int FPS_RANGE_SIZE = 2;
-        int[] fpsRange = new int[FPS_RANGE_SIZE];
+        Range<Integer> fpsRange;
         SimpleCaptureListener resultListener;
 
-        for (int i = 0; i < fpsRanges.length; i += FPS_RANGE_SIZE) {
-            fpsRange[0] = fpsRanges[i];
-            fpsRange[1] = fpsRanges[i + 1];
+        for (int i = 0; i < fpsRanges.length; i += 1) {
+            fpsRange = fpsRanges[i];
             Size previewSz = getMaxPreviewSizeForFpsRange(fpsRange);
             // If unable to find a preview size, then log the failure, and skip this run.
             if (!mCollector.expectTrue(String.format(
-                    "Unable to find a preview size supporting given fps range [%d, %d]",
-                    fpsRange[0], fpsRange[1]), previewSz != null)) {
+                    "Unable to find a preview size supporting given fps range %s",
+                    fpsRange), previewSz != null)) {
                 continue;
             }
 
             if (VERBOSE) {
-                Log.v(TAG, String.format("Test fps range [%d, %d] for preview size %s",
-                        fpsRange[0], fpsRange[1], previewSz.toString()));
+                Log.v(TAG, String.format("Test fps range %s for preview size %s",
+                        fpsRange, previewSz.toString()));
             }
             requestBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, fpsRange);
             // Turn off auto antibanding to avoid exposure time and frame duration interference
@@ -1858,7 +1884,7 @@
             resultListener = new SimpleCaptureListener();
             startPreview(requestBuilder, previewSz, resultListener);
             long[] frameDurationRange =
-                    new long[]{(long) (1e9 / fpsRange[1]), (long) (1e9 / fpsRange[0])};
+                    new long[]{(long) (1e9 / fpsRange.getUpper()), (long) (1e9 / fpsRange.getLower())};
             for (int j = 0; j < numFramesVerified; j++) {
                 CaptureResult result =
                         resultListener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
@@ -1929,32 +1955,37 @@
      * if the specified 3A region is not supported by camera device.
      * @param requestBuilder The request to be updated
      * @param algoIdx The index to the algorithm. (AE: 0, AWB: 1, AF: 2)
-     * @param region The 3A region to be set
+     * @param regions The 3A regions to be set
      */
-    private void update3aRegion(CaptureRequest.Builder requestBuilder, int algoIdx, int[] region)
+    private void update3aRegion(
+            CaptureRequest.Builder requestBuilder, int algoIdx, MeteringRectangle[] regions)
     {
-        int[] maxRegions = mStaticInfo.get3aMaxRegionsChecked();
+        int maxRegions;
+        CaptureRequest.Key<MeteringRectangle[]> key;
 
-        if (region.length == 0 ||
-                region.length % LENGTH_ALGORITHM_REGION != 0) {
+        if (regions == null || regions.length == 0) {
             throw new IllegalArgumentException("Invalid input 3A region!");
         }
 
-        if (maxRegions[algoIdx] * LENGTH_ALGORITHM_REGION >= region.length)
-        {
-            switch (algoIdx) {
-                case INDEX_ALGORITHM_AE:
-                    requestBuilder.set(CaptureRequest.CONTROL_AE_REGIONS, region);
-                    break;
-                case INDEX_ALGORITHM_AWB:
-                    requestBuilder.set(CaptureRequest.CONTROL_AWB_REGIONS, region);
-                    break;
-                case INDEX_ALGORITHM_AF:
-                    requestBuilder.set(CaptureRequest.CONTROL_AF_REGIONS, region);
-                    break;
-                default:
-                    throw new IllegalArgumentException("Unknown 3A Algorithm!");
-            }
+        switch (algoIdx) {
+            case INDEX_ALGORITHM_AE:
+                maxRegions = mStaticInfo.getAeMaxRegionsChecked();
+                key = CaptureRequest.CONTROL_AE_REGIONS;
+                break;
+            case INDEX_ALGORITHM_AWB:
+                maxRegions = mStaticInfo.getAwbMaxRegionsChecked();
+                key = CaptureRequest.CONTROL_AWB_REGIONS;
+                break;
+            case INDEX_ALGORITHM_AF:
+                maxRegions = mStaticInfo.getAfMaxRegionsChecked();
+                key = CaptureRequest.CONTROL_AF_REGIONS;
+                break;
+            default:
+                throw new IllegalArgumentException("Unknown 3A Algorithm!");
+        }
+
+        if (maxRegions >= regions.length) {
+            requestBuilder.set(key, regions);
         }
     }
 
@@ -1963,38 +1994,39 @@
      * supported. Do nothing if the specified 3A region is not supported by camera device.
      * @param result The capture result to be validated
      * @param algoIdx The index to the algorithm. (AE: 0, AWB: 1, AF: 2)
-     * @param expectRegion The 3A region expected
+     * @param expectRegions The 3A regions expected in capture result
      */
-    private void validate3aRegion(CaptureResult result, int algoIdx, int[] expectRegion)
+    private void validate3aRegion(
+            CaptureResult result, int algoIdx, MeteringRectangle[] expectRegions)
     {
-        int[] maxRegions = mStaticInfo.get3aMaxRegionsChecked();
-        int[] actualRegion;
+        int maxRegions;
+        CaptureResult.Key<MeteringRectangle[]> key;
+        MeteringRectangle[] actualRegion;
 
-        if (expectRegion.length == 0 ||
-                expectRegion.length % LENGTH_ALGORITHM_REGION != 0) {
-            throw new IllegalArgumentException("Invalid expected 3A region!");
+        switch (algoIdx) {
+            case INDEX_ALGORITHM_AE:
+                maxRegions = mStaticInfo.getAeMaxRegionsChecked();
+                key = CaptureResult.CONTROL_AE_REGIONS;
+                break;
+            case INDEX_ALGORITHM_AWB:
+                maxRegions = mStaticInfo.getAwbMaxRegionsChecked();
+                key = CaptureResult.CONTROL_AWB_REGIONS;
+                break;
+            case INDEX_ALGORITHM_AF:
+                maxRegions = mStaticInfo.getAfMaxRegionsChecked();
+                key = CaptureResult.CONTROL_AF_REGIONS;
+                break;
+            default:
+                throw new IllegalArgumentException("Unknown 3A Algorithm!");
         }
 
-        if (maxRegions[algoIdx] > 0)
+        if (maxRegions > 0)
         {
-            switch (algoIdx) {
-                case INDEX_ALGORITHM_AE:
-                    actualRegion = getValueNotNull(result, CaptureResult.CONTROL_AE_REGIONS);
-                    break;
-                case INDEX_ALGORITHM_AWB:
-                    actualRegion = getValueNotNull(result, CaptureResult.CONTROL_AWB_REGIONS);
-                    break;
-                case INDEX_ALGORITHM_AF:
-                    actualRegion = getValueNotNull(result, CaptureResult.CONTROL_AF_REGIONS);
-                    break;
-                default:
-                    throw new IllegalArgumentException("Unknown 3A Algorithm!");
-            }
+            actualRegion = getValueNotNull(result, key);
             mCollector.expectEquals(
-                    "Expected 3A region: " + Arrays.toString(expectRegion) +
+                    "Expected 3A regions: " + Arrays.toString(expectRegions) +
                     " does not match actual one: " + Arrays.toString(actualRegion),
-                    toObject(expectRegion),
-                    toObject(actualRegion));
+                    expectRegions, actualRegion);
         }
     }
 }
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureResultTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureResultTest.java
index a66debe..31d7016 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureResultTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureResultTest.java
@@ -78,9 +78,7 @@
          * FIXME: We need get ride of this list, see bug 11116270.
          */
         List<CaptureResult.Key<?>> waiverkeys = new ArrayList<CaptureResult.Key<?>>();
-        waiverkeys.add(CaptureResult.JPEG_GPS_COORDINATES);
-        waiverkeys.add(CaptureResult.JPEG_GPS_PROCESSING_METHOD);
-        waiverkeys.add(CaptureResult.JPEG_GPS_TIMESTAMP);
+        waiverkeys.add(CaptureResult.JPEG_GPS_LOCATION);
         waiverkeys.add(CaptureResult.JPEG_ORIENTATION);
         waiverkeys.add(CaptureResult.JPEG_QUALITY);
         waiverkeys.add(CaptureResult.JPEG_THUMBNAIL_QUALITY);
@@ -111,7 +109,7 @@
                 requestBuilder.addTarget(mReaderSurface);
 
                 // Enable face detection if supported
-                byte[] faceModes = mStaticInfo.getAvailableFaceDetectModesChecked();
+                int[] faceModes = mStaticInfo.getAvailableFaceDetectModesChecked();
                 for (int i = 0; i < faceModes.length; i++) {
                     if (faceModes[i] == CameraMetadata.STATISTICS_FACE_DETECT_MODE_FULL) {
                         if (VERBOSE) {
@@ -241,9 +239,7 @@
         resultKeys.add(CaptureResult.FLASH_MODE);
         resultKeys.add(CaptureResult.FLASH_STATE);
         resultKeys.add(CaptureResult.HOT_PIXEL_MODE);
-        resultKeys.add(CaptureResult.JPEG_GPS_COORDINATES);
-        resultKeys.add(CaptureResult.JPEG_GPS_PROCESSING_METHOD);
-        resultKeys.add(CaptureResult.JPEG_GPS_TIMESTAMP);
+        resultKeys.add(CaptureResult.JPEG_GPS_LOCATION);
         resultKeys.add(CaptureResult.JPEG_ORIENTATION);
         resultKeys.add(CaptureResult.JPEG_QUALITY);
         resultKeys.add(CaptureResult.JPEG_THUMBNAIL_QUALITY);
@@ -267,17 +263,16 @@
         resultKeys.add(CaptureResult.SENSOR_GREEN_SPLIT);
         resultKeys.add(CaptureResult.SENSOR_TEST_PATTERN_DATA);
         resultKeys.add(CaptureResult.SENSOR_TEST_PATTERN_MODE);
+        resultKeys.add(CaptureResult.SENSOR_ROLLING_SHUTTER_SKEW);
         resultKeys.add(CaptureResult.SHADING_MODE);
         resultKeys.add(CaptureResult.STATISTICS_FACE_DETECT_MODE);
         resultKeys.add(CaptureResult.STATISTICS_HOT_PIXEL_MAP_MODE);
         resultKeys.add(CaptureResult.STATISTICS_FACES);
-        resultKeys.add(CaptureResult.STATISTICS_LENS_SHADING_MAP);
+        resultKeys.add(CaptureResult.STATISTICS_LENS_SHADING_CORRECTION_MAP);
         resultKeys.add(CaptureResult.STATISTICS_SCENE_FLICKER);
         resultKeys.add(CaptureResult.STATISTICS_HOT_PIXEL_MAP);
         resultKeys.add(CaptureResult.STATISTICS_LENS_SHADING_MAP_MODE);
-        resultKeys.add(CaptureResult.TONEMAP_CURVE_BLUE);
-        resultKeys.add(CaptureResult.TONEMAP_CURVE_GREEN);
-        resultKeys.add(CaptureResult.TONEMAP_CURVE_RED);
+        resultKeys.add(CaptureResult.TONEMAP_CURVE);
         resultKeys.add(CaptureResult.TONEMAP_MODE);
         resultKeys.add(CaptureResult.BLACK_LEVEL_LOCK);
 
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/DngCreatorTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/DngCreatorTest.java
new file mode 100644
index 0000000..5a9baeb
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/DngCreatorTest.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera2.cts;
+
+import android.graphics.ImageFormat;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureResult;
+import android.hardware.camera2.DngCreator;
+import android.hardware.camera2.cts.helpers.StaticMetadata;
+import android.hardware.camera2.cts.testcases.Camera2AndroidTestCase;
+import android.media.Image;
+import android.media.ImageReader;
+import android.util.Log;
+import android.util.Pair;
+import android.util.Size;
+import android.view.Surface;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileOutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import static android.hardware.camera2.cts.CameraTestUtils.configureCameraOutputs;
+
+/**
+ * Tests for the DngCreator API.
+ */
+public class DngCreatorTest extends Camera2AndroidTestCase {
+    private static final String TAG = "DngCreatorTest";
+    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
+    private static final String DEBUG_DNG_FILE = "/raw16.dng";
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    /**
+     * Test basic raw capture and DNG saving functionality for each of the available cameras.
+     *
+     * <p>
+     * For each camera, capture a single RAW16 image at the first capture size reported for
+     * the raw format on that device, and save that image as a DNG file.  No further validation
+     * is done.
+     * </p>
+     *
+     * <p>
+     * Note: Enabling adb shell setprop log.tag.DngCreatorTest VERBOSE will also cause the
+     * raw image captured for the first reported camera device to be saved to an output file.
+     * </p>
+     */
+    public void testSingleImageBasic() throws Exception {
+        for (int i = 0; i < mCameraIds.length; i++) {
+            String deviceId = mCameraIds[i];
+            ImageReader captureReader = null;
+            FileOutputStream fileStream = null;
+            ByteArrayOutputStream outputStream = null;
+            try {
+                openDevice(deviceId);
+
+                Size[] targetCaptureSizes =
+                        mStaticInfo.getAvailableSizesForFormatChecked(ImageFormat.RAW_SENSOR,
+                                StaticMetadata.StreamDirection.Output);
+                if (targetCaptureSizes.length == 0) {
+                    if (VERBOSE) {
+                        Log.v(TAG, "Skipping testSingleImageBasic - " +
+                                "no raw output streams for camera " + deviceId);
+                    }
+                    continue;
+                }
+
+                Size s = targetCaptureSizes[0];
+
+                // Create capture image reader
+                CameraTestUtils.SimpleImageReaderListener captureListener
+                        = new CameraTestUtils.SimpleImageReaderListener();
+                captureReader = createImageReader(s, ImageFormat.RAW_SENSOR, 2,
+                        captureListener);
+                Pair<Image, CaptureResult> resultPair = captureSingleRawShot(s, captureReader, captureListener);
+                CameraCharacteristics characteristics = mStaticInfo.getCharacteristics();
+
+                // Test simple writeImage, no header checks
+                DngCreator dngCreator = new DngCreator(characteristics, resultPair.second);
+                outputStream = new ByteArrayOutputStream();
+                dngCreator.writeImage(outputStream, resultPair.first);
+
+                if (VERBOSE && i == 0) {
+                    // Write out captured DNG file for the first camera device if setprop is enabled
+                    fileStream = new FileOutputStream(DEBUG_FILE_NAME_BASE +
+                            DEBUG_DNG_FILE);
+                    fileStream.write(outputStream.toByteArray());
+                    fileStream.flush();
+                    fileStream.close();
+                    Log.v(TAG, "Test DNG file for camera " + deviceId + " saved to " +
+                            DEBUG_FILE_NAME_BASE + DEBUG_DNG_FILE);
+                }
+            } finally {
+                closeDevice(deviceId);
+                closeImageReader(captureReader);
+
+                if (outputStream != null) {
+                    outputStream.close();
+                }
+
+                if (fileStream != null) {
+                    fileStream.close();
+                }
+            }
+        }
+    }
+
+    // TODO: Further tests for DNG header validation.
+
+    /**
+     * Capture a single raw image.
+     *
+     * <p>Capture an raw image for a given size.</p>
+     *
+     * @param s The size of the raw image to capture.  Must be one of the available sizes for this
+     *          device.
+     * @return a pair containing the {@link Image} and {@link CaptureResult} used for this capture.
+     */
+    private Pair<Image, CaptureResult> captureSingleRawShot(Size s, ImageReader captureReader,
+            CameraTestUtils.SimpleImageReaderListener captureListener) throws Exception {
+        if (VERBOSE) {
+            Log.v(TAG, "captureSingleRawShot - Capturing raw image.");
+        }
+
+        Size maxYuvSz = mOrderedPreviewSizes.get(0);
+        Size[] targetCaptureSizes =
+                mStaticInfo.getAvailableSizesForFormatChecked(ImageFormat.RAW_SENSOR,
+                        StaticMetadata.StreamDirection.Output);
+
+        // Validate size
+        boolean validSize = false;
+        for (int i = 0; i < targetCaptureSizes.length; ++i) {
+            if (targetCaptureSizes[i].equals(s)) {
+                validSize = true;
+                break;
+            }
+        }
+        assertTrue("Capture size is supported.", validSize);
+        Surface captureSurface = captureReader.getSurface();
+
+        // Capture images.
+        List<Surface> outputSurfaces = new ArrayList<Surface>();
+        outputSurfaces.add(captureSurface);
+        CaptureRequest.Builder request = prepareCaptureRequestForSurfaces(outputSurfaces);
+        request.set(CaptureRequest.STATISTICS_LENS_SHADING_MAP_MODE,
+                CaptureRequest.STATISTICS_LENS_SHADING_MAP_MODE_ON);
+        CameraTestUtils.SimpleCaptureListener resultListener =
+                new CameraTestUtils.SimpleCaptureListener();
+
+        startCapture(request.build(), /*repeating*/false, resultListener, mHandler);
+
+        // Verify capture result and images
+        CaptureResult result = resultListener.getCaptureResult(CAPTURE_WAIT_TIMEOUT_MS);
+
+        Image captureImage = captureListener.getImage(CAPTURE_WAIT_TIMEOUT_MS);
+
+        CameraTestUtils.validateImage(captureImage, s.getWidth(), s.getHeight(),
+                ImageFormat.RAW_SENSOR, null);
+        // Stop capture, delete the streams.
+        stopCapture(/*fast*/false);
+
+        return new Pair<Image, CaptureResult>(captureImage, result);
+    }
+
+    private CaptureRequest.Builder prepareCaptureRequestForSurfaces(List<Surface> surfaces)
+            throws Exception {
+        configureCameraOutputs(mCamera, surfaces, mCameraListener);
+
+        CaptureRequest.Builder captureBuilder =
+                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+        assertNotNull("Fail to get captureRequest", captureBuilder);
+        for (Surface surface : surfaces) {
+            captureBuilder.addTarget(surface);
+        }
+
+        return captureBuilder;
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/RecordingTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/RecordingTest.java
index ab9cddc..0d1baed 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/RecordingTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/RecordingTest.java
@@ -14,27 +14,29 @@
 import static android.hardware.camera2.cts.CameraTestUtils.*;
 import static com.android.ex.camera2.blocking.BlockingStateListener.*;
 
-import android.hardware.camera2.CameraCharacteristics;
+import android.graphics.ImageFormat;
 import android.hardware.camera2.CameraDevice;
 import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureResult;
 import android.util.Size;
 import android.hardware.camera2.cts.testcases.Camera2SurfaceViewTestCase;
 import android.media.CamcorderProfile;
 import android.media.MediaCodecInfo;
 import android.media.MediaCodecInfo.CodecCapabilities;
 import android.media.MediaCodecInfo.CodecProfileLevel;
+import android.media.Image;
+import android.media.ImageReader;
 import android.media.MediaCodecList;
 import android.media.MediaPlayer;
 import android.media.MediaRecorder;
 import android.os.Environment;
-import android.os.Handler;
-import android.os.Looper;
 import android.os.SystemClock;
 import android.test.suitebuilder.annotation.LargeTest;
 import android.util.Log;
-import android.view.SurfaceHolder;
+import android.util.Range;
 import android.view.Surface;
 
+import junit.framework.AssertionFailedError;
 
 import java.io.File;
 import java.util.ArrayList;
@@ -52,13 +54,14 @@
     private static final Size VIDEO_SIZE_BOUND = new Size(1920, 1080);
     private static final int RECORDING_DURATION_MS = 2000;
     private static final int DURATION_MARGIN_MS = 400;
-    private static final int WAIT_FOR_SURFACE_CHANGE_TIMEOUT_MS = 1000;
+    private static final int FRAME_DURATION_ERROR_TOLERANCE_MS = 3;
     private static final int BIT_RATE_1080P = 16000000;
     private static final int BIT_RATE_MIN = 64000;
     private static final int BIT_RATE_MAX = 40000000;
     private static final int VIDEO_FRAME_RATE = 30;
     private final String VIDEO_FILE_PATH = Environment.getExternalStorageDirectory().getPath();
     private static final int[] mCamcorderProfileList = {
+            CamcorderProfile.QUALITY_2160P,
             CamcorderProfile.QUALITY_1080P,
             CamcorderProfile.QUALITY_480P,
             CamcorderProfile.QUALITY_720P,
@@ -68,13 +71,15 @@
             CamcorderProfile.QUALITY_QCIF,
             CamcorderProfile.QUALITY_QVGA,
     };
+    private static final int MAX_VIDEO_SNAPSHOT_IMAGES = 5;
+    private static final int BURST_VIDEO_SNAPSHOT_NUM = 3;
 
     private List<Size> mSupportedVideoSizes;
     private Surface mRecordingSurface;
-    private Surface mPreviewSurface;
     private MediaRecorder mMediaRecorder;
-    private Size mPreviewSz = new Size(0, 0);
     private String mOutMediaFileName;
+    private int mVideoFrameRate;
+    private Size mVideoSize;
 
     @Override
     protected void setUp() throws Exception {
@@ -170,19 +175,34 @@
 
     /**
      * <p>
-     * Test video snapshot for each camera by using MediaRecorder.
+     * Test video snapshot for each camera.
      * </p>
      * <p>
-     * This test covers video snapshot typical use case. The MediaRecorder is
-     * used to record the video for each supported CamcorderProfile
-     * configuration. The largest still capture size is selected to capture the
-     * JPEG image. The still capture images are validated according to the
-     * capture configuration. The preview/recording jitters are evaluated such
-     * that still capture doesn't disrupt the recording session.
+     * This test covers video snapshot typical use case. The MediaRecorder is used to record the
+     * video for each available video size. The largest still capture size is selected to
+     * capture the JPEG image. The still capture images are validated according to the capture
+     * configuration. The timestamp of capture result before and after video snapshot is also
+     * checked to make sure no frame drop caused by video snapshot.
      * </p>
      */
-    public void testVideoSnapShot() throws Exception {
-        // TODO. Need implement.
+    public void testVideoSnapshot() throws Exception {
+        videoSnapshotHelper(/*burstTest*/false);
+    }
+
+    /**
+     * <p>
+     * Test burst video snapshot for each camera.
+     * </p>
+     * <p>
+     * This test covers burst video snapshot capture. The MediaRecorder is used to record the
+     * video for each available video size. The largest still capture size is selected to
+     * capture the JPEG image. {@value #BURST_VIDEO_SNAPSHOT_NUM} video snapshot requests will be
+     * sent during the test. The still capture images are validated according to the capture
+     * configuration.
+     * </p>
+     */
+    public void testBurstVideoSnapshot() throws Exception {
+        videoSnapshotHelper(/*burstTest*/true);
     }
 
     public void testTimelapseRecording() {
@@ -220,7 +240,7 @@
             prepareRecordingWithProfile(profile);
 
             // prepare preview surface: preview size is same as video size.
-            preparePreview(videoSz);
+            updatePreviewSurface(videoSz);
 
             // Start recording
             startRecording(/* useMediaRecorder */true);
@@ -261,7 +281,7 @@
             prepareRecording(sz, VIDEO_FRAME_RATE);
 
             // prepare preview surface: preview size is same as video size.
-            preparePreview(sz);
+            updatePreviewSurface(sz);
 
             // Start recording
             startRecording(/* useMediaRecorder */true);
@@ -278,6 +298,147 @@
     }
 
     /**
+     * Simple wrapper to wrap normal/burst video snapshot tests
+     */
+    private void videoSnapshotHelper(boolean burstTest) throws Exception {
+            for (String id : mCameraIds) {
+                try {
+                    Log.i(TAG, "Testing video snapshot for camera " + id);
+                    // Re-use the MediaRecorder object for the same camera device.
+                    mMediaRecorder = new MediaRecorder();
+                    openDevice(id);
+                    mSupportedVideoSizes =
+                            getSupportedVideoSizes(id, mCameraManager, VIDEO_SIZE_BOUND);
+                    // Use largest still size for video snapshot
+                    Size videoSnapshotSz = mOrderedStillSizes.get(0);
+                    // Image reader is shared for all tested profile, but listener is different
+                    // per profile and will be set later
+                    createImageReader(
+                            videoSnapshotSz, ImageFormat.JPEG,
+                            MAX_VIDEO_SNAPSHOT_IMAGES, /*listener*/null);
+
+                    videoSnapshotTestByCamera(videoSnapshotSz, burstTest);
+                } finally {
+                    closeDevice();
+                    releasRecorder();
+                    closeImageReader();
+                }
+            }
+    }
+
+    /**
+     * Test video snapshot for each  available CamcorderProfile for a given camera.
+     *
+     * <p>
+     * Preview size is set to the video size. For the burst test, frame drop and jittering
+     * is not checked.
+     * </p>
+     *
+     * @param videoSnapshotSz The size of video snapshot image
+     * @param burstTest Perfrom burst capture or single capture. For burst capture
+     *                  {@value #BURST_VIDEO_SNAPSHOT_NUM} capture requests will be sent.
+     */
+    private void videoSnapshotTestByCamera(Size videoSnapshotSz, boolean burstTest)
+            throws Exception {
+        for (int profileId : mCamcorderProfileList) {
+            int cameraId = Integer.valueOf(mCamera.getId());
+            if (!CamcorderProfile.hasProfile(cameraId, profileId)) {
+                continue;
+            }
+
+            CamcorderProfile profile = CamcorderProfile.get(cameraId, profileId);
+            Size videoSz = new Size(profile.videoFrameWidth, profile.videoFrameHeight);
+            assertTrue("Video size " + videoSz.toString()
+                    + " must be one of the camera device supported video size!",
+                    mSupportedVideoSizes.contains(videoSz));
+
+            if (VERBOSE) {
+                Log.v(TAG, "Testing camera recording with video size " + videoSz.toString());
+            }
+
+            // Configure preview and recording surfaces.
+            mOutMediaFileName = VIDEO_FILE_PATH + "/test_video.mp4";
+            if (DEBUG_DUMP) {
+                mOutMediaFileName = VIDEO_FILE_PATH + "/test_video_" + cameraId + "_"
+                        + videoSz.toString() + ".mp4";
+            }
+
+            prepareRecordingWithProfile(profile);
+
+            // prepare video snapshot
+            SimpleCaptureListener resultListener = new SimpleCaptureListener();
+            SimpleImageReaderListener imageListener = new SimpleImageReaderListener();
+            CaptureRequest.Builder videoSnapshotRequestBuilder =
+                    mCamera.createCaptureRequest(CameraDevice.TEMPLATE_VIDEO_SNAPSHOT);
+            prepareVideoSnapshot(videoSnapshotRequestBuilder, imageListener);
+
+            // prepare preview surface: preview size is same as video size.
+            updatePreviewSurface(videoSz);
+
+            // Start recording
+            startRecording(/* useMediaRecorder */true, resultListener);
+
+            // Record certain duration.
+            SystemClock.sleep(RECORDING_DURATION_MS / 2);
+
+            // take a video snapshot
+            CaptureRequest request = videoSnapshotRequestBuilder.build();
+            if (burstTest) {
+                List<CaptureRequest> requests =
+                        new ArrayList<CaptureRequest>(BURST_VIDEO_SNAPSHOT_NUM);
+                for (int i = 0; i < BURST_VIDEO_SNAPSHOT_NUM; i++) {
+                    requests.add(request);
+                }
+                mCamera.captureBurst(requests, resultListener, mHandler);
+            } else {
+                mCamera.capture(request, resultListener, mHandler);
+            }
+
+            // make sure recording is still going after video snapshot
+            SystemClock.sleep(RECORDING_DURATION_MS / 2);
+
+            // Stop recording and preview
+            stopRecording(/* useMediaRecorder */true);
+
+            // Validation recorded video
+            validateRecording(videoSz, RECORDING_DURATION_MS);
+
+            if (burstTest) {
+                for (int i = 0; i < BURST_VIDEO_SNAPSHOT_NUM; i++) {
+                    Image image = imageListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS);
+                    validateVideoSnapshotCapture(image, videoSnapshotSz);
+                    image.close();
+                }
+            } else {
+                // validate video snapshot image
+                Image image = imageListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS);
+                validateVideoSnapshotCapture(image, videoSnapshotSz);
+
+                // validate if there is framedrop around video snapshot
+                validateFrameDropAroundVideoSnapshot(resultListener, image.getTimestamp());
+
+                //TODO: validate jittering. Should move to PTS
+                //validateJittering(resultListener);
+
+                image.close();
+            }
+        }
+    }
+
+    /**
+     * Configure video snapshot request according to the still capture size
+     */
+    private void prepareVideoSnapshot(
+            CaptureRequest.Builder requestBuilder,
+            ImageReader.OnImageAvailableListener imageListener)
+            throws Exception {
+        mReader.setOnImageAvailableListener(imageListener, mHandler);
+        requestBuilder.addTarget(mRecordingSurface);
+        requestBuilder.addTarget(mPreviewSurface);
+        requestBuilder.addTarget(mReaderSurface);
+    }
+
+    /**
      * Configure MediaRecorder recording session with CamcorderProfile, prepare
      * the recording surface.
      */
@@ -291,6 +452,8 @@
         mMediaRecorder.prepare();
         mRecordingSurface = mMediaRecorder.getSurface();
         assertNotNull("Recording surface must be non-null!", mRecordingSurface);
+        mVideoFrameRate = profile.videoFrameRate;
+        mVideoSize = new Size(profile.videoFrameWidth, profile.videoFrameHeight);
     }
 
     /**
@@ -312,14 +475,21 @@
         mMediaRecorder.prepare();
         mRecordingSurface = mMediaRecorder.getSurface();
         assertNotNull("Recording surface must be non-null!", mRecordingSurface);
+        mVideoFrameRate = frameRate;
+        mVideoSize = sz;
     }
 
-    private void startRecording(boolean useMediaRecorder) throws Exception {
+    private void startRecording(boolean useMediaRecorder, CameraDevice.CaptureListener listener)
+            throws Exception {
         List<Surface> outputSurfaces = new ArrayList<Surface>(2);
         assertTrue("Both preview and recording surfaces should be valid",
                 mPreviewSurface.isValid() && mRecordingSurface.isValid());
         outputSurfaces.add(mPreviewSurface);
         outputSurfaces.add(mRecordingSurface);
+        // Video snapshot surface
+        if (mReaderSurface != null) {
+            outputSurfaces.add(mReaderSurface);
+        }
         mCamera.configureOutputs(outputSurfaces);
         mCameraListener.waitForState(STATE_BUSY, CAMERA_BUSY_TIMEOUT_MS);
         mCameraListener.waitForState(STATE_IDLE, CAMERA_IDLE_TIMEOUT_MS);
@@ -327,11 +497,11 @@
         CaptureRequest.Builder recordingRequestBuilder =
                 mCamera.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
         // Make sure camera output frame rate is set to correct value.
-        int[] fpsRange = {VIDEO_FRAME_RATE, VIDEO_FRAME_RATE};
+        Range<Integer> fpsRange = Range.create(mVideoFrameRate, mVideoFrameRate);
         recordingRequestBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, fpsRange);
         recordingRequestBuilder.addTarget(mRecordingSurface);
         recordingRequestBuilder.addTarget(mPreviewSurface);
-        mCamera.setRepeatingRequest(recordingRequestBuilder.build(), null, null);
+        mCamera.setRepeatingRequest(recordingRequestBuilder.build(), listener, mHandler);
 
         if (useMediaRecorder) {
             mMediaRecorder.start();
@@ -340,33 +510,8 @@
         }
     }
 
-    /**
-     * Set the preview surface with given size.
-     *
-     * <p>This method shouldn't be called from UI/mail thread.</p>
-     */
-    private void preparePreview(final Size sz) {
-        // Don't need change the preview size if it is same as current one.
-        if (sz.equals(mPreviewSz)) {
-            return;
-        }
-        mPreviewSz = sz;
-
-        Camera2SurfaceViewStubActivity stubActivity = getActivity();
-        final SurfaceHolder holder = stubActivity.getSurfaceView().getHolder();
-        Handler handler = new Handler(Looper.getMainLooper());
-        handler.post(new Runnable() {
-            @Override
-            public void run() {
-                holder.setFixedSize(sz.getWidth(), sz.getHeight());
-            }
-        });
-
-        boolean res = stubActivity.waitForSurfaceSizeChanged(
-                WAIT_FOR_SURFACE_CHANGE_TIMEOUT_MS, sz.getWidth(), sz.getHeight());
-        assertTrue("wait for surface change to " + sz.toString() + " timed out", res);
-        mPreviewSurface = holder.getSurface();
-        assertTrue("Preview surface is invalid", mPreviewSurface.isValid());
+    private void startRecording(boolean useMediaRecorder)  throws Exception {
+        startRecording(useMediaRecorder, null);
     }
 
     private void stopCameraStreaming() throws Exception {
@@ -426,6 +571,87 @@
     }
 
     /**
+     * Validate video snapshot capture image object sanity and test.
+     *
+     * <p> Check for size, format and jpeg decoding</p>
+     *
+     * @param image The JPEG image to be verified.
+     * @param size The JPEG capture size to be verified against.
+     */
+    private void validateVideoSnapshotCapture(Image image, Size size) {
+        CameraTestUtils.validateImage(image, size.getWidth(), size.getHeight(),
+                ImageFormat.JPEG, /*filePath*/null);
+    }
+
+    /**
+     * Validate if video snapshot causes frame drop.
+     * Here frame drop is defined as frame duration >= 2 * expected frame duration.
+     */
+    private void validateFrameDropAroundVideoSnapshot(
+            SimpleCaptureListener resultListener, long imageTimeStamp) {
+        int expectedDurationMs = 1000 / mVideoFrameRate;
+        CaptureResult prevResult = resultListener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
+        long prevTS = getValueNotNull(prevResult, CaptureResult.SENSOR_TIMESTAMP);
+        while (!resultListener.hasMoreResults()) {
+            CaptureResult currentResult =
+                    resultListener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
+            long currentTS = getValueNotNull(currentResult, CaptureResult.SENSOR_TIMESTAMP);
+            if (currentTS == imageTimeStamp) {
+                // validate the timestamp before and after, then return
+                CaptureResult nextResult =
+                        resultListener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
+                long nextTS = getValueNotNull(nextResult, CaptureResult.SENSOR_TIMESTAMP);
+                int durationMs = (int) (currentTS - prevTS) / 1000000;
+                mCollector.expectTrue(
+                        String.format(
+                                "Video %dx%d Frame drop detected before video snapshot: " +
+                                "duration %dms (expected %dms)",
+                                mVideoSize.getWidth(), mVideoSize.getHeight(),
+                                durationMs, expectedDurationMs),
+                        durationMs < (expectedDurationMs * 2));
+                durationMs = (int) (nextTS - currentTS) / 1000000;
+                mCollector.expectTrue(
+                        String.format(
+                                "Video %dx%d Frame drop detected after video snapshot: " +
+                                "duration %dms (expected %dms)",
+                                mVideoSize.getWidth(), mVideoSize.getHeight(),
+                                durationMs, expectedDurationMs),
+                        durationMs < (expectedDurationMs * 2));
+                return;
+            }
+            prevTS = currentTS;
+        }
+        throw new AssertionFailedError(
+                "Video snapshot timestamp does not match any of capture results!");
+    }
+
+    /**
+     * Validate frame jittering from the input simple listener's buffered results
+     */
+    private void validateJittering(SimpleCaptureListener resultListener) {
+        int expectedDurationMs = 1000 / mVideoFrameRate;
+        CaptureResult prevResult = resultListener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
+        long prevTS = getValueNotNull(prevResult, CaptureResult.SENSOR_TIMESTAMP);
+        while (!resultListener.hasMoreResults()) {
+            CaptureResult currentResult =
+                    resultListener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
+            long currentTS = getValueNotNull(currentResult, CaptureResult.SENSOR_TIMESTAMP);
+            int durationMs = (int) (currentTS - prevTS) / 1000000;
+            int durationError = Math.abs(durationMs - expectedDurationMs);
+            int frameNumber = currentResult.getFrameNumber();
+            mCollector.expectTrue(
+                    String.format(
+                            "Resolution %dx%d Frame %d: jittering (%dms) exceeds bound [%dms,%dms]",
+                            mVideoSize.getWidth(), mVideoSize.getHeight(),
+                            frameNumber, durationMs,
+                            expectedDurationMs - FRAME_DURATION_ERROR_TOLERANCE_MS,
+                            expectedDurationMs + FRAME_DURATION_ERROR_TOLERANCE_MS),
+                    durationError <= FRAME_DURATION_ERROR_TOLERANCE_MS);
+            prevTS = currentTS;
+        }
+    }
+
+    /**
      * Calculate a video bit rate based on the size. The bit rate is scaled
      * based on ratio of video size to 1080p size.
      */
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/StaticMetadataTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/StaticMetadataTest.java
new file mode 100644
index 0000000..d7b77d2
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/StaticMetadataTest.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera2.cts;
+
+import static android.hardware.camera2.CameraCharacteristics.*;
+
+import android.graphics.ImageFormat;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.cts.helpers.StaticMetadata;
+import android.hardware.camera2.cts.helpers.StaticMetadata.CheckLevel;
+import android.hardware.camera2.cts.testcases.Camera2AndroidTestCase;
+import android.util.Log;
+import android.util.Size;
+
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * <p>
+ * This class covers the {@link CameraCharacteristics} tests that are not
+ * covered by {@link CaptureRequestTest} and {@link CameraCharacteristicsTest}
+ * (auto-generated tests that only do the non-null checks).
+ * </p>
+ * <p>
+ * Note that most of the tests in this class don't require camera open.
+ * </p>
+ */
+public class StaticMetadataTest extends Camera2AndroidTestCase {
+    private static final String TAG = "StaticMetadataTest";
+    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
+    private static final float MIN_FPS_FOR_FULL_DEVICE = 20.0f;
+
+    /**
+     * Test the available capability for different hardware support level devices.
+     */
+    public void testHwSupportedLevel() throws Exception {
+        for (String id : mCameraIds) {
+            initStaticMetadata(id);
+            List<Integer> availabeCaps = mStaticInfo.getAvailableCapabilitiesChecked();
+
+            //TODO: Backward compatible key is hidden. Fix that later
+            /*mCollector.expectTrue("All device must contains BACKWARD_COMPATIBLE capability",
+                    availabeCaps.contains(REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE));*/
+
+            if (mStaticInfo.isHardwareLevelFull()) {
+                // Capability advertisement must be right.
+                mCollector.expectTrue("Full device must contains MANUAL_SENSOR capability",
+                        availabeCaps.contains(REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR));
+                mCollector.expectTrue("Full device must contains MANUAL_POST_PROCESSING capability",
+                        availabeCaps.contains(
+                                REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING));
+
+                // Max resolution fps must be >= 20.
+                mCollector.expectTrue("Full device must support at least 20fps for max resolution",
+                        getFpsForMaxSize(id) >= MIN_FPS_FOR_FULL_DEVICE);
+
+                // Need support per frame control
+                mCollector.expectTrue("Full device must support per frame control",
+                        mStaticInfo.isPerFrameControlSupported());
+            }
+
+            // TODO: test all the keys mandatory for all capability devices.
+        }
+    }
+
+    /**
+     * Test max number of output stream reported by device
+     */
+    public void testMaxNumOutputStreams() throws Exception {
+        for (String id : mCameraIds) {
+            initStaticMetadata(id);
+            int maxNumStreamsRaw = mStaticInfo.getMaxNumOutputStreamsRawChecked();
+            int maxNumStreamsProc = mStaticInfo.getMaxNumOutputStreamsProcessedChecked();
+            int maxNumStreamsProcStall = mStaticInfo.getMaxNumOutputStreamsProcessedStallChecked();
+
+            mCollector.expectTrue("max number of raw output streams must be a non negative number",
+                    maxNumStreamsRaw >= 0);
+            mCollector.expectTrue("max number of processed (stalling) output streams must be >= 1",
+                    maxNumStreamsProcStall >= 1);
+
+            if (mStaticInfo.isHardwareLevelFull()) {
+                mCollector.expectTrue("max number of processed (non-stalling) output streams" +
+                        "must be >= 3 for FULL device",
+                        maxNumStreamsProc >= 3);
+            } else {
+                mCollector.expectTrue("max number of processed (non-stalling) output streams" +
+                        "must be >= 2 for LIMITED device",
+                        maxNumStreamsProc >= 2);
+            }
+        }
+
+    }
+
+    /**
+     * Test lens facing.
+     */
+    public void testLensFacing() throws Exception {
+        for (String id : mCameraIds) {
+            initStaticMetadata(id);
+            mStaticInfo.getLensFacingChecked();
+        }
+    }
+
+    private float getFpsForMaxSize(String cameraId) throws Exception {
+        HashMap<Size, Long> minFrameDurationMap =
+                mStaticInfo.getAvailableMinFrameDurationsForFormatChecked(ImageFormat.YUV_420_888);
+
+        Size[] sizes = CameraTestUtils.getSupportedSizeForFormat(ImageFormat.YUV_420_888,
+                cameraId, mCameraManager);
+        Size maxSize = CameraTestUtils.getMaxSize(sizes);
+        Long minDuration = minFrameDurationMap.get(maxSize);
+        if (VERBOSE) {
+            Log.v(TAG, "min frame duration for size " + maxSize + " is " + minDuration);
+        }
+        assertTrue("min duration for max size must be postive number",
+                minDuration != null && minDuration > 0);
+
+        return 1e9f / minDuration;
+    }
+
+    /**
+     * Initialize static metadata for a given camera id.
+     */
+    private void initStaticMetadata(String cameraId) throws Exception {
+        mCollector.setCameraId(cameraId);
+        mStaticInfo = new StaticMetadata(mCameraManager.getCameraCharacteristics(cameraId),
+                CheckLevel.COLLECT, /* collector */mCollector);
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/StillCaptureTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/StillCaptureTest.java
index 9f0af9b..6d38c19 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/StillCaptureTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/StillCaptureTest.java
@@ -23,22 +23,31 @@
 import android.hardware.camera2.CameraDevice;
 import android.hardware.camera2.CaptureRequest;
 import android.hardware.camera2.CaptureResult;
+import android.location.Location;
+import android.location.LocationManager;
+import android.hardware.camera2.DngCreator;
+import android.media.ImageReader;
 import android.util.Size;
 import android.hardware.camera2.cts.CameraTestUtils.SimpleCaptureListener;
 import android.hardware.camera2.cts.CameraTestUtils.SimpleImageReaderListener;
 import android.hardware.camera2.cts.helpers.Camera2Focuser;
 import android.hardware.camera2.cts.testcases.Camera2SurfaceViewTestCase;
+import android.hardware.camera2.params.MeteringRectangle;
 import android.media.ExifInterface;
 import android.media.Image;
 import android.os.Build;
 import android.os.ConditionVariable;
 import android.util.Log;
+import android.util.Range;
 import android.util.Rational;
+import android.view.Surface;
 
 import com.android.ex.camera2.exceptions.TimeoutRuntimeException;
 
+import java.io.ByteArrayOutputStream;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Date;
 import java.util.List;
@@ -46,7 +55,7 @@
 public class StillCaptureTest extends Camera2SurfaceViewTestCase {
     private static final String TAG = "StillCaptureTest";
     private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);;
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
     private static final String JPEG_FILE_NAME = DEBUG_FILE_NAME_BASE + "/test.jpeg";
     // 60 second to accommodate the possible long exposure time.
     private static final int EXIF_DATETIME_ERROR_MARGIN_SEC = 60;
@@ -54,32 +63,39 @@
     // TODO: exposure time error margin need to be scaled with exposure time.
     private static final float EXIF_EXPOSURE_TIME_ERROR_MARGIN_SEC = 0.002f;
     private static final float EXIF_APERTURE_ERROR_MARGIN = 0.001f;
+    private static final Location sTestLocation0 = new Location(LocationManager.GPS_PROVIDER);
+    private static final Location sTestLocation1 = new Location(LocationManager.GPS_PROVIDER);
+    private static final Location sTestLocation2 = new Location(LocationManager.NETWORK_PROVIDER);
+    static {
+        sTestLocation0.setTime(1199145600L);
+        sTestLocation0.setLatitude(37.736071);
+        sTestLocation0.setLongitude(-122.441983);
+        sTestLocation0.setAltitude(21.0);
+
+        sTestLocation1.setTime(1199145601L);
+        sTestLocation1.setLatitude(0.736071);
+        sTestLocation1.setLongitude(0.441983);
+        sTestLocation1.setAltitude(1.0);
+
+        sTestLocation2.setTime(1199145602L);
+        sTestLocation2.setLatitude(-89.736071);
+        sTestLocation2.setLongitude(-179.441983);
+        sTestLocation2.setAltitude(100000.0);
+    }
     // Exif test data vectors.
     private static final ExifTestData[] EXIF_TEST_DATA = {
             new ExifTestData(
-                    /* coords */new double[] {
-                            37.736071, -122.441983, 21.0
-                    },
-                    /* procMethod */"GPS NETWORK HYBRID ARE ALL FINE.",
-                    /* timestamp */1199145600L,
+                    /*gpsLocation*/ sTestLocation0,
                     /* orientation */90,
                     /* jpgQuality */(byte) 80,
                     /* thumbQuality */(byte) 75),
             new ExifTestData(
-                    /* coords */new double[] {
-                            0.736071, 0.441983, 1.0
-                    },
-                    /* procMethod */"GPS",
-                    /* timestamp */1199145601L,
+                    /*gpsLocation*/ sTestLocation1,
                     /* orientation */180,
                     /* jpgQuality */(byte) 90,
                     /* thumbQuality */(byte) 85),
             new ExifTestData(
-                    /* coords */new double[] {
-                            -89.736071, -179.441983, 100000.0
-                    },
-                    /* procMethod */"NETWORK",
-                    /* timestamp */1199145602L,
+                    /*gpsLocation*/ sTestLocation2,
                     /* orientation */270,
                     /* jpgQuality */(byte) 100,
                     /* thumbQuality */(byte) 100)
@@ -164,8 +180,30 @@
                closeImageReader();
            }
        }
-   }
+    }
 
+
+    /**
+     * Test the full raw capture use case.
+     *
+     * This includes:
+     * - Configuring the camera with a preview, jpeg, and raw output stream.
+     * - Running preview until AE/AF can settle.
+     * - Capturing with a request targeting all three output streams.
+     */
+    public void testFullRawCapture() throws Exception {
+        for (int i = 0; i < mCameraIds.length; i++) {
+            try {
+                Log.i(TAG, "Testing raw capture for Camera " + mCameraIds[i]);
+                openDevice(mCameraIds[i]);
+
+                fullRawCaptureTestByCamera();
+            } finally {
+                closeDevice();
+                closeImageReader();
+            }
+        }
+    }
     /**
      * Test touch for focus.
      * <p>
@@ -179,8 +217,8 @@
             try {
                 Log.i(TAG, "Testing touch for focus for Camera " + id);
                 openDevice(id);
-                int[] max3ARegions = mStaticInfo.get3aMaxRegionsChecked();
-                if (!(mStaticInfo.hasFocuser() && max3ARegions[MAX_REGIONS_AF_INDEX] > 0)) {
+                int maxAfRegions = mStaticInfo.getAfMaxRegionsChecked();
+                if (!(mStaticInfo.hasFocuser() && maxAfRegions > 0)) {
                     continue;
                 }
 
@@ -254,9 +292,9 @@
                     continue;
                 }
 
-                int[][] aeRegions = get3ATestRegionsForCamera();
-                for (int i = 0; i < aeRegions.length; i++) {
-                    takePictureTestByCamera(aeRegions[i], /*awbRegions*/null, /*afRegions*/null);
+                ArrayList<MeteringRectangle[]> aeRegionTestCases = get3ARegionTestCasesForCamera();
+                for (MeteringRectangle[] aeRegions : aeRegionTestCases) {
+                    takePictureTestByCamera(aeRegions, /*awbRegions*/null, /*afRegions*/null);
                 }
             } finally {
                 closeDevice();
@@ -279,9 +317,9 @@
                     continue;
                 }
 
-                int[][] awbRegions = get3ATestRegionsForCamera();
-                for (int i = 0; i < awbRegions.length; i++) {
-                    takePictureTestByCamera(/*aeRegions*/null, awbRegions[i], /*afRegions*/null);
+                ArrayList<MeteringRectangle[]> awbRegionTestCases = get3ARegionTestCasesForCamera();
+                for (MeteringRectangle[] awbRegions : awbRegionTestCases) {
+                    takePictureTestByCamera(/*aeRegions*/null, awbRegions, /*afRegions*/null);
                 }
             } finally {
                 closeDevice();
@@ -304,9 +342,9 @@
                     continue;
                 }
 
-                int[][] afRegions = get3ATestRegionsForCamera();
-                for (int i = 0; i < afRegions.length; i++) {
-                    takePictureTestByCamera(/*aeRegions*/null, /*awbRegions*/null, afRegions[i]);
+                ArrayList<MeteringRectangle[]> afRegionTestCases = get3ARegionTestCasesForCamera();
+                for (MeteringRectangle[] afRegions : afRegionTestCases) {
+                    takePictureTestByCamera(/*aeRegions*/null, /*awbRegions*/null, afRegions);
                 }
             } finally {
                 closeDevice();
@@ -381,8 +419,10 @@
      * @param awbRegions AWB regions for this capture
      * @param afRegions AF regions for this capture
      */
-    private void takePictureTestByCamera(int[] aeRegions, int[] awbRegions, int[] afRegions)
-            throws Exception {
+    private void takePictureTestByCamera(
+            MeteringRectangle[] aeRegions, MeteringRectangle[] awbRegions,
+            MeteringRectangle[] afRegions) throws Exception {
+
         boolean hasFocuser = mStaticInfo.hasFocuser();
 
         Size maxStillSz = mOrderedStillSizes.get(0);
@@ -459,10 +499,10 @@
                 previewRequest.get(CaptureRequest.CONTROL_AWB_MODE),
                 result.get(CaptureResult.CONTROL_AWB_MODE));
         if (canSetAwbRegion) {
-            int[] resultAwbRegions = getValueNotNull(result, CaptureResult.CONTROL_AWB_REGIONS);
+            MeteringRectangle[] resultAwbRegions =
+                    getValueNotNull(result, CaptureResult.CONTROL_AWB_REGIONS);
             mCollector.expectEquals("AWB regions in result and request should be same",
-                    toObject(awbRegions),
-                    toObject(resultAwbRegions));
+                    awbRegions, resultAwbRegions);
         }
 
         /**
@@ -486,10 +526,10 @@
                 previewRequest.get(CaptureRequest.CONTROL_AE_MODE),
                 result.get(CaptureResult.CONTROL_AE_MODE));
         if (canSetAeRegion) {
-            int[] resultAeRegions = getValueNotNull(result, CaptureResult.CONTROL_AE_REGIONS);
+            MeteringRectangle[] resultAeRegions =
+                    getValueNotNull(result, CaptureResult.CONTROL_AE_REGIONS);
             mCollector.expectEquals("AE regions in result and request should be same",
-                    toObject(aeRegions),
-                    toObject(resultAeRegions));
+                    aeRegions, resultAeRegions);
         }
 
         /**
@@ -504,10 +544,10 @@
                 stillRequest.get(CaptureRequest.CONTROL_AF_MODE),
                 result.get(CaptureResult.CONTROL_AF_MODE));
         if (canSetAfRegion) {
-            int[] resultAfRegions = getValueNotNull(result, CaptureResult.CONTROL_AF_REGIONS);
+            MeteringRectangle[] resultAfRegions =
+                    getValueNotNull(result, CaptureResult.CONTROL_AF_REGIONS);
             mCollector.expectEquals("AF regions in result and request should be same",
-                    toObject(afRegions),
-                    toObject(resultAfRegions));
+                    afRegions, resultAfRegions);
         }
 
         if (hasFocuser) {
@@ -535,10 +575,10 @@
         SimpleAutoFocusListener afListener = new SimpleAutoFocusListener();
         Camera2Focuser focuser = new Camera2Focuser(mCamera, mPreviewSurface, afListener,
                 mStaticInfo.getCharacteristics(), mHandler);
-        int[][] testAfRegions = get3ATestRegionsForCamera();
+        ArrayList<MeteringRectangle[]> testAfRegions = get3ARegionTestCasesForCamera();
 
-        for (int i = 0; i < testAfRegions.length; i++) {
-            focuser.touchForAutoFocus(testAfRegions[i]);
+        for (MeteringRectangle[] afRegions : testAfRegions) {
+            focuser.touchForAutoFocus(afRegions);
             afListener.waitForAutoFocusDone(WAIT_FOR_FOCUS_DONE_TIMEOUT_MS);
             focuser.cancelAutoFocus();
         }
@@ -611,11 +651,116 @@
         }
     }
 
+    private void fullRawCaptureTestByCamera() throws Exception {
+        Size maxPreviewSz = mOrderedPreviewSizes.get(0);
+        Size maxStillSz = mOrderedStillSizes.get(0);
+        Size[] rawSizes = mStaticInfo.getRawOutputSizesChecked();
+        for (Size size : rawSizes) {
+            if (VERBOSE) {
+                Log.v(TAG, "Testing multi capture with size " + size.toString()
+                        + ", preview size " + maxPreviewSz);
+            }
+
+            // Prepare raw capture and start preview.
+            CaptureRequest.Builder previewBuilder =
+                    mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+            CaptureRequest.Builder multiBuilder =
+                    mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
+
+            SimpleCaptureListener resultListener = new SimpleCaptureListener();
+            SimpleImageReaderListener jpegListener = new SimpleImageReaderListener();
+            SimpleImageReaderListener rawListener = new SimpleImageReaderListener();
+
+            updatePreviewSurface(maxPreviewSz);
+
+            ImageReader rawReader = null;
+            ImageReader jpegReader = null;
+            try {
+
+                // Create ImageReaders.
+                rawReader = makeImageReader(size,
+                        ImageFormat.RAW_SENSOR, MAX_READER_IMAGES, rawListener, mHandler);
+                jpegReader = makeImageReader(maxStillSz,
+                        ImageFormat.JPEG, MAX_READER_IMAGES, jpegListener, mHandler);
+
+                // Configure output streams with preview and jpeg streams.
+                List<Surface> outputSurfaces = new ArrayList<Surface>();
+                outputSurfaces.add(rawReader.getSurface());
+                outputSurfaces.add(jpegReader.getSurface());
+                outputSurfaces.add(mPreviewSurface);
+                configureCameraOutputs(mCamera, outputSurfaces, mCameraListener);
+
+                // Configure the requests.
+                previewBuilder.addTarget(mPreviewSurface);
+                multiBuilder.addTarget(mPreviewSurface);
+                multiBuilder.addTarget(rawReader.getSurface());
+                multiBuilder.addTarget(jpegReader.getSurface());
+
+                // Start preview.
+                mCamera.setRepeatingRequest(previewBuilder.build(), null, mHandler);
+
+                // Poor man's 3A, wait 2 seconds for AE/AF (if any) to settle.
+                // TODO: Do proper 3A trigger and lock (see testTakePictureTest).
+                Thread.sleep(3000);
+
+                multiBuilder.set(CaptureRequest.STATISTICS_LENS_SHADING_MAP_MODE,
+                        CaptureRequest.STATISTICS_LENS_SHADING_MAP_MODE_ON);
+                CaptureRequest multiRequest = multiBuilder.build();
+
+                mCamera.capture(multiRequest, resultListener, mHandler);
+
+                CaptureResult result = resultListener.getCaptureResultForRequest(multiRequest,
+                        NUM_RESULTS_WAIT_TIMEOUT);
+                Image jpegImage = jpegListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS);
+                basicValidateJpegImage(jpegImage, maxStillSz);
+                Image rawImage = rawListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS);
+                validateRaw16Image(rawImage, size);
+
+
+                DngCreator dngCreator = new DngCreator(mStaticInfo.getCharacteristics(), result);
+                ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+                dngCreator.writeImage(outputStream, rawImage);
+
+                if (DEBUG) {
+                    byte[] rawBuffer = outputStream.toByteArray();
+                    String rawFileName =
+                            DEBUG_FILE_NAME_BASE + "/raw16_" + TAG + size.toString() +
+                                    "_cam_" + mCamera.getId() + ".dng";
+                    Log.d(TAG, "Dump raw file into " + rawFileName);
+                    dumpFile(rawFileName, rawBuffer);
+
+                    byte[] jpegBuffer = getDataFromImage(jpegImage);
+                    String jpegFileName =
+                            DEBUG_FILE_NAME_BASE + "/jpeg_" + TAG + size.toString() +
+                                    "_cam_" + mCamera.getId() + ".jpg";
+                    Log.d(TAG, "Dump jpeg file into " + rawFileName);
+                    dumpFile(jpegFileName, jpegBuffer);
+                }
+
+                stopPreview();
+            } finally {
+                closeImageReader(rawReader);
+                closeImageReader(jpegReader);
+                rawReader = null;
+                jpegReader = null;
+            }
+        }
+    }
+
     private void verifyRawCaptureResult(CaptureRequest rawRequest,
             SimpleCaptureListener resultListener) {
         // TODO: validate DNG metadata tags.
     }
 
+    private static boolean areGpsFieldsEqual(Location a, Location b) {
+        if (a == null || b == null) {
+            return false;
+        }
+
+        return a.getTime() == b.getTime() && a.getLatitude() == b.getLatitude() &&
+                a.getLongitude() == b.getLongitude() && a.getAltitude() == b.getAltitude() &&
+                a.getProvider() == b.getProvider();
+    }
     /**
      * Issue a Jpeg capture and validate the exif information.
      * <p>
@@ -661,10 +806,7 @@
              *   present and semantically correct.
              */
             stillBuilder.set(CaptureRequest.JPEG_THUMBNAIL_SIZE, testThumbnailSizes[i]);
-            stillBuilder.set(CaptureRequest.JPEG_GPS_COORDINATES, EXIF_TEST_DATA[i].gpsCoordinates);
-            stillBuilder.set(CaptureRequest.JPEG_GPS_PROCESSING_METHOD,
-                    EXIF_TEST_DATA[i].gpsProcessingMethod);
-            stillBuilder.set(CaptureRequest.JPEG_GPS_TIMESTAMP, EXIF_TEST_DATA[i].gpsTimeStamp);
+            stillBuilder.set(CaptureRequest.JPEG_GPS_LOCATION, EXIF_TEST_DATA[i].gpsLocation);
             stillBuilder.set(CaptureRequest.JPEG_ORIENTATION, EXIF_TEST_DATA[i].jpegOrientation);
             stillBuilder.set(CaptureRequest.JPEG_QUALITY, EXIF_TEST_DATA[i].jpegQuality);
             stillBuilder.set(CaptureRequest.JPEG_THUMBNAIL_QUALITY,
@@ -674,15 +816,9 @@
             mCollector.expectEquals("JPEG thumbnail size request set and get should match",
                     testThumbnailSizes[i],
                     stillBuilder.get(CaptureRequest.JPEG_THUMBNAIL_SIZE));
-            mCollector.expectEquals("GPS coordinates request set and get should match.",
-                    toObject(EXIF_TEST_DATA[i].gpsCoordinates),
-                    toObject(stillBuilder.get(CaptureRequest.JPEG_GPS_COORDINATES)));
-            mCollector.expectEquals("GPS processing method request set and get should match",
-                    EXIF_TEST_DATA[i].gpsProcessingMethod,
-                    stillBuilder.get(CaptureRequest.JPEG_GPS_PROCESSING_METHOD));
-            mCollector.expectEquals("GPS time stamp request set and get should match",
-                    EXIF_TEST_DATA[i].gpsTimeStamp,
-                    stillBuilder.get(CaptureRequest.JPEG_GPS_TIMESTAMP));
+            mCollector.expectTrue("GPS locations request set and get should match.",
+                    areGpsFieldsEqual(EXIF_TEST_DATA[i].gpsLocation,
+                            stillBuilder.get(CaptureRequest.JPEG_GPS_LOCATION)));
             mCollector.expectEquals("JPEG orientation request set and get should match",
                     EXIF_TEST_DATA[i].jpegOrientation,
                     stillBuilder.get(CaptureRequest.JPEG_ORIENTATION));
@@ -719,18 +855,12 @@
             mCollector.expectEquals("JPEG thumbnail size result and request should match",
                     testThumbnailSizes[i],
                     stillResult.get(CaptureResult.JPEG_THUMBNAIL_SIZE));
-            CaptureResult.Key<double[]> gpsCoordsKey = CaptureResult.JPEG_GPS_COORDINATES;
-            if (mCollector.expectKeyValueNotNull(stillResult, gpsCoordsKey) != null) {
-                mCollector.expectEquals("GPS coordinates result and request should match.",
-                        toObject(EXIF_TEST_DATA[i].gpsCoordinates),
-                        toObject(stillResult.get(gpsCoordsKey)));
+            if (mCollector.expectKeyValueNotNull(stillResult, CaptureResult.JPEG_GPS_LOCATION) !=
+                    null) {
+                mCollector.expectTrue("GPS location result and request should match.",
+                        areGpsFieldsEqual(EXIF_TEST_DATA[i].gpsLocation,
+                                stillResult.get(CaptureResult.JPEG_GPS_LOCATION)));
             }
-            mCollector.expectEquals("GPS processing method result and request should match",
-                    EXIF_TEST_DATA[i].gpsProcessingMethod,
-                    stillResult.get(CaptureResult.JPEG_GPS_PROCESSING_METHOD));
-            mCollector.expectEquals("GPS time stamp result and request should match",
-                    EXIF_TEST_DATA[i].gpsTimeStamp,
-                    stillResult.get(CaptureResult.JPEG_GPS_TIMESTAMP));
             mCollector.expectEquals("JPEG orientation result and request should match",
                     EXIF_TEST_DATA[i].jpegOrientation,
                     stillResult.get(CaptureResult.JPEG_ORIENTATION));
@@ -942,18 +1072,14 @@
      * Immutable class wrapping the exif test data.
      */
     private static class ExifTestData {
-        public final double[] gpsCoordinates;
-        public final String gpsProcessingMethod;
-        public final long gpsTimeStamp;
+        public final Location gpsLocation;
         public final int jpegOrientation;
         public final byte jpegQuality;
         public final byte thumbnailQuality;
 
-        public ExifTestData(double[] coords, String procMethod, long timeStamp, int orientation,
+        public ExifTestData(Location location, int orientation,
                 byte jpgQuality, byte thumbQuality) {
-            gpsCoordinates = coords;
-            gpsProcessingMethod = procMethod;
-            gpsTimeStamp = timeStamp;
+            gpsLocation = location;
             jpegOrientation = orientation;
             jpegQuality = jpgQuality;
             thumbnailQuality = thumbQuality;
@@ -961,10 +1087,11 @@
     }
 
     private void aeCompensationTestByCamera() throws Exception {
-        int[] compensationRange = mStaticInfo.getAeCompensationRangeChecked();
+        Range<Integer> compensationRange = mStaticInfo.getAeCompensationRangeChecked();
         Rational step = mStaticInfo.getAeCompensationStepChecked();
-        int stepsPerEv = (int) Math.round(1.0 / step.toFloat());
-        int numSteps = (compensationRange[1] - compensationRange[0]) / stepsPerEv;
+        float stepF = (float) step.getNumerator() / step.getDenominator();
+        int stepsPerEv = (int) Math.round(1.0 / stepF);
+        int numSteps = (compensationRange.getUpper() - compensationRange.getLower()) / stepsPerEv;
 
         Size maxStillSz = mOrderedStillSizes.get(0);
         Size maxPreviewSz = mOrderedPreviewSizes.get(0);
@@ -993,7 +1120,7 @@
                 maxStillSz, resultListener, numSteps, imageListener);
 
         for (int i = 0; i <= numSteps; i++) {
-            int exposureCompensation = i * stepsPerEv + compensationRange[0];
+            int exposureCompensation = i * stepsPerEv + compensationRange.getLower();
 
             // Wait for AE to be stabilized before capture: CONVERGED or FLASH_REQUIRED.
             waitForAeStable(resultListener);
@@ -1072,10 +1199,8 @@
 
     private long getMaxExposureValue(CaptureRequest.Builder request, long maxExposureTimeUs,
                 long maxSensitivity)  throws Exception {
-        int[] fpsRange = request.get(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE);
-        mCollector.expectEquals("Length of CaptureResult FPS range must be 2",
-                2, fpsRange.length);
-        long maxFrameDurationUs = Math.round(1000000.0 / fpsRange[0]);
+        Range<Integer> fpsRange = request.get(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE);
+        long maxFrameDurationUs = Math.round(1000000.0 / fpsRange.getLower());
         long currentMaxExposureTimeUs = Math.min(maxFrameDurationUs, maxExposureTimeUs);
         return currentMaxExposureTimeUs * maxSensitivity;
     }
@@ -1206,75 +1331,107 @@
     }
 
     /**
-     * Get 5 3A test square regions, one is at center, the other four are at corners of
+     * Get 5 3A region test cases, each with one square region in it.
+     * The first one is at center, the other four are at corners of
      * active array rectangle.
      *
      * @return array of test 3A regions
      */
-    private int[][] get3ATestRegionsForCamera() {
+    private ArrayList<MeteringRectangle[]> get3ARegionTestCasesForCamera() {
         final int TEST_3A_REGION_NUM = 5;
-        final int NUM_ELEMENT_IN_REGION = 5;
         final int DEFAULT_REGION_WEIGHT = 30;
         final int DEFAULT_REGION_SCALE_RATIO = 8;
-        int[][] regions = new int[TEST_3A_REGION_NUM][NUM_ELEMENT_IN_REGION];
+        ArrayList<MeteringRectangle[]> testCases =
+                new ArrayList<MeteringRectangle[]>(TEST_3A_REGION_NUM);
         final Rect activeArraySize = mStaticInfo.getActiveArraySizeChecked();
-        int regionWidth = activeArraySize.width() / DEFAULT_REGION_SCALE_RATIO;
-        int regionHeight = activeArraySize.height() / DEFAULT_REGION_SCALE_RATIO;
+        int regionWidth = activeArraySize.width() / DEFAULT_REGION_SCALE_RATIO - 1;
+        int regionHeight = activeArraySize.height() / DEFAULT_REGION_SCALE_RATIO - 1;
         int centerX = activeArraySize.width() / 2;
         int centerY = activeArraySize.height() / 2;
         int bottomRightX = activeArraySize.width() - 1;
         int bottomRightY = activeArraySize.height() - 1;
 
         // Center region
-        int i = 0;
-        regions[i][0] = centerX - regionWidth / 2;       // xmin
-        regions[i][1] = centerY - regionHeight / 2;      // ymin
-        regions[i][2] = centerX + regionWidth / 2 - 1;   // xmax
-        regions[i][3] = centerY + regionHeight / 2 - 1;  // ymax
-        regions[i][4] = DEFAULT_REGION_WEIGHT;
-        i++;
+        testCases.add(
+                new MeteringRectangle[] {
+                    new MeteringRectangle(
+                            centerX - regionWidth / 2,  // x
+                            centerY - regionHeight / 2, // y
+                            regionWidth,                // width
+                            regionHeight,               // height
+                            DEFAULT_REGION_WEIGHT)});
 
         // Upper left corner
-        regions[i][0] = 0;                // xmin
-        regions[i][1] = 0;                // ymin
-        regions[i][2] = regionWidth - 1;  // xmax
-        regions[i][3] = regionHeight - 1; // ymax
-        regions[i][4] = DEFAULT_REGION_WEIGHT;
-        i++;
+        testCases.add(
+                new MeteringRectangle[] {
+                    new MeteringRectangle(
+                            0,                // x
+                            0,                // y
+                            regionWidth,      // width
+                            regionHeight,     // height
+                            DEFAULT_REGION_WEIGHT)});
 
         // Upper right corner
-        regions[i][0] = activeArraySize.width() - regionWidth; // xmin
-        regions[i][1] = 0;                                     // ymin
-        regions[i][2] = bottomRightX;                          // xmax
-        regions[i][3] = regionHeight - 1;                      // ymax
-        regions[i][4] = DEFAULT_REGION_WEIGHT;
-        i++;
+        testCases.add(
+                new MeteringRectangle[] {
+                    new MeteringRectangle(
+                            bottomRightX - regionWidth, // x
+                            0,                          // y
+                            regionWidth,                // width
+                            regionHeight,               // height
+                            DEFAULT_REGION_WEIGHT)});
 
         // Bootom left corner
-        regions[i][0] = 0;                                       // xmin
-        regions[i][1] = activeArraySize.height() - regionHeight; // ymin
-        regions[i][2] = regionWidth - 1;                         // xmax
-        regions[i][3] = bottomRightY;                            // ymax
-        regions[i][4] = DEFAULT_REGION_WEIGHT;
-        i++;
+        testCases.add(
+                new MeteringRectangle[] {
+                    new MeteringRectangle(
+                            0,                           // x
+                            bottomRightY - regionHeight, // y
+                            regionWidth,                 // width
+                            regionHeight,                // height
+                            DEFAULT_REGION_WEIGHT)});
 
         // Bootom right corner
-        regions[i][0] = activeArraySize.width() - regionWidth;   // xmin
-        regions[i][1] = activeArraySize.height() - regionHeight; // ymin
-        regions[i][2] = bottomRightX;                            // xmax
-        regions[i][3] = bottomRightY;                            // ymax
-        regions[i][4] = DEFAULT_REGION_WEIGHT;
-        i++;
+        testCases.add(
+                new MeteringRectangle[] {
+                    new MeteringRectangle(
+                            bottomRightX - regionWidth,  // x
+                            bottomRightY - regionHeight, // y
+                            regionWidth,                 // width
+                            regionHeight,                // height
+                            DEFAULT_REGION_WEIGHT)});
 
         if (VERBOSE) {
-            Log.v(TAG, "Generated test regions are: " + Arrays.deepToString(regions));
+            StringBuilder sb = new StringBuilder();
+            for (MeteringRectangle[] mr : testCases) {
+                sb.append("{");
+                sb.append(Arrays.toString(mr));
+                sb.append("}, ");
+            }
+            if (sb.length() > 1)
+                sb.setLength(sb.length() - 2); // Remove the redundant comma and space at the end
+            Log.v(TAG, "Generated test regions are: " + sb.toString());
         }
 
-        return regions;
+        return testCases;
     }
 
     private boolean isRegionsSupportedFor3A(int index) {
-        boolean isRegionsSupported = mStaticInfo.get3aMaxRegionsChecked()[index] > 0;
+        int maxRegions = 0;
+        switch (index) {
+            case MAX_REGIONS_AE_INDEX:
+                maxRegions = mStaticInfo.getAeMaxRegionsChecked();
+                break;
+            case MAX_REGIONS_AWB_INDEX:
+                maxRegions = mStaticInfo.getAwbMaxRegionsChecked();
+                break;
+            case  MAX_REGIONS_AF_INDEX:
+                maxRegions = mStaticInfo.getAfMaxRegionsChecked();
+                break;
+            default:
+                throw new IllegalArgumentException("Unknown algorithm index");
+        }
+        boolean isRegionsSupported = maxRegions > 0;
         if (index == MAX_REGIONS_AF_INDEX && isRegionsSupported) {
             mCollector.expectTrue(
                     "Device reports non-zero max AF region count for a camera without focuser!",
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/SurfaceViewPreviewTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/SurfaceViewPreviewTest.java
index d569fab..37b6357 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/SurfaceViewPreviewTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/SurfaceViewPreviewTest.java
@@ -28,6 +28,7 @@
 import android.hardware.camera2.cts.CameraTestUtils.SimpleCaptureListener;
 import android.hardware.camera2.cts.testcases.Camera2SurfaceViewTestCase;
 import android.util.Log;
+import android.util.Range;
 
 import org.mockito.ArgumentCaptor;
 import org.mockito.ArgumentMatcher;
@@ -122,17 +123,16 @@
     private void previewFpsRangeTestByCamera() throws Exception {
         final int FPS_RANGE_SIZE = 2;
         Size maxPreviewSz = mOrderedPreviewSizes.get(0);
-        int[] fpsRanges = mStaticInfo.getAeAvailableTargetFpsRangesChecked();
+        Range<Integer>[] fpsRanges = mStaticInfo.getAeAvailableTargetFpsRangesChecked();
         boolean antiBandingOffIsSupported = mStaticInfo.isAntiBandingOffModeSupported();
-        int[] fpsRange = new int[FPS_RANGE_SIZE];
+        Range<Integer> fpsRange;
         CaptureRequest.Builder requestBuilder =
                 mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
         SimpleCaptureListener resultListener = new SimpleCaptureListener();
         startPreview(requestBuilder, maxPreviewSz, resultListener);
 
-        for (int i = 0; i < fpsRanges.length; i += FPS_RANGE_SIZE) {
-            fpsRange[0] = fpsRanges[i];
-            fpsRange[1] = fpsRanges[i + 1];
+        for (int i = 0; i < fpsRanges.length; i += 1) {
+            fpsRange = fpsRanges[i];
 
             requestBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, fpsRange);
             // Turn off auto antibanding to avoid exposure time and frame duration interference
@@ -159,11 +159,11 @@
     }
 
     private void verifyPreviewTargetFpsRange(SimpleCaptureListener resultListener,
-            int numFramesVerified, int[] fpsRange, Size previewSz) {
+            int numFramesVerified, Range<Integer> fpsRange, Size previewSz) {
         CaptureResult result = resultListener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
         long frameDuration = getValueNotNull(result, CaptureResult.SENSOR_FRAME_DURATION);
         long[] frameDurationRange =
-                new long[]{(long) (1e9 / fpsRange[1]), (long) (1e9 / fpsRange[0])};
+                new long[]{(long) (1e9 / fpsRange.getUpper()), (long) (1e9 / fpsRange.getLower())};
         mCollector.expectInRange(
                 "Frame duration must be in the range of " + Arrays.toString(frameDurationRange),
                 frameDuration, (long) (frameDurationRange[0] * (1 - FRAME_DURATION_ERROR_MARGIN)),
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/Camera2Focuser.java b/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/Camera2Focuser.java
index b1fd4a1..28af79c 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/Camera2Focuser.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/Camera2Focuser.java
@@ -21,6 +21,7 @@
 import android.hardware.camera2.CameraCharacteristics;
 import android.hardware.camera2.CameraDevice;
 import android.hardware.camera2.CameraDevice.CaptureListener;
+import android.hardware.camera2.params.MeteringRectangle;
 import android.hardware.camera2.CaptureRequest;
 import android.hardware.camera2.CaptureResult;
 import android.hardware.camera2.TotalCaptureResult;
@@ -50,11 +51,10 @@
     private final AutoFocusListener mAutoFocusListener;
     private final CameraDevice mCamera;
     private final Surface mRequestSurface;
-    private final int AF_REGION_NUM_ELEMENTS = 5;
     private final CameraCharacteristics mStaticInfo;
 
     private int mAfRun = 0;
-    private int[] mAfRegions; // int x AF_REGION_NUM_ELEMENTS array.
+    private MeteringRectangle[] mAfRegions;
     private boolean mLocked = false;
     private boolean mSuccess = false;
     private CaptureRequest.Builder mRepeatingBuilder;
@@ -165,7 +165,8 @@
      * array size is used if afRegions is null.
      * @throws CameraAccessException
      */
-    public synchronized void touchForAutoFocus(int[] afRegions) throws CameraAccessException {
+    public synchronized void touchForAutoFocus(MeteringRectangle[] afRegions)
+            throws CameraAccessException {
         startAutoFocusLocked(/*active*/true, afRegions);
     }
 
@@ -182,7 +183,8 @@
      *            array size is used if afRegions is null.
      * @throws CameraAccessException
      */
-    public synchronized void startAutoFocus(int[] afRegions) throws CameraAccessException {
+    public synchronized void startAutoFocus(MeteringRectangle[] afRegions)
+            throws CameraAccessException {
         startAutoFocusLocked(/*forceActive*/false, afRegions);
     }
 
@@ -222,7 +224,9 @@
         return mRepeatingBuilder.get(CaptureRequest.CONTROL_AF_MODE);
     }
 
-    private void startAutoFocusLocked(boolean forceActive, int[] afRegions) throws CameraAccessException {
+    private void startAutoFocusLocked(
+            boolean forceActive, MeteringRectangle[] afRegions) throws CameraAccessException {
+
         setAfRegions(afRegions);
         mAfRun++;
 
@@ -282,9 +286,6 @@
      * @throws CameraAccessException
      */
     private CaptureRequest.Builder createRequestBuilder() throws CameraAccessException {
-        if (mAfRegions == null) {
-            throw new IllegalStateException("AF regions are not initialized yet");
-        }
         CaptureRequest.Builder requestBuilder =
                 mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
 
@@ -298,17 +299,16 @@
      * Set AF regions, fall back to default region if afRegions is null.
      *
      * @param afRegions The AF regions to set
-     * @throws IllegalArgumentException if the region is malformed (length is 0
-     *             or not multiple times of {@value #AF_REGION_NUM_ELEMENTS}).
+     * @throws IllegalArgumentException if the region is malformed (length is 0).
      */
-    private void setAfRegions(int[] afRegions) {
+    private void setAfRegions(MeteringRectangle[] afRegions) {
         if (afRegions == null) {
             setDefaultAfRegions();
             return;
         }
         // Throw IAE if AF regions are malformed.
-        if (afRegions.length % AF_REGION_NUM_ELEMENTS != 0 || afRegions.length == 0) {
-            throw new IllegalArgumentException("afRegions is malformed, length: " + afRegions.length);
+        if (afRegions.length == 0) {
+            throw new IllegalArgumentException("afRegions is malformed, length: 0");
         }
 
         mAfRegions = afRegions;
@@ -325,7 +325,8 @@
 
         // Initialize AF regions with all zeros, meaning that it is up to camera device to device
         // the regions used by AF.
-        mAfRegions = new int[]{0, 0, 0, 0, 0};
+        mAfRegions = new MeteringRectangle[] {
+                new MeteringRectangle(0, 0, 0, 0, 0)};
     }
     private CaptureListener createCaptureListener() {
 
@@ -339,6 +340,8 @@
         return new CaptureListener() {
             private int mLatestFrameCount = -1;
 
+            // TODO: CaptureListener#onCpaturePartial is hidden. Replace it by
+            //       CameraCaptureSession.CaptureListener#onCapturePartial later.
             @Override
             public void onCapturePartial(CameraDevice camera, CaptureRequest request,
                     CaptureResult result) {
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/StaticMetadata.java b/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
index e99d64a..bdfdbef 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
@@ -21,6 +21,7 @@
 import android.hardware.camera2.CameraCharacteristics;
 import android.hardware.camera2.CameraCharacteristics.Key;
 import android.hardware.camera2.CameraMetadata;
+import android.util.Range;
 import android.util.Size;
 import android.hardware.camera2.cts.CameraTestUtils;
 import android.hardware.camera2.params.StreamConfigurationMap;
@@ -159,11 +160,9 @@
      * @return true if the device is FULL, false otherwise.
      */
     public boolean isHardwareLevelFull() {
-        // TODO: Make this key non-optional for all HAL3.2+ devices
         Integer hwLevel = getValueFromKeyNonNull(
                 CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
 
-        // Bad. Missing metadata. Warning is logged.
         if (hwLevel == null) {
             return false;
         }
@@ -288,33 +287,54 @@
     }
 
     /**
-     * Get max 3A regions and do sanity check.
+     * Get max AE regions and do sanity check.
      *
-     * @return 3A max regions supported by the camera device
+     * @return AE max regions supported by the camera device
      */
-    public int[] get3aMaxRegionsChecked() {
-        Key<int[]> key = CameraCharacteristics.CONTROL_MAX_REGIONS;
-        int[] regionCounts = getValueFromKeyNonNull(key);
-
-        if (regionCounts == null) {
-            return new int[]{0, 0, 0};
+    public int getAeMaxRegionsChecked() {
+        Integer regionCount = getValueFromKeyNonNull(CameraCharacteristics.CONTROL_MAX_REGIONS_AE);
+        if (regionCount == null) {
+            return 0;
         }
-
-        checkTrueForKey(key, " value should contain 3 elements", regionCounts.length == 3);
-        return regionCounts;
+        return regionCount;
     }
 
     /**
+     * Get max AWB regions and do sanity check.
+     *
+     * @return AWB max regions supported by the camera device
+     */
+    public int getAwbMaxRegionsChecked() {
+        Integer regionCount = getValueFromKeyNonNull(CameraCharacteristics.CONTROL_MAX_REGIONS_AWB);
+        if (regionCount == null) {
+            return 0;
+        }
+        return regionCount;
+    }
+
+    /**
+     * Get max AF regions and do sanity check.
+     *
+     * @return AF max regions supported by the camera device
+     */
+    public int getAfMaxRegionsChecked() {
+        Integer regionCount = getValueFromKeyNonNull(CameraCharacteristics.CONTROL_MAX_REGIONS_AF);
+        if (regionCount == null) {
+            return 0;
+        }
+        return regionCount;
+    }
+    /**
      * Get the available anti-banding modes.
      *
      * @return The array contains available anti-banding modes.
      */
-    public byte[] getAeAvailableAntiBandingModesChecked() {
-        Key<byte[]> key = CameraCharacteristics.CONTROL_AE_AVAILABLE_ANTIBANDING_MODES;
-        byte[] modes = getValueFromKeyNonNull(key);
+    public int[] getAeAvailableAntiBandingModesChecked() {
+        Key<int[]> key = CameraCharacteristics.CONTROL_AE_AVAILABLE_ANTIBANDING_MODES;
+        int[] modes = getValueFromKeyNonNull(key);
 
         boolean foundAuto = false;
-        for (byte mode : modes) {
+        for (int mode : modes) {
             checkTrueForKey(key, "mode value " + mode + " is out if range",
                     mode >= CameraMetadata.CONTROL_AE_ANTIBANDING_MODE_OFF ||
                     mode <= CameraMetadata.CONTROL_AE_ANTIBANDING_MODE_AUTO);
@@ -335,10 +355,10 @@
      * @return true if antibanding OFF mode is supported, false otherwise.
      */
     public boolean isAntiBandingOffModeSupported() {
-        List<Byte> antiBandingModes =
+        List<Integer> antiBandingModes =
                 Arrays.asList(CameraTestUtils.toObject(getAeAvailableAntiBandingModesChecked()));
 
-        return antiBandingModes.contains((byte)CameraMetadata.CONTROL_AE_ANTIBANDING_MODE_OFF);
+        return antiBandingModes.contains(CameraMetadata.CONTROL_AE_ANTIBANDING_MODE_OFF);
     }
 
     public Boolean getFlashInfoChecked() {
@@ -445,20 +465,20 @@
      *
      * @return The non-null array of available face detection modes
      */
-    public byte[] getAvailableFaceDetectModesChecked() {
-        Key<byte[]> key = CameraCharacteristics.STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES;
-        byte[] modes = getValueFromKeyNonNull(key);
+    public int[] getAvailableFaceDetectModesChecked() {
+        Key<int[]> key = CameraCharacteristics.STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES;
+        int[] modes = getValueFromKeyNonNull(key);
 
         if (modes == null) {
-            return new byte[0];
+            return new int[0];
         }
 
-        List<Byte> modeList = Arrays.asList(CameraTestUtils.toObject(modes));
+        List<Integer> modeList = Arrays.asList(CameraTestUtils.toObject(modes));
         checkTrueForKey(key, "Array should contain OFF mode",
-                modeList.contains((byte)CameraMetadata.STATISTICS_FACE_DETECT_MODE_OFF));
+                modeList.contains(CameraMetadata.STATISTICS_FACE_DETECT_MODE_OFF));
         checkElementDistinct(key, modeList);
-        checkArrayValuesInRange(key, modes, (byte)CameraMetadata.STATISTICS_FACE_DETECT_MODE_OFF,
-                (byte)CameraMetadata.STATISTICS_FACE_DETECT_MODE_FULL);
+        checkArrayValuesInRange(key, modes, CameraMetadata.STATISTICS_FACE_DETECT_MODE_OFF,
+                CameraMetadata.STATISTICS_FACE_DETECT_MODE_FULL);
 
         return modes;
     }
@@ -476,9 +496,9 @@
             return 0;
         }
 
-        List<Byte> faceDetectModes =
+        List<Integer> faceDetectModes =
                 Arrays.asList(CameraTestUtils.toObject(getAvailableFaceDetectModesChecked()));
-        if (faceDetectModes.contains((byte)CameraMetadata.STATISTICS_FACE_DETECT_MODE_OFF) &&
+        if (faceDetectModes.contains(CameraMetadata.STATISTICS_FACE_DETECT_MODE_OFF) &&
                 faceDetectModes.size() == 1) {
             checkTrueForKey(key, " value must be 0 if only OFF mode is supported in "
                     + "availableFaceDetectionModes", count == 0);
@@ -497,26 +517,26 @@
      *
      * @return the availalbe tone map modes
      */
-    public byte[] getAvailableToneMapModesChecked() {
-        Key<byte[]> key = CameraCharacteristics.TONEMAP_AVAILABLE_TONE_MAP_MODES;
-        byte[] modes = getValueFromKeyNonNull(key);
+    public int[] getAvailableToneMapModesChecked() {
+        Key<int[]> key = CameraCharacteristics.TONEMAP_AVAILABLE_TONE_MAP_MODES;
+        int[] modes = getValueFromKeyNonNull(key);
 
         if (modes == null) {
-            return new byte[0];
+            return new int[0];
         }
 
-        List<Byte> modeList = Arrays.asList(CameraTestUtils.toObject(modes));
+        List<Integer> modeList = Arrays.asList(CameraTestUtils.toObject(modes));
         checkTrueForKey(key, " Camera devices must always support FAST mode",
-                modeList.contains((byte)CameraMetadata.TONEMAP_MODE_FAST));
+                modeList.contains(CameraMetadata.TONEMAP_MODE_FAST));
         if (isHardwareLevelFull()) {
             checkTrueForKey(key, "Full-capability camera devices must support"
                     + "CONTRAST_CURVE mode",
-                    modeList.contains((byte)CameraMetadata.TONEMAP_MODE_CONTRAST_CURVE) &&
-                    modeList.contains((byte)CameraMetadata.TONEMAP_MODE_FAST));
+                    modeList.contains(CameraMetadata.TONEMAP_MODE_CONTRAST_CURVE) &&
+                    modeList.contains(CameraMetadata.TONEMAP_MODE_FAST));
         }
         checkElementDistinct(key, modeList);
-        checkArrayValuesInRange(key, modes, (byte)CameraMetadata.TONEMAP_MODE_CONTRAST_CURVE,
-                (byte)CameraMetadata.TONEMAP_MODE_HIGH_QUALITY);
+        checkArrayValuesInRange(key, modes, CameraMetadata.TONEMAP_MODE_CONTRAST_CURVE,
+                CameraMetadata.TONEMAP_MODE_HIGH_QUALITY);
 
         return modes;
     }
@@ -534,9 +554,9 @@
             return 0;
         }
 
-        List<Byte> modeList =
+        List<Integer> modeList =
                 Arrays.asList(CameraTestUtils.toObject(getAvailableToneMapModesChecked()));
-        if (modeList.contains((byte)CameraMetadata.TONEMAP_MODE_CONTRAST_CURVE)) {
+        if (modeList.contains(CameraMetadata.TONEMAP_MODE_CONTRAST_CURVE)) {
             checkTrueForKey(key, "Full-capability camera device must support maxCurvePoints "
                     + ">= " + TONEMAP_MAX_CURVE_POINTS_AT_LEAST,
                     count >= TONEMAP_MAX_CURVE_POINTS_AT_LEAST);
@@ -687,12 +707,14 @@
      * @return The value reported by the camera device or the defaultValue otherwise.
      */
     public int getSensitivityMinimumOrDefault(int defaultValue) {
-        return getArrayElementOrDefault(
-                CameraCharacteristics.SENSOR_INFO_SENSITIVITY_RANGE,
-                defaultValue,
-                "minimum",
-                SENSOR_INFO_SENSITIVITY_RANGE_MIN,
-                SENSOR_INFO_SENSITIVITY_RANGE_SIZE);
+        Range<Integer> range = getValueFromKeyNonNull(
+                CameraCharacteristics.SENSOR_INFO_SENSITIVITY_RANGE);
+        if (range == null) {
+            failKeyCheck(CameraCharacteristics.SENSOR_INFO_SENSITIVITY_RANGE,
+                    "had no valid minimum value; using default of " + defaultValue);
+            return defaultValue;
+        }
+        return range.getLower();
     }
 
     /**
@@ -718,12 +740,14 @@
      * @return The value reported by the camera device or the defaultValue otherwise.
      */
     public int getSensitivityMaximumOrDefault(int defaultValue) {
-        return getArrayElementOrDefault(
-                CameraCharacteristics.SENSOR_INFO_SENSITIVITY_RANGE,
-                defaultValue,
-                "maximum",
-                SENSOR_INFO_SENSITIVITY_RANGE_MAX,
-                SENSOR_INFO_SENSITIVITY_RANGE_SIZE);
+        Range<Integer> range = getValueFromKeyNonNull(
+                CameraCharacteristics.SENSOR_INFO_SENSITIVITY_RANGE);
+        if (range == null) {
+            failKeyCheck(CameraCharacteristics.SENSOR_INFO_SENSITIVITY_RANGE,
+                    "had no valid maximum value; using default of " + defaultValue);
+            return defaultValue;
+        }
+        return range.getUpper();
     }
 
     /**
@@ -736,12 +760,14 @@
      * @return The value reported by the camera device or the defaultValue otherwise.
      */
     public long getExposureMinimumOrDefault(long defaultValue) {
-        return getArrayElementOrDefault(
-                CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE,
-                defaultValue,
-                "minimum",
-                SENSOR_INFO_EXPOSURE_TIME_RANGE_MIN,
-                SENSOR_INFO_EXPOSURE_TIME_RANGE_SIZE);
+        Range<Long> range = getValueFromKeyNonNull(
+                CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE);
+        if (range == null) {
+            failKeyCheck(CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE,
+                    "had no valid minimum value; using default of " + defaultValue);
+            return defaultValue;
+        }
+        return range.getLower();
     }
 
     /**
@@ -767,12 +793,14 @@
      * @return The value reported by the camera device or the defaultValue otherwise.
      */
     public long getExposureMaximumOrDefault(long defaultValue) {
-        return getArrayElementOrDefault(
-                CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE,
-                defaultValue,
-                "maximum",
-                SENSOR_INFO_EXPOSURE_TIME_RANGE_MAX,
-                SENSOR_INFO_EXPOSURE_TIME_RANGE_SIZE);
+        Range<Long> range = getValueFromKeyNonNull(
+                CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE);
+        if (range == null) {
+            failKeyCheck(CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE,
+                    "had no valid maximum value; using default of " + defaultValue);
+            return defaultValue;
+        }
+        return range.getUpper();
     }
 
     /**
@@ -796,14 +824,14 @@
      * have to abort the execution even the aeMode list is invalid.</p>
      * @return AE available modes
      */
-    public byte[] getAeAvailableModesChecked() {
-        Key<byte[]> modesKey = CameraCharacteristics.CONTROL_AE_AVAILABLE_MODES;
-        byte[] modes = getValueFromKeyNonNull(modesKey);
+    public int[] getAeAvailableModesChecked() {
+        Key<int[]> modesKey = CameraCharacteristics.CONTROL_AE_AVAILABLE_MODES;
+        int[] modes = getValueFromKeyNonNull(modesKey);
         if (modes == null) {
-            modes = new byte[0];
+            modes = new int[0];
         }
         List<Integer> modeList = new ArrayList<Integer>();
-        for (byte mode : modes) {
+        for (int mode : modes) {
             modeList.add((int)(mode));
         }
         checkTrueForKey(modesKey, "value is empty", !modeList.isEmpty());
@@ -842,7 +870,7 @@
         checkTrueForKey(modesKey, "Full capability device must have OFF mode", condition);
 
         // Boundary check.
-        for (byte mode : modes) {
+        for (int mode : modes) {
             checkTrueForKey(modesKey, "Value " + mode + " is out of bound",
                     mode >= CameraMetadata.CONTROL_AE_MODE_OFF
                     && mode <= CameraMetadata.CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE);
@@ -857,21 +885,21 @@
      * @return array that contains available AWB modes, empty array if awbAvailableModes is
      * unavailable.
      */
-    public byte[] getAwbAvailableModesChecked() {
-        Key<byte[]> key =
+    public int[] getAwbAvailableModesChecked() {
+        Key<int[]> key =
                 CameraCharacteristics.CONTROL_AWB_AVAILABLE_MODES;
-        byte[] awbModes = getValueFromKeyNonNull(key);
+        int[] awbModes = getValueFromKeyNonNull(key);
 
         if (awbModes == null) {
-            return new byte[0];
+            return new int[0];
         }
 
-        List<Byte> modesList = Arrays.asList(CameraTestUtils.toObject(awbModes));
+        List<Integer> modesList = Arrays.asList(CameraTestUtils.toObject(awbModes));
         checkTrueForKey(key, " All camera devices must support AUTO mode",
-                modesList.contains((byte)CameraMetadata.CONTROL_AWB_MODE_AUTO));
+                modesList.contains(CameraMetadata.CONTROL_AWB_MODE_AUTO));
         if (isHardwareLevelFull()) {
             checkTrueForKey(key, " Full capability camera devices must support OFF mode",
-                    modesList.contains((byte)CameraMetadata.CONTROL_AWB_MODE_OFF));
+                    modesList.contains(CameraMetadata.CONTROL_AWB_MODE_OFF));
         }
 
         return awbModes;
@@ -883,21 +911,21 @@
      * @return array that contains available AF modes, empty array if afAvailableModes is
      * unavailable.
      */
-    public byte[] getAfAvailableModesChecked() {
-        Key<byte[]> key =
+    public int[] getAfAvailableModesChecked() {
+        Key<int[]> key =
                 CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES;
-        byte[] afModes = getValueFromKeyNonNull(key);
+        int[] afModes = getValueFromKeyNonNull(key);
 
         if (afModes == null) {
-            return new byte[0];
+            return new int[0];
         }
 
-        List<Byte> modesList = Arrays.asList(CameraTestUtils.toObject(afModes));
+        List<Integer> modesList = Arrays.asList(CameraTestUtils.toObject(afModes));
         checkTrueForKey(key, " All camera devices must support OFF mode",
-                modesList.contains((byte)CameraMetadata.CONTROL_AF_MODE_OFF));
+                modesList.contains(CameraMetadata.CONTROL_AF_MODE_OFF));
         if (hasFocuser()) {
             checkTrueForKey(key, " Camera devices that have focuser units must support AUTO mode",
-                    modesList.contains((byte)CameraMetadata.CONTROL_AF_MODE_AUTO));
+                    modesList.contains(CameraMetadata.CONTROL_AF_MODE_AUTO));
         }
 
         return afModes;
@@ -959,7 +987,7 @@
                 utilSizes = config.getOutputSizes(format);
                 break;
             case Input:
-                utilSizes = config.getInputSizes(format);
+                utilSizes = null;
                 break;
             default:
                 throw new IllegalArgumentException("direction must be output or input");
@@ -984,27 +1012,24 @@
      *
      * @return Empty int array if aeAvailableTargetFpsRanges is invalid.
      */
-    public int[] getAeAvailableTargetFpsRangesChecked() {
-        final int NUM_ELEMENTS_IN_FPS_RANGE = 2;
-        Key<int[]> key =
+    @SuppressWarnings("raw")
+    public Range<Integer>[] getAeAvailableTargetFpsRangesChecked() {
+        Key<Range<Integer>[]> key =
                 CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES;
-        int[] fpsRanges = getValueFromKeyNonNull(key);
+        Range<Integer>[] fpsRanges = getValueFromKeyNonNull(key);
 
         if (fpsRanges == null) {
-            return new int[0];
+            return new Range[0];
         }
 
-        checkTrueForKey(key, "array length is invalid", fpsRanges.length
-                % NUM_ELEMENTS_IN_FPS_RANGE == 0);
         // Round down to 2 boundary if it is not integer times of 2, to avoid array out of bound
         // in case the above check fails.
-        int fpsRangeLength = (fpsRanges.length / NUM_ELEMENTS_IN_FPS_RANGE)
-                * NUM_ELEMENTS_IN_FPS_RANGE;
+        int fpsRangeLength = fpsRanges.length;
         int minFps, maxFps;
         long maxFrameDuration = getMaxFrameDurationChecked();
-        for (int i = 0; i < fpsRangeLength; i += NUM_ELEMENTS_IN_FPS_RANGE) {
-            minFps = fpsRanges[i];
-            maxFps = fpsRanges[i + 1];
+        for (int i = 0; i < fpsRangeLength; i += 1) {
+            minFps = fpsRanges[i].getLower();
+            maxFps = fpsRanges[i].getUpper();
             checkTrueForKey(key, " min fps must be no larger than max fps!",
                     minFps > 0 && maxFps >= minFps);
             long maxDuration = (long) (1e9 / minFps);
@@ -1063,40 +1088,40 @@
         return minDurationMap;
     }
 
-    public byte[] getAvailableEdgeModesChecked() {
-        Key<byte[]> key = CameraCharacteristics.EDGE_AVAILABLE_EDGE_MODES;
-        byte[] edgeModes = getValueFromKeyNonNull(key);
+    public int[] getAvailableEdgeModesChecked() {
+        Key<int[]> key = CameraCharacteristics.EDGE_AVAILABLE_EDGE_MODES;
+        int[] edgeModes = getValueFromKeyNonNull(key);
 
         if (edgeModes == null) {
-            return new byte[0];
+            return new int[0];
         }
 
         // Full device should always include OFF and FAST
         if (isHardwareLevelFull()) {
-            List<Byte> modeList = Arrays.asList(CameraTestUtils.toObject(edgeModes));
+            List<Integer> modeList = Arrays.asList(CameraTestUtils.toObject(edgeModes));
             checkTrueForKey(key, "Full device must contain OFF and FAST edge modes",
-                    modeList.contains((byte)CameraMetadata.EDGE_MODE_OFF) &&
-                    modeList.contains((byte)CameraMetadata.EDGE_MODE_FAST));
+                    modeList.contains(CameraMetadata.EDGE_MODE_OFF) &&
+                    modeList.contains(CameraMetadata.EDGE_MODE_FAST));
         }
 
         return edgeModes;
     }
 
-    public byte[] getAvailableNoiseReductionModesChecked() {
-        Key<byte[]> key =
+    public int[] getAvailableNoiseReductionModesChecked() {
+        Key<int[]> key =
                 CameraCharacteristics.NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES;
-        byte[] noiseReductionModes = getValueFromKeyNonNull(key);
+        int[] noiseReductionModes = getValueFromKeyNonNull(key);
 
         if (noiseReductionModes == null) {
-            return new byte[0];
+            return new int[0];
         }
 
         // Full device should always include OFF and FAST
         if (isHardwareLevelFull()) {
-            List<Byte> modeList = Arrays.asList(CameraTestUtils.toObject(noiseReductionModes));
+            List<Integer> modeList = Arrays.asList(CameraTestUtils.toObject(noiseReductionModes));
             checkTrueForKey(key, "Full device must contain OFF and FAST noise reduction modes",
-                    modeList.contains((byte)CameraMetadata.NOISE_REDUCTION_MODE_OFF) &&
-                    modeList.contains((byte)CameraMetadata.NOISE_REDUCTION_MODE_FAST));
+                    modeList.contains(CameraMetadata.NOISE_REDUCTION_MODE_OFF) &&
+                    modeList.contains(CameraMetadata.NOISE_REDUCTION_MODE_FAST));
         }
 
         return noiseReductionModes;
@@ -1117,7 +1142,9 @@
             return CONTROL_AE_COMPENSATION_STEP_DEFAULT;
         }
 
-        checkTrueForKey(key, " value must be no more than 1/2", compensationStep.toFloat() < 0.5f);
+        float compensationStepF =
+                (float) compensationStep.getNumerator() / compensationStep.getDenominator();
+        checkTrueForKey(key, " value must be no more than 1/2", compensationStepF < 0.5f);
         return compensationStep;
     }
 
@@ -1126,26 +1153,23 @@
      *
      * @return default value if the value is null or malformed.
      */
-    public int[] getAeCompensationRangeChecked() {
-        Key<int[]> key =
+    public Range<Integer> getAeCompensationRangeChecked() {
+        Key<Range<Integer>> key =
                 CameraCharacteristics.CONTROL_AE_COMPENSATION_RANGE;
-        int[] compensationRange = getValueFromKeyNonNull(key);
-        float compensationStep = getAeCompensationStepChecked().toFloat();
-        final int[] DEFAULT_RANGE = new int[] {
-                (int)(CONTROL_AE_COMPENSATION_RANGE_DEFAULT_MIN / compensationStep),
-                (int)(CONTROL_AE_COMPENSATION_RANGE_DEFAULT_MAX / compensationStep)};
+        Range<Integer> compensationRange = getValueFromKeyNonNull(key);
+        Rational compensationStep = getAeCompensationStepChecked();
+        float compensationStepF =
+                (float) compensationStep.getNumerator() / compensationStep.getDenominator();
+        final Range<Integer> DEFAULT_RANGE = Range.create(
+                (int)(CONTROL_AE_COMPENSATION_RANGE_DEFAULT_MIN / compensationStepF),
+                (int)(CONTROL_AE_COMPENSATION_RANGE_DEFAULT_MAX / compensationStepF));
         if (compensationRange == null) {
             return DEFAULT_RANGE;
         }
 
-        checkTrueForKey(key, " value must have 2 elements", compensationRange.length == 2);
-        if (compensationRange.length != 2) {
-            return DEFAULT_RANGE;
-        }
-
-        checkTrueForKey(key, " range value must be at least " + Arrays.toString(DEFAULT_RANGE),
-               compensationRange[0] <= DEFAULT_RANGE[0] &&
-               compensationRange[1] >= DEFAULT_RANGE[1]);
+        checkTrueForKey(key, " range value must be at least " + DEFAULT_RANGE,
+               compensationRange.getLower() <= DEFAULT_RANGE.getLower() &&
+               compensationRange.getUpper() >= DEFAULT_RANGE.getUpper());
 
         return compensationRange;
     }
@@ -1155,21 +1179,21 @@
      *
      * @return available video stabilization modes, empty array if it is unavailable.
      */
-    public byte[] getAvailableVideoStabilizationModesChecked() {
-        Key<byte[]> key =
+    public int[] getAvailableVideoStabilizationModesChecked() {
+        Key<int[]> key =
                 CameraCharacteristics.CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES;
-        byte[] modes = getValueFromKeyNonNull(key);
+        int[] modes = getValueFromKeyNonNull(key);
 
         if (modes == null) {
-            return new byte[0];
+            return new int[0];
         }
 
-        List<Byte> modeList = Arrays.asList(CameraTestUtils.toObject(modes));
+        List<Integer> modeList = Arrays.asList(CameraTestUtils.toObject(modes));
         checkTrueForKey(key, " All device should support OFF mode",
-                modeList.contains((byte)CameraMetadata.CONTROL_VIDEO_STABILIZATION_MODE_OFF));
+                modeList.contains(CameraMetadata.CONTROL_VIDEO_STABILIZATION_MODE_OFF));
         checkArrayValuesInRange(key, modes,
-                (byte)CameraMetadata.CONTROL_VIDEO_STABILIZATION_MODE_OFF,
-                (byte)CameraMetadata.CONTROL_VIDEO_STABILIZATION_MODE_ON);
+                CameraMetadata.CONTROL_VIDEO_STABILIZATION_MODE_OFF,
+                CameraMetadata.CONTROL_VIDEO_STABILIZATION_MODE_ON);
 
         return modes;
     }
@@ -1179,18 +1203,18 @@
      *
      * @return available optical stabilization modes, empty array if it is unavailable.
      */
-    public byte[] getAvailableOpticalStabilizationChecked() {
-        Key<byte[]> key =
+    public int[] getAvailableOpticalStabilizationChecked() {
+        Key<int[]> key =
                 CameraCharacteristics.LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION;
-        byte[] modes = getValueFromKeyNonNull(key);
+        int[] modes = getValueFromKeyNonNull(key);
 
         if (modes == null) {
-            return new byte[0];
+            return new int[0];
         }
 
         checkArrayValuesInRange(key, modes,
-                (byte)CameraMetadata.LENS_OPTICAL_STABILIZATION_MODE_OFF,
-                (byte)CameraMetadata.LENS_OPTICAL_STABILIZATION_MODE_ON);
+                CameraMetadata.LENS_OPTICAL_STABILIZATION_MODE_OFF,
+                CameraMetadata.LENS_OPTICAL_STABILIZATION_MODE_ON);
 
         return modes;
     }
@@ -1214,38 +1238,38 @@
         return maxZoom;
     }
 
-    public byte[] getAvailableSceneModesChecked() {
-        Key<byte[]> key =
+    public int[] getAvailableSceneModesChecked() {
+        Key<int[]> key =
                 CameraCharacteristics.CONTROL_AVAILABLE_SCENE_MODES;
-        byte[] modes = getValueFromKeyNonNull(key);
+        int[] modes = getValueFromKeyNonNull(key);
 
         if (modes == null) {
-            return new byte[0];
+            return new int[0];
         }
 
-        List<Byte> modeList = Arrays.asList(CameraTestUtils.toObject(modes));
+        List<Integer> modeList = Arrays.asList(CameraTestUtils.toObject(modes));
         // FACE_PRIORITY must be included if face detection is supported.
         if (getMaxFaceCountChecked() > 0) {
             checkTrueForKey(key, " FACE_PRIORITY must be included if face detection is supported",
-                    modeList.contains((byte)CameraMetadata.CONTROL_SCENE_MODE_FACE_PRIORITY));
+                    modeList.contains(CameraMetadata.CONTROL_SCENE_MODE_FACE_PRIORITY));
         }
 
         return modes;
     }
 
-    public byte[] getAvailableEffectModesChecked() {
-        Key<byte[]> key =
+    public int[] getAvailableEffectModesChecked() {
+        Key<int[]> key =
                 CameraCharacteristics.CONTROL_AVAILABLE_EFFECTS;
-        byte[] modes = getValueFromKeyNonNull(key);
+        int[] modes = getValueFromKeyNonNull(key);
 
         if (modes == null) {
-            return new byte[0];
+            return new int[0];
         }
 
-        List<Byte> modeList = Arrays.asList(CameraTestUtils.toObject(modes));
+        List<Integer> modeList = Arrays.asList(CameraTestUtils.toObject(modes));
         // OFF must be included.
         checkTrueForKey(key, " OFF must be included",
-                modeList.contains((byte)CameraMetadata.CONTROL_EFFECT_MODE_OFF));
+                modeList.contains(CameraMetadata.CONTROL_EFFECT_MODE_OFF));
 
         return modes;
     }
@@ -1271,6 +1295,87 @@
     }
 
     /**
+     * Get available capabilities and do the sanity check.
+     *
+     * @return reported available capabilities list, empty list if the value is unavailable.
+     */
+    public List<Integer> getAvailableCapabilitiesChecked() {
+        Key<int[]> key =
+                CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES;
+        int[] availableCaps = getValueFromKeyNonNull(key);
+        List<Integer> capList;
+
+        if (availableCaps == null) {
+            return new ArrayList<Integer>();
+        }
+
+        // TODO: Backward compatible key is hidden. Fix that after we have better enum check
+        /*checkArrayValuesInRange(key, availableCaps,
+                CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE,
+                CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_DNG);*/
+        capList = Arrays.asList(CameraTestUtils.toObject(availableCaps));
+        return capList;
+    }
+
+    /**
+     * Get max number of output raw streams and do the basic sanity check.
+     *
+     * @return reported max number of raw output stream
+     */
+    public int getMaxNumOutputStreamsRawChecked() {
+        Integer maxNumStreams =
+                getValueFromKeyNonNull(CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_RAW);
+        if (maxNumStreams == null)
+            return 0;
+        return maxNumStreams;
+    }
+
+    /**
+     * Get max number of output processed streams and do the basic sanity check.
+     *
+     * @return reported max number of processed output stream
+     */
+    public int getMaxNumOutputStreamsProcessedChecked() {
+        Integer maxNumStreams =
+                getValueFromKeyNonNull(CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_PROC);
+        if (maxNumStreams == null)
+            return 0;
+        return maxNumStreams;
+    }
+
+    /**
+     * Get max number of output stalling processed streams and do the basic sanity check.
+     *
+     * @return reported max number of stalling processed output stream
+     */
+    public int getMaxNumOutputStreamsProcessedStallChecked() {
+        Integer maxNumStreams =
+                getValueFromKeyNonNull(CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_PROC_STALLING);
+        if (maxNumStreams == null)
+            return 0;
+        return maxNumStreams;
+    }
+
+    /**
+     * Get lens facing and do the sanity check
+     * @return lens facing, return default value (BACK) if value is unavailable.
+     */
+    public int getLensFacingChecked() {
+        Key<Integer> key =
+                CameraCharacteristics.LENS_FACING;
+        Integer facing = getValueFromKeyNonNull(key);
+
+        if (facing == null) {
+            return CameraCharacteristics.LENS_FACING_BACK;
+        }
+
+        checkTrueForKey(key, " value is out of range ",
+                facing >= CameraCharacteristics.LENS_FACING_FRONT &&
+                facing <= CameraCharacteristics.LENS_FACING_BACK);
+        return facing;
+    }
+
+    /**
      * Get the value in index for a fixed-size array from a given key.
      *
      * <p>If the camera device is incorrectly reporting values, log a warning and return
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/testcases/Camera2AndroidTestCase.java b/tests/tests/hardware/src/android/hardware/camera2/cts/testcases/Camera2AndroidTestCase.java
index 75d91bf..de8a49a 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/testcases/Camera2AndroidTestCase.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/testcases/Camera2AndroidTestCase.java
@@ -20,6 +20,7 @@
 import static com.android.ex.camera2.blocking.BlockingStateListener.*;
 
 import android.content.Context;
+import android.hardware.camera2.CameraCaptureSession;
 import android.hardware.camera2.CameraDevice;
 import android.hardware.camera2.CameraDevice.CaptureListener;
 import android.hardware.camera2.CameraManager;
@@ -115,7 +116,7 @@
      */
     protected void startCapture(CaptureRequest request, boolean repeating,
             CaptureListener listener, Handler handler) throws Exception {
-        if (VERBOSE) Log.v(TAG, "Starting capture");
+        if (VERBOSE) Log.v(TAG, "Starting capture from device");
 
         if (repeating) {
             mCamera.setRepeatingRequest(request, listener, handler);
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/testcases/Camera2SurfaceViewTestCase.java b/tests/tests/hardware/src/android/hardware/camera2/cts/testcases/Camera2SurfaceViewTestCase.java
index 7470f24..e84d417 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/testcases/Camera2SurfaceViewTestCase.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/testcases/Camera2SurfaceViewTestCase.java
@@ -37,6 +37,7 @@
 import android.hardware.camera2.CaptureRequest;
 import android.hardware.camera2.CaptureResult;
 import android.util.Size;
+import android.util.Range;
 import android.hardware.camera2.CameraDevice.CaptureListener;
 import android.hardware.camera2.cts.Camera2SurfaceViewStubActivity;
 import android.hardware.camera2.cts.CameraTestUtils;
@@ -67,9 +68,7 @@
     private static final String TAG = "SurfaceViewTestCase";
     private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
     private static final int WAIT_FOR_SURFACE_CHANGE_TIMEOUT_MS = 1000;
-    private static final int MAX_READER_IMAGES = 5;
-
-    private Size mPreviewSize;
+    protected static final int MAX_READER_IMAGES = 5;
 
     // TODO: Use internal storage for this to make sure the file is only visible to test.
     protected static final String DEBUG_FILE_NAME_BASE =
@@ -91,6 +90,7 @@
     protected ImageReader mReader;
     protected Surface mReaderSurface;
     protected Surface mPreviewSurface;
+    protected Size mPreviewSize;
     protected List<Size> mOrderedPreviewSizes; // In descending order.
     protected List<Size> mOrderedVideoSizes; // In descending order.
     protected List<Size> mOrderedStillSizes; // In descending order.
@@ -392,26 +392,56 @@
             ImageReader.OnImageAvailableListener listener) throws Exception {
         closeImageReader();
 
-        mReader = ImageReader.newInstance(size.getWidth(), size.getHeight(), format, maxNumImages);
-        mReaderSurface = mReader.getSurface();
-        mReader.setOnImageAvailableListener(listener, mHandler);
+        ImageReader r = makeImageReader(size, format, maxNumImages, listener,
+                mHandler);
+        mReader = r;
+        mReaderSurface = r.getSurface();
+    }
+
+    /**
+     * Create an {@link ImageReader} object and get the surface.
+     *
+     * @param size The size of this ImageReader to be created.
+     * @param format The format of this ImageReader to be created
+     * @param maxNumImages The max number of images that can be acquired simultaneously.
+     * @param listener The listener used by this ImageReader to notify callbacks.
+     * @param handler The handler to use for any listener callbacks.
+     */
+    protected static ImageReader makeImageReader(Size size, int format,
+                                                             int maxNumImages,
+                                                             ImageReader.OnImageAvailableListener
+                                                                     listener,
+                                                             Handler handler) {
+        ImageReader reader =  ImageReader.newInstance(size.getWidth(), size.getHeight(), format,
+                maxNumImages);
+        reader.setOnImageAvailableListener(listener, handler);
         if (VERBOSE) Log.v(TAG, "Created ImageReader size " + size.toString());
+        return reader;
     }
 
     /**
      * Close the pending images then close current active {@link ImageReader} object.
      */
     protected void closeImageReader() {
-        if (mReader != null) {
+        closeImageReader(mReader);
+        mReader = null;
+        mReaderSurface = null;
+    }
+
+    /**
+     * Close pending images and clean up an {@link ImageReader} object.
+     * @param reader an {@link ImageReader} to close.
+     */
+    public static void closeImageReader(ImageReader reader) {
+        if (reader != null) {
             try {
                 // Close all possible pending images first.
-                Image image = mReader.acquireLatestImage();
+                Image image = reader.acquireLatestImage();
                 if (image != null) {
                     image.close();
                 }
             } finally {
-                mReader.close();
-                mReader = null;
+                reader.close();
             }
         }
     }
@@ -523,8 +553,8 @@
      * @param fpsRange The fps range the returned size must support.
      * @return max size that support the given fps range.
      */
-    protected Size getMaxPreviewSizeForFpsRange(int[] fpsRange) {
-        if (fpsRange == null || fpsRange[0] <= 0 || fpsRange[1] <= 0) {
+    protected Size getMaxPreviewSizeForFpsRange(Range<Integer> fpsRange) {
+        if (fpsRange == null || fpsRange.getLower() <= 0 || fpsRange.getUpper() <= 0) {
             throw new IllegalArgumentException("Invalid fps range argument");
         }
         if (mOrderedPreviewSizes == null || mMinPreviewFrameDurationMap == null) {
@@ -533,7 +563,7 @@
         }
 
         long[] frameDurationRange =
-                new long[]{(long) (1e9 / fpsRange[1]), (long) (1e9 / fpsRange[0])};
+                new long[]{(long) (1e9 / fpsRange.getUpper()), (long) (1e9 / fpsRange.getLower())};
         for (Size size : mOrderedPreviewSizes) {
             long minDuration = mMinPreviewFrameDurationMap.get(size);
             if (minDuration <= frameDurationRange[0]) {
diff --git a/tests/tests/hardware/src/android/hardware/cts/CameraTest.java b/tests/tests/hardware/src/android/hardware/cts/CameraTest.java
index 863325f..50a3573 100644
--- a/tests/tests/hardware/src/android/hardware/cts/CameraTest.java
+++ b/tests/tests/hardware/src/android/hardware/cts/CameraTest.java
@@ -2996,6 +2996,7 @@
     }
 
     private static final int[] mCamcorderProfileList = {
+        CamcorderProfile.QUALITY_2160P,
         CamcorderProfile.QUALITY_1080P,
         CamcorderProfile.QUALITY_480P,
         CamcorderProfile.QUALITY_720P,
diff --git a/tests/tests/hardware/src/android/hardware/cts/SensorTest.java b/tests/tests/hardware/src/android/hardware/cts/SensorTest.java
index 907759f..ea4a212 100644
--- a/tests/tests/hardware/src/android/hardware/cts/SensorTest.java
+++ b/tests/tests/hardware/src/android/hardware/cts/SensorTest.java
@@ -21,6 +21,7 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 
 import android.content.Context;
 import android.content.pm.PackageManager;
@@ -33,13 +34,21 @@
 import android.hardware.TriggerEventListener;
 import android.os.Handler;
 import android.os.HandlerThread;
+import android.os.PowerManager;
 import android.test.AndroidTestCase;
+import android.util.Log;
 
 public class SensorTest extends AndroidTestCase {
     private SensorManager mSensorManager;
     private TriggerListener mTriggerListener;
     private SensorListener mSensorListener;
-    private ArrayList<Sensor> mContinuousSensorList;
+    private List<Sensor> mSensorList;
+    private static final String TAG = "SensorTest";
+    // Test only SDK defined sensors. Any sensors with type > 100 are ignored.
+    private static final int MAX_SENSOR_TYPE = 100;
+    private static final int TIMEOUT = 40;
+
+    private PowerManager.WakeLock mWakeLock;
 
     @Override
     protected void setUp() throws Exception {
@@ -47,18 +56,9 @@
         mSensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE);
         mTriggerListener = new TriggerListener();
         mSensorListener = new SensorListener();
-        mContinuousSensorList = new ArrayList<Sensor>();
-        for (int i = Sensor.TYPE_ACCELEROMETER; i <= Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR; ++i) {
-            Sensor sensor = mSensorManager.getDefaultSensor(i);
-            // Skip all non-continuous mode sensors.
-            if (sensor == null || Sensor.TYPE_SIGNIFICANT_MOTION == i ||
-                Sensor.TYPE_STEP_COUNTER == i || Sensor.TYPE_STEP_DETECTOR == i ||
-                Sensor.TYPE_LIGHT == i || Sensor.TYPE_PROXIMITY == i ||
-                Sensor.TYPE_AMBIENT_TEMPERATURE == i) {
-                continue;
-            }
-            mContinuousSensorList.add(sensor);
-        }
+        mSensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL);
+        PowerManager pm = (PowerManager) getContext().getSystemService(Context.POWER_SERVICE);
+        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
     }
 
     public void testSensorOperations() {
@@ -79,7 +79,7 @@
 
         sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);
         boolean hasStepCounter = getContext().getPackageManager().hasSystemFeature(
-                                        PackageManager.FEATURE_SENSOR_STEP_COUNTER);
+                PackageManager.FEATURE_SENSOR_STEP_COUNTER);
         // stepcounter sensor is optional
         if (hasStepCounter) {
             assertEquals(Sensor.TYPE_STEP_COUNTER, sensor.getType());
@@ -90,7 +90,7 @@
 
         sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR);
         boolean hasStepDetector = getContext().getPackageManager().hasSystemFeature(
-                                        PackageManager.FEATURE_SENSOR_STEP_DETECTOR);
+                PackageManager.FEATURE_SENSOR_STEP_DETECTOR);
         // stepdetector sensor is optional
         if (hasStepDetector) {
             assertEquals(Sensor.TYPE_STEP_DETECTOR, sensor.getType());
@@ -189,76 +189,90 @@
     // Register for updates from each continuous mode sensor, wait for 25 events, call flush and
     // wait for flushCompleteEvent before unregistering for the sensor.
     public void testBatchAndFlush() throws Exception {
-        for (Sensor sensor : mContinuousSensorList) {
-            final CountDownLatch eventReceived = new CountDownLatch(25);
-            final CountDownLatch flushReceived = new CountDownLatch(1);
-            SensorEventListener2 listener = new SensorEventListener2() {
-                @Override
-                public void onSensorChanged(SensorEvent event) {
-                    eventReceived.countDown();
+        try {
+            mWakeLock.acquire();
+            for (Sensor sensor : mSensorList) {
+                // Skip OEM defined sensors and trigger sensors.
+                if (sensor.getType() > MAX_SENSOR_TYPE || sensor.getMinDelay() < 0) {
+                    continue;
                 }
-
-                @Override
-                public void onAccuracyChanged(Sensor sensor, int accuracy) {
-                }
-
-                @Override
-                public void onFlushCompleted(Sensor sensor) {
-                    flushReceived.countDown();
-                }
-            };
-            boolean result = mSensorManager.registerListener(listener, sensor,
-                                            SensorManager.SENSOR_DELAY_NORMAL, 10000000);
-            assertTrue(result);
-            // Wait for 25 events and call flush.
-            eventReceived.await();
-            result = mSensorManager.flush(listener);
-            assertTrue(result);
-            flushReceived.await();
-            mSensorManager.unregisterListener(listener);
+                registerListenerCallFlush(sensor, null);
+            }
+        } finally {
+            mWakeLock.release();
         }
     }
 
     // Same as testBatchAndFlush but using Handler version of the API to register for sensors.
     // onSensorChanged is now called on a background thread.
     public void testBatchAndFlushWithHandler() throws Exception {
-        for (Sensor sensor : mContinuousSensorList) {
-            final CountDownLatch eventReceived = new CountDownLatch(25);
-            final CountDownLatch flushReceived = new CountDownLatch(1);
-            SensorEventListener2 listener = new SensorEventListener2() {
-                @Override
-                public void onSensorChanged(SensorEvent event) {
-                    eventReceived.countDown();
-                }
-
-                @Override
-                public void onAccuracyChanged(Sensor sensor, int accuracy) {
-                }
-
-                @Override
-                public void onFlushCompleted(Sensor sensor) {
-                    flushReceived.countDown();
-                }
-            };
+        try {
+            mWakeLock.acquire();
             HandlerThread handlerThread = new HandlerThread("sensorThread");
             handlerThread.start();
             Handler handler = new Handler(handlerThread.getLooper());
-            boolean result = mSensorManager.registerListener(listener, sensor,
-                                            SensorManager.SENSOR_DELAY_NORMAL, 15000000,
-                                            handler);
-            assertTrue(result);
-            // Wait for 25 events and call flush.
-            eventReceived.await();
-            result = mSensorManager.flush(listener);
-            assertTrue(result);
-            flushReceived.await();
-            mSensorManager.unregisterListener(listener);
+            for (Sensor sensor : mSensorList) {
+                // Skip OEM defined sensors and trigger sensors.
+                if (sensor.getType() > MAX_SENSOR_TYPE || sensor.getMinDelay() < 0) {
+                    continue;
+                }
+                registerListenerCallFlush(sensor, handler);
+            }
+        }  finally {
+            mWakeLock.release();
         }
     }
 
+    private void registerListenerCallFlush(Sensor sensor, Handler handler)
+            throws InterruptedException {
+        final CountDownLatch eventReceived = new CountDownLatch(25);
+        final CountDownLatch flushReceived = new CountDownLatch(1);
+        SensorEventListener2 listener = new SensorEventListener2() {
+            @Override
+            public void onSensorChanged(SensorEvent event) {
+                eventReceived.countDown();
+            }
+
+            @Override
+            public void onAccuracyChanged(Sensor sensor, int accuracy) {
+            }
+
+            @Override
+            public void onFlushCompleted(Sensor sensor) {
+                flushReceived.countDown();
+            }
+        };
+        // Consider only continuous mode sensors for testing registerListener.
+        // For on-change sensors, call registerListener() so that the listener is associated
+        // with the sensor so that flush(listener) can be called on it.
+        if (sensor.getMinDelay() >= 0) {
+            Log.i(TAG, "testBatch " + sensor.getName());
+            boolean result = mSensorManager.registerListener(listener, sensor,
+                    SensorManager.SENSOR_DELAY_NORMAL, 10000000, handler);
+            assertTrue("registerListener failed " + sensor.getName(), result);
+            // Wait for 25 events or 40 seconds only for continuous mode sensors.
+            if (sensor.getMinDelay() > 0) {
+                boolean countZero = eventReceived.await(TIMEOUT, TimeUnit.SECONDS);
+                if (!countZero) {
+                    fail("Timed out waiting for events from " + sensor.getName());
+                }
+            }
+        }
+        Log.i(TAG, "testFlush " + sensor.getName());
+        boolean result = mSensorManager.flush(listener);
+        assertTrue("flush failed " + sensor.getName(), result);
+        boolean countZero = flushReceived.await(TIMEOUT, TimeUnit.SECONDS);
+        if (!countZero) {
+            fail("Timed out waiting for flushCompleteEvent from " + sensor.getName());
+        }
+        mSensorManager.unregisterListener(listener);
+        Log.i(TAG, "testBatchAndFlush pass " + sensor.getName());
+    }
+
     // Call registerListener for multiple sensors at a time and call flush.
     public void testBatchAndFlushWithMutipleSensors() throws Exception {
-        int numSensors = mContinuousSensorList.size() < 3 ? mContinuousSensorList.size() : 3;
+        final int MAX_SENSORS = 3;
+        int numSensors = mSensorList.size() < MAX_SENSORS ? mSensorList.size() : MAX_SENSORS;
         if (numSensors == 0) {
             return;
         }
@@ -279,18 +293,46 @@
                 flushReceived.countDown();
             }
         };
-        for (int i = 0; i < numSensors; ++i) {
-            Sensor sensor = mContinuousSensorList.get(i);
-            boolean result = mSensorManager.registerListener(listener, sensor,
-                                            SensorManager.SENSOR_DELAY_FASTEST);
-            assertTrue(result);
+
+        try {
+            mWakeLock.acquire();
+            StringBuilder registeredSensors = new StringBuilder(30);
+            for (Sensor sensor : mSensorList) {
+                // Skip all non-continuous sensors.
+                if (sensor.getMinDelay() <= 0 || sensor.getType() > MAX_SENSOR_TYPE) {
+                    continue;
+                }
+                boolean result = mSensorManager.registerListener(listener, sensor,
+                        SensorManager.SENSOR_DELAY_GAME, 10000000);
+                assertTrue("registerListener failed for " + sensor.getName(), result);
+                registeredSensors.append(sensor.getName());
+                registeredSensors.append(" ");
+                if (--numSensors == 0) {
+                    break;
+                }
+            }
+            if (registeredSensors.toString().isEmpty()) {
+                return;
+            }
+
+            Log.i(TAG, "testBatchAndFlushWithMutipleSensors " + registeredSensors);
+            // Wait for numSensors * 50 events or 40 seconds.
+            boolean countZero = eventReceived.await(TIMEOUT, TimeUnit.SECONDS);
+            if (!countZero) {
+                fail("Timed out waiting for events from " + registeredSensors.toString());
+            }
+            boolean result = mSensorManager.flush(listener);
+            assertTrue("flush failed " + registeredSensors.toString(), result);
+            countZero = flushReceived.await(TIMEOUT, TimeUnit.SECONDS);
+            if (!countZero) {
+                fail("Timed out waiting for flushCompleteEvent from " +
+                      registeredSensors.toString());
+            }
+            mSensorManager.unregisterListener(listener);
+            Log.i(TAG, "testBatchAndFlushWithMutipleSensors passed");
+        } finally {
+            mWakeLock.release();
         }
-        // Wait for N events and call flush.
-        eventReceived.await();
-        boolean result = mSensorManager.flush(listener);
-        assertTrue(result);
-        flushReceived.await();
-        mSensorManager.unregisterListener(listener);
     }
 
     private void assertSensorValues(Sensor sensor) {
diff --git a/tests/tests/media/libmediandkjni/native-media-jni.cpp b/tests/tests/media/libmediandkjni/native-media-jni.cpp
index 9adc887..51d2cf2 100644
--- a/tests/tests/media/libmediandkjni/native-media-jni.cpp
+++ b/tests/tests/media/libmediandkjni/native-media-jni.cpp
@@ -129,7 +129,7 @@
         sizes.add(n);
         sizes.add(AMediaExtractor_getSampleTrackIndex(ex));
         sizes.add(AMediaExtractor_getSampleFlags(ex));
-        sizes.add(AMediaExtractor_getSampletime(ex));
+        sizes.add(AMediaExtractor_getSampleTime(ex));
         AMediaExtractor_advance(ex);
     }
 
@@ -279,7 +279,7 @@
                     ALOGV("EOS");
                     //break;
                 }
-                int64_t presentationTimeUs = AMediaExtractor_getSampletime(ex);
+                int64_t presentationTimeUs = AMediaExtractor_getSampleTime(ex);
 
                 AMediaCodec_queueInputBuffer(codec[t], bufidx, 0, sampleSize, presentationTimeUs,
                         sawInputEOS[t] ? AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM : 0);
@@ -421,7 +421,7 @@
                 sawInputEOS = true;
                 ALOGV("EOS");
             }
-            int64_t presentationTimeUs = AMediaExtractor_getSampletime(ex);
+            int64_t presentationTimeUs = AMediaExtractor_getSampleTime(ex);
 
             AMediaCodec_queueInputBuffer(codec, bufidx, 0, sampleSize, presentationTimeUs,
                     sawInputEOS ? AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM : 0);
@@ -504,7 +504,7 @@
         }
         info.offset = 0;
         info.size = n;
-        info.presentationTimeUs = AMediaExtractor_getSampletime(ex);
+        info.presentationTimeUs = AMediaExtractor_getSampleTime(ex);
         info.flags = AMediaExtractor_getSampleFlags(ex);
 
         size_t idx = (size_t) AMediaExtractor_getSampleTrackIndex(ex);
diff --git a/tests/tests/media/src/android/media/cts/CamcorderProfileTest.java b/tests/tests/media/src/android/media/cts/CamcorderProfileTest.java
index 1df5011..965deae 100644
--- a/tests/tests/media/src/android/media/cts/CamcorderProfileTest.java
+++ b/tests/tests/media/src/android/media/cts/CamcorderProfileTest.java
@@ -65,13 +65,15 @@
                    profile.quality == CamcorderProfile.QUALITY_480P ||
                    profile.quality == CamcorderProfile.QUALITY_720P ||
                    profile.quality == CamcorderProfile.QUALITY_1080P ||
+                   profile.quality == CamcorderProfile.QUALITY_2160P ||
                    profile.quality == CamcorderProfile.QUALITY_TIME_LAPSE_LOW ||
                    profile.quality == CamcorderProfile.QUALITY_TIME_LAPSE_HIGH ||
                    profile.quality == CamcorderProfile.QUALITY_TIME_LAPSE_QCIF ||
                    profile.quality == CamcorderProfile.QUALITY_TIME_LAPSE_CIF ||
                    profile.quality == CamcorderProfile.QUALITY_TIME_LAPSE_480P ||
                    profile.quality == CamcorderProfile.QUALITY_TIME_LAPSE_720P ||
-                   profile.quality == CamcorderProfile.QUALITY_TIME_LAPSE_1080P);
+                   profile.quality == CamcorderProfile.QUALITY_TIME_LAPSE_1080P ||
+                   profile.quality == CamcorderProfile.QUALITY_TIME_LAPSE_2160P);
         assertTrue(profile.videoBitRate > 0);
         assertTrue(profile.videoFrameRate > 0);
         assertTrue(profile.videoFrameWidth > 0);
@@ -137,6 +139,11 @@
                 assertTrue(1088 == profile.videoFrameHeight ||
                            1080 == profile.videoFrameHeight);
                 break;
+            case CamcorderProfile.QUALITY_2160P:
+            case CamcorderProfile.QUALITY_TIME_LAPSE_2160P:
+                assertEquals(3840, profile.videoFrameWidth);
+                assertEquals(2160, profile.videoFrameHeight);
+                break;
         }
     }
 
@@ -210,14 +217,16 @@
                                           CamcorderProfile.QUALITY_CIF,
                                           CamcorderProfile.QUALITY_480P,
                                           CamcorderProfile.QUALITY_720P,
-                                          CamcorderProfile.QUALITY_1080P};
+                                          CamcorderProfile.QUALITY_1080P,
+                                          CamcorderProfile.QUALITY_2160P};
 
         int[] specificTimeLapseProfileQualities = {CamcorderProfile.QUALITY_TIME_LAPSE_QCIF,
                                                    CamcorderProfile.QUALITY_TIME_LAPSE_QVGA,
                                                    CamcorderProfile.QUALITY_TIME_LAPSE_CIF,
                                                    CamcorderProfile.QUALITY_TIME_LAPSE_480P,
                                                    CamcorderProfile.QUALITY_TIME_LAPSE_720P,
-                                                   CamcorderProfile.QUALITY_TIME_LAPSE_1080P};
+                                                   CamcorderProfile.QUALITY_TIME_LAPSE_1080P,
+                                                   CamcorderProfile.QUALITY_TIME_LAPSE_2160P};
 
         checkSpecificProfiles(cameraId, lowProfile, highProfile,
                 specificProfileQualities, videoSizes);
diff --git a/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayTest.java b/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayTest.java
index d9ef023..89b06dc 100755
--- a/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayTest.java
+++ b/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayTest.java
@@ -161,6 +161,25 @@
         }
     }
 
+    private static boolean hasCodec(String mimeType) {
+        int numCodecs = MediaCodecList.getCodecCount();
+        for (int i = 0; i < numCodecs; i++) {
+            MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
+
+            if (!codecInfo.isEncoder()) {
+                continue;
+            }
+
+            String[] types = codecInfo.getSupportedTypes();
+            for (int j = 0; j < types.length; j++) {
+                if (types[j].equalsIgnoreCase(mimeType)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
     /**
      * Returns true if the encoder level, specified in the ENCODER_PARAM_TABLE, can be supported.
      */
@@ -226,6 +245,11 @@
         OutputSurface outputSurface = null;
         VirtualDisplay virtualDisplay = null;
 
+        // Don't run the test of the codec isn't present.
+        if (!hasCodec(MIME_TYPE)) {
+            return;
+        }
+
         try {
             // Encoded video resolution matches virtual display.
             MediaFormat encoderFormat = MediaFormat.createVideoFormat(MIME_TYPE, sWidth, sHeight);
diff --git a/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayWithCompositionTest.java b/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayWithCompositionTest.java
index d7ba82d..42e188c 100644
--- a/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayWithCompositionTest.java
+++ b/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayWithCompositionTest.java
@@ -138,6 +138,10 @@
     public void testRendering800x480Locally() throws Throwable {
         Log.i(TAG, "testRendering800x480Locally");
         Pair<Integer, Integer> maxRes = checkMaxConcurrentEncodingDecodingResolution();
+        if (maxRes == null) {
+            Log.i(TAG, "codec not supported, skipping the test");
+            return;
+        }
         if (maxRes.first >= 800 && maxRes.second >= 480) {
             runTestRenderingInSeparateThread(800, 480, false, false);
         } else {
@@ -148,6 +152,10 @@
     public void testRenderingMaxResolutionLocally() throws Throwable {
         Log.i(TAG, "testRenderingMaxResolutionLocally");
         Pair<Integer, Integer> maxRes = checkMaxConcurrentEncodingDecodingResolution();
+        if (maxRes == null) {
+            Log.i(TAG, "codec not supported, skipping the test");
+            return;
+        }
         Log.w(TAG, "Trying resolution w:" + maxRes.first + " h:" + maxRes.second);
         runTestRenderingInSeparateThread(maxRes.first, maxRes.second, false, false);
     }
@@ -155,6 +163,10 @@
     public void testRendering800x480Remotely() throws Throwable {
         Log.i(TAG, "testRendering800x480Remotely");
         Pair<Integer, Integer> maxRes = checkMaxConcurrentEncodingDecodingResolution();
+        if (maxRes == null) {
+            Log.i(TAG, "codec not supported, skipping the test");
+            return;
+        }
         if (maxRes.first >= 800 && maxRes.second >= 480) {
             runTestRenderingInSeparateThread(800, 480, true, false);
         } else {
@@ -165,6 +177,10 @@
     public void testRenderingMaxResolutionRemotely() throws Throwable {
         Log.i(TAG, "testRenderingMaxResolutionRemotely");
         Pair<Integer, Integer> maxRes = checkMaxConcurrentEncodingDecodingResolution();
+        if (maxRes == null) {
+            Log.i(TAG, "codec not supported, skipping the test");
+            return;
+        }
         Log.w(TAG, "Trying resolution w:" + maxRes.first + " h:" + maxRes.second);
         runTestRenderingInSeparateThread(maxRes.first, maxRes.second, true, false);
     }
@@ -172,6 +188,10 @@
     public void testRendering800x480RemotelyWith3Windows() throws Throwable {
         Log.i(TAG, "testRendering800x480RemotelyWith3Windows");
         Pair<Integer, Integer> maxRes = checkMaxConcurrentEncodingDecodingResolution();
+        if (maxRes == null) {
+            Log.i(TAG, "codec not supported, skipping the test");
+            return;
+        }
         if (maxRes.first >= 800 && maxRes.second >= 480) {
             runTestRenderingInSeparateThread(800, 480, true, true);
         } else {
@@ -182,6 +202,10 @@
     public void testRendering800x480LocallyWith3Windows() throws Throwable {
         Log.i(TAG, "testRendering800x480LocallyWith3Windows");
         Pair<Integer, Integer> maxRes = checkMaxConcurrentEncodingDecodingResolution();
+        if (maxRes == null) {
+            Log.i(TAG, "codec not supported, skipping the test");
+            return;
+        }
         if (maxRes.first >= 800 && maxRes.second >= 480) {
             runTestRenderingInSeparateThread(800, 480, false, true);
         } else {
@@ -400,6 +424,10 @@
     private static final int NUM_RENDERING = 10;
     private void doTestVirtualDisplayRecycles(int numDisplays) throws Exception {
         CodecInfo codecInfo = getAvcSupportedFormatInfo();
+        if (codecInfo == null) {
+            Log.i(TAG, "no codec found, skipping");
+            return;
+        }
         VirtualDisplayPresentation[] virtualDisplays = new VirtualDisplayPresentation[numDisplays];
         for (int i = 0; i < NUM_CODEC_CREATION; i++) {
             mCodecConfigReceived = false;
@@ -1323,6 +1351,9 @@
 
     private static CodecInfo getAvcSupportedFormatInfo() {
         MediaCodecInfo mediaCodecInfo = selectCodec(MIME_TYPE);
+        if (mediaCodecInfo == null) {
+            return null;
+        }
         CodecCapabilities cap = mediaCodecInfo.getCapabilitiesForType(MIME_TYPE);
         if (cap == null) { // not supported
             return null;
@@ -1405,6 +1436,9 @@
      */
     private Pair<Integer, Integer> checkMaxConcurrentEncodingDecodingResolution() {
         CodecInfo codecInfo = getAvcSupportedFormatInfo();
+        if (codecInfo == null) {
+            return null;
+        }
         int maxW = codecInfo.mMaxW;
         int maxH = codecInfo.mMaxH;
         if (maxW >= 1920 && maxH >= 1080) {
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java b/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java
index b75a635..142318a 100644
--- a/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java
@@ -35,7 +35,10 @@
     private static final int PLAY_TIME_MS = 30000;
 
     public void testAvcBaseline1() throws Exception {
-        if (!supports(AVC_MIME, CodecProfileLevel.AVCProfileBaseline,
+        if (!supports(AVC_MIME, CodecProfileLevel.AVCProfileBaseline)) {
+          return;
+        }
+        if (supports(AVC_MIME, CodecProfileLevel.AVCProfileBaseline,
                 CodecProfileLevel.AVCLevel1)) {
             throw new RuntimeException("AVCLevel1 support is required by CDD");
         }
@@ -44,6 +47,9 @@
     }
 
     public void testAvcBaseline12() throws Exception {
+        if (!supports(AVC_MIME, CodecProfileLevel.AVCProfileBaseline)) {
+            return;
+        }
         if (!supports(AVC_MIME, CodecProfileLevel.AVCProfileBaseline,
                 CodecProfileLevel.AVCLevel12)) {
             Log.i(TAG, "AvcBaseline12 not supported");
@@ -59,6 +65,9 @@
     }
 
     public void testAvcBaseline30() throws Exception {
+        if (!supports(AVC_MIME, CodecProfileLevel.AVCProfileBaseline)) {
+            return;
+        }
         if (!supports(AVC_MIME, CodecProfileLevel.AVCProfileBaseline,
                 CodecProfileLevel.AVCLevel3)) {
             Log.i(TAG, "AvcBaseline30 not supported");
@@ -74,6 +83,9 @@
     }
 
     public void testAvcHigh31() throws Exception {
+        if (!supports(AVC_MIME, CodecProfileLevel.AVCProfileHigh)) {
+            return;
+        }
         if (!supports(AVC_MIME, CodecProfileLevel.AVCProfileHigh,
                 CodecProfileLevel.AVCLevel31)) {
             Log.i(TAG, "AvcHigh31 not supported");
@@ -90,6 +102,9 @@
     }
 
     public void testAvcHigh40() throws Exception {
+        if (!supports(AVC_MIME, CodecProfileLevel.AVCProfileHigh)) {
+            return;
+        }
         if (!supports(AVC_MIME, CodecProfileLevel.AVCProfileHigh,
                 CodecProfileLevel.AVCLevel4)) {
             Log.i(TAG, "AvcHigh40 not supported");
@@ -108,7 +123,15 @@
                 + "&key=test_key1", 1920, 1080, PLAY_TIME_MS);
     }
 
+    private boolean supports(String mimeType, int profile) {
+        return supports(mimeType, profile, 0, false);
+    }
+
     private boolean supports(String mimeType, int profile, int level) {
+        return supports(mimeType, profile, level, true);
+    }
+
+    private boolean supports(String mimeType, int profile, int level, boolean testLevel) {
         int numCodecs = MediaCodecList.getCodecCount();
         for (int i = 0; i < numCodecs; i++) {
             MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
@@ -119,7 +142,7 @@
             CodecCapabilities capabilities = codecInfo.getCapabilitiesForType(mimeType);
             for (CodecProfileLevel profileLevel : capabilities.profileLevels) {
                 if (profileLevel.profile == profile
-                        && profileLevel.level >= level) {
+                        && (!testLevel || profileLevel.level >= level)) {
                     return true;
                 }
             }
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecListTest.java b/tests/tests/media/src/android/media/cts/MediaCodecListTest.java
index 9c07cf1..aa56629 100644
--- a/tests/tests/media/src/android/media/cts/MediaCodecListTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaCodecListTest.java
@@ -242,6 +242,7 @@
         list.add(new CodecType("video/3gpp", true));            // h263 encoder
         list.add(new CodecType("video/mp4v-es", false));        // m4v decoder
         list.add(new CodecType("video/x-vnd.on2.vp8", false));  // vp8 decoder
+        list.add(new CodecType("video/x-vnd.on2.vp8", true));   // vp8 encoder
         list.add(new CodecType("video/x-vnd.on2.vp9", false));  // vp9 decoder
 
         return list;
diff --git a/tests/tests/net/src/android/net/cts/VpnServiceTest.java b/tests/tests/net/src/android/net/cts/VpnServiceTest.java
index 9e35375..8bdd7b0 100644
--- a/tests/tests/net/src/android/net/cts/VpnServiceTest.java
+++ b/tests/tests/net/src/android/net/cts/VpnServiceTest.java
@@ -42,7 +42,7 @@
 
         // Should be always resolved by only one activity.
         int count = mContext.getPackageManager().queryIntentActivities(intent, 0).size();
-        assertEquals(count, 1);
+        assertEquals(1, count);
     }
 
     public void testEstablish() throws Exception {
diff --git a/tests/tests/net/src/android/net/wifi/cts/WifiEnterpriseConfigTest.java b/tests/tests/net/src/android/net/wifi/cts/WifiEnterpriseConfigTest.java
index 58298d5..6e395aa 100644
--- a/tests/tests/net/src/android/net/wifi/cts/WifiEnterpriseConfigTest.java
+++ b/tests/tests/net/src/android/net/wifi/cts/WifiEnterpriseConfigTest.java
@@ -17,6 +17,7 @@
 package android.net.wifi.cts;
 
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiEnterpriseConfig;
 import android.net.wifi.WifiEnterpriseConfig.Eap;
@@ -34,6 +35,11 @@
     private static final String ANON_IDENTITY = "anonidentity";
     private static final int ENABLE_DELAY = 10000;
 
+    private boolean hasWifi() {
+        return getContext().getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_WIFI);
+    }
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
@@ -42,10 +48,16 @@
         assertNotNull(mWifiManager);
         mWifiManager.setWifiEnabled(true);
         Thread.sleep(ENABLE_DELAY);
-        assertTrue(mWifiManager.isWifiEnabled());
+        if (hasWifi()) {
+            assertTrue(mWifiManager.isWifiEnabled());
+        }
     }
 
     public void testSettersAndGetters() {
+        if (!hasWifi()) {
+            return;
+        }
+
         WifiEnterpriseConfig config = new WifiEnterpriseConfig();
         assertTrue(config.getEapMethod() == Eap.NONE);
         config.setEapMethod(Eap.PEAP);
@@ -78,6 +90,10 @@
     }
 
     public void testAddEapNetwork() {
+        if (!hasWifi()) {
+            return;
+        }
+
         WifiConfiguration config = new WifiConfiguration();
         WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
         enterpriseConfig.setEapMethod(Eap.PWD);
diff --git a/tests/tests/os/src/android/os/cts/BuildVersionTest.java b/tests/tests/os/src/android/os/cts/BuildVersionTest.java
index ad4ec37..bee12b1 100644
--- a/tests/tests/os/src/android/os/cts/BuildVersionTest.java
+++ b/tests/tests/os/src/android/os/cts/BuildVersionTest.java
@@ -29,8 +29,8 @@
 
     private static final String LOG_TAG = "BuildVersionTest";
     private static final Set<String> EXPECTED_RELEASES =
-        new HashSet<String>(Arrays.asList("4.4", "4.4.1", "4.4.2", "4.4.3"));
-    private static final int EXPECTED_SDK = 19;
+        new HashSet<String>(Arrays.asList("4.4W", "4.4", "4.4.1", "4.4.2", "4.4.3"));
+    private static final int EXPECTED_SDK = 20;
 
     @SuppressWarnings("deprecation")
     public void testReleaseVersion() {
diff --git a/tests/tests/permission/src/android/permission/cts/AppWidgetManagerPermissionTest.java b/tests/tests/permission/src/android/permission/cts/AppWidgetManagerPermissionTest.java
index a290f6a..4223f08 100644
--- a/tests/tests/permission/src/android/permission/cts/AppWidgetManagerPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/AppWidgetManagerPermissionTest.java
@@ -18,6 +18,7 @@
 
 import android.appwidget.AppWidgetManager;
 import android.content.ComponentName;
+import android.content.pm.PackageManager;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 
@@ -44,6 +45,11 @@
      */
     @SmallTest
     public void testBindAppWidget() {
+        if (!getContext().getPackageManager()
+                .hasSystemFeature(PackageManager.FEATURE_APP_WIDGETS)) {
+            return;
+        }
+
         try {
             mAppWidgetManager.bindAppWidgetId(1, new ComponentName(mContext, "foo"));
             fail("Was able to call bindAppWidgetId");
diff --git a/tests/tests/permission/src/android/permission/cts/NoLocationPermissionTest.java b/tests/tests/permission/src/android/permission/cts/NoLocationPermissionTest.java
index da9057e..b5a4f24 100644
--- a/tests/tests/permission/src/android/permission/cts/NoLocationPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/NoLocationPermissionTest.java
@@ -19,6 +19,7 @@
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.location.Location;
 import android.location.LocationListener;
 import android.location.LocationManager;
@@ -39,6 +40,7 @@
 
     private LocationManager mLocationManager;
     private List<String> mAllProviders;
+    private boolean mHasTelephony;
 
     @Override
     protected void setUp() throws Exception {
@@ -46,6 +48,8 @@
         mLocationManager = (LocationManager) getContext().getSystemService(
                 Context.LOCATION_SERVICE);
         mAllProviders = mLocationManager.getAllProviders();
+        mHasTelephony = getContext().getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_TELEPHONY);
 
         assertNotNull(mLocationManager);
         assertNotNull(mAllProviders);
@@ -63,6 +67,10 @@
      */
     @SmallTest
     public void testListenCellLocation() {
+        if (!mHasTelephony) {
+            return;
+        }
+
         TelephonyManager telephonyManager = (TelephonyManager) getContext().getSystemService(
                 Context.TELEPHONY_SERVICE);
         PhoneStateListener phoneStateListener = new PhoneStateListener();
@@ -90,6 +98,10 @@
      */
     @SmallTest
     public void testListenCellLocation2() {
+        if (!mHasTelephony) {
+            return;
+        }
+
         TelephonyManager telephonyManager = (TelephonyManager) getContext().getSystemService(
                 Context.TELEPHONY_SERVICE);
         PhoneStateListener phoneStateListener = new PhoneStateListener();
diff --git a/tests/tests/permission/src/android/permission/cts/NoSystemFunctionPermissionTest.java b/tests/tests/permission/src/android/permission/cts/NoSystemFunctionPermissionTest.java
index 17f916a..9eec0ac 100644
--- a/tests/tests/permission/src/android/permission/cts/NoSystemFunctionPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/NoSystemFunctionPermissionTest.java
@@ -20,6 +20,7 @@
 import android.app.ActivityManager;
 import android.app.AlarmManager;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.graphics.Bitmap;
 import android.os.Vibrator;
 import android.telephony.gsm.SmsManager;
@@ -146,6 +147,10 @@
      */
     @SmallTest
     public void testSendSms() {
+        if (!getContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+            return;
+        }
+
         SmsManager smsManager = SmsManager.getDefault();
         byte[] testData = new byte[10];
         try {
diff --git a/tests/tests/permission/src/android/permission/cts/TelephonyManagerPermissionTest.java b/tests/tests/permission/src/android/permission/cts/TelephonyManagerPermissionTest.java
index 4c116dd..2681c0f 100644
--- a/tests/tests/permission/src/android/permission/cts/TelephonyManagerPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/TelephonyManagerPermissionTest.java
@@ -17,6 +17,7 @@
 package android.permission.cts;
 
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.telephony.TelephonyManager;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
@@ -26,11 +27,14 @@
  */
 public class TelephonyManagerPermissionTest extends AndroidTestCase {
 
+    private boolean mHasTelephony;
     TelephonyManager mTelephonyManager = null;
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
+        mHasTelephony = getContext().getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_TELEPHONY);
         mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
         assertNotNull(mTelephonyManager);
     }
@@ -43,6 +47,10 @@
      */
     @SmallTest
     public void testGetDeviceId() {
+        if (!mHasTelephony) {
+            return;
+        }
+
         try {
             String id = mTelephonyManager.getDeviceId();
             fail("Got device ID: " + id);
@@ -59,6 +67,10 @@
      */
     @SmallTest
     public void testGetLine1Number() {
+        if (!mHasTelephony) {
+            return;
+        }
+
         try {
             String nmbr = mTelephonyManager.getLine1Number();
             fail("Got line 1 number: " + nmbr);
@@ -75,6 +87,10 @@
      */
     @SmallTest
     public void testGetSimSerialNumber() {
+        if (!mHasTelephony) {
+            return;
+        }
+
         try {
             String nmbr = mTelephonyManager.getSimSerialNumber();
             fail("Got SIM serial number: " + nmbr);
@@ -91,6 +107,10 @@
      */
     @SmallTest
     public void testGetSubscriberId() {
+        if (!mHasTelephony) {
+            return;
+        }
+
         try {
             String sid = mTelephonyManager.getSubscriberId();
             fail("Got subscriber id: " + sid);
@@ -107,6 +127,10 @@
      */
     @SmallTest
     public void testVoiceMailNumber() {
+        if (!mHasTelephony) {
+            return;
+        }
+
         try {
             String vmnum = mTelephonyManager.getVoiceMailNumber();
             fail("Got voicemail number: " + vmnum);
diff --git a/tests/tests/permission2/src/android/permission2/cts/NoProcessOutgoingCallPermissionTest.java b/tests/tests/permission2/src/android/permission2/cts/NoProcessOutgoingCallPermissionTest.java
index 4a124e7..956f1a6 100644
--- a/tests/tests/permission2/src/android/permission2/cts/NoProcessOutgoingCallPermissionTest.java
+++ b/tests/tests/permission2/src/android/permission2/cts/NoProcessOutgoingCallPermissionTest.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.PackageManager;
 import android.net.Uri;
 import android.os.Bundle;
 import android.test.AndroidTestCase;
@@ -51,6 +52,12 @@
      */
     // TODO: add back to LargeTest when test can cancel initiated call
     public void testProcessOutgoingCall() {
+        final PackageManager pm = getContext().getPackageManager();
+        if (!pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY) ||
+                !pm.hasSystemFeature(PackageManager.FEATURE_SIP_VOIP)) {
+            return;
+        }
+
         Log.i(LOG_TAG, "Beginning testProcessOutgoingCall");
         OutgoingCallBroadcastReceiver rcvr = new OutgoingCallBroadcastReceiver();
         Intent ntnt = mContext.registerReceiver(rcvr,
diff --git a/tests/tests/print/src/android/print/cts/BasePrintTest.java b/tests/tests/print/src/android/print/cts/BasePrintTest.java
index d193bb0..d0bfc97 100644
--- a/tests/tests/print/src/android/print/cts/BasePrintTest.java
+++ b/tests/tests/print/src/android/print/cts/BasePrintTest.java
@@ -75,6 +75,7 @@
 
     private Locale mOldLocale;
 
+    private CallCounter mCancelOperationCounter;
     private CallCounter mLayoutCallCounter;
     private CallCounter mWriteCallCounter;
     private CallCounter mFinishCallCounter;
@@ -103,6 +104,7 @@
         }
 
         // Initialize the latches.
+        mCancelOperationCounter = new CallCounter();
         mLayoutCallCounter = new CallCounter();
         mFinishCallCounter = new CallCounter();
         mWriteCallCounter = new CallCounter();
@@ -145,6 +147,10 @@
         });
     }
 
+    protected void onCancelOperationCalled() {
+        mCancelOperationCounter.call();
+    }
+
     protected void onLayoutCalled() {
         mLayoutCallCounter.call();
     }
@@ -165,6 +171,11 @@
         mDestroySessionCallCounter.call();
     }
 
+    protected void waitForCancelOperationCallbackCalled() {
+        waitForCallbackCallCount(mCancelOperationCounter, 1,
+                "Did not get expected call to onCancel for the current operation.");
+    }
+
     protected void waitForPrinterDiscoverySessionDestroyCallbackCalled() {
         waitForCallbackCallCount(mDestroySessionCallCounter, 1,
                 "Did not get expected call to onDestroyPrinterDiscoverySession.");
@@ -185,7 +196,7 @@
                 "Did not get expected call to layout.");
     }
 
-    protected void waitForWriteForAdapterCallback() {
+    protected void waitForWriteAdapterCallback() {
         waitForCallbackCallCount(mWriteCallCounter, 1, "Did not get expected call to write.");
     }
 
@@ -245,6 +256,12 @@
                 PrintDocumentActivity.class, null);
     }
 
+    protected void openPrintOptions() throws UiObjectNotFoundException {
+        UiObject expandHandle = new UiObject(new UiSelector().resourceId(
+                "com.android.printspooler:id/expand_collapse_handle"));
+        expandHandle.click();
+    }
+
     protected void clearPrintSpoolerData() throws Exception {
         IPrivilegedOperations privilegedOps = IPrivilegedOperations.Stub.asInterface(
                 getParams().getBinder(ARG_PRIVILEGED_OPS));
@@ -358,20 +375,21 @@
         public void call() {
             synchronized (mLock) {
                 mCallCount++;
+                mLock.notifyAll();
             }
         }
 
-        public void waitForCount(int count, long timeoutMIllis) throws TimeoutException {
+        public void waitForCount(int count, long timeoutMillis) throws TimeoutException {
             synchronized (mLock) {
                 final long startTimeMillis = SystemClock.uptimeMillis();
                 while (mCallCount < count) {
                     try {
                         final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis;
-                        final long remainingTimeMillis = timeoutMIllis - elapsedTimeMillis;
+                        final long remainingTimeMillis = timeoutMillis - elapsedTimeMillis;
                         if (remainingTimeMillis <= 0) {
                             throw new TimeoutException();
                         }
-                        mLock.wait(timeoutMIllis);
+                        mLock.wait(timeoutMillis);
                     } catch (InterruptedException ie) {
                         /* ignore */
                     }
diff --git a/tests/tests/print/src/android/print/cts/PageRangeAdjustmentTest.java b/tests/tests/print/src/android/print/cts/PageRangeAdjustmentTest.java
index 6b1bb3f..9e41c89 100644
--- a/tests/tests/print/src/android/print/cts/PageRangeAdjustmentTest.java
+++ b/tests/tests/print/src/android/print/cts/PageRangeAdjustmentTest.java
@@ -30,6 +30,7 @@
 import android.print.PrintDocumentAdapter.LayoutResultCallback;
 import android.print.PrintDocumentAdapter.WriteResultCallback;
 import android.print.PrintDocumentInfo;
+import android.print.PrintJobInfo;
 import android.print.PrinterCapabilitiesInfo;
 import android.print.PrinterId;
 import android.print.PrinterInfo;
@@ -74,7 +75,7 @@
             public Void answer(InvocationOnMock invocation) {
                 PrintJob printJob = (PrintJob) invocation.getArguments()[0];
                 PageRange[] pages = printJob.getInfo().getPages();
-                assert(pages.length == 1 && PageRange.ALL_PAGES.equals(pages[0]));
+                assertTrue(pages.length == 1 && PageRange.ALL_PAGES.equals(pages[0]));
                 printJob.complete();
                 onPrintJobQueuedCalled();
                 return null;
@@ -126,7 +127,7 @@
         print(adapter);
 
         // Wait for write.
-        waitForWriteForAdapterCallback();
+        waitForWriteAdapterCallback();
 
         // Select the first printer.
         selectPrinter(FIRST_PRINTER);
@@ -223,7 +224,10 @@
         print(adapter);
 
         // Wait for write.
-        waitForWriteForAdapterCallback();
+        waitForWriteAdapterCallback();
+
+        // Open the print options.
+        openPrintOptions();
 
         // Select the first printer.
         selectPrinter(FIRST_PRINTER);
@@ -268,9 +272,14 @@
             @Override
             public Void answer(InvocationOnMock invocation) {
                 PrintJob printJob = (PrintJob) invocation.getArguments()[0];
-                PageRange[] pages = printJob.getInfo().getPages();
-                assert(pages.length == 1 && pages[0].getStart() == 1
-                        && pages[0].getEnd() == 2);
+                PrintJobInfo printJobInfo = printJob.getInfo();
+                PageRange[] pages = printJobInfo.getPages();
+                // We asked only for page 3 (index 2) but got 4 and 3 (indices
+                // 2, 3), hence the written document has two pages (3 and 4)
+                // and the first one, i.e. 3 should be printed.
+                assertTrue(pages.length == 1 && pages[0].getStart() == 0
+                        && pages[0].getEnd() == 0);
+                assertSame(printJob.getDocument().getInfo().getPageCount(), 2);
                 printJob.complete();
                 onPrintJobQueuedCalled();
                 return null;
@@ -308,9 +317,9 @@
                 assertSame(pages.length, 1);
                 fd.close();
 
-                PageRange reqeustedPages = pages[0];
-                if (reqeustedPages.getStart() == reqeustedPages.getEnd()
-                        && reqeustedPages.getEnd() == 0) {
+                PageRange requestedPages = pages[0];
+                if (requestedPages.getStart() == requestedPages.getEnd()
+                        && requestedPages.getEnd() == 0) {
                     // If asked for the first page, which is for preview
                     // then write it...
                     callback.onWriteFinished(pages);
@@ -335,7 +344,10 @@
         print(adapter);
 
         // Wait for write.
-        waitForWriteForAdapterCallback();
+        waitForWriteAdapterCallback();
+
+        // Open the print options.
+        openPrintOptions();
 
         // Select the first printer.
         selectPrinter(FIRST_PRINTER);
@@ -431,7 +443,7 @@
         print(adapter);
 
         // Wait for write.
-        waitForWriteForAdapterCallback();
+        waitForWriteAdapterCallback();
 
         // Cancel printing.
         getUiDevice().pressBack(); // wakes up the device.
@@ -476,7 +488,7 @@
                 PrintService service = session.getService();
 
                 if (session.getPrinters().isEmpty()) {
-                          List<PrinterInfo> printers = new ArrayList<PrinterInfo>();
+                          List<PrinterInfo> printers = new ArrayList<>();
 
                     // Add one printer.
                     PrinterId firstPrinterId = service.generatePrinterId("first_printer");
diff --git a/tests/tests/print/src/android/print/cts/PrintDocumentAdapterContractTest.java b/tests/tests/print/src/android/print/cts/PrintDocumentAdapterContractTest.java
index d445692..a7c7d33 100644
--- a/tests/tests/print/src/android/print/cts/PrintDocumentAdapterContractTest.java
+++ b/tests/tests/print/src/android/print/cts/PrintDocumentAdapterContractTest.java
@@ -70,7 +70,7 @@
             public Void answer(InvocationOnMock invocation) throws Throwable {
                 LayoutResultCallback callback = (LayoutResultCallback) invocation.getArguments()[3];
                 PrintDocumentInfo info = new PrintDocumentInfo.Builder(PRINT_JOB_NAME)
-                        .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT).setPageCount(1)
+                        .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT).setPageCount(2)
                         .build();
                 callback.onLayoutFinished(info, false);
                 // Mark layout was called.
@@ -103,7 +103,7 @@
         print(adapter);
 
         // Wait for write.
-        waitForWriteForAdapterCallback();
+        waitForWriteAdapterCallback();
 
         // Select the second printer.
         selectPrinter("Second printer");
@@ -212,7 +212,7 @@
         print(adapter);
 
         // Wait for write.
-        waitForWriteForAdapterCallback();
+        waitForWriteAdapterCallback();
 
         // Cancel the printing.
         getUiDevice().pressBack(); // wakes up the device.
@@ -297,7 +297,10 @@
         print(adapter);
 
         // Wait for write.
-        waitForWriteForAdapterCallback();
+        waitForWriteAdapterCallback();
+
+        // Open the print options.
+        openPrintOptions();
 
         // Select the second printer.
         selectPrinter("Second printer");
@@ -462,7 +465,10 @@
         print(adapter);
 
         // Wait for write.
-        waitForWriteForAdapterCallback();
+        waitForWriteAdapterCallback();
+
+        // Open the print options.
+        openPrintOptions();
 
         // Select the second printer.
         selectPrinter("Second printer");
@@ -608,7 +614,10 @@
         print(adapter);
 
         // Wait for write.
-        waitForWriteForAdapterCallback();
+        waitForWriteAdapterCallback();
+
+        // Open the print options.
+        openPrintOptions();
 
         // Select the second printer.
         selectPrinter("Second printer");
@@ -681,44 +690,47 @@
 
         // Create a mock print adapter.
         final PrintDocumentAdapter adapter = createMockPrintDocumentAdapter(
-            new Answer<Void>() {
-            @Override
-            public Void answer(InvocationOnMock invocation) throws Throwable {
-                LayoutResultCallback callback = (LayoutResultCallback) invocation.getArguments()[3];
-                PrintDocumentInfo info = new PrintDocumentInfo.Builder(PRINT_JOB_NAME)
-                        .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT).setPageCount(1)
-                        .build();
-                // The content changes after every layout.
-                callback.onLayoutFinished(info, false);
-                return null;
-            }
-        }, new Answer<Void>() {
-            @Override
-            public Void answer(InvocationOnMock invocation) throws Throwable {
-                Object[] args = invocation.getArguments();
-                PageRange[] pages = (PageRange[]) args[0];
-                ParcelFileDescriptor fd = (ParcelFileDescriptor) args[1];
-                WriteResultCallback callback = (WriteResultCallback) args[3];
-                fd.close();
-                callback.onWriteFinished(pages);
-                // Mark write was called.
-                onWriteCalled();
-                return null;
-            }
-        }, new Answer<Void>() {
-            @Override
-            public Void answer(InvocationOnMock invocation) throws Throwable {
-                // Mark finish was called.
-                onFinishCalled();
-                return null;
-            }
-        });
+                new Answer<Void>() {
+                    @Override
+                    public Void answer(InvocationOnMock invocation) throws Throwable {
+                        LayoutResultCallback callback = (LayoutResultCallback) invocation.getArguments()[3];
+                        PrintDocumentInfo info = new PrintDocumentInfo.Builder(PRINT_JOB_NAME)
+                                .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT).setPageCount(1)
+                                .build();
+                        // The content changes after every layout.
+                        callback.onLayoutFinished(info, true);
+                        return null;
+                    }
+                }, new Answer<Void>() {
+                    @Override
+                    public Void answer(InvocationOnMock invocation) throws Throwable {
+                        Object[] args = invocation.getArguments();
+                        PageRange[] pages = (PageRange[]) args[0];
+                        ParcelFileDescriptor fd = (ParcelFileDescriptor) args[1];
+                        WriteResultCallback callback = (WriteResultCallback) args[3];
+                        fd.close();
+                        callback.onWriteFinished(pages);
+                        // Mark write was called.
+                        onWriteCalled();
+                        return null;
+                    }
+                }, new Answer<Void>() {
+                    @Override
+                    public Void answer(InvocationOnMock invocation) throws Throwable {
+                        // Mark finish was called.
+                        onFinishCalled();
+                        return null;
+                    }
+                });
 
         // Start printing.
         print(adapter);
 
         // Wait for write.
-        waitForWriteForAdapterCallback();
+        waitForWriteAdapterCallback();
+
+        // Open the print options.
+        openPrintOptions();
 
         // Select the third printer.
         selectPrinter("Third printer");
@@ -809,7 +821,10 @@
         print(adapter);
 
         // Wait for write.
-        waitForWriteForAdapterCallback();
+        waitForWriteAdapterCallback();
+
+        // Open the print options.
+        openPrintOptions();
 
         // Select the second printer.
         selectPrinter("Second printer");
@@ -890,6 +905,7 @@
                 cancellation.setOnCancelListener(new OnCancelListener() {
                     @Override
                     public void onCancel() {
+                        onCancelOperationCalled();
                         callback.onLayoutCancelled();
                     }
                 });
@@ -915,6 +931,9 @@
         getUiDevice().pressBack(); // wakes up the device.
         getUiDevice().pressBack();
 
+        // Wait for the cancellation request.
+        waitForCancelOperationCallbackCalled();
+
         // Wait for a finish.
         waitForAdapterFinishCallbackCalled();
 
@@ -973,6 +992,7 @@
                         } catch (IOException ioe) {
                             /* ignore */
                         }
+                        onCancelOperationCalled();
                         callback.onWriteCancelled();
                     }
                 });
@@ -993,12 +1013,15 @@
         print(adapter);
 
         // Wait for write.
-        waitForWriteForAdapterCallback();
+        waitForWriteAdapterCallback();
 
         // Cancel printing.
         getUiDevice().pressBack(); // wakes up the device.
         getUiDevice().pressBack();
 
+        // Wait for the cancellation request.
+        waitForCancelOperationCallbackCalled();
+
         // Wait for a finish.
         waitForAdapterFinishCallbackCalled();
 
@@ -1135,7 +1158,7 @@
         print(adapter);
 
         // Wait for write.
-        waitForWriteForAdapterCallback();
+        waitForWriteAdapterCallback();
 
         // Cancel printing.
         getUiDevice().pressBack(); // wakes up the device.
@@ -1216,7 +1239,7 @@
         print(adapter);
 
         // Wait for write.
-        waitForWriteForAdapterCallback();
+        waitForWriteAdapterCallback();
 
         // Cancel printing.
         getUiDevice().pressBack(); // wakes up the device.
@@ -1354,7 +1377,7 @@
         print(adapter);
 
         // Wait for write.
-        waitForWriteForAdapterCallback();
+        waitForWriteAdapterCallback();
 
         // Cancel printing.
         getUiDevice().pressBack(); // wakes up the device.
diff --git a/tests/tests/print/src/android/print/cts/PrinterDiscoverySessionLifecycleTest.java b/tests/tests/print/src/android/print/cts/PrinterDiscoverySessionLifecycleTest.java
index b9ea280..1eba5e6 100644
--- a/tests/tests/print/src/android/print/cts/PrinterDiscoverySessionLifecycleTest.java
+++ b/tests/tests/print/src/android/print/cts/PrinterDiscoverySessionLifecycleTest.java
@@ -92,7 +92,7 @@
         print(adapter);
 
         // Wait for write of the first page.
-        waitForWriteForAdapterCallback();
+        waitForWriteAdapterCallback();
 
         // Select the first printer.
         selectPrinter(FIRST_PRINTER_NAME);
@@ -186,7 +186,7 @@
         print(adapter);
 
         // Wait for write of the first page.
-        waitForWriteForAdapterCallback();
+        waitForWriteAdapterCallback();
 
         // Select the first printer.
         selectPrinter(FIRST_PRINTER_NAME);
@@ -222,15 +222,14 @@
         getUiDevice().pressBack(); // wakes up the device.
         getUiDevice().pressBack();
 
-        // Wait for all print jobs to be handled after which the session destroyed.
+        // Wait for all print jobs to be handled after which the is session destroyed.
         waitForPrinterDiscoverySessionDestroyCallbackCalled();
 
         // Verify the expected calls.
         InOrder inOrder = inOrder(firstSessionCallbacks);
 
-        // We start discovery as the print dialog was up.
+        // We start discovery with no printer history.
         List<PrinterId> priorityList = new ArrayList<PrinterId>();
-        priorityList.add(firstPrinterId);
         inOrder.verify(firstSessionCallbacks).onStartPrinterDiscovery(
                 priorityList);
 
@@ -238,11 +237,28 @@
         inOrder.verify(firstSessionCallbacks).onStartPrinterStateTracking(
                 firstPrinterId);
 
-        // We selected the second printer so the first should not be tracked.
+        // We confirmed print so the first should not be tracked.
         inOrder.verify(firstSessionCallbacks).onStopPrinterStateTracking(
                 firstPrinterId);
 
-        // ...next we stop printer discovery...
+        // We print again which brings the print activity up but the old
+        // print activity is not destroyed yet (just fine) which is the
+        // printer discovery session is not destroyed and the second print
+        // will join the ongoing session. Hence, instead of start printer
+        // discovery we are getting a printer validation request.
+        priorityList.add(firstPrinterId);
+        inOrder.verify(firstSessionCallbacks).onValidatePrinters(priorityList);
+
+        // The system selects the highest ranked historical printer.
+        inOrder.verify(firstSessionCallbacks).onStartPrinterStateTracking(
+                firstPrinterId);
+
+        // We canceled print so the first should not be tracked.
+        inOrder.verify(firstSessionCallbacks).onStopPrinterStateTracking(
+                firstPrinterId);
+
+
+        // Discovery is always stopped before the session is always destroyed.
         inOrder.verify(firstSessionCallbacks).onStopPrinterDiscovery();
 
         // ...last the session is destroyed.
diff --git a/tests/tests/provider/src/android/provider/cts/Contacts_PeopleTest.java b/tests/tests/provider/src/android/provider/cts/Contacts_PeopleTest.java
index d634d30..e5085b8 100644
--- a/tests/tests/provider/src/android/provider/cts/Contacts_PeopleTest.java
+++ b/tests/tests/provider/src/android/provider/cts/Contacts_PeopleTest.java
@@ -28,10 +28,12 @@
 import android.net.Uri;
 import android.os.RemoteException;
 import android.provider.Contacts;
+import android.provider.Contacts.GroupMembership;
 import android.provider.Contacts.Groups;
 import android.provider.Contacts.GroupsColumns;
 import android.provider.Contacts.People;
 import android.test.InstrumentationTestCase;
+import android.util.Log;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -53,9 +55,6 @@
     private static final int PEOPLE_ID_INDEX = 0;
     private static final int PEOPLE_LAST_CONTACTED_INDEX = 1;
 
-    private static final int MEMBERSHIP_PERSON_ID_INDEX = 1;
-    private static final int MEMBERSHIP_GROUP_ID_INDEX = 5;
-
     private static final String[] GROUPS_PROJECTION = new String[] {
         Groups._ID,
         Groups.NAME
@@ -127,13 +126,19 @@
             mRowsAdded.add(People.addToMyContactsGroup(mContentResolver, personId));
             cursor = mProvider.query(Groups.CONTENT_URI, GROUPS_PROJECTION,
                     Groups.SYSTEM_ID + "='" + Groups.GROUP_MY_CONTACTS + "'", null, null, null);
-            cursor.moveToFirst();
+            assertTrue(cursor.moveToFirst());
             int groupId = cursor.getInt(GROUPS_ID_INDEX);
             cursor.close();
             cursor = People.queryGroups(mContentResolver, personId);
-            cursor.moveToFirst();
-            assertEquals(personId, cursor.getInt(MEMBERSHIP_PERSON_ID_INDEX));
-            assertEquals(groupId, cursor.getInt(MEMBERSHIP_GROUP_ID_INDEX));
+
+            int membershipGroupIdIndex =
+                    cursor.getColumnIndex(android.provider.Contacts.GroupMembership.GROUP_ID);
+            int membershipPersonIdIndex =
+                    cursor.getColumnIndex(android.provider.Contacts.GroupMembership.PERSON_ID);
+
+            assertTrue(cursor.moveToFirst());
+            assertEquals(personId, cursor.getInt(membershipPersonIdIndex));
+            assertEquals(groupId, cursor.getInt(membershipGroupIdIndex));
             cursor.close();
 
             // People: test_people_create, Group: Groups.GROUP_MY_CONTACTS
@@ -145,38 +150,38 @@
             cursor = mProvider.query(People.CONTENT_URI, PEOPLE_PROJECTION,
                     People.NAME + " = 'test_people_create'", null, null, null);
 
-            cursor.moveToFirst();
+            assertTrue(cursor.moveToFirst());
             personId = cursor.getInt(PEOPLE_ID_INDEX);
             mRowsAdded.add(ContentUris.withAppendedId(People.CONTENT_URI, personId));
             cursor.close();
             cursor = mProvider.query(Groups.CONTENT_URI, GROUPS_PROJECTION,
                     Groups.SYSTEM_ID + "='" + Groups.GROUP_MY_CONTACTS + "'", null, null, null);
-            cursor.moveToFirst();
+            assertTrue(cursor.moveToFirst());
             groupId = cursor.getInt(GROUPS_ID_INDEX);
             cursor.close();
             cursor = People.queryGroups(mContentResolver, personId);
-            cursor.moveToFirst();
-            assertEquals(personId, cursor.getInt(MEMBERSHIP_PERSON_ID_INDEX));
-            assertEquals(groupId, cursor.getInt(MEMBERSHIP_GROUP_ID_INDEX));
+            assertTrue(cursor.moveToFirst());
+            assertEquals(personId, cursor.getInt(membershipPersonIdIndex));
+            assertEquals(groupId, cursor.getInt(membershipGroupIdIndex));
             cursor.close();
 
             // People: test_people_1, Group: test_group_0
             cursor = mProvider.query(mPeopleRowsAdded.get(1), PEOPLE_PROJECTION,
                     null, null, null, null);
-            cursor.moveToFirst();
+            assertTrue(cursor.moveToFirst());
             personId = cursor.getInt(PEOPLE_ID_INDEX);
             cursor.close();
             cursor = mProvider.query(mGroupRowsAdded.get(0), GROUPS_PROJECTION,
                     null, null, null, null);
-            cursor.moveToFirst();
+            assertTrue(cursor.moveToFirst());
             groupId = cursor.getInt(GROUPS_ID_INDEX);
             cursor.close();
             mRowsAdded.add(People.addToGroup(mContentResolver, personId, groupId));
             cursor = People.queryGroups(mContentResolver, personId);
             boolean found = false;
             while (cursor.moveToNext()) {
-                assertEquals(personId, cursor.getInt(MEMBERSHIP_PERSON_ID_INDEX));
-                if (cursor.getInt(MEMBERSHIP_GROUP_ID_INDEX) == groupId) {
+                assertEquals(personId, cursor.getInt(membershipPersonIdIndex));
+                if (cursor.getInt(membershipGroupIdIndex) == groupId) {
                     found = true;
                     break;
                 }
@@ -188,7 +193,7 @@
             // People: test_people_2, Group: test_group_1
             cursor = mProvider.query(mPeopleRowsAdded.get(2), PEOPLE_PROJECTION,
                     null, null, null, null);
-            cursor.moveToFirst();
+            assertTrue(cursor.moveToFirst());
             personId = cursor.getInt(PEOPLE_ID_INDEX);
             cursor.close();
             String groupName = "test_group_1";
@@ -196,8 +201,8 @@
             cursor = People.queryGroups(mContentResolver, personId);
             List<Integer> groupIds = new ArrayList<Integer>();
             while (cursor.moveToNext()) {
-                assertEquals(personId, cursor.getInt(MEMBERSHIP_PERSON_ID_INDEX));
-                groupIds.add(cursor.getInt(MEMBERSHIP_GROUP_ID_INDEX));
+                assertEquals(personId, cursor.getInt(membershipPersonIdIndex));
+                groupIds.add(cursor.getInt(membershipGroupIdIndex));
             }
             cursor.close();
 
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStore_Video_ThumbnailsTest.java b/tests/tests/provider/src/android/provider/cts/MediaStore_Video_ThumbnailsTest.java
index 287551c..ac0bc03 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStore_Video_ThumbnailsTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStore_Video_ThumbnailsTest.java
@@ -22,22 +22,49 @@
 import android.content.ContentUris;
 import android.content.ContentValues;
 import android.database.Cursor;
+import android.media.MediaCodecInfo;
+import android.media.MediaCodecList;
 import android.net.Uri;
 import android.os.Environment;
 import android.provider.MediaStore.Video.Media;
 import android.provider.MediaStore.Video.Thumbnails;
 import android.provider.MediaStore.Video.VideoColumns;
 import android.test.AndroidTestCase;
+import android.util.Log;
 
 import java.io.File;
 import java.io.IOException;
 
 public class MediaStore_Video_ThumbnailsTest extends AndroidTestCase {
+    private static final String TAG = "MediaStore_Video_ThumbnailsTest";
+    private static final String MIME_TYPE = "video/3gpp";
 
     private ContentResolver mResolver;
 
     private FileCopyHelper mFileHelper;
 
+    // TODO: Make a public method selectCodec() in common libraries (e.g. cts/libs/), to avoid
+    // redundant function definitions in this and other media related test files.
+    private static boolean hasCodec(String mimeType) {
+        int numCodecs = MediaCodecList.getCodecCount();
+
+        for (int i = 0; i < numCodecs; i++) {
+            MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
+
+            if (!codecInfo.isEncoder()) {
+                continue;
+            }
+
+            String[] types = codecInfo.getSupportedTypes();
+            for (int j = 0; j < types.length; j++) {
+                if (types[j].equalsIgnoreCase(mimeType)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
@@ -69,6 +96,14 @@
         // Get the current thumbnail count for future comparison.
         int count = getThumbnailCount(Thumbnails.EXTERNAL_CONTENT_URI);
 
+        // Don't run the test if the codec isn't supported.
+        if (!hasCodec(MIME_TYPE)) {
+            // Calling getThumbnail should not generate a new thumbnail.
+            assertNull(Thumbnails.getThumbnail(mResolver, videoId, Thumbnails.MINI_KIND, null));
+            Log.w(TAG, "Codec " + MIME_TYPE + " not supported. Return from testGetThumbnail.");
+            return;
+        }
+
         // Calling getThumbnail should generate a new thumbnail.
         assertNotNull(Thumbnails.getThumbnail(mResolver, videoId, Thumbnails.MINI_KIND, null));
         assertNotNull(Thumbnails.getThumbnail(mResolver, videoId, Thumbnails.MICRO_KIND, null));
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/AtomicTest.java b/tests/tests/renderscript/src/android/renderscript/cts/AtomicTest.java
new file mode 100644
index 0000000..a0e3b7a
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/AtomicTest.java
@@ -0,0 +1,391 @@
+/*
+ * Copyright (C) 2014 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.renderscript.cts;
+import java.util.Random;
+import android.renderscript.*;
+
+public class AtomicTest extends RSBaseCompute {
+    int[] mSrcData;
+    int[] mReturnData = new int[1];
+    int[] mRefData = new int[1];
+    ScriptC_AtomicTest mScript;
+    Allocation mSrc;
+    Allocation mReturn;
+
+    private void initS(boolean fillData, int sz) {
+        mSrcData = new int[sz * sz];
+        mScript = new ScriptC_AtomicTest(mRS);
+        mSrc = Allocation.createTyped(mRS, Type.createXY(mRS, Element.I32(mRS), sz, sz));
+        mReturn = Allocation.createSized(mRS, Element.I32(mRS), 1);
+        if (fillData) {
+            RSUtils.genRandomInts(0, mSrcData, true, 32);
+            mSrc.copyFrom(mSrcData);
+        }
+    }
+
+    private void initU(boolean fillData, int sz) {
+        mSrcData = new int[sz * sz];
+        mScript = new ScriptC_AtomicTest(mRS);
+        mSrc = Allocation.createTyped(mRS, Type.createXY(mRS, Element.U32(mRS), sz, sz));
+        mReturn = Allocation.createSized(mRS, Element.U32(mRS), 1);
+        if (fillData) {
+            RSUtils.genRandomInts(0, mSrcData, false, 32);
+            mSrc.copyFrom(mSrcData);
+        }
+    }
+
+    public void testCas() {
+        initS(true, 1024);
+        mScript.set_gISum(10);
+        mScript.forEach_test_Cas(mSrc);
+        mScript.invoke_getValueS(mReturn);
+        mReturn.copyTo(mReturnData);
+        assertEquals("Incorrect value for Cas ", (10 + 1024*1024), mReturnData[0]);
+    }
+
+    public void testUCas() {
+        initU(true, 1024);
+        mScript.set_gUSum(10);
+        mScript.forEach_test_uCas(mSrc);
+        mScript.invoke_getValueU(mReturn);
+        mReturn.copyTo(mReturnData);
+        assertEquals("Incorrect value for UCas ", (10 + 1024*1024), mReturnData[0]);
+    }
+
+    public void testInc() {
+        initS(true, 1024);
+        mScript.set_gISum(10);
+        mScript.forEach_test_Inc(mSrc);
+        mScript.invoke_getValueS(mReturn);
+        mReturn.copyTo(mReturnData);
+        assertEquals("Incorrect value for Inc ", (10 + 1024*1024), mReturnData[0]);
+    }
+
+    public void testUInc() {
+        initU(true, 1024);
+        mScript.set_gUSum(10);
+        mScript.forEach_test_uInc(mSrc);
+        mScript.invoke_getValueU(mReturn);
+        mReturn.copyTo(mReturnData);
+        assertEquals("Incorrect value for UInc ", (10 + 1024*1024), mReturnData[0]);
+    }
+
+    public void testDec() {
+        initS(true, 1024);
+        mScript.set_gISum(10 + 1024*1024);
+        mScript.forEach_test_Dec(mSrc);
+        mScript.invoke_getValueS(mReturn);
+        mReturn.copyTo(mReturnData);
+        assertEquals("Incorrect value for Dec ", 10, mReturnData[0]);
+    }
+
+    public void testUDec() {
+        initU(true, 1024);
+        mScript.set_gUSum(10 + 1024*1024);
+        mScript.forEach_test_uDec(mSrc);
+        mScript.invoke_getValueU(mReturn);
+        mReturn.copyTo(mReturnData);
+        assertEquals("Incorrect value for UDec ", 10, mReturnData[0]);
+    }
+
+
+    public void testAdd() {
+        initS(true, 1024);
+        mScript.set_gISum(10);
+        mScript.forEach_test_Add(mSrc);
+        mScript.invoke_getValueS(mReturn);
+        mReturn.copyTo(mReturnData);
+
+        int sExpected = 10;
+        for (int i=0; i < mSrcData.length; i++) {
+            sExpected += mSrcData[i];
+        }
+        assertEquals("Incorrect value for Add ", sExpected, mReturnData[0]);
+    }
+
+    public void testUAdd() {
+        initU(true, 1024);
+        mScript.set_gUSum(10);
+        mScript.forEach_test_uAdd(mSrc);
+        mScript.invoke_getValueU(mReturn);
+        mReturn.copyTo(mReturnData);
+
+        int sExpected = 10;
+        for (int i=0; i < mSrcData.length; i++) {
+            sExpected += mSrcData[i];
+        }
+        assertEquals("Incorrect value for UAdd ", sExpected, mReturnData[0]);
+    }
+
+    public void testSub() {
+        initS(true, 1024);
+        mScript.set_gISum(10);
+        mScript.forEach_test_Sub(mSrc);
+        mScript.invoke_getValueS(mReturn);
+        mReturn.copyTo(mReturnData);
+
+        int sExpected = 10;
+        for (int i=0; i < mSrcData.length; i++) {
+            sExpected -= mSrcData[i];
+        }
+        assertEquals("Incorrect value for Sub ", sExpected, mReturnData[0]);
+    }
+
+    public void testUSub() {
+        initU(true, 1024);
+        mScript.set_gUSum(10);
+        mScript.forEach_test_uSub(mSrc);
+        mScript.invoke_getValueU(mReturn);
+        mReturn.copyTo(mReturnData);
+
+        int sExpected = 10;
+        for (int i=0; i < mSrcData.length; i++) {
+            sExpected -= mSrcData[i];
+        }
+        assertEquals("Incorrect value for USub ", sExpected, mReturnData[0]);
+    }
+
+    public void testXor() {
+        initS(true, 1024);
+        mScript.set_gISum(10);
+        mScript.forEach_test_Xor(mSrc);
+        mScript.invoke_getValueS(mReturn);
+        mReturn.copyTo(mReturnData);
+
+        int sExpected = 10;
+        for (int i=0; i < mSrcData.length; i++) {
+            sExpected ^= mSrcData[i];
+        }
+        assertEquals("Incorrect value for Xor ", sExpected, mReturnData[0]);
+    }
+
+    public void testUXor() {
+        initU(true, 1024);
+        mScript.set_gUSum(10);
+        mScript.forEach_test_uXor(mSrc);
+        mScript.invoke_getValueU(mReturn);
+        mReturn.copyTo(mReturnData);
+
+        int sExpected = 10;
+        for (int i=0; i < mSrcData.length; i++) {
+            sExpected ^= mSrcData[i];
+        }
+        assertEquals("Incorrect value for UXor ", sExpected, mReturnData[0]);
+    }
+
+    public void testMin() {
+        for (int i = 0; i < 16; i++) {
+            initS(true, 256);
+
+            mScript.set_gISum(0x7fffffff);
+            mScript.forEach_test_Min(mSrc);
+            mScript.invoke_getValueS(mReturn);
+            mReturn.copyTo(mReturnData);
+
+            mScript.set_gISum(0x7fffffff);
+            mScript.invoke_computeReference_Min(mSrc, mReturn);
+            mReturn.copyTo(mRefData);
+
+            assertEquals("Incorrect value for Min ", mRefData[0], mReturnData[0]);
+        }
+    }
+
+    public void testUMin() {
+        for (int i = 0; i < 16; i++) {
+            initU(true, 256);
+
+            mScript.set_gUSum(0xffffffffL);
+            mScript.forEach_test_uMin(mSrc);
+            mScript.invoke_getValueU(mReturn);
+            mReturn.copyTo(mReturnData);
+
+            mScript.set_gUSum(0xffffffffL);
+            mScript.invoke_computeReference_uMin(mSrc, mReturn);
+            mReturn.copyTo(mRefData);
+
+            assertEquals("Incorrect value for UMin ", mRefData[0], mReturnData[0]);
+        }
+    }
+
+    public void testMax() {
+        for (int i = 0; i < 16; i++) {
+            initS(true, 256);
+
+            mScript.set_gISum(0);
+            mScript.forEach_test_Max(mSrc);
+            mScript.invoke_getValueS(mReturn);
+            mReturn.copyTo(mReturnData);
+
+            mScript.set_gISum(0);
+            mScript.invoke_computeReference_Max(mSrc, mReturn);
+            mReturn.copyTo(mRefData);
+
+            assertEquals("Incorrect value for Min ", mRefData[0], mReturnData[0]);
+        }
+    }
+
+    public void testUMax() {
+        for (int i = 0; i < 16; i++) {
+            initU(true, 256);
+
+            mScript.set_gISum(0);
+            mScript.forEach_test_uMax(mSrc);
+            mScript.invoke_getValueU(mReturn);
+            mReturn.copyTo(mReturnData);
+
+            mScript.set_gISum(0);
+            mScript.invoke_computeReference_uMax(mSrc, mReturn);
+            mReturn.copyTo(mRefData);
+
+            assertEquals("Incorrect value for UMax ", mRefData[0], mReturnData[0]);
+        }
+    }
+
+    public void testAnd() {
+        Random r = new Random(78);
+
+        for (int i = 0; i < 64; i++) {
+            initS(false, 128);
+
+            for (int j = 0; j < mSrcData.length; j++) {
+                mSrcData[j] = ~0;
+            }
+            mSrcData[r.nextInt(mSrcData.length)] = ~0x40000000;
+            mSrcData[r.nextInt(mSrcData.length)] = ~0x10000000;
+            mSrcData[r.nextInt(mSrcData.length)] = ~0x02000000;
+            mSrcData[r.nextInt(mSrcData.length)] = ~0x00c00000;
+            mSrcData[r.nextInt(mSrcData.length)] = ~0x00010000;
+            mSrcData[r.nextInt(mSrcData.length)] = ~0x00080000;
+            mSrcData[r.nextInt(mSrcData.length)] = ~0x00001000;
+            mSrcData[r.nextInt(mSrcData.length)] = ~0x00000200;
+            mSrcData[r.nextInt(mSrcData.length)] = ~0x0000000f;
+            mSrc.copyFrom(mSrcData);
+
+            mScript.set_gISum(0xffffffff);
+            mScript.forEach_test_And(mSrc);
+            mScript.invoke_getValueS(mReturn);
+            mReturn.copyTo(mReturnData);
+
+            int sExpected = 0xffffffff;
+            for (int j = 0; j < mSrcData.length; j++) {
+                sExpected &= mSrcData[j];
+            }
+            assertEquals("Incorrect value for And ", sExpected, mReturnData[0]);
+        }
+    }
+
+    public void testUAnd() {
+        Random r = new Random(78);
+
+        for (int i = 0; i < 64; i++) {
+            initU(false, 128);
+
+            for (int j = 0; j < mSrcData.length; j++) {
+                mSrcData[j] = ~0;
+            }
+            mSrcData[r.nextInt(mSrcData.length)] = ~0x40000000;
+            mSrcData[r.nextInt(mSrcData.length)] = ~0x10000000;
+            mSrcData[r.nextInt(mSrcData.length)] = ~0x02000000;
+            mSrcData[r.nextInt(mSrcData.length)] = ~0x00c00000;
+            mSrcData[r.nextInt(mSrcData.length)] = ~0x00010000;
+            mSrcData[r.nextInt(mSrcData.length)] = ~0x00080000;
+            mSrcData[r.nextInt(mSrcData.length)] = ~0x00001000;
+            mSrcData[r.nextInt(mSrcData.length)] = ~0x00000200;
+            mSrcData[r.nextInt(mSrcData.length)] = ~0x0000000f;
+            mSrc.copyFrom(mSrcData);
+
+            mScript.set_gUSum(0xffffffffL);
+            mScript.forEach_test_uAnd(mSrc);
+            mScript.invoke_getValueU(mReturn);
+            mReturn.copyTo(mReturnData);
+
+            int sExpected = 0xffffffff;
+            for (int j = 0; j < mSrcData.length; j++) {
+                sExpected &= mSrcData[j];
+            }
+            assertEquals("Incorrect value for uAnd ", sExpected, mReturnData[0]);
+        }
+    }
+
+    public void testOr() {
+        Random r = new Random(78);
+
+        for (int i = 0; i < 64; i++) {
+            initS(false, 128);
+
+            for (int j = 0; j < mSrcData.length; j++) {
+                mSrcData[j] = 0;
+            }
+            mSrcData[r.nextInt(mSrcData.length)] = 0x40000000;
+            mSrcData[r.nextInt(mSrcData.length)] = 0x10000000;
+            mSrcData[r.nextInt(mSrcData.length)] = 0x02000000;
+            mSrcData[r.nextInt(mSrcData.length)] = 0x00c00000;
+            mSrcData[r.nextInt(mSrcData.length)] = 0x00010000;
+            mSrcData[r.nextInt(mSrcData.length)] = 0x00080000;
+            mSrcData[r.nextInt(mSrcData.length)] = 0x00001000;
+            mSrcData[r.nextInt(mSrcData.length)] = 0x00000200;
+            mSrcData[r.nextInt(mSrcData.length)] = 0x0000000f;
+            mSrc.copyFrom(mSrcData);
+
+            mScript.set_gISum(0);
+            mScript.forEach_test_Or(mSrc);
+            mScript.invoke_getValueS(mReturn);
+            mReturn.copyTo(mReturnData);
+
+            int sExpected = 0;
+            for (int j = 0; j < mSrcData.length; j++) {
+                sExpected |= mSrcData[j];
+            }
+            assertEquals("Incorrect value for Or ", sExpected, mReturnData[0]);
+        }
+    }
+
+    public void testUOr() {
+        Random r = new Random(78);
+
+        for (int i = 0; i < 64; i++) {
+            initU(false, 128);
+
+            for (int j = 0; j < mSrcData.length; j++) {
+                mSrcData[j] = 0;
+            }
+            mSrcData[r.nextInt(mSrcData.length)] = 0x40000000;
+            mSrcData[r.nextInt(mSrcData.length)] = 0x10000000;
+            mSrcData[r.nextInt(mSrcData.length)] = 0x02000000;
+            mSrcData[r.nextInt(mSrcData.length)] = 0x00c00000;
+            mSrcData[r.nextInt(mSrcData.length)] = 0x00010000;
+            mSrcData[r.nextInt(mSrcData.length)] = 0x00080000;
+            mSrcData[r.nextInt(mSrcData.length)] = 0x00001000;
+            mSrcData[r.nextInt(mSrcData.length)] = 0x00000200;
+            mSrcData[r.nextInt(mSrcData.length)] = 0x0000000f;
+            mSrc.copyFrom(mSrcData);
+
+            mScript.set_gUSum(0);
+            mScript.forEach_test_uOr(mSrc);
+            mScript.invoke_getValueU(mReturn);
+            mReturn.copyTo(mReturnData);
+
+            int sExpected = 0;
+            for (int j = 0; j < mSrcData.length; j++) {
+                sExpected |= mSrcData[j];
+            }
+            assertEquals("Incorrect value for UOr ", sExpected, mReturnData[0]);
+        }
+    }
+
+}
+
diff --git a/tests/tests/rscpp/src/android/cts/rscpp/RSBlendTest.java b/tests/tests/rscpp/src/android/cts/rscpp/RSBlendTest.java
index 0830f78..7c0ba38 100644
--- a/tests/tests/rscpp/src/android/cts/rscpp/RSBlendTest.java
+++ b/tests/tests/rscpp/src/android/cts/rscpp/RSBlendTest.java
@@ -117,7 +117,8 @@
                 assertTrue(byteAlloc[i] == byteAlloc2[i]);
             }
 
+            mRS.destroy();
         }
 
     }
-}
\ No newline at end of file
+}
diff --git a/tests/tests/security/src/android/security/cts/OpenSSLEarlyCCSTest.java b/tests/tests/security/src/android/security/cts/OpenSSLEarlyCCSTest.java
new file mode 100644
index 0000000..9cdb288
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/OpenSSLEarlyCCSTest.java
@@ -0,0 +1,582 @@
+/*
+ * Copyright (C) 2014 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.security.cts.OpenSSLHeartbleedTest.AlertMessage;
+import android.security.cts.OpenSSLHeartbleedTest.HandshakeMessage;
+import android.security.cts.OpenSSLHeartbleedTest.HardcodedCertX509KeyManager;
+import android.security.cts.OpenSSLHeartbleedTest.TlsProtocols;
+import android.security.cts.OpenSSLHeartbleedTest.TlsRecord;
+import android.security.cts.OpenSSLHeartbleedTest.TlsRecordReader;
+import android.security.cts.OpenSSLHeartbleedTest.TrustAllX509TrustManager;
+import android.test.InstrumentationTestCase;
+import android.util.Log;
+
+import com.android.cts.security.R;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.security.KeyFactory;
+import java.security.PrivateKey;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import javax.net.ServerSocketFactory;
+import javax.net.SocketFactory;
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.TrustManager;
+
+/**
+ * Tests for the OpenSSL early ChangeCipherSpec (CCS) vulnerability (CVE-2014-0224).
+ */
+public class OpenSSLEarlyCCSTest extends InstrumentationTestCase {
+
+    // IMPLEMENTATION NOTE: This test spawns an SSLSocket client, SSLServerSocket server, and a
+    // Man-in-The-Middle (MiTM). The client connects to the MiTM which then connects to the server
+    // and starts forwarding all TLS records between the client and the server. In tests that check
+    // for the early CCS vulnerability, the MiTM also injects an early ChangeCipherSpec record into
+    // the traffic to which a correctly implemented peer is supposed to reply by immediately
+    // aborting the TLS handshake with an unexpected_message fatal alert.
+
+    // IMPLEMENTATION NOTE: This test spawns several background threads that perform network I/O
+    // on localhost. To ensure that these background threads are cleaned up at the end of the test,
+    // tearDown() kills the sockets they may be using. To aid this behavior, all Socket and
+    // ServerSocket instances are available as fields of this class. These fields should be accessed
+    // via setters and getters to avoid memory visibility issues due to concurrency.
+
+    private static final String TAG = OpenSSLEarlyCCSTest.class.getSimpleName();
+
+    private SSLServerSocket mServerListeningSocket;
+    private SSLSocket mServerSocket;
+    private SSLSocket mClientSocket;
+    private ServerSocket mMitmListeningSocket;
+    private Socket mMitmServerSocket;
+    private Socket mMitmClientSocket;
+    private ExecutorService mExecutorService;
+
+    private boolean mCCSWasInjected;
+    private TlsRecord mFirstRecordReceivedAfterCCSWasInjected;
+    private boolean mFirstRecordReceivedAfterCCSWasInjectedMayBeEncrypted;
+
+    @Override
+    protected void tearDown() throws Exception {
+        Log.i(TAG, "Tearing down");
+        try {
+            if (mExecutorService != null) {
+                mExecutorService.shutdownNow();
+            }
+            OpenSSLHeartbleedTest.closeQuietly(getServerListeningSocket());
+            OpenSSLHeartbleedTest.closeQuietly(getServerSocket());
+            OpenSSLHeartbleedTest.closeQuietly(getClientSocket());
+            OpenSSLHeartbleedTest.closeQuietly(getMitmListeningSocket());
+            OpenSSLHeartbleedTest.closeQuietly(getMitmServerSocket());
+            OpenSSLHeartbleedTest.closeQuietly(getMitmClientSocket());
+        } finally {
+            super.tearDown();
+            Log.i(TAG, "Tear down completed");
+        }
+    }
+
+    /**
+     * Tests that TLS handshake succeeds when the MiTM simply forwards all data without tampering
+     * with it. This is to catch issues unrelated to early CCS.
+     */
+    public void testWithoutEarlyCCS() throws Exception {
+        handshake(false, false);
+    }
+
+    /**
+     * Tests whether client sockets are vulnerable to early CCS.
+     */
+    public void testEarlyCCSInjectedIntoClient() throws Exception {
+        checkEarlyCCS(true);
+    }
+
+    /**
+     * Tests whether server sockets are vulnerable to early CCS.
+     */
+    public void testEarlyCCSInjectedIntoServer() throws Exception {
+        checkEarlyCCS(false);
+    }
+
+    /**
+     * Tests for the early CCS vulnerability.
+     *
+     * @param client {@code true} to test the client, {@code false} to test the server.
+     */
+    private void checkEarlyCCS(boolean client) throws Exception {
+        // IMPLEMENTATION NOTE: The MiTM is forwarding all TLS records between the client and the
+        // server unmodified. Additionally, the MiTM transmits an early ChangeCipherSpec to server
+        // (if "client" argument is false) right before client's ClientKeyExchange or to client (if
+        // "client" argument is true) right before server's Certificate. The peer is expected to
+        // to abort the handshake immediately with unexpected_message alert.
+        try {
+            handshake(true, client);
+            // TLS handshake succeeded
+            assertTrue("Early CCS injected", wasCCSInjected());
+            fail("Handshake succeeded despite early CCS having been injected");
+        } catch (ExecutionException e) {
+            // TLS handshake failed
+            assertTrue("Early CCS injected", wasCCSInjected());
+            TlsRecord firstRecordReceivedAfterCCSWasInjected =
+                    getFirstRecordReceivedAfterCCSWasInjected();
+            assertNotNull(
+                    "Nothing received after early CCS was injected",
+                    firstRecordReceivedAfterCCSWasInjected);
+            if (firstRecordReceivedAfterCCSWasInjected.protocol == TlsProtocols.ALERT) {
+                AlertMessage alert = AlertMessage.tryParse(firstRecordReceivedAfterCCSWasInjected);
+                if ((alert != null)
+                        && (alert.level == AlertMessage.LEVEL_FATAL)
+                        && (alert.description == AlertMessage.DESCRIPTION_UNEXPECTED_MESSAGE)) {
+                    // Expected/correct response to an early CCS
+                    return;
+                }
+            }
+            fail("SSLSocket is vulnerable to early CCS in " + ((client) ? "client" : "server")
+                    + " mode: unexpected record received after CCS was injected: "
+                    + getRecordInfo(
+                            getFirstRecordReceivedAfterCCSWasInjected(),
+                            getFirstRecordReceivedAfterCCSWasInjectedMayBeEncrypted()));
+        }
+    }
+
+    /**
+     * Starts the client, server, and the MiTM. Makes the client and server perform a TLS handshake
+     * and exchange application-level data. The MiTM injects a ChangeCipherSpec record if requested
+     * by {@code earlyCCSInjected}. The direction of the injected message is specified by
+     * {@code injectedIntoClient}.
+     */
+    private void handshake(
+            final boolean earlyCCSInjected,
+            final boolean injectedIntoClient) throws Exception {
+        mExecutorService = Executors.newFixedThreadPool(4);
+        setServerListeningSocket(serverBind());
+        final SocketAddress serverAddress = getServerListeningSocket().getLocalSocketAddress();
+        Log.i(TAG, "Server bound to " + serverAddress);
+
+        setMitmListeningSocket(mitmBind());
+        final SocketAddress mitmAddress = getMitmListeningSocket().getLocalSocketAddress();
+        Log.i(TAG, "MiTM bound to " + mitmAddress);
+
+        // Start the MiTM daemon in the background
+        mExecutorService.submit(new Callable<Void>() {
+            @Override
+            public Void call() throws Exception {
+                mitmAcceptAndForward(serverAddress, earlyCCSInjected, injectedIntoClient);
+                return null;
+            }
+        });
+        // Start the server in the background
+        Future<Void> serverFuture = mExecutorService.submit(new Callable<Void>() {
+            @Override
+            public Void call() throws Exception {
+                serverAcceptAndHandshake();
+                return null;
+            }
+        });
+        // Start the client in the background
+        Future<Void> clientFuture = mExecutorService.submit(new Callable<Void>() {
+            @Override
+            public Void call() throws Exception {
+                clientConnectAndHandshake(mitmAddress);
+                return null;
+            }
+        });
+
+        // Wait for both client and server to terminate, to ensure that we observe all the traffic
+        // exchanged between them. Throw an exception if one of them failed.
+        Log.i(TAG, "Waiting for client");
+        // Wait for the client, but don't yet throw an exception if it failed.
+        Exception clientException = null;
+        try {
+            clientFuture.get(10, TimeUnit.SECONDS);
+        } catch (Exception e) {
+            clientException = e;
+        }
+        Log.i(TAG, "Waiting for server");
+        // Wait for the server and throw an exception if it failed.
+        serverFuture.get(5, TimeUnit.SECONDS);
+        // Throw an exception if the client failed.
+        if (clientException != null) {
+            throw clientException;
+        }
+        Log.i(TAG, "Handshake completed and application data exchanged");
+    }
+
+    private void clientConnectAndHandshake(SocketAddress serverAddress) throws Exception {
+        SSLContext sslContext = SSLContext.getInstance("TLS");
+        sslContext.init(
+                null,
+                new TrustManager[] {new TrustAllX509TrustManager()},
+                null);
+        SSLSocket socket = (SSLSocket) sslContext.getSocketFactory().createSocket();
+        setClientSocket(socket);
+        try {
+            Log.i(TAG, "Client connecting to " + serverAddress);
+            socket.connect(serverAddress);
+            Log.i(TAG, "Client connected to server from " + socket.getLocalSocketAddress());
+            // Ensure a TLS handshake is performed and an exception is thrown if it fails.
+            socket.getOutputStream().write("client".getBytes());
+            socket.getOutputStream().flush();
+            Log.i(TAG, "Client sent request. Reading response");
+            int b = socket.getInputStream().read();
+            Log.i(TAG, "Client read response: " + b);
+        } catch (Exception e) {
+            // Make sure the test log includes exceptions from all parties involved.
+            Log.w(TAG, "Client failed", e);
+            throw e;
+          } finally {
+            socket.close();
+        }
+    }
+
+    private SSLServerSocket serverBind() throws Exception {
+        // Load the server's private key and cert chain
+        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+        PrivateKey privateKey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(
+                OpenSSLHeartbleedTest.readResource(
+                        getInstrumentation().getContext(), R.raw.openssl_heartbleed_test_key)));
+        CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+        X509Certificate[] certChain =  new X509Certificate[] {
+                (X509Certificate) certFactory.generateCertificate(
+                        new ByteArrayInputStream(OpenSSLHeartbleedTest.readResource(
+                                getInstrumentation().getContext(),
+                                R.raw.openssl_heartbleed_test_cert)))
+        };
+
+        // Initialize TLS context to use the private key and cert chain for server sockets
+        SSLContext sslContext = SSLContext.getInstance("TLS");
+        sslContext.init(
+                new KeyManager[] {new HardcodedCertX509KeyManager(privateKey, certChain)},
+                null,
+                null);
+
+        Log.i(TAG, "Server binding to local port");
+        return (SSLServerSocket) sslContext.getServerSocketFactory().createServerSocket(0);
+    }
+
+    private void serverAcceptAndHandshake() throws Exception {
+        SSLSocket socket = null;
+        SSLServerSocket serverSocket = getServerListeningSocket();
+        try {
+            Log.i(TAG, "Server listening for incoming connection");
+            socket = (SSLSocket) serverSocket.accept();
+            setServerSocket(socket);
+            Log.i(TAG, "Server accepted connection from " + socket.getRemoteSocketAddress());
+            // Ensure a TLS handshake is performed and an exception is thrown if it fails.
+            socket.getOutputStream().write("server".getBytes());
+            socket.getOutputStream().flush();
+            Log.i(TAG, "Server sent reply. Reading response");
+            int b = socket.getInputStream().read();
+            Log.i(TAG, "Server read response: " + b);
+        } catch (Exception e) {
+            // Make sure the test log includes exceptions from all parties involved.
+            Log.w(TAG, "Server failed", e);
+            throw e;
+        } finally {
+            if (socket != null) {
+                socket.close();
+            }
+        }
+    }
+
+    private ServerSocket mitmBind() throws Exception {
+        Log.i(TAG, "MiTM binding to local port");
+        return ServerSocketFactory.getDefault().createServerSocket(0);
+    }
+
+    /**
+     * Accepts the connection on the MiTM listening socket, forwards the TLS records between the
+     * client and the server, and, if requested, injects an early {@code ChangeCipherSpec} record.
+     *
+     * @param injectEarlyCCS whether to inject an early {@code ChangeCipherSpec} record.
+     * @param injectIntoClient when {@code injectEarlyCCS} is {@code true}, whether to inject the
+     *        {@code ChangeCipherSpec} record into client or into server.
+     */
+    private void mitmAcceptAndForward(
+            SocketAddress serverAddress,
+            final boolean injectEarlyCCS,
+            final boolean injectIntoClient) throws Exception {
+        Socket clientSocket = null;
+        Socket serverSocket = null;
+        ServerSocket listeningSocket = getMitmListeningSocket();
+        try {
+            Log.i(TAG, "MiTM waiting for incoming connection");
+            clientSocket = listeningSocket.accept();
+            setMitmClientSocket(clientSocket);
+            Log.i(TAG, "MiTM accepted connection from " + clientSocket.getRemoteSocketAddress());
+            serverSocket = SocketFactory.getDefault().createSocket();
+            setMitmServerSocket(serverSocket);
+            Log.i(TAG, "MiTM connecting to server " + serverAddress);
+            serverSocket.connect(serverAddress, 10000);
+            Log.i(TAG, "MiTM connected to server from " + serverSocket.getLocalSocketAddress());
+            final InputStream serverInputStream = serverSocket.getInputStream();
+            final OutputStream clientOutputStream = clientSocket.getOutputStream();
+            Future<Void> serverToClientTask = mExecutorService.submit(new Callable<Void>() {
+                @Override
+                public Void call() throws Exception {
+                    // Inject early ChangeCipherSpec before Certificate, if requested
+                    forwardTlsRecords(
+                            "MiTM S->C",
+                            serverInputStream,
+                            clientOutputStream,
+                            (injectEarlyCCS && injectIntoClient)
+                                      ? HandshakeMessage.TYPE_CERTIFICATE : -1);
+                    return null;
+                }
+            });
+            // Inject early ChangeCipherSpec before ClientKeyExchange, if requested
+            forwardTlsRecords(
+                    "MiTM C->S",
+                    clientSocket.getInputStream(),
+                    serverSocket.getOutputStream(),
+                    (injectEarlyCCS && !injectIntoClient)
+                            ? HandshakeMessage.TYPE_CLIENT_KEY_EXCHANGE : -1);
+            serverToClientTask.get(10, TimeUnit.SECONDS);
+        } catch (Exception e) {
+            // Make sure the test log includes exceptions from all parties involved.
+            Log.w(TAG, "MiTM failed", e);
+            throw e;
+        } finally {
+            OpenSSLHeartbleedTest.closeQuietly(clientSocket);
+            OpenSSLHeartbleedTest.closeQuietly(serverSocket);
+        }
+    }
+
+    /**
+     * Forwards TLS records from the provided {@code InputStream} to the provided
+     * {@code OutputStream}. If requested, injects an early {@code ChangeCipherSpec}.
+     */
+    private void forwardTlsRecords(
+            String logPrefix,
+            InputStream in,
+            OutputStream out,
+            int handshakeMessageTypeBeforeWhichToInjectEarlyCCS) throws Exception {
+        Log.i(TAG, logPrefix + ": record forwarding started");
+        boolean interestingRecordsLogged =
+                handshakeMessageTypeBeforeWhichToInjectEarlyCCS == -1;
+        try {
+            TlsRecordReader reader = new TlsRecordReader(in);
+            byte[] recordBytes;
+            // Fragments contained in records may be encrypted after a certain point in the
+            // handshake. Once they are encrypted, this MiTM cannot inspect their plaintext which.
+            boolean fragmentEncryptionMayBeEnabled = false;
+            while ((recordBytes = reader.readRecord()) != null) {
+                TlsRecord record = TlsRecord.parse(recordBytes);
+                forwardTlsRecord(logPrefix,
+                        recordBytes,
+                        record,
+                        fragmentEncryptionMayBeEnabled,
+                        out,
+                        interestingRecordsLogged,
+                        handshakeMessageTypeBeforeWhichToInjectEarlyCCS);
+                if (record.protocol == TlsProtocols.CHANGE_CIPHER_SPEC) {
+                    fragmentEncryptionMayBeEnabled = true;
+                }
+            }
+        } finally {
+            Log.d(TAG, logPrefix + ": record forwarding finished");
+        }
+    }
+
+    private void forwardTlsRecord(
+            String logPrefix,
+            byte[] recordBytes,
+            TlsRecord record,
+            boolean fragmentEncryptionMayBeEnabled,
+            OutputStream out,
+            boolean interestingRecordsLogged,
+            int handshakeMessageTypeBeforeWhichToInjectCCS) throws IOException {
+        // Save information about the record if it's of interest to this test
+        if (interestingRecordsLogged) {
+            if (wasCCSInjected()) {
+                setFirstRecordReceivedAfterCCSWasInjected(record, fragmentEncryptionMayBeEnabled);
+            }
+        } else if ((record.protocol == TlsProtocols.CHANGE_CIPHER_SPEC)
+                && (handshakeMessageTypeBeforeWhichToInjectCCS != -1)) {
+            // Do not forward original ChangeCipherSpec record(s) if we're injecting such a record
+            // ourselves. This is to make sure that the peer sees only one ChangeCipherSpec.
+            Log.i(TAG, logPrefix + ": Dropping TLS record. "
+                    + getRecordInfo(record, fragmentEncryptionMayBeEnabled));
+            return;
+        }
+
+        // Inject a ChangeCipherSpec, if necessary, before the specified handshake message type
+        if (handshakeMessageTypeBeforeWhichToInjectCCS != -1) {
+            if ((!fragmentEncryptionMayBeEnabled) && (OpenSSLHeartbleedTest.isHandshakeMessageType(
+                    record, handshakeMessageTypeBeforeWhichToInjectCCS))) {
+                Log.i(TAG, logPrefix + ": Injecting ChangeCipherSpec");
+                setCCSWasInjected();
+                out.write(createChangeCipherSpecRecord(record.versionMajor, record.versionMinor));
+                out.flush();
+            }
+        }
+
+        Log.i(TAG, logPrefix + ": Forwarding TLS record. "
+                + getRecordInfo(record, fragmentEncryptionMayBeEnabled));
+        out.write(recordBytes);
+        out.flush();
+    }
+
+    private static String getRecordInfo(TlsRecord record, boolean mayBeEncrypted) {
+        StringBuilder result = new StringBuilder();
+        result.append(getProtocolName(record.protocol))
+                .append(", ")
+                .append(getFragmentInfo(record, mayBeEncrypted));
+        return result.toString();
+    }
+
+    private static String getProtocolName(int protocol) {
+        switch (protocol) {
+            case TlsProtocols.ALERT:
+                return "alert";
+            case TlsProtocols.APPLICATION_DATA:
+                return "application data";
+            case TlsProtocols.CHANGE_CIPHER_SPEC:
+                return "change cipher spec";
+            case TlsProtocols.HANDSHAKE:
+                return "handshake";
+            default:
+                return String.valueOf(protocol);
+        }
+    }
+
+    private static String getFragmentInfo(TlsRecord record, boolean mayBeEncrypted) {
+        StringBuilder result = new StringBuilder();
+        if (mayBeEncrypted) {
+            result.append("encrypted?");
+        } else {
+            switch (record.protocol) {
+                case TlsProtocols.ALERT:
+                    result.append("level: " + ((record.fragment.length > 0)
+                            ? String.valueOf(record.fragment[0] & 0xff) : "n/a")
+                    + ", description: "
+                    + ((record.fragment.length > 1)
+                            ? String.valueOf(record.fragment[1] & 0xff) : "n/a"));
+                    break;
+                case TlsProtocols.APPLICATION_DATA:
+                    break;
+                case TlsProtocols.CHANGE_CIPHER_SPEC:
+                    result.append("payload: " + ((record.fragment.length > 0)
+                            ? String.valueOf(record.fragment[0] & 0xff) : "n/a"));
+                    break;
+                case TlsProtocols.HANDSHAKE:
+                    result.append("type: " + ((record.fragment.length > 0)
+                            ? String.valueOf(record.fragment[0] & 0xff) : "n/a"));
+                    break;
+            }
+        }
+        result.append(", ").append("fragment length: " + record.fragment.length);
+        return result.toString();
+    }
+
+    private synchronized void setServerListeningSocket(SSLServerSocket socket) {
+        mServerListeningSocket = socket;
+    }
+
+    private synchronized SSLServerSocket getServerListeningSocket() {
+        return mServerListeningSocket;
+    }
+
+    private synchronized void setServerSocket(SSLSocket socket) {
+        mServerSocket = socket;
+    }
+
+    private synchronized SSLSocket getServerSocket() {
+        return mServerSocket;
+    }
+
+    private synchronized void setClientSocket(SSLSocket socket) {
+        mClientSocket = socket;
+    }
+
+    private synchronized SSLSocket getClientSocket() {
+        return mClientSocket;
+    }
+
+    private synchronized void setMitmListeningSocket(ServerSocket socket) {
+        mMitmListeningSocket = socket;
+    }
+
+    private synchronized ServerSocket getMitmListeningSocket() {
+        return mMitmListeningSocket;
+    }
+
+    private synchronized void setMitmServerSocket(Socket socket) {
+        mMitmServerSocket = socket;
+    }
+
+    private synchronized Socket getMitmServerSocket() {
+        return mMitmServerSocket;
+    }
+
+    private synchronized void setMitmClientSocket(Socket socket) {
+        mMitmClientSocket = socket;
+    }
+
+    private synchronized Socket getMitmClientSocket() {
+        return mMitmClientSocket;
+    }
+
+    private synchronized void setCCSWasInjected() {
+        mCCSWasInjected = true;
+    }
+
+    private synchronized boolean wasCCSInjected() {
+        return mCCSWasInjected;
+    }
+
+    private synchronized void setFirstRecordReceivedAfterCCSWasInjected(
+            TlsRecord record, boolean mayBeEncrypted) {
+        if (mFirstRecordReceivedAfterCCSWasInjected == null) {
+            mFirstRecordReceivedAfterCCSWasInjected = record;
+            mFirstRecordReceivedAfterCCSWasInjectedMayBeEncrypted = mayBeEncrypted;
+        }
+    }
+
+    private synchronized TlsRecord getFirstRecordReceivedAfterCCSWasInjected() {
+        return mFirstRecordReceivedAfterCCSWasInjected;
+    }
+
+    private synchronized boolean getFirstRecordReceivedAfterCCSWasInjectedMayBeEncrypted() {
+        return mFirstRecordReceivedAfterCCSWasInjectedMayBeEncrypted;
+    }
+
+    private static byte[] createChangeCipherSpecRecord(int versionMajor, int versionMinor) {
+        TlsRecord record = new TlsRecord();
+        record.protocol = TlsProtocols.CHANGE_CIPHER_SPEC;
+        record.versionMajor = versionMajor;
+        record.versionMinor = versionMinor;
+        record.fragment = new byte[] {1};
+        return TlsRecord.unparse(record);
+    }
+}
diff --git a/tests/tests/security/src/android/security/cts/OpenSSLHeartbleedTest.java b/tests/tests/security/src/android/security/cts/OpenSSLHeartbleedTest.java
index 3aa0268..12fcee4 100644
--- a/tests/tests/security/src/android/security/cts/OpenSSLHeartbleedTest.java
+++ b/tests/tests/security/src/android/security/cts/OpenSSLHeartbleedTest.java
@@ -261,7 +261,7 @@
         }
     }
 
-    private SSLServerSocket serverBind() throws Exception {
+    public SSLServerSocket serverBind() throws Exception {
         // Load the server's private key and cert chain
         KeyFactory keyFactory = KeyFactory.getInstance("RSA");
         PrivateKey privateKey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(
@@ -608,7 +608,7 @@
         return mFirstDetectedFatalAlertDescription;
     }
 
-    private static abstract class TlsProtocols {
+    public static abstract class TlsProtocols {
         public static final int CHANGE_CIPHER_SPEC = 20;
         public static final int ALERT = 21;
         public static final int HANDSHAKE = 22;
@@ -617,13 +617,13 @@
         private TlsProtocols() {}
     }
 
-    private static class TlsRecord {
-        private int protocol;
-        private int versionMajor;
-        private int versionMinor;
-        private byte[] fragment;
+    public static class TlsRecord {
+        public int protocol;
+        public int versionMajor;
+        public int versionMinor;
+        public byte[] fragment;
 
-        private static TlsRecord parse(byte[] record) throws IOException {
+        public static TlsRecord parse(byte[] record) throws IOException {
             TlsRecord result = new TlsRecord();
             if (record.length < TlsRecordReader.RECORD_HEADER_LENGTH) {
                 throw new IOException("Record too short: " + record.length);
@@ -645,7 +645,7 @@
             return result;
         }
 
-        private static byte[] unparse(TlsRecord record) {
+        public static byte[] unparse(TlsRecord record) {
             byte[] result = new byte[TlsRecordReader.RECORD_HEADER_LENGTH + record.fragment.length];
             result[0] = (byte) record.protocol;
             result[1] = (byte) record.versionMajor;
@@ -659,7 +659,7 @@
         }
     }
 
-    private static final boolean isHandshakeMessageType(TlsRecord record, int type) {
+    public static final boolean isHandshakeMessageType(TlsRecord record, int type) {
         HandshakeMessage handshake = HandshakeMessage.tryParse(record);
         if (handshake == null) {
             return false;
@@ -667,18 +667,19 @@
         return handshake.type == type;
     }
 
-    private static class HandshakeMessage {
-        private static final int TYPE_SERVER_HELLO = 2;
-        private static final int TYPE_CLIENT_KEY_EXCHANGE = 16;
+    public static class HandshakeMessage {
+        public static final int TYPE_SERVER_HELLO = 2;
+        public static final int TYPE_CERTIFICATE = 11;
+        public static final int TYPE_CLIENT_KEY_EXCHANGE = 16;
 
-        private int type;
+        public int type;
 
         /**
          * Parses the provided TLS record as a handshake message.
          *
          * @return alert message or {@code null} if the record does not contain a handshake message.
          */
-        private static HandshakeMessage tryParse(TlsRecord record) {
+        public static HandshakeMessage tryParse(TlsRecord record) {
             if (record.protocol != TlsProtocols.HANDSHAKE) {
                 return null;
             }
@@ -691,19 +692,19 @@
         }
     }
 
-    private static class AlertMessage {
-        private static final int LEVEL_FATAL = 2;
-        private static final int DESCRIPTION_UNEXPECTED_MESSAGE = 10;
+    public static class AlertMessage {
+        public static final int LEVEL_FATAL = 2;
+        public static final int DESCRIPTION_UNEXPECTED_MESSAGE = 10;
 
-        private int level;
-        private int description;
+        public int level;
+        public int description;
 
         /**
          * Parses the provided TLS record as an alert message.
          *
          * @return alert message or {@code null} if the record does not contain an alert message.
          */
-        private static AlertMessage tryParse(TlsRecord record) {
+        public static AlertMessage tryParse(TlsRecord record) {
             if (record.protocol != TlsProtocols.ALERT) {
                 return null;
             }
@@ -747,7 +748,7 @@
     /**
      * Reader of TLS records.
      */
-    private static class TlsRecordReader {
+    public static class TlsRecordReader {
         private static final int MAX_RECORD_LENGTH = 16384;
         public static final int RECORD_HEADER_LENGTH = 5;
 
@@ -884,7 +885,7 @@
         }
     }
 
-    private static void closeQuietly(ServerSocket socket) {
+    public static void closeQuietly(ServerSocket socket) {
         if (socket != null) {
             try {
                 socket.close();
@@ -892,7 +893,7 @@
         }
     }
 
-    private static void closeQuietly(Socket socket) {
+    public static void closeQuietly(Socket socket) {
         if (socket != null) {
             try {
                 socket.close();
@@ -900,7 +901,7 @@
         }
     }
 
-    private static byte[] readResource(Context context, int resId) throws IOException {
+    public static byte[] readResource(Context context, int resId) throws IOException {
         ByteArrayOutputStream result = new ByteArrayOutputStream();
         InputStream in = null;
         byte[] buf = new byte[16 * 1024];
@@ -919,7 +920,7 @@
     /**
      * {@link X509TrustManager} which trusts all certificate chains.
      */
-    private static class TrustAllX509TrustManager implements X509TrustManager {
+    public static class TrustAllX509TrustManager implements X509TrustManager {
         @Override
         public void checkClientTrusted(X509Certificate[] chain, String authType)
                 throws CertificateException {
@@ -939,12 +940,12 @@
     /**
      * {@link X509KeyManager} which uses the provided private key and cert chain for all sockets.
      */
-    private static class HardcodedCertX509KeyManager implements X509KeyManager {
+    public static class HardcodedCertX509KeyManager implements X509KeyManager {
 
         private final PrivateKey mPrivateKey;
         private final X509Certificate[] mCertChain;
 
-        private HardcodedCertX509KeyManager(PrivateKey privateKey, X509Certificate[] certChain) {
+        HardcodedCertX509KeyManager(PrivateKey privateKey, X509Certificate[] certChain) {
             mPrivateKey = privateKey;
             mCertChain = certChain;
         }
diff --git a/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java b/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java
index 09c7cc7..9986e67 100644
--- a/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java
@@ -16,6 +16,7 @@
 
 package android.telephony.cts;
 
+import android.bluetooth.BluetoothAdapter;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.net.ConnectivityManager;
@@ -184,13 +185,14 @@
                 break;
 
             case TelephonyManager.PHONE_TYPE_NONE:
-                boolean nwSupported = mCm.isNetworkSupported(mCm.TYPE_WIFI);
-                if (nwSupported) {
+                if (mCm.isNetworkSupported(ConnectivityManager.TYPE_WIFI)) {
                     assertSerialNumber();
-                    assertMacAddressReported();
+                    assertMacAddress(getWifiMacAddress());
+                } else if (mCm.isNetworkSupported(ConnectivityManager.TYPE_BLUETOOTH)) {
+                    assertSerialNumber();
+                    assertMacAddress(getBluetoothMacAddress());
                 } else {
-                    nwSupported = mCm.isNetworkSupported(mCm.TYPE_ETHERNET);
-                    assertTrue(nwSupported);
+                    assertTrue(mCm.isNetworkSupported(ConnectivityManager.TYPE_ETHERNET));
                 }
                 break;
 
@@ -284,15 +286,14 @@
                 Pattern.matches("[0-9A-Za-z]+", Build.SERIAL));
     }
 
-    private void assertMacAddressReported() {
-        String macAddress = getMacAddress();
+    private void assertMacAddress(String macAddress) {
         String macPattern = "([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}";
         assertTrue("MAC Address " + macAddress + " does not match pattern " + macPattern,
                 Pattern.matches(macPattern, macAddress));
     }
 
     /** @return mac address which requires the WiFi system to be enabled */
-    private String getMacAddress() {
+    private String getWifiMacAddress() {
         WifiManager wifiManager = (WifiManager) getContext()
                 .getSystemService(Context.WIFI_SERVICE);
 
@@ -313,6 +314,15 @@
         }
     }
 
+    private String getBluetoothMacAddress() {
+        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+        if (adapter == null) {
+            return "";
+        }
+
+        return adapter.getAddress();
+    }
+
     private static final String ISO_COUNTRY_CODE_PATTERN = "[a-z]{2}";
 
     public void testGetNetworkCountryIso() {
diff --git a/tests/tests/text/src/android/text/cts/SpannableStringBuilderTest.java b/tests/tests/text/src/android/text/cts/SpannableStringBuilderTest.java
index cfc000d..4895ca9 100644
--- a/tests/tests/text/src/android/text/cts/SpannableStringBuilderTest.java
+++ b/tests/tests/text/src/android/text/cts/SpannableStringBuilderTest.java
@@ -259,6 +259,8 @@
             fail("should throw IndexOutOfBoundsException here");
         } catch (IndexOutOfBoundsException e) {
             // expected exception
+        } catch (NullPointerException e) {
+            // expected exception
         }
     }
 
diff --git a/tests/tests/text/src/android/text/cts/StaticLayoutLineBreakingTest.java b/tests/tests/text/src/android/text/cts/StaticLayoutLineBreakingTest.java
index b249b9e..b754a12 100644
--- a/tests/tests/text/src/android/text/cts/StaticLayoutLineBreakingTest.java
+++ b/tests/tests/text/src/android/text/cts/StaticLayoutLineBreakingTest.java
@@ -48,7 +48,7 @@
 
         @Override
         public float getTextRunAdvances(char[] chars, int index, int count,
-                int contextIndex, int contextCount, int flags, float[] advances,
+                int contextIndex, int contextCount, boolean isRtl, float[] advances,
                 int advancesIndex) {
 
             // Conditions copy pasted from Paint
@@ -56,10 +56,6 @@
                 throw new IllegalArgumentException("text cannot be null");
             }
 
-            if (flags != DIRECTION_LTR && flags != DIRECTION_RTL) {
-                throw new IllegalArgumentException("unknown flags value: " + flags);
-            }
-
             if ((index | count | contextIndex | contextCount | advancesIndex
                     | (index - contextIndex) | (contextCount - count)
                     | ((contextIndex + contextCount) - (index + count))
diff --git a/tests/tests/text/src/android/text/method/cts/ArrowKeyMovementMethodTest.java b/tests/tests/text/src/android/text/method/cts/ArrowKeyMovementMethodTest.java
index 9d3cbc7..3513281 100644
--- a/tests/tests/text/src/android/text/method/cts/ArrowKeyMovementMethodTest.java
+++ b/tests/tests/text/src/android/text/method/cts/ArrowKeyMovementMethodTest.java
@@ -30,6 +30,7 @@
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.WindowManager;
 import android.widget.TextView;
 import android.widget.TextView.BufferType;
 
@@ -68,6 +69,9 @@
 
         getInstrumentation().runOnMainSync(new Runnable() {
             public void run() {
+                getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON |
+                        WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
+                
                 getActivity().setContentView(mTextView);
                 mTextView.setFocusable(true);
                 mTextView.requestFocus();
diff --git a/tests/tests/text/src/android/text/method/cts/KeyListenerTestCase.java b/tests/tests/text/src/android/text/method/cts/KeyListenerTestCase.java
index 4007f33..375ea54 100644
--- a/tests/tests/text/src/android/text/method/cts/KeyListenerTestCase.java
+++ b/tests/tests/text/src/android/text/method/cts/KeyListenerTestCase.java
@@ -23,6 +23,7 @@
 import android.text.format.DateUtils;
 import android.text.method.cts.KeyListenerStubActivity;
 import android.text.method.KeyListener;
+import android.view.WindowManager;
 import android.widget.TextView;
 
 /**
@@ -63,6 +64,13 @@
         mInstrumentation = getInstrumentation();
         mTextView = (TextView) mActivity.findViewById(R.id.keylistener_textview);
 
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                // Ensure that the screen is on for this test.
+                mTextView.setKeepScreenOn(true);
+            }
+        });
+
         assertTrue(mActivity.waitForWindowFocus(5 * DateUtils.SECOND_IN_MILLIS));
     }
 
diff --git a/tests/tests/tv/Android.mk b/tests/tests/tv/Android.mk
index b45129d..477fe39 100644
--- a/tests/tests/tv/Android.mk
+++ b/tests/tests/tv/Android.mk
@@ -12,6 +12,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# Temporarily disable building the TV CTS until we finalize the API.
+# See b/15419005.
+ifeq (1,0)
+
 LOCAL_PATH:= $(call my-dir)
 
 include $(CLEAR_VARS)
@@ -29,3 +33,5 @@
 LOCAL_SDK_VERSION := current
 
 include $(BUILD_CTS_PACKAGE)
+
+endif
diff --git a/tests/tests/tv/src/android/tv/cts/TvInputManagerTest.java b/tests/tests/tv/src/android/tv/cts/TvInputManagerTest.java
index 2b19963..0b9378f 100644
--- a/tests/tests/tv/src/android/tv/cts/TvInputManagerTest.java
+++ b/tests/tests/tv/src/android/tv/cts/TvInputManagerTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.tv.cts;
+package android.media.tv.cts;
 
 import android.content.ComponentName;
 import android.content.ContentUris;
@@ -23,16 +23,16 @@
 import android.net.Uri;
 import android.os.Handler;
 import android.os.HandlerThread;
-import android.provider.TvContract;
 import android.test.AndroidTestCase;
 import android.text.TextUtils;
-import android.tv.TvInputInfo;
-import android.tv.TvInputManager;
-import android.tv.TvInputManager.Session;
-import android.tv.TvInputManager.SessionCallback;
-import android.tv.TvInputManager.TvInputListener;
-import android.tv.TvInputService;
-import android.tv.TvInputService.TvInputSessionImpl;
+import android.media.tv.TvContract;
+import android.media.tv.TvInputInfo;
+import android.media.tv.TvInputManager;
+import android.media.tv.TvInputManager.Session;
+import android.media.tv.TvInputManager.SessionCallback;
+import android.media.tv.TvInputManager.TvInputListener;
+import android.media.tv.TvInputService;
+import android.media.tv.TvInputService.TvInputSessionImpl;
 import android.util.Log;
 import android.view.Surface;
 
@@ -40,7 +40,7 @@
 import java.util.concurrent.TimeUnit;
 
 /**
- * Test for {@link android.tv.TvInputManager}.
+ * Test for {@link android.media.tv.TvInputManager}.
  */
 public class TvInputManagerTest extends AndroidTestCase {
     private static final String TAG = "TvInputManagerTest";
@@ -48,7 +48,7 @@
 
     private TvInputManager mManager;
     private Session mSession;
-    private SessionCallback mSessionCallback;
+    private final SessionCallback mSessionCallback;
     private boolean mAvailability;
     private TvInputListener mTvInputListener;
     private HandlerThread mCallbackThread;
diff --git a/tests/tests/util/src/android/util/cts/RangeTest.java b/tests/tests/util/src/android/util/cts/RangeTest.java
new file mode 100644
index 0000000..45c1fef
--- /dev/null
+++ b/tests/tests/util/src/android/util/cts/RangeTest.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2014 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.util.cts;
+
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Range;
+import android.util.Rational;
+
+public class RangeTest extends junit.framework.TestCase {
+
+    @SmallTest
+    public void testConstructor() {
+        // Trivial, same range
+        Range<Integer> intRange = new Range<Integer>(1, 1);
+
+        assertLower(intRange, 1);
+        assertUpper(intRange, 1);
+
+        // Different values in range
+        Range<Integer> intRange2 = new Range<Integer>(100, 200);
+        assertLower(intRange2, 100);
+        assertUpper(intRange2, 200);
+
+        Range<Float> floatRange = new Range<Float>(Float.NEGATIVE_INFINITY,
+                Float.POSITIVE_INFINITY);
+        assertLower(floatRange, Float.NEGATIVE_INFINITY);
+        assertUpper(floatRange, Float.POSITIVE_INFINITY);
+    }
+
+    @SmallTest
+    public void testIllegalValues() {
+        // Test NPEs
+        try {
+            new Range<Integer>(null, null);
+            fail("Expected exception to be thrown for (null, null)");
+        } catch (NullPointerException e) {
+            // OK: both args are null
+        }
+
+        try {
+            new Range<Integer>(null, 0);
+            fail("Expected exception to be thrown for (null, 0)");
+        } catch (NullPointerException e) {
+            // OK: left arg is null
+        }
+
+        try {
+            new Range<Integer>(0, null);
+            fail("Expected exception to be thrown for (0, null)");
+        } catch (NullPointerException e) {
+            // OK: right arg is null
+        }
+
+        // Test IAEs
+
+        try {
+            new Range<Integer>(50, -50);
+            fail("Expected exception to be thrown for (50, -50)");
+        } catch (IllegalArgumentException e) {
+            // OK: 50 > -50 so it fails
+        }
+
+        try {
+            new Range<Float>(0.0f, Float.NEGATIVE_INFINITY);
+            fail("Expected exception to be thrown for (0.0f, -Infinity)");
+        } catch (IllegalArgumentException e) {
+            // OK: 0.0f is > NEGATIVE_INFINITY, so it fails
+        }
+    }
+
+    @SmallTest
+    public void testEquals() {
+        Range<Float> oneHalf = Range.create(1.0f, 2.0f);
+        Range<Float> oneHalf2 = new Range<Float>(1.0f, 2.0f);
+        assertEquals(oneHalf, oneHalf2);
+        assertHashCodeEquals(oneHalf, oneHalf2);
+
+        Range<Float> twoThirds = new Range<Float>(2.0f, 3.0f);
+        Range<Float> twoThirds2 = Range.create(2.0f, 3.0f);
+        assertEquals(twoThirds, twoThirds2);
+        assertHashCodeEquals(twoThirds, twoThirds2);
+
+        Range<Rational> negativeOneTenthPositiveOneTenth =
+                new Range<Rational>(new Rational(-1, 10), new Rational(1, 10));
+        Range<Rational> negativeOneTenthPositiveOneTenth2 =
+                Range.create(new Rational(-1, 10), new Rational(1, 10));
+        assertEquals(negativeOneTenthPositiveOneTenth, negativeOneTenthPositiveOneTenth2);
+        assertHashCodeEquals(negativeOneTenthPositiveOneTenth, negativeOneTenthPositiveOneTenth2);
+    }
+
+    @SmallTest
+    public void testInRange() {
+        Range<Integer> hundredOneTwo = Range.create(100, 200);
+
+        assertInRange(hundredOneTwo, 100);
+        assertInRange(hundredOneTwo, 200);
+        assertInRange(hundredOneTwo, 150);
+        assertOutOfRange(hundredOneTwo, 99);
+        assertOutOfRange(hundredOneTwo, 201);
+        assertOutOfRange(hundredOneTwo, 100000);
+
+        Range<Float> infinities = Range.create(Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY);
+
+        assertInRange(infinities, Float.NEGATIVE_INFINITY);
+        assertInRange(infinities, Float.POSITIVE_INFINITY);
+        assertInRange(infinities, 0.0f);
+        assertOutOfRange(infinities, Float.NaN);
+
+        Range<Rational> negativeOneTenthPositiveOneTenth =
+                new Range<Rational>(new Rational(-1, 10), new Rational(1, 10));
+        assertInRange(negativeOneTenthPositiveOneTenth, new Rational(-1, 10));
+        assertInRange(negativeOneTenthPositiveOneTenth, new Rational(1, 10));
+        assertInRange(negativeOneTenthPositiveOneTenth, Rational.ZERO);
+        assertOutOfRange(negativeOneTenthPositiveOneTenth, new Rational(-100, 1));
+        assertOutOfRange(negativeOneTenthPositiveOneTenth, new Rational(100, 1));
+    }
+
+    private static <T extends Comparable<? super T>> void assertInRange(Range<T> object, T needle) {
+        assertAction("in-range", object, needle, true, object.inRange(needle));
+    }
+
+    private static <T extends Comparable<? super T>> void assertOutOfRange(Range<T> object,
+            T needle) {
+        assertAction("out-of-range", object, needle, false, object.inRange(needle));
+    }
+
+    private static <T extends Comparable<? super T>> void assertUpper(Range<T> object, T expected) {
+        assertAction("upper", object, expected, object.getUpper());
+    }
+
+    private static <T extends Comparable<? super T>> void assertLower(Range<T> object, T expected) {
+        assertAction("lower", object, expected, object.getLower());
+    }
+
+    private static <T, T2> void assertAction(String action, T object, T2 expected,
+            T2 actual) {
+        assertEquals("Expected " + object + " " + action + " to be ",
+                expected, actual);
+    }
+
+    private static <T, T2> void assertAction(String action, T object, T2 needle, boolean expected,
+            boolean actual) {
+        String expectedMessage = expected ? action : ("not " + action);
+        assertEquals("Expected " + needle + " to be " + expectedMessage + " of " + object,
+                expected, actual);
+    }
+
+    private static <T extends Comparable<? super T>> void assertHashCodeEquals(
+            Range<T> left, Range<T> right) {
+        assertEquals("Left hash code for " + left +
+                " expected to be equal to right hash code for " + right,
+                left.hashCode(), right.hashCode());
+    }
+}
diff --git a/tests/tests/util/src/android/util/cts/RationalTest.java b/tests/tests/util/src/android/util/cts/RationalTest.java
new file mode 100644
index 0000000..ab5c063
--- /dev/null
+++ b/tests/tests/util/src/android/util/cts/RationalTest.java
@@ -0,0 +1,492 @@
+/*
+ * Copyright (C) 2014 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.util.cts;
+
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Rational;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.lang.reflect.Field;
+
+import static android.util.Rational.*;
+
+public class RationalTest extends junit.framework.TestCase {
+
+    /** (1,1) */
+    private static final Rational UNIT = new Rational(1, 1);
+
+    @SmallTest
+    public void testConstructor() {
+
+        // Simple case
+        Rational r = new Rational(1, 2);
+        assertEquals(1, r.getNumerator());
+        assertEquals(2, r.getDenominator());
+
+        // Denominator negative
+        r = new Rational(-1, 2);
+        assertEquals(-1, r.getNumerator());
+        assertEquals(2, r.getDenominator());
+
+        // Numerator negative
+        r = new Rational(1, -2);
+        assertEquals(-1, r.getNumerator());
+        assertEquals(2, r.getDenominator());
+
+        // Both negative
+        r = new Rational(-1, -2);
+        assertEquals(1, r.getNumerator());
+        assertEquals(2, r.getDenominator());
+
+        // Infinity.
+        r = new Rational(1, 0);
+        assertEquals(1, r.getNumerator());
+        assertEquals(0, r.getDenominator());
+
+        // Negative infinity.
+        r = new Rational(-1, 0);
+        assertEquals(-1, r.getNumerator());
+        assertEquals(0, r.getDenominator());
+
+        // NaN.
+        r = new Rational(0, 0);
+        assertEquals(0, r.getNumerator());
+        assertEquals(0, r.getDenominator());
+    }
+
+    @SmallTest
+    public void testEquals() {
+        Rational r = new Rational(1, 2);
+        assertEquals(1, r.getNumerator());
+        assertEquals(2, r.getDenominator());
+
+        assertEquals(r, r);
+        assertFalse(r.equals(null));
+        assertFalse(r.equals(new Object()));
+
+        Rational twoThirds = new Rational(2, 3);
+        assertFalse(r.equals(twoThirds));
+        assertFalse(twoThirds.equals(r));
+
+        Rational fourSixths = new Rational(4, 6);
+        assertEquals(twoThirds, fourSixths);
+        assertEquals(fourSixths, twoThirds);
+
+        Rational moreComplicated = new Rational(5*6*7*8*9, 1*2*3*4*5);
+        Rational moreComplicated2 = new Rational(5*6*7*8*9*78, 1*2*3*4*5*78);
+        assertEquals(moreComplicated, moreComplicated2);
+        assertEquals(moreComplicated2, moreComplicated);
+
+        // Ensure negatives are fine
+        twoThirds = new Rational(-2, 3);
+        fourSixths = new Rational(-4, 6);
+        assertEquals(twoThirds, fourSixths);
+        assertEquals(fourSixths, twoThirds);
+
+        moreComplicated = new Rational(-5*6*7*8*9, 1*2*3*4*5);
+        moreComplicated2 = new Rational(-5*6*7*8*9*78, 1*2*3*4*5*78);
+        assertEquals(moreComplicated, moreComplicated2);
+        assertEquals(moreComplicated2, moreComplicated);
+
+        // Zero is always equal to itself
+        Rational zero2 = new Rational(0, 100);
+        assertEquals(ZERO, zero2);
+        assertEquals(zero2, ZERO);
+
+        // NaN is always equal to itself
+        Rational nan = NaN;
+        Rational nan2 = new Rational(0, 0);
+        assertTrue(nan.equals(nan));
+        assertTrue(nan.equals(nan2));
+        assertTrue(nan2.equals(nan));
+        assertFalse(nan.equals(r));
+        assertFalse(r.equals(nan));
+
+        // Infinities of the same sign are equal.
+        Rational posInf = POSITIVE_INFINITY;
+        Rational posInf2 = new Rational(2, 0);
+        Rational negInf = NEGATIVE_INFINITY;
+        Rational negInf2 = new Rational(-2, 0);
+        assertEquals(posInf, posInf);
+        assertEquals(negInf, negInf);
+        assertEquals(posInf, posInf2);
+        assertEquals(negInf, negInf2);
+
+        // Infinities aren't equal to anything else.
+        assertFalse(posInf.equals(negInf));
+        assertFalse(negInf.equals(posInf));
+        assertFalse(negInf.equals(r));
+        assertFalse(posInf.equals(r));
+        assertFalse(r.equals(negInf));
+        assertFalse(r.equals(posInf));
+        assertFalse(posInf.equals(nan));
+        assertFalse(negInf.equals(nan));
+        assertFalse(nan.equals(posInf));
+        assertFalse(nan.equals(negInf));
+    }
+
+    @SmallTest
+    public void testReduction() {
+        Rational moreComplicated = new Rational(5 * 78, 7 * 78);
+        assertEquals(new Rational(5, 7), moreComplicated);
+        assertEquals(5, moreComplicated.getNumerator());
+        assertEquals(7, moreComplicated.getDenominator());
+
+        Rational posInf = new Rational(5, 0);
+        assertEquals(1, posInf.getNumerator());
+        assertEquals(0, posInf.getDenominator());
+        assertEquals(POSITIVE_INFINITY, posInf);
+
+        Rational negInf = new Rational(-100, 0);
+        assertEquals(-1, negInf.getNumerator());
+        assertEquals(0, negInf.getDenominator());
+        assertEquals(NEGATIVE_INFINITY, negInf);
+
+        Rational zero = new Rational(0, -100);
+        assertEquals(0, zero.getNumerator());
+        assertEquals(1, zero.getDenominator());
+        assertEquals(ZERO, zero);
+
+        Rational flipSigns = new Rational(1, -1);
+        assertEquals(-1, flipSigns.getNumerator());
+        assertEquals(1, flipSigns.getDenominator());
+
+        Rational flipAndReduce = new Rational(100, -200);
+        assertEquals(-1, flipAndReduce.getNumerator());
+        assertEquals(2, flipAndReduce.getDenominator());
+    }
+
+    @SmallTest
+    public void testCompareTo() {
+        // unit is equal to itself
+        assertCompareEquals(UNIT, new Rational(1, 1));
+
+        // NaN is greater than anything but NaN
+        assertCompareEquals(NaN, new Rational(0, 0));
+        assertGreaterThan(NaN, UNIT);
+        assertGreaterThan(NaN, POSITIVE_INFINITY);
+        assertGreaterThan(NaN, NEGATIVE_INFINITY);
+        assertGreaterThan(NaN, ZERO);
+
+        // Positive infinity is greater than any other non-NaN
+        assertCompareEquals(POSITIVE_INFINITY, new Rational(1, 0));
+        assertGreaterThan(POSITIVE_INFINITY, UNIT);
+        assertGreaterThan(POSITIVE_INFINITY, NEGATIVE_INFINITY);
+        assertGreaterThan(POSITIVE_INFINITY, ZERO);
+
+        // Negative infinity is smaller than any other non-NaN
+        assertCompareEquals(NEGATIVE_INFINITY, new Rational(-1, 0));
+        assertLessThan(NEGATIVE_INFINITY, UNIT);
+        assertLessThan(NEGATIVE_INFINITY, POSITIVE_INFINITY);
+        assertLessThan(NEGATIVE_INFINITY, ZERO);
+
+        // A finite number with the same denominator is trivially comparable
+        assertGreaterThan(new Rational(3, 100), new Rational(1, 100));
+        assertGreaterThan(new Rational(3, 100), ZERO);
+
+        // Compare finite numbers with different divisors
+        assertGreaterThan(new Rational(5, 25), new Rational(1, 10));
+        assertGreaterThan(new Rational(5, 25), ZERO);
+
+        // Compare finite numbers with different signs
+        assertGreaterThan(new Rational(5, 25), new Rational(-1, 10));
+        assertLessThan(new Rational(-5, 25), ZERO);
+    }
+
+    @SmallTest
+    public void testConvenienceMethods() {
+        // isFinite
+        assertFinite(ZERO, true);
+        assertFinite(NaN, false);
+        assertFinite(NEGATIVE_INFINITY, false);
+        assertFinite(POSITIVE_INFINITY, false);
+        assertFinite(UNIT, true);
+
+        // isInfinite
+        assertInfinite(ZERO, false);
+        assertInfinite(NaN, false);
+        assertInfinite(NEGATIVE_INFINITY, true);
+        assertInfinite(POSITIVE_INFINITY, true);
+        assertInfinite(UNIT, false);
+
+        // isNaN
+        assertNaN(ZERO, false);
+        assertNaN(NaN, true);
+        assertNaN(NEGATIVE_INFINITY, false);
+        assertNaN(POSITIVE_INFINITY, false);
+        assertNaN(UNIT, false);
+
+        // isZero
+        assertZero(ZERO, true);
+        assertZero(NaN, false);
+        assertZero(NEGATIVE_INFINITY, false);
+        assertZero(POSITIVE_INFINITY, false);
+        assertZero(UNIT, false);
+    }
+
+    @SmallTest
+    public void testValueConversions() {
+        // Unit, simple case
+        assertValueEquals(UNIT, 1.0f);
+        assertValueEquals(UNIT, 1.0);
+        assertValueEquals(UNIT, 1L);
+        assertValueEquals(UNIT, 1);
+        assertValueEquals(UNIT, (short)1);
+
+        // Zero, simple case
+        assertValueEquals(ZERO, 0.0f);
+        assertValueEquals(ZERO, 0.0);
+        assertValueEquals(ZERO, 0L);
+        assertValueEquals(ZERO, 0);
+        assertValueEquals(ZERO, (short)0);
+
+        // NaN is 0 for integers, not-a-number for floating point
+        assertValueEquals(NaN, Float.NaN);
+        assertValueEquals(NaN, Double.NaN);
+        assertValueEquals(NaN, 0L);
+        assertValueEquals(NaN, 0);
+        assertValueEquals(NaN, (short)0);
+
+        // Positive infinity, saturates upwards for integers
+        assertValueEquals(POSITIVE_INFINITY, Float.POSITIVE_INFINITY);
+        assertValueEquals(POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
+        assertValueEquals(POSITIVE_INFINITY, Long.MAX_VALUE);
+        assertValueEquals(POSITIVE_INFINITY, Integer.MAX_VALUE);
+        assertValueEquals(POSITIVE_INFINITY, (short)-1);
+
+        // Negative infinity, saturates downwards for integers
+        assertValueEquals(NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY);
+        assertValueEquals(NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY);
+        assertValueEquals(NEGATIVE_INFINITY, Long.MIN_VALUE);
+        assertValueEquals(NEGATIVE_INFINITY, Integer.MIN_VALUE);
+        assertValueEquals(NEGATIVE_INFINITY, (short)0);
+
+        // Normal finite values, round down for integers
+        final Rational oneQuarter = new Rational(1, 4);
+        assertValueEquals(oneQuarter, 1.0f / 4.0f);
+        assertValueEquals(oneQuarter, 1.0 / 4.0);
+        assertValueEquals(oneQuarter, 0L);
+        assertValueEquals(oneQuarter, 0);
+        assertValueEquals(oneQuarter, (short)0);
+
+        final Rational nineFifths = new Rational(9, 5);
+        assertValueEquals(nineFifths, 9.0f / 5.0f);
+        assertValueEquals(nineFifths, 9.0 / 5.0);
+        assertValueEquals(nineFifths, 1L);
+        assertValueEquals(nineFifths, 1);
+        assertValueEquals(nineFifths, (short)1);
+
+        final Rational negativeHundred = new Rational(-1000, 10);
+        assertValueEquals(negativeHundred, -100.f / 1.f);
+        assertValueEquals(negativeHundred, -100.0 / 1.0);
+        assertValueEquals(negativeHundred, -100L);
+        assertValueEquals(negativeHundred, -100);
+        assertValueEquals(negativeHundred, (short)-100);
+
+        // Short truncates if the result is too large
+        assertValueEquals(new Rational(Integer.MAX_VALUE, 1), (short)Integer.MAX_VALUE);
+        assertValueEquals(new Rational(0x00FFFFFF, 1), (short)0x00FFFFFF);
+        assertValueEquals(new Rational(0x00FF00FF, 1), (short)0x00FF00FF);
+    }
+
+    @SmallTest
+    public void testSerialize() throws ClassNotFoundException, IOException {
+        /*
+         * Check correct [de]serialization
+         */
+        assertEqualsAfterSerializing(ZERO);
+        assertEqualsAfterSerializing(NaN);
+        assertEqualsAfterSerializing(NEGATIVE_INFINITY);
+        assertEqualsAfterSerializing(POSITIVE_INFINITY);
+        assertEqualsAfterSerializing(UNIT);
+        assertEqualsAfterSerializing(new Rational(100, 200));
+        assertEqualsAfterSerializing(new Rational(-100, 200));
+        assertEqualsAfterSerializing(new Rational(5, 1));
+        assertEqualsAfterSerializing(new Rational(Integer.MAX_VALUE, Integer.MIN_VALUE));
+
+        /*
+         * Check bad deserialization fails
+         */
+        try {
+            Rational badZero = createIllegalRational(0, 100); // [0, 100] , should be [0, 1]
+            Rational results = serializeRoundTrip(badZero);
+            fail("Deserializing " + results + " should not have succeeded");
+        } catch (InvalidObjectException e) {
+            // OK
+        }
+
+        try {
+            Rational badPosInfinity = createIllegalRational(100, 0); // [100, 0] , should be [1, 0]
+            Rational results = serializeRoundTrip(badPosInfinity);
+            fail("Deserializing " + results + " should not have succeeded");
+        } catch (InvalidObjectException e) {
+            // OK
+        }
+
+        try {
+            Rational badNegInfinity =
+                    createIllegalRational(-100, 0); // [-100, 0] , should be [-1, 0]
+            Rational results = serializeRoundTrip(badNegInfinity);
+            fail("Deserializing " + results + " should not have succeeded");
+        } catch (InvalidObjectException e) {
+            // OK
+        }
+
+        try {
+            Rational badReduced = createIllegalRational(2, 4); // [2,4] , should be [1, 2]
+            Rational results = serializeRoundTrip(badReduced);
+            fail("Deserializing " + results + " should not have succeeded");
+        } catch (InvalidObjectException e) {
+            // OK
+        }
+
+        try {
+            Rational badReducedNeg = createIllegalRational(-2, 4); // [-2, 4] should be [-1, 2]
+            Rational results = serializeRoundTrip(badReducedNeg);
+            fail("Deserializing " + results + " should not have succeeded");
+        } catch (InvalidObjectException e) {
+            // OK
+        }
+    }
+
+    private static void assertValueEquals(Rational object, float expected) {
+        assertEquals("Checking floatValue() for " + object + ";",
+                expected, object.floatValue());
+    }
+
+    private static void assertValueEquals(Rational object, double expected) {
+        assertEquals("Checking doubleValue() for " + object + ";",
+                expected, object.doubleValue());
+    }
+
+    private static void assertValueEquals(Rational object, long expected) {
+        assertEquals("Checking longValue() for " + object + ";",
+                expected, object.longValue());
+    }
+
+    private static void assertValueEquals(Rational object, int expected) {
+        assertEquals("Checking intValue() for " + object + ";",
+                expected, object.intValue());
+    }
+
+    private static void assertValueEquals(Rational object, short expected) {
+        assertEquals("Checking shortValue() for " + object + ";",
+                expected, object.shortValue());
+    }
+
+    private static void assertFinite(Rational object, boolean expected) {
+        assertAction("finite", object, expected, object.isFinite());
+    }
+
+    private static void assertInfinite(Rational object, boolean expected) {
+        assertAction("infinite", object, expected, object.isInfinite());
+    }
+
+    private static void assertNaN(Rational object, boolean expected) {
+        assertAction("NaN", object, expected, object.isNaN());
+    }
+
+    private static void assertZero(Rational object, boolean expected) {
+        assertAction("zero", object, expected, object.isZero());
+    }
+
+    private static <T> void assertAction(String action, T object, boolean expected,
+            boolean actual) {
+        String expectedMessage = expected ? action : ("not " + action);
+        assertEquals("Expected " + object + " to be " + expectedMessage,
+                expected, actual);
+    }
+
+    private static <T extends Comparable<? super T>> void assertLessThan(T left, T right) {
+        assertTrue("Expected (LR) left " + left + " to be less than right " + right,
+                left.compareTo(right) < 0);
+        assertTrue("Expected (RL) left " + left + " to be less than right " + right,
+                right.compareTo(left) > 0);
+    }
+
+    private static <T extends Comparable<? super T>> void assertGreaterThan(T left, T right) {
+        assertTrue("Expected (LR) left " + left + " to be greater than right " + right,
+                left.compareTo(right) > 0);
+        assertTrue("Expected (RL) left " + left + " to be greater than right " + right,
+                right.compareTo(left) < 0);
+    }
+
+    private static <T extends Comparable<? super T>> void assertCompareEquals(T left, T right) {
+        assertTrue("Expected (LR) left " + left + " to be compareEquals to right " + right,
+                left.compareTo(right) == 0);
+        assertTrue("Expected (RL) left " + left + " to be compareEquals to right " + right,
+                right.compareTo(left) == 0);
+    }
+
+    private static <T extends Serializable> byte[] serialize(T obj) throws IOException {
+        ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
+        try (ObjectOutputStream objectStream = new ObjectOutputStream(byteStream)) {
+            objectStream.writeObject(obj);
+        }
+        return byteStream.toByteArray();
+    }
+
+    private static <T extends Serializable> T deserialize(byte[] array, Class<T> klass)
+            throws IOException, ClassNotFoundException {
+        ByteArrayInputStream bais = new ByteArrayInputStream(array);
+        ObjectInputStream ois = new ObjectInputStream(bais);
+        Object obj = ois.readObject();
+        return klass.cast(obj);
+    }
+
+    @SuppressWarnings("unchecked")
+    private static <T extends Serializable> T serializeRoundTrip(T obj)
+            throws IOException, ClassNotFoundException {
+        Class<T> klass = (Class<T>) obj.getClass();
+        byte[] arr = serialize(obj);
+        T serialized = deserialize(arr, klass);
+        return serialized;
+    }
+
+    private static <T extends Serializable> void assertEqualsAfterSerializing(T obj)
+            throws ClassNotFoundException, IOException {
+        T serialized = serializeRoundTrip(obj);
+        assertEquals("Expected values to be equal after serialization round-trip", obj, serialized);
+    }
+
+    private static Rational createIllegalRational(int numerator, int denominator) {
+        Rational r = new Rational(numerator, denominator);
+        mutateField(r, "mNumerator", numerator);
+        mutateField(r, "mDenominator", denominator);
+        return r;
+    }
+
+    private static <T> void mutateField(T object, String name, int value) {
+        try {
+            Field f = object.getClass().getDeclaredField(name);
+            f.setAccessible(true);
+            f.set(object, value);
+        } catch (NoSuchFieldException e) {
+            throw new AssertionError(e);
+        } catch (IllegalAccessException e) {
+            throw new AssertionError(e);
+        } catch (IllegalArgumentException e) {
+            throw new AssertionError(e);
+        }
+    }
+}
diff --git a/tests/tests/view/src/android/view/inputmethod/cts/InputMethodInfoTest.java b/tests/tests/view/src/android/view/inputmethod/cts/InputMethodInfoTest.java
index b4d65a5..1a067b4 100644
--- a/tests/tests/view/src/android/view/inputmethod/cts/InputMethodInfoTest.java
+++ b/tests/tests/view/src/android/view/inputmethod/cts/InputMethodInfoTest.java
@@ -197,6 +197,11 @@
     }
 
     public void testInputMethodSubtypesOfSystemImes() {
+        if (!getContext().getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_INPUT_METHODS)) {
+            return;
+        }
+
         final InputMethodManager imm = (InputMethodManager) mContext
                 .getSystemService(Context.INPUT_METHOD_SERVICE);
         final List<InputMethodInfo> imis = imm.getInputMethodList();
diff --git a/tests/tests/view/src/android/view/inputmethod/cts/InputMethodManagerTest.java b/tests/tests/view/src/android/view/inputmethod/cts/InputMethodManagerTest.java
index 46f58e6..033deb2 100644
--- a/tests/tests/view/src/android/view/inputmethod/cts/InputMethodManagerTest.java
+++ b/tests/tests/view/src/android/view/inputmethod/cts/InputMethodManagerTest.java
@@ -19,6 +19,7 @@
 
 import android.app.Instrumentation;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.cts.util.PollingCheck;
 import android.os.Handler;
 import android.os.IBinder;
@@ -58,6 +59,11 @@
     }
 
     public void testInputMethodManager() throws Throwable {
+        if (!getActivity().getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_INPUT_METHODS)) {
+            return;
+        }
+
         Window window = mActivity.getWindow();
         final EditText view = (EditText) window.findViewById(R.id.entry);
 
diff --git a/tests/tests/webkit/src/android/webkit/cts/CookieSyncManagerTest.java b/tests/tests/webkit/src/android/webkit/cts/CookieSyncManagerTest.java
index e2112b7..95e3add 100644
--- a/tests/tests/webkit/src/android/webkit/cts/CookieSyncManagerTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/CookieSyncManagerTest.java
@@ -33,7 +33,7 @@
     }
 
     public void testCookieSyncManager() throws Exception {
-        if (!NullWebViewUtils.isWebViewAvailable()) {
+        if (getActivity().getWebView() == null) {
             return;
         }
         CookieSyncManager csm1 = CookieSyncManager.createInstance(getActivity());
diff --git a/tests/tests/webkit/src/android/webkit/cts/CookieTest.java b/tests/tests/webkit/src/android/webkit/cts/CookieTest.java
index 704ae24..7f3b183 100644
--- a/tests/tests/webkit/src/android/webkit/cts/CookieTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/CookieTest.java
@@ -36,7 +36,7 @@
     protected void setUp() throws Exception {
         super.setUp();
 
-        if (!NullWebViewUtils.isWebViewAvailable()) {
+        if (getActivity().getWebView() == null) {
             return;
         }
 
diff --git a/tests/tests/widget/src/android/widget/cts/FrameLayoutTest.java b/tests/tests/widget/src/android/widget/cts/FrameLayoutTest.java
index 5b225e8..6564ce0 100644
--- a/tests/tests/widget/src/android/widget/cts/FrameLayoutTest.java
+++ b/tests/tests/widget/src/android/widget/cts/FrameLayoutTest.java
@@ -156,7 +156,7 @@
         // text view and button are VISIBLE, they should be measured
         final TextView textView = (TextView) frameLayout.findViewById(R.id.framelayout_textview);
         compareScaledPixels(30, textView.getMeasuredHeight());
-        compareScaledPixels(100, textView.getMeasuredWidth());
+        compareScaledPixels(60, textView.getMeasuredWidth());
         assertEquals(textView.getMeasuredHeight(), frameLayout.getMeasuredHeight());
         assertEquals(textView.getMeasuredWidth(), frameLayout.getMeasuredWidth());
 
diff --git a/tests/tests/widget/src/android/widget/cts/VideoViewTest.java b/tests/tests/widget/src/android/widget/cts/VideoViewTest.java
index 679a298..c8d9fc7 100644
--- a/tests/tests/widget/src/android/widget/cts/VideoViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/VideoViewTest.java
@@ -18,16 +18,18 @@
 
 import com.android.cts.stub.R;
 
-
 import android.app.Activity;
 import android.app.Instrumentation;
 import android.content.Context;
 import android.cts.util.PollingCheck;
+import android.media.MediaCodecInfo;
+import android.media.MediaCodecList;
 import android.media.MediaPlayer;
 import android.media.MediaPlayer.OnCompletionListener;
 import android.media.MediaPlayer.OnErrorListener;
 import android.media.MediaPlayer.OnPreparedListener;
 import android.test.ActivityInstrumentationTestCase2;
+import android.util.Log;
 import android.view.View.MeasureSpec;
 import android.widget.MediaController;
 import android.widget.VideoView;
@@ -40,6 +42,8 @@
  * Test {@link VideoView}.
  */
 public class VideoViewTest extends ActivityInstrumentationTestCase2<VideoViewStubActivity> {
+    /** Debug TAG. **/
+    private static final String TAG = "VideoViewTest";
     /** The maximum time to wait for an operation. */
     private static final long   TIME_OUT = 15000L;
     /** The interval time to wait for completing an operation. */
@@ -48,6 +52,8 @@
     private static final int    TEST_VIDEO_DURATION = 11047;
     /** The full name of R.raw.testvideo. */
     private static final String VIDEO_NAME   = "testvideo.3gp";
+    /** The MIME type. */
+    private static final String MIME_TYPE = "video/3gpp";
     /** delta for duration in case user uses different decoders on different
         hardware that report a duration that's different by a few milliseconds */
     private static final int DURATION_DELTA = 100;
@@ -95,6 +101,28 @@
         }
     }
 
+    // TODO: Make a public method selectCodec() in common libraries (e.g. cts/libs/), to avoid
+    // redundant function definitions in this and other media related test files.
+    private static boolean hasCodec(String mimeType) {
+        int numCodecs = MediaCodecList.getCodecCount();
+
+        for (int i = 0; i < numCodecs; i++) {
+            MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
+
+            if (!codecInfo.isEncoder()) {
+                continue;
+            }
+
+            String[] types = codecInfo.getSupportedTypes();
+            for (int j = 0; j < types.length; j++) {
+                if (types[j].equalsIgnoreCase(mimeType)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
     /**
      * Instantiates a new video view test.
      */
@@ -165,6 +193,12 @@
     }
 
     public void testPlayVideo1() throws Throwable {
+        // Don't run the test if the codec isn't supported.
+        if (!hasCodec(MIME_TYPE)) {
+            Log.w(TAG, "Codec " + MIME_TYPE + " not supported. Return from testPlayVideo1.");
+            return;
+        }
+
         final MockOnPreparedListener preparedListener = new MockOnPreparedListener();
         mVideoView.setOnPreparedListener(preparedListener);
         final MockOnCompletionListener completionListener = new MockOnCompletionListener();
@@ -219,6 +253,12 @@
     }
 
     public void testGetBufferPercentage() throws Throwable {
+        // Don't run the test if the codec isn't supported.
+        if (!hasCodec(MIME_TYPE)) {
+            Log.w(TAG, MIME_TYPE + " not supported. Return from testGetBufferPercentage.");
+            return;
+        }
+
         final MockOnPreparedListener prepareListener = new MockOnPreparedListener();
         mVideoView.setOnPreparedListener(prepareListener);
 
@@ -255,6 +295,12 @@
     }
 
     public void testGetDuration() throws Throwable {
+        // Don't run the test if the codec isn't supported.
+        if (!hasCodec(MIME_TYPE)) {
+            Log.w(TAG, "Codec " + MIME_TYPE + " not supported. Return from testGetDuration.");
+            return;
+        }
+
         runTestOnUiThread(new Runnable() {
             public void run() {
                 mVideoView.setVideoPath(mVideoPath);
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values-watch/styles.xml b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values-watch/styles.xml
new file mode 100644
index 0000000..1d904c2
--- /dev/null
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values-watch/styles.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ * Copyright (C) 2011 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.
+ -->
+<resources>
+
+    <style name="AppTheme" parent="android:Theme.Holo.Light.NoActionBar" />
+
+</resources>
\ No newline at end of file
diff --git a/tools/cts-java-scanner-doclet/src/com/android/cts/javascannerdoclet/CtsJavaScannerDoclet.java b/tools/cts-java-scanner-doclet/src/com/android/cts/javascannerdoclet/CtsJavaScannerDoclet.java
index 40a3d05..f54ba00 100644
--- a/tools/cts-java-scanner-doclet/src/com/android/cts/javascannerdoclet/CtsJavaScannerDoclet.java
+++ b/tools/cts-java-scanner-doclet/src/com/android/cts/javascannerdoclet/CtsJavaScannerDoclet.java
@@ -61,6 +61,8 @@
  */
 public class CtsJavaScannerDoclet extends Doclet {
 
+    private static final String JUNIT4_TEST_ANNOTATION = "org.junit.Test";
+
     static final String JUNIT_TEST_CASE_CLASS_NAME = "junit.framework.testcase";
 
     public static boolean start(RootDoc root) {
@@ -72,31 +74,61 @@
         PrintWriter writer = new PrintWriter(System.out);
 
         for (ClassDoc clazz : classes) {
-            if (clazz.isAbstract() || !isValidJUnitTestCase(clazz)) {
+            if (clazz.isAbstract()) {
                 continue;
             }
+
+            final boolean isJUnit3 = isJUnit3TestCase(clazz);
+            if (!isJUnit3 && !isJUnit4TestClass(clazz)) {
+                continue;
+            }
+
             writer.append("suite:").println(clazz.containingPackage().name());
             writer.append("case:").println(clazz.name());
             for (; clazz != null; clazz = clazz.superclass()) {
                 for (MethodDoc method : clazz.methods()) {
-                    if (!method.name().startsWith("test")) {
-                        continue;
-                    }
                     int timeout = -1;
-                    AnnotationDesc[] annotations = method.annotations();
-                    for (AnnotationDesc annot : annotations) {
-                        AnnotationTypeDoc atype = annot.annotationType();
-                        if (atype.toString().equals("com.android.cts.util.TimeoutReq")) {
-                            ElementValuePair[] cpairs = annot.elementValues();
-                            for (ElementValuePair pair: cpairs) {
-                                AnnotationTypeElementDoc elem = pair.element();
-                                AnnotationValue value = pair.value();
-                                if (elem.name().equals("minutes")) {
-                                    timeout = ((Integer)value.value());
+                    if (isJUnit3) {
+                        if (!method.name().startsWith("test")) {
+                            continue;
+                        }
+
+                        AnnotationDesc[] annotations = method.annotations();
+                        for (AnnotationDesc annot : annotations) {
+                            String atype = annot.annotationType().toString();
+                            if (atype.equals("android.cts.util.TimeoutReq")) {
+                                ElementValuePair[] cpairs = annot.elementValues();
+                                for (ElementValuePair pair : cpairs) {
+                                    AnnotationTypeElementDoc elem = pair.element();
+                                    AnnotationValue value = pair.value();
+                                    if (elem.name().equals("minutes")) {
+                                        timeout = ((Integer) value.value());
+                                    }
                                 }
                             }
                         }
+                    } else {
+                        /* JUnit4 */
+                        boolean isTest = false;
+
+                        for (AnnotationDesc annot : method.annotations()) {
+                            if (annot.annotationType().toString().equals(JUNIT4_TEST_ANNOTATION)) {
+                                isTest = true;
+
+                                for (ElementValuePair pair : annot.elementValues()) {
+                                    if (pair.element().name().equals("timeout")) {
+                                        /* JUnit4 timeouts are in milliseconds. */
+                                        timeout = (int) (((Long) pair.value().value()) / 60000L);
+                                    }
+                                }
+                            }
+                        }
+
+                        if (!isTest) {
+                            continue;
+                        }
                     }
+
                     writer.append("test:");
                     if (timeout >= 0) {
                         writer.append(method.name()).println(":" + timeout);
@@ -111,7 +143,7 @@
         return true;
     }
 
-    private static boolean isValidJUnitTestCase(ClassDoc clazz) {
+    private static boolean isJUnit3TestCase(ClassDoc clazz) {
         while((clazz = clazz.superclass()) != null) {
             if (JUNIT_TEST_CASE_CLASS_NAME.equals(clazz.qualifiedName().toLowerCase())) {
                 return true;
@@ -119,4 +151,15 @@
         }
         return false;
     }
+
+    private static boolean isJUnit4TestClass(ClassDoc clazz) {
+        for (MethodDoc method : clazz.methods()) {
+            for (AnnotationDesc annot : method.annotations()) {
+                if (annot.annotationType().toString().equals(JUNIT4_TEST_ANNOTATION)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
 }
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/result/CtsXmlResultReporter.java b/tools/tradefed-host/src/com/android/cts/tradefed/result/CtsXmlResultReporter.java
index ae22613..f6e10d0 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/result/CtsXmlResultReporter.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/result/CtsXmlResultReporter.java
@@ -26,12 +26,14 @@
 import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.build.IFolderBuildInfo;
 import com.android.tradefed.config.Option;
+import com.android.tradefed.config.Option.Importance;
 import com.android.tradefed.log.LogUtil.CLog;
 import com.android.tradefed.result.ITestInvocationListener;
 import com.android.tradefed.result.InputStreamSource;
 import com.android.tradefed.result.LogDataType;
 import com.android.tradefed.result.LogFileSaver;
 import com.android.tradefed.result.TestSummary;
+import com.android.tradefed.util.AbiFormatter;
 import com.android.tradefed.util.FileUtil;
 import com.android.tradefed.util.StreamUtil;
 
@@ -101,6 +103,11 @@
 
     private static final Pattern mCtsLogPattern = Pattern.compile("(.*)\\+\\+\\+\\+(.*)");
 
+    @Option(name = AbiFormatter.FORCE_ABI_STRING,
+            description = AbiFormatter.FORCE_ABI_DESCRIPTION,
+            importance = Importance.IF_UNSET)
+    private String mForceAbi = null;
+
     public void setReportDir(File reportDir) {
         mReportDir = reportDir;
     }
@@ -367,7 +374,9 @@
         serializer.attribute(ns, "endtime", endTime);
         serializer.attribute(ns, "version", CTS_RESULT_FILE_VERSION);
         serializer.attribute(ns, "suite", mSuiteName);
-
+        if (mForceAbi != null) {
+            serializer.attribute(ns, "abi", mForceAbi);
+        }
         mResults.serialize(serializer);
         // TODO: not sure why, but the serializer doesn't like this statement
         //serializer.endTag(ns, RESULT_TAG);
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 2f35266..de868d1 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
@@ -26,6 +26,7 @@
 import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.config.ConfigurationException;
 import com.android.tradefed.config.Option;
+import com.android.tradefed.config.OptionSetter;
 import com.android.tradefed.config.Option.Importance;
 import com.android.tradefed.config.OptionCopier;
 import com.android.tradefed.device.DeviceNotAvailableException;
@@ -41,6 +42,7 @@
 import com.android.tradefed.testtype.IRemoteTest;
 import com.android.tradefed.testtype.IResumableTest;
 import com.android.tradefed.testtype.IShardableTest;
+import com.android.tradefed.util.AbiFormatter;
 import com.android.tradefed.util.RunUtil;
 import com.android.tradefed.util.xml.AbstractXmlParser.ParseException;
 
@@ -63,6 +65,7 @@
 import java.util.Queue;
 import java.util.Set;
 
+
 /**
  * A {@link Test} for running CTS tests.
  * <p/>
@@ -158,6 +161,11 @@
             "performant.")
     private boolean mLogcatOnFailures = false;
 
+    @Option(name = AbiFormatter.FORCE_ABI_STRING,
+            description = AbiFormatter.FORCE_ABI_DESCRIPTION,
+            importance = Importance.IF_UNSET)
+    private String mForceAbi = null;
+
     @Option(name = "logcat-on-failure-size", description =
             "The max number of logcat data in bytes to capture when --logcat-on-failure is on. " +
             "Should be an amount that can comfortably fit in memory.")
@@ -439,11 +447,35 @@
                 TestPackage knownTests = mRemainingTestPkgs.get(0);
 
                 IRemoteTest test = knownTests.getTestForPackage();
+
+                if (mForceAbi != null) {
+                    OptionSetter optionSetter = null;
+                    boolean hasField = false;
+                    try {
+                        optionSetter = new OptionSetter(test);
+                        if (optionSetter.getTypeForOption(AbiFormatter.FORCE_ABI_STRING)
+                                .equals("string")) {
+                            hasField = true;
+                        }
+                    } catch (ConfigurationException e) {
+                        // ignore if there are tests not taking force-abi option
+                        // for example native test do not need this option.
+                    }
+                    if (hasField) {
+                        try{
+                            optionSetter.setOptionValue(AbiFormatter.FORCE_ABI_STRING, mForceAbi);
+                        } catch (ConfigurationException e) {
+                            CLog.e(e);
+                            throw new RuntimeException(e);
+                        }
+                    }
+                }
+
                 if (test instanceof IDeviceTest) {
-                    ((IDeviceTest)test).setDevice(getDevice());
+                    ((IDeviceTest) test).setDevice(getDevice());
                 }
                 if (test instanceof IBuildReceiver) {
-                    ((IBuildReceiver)test).setBuild(mBuildInfo);
+                    ((IBuildReceiver) test).setBuild(mBuildInfo);
                 }
 
                 forwardPackageDetails(knownTests.getPackageDef(), listener);
@@ -700,7 +732,15 @@
         for (String apkName : prerequisiteApks) {
             try {
                 File apkFile = mCtsBuild.getTestApp(apkName);
-                String errorCode = getDevice().installPackage(apkFile, true);
+                String errorCode = null;
+                String[] options = {};
+                if (mForceAbi != null) {
+                    String abi = AbiFormatter.getDefaultAbi(getDevice(), mForceAbi);
+                    if (abi != null) {
+                        options = new String[]{String.format("--abi %s ", abi)};
+                    }
+                }
+                errorCode = getDevice().installPackage(apkFile, true, options);
                 if (errorCode != null) {
                     CLog.e("Failed to install %s. Reason: %s", apkName, errorCode);
                 }
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/InstrumentationApkTest.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/InstrumentationApkTest.java
index 01c3370..ff40154 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/InstrumentationApkTest.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/InstrumentationApkTest.java
@@ -18,13 +18,17 @@
 import com.android.cts.tradefed.build.CtsBuildHelper;
 import com.android.ddmlib.Log;
 import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.config.Option;
+import com.android.tradefed.config.Option.Importance;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.result.ITestInvocationListener;
 import com.android.tradefed.testtype.IBuildReceiver;
 import com.android.tradefed.testtype.InstrumentationTest;
+import com.android.tradefed.util.AbiFormatter;
 
 import junit.framework.Assert;
 
+import java.io.File;
 import java.io.FileNotFoundException;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -43,6 +47,11 @@
 
     private CtsBuildHelper mCtsBuild = null;
 
+    @Option(name = AbiFormatter.FORCE_ABI_STRING,
+            description = AbiFormatter.FORCE_ABI_DESCRIPTION,
+            importance = Importance.IF_UNSET)
+    private String mForceAbi = null;
+
     /**
      * {@inheritDoc}
      */
@@ -75,11 +84,18 @@
             Log.d(LOG_TAG, String.format("Installing %s on %s", apkFileName,
                     getDevice().getSerialNumber()));
             try {
-                String installCode = getDevice().installPackage(mCtsBuild.getTestApp(apkFileName),
-                        true);
+                File apkFile = mCtsBuild.getTestApp(apkFileName);
+                String errorCode = null;
+                String[] options = {};
+                if (mForceAbi != null) {
+                    String abi = AbiFormatter.getDefaultAbi(getDevice(), mForceAbi);
+                    if (abi != null) {
+                        options = new String[]{String.format("--abi %s ", abi)};
+                    }
+                }
+                errorCode = getDevice().installPackage(apkFile, true, options);
                 Assert.assertNull(String.format("Failed to install %s on %s. Reason: %s",
-                        apkFileName, getDevice().getSerialNumber(), installCode), installCode);
-
+                        apkFileName, getDevice().getSerialNumber(), errorCode), errorCode);
             } catch (FileNotFoundException e) {
                 Assert.fail(String.format("Could not find file %s", apkFileName));
             }
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/JarHostTest.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/JarHostTest.java
index 1c59b69..22a016a 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/JarHostTest.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/JarHostTest.java
@@ -19,9 +19,11 @@
 import com.android.ddmlib.Log;
 import com.android.ddmlib.testrunner.TestIdentifier;
 import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.config.ConfigurationException;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.result.ITestInvocationListener;
+
 import com.android.tradefed.testtype.DeviceTestResult.RuntimeDeviceNotAvailableException;
 import com.android.tradefed.testtype.IBuildReceiver;
 import com.android.tradefed.testtype.IDeviceTest;
@@ -188,6 +190,14 @@
     }
 
     /**
+     * setOptions sets options to the tests invoked from this test.
+     * It is used to passing options from JarHostTest to the tests started by JarHostTest.
+     * The default implementation does nothing.
+     */
+    protected void setOptions(Test junitTest) throws ConfigurationException {
+    }
+
+    /**
      * Run test with timeout support.
      */
     private void runTest(TestIdentifier testId, final Test junitTest, final TestResult junitResult) {
@@ -203,6 +213,11 @@
         if (junitTest instanceof IBuildReceiver) {
             ((IBuildReceiver)junitTest).setBuild(mBuildInfo);
         }
+        try {
+            setOptions(junitTest);
+        } catch (ConfigurationException e) {
+            Log.e(LOG_TAG, e.toString());
+        }
         TestRunnable testRunnable = new TestRunnable(junitTest, junitResult);
 
         CommandStatus status = RunUtil.getDefault().runTimed(mTimeoutMs, testRunnable, true);
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/VMHostTest.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/VMHostTest.java
index 0ebdeea..9b4c86d 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/VMHostTest.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/VMHostTest.java
@@ -16,12 +16,19 @@
 package com.android.cts.tradefed.testtype;
 
 import com.android.cts.tradefed.build.CtsBuildHelper;
+import com.android.tradefed.config.ConfigurationException;
+import com.android.tradefed.config.Option;
+import com.android.tradefed.config.Option.Importance;
+import com.android.tradefed.config.OptionSetter;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.log.LogUtil.CLog;
 import com.android.tradefed.result.ITestInvocationListener;
+import com.android.tradefed.util.AbiFormatter;
 import com.android.tradefed.util.FileUtil;
 
+import junit.framework.Test;
+
 import java.io.File;
 import java.io.IOException;
 import java.util.zip.ZipFile;
@@ -35,6 +42,12 @@
     private static final String VM_TEST_TEMP_DIR = "/data/local/tmp/vm-tests";
     private static final String EMULATOR_TEMP_DIR = "/data/local/tmp";
 
+    @Option(name = AbiFormatter.FORCE_ABI_STRING,
+            description = AbiFormatter.FORCE_ABI_DESCRIPTION,
+            importance = Importance.IF_UNSET)
+    private String mForceAbi = null;
+
+
     /**
      * {@inheritDoc}
      */
@@ -95,6 +108,14 @@
         return true;
     }
 
+    @Override
+    protected void setOptions(Test junitTest) throws ConfigurationException{
+        if (mForceAbi != null) {
+            OptionSetter optionSetter = new OptionSetter(junitTest);
+            optionSetter.setOptionValue(AbiFormatter.FORCE_ABI_STRING, mForceAbi);
+        }
+    }
+
     /**
      * Removes temporary file directory from device
      *
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/WrappedGTest.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/WrappedGTest.java
index 74c15f6..78cd6f77 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/WrappedGTest.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/WrappedGTest.java
@@ -19,6 +19,8 @@
 import com.android.cts.tradefed.build.CtsBuildHelper;
 import com.android.ddmlib.testrunner.ITestRunListener;
 import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.config.Option;
+import com.android.tradefed.config.Option.Importance;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.log.LogUtil.CLog;
@@ -26,6 +28,7 @@
 import com.android.tradefed.testtype.IBuildReceiver;
 import com.android.tradefed.testtype.IDeviceTest;
 import com.android.tradefed.testtype.IRemoteTest;
+import com.android.tradefed.util.AbiFormatter;
 
 import java.io.File;
 import java.io.FileNotFoundException;
@@ -45,6 +48,10 @@
     private final String mName;
     private final String mUri;
 
+    @Option(name = AbiFormatter.FORCE_ABI_STRING,
+            description = AbiFormatter.FORCE_ABI_DESCRIPTION,
+            importance = Importance.IF_UNSET)
+    private String mForceAbi = null;
 
     public WrappedGTest(String appNameSpace, String uri, String name, String runner) {
         mAppNameSpace = appNameSpace;
@@ -100,7 +107,14 @@
         WrappedGTestResultParser resultParser = new WrappedGTestResultParser(mUri, listener);
         resultParser.setFakePackagePrefix(mUri + ".");
         try {
-            String command = String.format("am instrument -w %s/.%s", mAppNameSpace, mRunner);
+            String options = "";
+            if (mForceAbi != null) {
+                String abi = AbiFormatter.getDefaultAbi(getDevice(), mForceAbi);
+                if (abi != null) {
+                    options = String.format("--abi %s ", abi);
+                }
+            }
+            String command = String.format("am instrument -w %s%s/.%s", options, mAppNameSpace, mRunner);
             mDevice.executeShellCommand(command, resultParser, mMaxTestTimeMs, 0);
         } catch (DeviceNotAvailableException e) {
             resultParser.flush();
diff --git a/tools/utils/CollectAllTests.java b/tools/utils/CollectAllTests.java
index 4efc8bd..367fb93 100644
--- a/tools/utils/CollectAllTests.java
+++ b/tools/utils/CollectAllTests.java
@@ -14,27 +14,23 @@
  * limitations under the License.
  */
 
+import org.junit.runner.RunWith;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
 
-import vogar.Expectation;
 import vogar.ExpectationStore;
-import vogar.ModeId;
 
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileReader;
-import java.io.FilenameFilter;
 import java.io.IOException;
 import java.lang.annotation.Annotation;
-import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Enumeration;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -47,11 +43,7 @@
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
 
-import junit.framework.Test;
 import junit.framework.TestCase;
-import junit.framework.TestResult;
-import junit.textui.ResultPrinter;
-import junit.textui.TestRunner;
 
 public class CollectAllTests extends DescriptionGenerator {
 
@@ -203,18 +195,19 @@
                 Class<?> klass = Class.forName(className,
                                                false,
                                                CollectAllTests.class.getClassLoader());
-                if (!TestCase.class.isAssignableFrom(klass)) {
+                final int modifiers = klass.getModifiers();
+                if (Modifier.isAbstract(modifiers) || !Modifier.isPublic(modifiers)) {
                     continue;
                 }
-                if (Modifier.isAbstract(klass.getModifiers())) {
+
+                final boolean isJunit4Class = isJunit4Class(klass);
+                if (!isJunit4Class && !isJunit3Test(klass)) {
                     continue;
                 }
-                if (!Modifier.isPublic(klass.getModifiers())) {
-                    continue;
-                }
+
                 try {
                     klass.getConstructor(new Class<?>[] { String.class } );
-                    addToTests(expectations, testCases, klass.asSubclass(TestCase.class));
+                    addToTests(expectations, testCases, klass);
                     continue;
                 } catch (NoSuchMethodException e) {
                 } catch (SecurityException e) {
@@ -222,9 +215,10 @@
                             + className);
                     e.printStackTrace();
                 }
+
                 try {
                     klass.getConstructor(new Class<?>[0]);
-                    addToTests(expectations, testCases, klass.asSubclass(TestCase.class));
+                    addToTests(expectations, testCases, klass);
                     continue;
                 } catch (NoSuchMethodException e) {
                 } catch (SecurityException e) {
@@ -276,7 +270,7 @@
                 BufferedReader reader = new BufferedReader(new FileReader(makeFileName));
                 String line;
 
-                while ((line =reader.readLine())!=null) {
+                while ((line = reader.readLine())!=null) {
                     if (line.startsWith(TEST_TYPE)) {
                         if (line.indexOf(ATTRIBUTE_VM_HOST_TEST) >= 0) {
                             type = VM_HOST_TEST;
@@ -314,22 +308,22 @@
         }
     }
 
-    private static String getKnownFailure(final Class<? extends TestCase> testClass,
+    private static String getKnownFailure(final Class<?> testClass,
             final String testName) {
         return getAnnotation(testClass, testName, KNOWN_FAILURE);
     }
 
-    private static boolean isKnownFailure(final Class<? extends TestCase> testClass,
+    private static boolean isKnownFailure(final Class<?> testClass,
             final String testName) {
         return getAnnotation(testClass, testName, KNOWN_FAILURE) != null;
     }
 
-    private static boolean isSuppressed(final Class<? extends TestCase> testClass,
+    private static boolean isSuppressed(final Class<?> testClass,
             final String testName)  {
         return getAnnotation(testClass, testName, SUPPRESSED_TEST) != null;
     }
 
-    private static String getAnnotation(final Class<? extends TestCase> testClass,
+    private static String getAnnotation(final Class<?> testClass,
             final String testName, final String annotationName) {
         try {
             Method testMethod = testClass.getMethod(testName, (Class[])null);
@@ -363,38 +357,42 @@
 
     private static void addToTests(ExpectationStore[] expectations,
                                    Map<String,TestClass> testCases,
-                                   Class<? extends TestCase> test) {
-        Class testClass = test;
+                                   Class<?> testClass) {
         Set<String> testNames = new HashSet<String>();
-        while (TestCase.class.isAssignableFrom(testClass)) {
-            Method[] testMethods = testClass.getDeclaredMethods();
-            for (Method testMethod : testMethods) {
-                String testName = testMethod.getName();
-                if (testNames.contains(testName)) {
-                    continue;
-                }
-                if (!testName.startsWith("test")) {
-                    continue;
-                }
-                if (testMethod.getParameterTypes().length != 0) {
-                    continue;
-                }
-                if (!testMethod.getReturnType().equals(Void.TYPE)) {
-                    continue;
-                }
-                if (!Modifier.isPublic(testMethod.getModifiers())) {
-                    continue;
-                }
-                testNames.add(testName);
-                addToTests(expectations, testCases, test, testName);
+
+        boolean isJunit3Test = isJunit3Test(testClass);
+
+        Method[] testMethods = testClass.getMethods();
+        for (Method testMethod : testMethods) {
+            String testName = testMethod.getName();
+            if (testNames.contains(testName)) {
+                continue;
             }
-            testClass = testClass.getSuperclass();
+
+            /* Make sure the method has the right signature. */
+            if (!Modifier.isPublic(testMethod.getModifiers())) {
+                continue;
+            }
+            if (!testMethod.getReturnType().equals(Void.TYPE)) {
+                continue;
+            }
+            if (testMethod.getParameterTypes().length != 0) {
+                continue;
+            }
+
+            if ((isJunit3Test && !testName.startsWith("test"))
+                    || (!isJunit3Test && !isJunit4TestMethod(testMethod))) {
+                continue;
+            }
+
+            testNames.add(testName);
+            addToTests(expectations, testCases, testClass, testName);
         }
     }
 
     private static void addToTests(ExpectationStore[] expectations,
                                    Map<String,TestClass> testCases,
-                                   Class<? extends TestCase> test,
+                                   Class<?> test,
                                    String testName) {
 
         String testClassName = test.getName();
@@ -414,7 +412,7 @@
             return;
         }
 
-        TestClass testClass = null;
+        TestClass testClass;
         if (testCases.containsKey(testClassName)) {
             testClass = testCases.get(testClassName);
         } else {
@@ -425,6 +423,40 @@
         testClass.mCases.add(new TestMethod(testName, "", "", knownFailure, false, false));
     }
 
+    private static boolean isJunit3Test(Class<?> klass) {
+        return TestCase.class.isAssignableFrom(klass);
+    }
+
+    private static boolean isJunit4Class(Class<?> klass) {
+        for (Annotation a : klass.getAnnotations()) {
+            if (RunWith.class.isAssignableFrom(a.annotationType())) {
+                // @RunWith is currently not supported for CTS tests because tradefed cannot handle
+                // a single test spawning other tests with different names.
+                System.out.println("Skipping test class " + klass.getName()
+                        + ": JUnit4 @RunWith is not supported");
+                return false;
+            }
+        }
+
+        for (Method m : klass.getMethods()) {
+            if (isJunit4TestMethod(m)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    private static boolean isJunit4TestMethod(Method method) {
+        for (Annotation a : method.getAnnotations()) {
+            if (org.junit.Test.class.isAssignableFrom(a.annotationType())) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
     /**
      * Determines if a given string is a valid java package name
      * @param javaPackageName
diff --git a/tools/utils/buildCts.py b/tools/utils/buildCts.py
index cb70c54..0f74a81 100755
--- a/tools/utils/buildCts.py
+++ b/tools/utils/buildCts.py
@@ -72,8 +72,6 @@
 
     self.test_repository = os.path.join(self.out_dir, 'repository/testcases')
     self.plan_repository = os.path.join(self.out_dir, 'repository/plans')
-    
-    #dirty hack to copy over prepopulated CTS test plans, stable vs flaky, for autoCTS
     self.definedplans_repository = os.path.join(self.android_root, 'cts/tests/plans')
 
   def GenerateTestDescriptions(self):
@@ -160,14 +158,76 @@
     plan.Include('android\.telephony')
     plan.Include('android\.nativemedia.*')
     plan.Include('com\.android\.cts\..*')#TODO(stuartscott): Should PDK have all these?
-    #TODO(stuartscott): Maybe move away from com.android.* to android.* - less typing
     self.__WritePlan(plan, 'PDK')
 
-    #dirty hack to copy over pre-populated CTS plans - flaky vs stable - to streamline autoCTS
-    shutil.copyfile(os.path.join(self.definedplans_repository, 'CTS-flaky.xml'),
-        os.path.join(self.plan_repository, 'CTS-flaky.xml'))
-    shutil.copyfile(os.path.join(self.definedplans_repository, 'CTS-stable.xml'),
-        os.path.join(self.plan_repository, 'CTS-stable.xml'))
+    flaky_tests = BuildCtsFlakyTestList()
+
+    # CTS Stable plan
+    plan = tools.TestPlan(packages)
+    plan.Exclude(r'android\.display')
+    for package, test_list in flaky_tests.iteritems():
+      plan.ExcludeTests(package, test_list)
+    self.__WritePlan(plan, 'CTS-stable')
+
+    # CTS Flaky plan - inversion of CTS Stable
+    plan = tools.TestPlan(packages)
+    plan.Exclude('.*')
+    plan.Include(r'android\.display')
+    for package, test_list in flaky_tests.iteritems():
+      plan.Include(package)
+      plan.IncludeTests(package, test_list)
+    self.__WritePlan(plan, 'CTS-flaky')
+
+
+def BuildCtsFlakyTestList():
+  """ Construct a defaultdict that maps package name to a list of tests
+      that are known to be flaky. """
+  return {
+      'android.app' : [
+          'cts.ActivityManagerTest#testIsRunningInTestHarness',
+          'cts.AlertDialogTest#testAlertDialogCancelable',
+          'cts.ExpandableListActivityTest#testCallback',],
+      'android.hardware' : [
+          'camera2.cts.CameraDeviceTest#testCameraDeviceRepeatingRequest',
+          'camera2.cts.ImageReaderTest#testImageReaderFromCameraJpeg',
+          'cts.CameraTest#testImmediateZoom',
+          'cts.CameraTest#testPreviewCallback',
+          'cts.CameraTest#testSmoothZoom',
+          'cts.CameraTest#testVideoSnapshot',
+          'cts.CameraGLTest#testCameraToSurfaceTextureMetadata',
+          'cts.CameraGLTest#testSetPreviewTextureBothCallbacks',
+          'cts.CameraGLTest#testSetPreviewTexturePreviewCallback',],
+      'android.media' : [
+          'cts.DecoderTest#testCodecResetsH264WithSurface',
+          'cts.StreamingMediaPlayerTest#testHLS',],
+      'android.mediastress' : [
+          'cts.NativeMediaTest#test480pPlay',],
+      'android.net' : [
+          'cts.ConnectivityManagerTest#testStartUsingNetworkFeature_enableHipri',
+          'cts.DnsTest#testDnsWorks',
+          'cts.SSLCertificateSocketFactoryTest#testCreateSocket',
+          'cts.SSLCertificateSocketFactoryTest#test_createSocket_bind',
+          'cts.SSLCertificateSocketFactoryTest#test_createSocket_simple',
+          'cts.SSLCertificateSocketFactoryTest#test_createSocket_wrapping',
+          'cts.TrafficStatsTest#testTrafficStatsForLocalhost',
+          'wifi.cts.NsdManagerTest#testAndroidTestCaseSetupProperly',
+          'wifi.cts.ScanResultTest#testAndroidTestCaseSetupProperly',
+          'wifi.cts.ScanResultTest#testScanResultTimeStamp',],
+      'android.security' : [
+          'cts.BannedFilesTest#testNoSu',
+          'cts.BannedFilesTest#testNoSuInPath',
+          'cts.ListeningPortsTest#testNoRemotelyAccessibleListeningUdp6Ports',
+          'cts.ListeningPortsTest#testNoRemotelyAccessibleListeningUdpPorts',
+          'cts.PackageSignatureTest#testPackageSignatures',],
+      'android.webkit' : [
+          'cts.WebViewClientTest#testDoUpdateVisitedHistory',
+          'cts.WebViewClientTest#testLoadPage',
+          'cts.WebViewClientTest#testOnFormResubmission',
+          'cts.WebViewClientTest#testOnReceivedError',
+          'cts.WebViewClientTest#testOnReceivedHttpAuthRequest',
+          'cts.WebViewClientTest#testOnScaleChanged',
+          'cts.WebViewClientTest#testOnUnhandledKeyEvent',
+          'cts.WebViewTest#testSetInitialScale',]}
 
 def LogGenerateDescription(name):
   print 'Generating test description for package %s' % name
diff --git a/tools/utils/cts/tools.py b/tools/utils/cts/tools.py
index 6cd1b95..0a4c97c 100644
--- a/tools/utils/cts/tools.py
+++ b/tools/utils/cts/tools.py
@@ -120,6 +120,45 @@
     self.all_packages = all_packages
     self.map = None
 
+    self.includedTestsMap = {}
+    self.excludedTestsMap = {}
+
+
+  def IncludeTests(self, package, test_list):
+    """Include only specific tests in this plan.
+
+    package The package that contains the tests. e.g. android.mypackage
+      This package should must be included via Include.
+    test_list A list of tests with methods to be included. e.g.
+      ['TestClass#testA', 'TestClass#testB']
+    """
+    packaged_test_list = []
+    for test in test_list:
+      packaged_test_list.append(package + '.' + test)
+
+    if package in self.includedTestsMap:
+      self.includedTestsMap[package] += packaged_test_list
+    else:
+      self.includedTestsMap[package] = packaged_test_list
+
+
+  def ExcludeTests(self, package, test_list):
+    """Exclude specific tests from this plan.
+
+    package The package that contains the tests. e.g. android.mypackage
+      This package should must be included via Include.
+    test_list A list of tests with methods to be excluded. e.g.
+      ['TestClass#testA', 'TestClass#textB']
+    """
+    packaged_test_list = []
+    for test in test_list:
+      packaged_test_list.append(package + '.' + test)
+    if package in self.excludedTestsMap:
+      self.excludedTestsMap[package] += packaged_test_list
+    else:
+      self.excludedTestsMap[package] = packaged_test_list
+
+
   def Exclude(self, pattern):
     """Exclude all packages matching the given regular expression from the plan.
 
@@ -167,6 +206,10 @@
       if self.map[package]:
         entry = doc.createElement('Entry')
         entry.setAttribute('uri', package)
+        if package in self.excludedTestsMap:
+          entry.setAttribute('exclude', ';'.join(self.excludedTestsMap[package]))
+        if package in self.includedTestsMap:
+          entry.setAttribute('include', ';'.join(self.includedTestsMap[package]))
         plan.appendChild(entry)
     stream = open(file_name, 'w')
     doc.writexml(stream, addindent='  ', newl='\n', encoding='UTF-8')
diff --git a/tools/vm-tests-tf/src/util/build/BuildDalvikSuite.java b/tools/vm-tests-tf/src/util/build/BuildDalvikSuite.java
index 7f52edf..6f5226c 100644
--- a/tools/vm-tests-tf/src/util/build/BuildDalvikSuite.java
+++ b/tools/vm-tests-tf/src/util/build/BuildDalvikSuite.java
@@ -212,17 +212,21 @@
         "package " + pName + ";\n" +
         "import java.io.IOException;\n" +
         "import com.android.tradefed.testtype.DeviceTestCase;\n" +
+        "import com.android.tradefed.config.Option;\n" +
+        "import com.android.tradefed.config.Option.Importance;\n" +
+        "import com.android.tradefed.util.AbiFormatter;\n" +
         "\n" +
         "public class " + sourceName + " extends DeviceTestCase {\n";
     }
 
     private String getShellExecJavaLine(String classpath, String mainclass) {
-      String cmd = String.format("ANDROID_DATA=%s dalvikvm -Xmx512M -Xss32K " +
+      String cmd = String.format("ANDROID_DATA=%s dalvikvm|#ABI#| -Xmx512M -Xss32K " +
               "-Djava.io.tmpdir=%s -classpath %s %s", TARGET_JAR_ROOT_PATH, TARGET_JAR_ROOT_PATH,
               classpath, mainclass);
-      return "String res = getDevice().executeShellCommand(\""+ cmd + "\");\n" +
-             "// A sucessful adb shell command returns an empty string.\n" +
-             "assertEquals(\"" + cmd + "\", \"\", res);";
+      return "String cmd = AbiFormatter.formatCmdForAbi(\"" + cmd + "\", mForceAbi);\n" +
+          "String res = getDevice().executeShellCommand(cmd);\n" +
+          "// A sucessful adb shell command returns an empty string.\n" +
+          "assertEquals(cmd, \"\", res);";
     }
 
     private String getWarningMessage() {
@@ -279,6 +283,10 @@
 
             openCTSHostFileFor(pName, classOnlyName);
 
+            curJunitFileData += "@Option(name = AbiFormatter.FORCE_ABI_STRING,\n" +
+                "description = AbiFormatter.FORCE_ABI_DESCRIPTION,\n" +
+                "importance = Importance.IF_UNSET)\nprivate String mForceAbi = null;\n\n";
+
             List<String> methods = entry.getValue();
             Collections.sort(methods, new Comparator<String>() {
                 public int compare(String s1, String s2) {